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 is_incomplete: bool,
456}
457
458impl<R: Read + Seek> HeaderReader<R> {
459 fn new(input: R) -> Self {
460 HeaderReader {
461 input,
462 header: None,
463 signals: None,
464 blackouts: None,
465 data_sections: Vec::default(),
466 float_endian: FloatingPointEndian::Little,
467 hierarchy: None,
468 time_table: None,
469 is_incomplete: false,
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) = self.header.as_mut() {
507 if self.data_sections.is_empty() {
508 self.is_incomplete = header.start_time == 0 && header.end_time == 0;
509 if self.is_incomplete {
510 header.start_time = start_time;
511 }
512 }
513 if self.is_incomplete {
514 header.end_time = end_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 tpe,
553 length,
554 is_alias,
555 ..
556 } if !is_alias => {
557 let signal_info = if tpe.is_real() {
560 SignalInfo::Real
561 } else {
562 SignalInfo::from_file_format(length)
563 };
564 signals.push(signal_info);
565 }
566 _ => {}
567 }
568 }
569 self.signals = Some(signals);
570 Ok(())
571 }
572
573 fn read(&mut self, read_time_table: bool) -> Result<()> {
574 if read_time_table {
575 self.time_table = Some(Vec::new());
576 }
577 loop {
578 let block_tpe = match read_block_tpe(&mut self.input) {
579 Err(ReaderError::Io(_)) => {
580 break;
581 }
582 Err(other) => return Err(other),
583 Ok(tpe) => tpe,
584 };
585
586 match block_tpe {
587 BlockType::Header => {
588 let (header, endian) = read_header(&mut self.input)?;
589 self.header = Some(header);
590 self.float_endian = endian;
591 }
592 BlockType::VcData => self.read_data(&block_tpe)?,
593 BlockType::VcDataDynamicAlias => self.read_data(&block_tpe)?,
594 BlockType::VcDataDynamicAlias2 => self.read_data(&block_tpe)?,
595 BlockType::Blackout => {
596 self.blackouts = Some(read_blackout(&mut self.input)?);
597 }
598 BlockType::Geometry => {
599 self.signals = Some(read_geometry(&mut self.input)?);
600 }
601 BlockType::Hierarchy => self.read_hierarchy(HierarchyCompression::ZLib)?,
602 BlockType::HierarchyLZ4 => self.read_hierarchy(HierarchyCompression::Lz4)?,
603 BlockType::HierarchyLZ4Duo => self.read_hierarchy(HierarchyCompression::Lz4Duo)?,
604 BlockType::GZipWrapper => panic!("GZip Wrapper should have been handled earlier!"),
605 BlockType::Skip => {
606 let section_length = read_u64(&mut self.input)?;
607 if section_length == 0 {
608 break;
609 }
610 self.skip(section_length, 8)?;
611 }
612 };
613 }
614
615 if self.signals.is_none() {
616 return Err(ReaderError::MissingGeometry());
617 }
618
619 if self.hierarchy.is_none() {
620 return Err(ReaderError::MissingHierarchy());
621 }
622
623 Ok(())
624 }
625
626 fn into_input_and_meta_data(mut self) -> Result<(R, MetaData)> {
627 self.input.seek(SeekFrom::Start(0))?;
628 let meta = MetaData {
629 header: self.header.unwrap(),
630 signals: self.signals.unwrap(),
631 blackouts: self.blackouts.unwrap_or_default(),
632 data_sections: self.data_sections,
633 float_endian: self.float_endian,
634 hierarchy_compression: self.hierarchy.unwrap().0,
635 hierarchy_offset: self.hierarchy.unwrap().1,
636 time_table: self.time_table,
637 };
638 Ok((self.input, meta))
639 }
640}
641
642struct DataReader<'a, R: Read + Seek, F: FnMut(u64, FstSignalHandle, FstSignalValue)> {
643 input: &'a mut R,
644 meta: &'a MetaData,
645 filter: &'a DataFilter,
646 callback: &'a mut F,
647}
648
649impl<R: Read + Seek, F: FnMut(u64, FstSignalHandle, FstSignalValue)> DataReader<'_, R, F> {
650 fn read_value_changes(
651 &mut self,
652 section_kind: DataSectionKind,
653 section_start: u64,
654 section_length: u64,
655 time_section_length: u64,
656 time_table: &[u64],
657 ) -> Result<()> {
658 let (max_handle, _) = read_variant_u64(&mut self.input)?;
659 let vc_start = self.input.stream_position()?;
660 let packtpe = ValueChangePackType::from_u8(read_u8(&mut self.input)?);
661 let chain_len_offset = section_start + section_length - time_section_length - 8;
663 let signal_offsets = read_signal_locs(
664 &mut self.input,
665 chain_len_offset,
666 section_kind,
667 max_handle,
668 vc_start,
669 )?;
670
671 let mut mu: Vec<u8> = Vec::new();
673 let mut head_pointer = vec![0u32; max_handle as usize];
674 let mut length_remaining = vec![0u32; max_handle as usize];
675 let mut scatter_pointer = vec![0u32; max_handle as usize];
676 let mut tc_head = vec![0u32; std::cmp::max(1, time_table.len())];
677
678 for entry in signal_offsets.iter() {
679 if self.filter.signals.is_set(entry.signal_idx) {
681 self.input.seek(SeekFrom::Start(vc_start + entry.offset))?;
683 let mut bytes =
684 read_packed_signal_value_bytes(&mut self.input, entry.len, packtpe)?;
685
686 let len = self.meta.signals[entry.signal_idx].len();
688 let tdelta = if len == 1 {
689 read_one_bit_signal_time_delta(&bytes, 0)?
690 } else {
691 read_multi_bit_signal_time_delta(&bytes, 0)?
692 };
693
694 head_pointer[entry.signal_idx] = mu.len() as u32;
696 length_remaining[entry.signal_idx] = bytes.len() as u32;
697 mu.append(&mut bytes);
698
699 scatter_pointer[entry.signal_idx] = tc_head[tdelta];
701 tc_head[tdelta] = entry.signal_idx as u32 + 1; }
703 }
704
705 let mut buffer = Vec::new();
706
707 for (time_id, time) in time_table.iter().enumerate() {
708 if *time > self.filter.end {
712 break;
713 }
714
715 let eof_error = || {
716 ReaderError::Io(std::io::Error::new(
717 std::io::ErrorKind::UnexpectedEof,
718 "unexpected eof",
719 ))
720 };
721
722 while tc_head[time_id] != 0 {
724 let signal_id = (tc_head[time_id] - 1) as usize; let mut mu_slice = &mu.as_slice()[head_pointer[signal_id] as usize..];
726 let (vli, skiplen) = read_variant_u32(&mut mu_slice)?;
727 let signal_len = self.meta.signals[signal_id].len();
728 let signal_handle = FstSignalHandle::from_index(signal_id);
729 let len = match signal_len {
730 1 => {
731 let value = one_bit_signal_value_to_char(vli);
732 let value_buf = [value];
733 (self.callback)(*time, signal_handle, FstSignalValue::String(&value_buf));
734 0 }
736 0 => {
737 let (len, skiplen2) = read_variant_u32(&mut mu_slice)?;
738 let value = mu_slice.get(..len as usize).ok_or_else(eof_error)?;
739 (self.callback)(*time, signal_handle, FstSignalValue::String(value));
740 len + skiplen2
741 }
742 len => {
743 let signal_len = len as usize;
744 if !self.meta.signals[signal_id].is_real() {
745 let (value, len) = if (vli & 1) == 0 {
746 let read_len = signal_len.div_ceil(8);
748 let bytes = mu_slice.get(..read_len).ok_or_else(eof_error)?;
749 multi_bit_digital_signal_to_chars(bytes, signal_len, &mut buffer);
750 (buffer.as_slice(), read_len as u32)
751 } else {
752 let value = mu_slice.get(..signal_len).ok_or_else(eof_error)?;
753 (value, len)
754 };
755 (self.callback)(*time, signal_handle, FstSignalValue::String(value));
756 len
757 } else {
758 assert_eq!(vli & 1, 1, "TODO: implement support for rare packed case");
759 let value = read_f64(&mut mu_slice, self.meta.float_endian)?;
760 (self.callback)(*time, signal_handle, FstSignalValue::Real(value));
761 8
762 }
763 }
764 };
765
766 let total_skiplen = skiplen + len;
768 head_pointer[signal_id] += total_skiplen;
770 length_remaining[signal_id] -= total_skiplen;
771 tc_head[time_id] = scatter_pointer[signal_id];
773 scatter_pointer[signal_id] = 0;
775
776 if length_remaining[signal_id] > 0 {
778 let tdelta = if signal_len == 1 {
779 read_one_bit_signal_time_delta(&mu, head_pointer[signal_id])?
780 } else {
781 read_multi_bit_signal_time_delta(&mu, head_pointer[signal_id])?
782 };
783
784 scatter_pointer[signal_id] = tc_head[time_id + tdelta];
786 tc_head[time_id + tdelta] = (signal_id + 1) as u32; }
788 }
789 }
790
791 Ok(())
792 }
793
794 fn read(&mut self) -> Result<()> {
795 let sections = self.meta.data_sections.clone();
796 let relevant_sections = sections
798 .iter()
799 .filter(|s| self.filter.end >= s.start_time && s.end_time >= self.filter.start);
800 for (sec_num, section) in relevant_sections.enumerate() {
801 self.input.seek(SeekFrom::Start(section.file_offset))?;
803 let section_length = read_u64(&mut self.input)?;
804
805 let start_time = read_u64(&mut self.input)?;
807 let end_time = read_u64(&mut self.input)?;
808 assert_eq!(start_time, section.start_time);
809 assert_eq!(end_time, section.end_time);
810 let is_first_section = sec_num == 0;
811
812 let (time_section_length, time_table) =
814 read_time_table(&mut self.input, section.file_offset, section_length)?;
815
816 if is_first_section && (time_table.is_empty() || time_table[0] > start_time) {
819 read_frame(
820 &mut self.input,
821 section.file_offset,
822 section_length,
823 &self.meta.signals,
824 &self.filter.signals,
825 self.meta.float_endian,
826 start_time,
827 self.callback,
828 )?;
829 } else {
830 skip_frame(&mut self.input, section.file_offset)?;
831 }
832
833 self.read_value_changes(
834 section.kind,
835 section.file_offset,
836 section_length,
837 time_section_length,
838 &time_table,
839 )?;
840 }
841
842 Ok(())
843 }
844}