1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
use failure::Error; use nom::*; use tree_reader::tree::Tree; use tree_reader::branch::TBranch; /// Iterator over the data of a column (`TBranch`) with a single element per entry /// # Example /// ``` /// extern crate failure; /// extern crate nom; /// extern crate root_io; /// /// use std::path::PathBuf; /// use failure::Error; /// use nom::{be_i32, be_f32}; /// /// use root_io::tree_reader::{ColumnFixedIntoIter, Tree}; /// use root_io::core::parsers::{string}; /// use root_io::RootFile; /// /// /// A model for the (or a subset) of the data. /// /// This is the object which contains the data of one "event" /// #[derive(Debug)] /// struct Model { /// one: i32, /// two: f32, /// three: String, /// } /// /// /// Struct holding all the iterators in one place needed for an /// /// analysis in one place. This makes it much harder to get them out /// /// of sync /// struct SchemaIter { /// one: ColumnFixedIntoIter<i32>, /// two: ColumnFixedIntoIter<f32>, /// three: ColumnFixedIntoIter<String>, /// } /// /// /// Initiate a new iterator by passing it the `Tree` which contains the data /// impl SchemaIter { /// fn new(t: Tree) -> Result<SchemaIter, Error> { /// Ok(SchemaIter { /// // Initialize each column; they are identified by name and /// // a `nom`-like parser is needed to parse the /// // data. ::core::parsers contains many more parsers for /// // common ROOT types /// one: ColumnFixedIntoIter::new(&t, "one", be_i32)?, /// two: ColumnFixedIntoIter::new(&t, "two", be_f32)?, /// three: ColumnFixedIntoIter::new(&t, "three", string)?, /// }) /// } /// } /// /// /// Iterator popping out `Model`s. Each model is one "event" /// impl Iterator for SchemaIter { /// type Item = Model; /// fn next(&mut self) -> Option<Self::Item> { /// Some(Model { /// one: self.one.next()?, /// two: self.two.next()?, /// three: self.three.next()? /// }) /// } /// } /// /// fn main() { /// let path = PathBuf::from("./src/test_data/simple.root"); /// let f = RootFile::new_from_file(&path).expect("Failed to open file"); /// let t = f.items()[0].as_tree().unwrap(); /// let schema = SchemaIter::new(t).unwrap(); /// for m in schema.into_iter() { /// println!("{:?}", m); /// } /// } /// ``` pub struct ColumnFixedIntoIter<T> { /// Containers holding the data containers: Box<Iterator<Item=T>>, } impl<T> ColumnFixedIntoIter<T> { pub fn new<P>(tr: &Tree, name: &str, p: P) -> Result<ColumnFixedIntoIter<T>, Error> where P: 'static + Fn(&[u8]) -> IResult<&[u8], T>, T: 'static { let br: &TBranch = tr.branches().iter() .find(|b| b.name == name) .ok_or_else(|| format_err!("Branch {} not found in tree: \n {:#?}", name, tr.branches().iter() .map(|b| b.name.to_owned()).collect::<Vec<_>>()) )?; let containers = Box::new( br.containers().to_owned().into_iter() // 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(); match count!(s, p, n_entries as usize) { IResult::Done(_, o) => o, _ => panic!("Parser failed unexpectedly!"), } })); Ok(ColumnFixedIntoIter { containers: containers, }) } } impl<T> Iterator for ColumnFixedIntoIter<T> { type Item = T; fn next(&mut self) -> Option<Self::Item> { self.containers.next() } }