use failure::Error;
use nom::combinator::rest;
use nom::number::complete::*;
use nom::*;
use crate::core::*;
#[derive(Debug, Clone)]
pub(crate) enum Container {
InMemory(Vec<u8>),
OnDisk(Source, u64, u64),
}
impl Container {
pub(crate) async fn raw_data(self) -> Result<(u32, Vec<u8>), Error> {
let buf = match self {
Container::InMemory(buf) => buf,
Container::OnDisk(source, seek, len) => source.fetch(seek, len).await?,
};
match tbasket2vec(buf.as_slice()) {
Ok((_, v)) => Ok(v),
_ => Err(format_err!("tbasket2vec parser failed")),
}
}
}
#[rustfmt::skip::macros(do_parse)]
fn tbasket2vec(input: &[u8]) -> IResult<&[u8], (u32, Vec<u8>)> {
do_parse!(input,
hdr: tkey_header >>
_ver: be_u16 >>
_buf_size: be_u32 >>
_entry_size: be_u32 >>
n_entry_buf: be_u32 >>
last: be_u32 >>
_flag: be_i8 >>
buf: rest >>
({
let buf = if hdr.uncomp_len as usize > buf.len() {
decompress(buf).unwrap().1
} else {
buf.to_vec()
};
let useful_bytes = (last - hdr.key_len as u32) as usize;
(n_entry_buf, buf.as_slice()[..useful_bytes].to_vec())
}))
}
#[cfg(test)]
mod tests {
use crate::core::tkey_header;
use nom::*;
use std::fs::File;
use std::io::{BufReader, Read, Seek, SeekFrom};
use super::tbasket2vec;
#[test]
fn basket_simple() {
let path = "./src/test_data/simple.root";
let f = File::open(&path).unwrap();
let mut reader = BufReader::new(f);
reader.seek(SeekFrom::Start(218)).unwrap();
let mut buf = vec![0; 86];
reader.read_exact(&mut buf).unwrap();
println!("{}", buf.to_hex(16));
println!("{:?}", tkey_header(&buf));
println!("{:#?}", tbasket2vec(&buf));
}
}