1use crate::io::*;
7use crate::types::*;
8use std::io::{BufRead, Read, Seek, SeekFrom, Write};
9
10trait BufReadSeek: BufRead + Seek {}
11impl<T> BufReadSeek for T where T: BufRead + Seek {}
12
13pub struct FstReader<R: BufRead + Seek> {
15 input: InputVariant<R>,
16 meta: MetaData,
17}
18
19enum InputVariant<R: BufRead + Seek> {
20 Original(R),
21 Incomplete(R, Box<dyn BufReadSeek + Sync + Send>),
22 UncompressedInMem(std::io::Cursor<Vec<u8>>),
23 IncompleteUncompressedInMem(std::io::Cursor<Vec<u8>>, Box<dyn BufReadSeek + Sync + Send>),
24}
25
26pub struct FstFilter {
30 pub start: u64,
31 pub end: Option<u64>,
32 pub include: Option<Vec<FstSignalHandle>>,
33}
34
35impl FstFilter {
36 pub fn all() -> Self {
37 FstFilter {
38 start: 0,
39 end: None,
40 include: None,
41 }
42 }
43
44 pub fn new(start: u64, end: u64, signals: Vec<FstSignalHandle>) -> Self {
45 FstFilter {
46 start,
47 end: Some(end),
48 include: Some(signals),
49 }
50 }
51
52 pub fn filter_time(start: u64, end: u64) -> Self {
53 FstFilter {
54 start,
55 end: Some(end),
56 include: None,
57 }
58 }
59
60 pub fn filter_signals(signals: Vec<FstSignalHandle>) -> Self {
61 FstFilter {
62 start: 0,
63 end: None,
64 include: Some(signals),
65 }
66 }
67}
68
69#[derive(Debug, Clone, PartialEq)]
70pub struct FstHeader {
71 pub start_time: u64,
73 pub end_time: u64,
75 pub var_count: u64,
77 pub max_handle: u64,
79 pub version: String,
81 pub date: String,
83 pub timescale_exponent: i8,
85}
86
87impl<R: BufRead + Seek> FstReader<R> {
88 pub fn open(input: R) -> Result<Self> {
90 Self::open_internal(input, false)
91 }
92
93 pub fn open_and_read_time_table(input: R) -> Result<Self> {
94 Self::open_internal(input, true)
95 }
96
97 fn open_internal(mut input: R, read_time_table: bool) -> Result<Self> {
98 let uncompressed_input = uncompress_gzip_wrapper(&mut input)?;
99 match uncompressed_input {
100 UncompressGzipWrapper::None => {
101 let mut header_reader = HeaderReader::new(input);
102 header_reader.read(read_time_table)?;
103 let (input, meta) = header_reader.into_input_and_meta_data().unwrap();
104 Ok(FstReader {
105 input: InputVariant::Original(input),
106 meta,
107 })
108 }
109 UncompressGzipWrapper::InMemory(uc) => {
110 let mut header_reader = HeaderReader::new(uc);
111 header_reader.read(read_time_table)?;
112 let (uc2, meta) = header_reader.into_input_and_meta_data().unwrap();
113 Ok(FstReader {
114 input: InputVariant::UncompressedInMem(uc2),
115 meta,
116 })
117 }
118 }
119 }
120
121 pub fn open_incomplete<H: BufRead + Seek + Sync + Send + 'static>(
130 input: R,
131 hierarchy: H,
132 ) -> Result<Self> {
133 Self::open_incomplete_internal(input, hierarchy, false)
134 }
135
136 pub fn open_incomplete_and_read_time_table<H: BufRead + Seek + Sync + Send + 'static>(
137 input: R,
138 hierarchy: H,
139 ) -> Result<Self> {
140 Self::open_incomplete_internal(input, hierarchy, true)
141 }
142
143 fn open_incomplete_internal<H: BufRead + Seek + Sync + Send + 'static>(
144 mut input: R,
145 mut hierarchy: H,
146 read_time_table: bool,
147 ) -> Result<Self> {
148 let uncompressed_input = uncompress_gzip_wrapper(&mut input)?;
149 match uncompressed_input {
150 UncompressGzipWrapper::None => {
151 let (input, meta) = Self::open_incomplete_internal_uncompressed(
152 input,
153 &mut hierarchy,
154 read_time_table,
155 )?;
156 Ok(FstReader {
157 input: InputVariant::Incomplete(input, Box::new(hierarchy)),
158 meta,
159 })
160 }
161 UncompressGzipWrapper::InMemory(uc) => {
162 let (uc2, meta) = Self::open_incomplete_internal_uncompressed(
163 uc,
164 &mut hierarchy,
165 read_time_table,
166 )?;
167 Ok(FstReader {
168 input: InputVariant::IncompleteUncompressedInMem(uc2, Box::new(hierarchy)),
169 meta,
170 })
171 }
172 }
173 }
174
175 fn open_incomplete_internal_uncompressed<I: BufRead + Seek, H: BufRead + Seek>(
176 input: I,
177 hierarchy: &mut H,
178 read_time_table: bool,
179 ) -> Result<(I, MetaData)> {
180 let mut header_reader = HeaderReader::new(input);
181 match header_reader.read(read_time_table) {
182 Ok(_) => {}
183 Err(ReaderError::MissingGeometry() | ReaderError::MissingHierarchy()) => {
184 header_reader
185 .hierarchy
186 .get_or_insert((HierarchyCompression::Uncompressed, 0));
187 header_reader.reconstruct_geometry(hierarchy)?;
188 }
189 Err(e) => return Err(e),
190 };
191 Ok(header_reader.into_input_and_meta_data().unwrap())
192 }
193
194 pub fn get_header(&self) -> FstHeader {
195 FstHeader {
196 start_time: self.meta.header.start_time,
197 end_time: self.meta.header.end_time,
198 var_count: self.meta.header.var_count,
199 max_handle: self.meta.header.max_var_id_code,
200 version: self.meta.header.version.clone(),
201 date: self.meta.header.date.clone(),
202 timescale_exponent: self.meta.header.timescale_exponent,
203 }
204 }
205
206 pub fn get_time_table(&self) -> Option<&[u64]> {
207 match &self.meta.time_table {
208 Some(table) => Some(table),
209 None => None,
210 }
211 }
212
213 pub fn read_hierarchy(&mut self, callback: impl FnMut(FstHierarchyEntry)) -> Result<()> {
215 match &mut self.input {
216 InputVariant::Original(input) => read_hierarchy(input, &self.meta, callback),
217 InputVariant::Incomplete(_, input) => read_hierarchy(input, &self.meta, callback),
218 InputVariant::UncompressedInMem(input) => read_hierarchy(input, &self.meta, callback),
219 InputVariant::IncompleteUncompressedInMem(_, input) => {
220 read_hierarchy(input, &self.meta, callback)
221 }
222 }
223 }
224
225 pub fn read_signals(
227 &mut self,
228 filter: &FstFilter,
229 callback: impl FnMut(u64, FstSignalHandle, FstSignalValue),
230 ) -> Result<()> {
231 let signal_count = self.meta.signals.len();
233 let signal_mask = if let Some(signals) = &filter.include {
234 let mut signal_mask = BitMask::repeat(false, signal_count);
235 for sig in signals {
236 let signal_idx = sig.get_index();
237 signal_mask.set(signal_idx, true);
238 }
239 signal_mask
240 } else {
241 BitMask::repeat(true, signal_count)
243 };
244 let data_filter = DataFilter {
245 start: filter.start,
246 end: filter.end.unwrap_or(self.meta.header.end_time),
247 signals: signal_mask,
248 };
249
250 match &mut self.input {
252 InputVariant::Original(input) => {
253 read_signals(input, &self.meta, &data_filter, callback)
254 }
255 InputVariant::Incomplete(input, _) => {
256 read_signals(input, &self.meta, &data_filter, callback)
257 }
258 InputVariant::UncompressedInMem(input) => {
259 read_signals(input, &self.meta, &data_filter, callback)
260 }
261 InputVariant::IncompleteUncompressedInMem(input, _) => {
262 read_signals(input, &self.meta, &data_filter, callback)
263 }
264 }
265 }
266}
267
268pub enum FstSignalValue<'a> {
269 String(&'a [u8]),
270 Real(f64),
271}
272
273pub fn is_fst_file(input: &mut (impl Read + Seek)) -> bool {
275 let is_fst = matches!(internal_check_fst_file(input), Ok(true));
276 let _ = input.seek(SeekFrom::Start(0));
278 is_fst
279}
280
281fn internal_check_fst_file(input: &mut (impl Read + Seek)) -> Result<bool> {
283 let mut seen_header = false;
284
285 loop {
287 let block_tpe = match read_block_tpe(input) {
288 Err(ReaderError::Io(_)) => {
289 break;
290 }
291 Err(other) => return Err(other),
292 Ok(tpe) => tpe,
293 };
294 let section_length = read_u64(input)?;
295 match block_tpe {
296 BlockType::GZipWrapper => return Ok(true),
297 BlockType::Header => {
298 seen_header = true;
299 }
300 BlockType::Skip if section_length == 0 => {
301 break;
302 }
303 _ => {}
304 }
305 input.seek(SeekFrom::Current((section_length as i64) - 8))?;
306 }
307 Ok(seen_header)
308}
309
310fn read_hierarchy(
311 input: &mut (impl Read + Seek),
312 meta: &MetaData,
313 mut callback: impl FnMut(FstHierarchyEntry),
314) -> Result<()> {
315 input.seek(SeekFrom::Start(meta.hierarchy_offset))?;
316 let bytes = read_hierarchy_bytes(input, meta.hierarchy_compression)?;
317 let mut input = bytes.as_slice();
318 let mut handle_count = 0u32;
319 while let Some(entry) = read_hierarchy_entry(&mut input, &mut handle_count)? {
320 callback(entry);
321 }
322 Ok(())
323}
324
325fn read_signals(
326 input: &mut (impl Read + Seek),
327 meta: &MetaData,
328 filter: &DataFilter,
329 mut callback: impl FnMut(u64, FstSignalHandle, FstSignalValue),
330) -> Result<()> {
331 let mut reader = DataReader {
332 input,
333 meta,
334 filter,
335 callback: &mut callback,
336 };
337 reader.read()
338}
339
340enum UncompressGzipWrapper {
341 None,
342 InMemory(std::io::Cursor<Vec<u8>>),
344}
345
346fn uncompress_gzip_wrapper(input: &mut (impl Read + Seek)) -> Result<UncompressGzipWrapper> {
349 let block_tpe = read_block_tpe(input)?;
350 if block_tpe != BlockType::GZipWrapper {
351 input.seek(SeekFrom::Start(0))?;
353 Ok(UncompressGzipWrapper::None)
354 } else {
355 let section_length = read_u64(input)?;
357 let uncompress_length = read_u64(input)? as usize;
358 if section_length == 0 {
359 return Err(ReaderError::NotFinishedCompressing());
360 }
361
362 let mut target = vec![];
365 decompress_gz_in_chunks(input, uncompress_length, &mut target)?;
366 let new_input = std::io::Cursor::new(target);
367 Ok(UncompressGzipWrapper::InMemory(new_input))
368 }
369}
370
371fn decompress_gz_in_chunks(
372 input: &mut (impl Read + Seek),
373 mut remaining: usize,
374 target: &mut impl Write,
375) -> Result<()> {
376 read_gzip_header(input)?;
377 let mut buf_in = vec![0u8; 32768 / 2]; let mut buf_out = vec![0u8; 32768 * 2]; let mut state = miniz_oxide::inflate::stream::InflateState::new(miniz_oxide::DataFormat::Raw);
381 let mut buf_in_remaining = 0;
382 while remaining > 0 {
383 buf_in_remaining += input.read(&mut buf_in[buf_in_remaining..])?;
385 debug_assert!(
386 buf_in_remaining > 0,
387 "ran out of input data while gzip decompressing"
388 );
389
390 let res = miniz_oxide::inflate::stream::inflate(
392 &mut state,
393 &buf_in[0..buf_in_remaining],
394 buf_out.as_mut_slice(),
395 miniz_oxide::MZFlush::None,
396 );
397
398 match res.status {
399 Ok(status) => {
400 buf_in.copy_within(res.bytes_consumed..buf_in_remaining, 0);
402 buf_in_remaining -= res.bytes_consumed;
403
404 let out_bytes = std::cmp::min(res.bytes_written, remaining);
406 remaining -= out_bytes;
407 target.write_all(&buf_out[..out_bytes])?;
408
409 match status {
410 miniz_oxide::MZStatus::Ok => {
411 }
413 miniz_oxide::MZStatus::StreamEnd => {
414 debug_assert_eq!(remaining, 0);
415 return Ok(());
416 }
417 miniz_oxide::MZStatus::NeedDict => {
418 todo!("hande NeedDict status");
419 }
420 }
421 }
422 Err(err) => {
423 return Err(ReaderError::GZipBody(format!("{err:?}")));
424 }
425 }
426 }
427
428 Ok(())
429}
430
431#[derive(Debug)]
432struct MetaData {
433 header: Header,
434 signals: Vec<SignalInfo>,
435 #[allow(dead_code)]
436 blackouts: Vec<BlackoutData>,
437 data_sections: Vec<DataSectionInfo>,
438 float_endian: FloatingPointEndian,
439 hierarchy_compression: HierarchyCompression,
440 hierarchy_offset: u64,
441 time_table: Option<Vec<u64>>,
442}
443
444pub type Result<T> = std::result::Result<T, ReaderError>;
445
446struct HeaderReader<R: Read + Seek> {
447 input: R,
448 header: Option<Header>,
449 signals: Option<Vec<SignalInfo>>,
450 blackouts: Option<Vec<BlackoutData>>,
451 data_sections: Vec<DataSectionInfo>,
452 float_endian: FloatingPointEndian,
453 hierarchy: Option<(HierarchyCompression, u64)>,
454 time_table: Option<Vec<u64>>,
455}
456
457impl<R: Read + Seek> HeaderReader<R> {
458 fn new(input: R) -> Self {
459 HeaderReader {
460 input,
461 header: None,
462 signals: None,
463 blackouts: None,
464 data_sections: Vec::default(),
465 float_endian: FloatingPointEndian::Little,
466 hierarchy: None,
467 time_table: None,
468 }
469 }
470
471 fn read_data(&mut self, tpe: &BlockType) -> Result<()> {
472 let file_offset = self.input.stream_position()?;
473 let section_length = read_u64(&mut self.input)?;
475 let start_time = read_u64(&mut self.input)?;
476 let end_time = read_u64(&mut self.input)?;
477 let mem_required_for_traversal = read_u64(&mut self.input)?;
478
479 if let Some(table) = &mut self.time_table {
481 let (_, mut time_chain) =
482 read_time_table(&mut self.input, file_offset, section_length)?;
483 let is_first_section = table.is_empty();
485 if is_first_section && time_chain[0] > start_time {
486 table.push(start_time);
487 }
488 table.append(&mut time_chain);
489 self.input.seek(SeekFrom::Start(file_offset + 4 * 8))?;
490 }
491 self.skip(section_length, 4 * 8)?;
493 let kind = DataSectionKind::from_block_type(tpe).unwrap();
494 let info = DataSectionInfo {
495 file_offset,
496 start_time,
497 end_time,
498 kind,
499 mem_required_for_traversal,
500 };
501
502 if let Some(Header {
505 start_time: header_start,
506 end_time: header_end,
507 ..
508 }) = self.header.as_mut()
509 && *header_start == 0
510 && *header_end == 0
511 {
512 *header_end = end_time;
513 if self.data_sections.is_empty() {
514 *header_start = start_time;
515 }
516 }
517
518 self.data_sections.push(info);
519 Ok(())
520 }
521
522 fn skip(&mut self, section_length: u64, already_read: i64) -> Result<u64> {
523 Ok(self
524 .input
525 .seek(SeekFrom::Current((section_length as i64) - already_read))?)
526 }
527
528 fn read_hierarchy(&mut self, compression: HierarchyCompression) -> Result<()> {
529 let file_offset = self.input.stream_position()?;
530 let section_length = read_u64(&mut self.input)?;
532 self.skip(section_length, 8)?;
533 assert!(
534 self.hierarchy.is_none(),
535 "Only a single hierarchy block is expected!"
536 );
537 self.hierarchy = Some((compression, file_offset));
538 Ok(())
539 }
540
541 fn reconstruct_geometry(&mut self, hierarchy: &mut (impl BufRead + Seek)) -> Result<()> {
544 hierarchy.seek(SeekFrom::Start(0))?;
545 let bytes = read_hierarchy_bytes(hierarchy, HierarchyCompression::Uncompressed)?;
546 let mut input = bytes.as_slice();
547 let mut handle_count = 0u32;
548 let mut signals: Vec<SignalInfo> = Vec::new();
549 while let Some(entry) = read_hierarchy_entry(&mut input, &mut handle_count)? {
550 match entry {
551 FstHierarchyEntry::Var {
552 length, is_alias, ..
553 } if !is_alias => {
554 signals.push(SignalInfo::from_file_format(length));
555 }
556 _ => {}
557 }
558 }
559 self.signals = Some(signals);
560 Ok(())
561 }
562
563 fn read(&mut self, read_time_table: bool) -> Result<()> {
564 if read_time_table {
565 self.time_table = Some(Vec::new());
566 }
567 loop {
568 let block_tpe = match read_block_tpe(&mut self.input) {
569 Err(ReaderError::Io(_)) => {
570 break;
571 }
572 Err(other) => return Err(other),
573 Ok(tpe) => tpe,
574 };
575
576 match block_tpe {
577 BlockType::Header => {
578 let (header, endian) = read_header(&mut self.input)?;
579 self.header = Some(header);
580 self.float_endian = endian;
581 }
582 BlockType::VcData => self.read_data(&block_tpe)?,
583 BlockType::VcDataDynamicAlias => self.read_data(&block_tpe)?,
584 BlockType::VcDataDynamicAlias2 => self.read_data(&block_tpe)?,
585 BlockType::Blackout => {
586 self.blackouts = Some(read_blackout(&mut self.input)?);
587 }
588 BlockType::Geometry => {
589 self.signals = Some(read_geometry(&mut self.input)?);
590 }
591 BlockType::Hierarchy => self.read_hierarchy(HierarchyCompression::ZLib)?,
592 BlockType::HierarchyLZ4 => self.read_hierarchy(HierarchyCompression::Lz4)?,
593 BlockType::HierarchyLZ4Duo => self.read_hierarchy(HierarchyCompression::Lz4Duo)?,
594 BlockType::GZipWrapper => panic!("GZip Wrapper should have been handled earlier!"),
595 BlockType::Skip => {
596 let section_length = read_u64(&mut self.input)?;
597 if section_length == 0 {
598 break;
599 }
600 self.skip(section_length, 8)?;
601 }
602 };
603 }
604
605 if self.signals.is_none() {
606 return Err(ReaderError::MissingGeometry());
607 }
608
609 if self.hierarchy.is_none() {
610 return Err(ReaderError::MissingHierarchy());
611 }
612
613 Ok(())
614 }
615
616 fn into_input_and_meta_data(mut self) -> Result<(R, MetaData)> {
617 self.input.seek(SeekFrom::Start(0))?;
618 let meta = MetaData {
619 header: self.header.unwrap(),
620 signals: self.signals.unwrap(),
621 blackouts: self.blackouts.unwrap_or_default(),
622 data_sections: self.data_sections,
623 float_endian: self.float_endian,
624 hierarchy_compression: self.hierarchy.unwrap().0,
625 hierarchy_offset: self.hierarchy.unwrap().1,
626 time_table: self.time_table,
627 };
628 Ok((self.input, meta))
629 }
630}
631
632struct DataReader<'a, R: Read + Seek, F: FnMut(u64, FstSignalHandle, FstSignalValue)> {
633 input: &'a mut R,
634 meta: &'a MetaData,
635 filter: &'a DataFilter,
636 callback: &'a mut F,
637}
638
639impl<R: Read + Seek, F: FnMut(u64, FstSignalHandle, FstSignalValue)> DataReader<'_, R, F> {
640 fn read_value_changes(
641 &mut self,
642 section_kind: DataSectionKind,
643 section_start: u64,
644 section_length: u64,
645 time_section_length: u64,
646 time_table: &[u64],
647 ) -> Result<()> {
648 let (max_handle, _) = read_variant_u64(&mut self.input)?;
649 let vc_start = self.input.stream_position()?;
650 let packtpe = ValueChangePackType::from_u8(read_u8(&mut self.input)?);
651 let chain_len_offset = section_start + section_length - time_section_length - 8;
653 let signal_offsets = read_signal_locs(
654 &mut self.input,
655 chain_len_offset,
656 section_kind,
657 max_handle,
658 vc_start,
659 )?;
660
661 let mut mu: Vec<u8> = Vec::new();
663 let mut head_pointer = vec![0u32; max_handle as usize];
664 let mut length_remaining = vec![0u32; max_handle as usize];
665 let mut scatter_pointer = vec![0u32; max_handle as usize];
666 let mut tc_head = vec![0u32; std::cmp::max(1, time_table.len())];
667
668 for entry in signal_offsets.iter() {
669 if self.filter.signals.is_set(entry.signal_idx) {
671 self.input.seek(SeekFrom::Start(vc_start + entry.offset))?;
673 let mut bytes =
674 read_packed_signal_value_bytes(&mut self.input, entry.len, packtpe)?;
675
676 let len = self.meta.signals[entry.signal_idx].len();
678 let tdelta = if len == 1 {
679 read_one_bit_signal_time_delta(&bytes, 0)?
680 } else {
681 read_multi_bit_signal_time_delta(&bytes, 0)?
682 };
683
684 head_pointer[entry.signal_idx] = mu.len() as u32;
686 length_remaining[entry.signal_idx] = bytes.len() as u32;
687 mu.append(&mut bytes);
688
689 scatter_pointer[entry.signal_idx] = tc_head[tdelta];
691 tc_head[tdelta] = entry.signal_idx as u32 + 1; }
693 }
694
695 let mut buffer = Vec::new();
696
697 for (time_id, time) in time_table.iter().enumerate() {
698 if *time > self.filter.end {
702 break;
703 }
704
705 let eof_error = || {
706 ReaderError::Io(std::io::Error::new(
707 std::io::ErrorKind::UnexpectedEof,
708 "unexpected eof",
709 ))
710 };
711
712 while tc_head[time_id] != 0 {
714 let signal_id = (tc_head[time_id] - 1) as usize; let mut mu_slice = &mu.as_slice()[head_pointer[signal_id] as usize..];
716 let (vli, skiplen) = read_variant_u32(&mut mu_slice)?;
717 let signal_len = self.meta.signals[signal_id].len();
718 let signal_handle = FstSignalHandle::from_index(signal_id);
719 let len = match signal_len {
720 1 => {
721 let value = one_bit_signal_value_to_char(vli);
722 let value_buf = [value];
723 (self.callback)(*time, signal_handle, FstSignalValue::String(&value_buf));
724 0 }
726 0 => {
727 let (len, skiplen2) = read_variant_u32(&mut mu_slice)?;
728 let value = mu_slice.get(..len as usize).ok_or_else(eof_error)?;
729 (self.callback)(*time, signal_handle, FstSignalValue::String(value));
730 len + skiplen2
731 }
732 len => {
733 let signal_len = len as usize;
734 if !self.meta.signals[signal_id].is_real() {
735 let (value, len) = if (vli & 1) == 0 {
736 let read_len = signal_len.div_ceil(8);
738 let bytes = mu_slice.get(..read_len).ok_or_else(eof_error)?;
739 multi_bit_digital_signal_to_chars(bytes, signal_len, &mut buffer);
740 (buffer.as_slice(), read_len as u32)
741 } else {
742 let value = mu_slice.get(..signal_len).ok_or_else(eof_error)?;
743 (value, len)
744 };
745 (self.callback)(*time, signal_handle, FstSignalValue::String(value));
746 len
747 } else {
748 assert_eq!(vli & 1, 1, "TODO: implement support for rare packed case");
749 let value = read_f64(&mut mu_slice, self.meta.float_endian)?;
750 (self.callback)(*time, signal_handle, FstSignalValue::Real(value));
751 8
752 }
753 }
754 };
755
756 let total_skiplen = skiplen + len;
758 head_pointer[signal_id] += total_skiplen;
760 length_remaining[signal_id] -= total_skiplen;
761 tc_head[time_id] = scatter_pointer[signal_id];
763 scatter_pointer[signal_id] = 0;
765
766 if length_remaining[signal_id] > 0 {
768 let tdelta = if signal_len == 1 {
769 read_one_bit_signal_time_delta(&mu, head_pointer[signal_id])?
770 } else {
771 read_multi_bit_signal_time_delta(&mu, head_pointer[signal_id])?
772 };
773
774 scatter_pointer[signal_id] = tc_head[time_id + tdelta];
776 tc_head[time_id + tdelta] = (signal_id + 1) as u32; }
778 }
779 }
780
781 Ok(())
782 }
783
784 fn read(&mut self) -> Result<()> {
785 let sections = self.meta.data_sections.clone();
786 let relevant_sections = sections
788 .iter()
789 .filter(|s| self.filter.end >= s.start_time && s.end_time >= self.filter.start);
790 for (sec_num, section) in relevant_sections.enumerate() {
791 self.input.seek(SeekFrom::Start(section.file_offset))?;
793 let section_length = read_u64(&mut self.input)?;
794
795 let start_time = read_u64(&mut self.input)?;
797 let end_time = read_u64(&mut self.input)?;
798 assert_eq!(start_time, section.start_time);
799 assert_eq!(end_time, section.end_time);
800 let is_first_section = sec_num == 0;
801
802 let (time_section_length, time_table) =
804 read_time_table(&mut self.input, section.file_offset, section_length)?;
805
806 if is_first_section && (time_table.is_empty() || time_table[0] > start_time) {
809 read_frame(
810 &mut self.input,
811 section.file_offset,
812 section_length,
813 &self.meta.signals,
814 &self.filter.signals,
815 self.meta.float_endian,
816 start_time,
817 self.callback,
818 )?;
819 } else {
820 skip_frame(&mut self.input, section.file_offset)?;
821 }
822
823 self.read_value_changes(
824 section.kind,
825 section.file_offset,
826 section_length,
827 time_section_length,
828 &time_table,
829 )?;
830 }
831
832 Ok(())
833 }
834}