1use std::convert::TryFrom;
2use std::io::{Read, Seek};
3
4use crate::error::{Error, Result};
5use crate::types::BlockType;
6use crate::util::{read_cstring, read_f64_be, read_u64_be, validate_endian};
7
8pub const VERSION_FIELD_LEN: usize = 128;
10pub const DATE_FIELD_LEN: usize = 119;
12
13#[derive(Debug, Clone)]
15pub struct Header {
16 pub section_length: u64,
18 pub start_time: u64,
20 pub end_time: u64,
22 pub memory_used: u64,
24 pub scope_count: u64,
26 pub var_count: u64,
28 pub max_handle: u64,
30 pub vc_section_count: u64,
32 pub timescale_exponent: i8,
34 pub version: String,
36 pub date: String,
38 pub file_type: u8,
40 pub time_zero: u64,
42}
43
44impl Default for Header {
45 fn default() -> Self {
46 Self {
47 section_length: 329,
48 start_time: 0,
49 end_time: 0,
50 memory_used: 0,
51 scope_count: 0,
52 var_count: 0,
53 max_handle: 0,
54 vc_section_count: 0,
55 timescale_exponent: -9,
56 version: String::from("fst-format"),
57 date: String::from(""),
58 file_type: 0,
59 time_zero: 0,
60 }
61 }
62}
63
64impl Header {
65 pub fn read<R: Read + Seek>(reader: &mut R) -> Result<Self> {
67 let mut block_type = [0u8; 1];
68 reader.read_exact(&mut block_type)?;
69 let block_type = BlockType::try_from(block_type[0]).map_err(|_| {
70 Error::invalid(format!("unexpected first block type {:02x}", block_type[0]))
71 })?;
72
73 if block_type != BlockType::Header {
74 return Err(Error::invalid(format!(
75 "expected header block (0), found {block_type:?}"
76 )));
77 }
78
79 let section_length = read_u64_be(reader)?;
80 let start_time = read_u64_be(reader)?;
81 let end_time = read_u64_be(reader)?;
82 let endian_test = read_f64_be(reader)?;
83 validate_endian(endian_test)?;
84 let memory_used = read_u64_be(reader)?;
85 let scope_count = read_u64_be(reader)?;
86 let var_count = read_u64_be(reader)?;
87 let max_handle = read_u64_be(reader)?;
88 let vc_section_count = read_u64_be(reader)?;
89
90 let mut timescale_buf = [0u8; 1];
91 reader.read_exact(&mut timescale_buf)?;
92 let timescale_exponent = timescale_buf[0] as i8;
93
94 let version = read_cstring(reader, VERSION_FIELD_LEN)?;
95 let date = read_cstring(reader, DATE_FIELD_LEN)?;
96
97 let mut file_type_buf = [0u8; 1];
98 reader.read_exact(&mut file_type_buf)?;
99 let file_type = file_type_buf[0];
100 let time_zero = read_u64_be(reader)?;
101
102 Ok(Self {
103 section_length,
104 start_time,
105 end_time,
106 memory_used,
107 scope_count,
108 var_count,
109 max_handle,
110 vc_section_count,
111 timescale_exponent,
112 version,
113 date,
114 file_type,
115 time_zero,
116 })
117 }
118
119 pub fn timescale_factor(&self) -> f64 {
121 10f64.powi(self.timescale_exponent as i32)
122 }
123}