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 println!("{res:?}\nremaining={remaining}");
399
400 match res.status {
401 Ok(status) => {
402 buf_in.copy_within(res.bytes_consumed..buf_in_remaining, 0);
404 buf_in_remaining -= res.bytes_consumed;
405
406 let out_bytes = std::cmp::min(res.bytes_written, remaining);
408 remaining -= out_bytes;
409 target.write_all(&buf_out[..out_bytes])?;
410
411 match status {
412 miniz_oxide::MZStatus::Ok => {
413 }
415 miniz_oxide::MZStatus::StreamEnd => {
416 debug_assert_eq!(remaining, 0);
417 return Ok(());
418 }
419 miniz_oxide::MZStatus::NeedDict => {
420 todo!("hande NeedDict status");
421 }
422 }
423 }
424 Err(err) => {
425 return Err(ReaderError::GZipBody(format!("{err:?}")));
426 }
427 }
428 }
429
430 Ok(())
431}
432
433#[derive(Debug)]
434struct MetaData {
435 header: Header,
436 signals: Vec<SignalInfo>,
437 #[allow(dead_code)]
438 blackouts: Vec<BlackoutData>,
439 data_sections: Vec<DataSectionInfo>,
440 float_endian: FloatingPointEndian,
441 hierarchy_compression: HierarchyCompression,
442 hierarchy_offset: u64,
443 time_table: Option<Vec<u64>>,
444}
445
446pub type Result<T> = std::result::Result<T, ReaderError>;
447
448struct HeaderReader<R: Read + Seek> {
449 input: R,
450 header: Option<Header>,
451 signals: Option<Vec<SignalInfo>>,
452 blackouts: Option<Vec<BlackoutData>>,
453 data_sections: Vec<DataSectionInfo>,
454 float_endian: FloatingPointEndian,
455 hierarchy: Option<(HierarchyCompression, u64)>,
456 time_table: Option<Vec<u64>>,
457}
458
459impl<R: Read + Seek> HeaderReader<R> {
460 fn new(input: R) -> Self {
461 HeaderReader {
462 input,
463 header: None,
464 signals: None,
465 blackouts: None,
466 data_sections: Vec::default(),
467 float_endian: FloatingPointEndian::Little,
468 hierarchy: None,
469 time_table: None,
470 }
471 }
472
473 fn read_data(&mut self, tpe: &BlockType) -> Result<()> {
474 let file_offset = self.input.stream_position()?;
475 let section_length = read_u64(&mut self.input)?;
477 let start_time = read_u64(&mut self.input)?;
478 let end_time = read_u64(&mut self.input)?;
479 let mem_required_for_traversal = read_u64(&mut self.input)?;
480
481 if let Some(table) = &mut self.time_table {
483 let (_, mut time_chain) =
484 read_time_table(&mut self.input, file_offset, section_length)?;
485 let is_first_section = table.is_empty();
487 if is_first_section && time_chain[0] > start_time {
488 table.push(start_time);
489 }
490 table.append(&mut time_chain);
491 self.input.seek(SeekFrom::Start(file_offset + 4 * 8))?;
492 }
493 self.skip(section_length, 4 * 8)?;
495 let kind = DataSectionKind::from_block_type(tpe).unwrap();
496 let info = DataSectionInfo {
497 file_offset,
498 start_time,
499 end_time,
500 kind,
501 mem_required_for_traversal,
502 };
503
504 if let Some(Header {
507 start_time: header_start,
508 end_time: header_end,
509 ..
510 }) = self.header.as_mut()
511 {
512 if *header_start == 0 && *header_end == 0 {
513 *header_end = end_time;
514 if self.data_sections.is_empty() {
515 *header_start = start_time;
516 }
517 }
518 }
519
520 self.data_sections.push(info);
521 Ok(())
522 }
523
524 fn skip(&mut self, section_length: u64, already_read: i64) -> Result<u64> {
525 Ok(self
526 .input
527 .seek(SeekFrom::Current((section_length as i64) - already_read))?)
528 }
529
530 fn read_hierarchy(&mut self, compression: HierarchyCompression) -> Result<()> {
531 let file_offset = self.input.stream_position()?;
532 let section_length = read_u64(&mut self.input)?;
534 self.skip(section_length, 8)?;
535 assert!(
536 self.hierarchy.is_none(),
537 "Only a single hierarchy block is expected!"
538 );
539 self.hierarchy = Some((compression, file_offset));
540 Ok(())
541 }
542
543 fn reconstruct_geometry(&mut self, hierarchy: &mut (impl BufRead + Seek)) -> Result<()> {
546 hierarchy.seek(SeekFrom::Start(0))?;
547 let bytes = read_hierarchy_bytes(hierarchy, HierarchyCompression::Uncompressed)?;
548 let mut input = bytes.as_slice();
549 let mut handle_count = 0u32;
550 let mut signals: Vec<SignalInfo> = Vec::new();
551 while let Some(entry) = read_hierarchy_entry(&mut input, &mut handle_count)? {
552 match entry {
553 FstHierarchyEntry::Var {
554 length, is_alias, ..
555 } if !is_alias => {
556 signals.push(SignalInfo::from_file_format(length));
557 }
558 _ => {}
559 }
560 }
561 self.signals = Some(signals);
562 Ok(())
563 }
564
565 fn read(&mut self, read_time_table: bool) -> Result<()> {
566 if read_time_table {
567 self.time_table = Some(Vec::new());
568 }
569 loop {
570 let block_tpe = match read_block_tpe(&mut self.input) {
571 Err(ReaderError::Io(_)) => {
572 break;
573 }
574 Err(other) => return Err(other),
575 Ok(tpe) => tpe,
576 };
577
578 dbg!(&block_tpe);
579
580 match block_tpe {
581 BlockType::Header => {
582 let (header, endian) = read_header(&mut self.input)?;
583 self.header = Some(header);
584 self.float_endian = endian;
585 }
586 BlockType::VcData => self.read_data(&block_tpe)?,
587 BlockType::VcDataDynamicAlias => self.read_data(&block_tpe)?,
588 BlockType::VcDataDynamicAlias2 => self.read_data(&block_tpe)?,
589 BlockType::Blackout => {
590 self.blackouts = Some(read_blackout(&mut self.input)?);
591 }
592 BlockType::Geometry => {
593 self.signals = Some(read_geometry(&mut self.input)?);
594 }
595 BlockType::Hierarchy => self.read_hierarchy(HierarchyCompression::ZLib)?,
596 BlockType::HierarchyLZ4 => self.read_hierarchy(HierarchyCompression::Lz4)?,
597 BlockType::HierarchyLZ4Duo => self.read_hierarchy(HierarchyCompression::Lz4Duo)?,
598 BlockType::GZipWrapper => panic!("GZip Wrapper should have been handled earlier!"),
599 BlockType::Skip => {
600 let section_length = read_u64(&mut self.input)?;
601 if section_length == 0 {
602 break;
603 }
604 self.skip(section_length, 8)?;
605 }
606 };
607 }
608
609 if self.signals.is_none() {
610 return Err(ReaderError::MissingGeometry());
611 }
612
613 if self.hierarchy.is_none() {
614 return Err(ReaderError::MissingHierarchy());
615 }
616
617 Ok(())
618 }
619
620 fn into_input_and_meta_data(mut self) -> Result<(R, MetaData)> {
621 self.input.seek(SeekFrom::Start(0))?;
622 let meta = MetaData {
623 header: self.header.unwrap(),
624 signals: self.signals.unwrap(),
625 blackouts: self.blackouts.unwrap_or_default(),
626 data_sections: self.data_sections,
627 float_endian: self.float_endian,
628 hierarchy_compression: self.hierarchy.unwrap().0,
629 hierarchy_offset: self.hierarchy.unwrap().1,
630 time_table: self.time_table,
631 };
632 Ok((self.input, meta))
633 }
634}
635
636struct DataReader<'a, R: Read + Seek, F: FnMut(u64, FstSignalHandle, FstSignalValue)> {
637 input: &'a mut R,
638 meta: &'a MetaData,
639 filter: &'a DataFilter,
640 callback: &'a mut F,
641}
642
643impl<R: Read + Seek, F: FnMut(u64, FstSignalHandle, FstSignalValue)> DataReader<'_, R, F> {
644 fn read_value_changes(
645 &mut self,
646 section_kind: DataSectionKind,
647 section_start: u64,
648 section_length: u64,
649 time_section_length: u64,
650 time_table: &[u64],
651 ) -> Result<()> {
652 let (max_handle, _) = read_variant_u64(&mut self.input)?;
653 let vc_start = self.input.stream_position()?;
654 let packtpe = ValueChangePackType::from_u8(read_u8(&mut self.input)?);
655 let chain_len_offset = section_start + section_length - time_section_length - 8;
657 let signal_offsets = read_signal_locs(
658 &mut self.input,
659 chain_len_offset,
660 section_kind,
661 max_handle,
662 vc_start,
663 )?;
664
665 let mut mu: Vec<u8> = Vec::new();
667 let mut head_pointer = vec![0u32; max_handle as usize];
668 let mut length_remaining = vec![0u32; max_handle as usize];
669 let mut scatter_pointer = vec![0u32; max_handle as usize];
670 let mut tc_head = vec![0u32; std::cmp::max(1, time_table.len())];
671
672 for entry in signal_offsets.iter() {
673 if self.filter.signals.is_set(entry.signal_idx) {
675 self.input.seek(SeekFrom::Start(vc_start + entry.offset))?;
677 let mut bytes =
678 read_packed_signal_value_bytes(&mut self.input, entry.len, packtpe)?;
679
680 let len = self.meta.signals[entry.signal_idx].len();
682 let tdelta = if len == 1 {
683 read_one_bit_signal_time_delta(&bytes, 0)?
684 } else {
685 read_multi_bit_signal_time_delta(&bytes, 0)?
686 };
687
688 head_pointer[entry.signal_idx] = mu.len() as u32;
690 length_remaining[entry.signal_idx] = bytes.len() as u32;
691 mu.append(&mut bytes);
692
693 scatter_pointer[entry.signal_idx] = tc_head[tdelta];
695 tc_head[tdelta] = entry.signal_idx as u32 + 1; }
697 }
698
699 let mut buffer = Vec::new();
700
701 for (time_id, time) in time_table.iter().enumerate() {
702 if *time > self.filter.end {
706 break;
707 }
708
709 let eof_error = || {
710 ReaderError::Io(std::io::Error::new(
711 std::io::ErrorKind::UnexpectedEof,
712 "unexpected eof",
713 ))
714 };
715
716 while tc_head[time_id] != 0 {
718 let signal_id = (tc_head[time_id] - 1) as usize; let mut mu_slice = &mu.as_slice()[head_pointer[signal_id] as usize..];
720 let (vli, skiplen) = read_variant_u32(&mut mu_slice)?;
721 let signal_len = self.meta.signals[signal_id].len();
722 let signal_handle = FstSignalHandle::from_index(signal_id);
723 let len = match signal_len {
724 1 => {
725 let value = one_bit_signal_value_to_char(vli);
726 let value_buf = [value];
727 (self.callback)(*time, signal_handle, FstSignalValue::String(&value_buf));
728 0 }
730 0 => {
731 let (len, skiplen2) = read_variant_u32(&mut mu_slice)?;
732 let value = mu_slice.get(..len as usize).ok_or_else(eof_error)?;
733 (self.callback)(*time, signal_handle, FstSignalValue::String(value));
734 len + skiplen2
735 }
736 len => {
737 let signal_len = len as usize;
738 if !self.meta.signals[signal_id].is_real() {
739 let (value, len) = if (vli & 1) == 0 {
740 let read_len = signal_len.div_ceil(8);
742 let bytes = mu_slice.get(..read_len).ok_or_else(eof_error)?;
743 multi_bit_digital_signal_to_chars(bytes, signal_len, &mut buffer);
744 (buffer.as_slice(), read_len as u32)
745 } else {
746 let value = mu_slice.get(..signal_len).ok_or_else(eof_error)?;
747 (value, len)
748 };
749 (self.callback)(*time, signal_handle, FstSignalValue::String(value));
750 len
751 } else {
752 assert_eq!(vli & 1, 1, "TODO: implement support for rare packed case");
753 let value = read_f64(&mut mu_slice, self.meta.float_endian)?;
754 (self.callback)(*time, signal_handle, FstSignalValue::Real(value));
755 8
756 }
757 }
758 };
759
760 let total_skiplen = skiplen + len;
762 head_pointer[signal_id] += total_skiplen;
764 length_remaining[signal_id] -= total_skiplen;
765 tc_head[time_id] = scatter_pointer[signal_id];
767 scatter_pointer[signal_id] = 0;
769
770 if length_remaining[signal_id] > 0 {
772 let tdelta = if signal_len == 1 {
773 read_one_bit_signal_time_delta(&mu, head_pointer[signal_id])?
774 } else {
775 read_multi_bit_signal_time_delta(&mu, head_pointer[signal_id])?
776 };
777
778 scatter_pointer[signal_id] = tc_head[time_id + tdelta];
780 tc_head[time_id + tdelta] = (signal_id + 1) as u32; }
782 }
783 }
784
785 Ok(())
786 }
787
788 fn read(&mut self) -> Result<()> {
789 let sections = self.meta.data_sections.clone();
790 let relevant_sections = sections
792 .iter()
793 .filter(|s| self.filter.end >= s.start_time && s.end_time >= self.filter.start);
794 for (sec_num, section) in relevant_sections.enumerate() {
795 self.input.seek(SeekFrom::Start(section.file_offset))?;
797 let section_length = read_u64(&mut self.input)?;
798
799 let start_time = read_u64(&mut self.input)?;
801 let end_time = read_u64(&mut self.input)?;
802 assert_eq!(start_time, section.start_time);
803 assert_eq!(end_time, section.end_time);
804 let is_first_section = sec_num == 0;
805
806 let (time_section_length, time_table) =
808 read_time_table(&mut self.input, section.file_offset, section_length)?;
809
810 if is_first_section && (time_table.is_empty() || time_table[0] > start_time) {
813 read_frame(
814 &mut self.input,
815 section.file_offset,
816 section_length,
817 &self.meta.signals,
818 &self.filter.signals,
819 self.meta.float_endian,
820 start_time,
821 self.callback,
822 )?;
823 } else {
824 skip_frame(&mut self.input, section.file_offset)?;
825 }
826
827 self.read_value_changes(
828 section.kind,
829 section.file_offset,
830 section_length,
831 time_section_length,
832 &time_table,
833 )?;
834 }
835
836 Ok(())
837 }
838}