root_io/core/
file_item.rs1use failure::Error;
2use nom::{error::VerboseError, multi::length_value};
3
4use crate::core::{checked_byte_count, decompress, Context, Source, TKeyHeader};
5use crate::tree_reader::{ttree, Tree};
6
7#[derive(Debug)]
9pub struct FileItem {
10 source: Source,
11 tkey_hdr: TKeyHeader,
12}
13
14impl FileItem {
15 pub(crate) fn new(tkey_hdr: &TKeyHeader, source: Source) -> FileItem {
17 FileItem {
18 source,
19 tkey_hdr: tkey_hdr.to_owned(),
20 }
21 }
22
23 pub fn verbose_info(&self) -> String {
25 format!("{:#?}", self.tkey_hdr)
26 }
27 pub fn name(&self) -> String {
28 format!(
29 "`{}` of type `{}`",
30 self.tkey_hdr.obj_name, self.tkey_hdr.class_name
31 )
32 }
33
34 async fn get_buffer(&self) -> Result<Vec<u8>, Error> {
35 let start = self.tkey_hdr.seek_key + self.tkey_hdr.key_len as u64;
36 let len = self.tkey_hdr.total_size - self.tkey_hdr.key_len as u32;
37 let comp_buf = self.source.fetch(start, len as u64).await?;
38
39 let buf = if self.tkey_hdr.total_size < self.tkey_hdr.uncomp_len {
40 let (_, buf) = decompress(comp_buf.as_slice()).unwrap();
42 buf
43 } else {
44 comp_buf
45 };
46 Ok(buf)
47 }
48
49 pub(crate) async fn get_context<'s>(&self) -> Result<Context, Error> {
50 let buffer = self.get_buffer().await?;
51 let k_map_offset = 2;
52 Ok(Context {
53 source: self.source.clone(),
54 offset: (self.tkey_hdr.key_len + k_map_offset) as u64,
55 s: buffer,
56 })
57 }
58
59 pub async fn as_tree(&self) -> Result<Tree, Error> {
61 let ctx = self.get_context().await?;
62 let buf = ctx.s.as_slice();
63
64 let res = length_value(checked_byte_count, |i| ttree::<VerboseError<_>>(i, &ctx))(&buf);
65 match res {
66 Ok((_, obj)) => Ok(obj),
67 Err(nom::Err::Error(e)) | Err(nom::Err::Failure(e)) => {
68 Err(format_err!("Supplied parser failed! {:?}", e.errors))
69 }
70 _ => panic!(),
71 }
72 }
73}
74
75#[cfg(all(test, not(target_arch = "wasm32")))]
76mod tests {
77 use crate::core::RootFile;
78 use std::path::Path;
79
80 #[tokio::test]
81 async fn open_simple() {
82 let path = Path::new("./src/test_data/simple.root");
83 let f = RootFile::new(path).await.expect("Failed to open file");
84 assert_eq!(f.items().len(), 1);
85 assert_eq!(f.items()[0].tkey_hdr.obj_name, "tree");
86 assert_eq!(f.streamer_infos().await.unwrap().len(), 18);
88 }
89
90 #[tokio::test]
92 #[cfg(all(not(target_os = "macos"), not(target_arch = "wasm32")))]
93 async fn open_esd() {
94 use alice_open_data;
95 let path = alice_open_data::test_file().unwrap();
96
97 let f = RootFile::new(path.as_path())
98 .await
99 .expect("Failed to open file");
100
101 assert_eq!(f.items().len(), 2);
102 assert_eq!(f.items()[0].tkey_hdr.obj_name, "esdTree");
103 assert_eq!(f.items()[1].tkey_hdr.obj_name, "HLTesdTree");
104 assert_eq!(f.streamer_infos().await.unwrap().len(), 87);
105 }
106}