Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Upgrade nom to version 4 #5

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions malice/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ default = []
cpp = ["alice-sys"]

[dependencies]
nom = "3.2.1"
root-io = "0.1.1"
nom = "4"
root-io = { path = "../root-io" }
failure = "0.1.1"
bitflags = "1.0.1"

Expand Down
39 changes: 18 additions & 21 deletions malice/src/dataset_rust.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Structs and iterators concerned with iterating over events stored in `root_io::Tree`s.

use failure::Error;
use nom;
use nom::{self, be_u8, be_u16, be_u32, be_u64, be_i8, be_i32, be_f32};

use root_io::tree_reader::{ColumnFixedIntoIter, ColumnVarIntoIter, Tree};
use root_io::core::types::ClassInfo;
Expand Down Expand Up @@ -32,7 +32,6 @@ pub struct DatasetIntoIter {
impl DatasetIntoIter {
/// Create a new `DatasetIntoIter` from the given `root_io::Tree`. The `Tree` must be a so-called "ESD" tree.
pub fn new(t: &Tree) -> Result<DatasetIntoIter, Error> {
use nom::*;
let track_counter: Vec<_> = ColumnFixedIntoIter::new(&t, "Tracks", be_u32)?.collect();
Ok(DatasetIntoIter {
aliesdrun_frunnumber: ColumnFixedIntoIter::new(&t, "AliESDRun.fRunNumber", be_i32)?,
Expand All @@ -49,10 +48,11 @@ impl DatasetIntoIter {

tracks_fitschi2: ColumnVarIntoIter::new(&t, "Tracks.fITSchi2", |i| parse_custom_mantissa(i, 8), &track_counter)?,
tracks_fitsncls: ColumnVarIntoIter::new(&t, "Tracks.fITSncls", be_i8, &track_counter)?,
tracks_fitsclustermap: ColumnVarIntoIter::new(&t, "Tracks.fITSClusterMap", be_u8, &track_counter)?,
tracks_fitsclustermap: ColumnVarIntoIter::new(&t, "Tracks.fITSClusterMap", be_u8, &track_counter)?,

tracks_ftpcncls: ColumnVarIntoIter::new(&t, "Tracks.fTPCncls", be_u16, &track_counter)?,
tracks_ftpcchi2: ColumnVarIntoIter::new(&t, "Tracks.fTPCchi2", |i| parse_custom_mantissa(i, 8), &track_counter)?,
tracks_ftpcchi2: ColumnVarIntoIter::new(&t, "Tracks.fTPCchi2",
|i| parse_custom_mantissa(i, 8), &track_counter)?,
})
}
}
Expand Down Expand Up @@ -95,20 +95,18 @@ impl Iterator for DatasetIntoIter {
/// it down to a simple vector
fn parse_trigger_classes(input: &[u8]) -> nom::IResult<&[u8], Vec<String>> {
let vals = length_value!(input, checked_byte_count, tobjarray_no_context);
vals.map(|arr| {
arr.iter()
.map(|&(ref ci, ref el)| {
match *ci {
ClassInfo::References(0) => "".to_string(),
_ => {
match tnamed(el.as_slice()).map(|tn| tn.name) {
nom::IResult::Done(_, n) => n,
_ => panic!()
}
}

vals.map(|(input, arr)| {
let names = arr.iter().map(|&(ref ci, ref el)| { match *ci {
ClassInfo::References(0) => "".to_string(),
_ => {
match tnamed(el.as_slice()).map(|(i, tnamed)| (i, tnamed.name)) {
Ok((_, n)) => n,
_ => panic!()
}
})
.collect::<Vec<String>>()
}}});

(input, names.collect::<Vec<String>>())
})
}

Expand All @@ -118,17 +116,16 @@ fn parse_trigger_classes(input: &[u8]) -> nom::IResult<&[u8], Vec<String>> {
/// This function reconstructs a float from the exponent and mantissa
/// TODO: Use ByteOrder crate to be cross-platform!
fn parse_custom_mantissa(input: &[u8], nbits: usize) -> nom::IResult<&[u8], f32> {
use nom::*; // cannot use module path in macro
pair!(input, be_u8, be_u16).map(|(exp, man)| {
pair!(input, be_u8, be_u16).map(|(i, (exp, man))| {
// let nbits = 8;
let mut s = exp as u32;
// Move the exponent into the last 23 bits
s <<= 23;
s |= (man as u32 & ((1<<(nbits+1))-1)) <<(23-nbits);
f32::from_bits(s)
(i, f32::from_bits(s))
})
}


#[cfg(test)]
mod tests {
Expand Down
11 changes: 5 additions & 6 deletions root-io/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "root-io"
version = "0.1.1"
version = "0.1.2"
authors = ["cbourjau <christian.bourjau@cern.ch>"]
exclude = ["*test_data/", "*.root"]
description = "Reading of `.root` binary files which are commonly used in particle physics"
Expand All @@ -10,14 +10,13 @@ keywords = ["root", "cern", "alice", "lhc", "physics"]
categories = ["parser-implementations", "science", "data-structures"]
license = "MPL-2.0"


[dependencies]
flate2 = "0.2"
xz2 = "^0.1.4"
xz2 = "0.1"
bitflags = "1.0.0"
quote = "0.3.15"
quote = "0.3"
failure = "0.1.0"

[dependencies.nom]
version = "^3"
#features = ["nightly", "verbose-errors"] # For better error messages
version = "4"
#features = ["nightly", "verbose-errors"] # For better error messages
28 changes: 14 additions & 14 deletions root-io/src/core/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ use std::io::{BufReader, Seek, SeekFrom, Read};


use failure::Error;
use nom::*;
use nom::{IResult, *};

use MAP_OFFSET;
use ::core::*;
use ::core::{*, Context};
use ::code_gen::rust::{ToNamedRustParser, ToRustStruct};

/// `RootFile` wraps the most basic information of a ROOT file.
Expand Down Expand Up @@ -120,7 +120,7 @@ impl RootFile {
parse_buffer(&mut reader, 1024, tkey)?
};
let keys = match tkey_headers(&tkey_of_keys.obj) {
IResult::Done(_, hdrs) => Ok(hdrs),
Ok((_, hdrs)) => Ok(hdrs),
_ => Err(format_err!("Expected TKeyHeaders"))
}?;
let items = keys.iter()
Expand All @@ -135,14 +135,14 @@ impl RootFile {
pub fn streamers(&self) -> Result<Vec<TStreamerInfo>, Error> {
let f = File::open(&self.path)?;
let mut reader = BufReader::new(f);

// Read streamer info
reader.seek(self.hdr.seek_info)?;
// Dunno why we are 4 bytes off with the size of the streamer info...
let info_key = parse_buffer(&mut reader, (self.hdr.nbytes_info + 4) as usize, tkey)?;

let key_len = info_key.hdr.key_len;
let context = Context{
let context = Context {
path: self.path.to_owned(),
offset: key_len as u64 + MAP_OFFSET,
s: info_key.obj.as_slice()
Expand All @@ -151,7 +151,7 @@ impl RootFile {
let wrapped_tlist = |i| apply!(i, tlist, &context);
let tlist_objs =
match length_value!(info_key.obj.as_slice(), checked_byte_count, wrapped_tlist) {
IResult::Done(_, l) => Ok(l.objs),
Ok((_, l)) => Ok(l.objs),
_ => Err(format_err!("Expected TStreamerInfo's TList"))
}?;
// Mainly this is a TList of `TStreamerInfo`s, but there might
Expand Down Expand Up @@ -223,7 +223,7 @@ impl RootFile {
// macro names are generated as my_macro ! (...) by `quote`
let parsers = parsers.replace(" ! (", "!(");
writeln!(s, "{}", parsers)?;
}
}
Ok(())
}
}
Expand All @@ -244,16 +244,16 @@ fn parse_buffer<R, F, O>(reader: &mut BufReader<R>, buf_size: usize, f: F)
}
};
match f(buf) {
IResult::Done(_, parsed) => Ok(parsed),
IResult::Incomplete(needed) => {
Ok((_, parsed)) => Ok(parsed),
Err(Err::Incomplete(needed)) => {
// Reset seek position and try again with updated buf size
reader.seek(SeekFrom::Current(-(read_bytes as i64)))?;
match needed {
Needed::Size(s) => parse_buffer(reader, s, f),
Needed::Size(s) => parse_buffer(reader, read_bytes + s, f),
_ => parse_buffer(reader, buf_size + 1000, f),
}
},
IResult::Error(e) => {
Err(Err::Error(e)) | Err(Err::Failure(e)) => {
println!("{}", buf.to_hex(8));
Err(format_err!("{:?}", e))
}
Expand Down Expand Up @@ -327,15 +327,15 @@ mod test {
offset: (key_len + k_map_offset) as u64,
s: key.obj.as_slice()
};

match length_value!(key.obj.as_slice(), checked_byte_count, apply!(tlist, &context)) {
IResult::Done(_, l) => {
Ok((_, l)) => {
assert_eq!(l.ver, 5);
assert_eq!(l.name, "");
assert_eq!(l.len, 19);
},
_ => panic!("Not parsed as TList!"),
};
}

}
6 changes: 3 additions & 3 deletions root-io/src/core/file_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl FileItem {
pub fn name(&self) -> String {
format!("`{}` of type `{}`", self.tkey_hdr.obj_name, self.tkey_hdr.class_name)
}


/// Read (and posibly decompress) data from disk and parse it as
/// the appropriate type using the TStreamerInfo types.
Expand Down Expand Up @@ -73,7 +73,7 @@ impl FileItem {
// wrap parser in a byte count
let res = length_value!(s, checked_byte_count, apply!(&parser, &context));
match res {
IResult::Done(_, obj) => Ok(obj),
Ok((_, obj)) => Ok(obj),
_ => Err(format_err!("Supplied parser failed!"))
}
}
Expand All @@ -84,7 +84,7 @@ impl FileItem {
mod tests {
use std::path::{PathBuf};
use core::RootFile;

#[test]
fn open_simple() {
let path = PathBuf::from("./src/test_data/simple.root");
Expand Down
15 changes: 8 additions & 7 deletions root-io/src/core/parsers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn is_byte_count(v: u32) -> bool {
}

/// Check that the given byte count is not zero after applying bit mask
///
///
named!(
#[doc="Return the size in bytes of the following object in the
input. The count is the remainder of this object minus the size
Expand Down Expand Up @@ -185,7 +185,7 @@ named!(
do_parse!(magic: take_str!(2) >>
_header: take!(7) >>
comp_buf: call!(nom::rest) >>
ret: expr_res!(decode_reader(comp_buf, magic)) >>
ret: expr_res!(decode_reader(comp_buf, magic)) >>
(ret)
)
);
Expand Down Expand Up @@ -278,23 +278,25 @@ pub fn raw<'s, 'c>(input: &'s[u8], context: &'c Context) -> nom::IResult<&'s[u8]
/// Same as `raw` but doesn't require a `Context` as input. Panics if
/// a `Context` is required to parse the underlying buffer (i.e., the
/// given buffer contains a reference to some other part of the file.
pub fn raw_no_context(input: &[u8]) -> nom::IResult<&[u8], (ClassInfo, &[u8])>
pub fn raw_no_context(input: &[u8]) ->
nom::IResult<&[u8], (ClassInfo, &[u8])>
{
use self::ClassInfo::*;
let first = do_parse!(input,
ci: classinfo >>
rest: call!(nom::rest) >>
rest: call!(nom::rest) >>
(ci, rest)
);
if first.is_done() {

if first.is_ok() {
let (_, (ci, rest)) = first.unwrap();
let obj = match ci {
References(0) => value!(rest, &input[..0]),
New(_) | Exists(_) => length_value!(rest, checked_byte_count, call!(nom::rest)),
// If its a reference to any other thing but 0 it needs a context
_ => panic!("Object needs context!"),
};
obj.map(|o| (ci, o))
obj.map(|(i, o)| (i, (ci, o)))
} else {
first
}
Expand All @@ -317,4 +319,3 @@ mod classinfo_test {
assert_eq!(i.len(), 352);
}
}

10 changes: 6 additions & 4 deletions root-io/src/core/tstreamerinfo.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use quote::*;
use nom::*;
use nom::HexDisplay;
use nom::{IResult, be_u16, be_u32};

use ::core::*;
use ::core::{TStreamer, tstreamer, TNamed, Context};
use ::core::parsers::*;
use ::code_gen::rust::{ToRustType, ToRustParser, ToNamedRustParser, ToRustStruct};
use ::code_gen::utils::{type_is_core};

Expand Down Expand Up @@ -33,7 +35,7 @@ pub(crate) fn tstreamerinfo<'s, 'c>(input: &'s[u8], context: &'c Context) -> IRe
let data_members = data_members.iter()
.filter_map(|el| {
match tstreamer(el) {
IResult::Done(_, v) => Some(v),
Ok((_, v)) => Some(v),
_ => {println!("Failed to parse TStreamer for {}:\n{}",
el.classinfo, el.obj.to_hex(16));
None
Expand Down Expand Up @@ -83,7 +85,7 @@ impl ToNamedRustParser for TStreamerInfo {
fn parser_name(&self) -> Tokens {
let ret = Ident::new(self.named.name.to_lowercase());
quote!(#ret)
}
}

fn to_named_parser(&self) -> Tokens {
if type_is_core(self.named.name.as_str()) {
Expand Down
20 changes: 10 additions & 10 deletions root-io/src/tests/read_esd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ struct Model {
primaryvertex_alivertex_fncontributors: i32,
aliesdrun_frunnumber: i32,
aliesdrun_ftriggerclasses: Vec<String>,
aliesdheader_ftriggermask: u64,
aliesdheader_ftriggermask: u64,
tracks_fx: Vec<f32>,
tracks_fp: Vec<[f32; 5]>,
tracks_falpha: Vec<f32>,
Expand Down Expand Up @@ -91,20 +91,20 @@ impl Iterator for SchemaIntoIter {
/// it down to a simple vector
fn parse_trigger_classes(input: &[u8]) -> IResult<&[u8], Vec<String>> {
let vals = length_value!(input, checked_byte_count, tobjarray_no_context);
vals.map(|arr| {
arr.iter()
vals.map(|(input, arr)| {
let items = arr.iter()
.map(|&(ref ci, ref el)| {
match *ci {
ClassInfo::References(0) => "".to_string(),
_ => {
match tnamed(el.as_slice()).map(|tn| tn.name) {
IResult::Done(_, n) => n,
match tnamed(el.as_slice()).map(|(i, tn)| (i, tn.name)) {
Ok((_, n)) => n,
_ => panic!()
}
}
}
})
.collect::<Vec<String>>()
});
(input, items.collect::<Vec<String>>())
})
}

Expand All @@ -114,16 +114,16 @@ fn parse_trigger_classes(input: &[u8]) -> IResult<&[u8], Vec<String>> {
/// This function reconstructs a float from the exponent and mantissa
/// TODO: Use ByteOrder crate to be cross-platform!
fn parse_its_chi2(input: &[u8]) -> IResult<&[u8], f32> {
pair!(input, be_u8, be_u16).map(|(exp, man)| {
pair!(input, be_u8, be_u16).map(|(i, (exp, man))| {
let nbits = 8;
let mut s = exp as u32;
// Move the exponent into the last 23 bits
s <<= 23;
s |= (man as u32 & ((1<<(nbits+1))-1)) <<(23-nbits);
f32::from_bits(s)
(i, f32::from_bits(s))
})
}


#[test]
#[ignore]
Expand Down
Loading