1use crate::io::*;
7use crate::types::*;
8use std::io::{BufRead, Read, Seek, SeekFrom, Write};
9
10pub struct FstReader<R: BufRead + Seek, H = std::io::Cursor<Vec<u8>>> {
12 input: InputVariant<R, H>,
13 meta: MetaData,
14}
15
16enum InputVariant<R: BufRead + Seek, H = std::io::Cursor<Vec<u8>>> {
17 Original(R),
18 Incomplete(R, H),
19 UncompressedInMem(std::io::Cursor<Vec<u8>>),
21 IncompleteUncompressedInMem(std::io::Cursor<Vec<u8>>, H),
22}
23
24pub struct FstFilter {
28 pub start: u64,
29 pub end: Option<u64>,
30 pub include: Option<Vec<FstSignalHandle>>,
31}
32
33impl FstFilter {
34 pub fn all() -> Self {
35 FstFilter {
36 start: 0,
37 end: None,
38 include: None,
39 }
40 }
41
42 pub fn new(start: u64, end: u64, signals: Vec<FstSignalHandle>) -> Self {
43 FstFilter {
44 start,
45 end: Some(end),
46 include: Some(signals),
47 }
48 }
49
50 pub fn filter_time(start: u64, end: u64) -> Self {
51 FstFilter {
52 start,
53 end: Some(end),
54 include: None,
55 }
56 }
57
58 pub fn filter_signals(signals: Vec<FstSignalHandle>) -> Self {
59 FstFilter {
60 start: 0,
61 end: None,
62 include: Some(signals),
63 }
64 }
65}
66
67#[derive(Debug, Clone, PartialEq)]
68pub struct FstHeader {
69 pub start_time: u64,
71 pub end_time: u64,
73 pub var_count: u64,
75 pub max_handle: u64,
77 pub version: String,
79 pub date: String,
81 pub timescale_exponent: i8,
83}
84
85impl<R: BufRead + Seek> FstReader<R> {
86 pub fn open(input: R) -> Result<Self> {
88 Self::open_internal(input, false)
89 }
90
91 pub fn open_and_read_time_table(input: R) -> Result<Self> {
92 Self::open_internal(input, true)
93 }
94
95 fn open_internal(mut input: R, read_time_table: bool) -> Result<Self> {
96 let uncompressed_input = uncompress_gzip_wrapper(&mut input)?;
97 match uncompressed_input {
98 UncompressGzipWrapper::None => {
99 let mut header_reader = HeaderReader::new(input);
100 header_reader.read(read_time_table)?;
101 let (input, meta) = header_reader.into_input_and_meta_data().unwrap();
102 Ok(FstReader {
103 input: InputVariant::Original(input),
104 meta,
105 })
106 }
107 UncompressGzipWrapper::InMemory(uc) => {
108 let mut header_reader = HeaderReader::new(uc);
109 header_reader.read(read_time_table)?;
110 let (uc2, meta) = header_reader.into_input_and_meta_data().unwrap();
111 Ok(FstReader {
112 input: InputVariant::UncompressedInMem(uc2),
113 meta,
114 })
115 }
116 }
117 }
118}
119
120impl<R: BufRead + Seek, H: BufRead + Seek> FstReader<R, H> {
121 pub fn open_incomplete(input: R, hierarchy: H) -> Result<Self> {
130 Self::open_incomplete_internal(input, hierarchy, false)
131 }
132
133 pub fn open_incomplete_and_read_time_table(input: R, hierarchy: H) -> Result<Self> {
134 Self::open_incomplete_internal(input, hierarchy, true)
135 }
136
137 fn open_incomplete_internal(
138 mut input: R,
139 mut hierarchy: H,
140 read_time_table: bool,
141 ) -> Result<Self> {
142 let uncompressed_input = uncompress_gzip_wrapper(&mut input)?;
143 match uncompressed_input {
144 UncompressGzipWrapper::None => {
145 let (input, meta) = Self::open_incomplete_internal_uncompressed(
146 input,
147 &mut hierarchy,
148 read_time_table,
149 )?;
150 Ok(FstReader {
151 input: InputVariant::Incomplete(input, hierarchy),
152 meta,
153 })
154 }
155 UncompressGzipWrapper::InMemory(uc) => {
156 let (uc2, meta) = Self::open_incomplete_internal_uncompressed(
157 uc,
158 &mut hierarchy,
159 read_time_table,
160 )?;
161 Ok(FstReader {
162 input: InputVariant::IncompleteUncompressedInMem(uc2, hierarchy),
163 meta,
164 })
165 }
166 }
167 }
168
169 fn open_incomplete_internal_uncompressed<I: BufRead + Seek>(
170 input: I,
171 hierarchy: &mut H,
172 read_time_table: bool,
173 ) -> Result<(I, MetaData)> {
174 let mut header_reader = HeaderReader::new(input);
175 match header_reader.read(read_time_table) {
176 Ok(_) => {}
177 Err(ReaderError::MissingGeometry() | ReaderError::MissingHierarchy()) => {
178 header_reader
179 .hierarchy
180 .get_or_insert((HierarchyCompression::Uncompressed, 0));
181 header_reader.reconstruct_geometry(hierarchy)?;
182 }
183 Err(e) => return Err(e),
184 };
185 Ok(header_reader.into_input_and_meta_data().unwrap())
186 }
187}
188
189impl<R: BufRead + Seek, H: BufRead + Seek> FstReader<R, H> {
190 pub fn get_header(&self) -> FstHeader {
191 FstHeader {
192 start_time: self.meta.header.start_time,
193 end_time: self.meta.header.end_time,
194 var_count: self.meta.header.var_count,
195 max_handle: self.meta.header.max_var_id_code,
196 version: self.meta.header.version.clone(),
197 date: self.meta.header.date.clone(),
198 timescale_exponent: self.meta.header.timescale_exponent,
199 }
200 }
201
202 pub fn get_time_table(&self) -> Option<&[u64]> {
203 match &self.meta.time_table {
204 Some(table) => Some(table),
205 None => None,
206 }
207 }
208
209 pub fn read_hierarchy(&mut self, callback: impl FnMut(FstHierarchyEntry)) -> Result<()> {
211 match &mut self.input {
212 InputVariant::Original(input) => read_hierarchy(input, &self.meta, callback),
213 InputVariant::Incomplete(_, input) => read_hierarchy(input, &self.meta, callback),
214 InputVariant::UncompressedInMem(input) => read_hierarchy(input, &self.meta, callback),
215 InputVariant::IncompleteUncompressedInMem(_, input) => {
216 read_hierarchy(input, &self.meta, callback)
217 }
218 }
219 }
220
221 pub fn read_signals(
223 &mut self,
224 filter: &FstFilter,
225 callback: impl FnMut(u64, FstSignalHandle, FstSignalValue),
226 ) -> Result<()> {
227 let signal_count = self.meta.signals.len();
229 let signal_mask = if let Some(signals) = &filter.include {
230 let mut signal_mask = BitMask::repeat(false, signal_count);
231 for sig in signals {
232 let signal_idx = sig.get_index();
233 signal_mask.set(signal_idx, true);
234 }
235 signal_mask
236 } else {
237 BitMask::repeat(true, signal_count)
239 };
240 let data_filter = DataFilter {
241 start: filter.start,
242 end: filter.end.unwrap_or(self.meta.header.end_time),
243 signals: signal_mask,
244 };
245
246 match &mut self.input {
248 InputVariant::Original(input) => {
249 read_signals(input, &self.meta, &data_filter, callback)
250 }
251 InputVariant::Incomplete(input, _) => {
252 read_signals(input, &self.meta, &data_filter, callback)
253 }
254 InputVariant::UncompressedInMem(input) => {
255 read_signals(input, &self.meta, &data_filter, callback)
256 }
257 InputVariant::IncompleteUncompressedInMem(input, _) => {
258 read_signals(input, &self.meta, &data_filter, callback)
259 }
260 }
261 }
262}
263
264pub enum FstSignalValue<'a> {
265 String(&'a [u8]),
266 Real(f64),
267}
268
269pub fn is_fst_file(input: &mut (impl Read + Seek)) -> bool {
271 let is_fst = matches!(internal_check_fst_file(input), Ok(true));
272 let _ = input.seek(SeekFrom::Start(0));
274 is_fst
275}
276
277fn internal_check_fst_file(input: &mut (impl Read + Seek)) -> Result<bool> {
279 let mut seen_header = false;
280
281 loop {
283 let block_tpe = match read_block_tpe(input) {
284 Err(ReaderError::Io(_)) => {
285 break;
286 }
287 Err(other) => return Err(other),
288 Ok(tpe) => tpe,
289 };
290 let section_length = read_u64(input)?;
291 match block_tpe {
292 BlockType::GZipWrapper => return Ok(true),
293 BlockType::Header => {
294 seen_header = true;
295 }
296 BlockType::Skip if section_length == 0 => {
297 break;
298 }
299 _ => {}
300 }
301 input.seek(SeekFrom::Current((section_length as i64) - 8))?;
302 }
303 Ok(seen_header)
304}
305
306fn read_hierarchy(
307 input: &mut (impl Read + Seek),
308 meta: &MetaData,
309 mut callback: impl FnMut(FstHierarchyEntry),
310) -> Result<()> {
311 input.seek(SeekFrom::Start(meta.hierarchy_offset))?;
312 let bytes = read_hierarchy_bytes(input, meta.hierarchy_compression)?;
313 let mut input = bytes.as_slice();
314 let mut handle_count = 0u32;
315 while let Some(entry) = read_hierarchy_entry(&mut input, &mut handle_count)? {
316 callback(entry);
317 }
318 Ok(())
319}
320
321fn read_signals(
322 input: &mut (impl Read + Seek),
323 meta: &MetaData,
324 filter: &DataFilter,
325 mut callback: impl FnMut(u64, FstSignalHandle, FstSignalValue),
326) -> Result<()> {
327 let mut reader = DataReader {
328 input,
329 meta,
330 filter,
331 callback: &mut callback,
332 };
333 reader.read()
334}
335
336enum UncompressGzipWrapper {
337 None,
338 InMemory(std::io::Cursor<Vec<u8>>),
340}
341
342fn uncompress_gzip_wrapper(input: &mut (impl Read + Seek)) -> Result<UncompressGzipWrapper> {
345 let block_tpe = read_block_tpe(input)?;
346 if block_tpe != BlockType::GZipWrapper {
347 input.seek(SeekFrom::Start(0))?;
349 Ok(UncompressGzipWrapper::None)
350 } else {
351 let section_length = read_u64(input)?;
353 let uncompress_length = read_u64(input)? as usize;
354 if section_length == 0 {
355 return Err(ReaderError::NotFinishedCompressing());
356 }
357
358 let mut target = vec![];
361 decompress_gz_in_chunks(input, uncompress_length, &mut target)?;
362 let new_input = std::io::Cursor::new(target);
363 Ok(UncompressGzipWrapper::InMemory(new_input))
364 }
365}
366
367fn decompress_gz_in_chunks(
368 input: &mut (impl Read + Seek),
369 mut remaining: usize,
370 target: &mut impl Write,
371) -> Result<()> {
372 read_gzip_header(input)?;
373 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);
377 let mut buf_in_remaining = 0;
378 while remaining > 0 {
379 buf_in_remaining += input.read(&mut buf_in[buf_in_remaining..])?;
381 debug_assert!(
382 buf_in_remaining > 0,
383 "ran out of input data while gzip decompressing"
384 );
385
386 let res = miniz_oxide::inflate::stream::inflate(
388 &mut state,
389 &buf_in[0..buf_in_remaining],
390 buf_out.as_mut_slice(),
391 miniz_oxide::MZFlush::None,
392 );
393
394 println!("{res:?}\nremaining={remaining}");
395
396 match res.status {
397 Ok(status) => {
398 buf_in.copy_within(res.bytes_consumed..buf_in_remaining, 0);
400 buf_in_remaining -= res.bytes_consumed;
401
402 let out_bytes = std::cmp::min(res.bytes_written, remaining);
404 remaining -= out_bytes;
405 target.write_all(&buf_out[..out_bytes])?;
406
407 match status {
408 miniz_oxide::MZStatus::Ok => {
409 }
411 miniz_oxide::MZStatus::StreamEnd => {
412 debug_assert_eq!(remaining, 0);
413 return Ok(());
414 }
415 miniz_oxide::MZStatus::NeedDict => {
416 todo!("hande NeedDict status");
417 }
418 }
419 }
420 Err(err) => {
421 return Err(ReaderError::GZipBody(format!("{err:?}")));
422 }
423 }
424 }
425
426 Ok(())
427}
428
429#[derive(Debug)]
430struct MetaData {
431 header: Header,
432 signals: Vec<SignalInfo>,
433 #[allow(dead_code)]
434 blackouts: Vec<BlackoutData>,
435 data_sections: Vec<DataSectionInfo>,
436 float_endian: FloatingPointEndian,
437 hierarchy_compression: HierarchyCompression,
438 hierarchy_offset: u64,
439 time_table: Option<Vec<u64>>,
440}
441
442pub type Result<T> = std::result::Result<T, ReaderError>;
443
444struct HeaderReader<R: Read + Seek> {
445 input: R,
446 header: Option<Header>,
447 signals: Option<Vec<SignalInfo>>,
448 blackouts: Option<Vec<BlackoutData>>,
449 data_sections: Vec<DataSectionInfo>,
450 float_endian: FloatingPointEndian,
451 hierarchy: Option<(HierarchyCompression, u64)>,
452 time_table: Option<Vec<u64>>,
453}
454
455impl<R: Read + Seek> HeaderReader<R> {
456 fn new(input: R) -> Self {
457 HeaderReader {
458 input,
459 header: None,
460 signals: None,
461 blackouts: None,
462 data_sections: Vec::default(),
463 float_endian: FloatingPointEndian::Little,
464 hierarchy: None,
465 time_table: None,
466 }
467 }
468
469 fn read_data(&mut self, tpe: &BlockType) -> Result<()> {
470 let file_offset = self.input.stream_position()?;
471 let section_length = read_u64(&mut self.input)?;
473 let start_time = read_u64(&mut self.input)?;
474 let end_time = read_u64(&mut self.input)?;
475 let mem_required_for_traversal = read_u64(&mut self.input)?;
476
477 if let Some(table) = &mut self.time_table {
479 let (_, mut time_chain) =
480 read_time_table(&mut self.input, file_offset, section_length)?;
481 let is_first_section = table.is_empty();
483 if is_first_section && time_chain[0] > start_time {
484 table.push(start_time);
485 }
486 table.append(&mut time_chain);
487 self.input.seek(SeekFrom::Start(file_offset + 4 * 8))?;
488 }
489 self.skip(section_length, 4 * 8)?;
491 let kind = DataSectionKind::from_block_type(tpe).unwrap();
492 let info = DataSectionInfo {
493 file_offset,
494 start_time,
495 end_time,
496 kind,
497 mem_required_for_traversal,
498 };
499
500 if let Some(Header {
503 start_time: header_start,
504 end_time: header_end,
505 ..
506 }) = self.header.as_mut()
507 {
508 if *header_start == 0 && *header_end == 0 {
509 *header_end = end_time;
510 if self.data_sections.is_empty() {
511 *header_start = start_time;
512 }
513 }
514 }
515
516 self.data_sections.push(info);
517 Ok(())
518 }
519
520 fn skip(&mut self, section_length: u64, already_read: i64) -> Result<u64> {
521 Ok(self
522 .input
523 .seek(SeekFrom::Current((section_length as i64) - already_read))?)
524 }
525
526 fn read_hierarchy(&mut self, compression: HierarchyCompression) -> Result<()> {
527 let file_offset = self.input.stream_position()?;
528 let section_length = read_u64(&mut self.input)?;
530 self.skip(section_length, 8)?;
531 assert!(
532 self.hierarchy.is_none(),
533 "Only a single hierarchy block is expected!"
534 );
535 self.hierarchy = Some((compression, file_offset));
536 Ok(())
537 }
538
539 fn reconstruct_geometry(&mut self, hierarchy: &mut (impl BufRead + Seek)) -> Result<()> {
542 hierarchy.seek(SeekFrom::Start(0))?;
543 let bytes = read_hierarchy_bytes(hierarchy, HierarchyCompression::Uncompressed)?;
544 let mut input = bytes.as_slice();
545 let mut handle_count = 0u32;
546 let mut signals: Vec<SignalInfo> = Vec::new();
547 while let Some(entry) = read_hierarchy_entry(&mut input, &mut handle_count)? {
548 match entry {
549 FstHierarchyEntry::Var {
550 length, is_alias, ..
551 } if !is_alias => {
552 signals.push(SignalInfo::from_file_format(length));
553 }
554 _ => {}
555 }
556 }
557 self.signals = Some(signals);
558 Ok(())
559 }
560
561 fn read(&mut self, read_time_table: bool) -> Result<()> {
562 if read_time_table {
563 self.time_table = Some(Vec::new());
564 }
565 loop {
566 let block_tpe = match read_block_tpe(&mut self.input) {
567 Err(ReaderError::Io(_)) => {
568 break;
569 }
570 Err(other) => return Err(other),
571 Ok(tpe) => tpe,
572 };
573
574 dbg!(&block_tpe);
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}