diff --git a/malice/Cargo.toml b/malice/Cargo.toml index 8974263..54d54c9 100644 --- a/malice/Cargo.toml +++ b/malice/Cargo.toml @@ -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" diff --git a/malice/src/dataset_rust.rs b/malice/src/dataset_rust.rs index 09b296a..6d314b2 100644 --- a/malice/src/dataset_rust.rs +++ b/malice/src/dataset_rust.rs @@ -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; @@ -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 { - use nom::*; let track_counter: Vec<_> = ColumnFixedIntoIter::new(&t, "Tracks", be_u32)?.collect(); Ok(DatasetIntoIter { aliesdrun_frunnumber: ColumnFixedIntoIter::new(&t, "AliESDRun.fRunNumber", be_i32)?, @@ -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)?, }) } } @@ -95,20 +95,18 @@ impl Iterator for DatasetIntoIter { /// it down to a simple vector fn parse_trigger_classes(input: &[u8]) -> nom::IResult<&[u8], Vec> { 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::>() + }}}); + + (input, names.collect::>()) }) } @@ -118,17 +116,16 @@ fn parse_trigger_classes(input: &[u8]) -> nom::IResult<&[u8], Vec> { /// 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 { diff --git a/root-io/Cargo.toml b/root-io/Cargo.toml index 8496e64..922ca52 100644 --- a/root-io/Cargo.toml +++ b/root-io/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "root-io" -version = "0.1.1" +version = "0.1.2" authors = ["cbourjau "] exclude = ["*test_data/", "*.root"] description = "Reading of `.root` binary files which are commonly used in particle physics" @@ -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 \ No newline at end of file +version = "4" +#features = ["nightly", "verbose-errors"] # For better error messages diff --git a/root-io/src/core/file.rs b/root-io/src/core/file.rs index 5b8105c..4942b50 100644 --- a/root-io/src/core/file.rs +++ b/root-io/src/core/file.rs @@ -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. @@ -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() @@ -135,14 +135,14 @@ impl RootFile { pub fn streamers(&self) -> Result, 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() @@ -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 @@ -223,7 +223,7 @@ impl RootFile { // macro names are generated as my_macro ! (...) by `quote` let parsers = parsers.replace(" ! (", "!("); writeln!(s, "{}", parsers)?; - } + } Ok(()) } } @@ -244,16 +244,16 @@ fn parse_buffer(reader: &mut BufReader, 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)) } @@ -327,9 +327,9 @@ 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); @@ -337,5 +337,5 @@ mod test { _ => panic!("Not parsed as TList!"), }; } - + } diff --git a/root-io/src/core/file_item.rs b/root-io/src/core/file_item.rs index 8389023..9268a16 100644 --- a/root-io/src/core/file_item.rs +++ b/root-io/src/core/file_item.rs @@ -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. @@ -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!")) } } @@ -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"); diff --git a/root-io/src/core/parsers.rs b/root-io/src/core/parsers.rs index 23ce202..3652923 100644 --- a/root-io/src/core/parsers.rs +++ b/root-io/src/core/parsers.rs @@ -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 @@ -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) ) ); @@ -278,15 +278,17 @@ 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]), @@ -294,7 +296,7 @@ pub fn raw_no_context(input: &[u8]) -> nom::IResult<&[u8], (ClassInfo, &[u8])> // 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 } @@ -317,4 +319,3 @@ mod classinfo_test { assert_eq!(i.len(), 352); } } - diff --git a/root-io/src/core/tstreamerinfo.rs b/root-io/src/core/tstreamerinfo.rs index e15e45f..dde3a78 100644 --- a/root-io/src/core/tstreamerinfo.rs +++ b/root-io/src/core/tstreamerinfo.rs @@ -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}; @@ -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 @@ -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()) { diff --git a/root-io/src/tests/read_esd.rs b/root-io/src/tests/read_esd.rs index 05f9668..42a42a2 100644 --- a/root-io/src/tests/read_esd.rs +++ b/root-io/src/tests/read_esd.rs @@ -52,7 +52,7 @@ struct Model { primaryvertex_alivertex_fncontributors: i32, aliesdrun_frunnumber: i32, aliesdrun_ftriggerclasses: Vec, - aliesdheader_ftriggermask: u64, + aliesdheader_ftriggermask: u64, tracks_fx: Vec, tracks_fp: Vec<[f32; 5]>, tracks_falpha: Vec, @@ -91,20 +91,20 @@ impl Iterator for SchemaIntoIter { /// it down to a simple vector fn parse_trigger_classes(input: &[u8]) -> IResult<&[u8], Vec> { 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::>() + }); + (input, items.collect::>()) }) } @@ -114,16 +114,16 @@ fn parse_trigger_classes(input: &[u8]) -> IResult<&[u8], Vec> { /// 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] diff --git a/root-io/src/tree_reader/branch.rs b/root-io/src/tree_reader/branch.rs index f2eb8c9..5aa6198 100644 --- a/root-io/src/tree_reader/branch.rs +++ b/root-io/src/tree_reader/branch.rs @@ -2,8 +2,9 @@ use std::io::SeekFrom; use std::path::PathBuf; use nom::*; -use core::parsers::*; -use core::types::*; +use ::core::parsers::*; +use ::core::types::{Raw, Context}; + use code_gen::rust::ToRustType; use tree_reader::container::Container; @@ -182,4 +183,3 @@ fn tbranch<'s>(input: &'s [u8], context: & Context<'s>) -> IResult<&'s [u8], TBr } })) } - diff --git a/root-io/src/tree_reader/column_fixed_into_iter.rs b/root-io/src/tree_reader/column_fixed_into_iter.rs index 7bcec18..a952b6a 100644 --- a/root-io/src/tree_reader/column_fixed_into_iter.rs +++ b/root-io/src/tree_reader/column_fixed_into_iter.rs @@ -96,9 +96,9 @@ impl ColumnFixedIntoIter { // Read and decompress data into a vec .flat_map(|c| c.raw_data()) .flat_map(move |(n_entries, raw_slice)| { - let s: &[u8] = raw_slice.as_slice(); + let s: &[u8] = raw_slice.as_slice(); match count!(s, p, n_entries as usize) { - IResult::Done(_, o) => o, + Ok((_, o)) => o, _ => panic!("Parser failed unexpectedly!"), } })); diff --git a/root-io/src/tree_reader/column_var_into_iter.rs b/root-io/src/tree_reader/column_var_into_iter.rs index 7b14758..141b8c7 100644 --- a/root-io/src/tree_reader/column_var_into_iter.rs +++ b/root-io/src/tree_reader/column_var_into_iter.rs @@ -31,7 +31,7 @@ impl ColumnVarIntoIter { // `el_counter[N]` times. TODO: This is not what currently // happens! Currently, I'm parsing all _elements_ of a basket, // ignoring the size of each event. I then chunk the numer of - // elements into the size of the entry in the `next` function + // elements into the size of the entry in the `next` function let br: &TBranch = tr.branches().iter() .find(|b| b.name == name) .ok_or_else(|| format_err!("Branch {} not found in tree: \n {:#?}", @@ -57,7 +57,7 @@ impl ColumnVarIntoIter { .flat_map(move |((n_entries_in_buf, raw_slice), n_elems)| { let s: &[u8] = raw_slice.as_slice(); match count!(s, p, n_elems as usize) { - IResult::Done(_, o) => o, + Ok((_, o)) => o, _ => panic!("Parser failed unexpectedly! {}, {}", n_entries_in_buf, s.len()), }}) ); diff --git a/root-io/src/tree_reader/container.rs b/root-io/src/tree_reader/container.rs index 552cb69..b488fea 100644 --- a/root-io/src/tree_reader/container.rs +++ b/root-io/src/tree_reader/container.rs @@ -20,7 +20,7 @@ impl Container { match self { Container::InMemory(buf) => { match tbasket2vec(buf.as_slice()) { - IResult::Done(_, v) => Ok(v), + Ok((_, v)) => Ok(v), _ => Err(format_err!("tbasket2vec parser failed")) } }, @@ -32,7 +32,7 @@ impl Container { reader.read_exact(&mut buf)?; // println!("{:#?}", tbasket(buf.as_slice(), be_u32).unwrap().1); match tbasket2vec(buf.as_slice()) { - IResult::Done(_, v) => Ok(v), + Ok((_, v)) => Ok(v), _ => Err(format_err!("tbasket2vec parser failed")) } } diff --git a/root-io/src/tree_reader/leafs.rs b/root-io/src/tree_reader/leafs.rs index 5930cd9..1c3a5b9 100644 --- a/root-io/src/tree_reader/leafs.rs +++ b/root-io/src/tree_reader/leafs.rs @@ -2,7 +2,7 @@ use std::fmt; use nom::*; use quote::{Ident, Tokens}; -use core::*; +use ::core::{*, Context}; use code_gen::rust::ToRustType; #[derive(Debug, Clone)] @@ -60,7 +60,7 @@ impl fmt::Debug for TLeaf { writeln!(f, "String: {:#?}", leaf), TLeaf::Element(ref leaf) => writeln!(f, "Element: {:#?}", leaf), - TLeaf::Object(ref leaf_name, ref leaf) => + TLeaf::Object(ref leaf_name, ref leaf) => writeln!(f, "`{}`: {:#?}", leaf_name, leaf), } } diff --git a/root-io/src/tree_reader/tree.rs b/root-io/src/tree_reader/tree.rs index e2360af..3ce48e4 100644 --- a/root-io/src/tree_reader/tree.rs +++ b/root-io/src/tree_reader/tree.rs @@ -2,8 +2,8 @@ use std::fmt; use std::ops::Deref; use nom::*; -use core::parsers::*; -use core::types::*; +use ::core::parsers::*; +use ::core::types::{TNamed, Context}; use tree_reader::branch::TBranch; use tree_reader::branch::tbranch_hdr; @@ -111,7 +111,7 @@ pub fn ttree<'s>(input: &'s[u8], context: &Context) -> IResult<&'s[u8], Tree> { map!(call!(_curried_raw), |r| r.obj.to_vec()), Some)); let grab_checked_byte_count = |i| length_data!(i, checked_byte_count); - let wrapped_tobjarray = |i: &'s[u8]| length_value!(i, checked_byte_count, apply!(tobjarray, context)); + let wrapped_tobjarray = |i: &'s[u8]| length_value!(i, checked_byte_count, apply!(tobjarray, context)); do_parse!(input, ver: be_u16 >> tnamed: length_value!(checked_byte_count, tnamed) >>