1use std::fmt;
2use std::fmt::Debug;
3use std::ops::Deref;
4
5use failure::Error;
6use nom::{
7 combinator::{cond, verify},
8 error::ParseError,
9 multi::{count, length_value},
10 number::complete::*,
11 sequence::preceded,
12 IResult,
13};
14
15use crate::{
16 core::parsers::*, core::types::*, tree_reader::branch::tbranch_hdr,
17 tree_reader::branch::TBranch, tree_reader::leafs::TLeaf,
18};
19
20struct Pointer(pub Vec<u8>);
24
25impl Deref for Pointer {
26 type Target = Vec<u8>;
27 fn deref(&self) -> &Vec<u8> {
28 &self.0
29 }
30}
31
32impl fmt::Debug for Pointer {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 writeln!(f, "Buffer of {} bytes ", self.len())
35 }
36}
37
38#[derive(Debug)]
43pub struct Tree {
44 ver: u16,
46 tnamed: TNamed,
48 fentries: i64,
50 ftotbytes: i64,
52 fzipbytes: i64,
54 fsavedbytes: i64,
56 fflushedbytes: Option<i64>,
58 fweight: f64,
60 ftimerinterval: i32,
62 fscanfield: i32,
64 fupdate: i32,
66 fmaxentries: i64,
68 fmaxentryloop: i64,
70 festimate: i64,
72 pub(crate) fbranches: Vec<TBranch>,
74 pub(crate) fleaves: Vec<TLeaf>,
76 faliases: Option<Vec<u8>>,
78 findexvalues: Vec<f64>,
80 findex: Vec<i32>,
82 ftreeindex: Option<Pointer>,
84 ffriends: Option<Pointer>,
86 fuserinfo: Option<Pointer>,
88 fbranchref: Option<Pointer>,
90}
91
92impl<'s> Tree {
93 pub(crate) fn branches(&self) -> Vec<&TBranch> {
95 self.fbranches
96 .iter()
97 .flat_map(|b| vec![b].into_iter().chain(b.branches().into_iter()))
98 .collect()
99 }
100 pub fn branch_names_and_types(&self) -> Vec<(String, Vec<String>)> {
103 self.fbranches
104 .iter()
105 .flat_map(|b| vec![b].into_iter().chain(b.branches().into_iter()))
106 .map(|b| (b.name(), b.element_types()))
107 .collect()
108 }
109
110 pub fn branch_by_name(&self, name: &str) -> Result<&TBranch, Error> {
111 self.branches()
112 .into_iter()
113 .find(|b| b.name == name)
114 .ok_or_else(|| {
115 format_err!(
116 "Branch {} not found in tree: \n {:#?}",
117 name,
118 self.branches()
119 .iter()
120 .map(|b| b.name.to_owned())
121 .collect::<Vec<_>>()
122 )
123 })
124 }
125}
126
127#[allow(clippy::unnecessary_unwrap)]
129pub fn ttree<'s, E>(i: &'s [u8], context: &'s Context) -> IResult<&'s [u8], Tree, E>
130where
131 E: ParseError<&'s [u8]> + Debug,
132{
133 let _curried_raw = |i| raw(i, context);
134 let none_or_u8_buf = |i: &'s [u8]| {
135 switch!(i, peek!(be_u32),
136 0 => map!(call!(be_u32), | _ | None) |
137 _ => map!(
138 map!(call!(_curried_raw), |r| r.obj.to_vec()),
139 Some)
140 )
141 };
142 let grab_checked_byte_count = |i| length_data!(i, checked_byte_count);
143 let (i, ver) = verify(be_u16, |v| [16, 17, 18, 19].contains(v))(i)?;
144 let (i, tnamed) = length_value(checked_byte_count, tnamed)(i)?;
145 let (i, _tattline) = grab_checked_byte_count(i)?;
146 let (i, _tattfill) = grab_checked_byte_count(i)?;
147 let (i, _tattmarker) = grab_checked_byte_count(i)?;
148 let (i, fentries) = be_i64(i)?;
149 let (i, ftotbytes) = be_i64(i)?;
150 let (i, fzipbytes) = be_i64(i)?;
151 let (i, fsavedbytes) = be_i64(i)?;
152 let (i, fflushedbytes) = cond(ver >= 18, be_i64)(i)?;
153 let (i, fweight) = be_f64(i)?;
154 let (i, ftimerinterval) = be_i32(i)?;
155 let (i, fscanfield) = be_i32(i)?;
156 let (i, fupdate) = be_i32(i)?;
157 let (i, _fdefaultentryoffsetlen) = cond(ver >= 17, be_i32)(i)?;
158 let (i, fnclusterrange) = cond(ver >= 19, be_i32)(i)?;
159 let (i, fmaxentries) = be_i64(i)?;
160 let (i, fmaxentryloop) = be_i64(i)?;
161 let (i, _fmaxvirtualsize) = be_i64(i)?;
162 let (i, _fautosave) = be_i64(i)?;
163 let (i, _fautoflush) = cond(ver >= 18, be_i64)(i)?;
164 let (i, festimate) = be_i64(i)?;
165 let (i, _fclusterrangeend) = {
166 if let Some(n_clst_range) = fnclusterrange {
167 preceded(be_u8, count(be_i64, n_clst_range as usize))(i)
168 .map(|(i, ends)| (i, Some(ends)))?
169 } else {
170 (i, None)
171 }
172 };
173 let (i, _fclustersize) = {
174 if let Some(n_clst_range) = fnclusterrange {
175 preceded(be_u8, count(be_i64, n_clst_range as usize))(i)
176 .map(|(i, ends)| (i, Some(ends)))?
177 } else {
178 (i, None)
179 }
180 };
181 let (i, fbranches) =
182 length_value(checked_byte_count, |i| tobjarray(tbranch_hdr, i, context))(i)?;
183 let (i, fleaves) = length_value(checked_byte_count, |i| {
184 tobjarray(TLeaf::parse_from_raw, i, context)
185 })(i)?;
186
187 let (i, faliases) = none_or_u8_buf(i)?;
188 let (i, findexvalues) = tarray(be_f64, i)?;
189 let (i, findex) = tarray(be_i32, i)?;
190 let (i, ftreeindex) = none_or_u8_buf(i)?;
191 let (i, ffriends) = none_or_u8_buf(i)?;
192 let (i, fuserinfo) = none_or_u8_buf(i)?;
193 let (i, fbranchref) = none_or_u8_buf(i)?;
194 let ftreeindex = ftreeindex.map(Pointer);
195 let ffriends = ffriends.map(Pointer);
196 let fuserinfo = fuserinfo.map(Pointer);
197 let fbranchref = fbranchref.map(Pointer);
198 Ok((
199 i,
200 Tree {
201 ver,
202 tnamed,
203 fentries,
204 ftotbytes,
205 fzipbytes,
206 fsavedbytes,
207 fflushedbytes,
208 fweight,
209 ftimerinterval,
210 fscanfield,
211 fupdate,
212 fmaxentries,
213 fmaxentryloop,
214 festimate,
215 fbranches,
216 fleaves,
217 faliases,
218 findexvalues,
219 findex,
220 ftreeindex,
221 ffriends,
222 fuserinfo,
223 fbranchref,
224 },
225 ))
226}