1use crate::{FileFormat, Hierarchy, LoadOptions, Result, SignalSource, TimeTable, WellenError};
9use std::io::{BufRead, Seek};
10
11impl From<crate::ghw::GhwParseError> for WellenError {
12 fn from(value: crate::ghw::GhwParseError) -> Self {
13 WellenError::FailedToLoad(FileFormat::Ghw, value.to_string())
14 }
15}
16
17impl From<crate::vcd::VcdParseError> for WellenError {
18 fn from(value: crate::vcd::VcdParseError) -> Self {
19 WellenError::FailedToLoad(FileFormat::Vcd, value.to_string())
20 }
21}
22
23impl From<fst_reader::ReaderError> for WellenError {
24 fn from(value: fst_reader::ReaderError) -> Self {
25 WellenError::FailedToLoad(FileFormat::Fst, value.to_string())
26 }
27}
28
29pub struct HeaderResult<R: BufRead + Seek> {
30 pub hierarchy: Hierarchy,
31 pub file_format: FileFormat,
32 pub body_len: u64,
34 pub body: ReadBodyContinuation<R>,
35}
36
37pub fn read_header_from_file<P: AsRef<std::path::Path>>(
38 filename: P,
39 options: &LoadOptions,
40) -> Result<HeaderResult<std::io::BufReader<std::fs::File>>> {
41 let file_format = open_and_detect_file_format(filename.as_ref());
42 match file_format {
43 FileFormat::Unknown => Err(WellenError::UnknownFileFormat),
44 FileFormat::Vcd => {
45 let (hierarchy, body, body_len) = crate::vcd::read_header_from_file(filename, options)?;
46 let body = ReadBodyContinuation(ReadBodyData::Vcd(Box::new(body)));
47 Ok(HeaderResult {
48 hierarchy,
49 file_format,
50 body_len,
51 body,
52 })
53 }
54 FileFormat::Ghw => {
55 let input = std::io::BufReader::new(std::fs::File::open(filename)?);
56 let (hierarchy, body, body_len) = crate::ghw::read_header(input, options)?;
57 let body = ReadBodyContinuation(ReadBodyData::Ghw(Box::new(body)));
58 Ok(HeaderResult {
59 hierarchy,
60 file_format,
61 body_len,
62 body,
63 })
64 }
65 FileFormat::Fst => {
66 let (hierarchy, body) = crate::fst::read_header_from_file(filename, options)?;
67 let body = ReadBodyContinuation(ReadBodyData::Fst(Box::new(body)));
68 Ok(HeaderResult {
69 hierarchy,
70 file_format,
71 body_len: 0, body,
73 })
74 }
75 }
76}
77
78pub fn read_header<R: BufRead + Seek>(
79 mut input: R,
80 options: &LoadOptions,
81) -> Result<HeaderResult<R>> {
82 let file_format = detect_file_format(&mut input);
83 match file_format {
84 FileFormat::Unknown => Err(WellenError::UnknownFileFormat),
85 FileFormat::Vcd => {
86 let (hierarchy, body, body_len) = crate::vcd::read_header(input, options)?;
87 let body = ReadBodyContinuation(ReadBodyData::Vcd(Box::new(body)));
88 Ok(HeaderResult {
89 hierarchy,
90 file_format,
91 body_len,
92 body,
93 })
94 }
95 FileFormat::Ghw => {
96 let (hierarchy, body, body_len) = crate::ghw::read_header(input, options)?;
97 let body = ReadBodyContinuation(ReadBodyData::Ghw(Box::new(body)));
98 Ok(HeaderResult {
99 hierarchy,
100 file_format,
101 body_len,
102 body,
103 })
104 }
105 FileFormat::Fst => {
106 let (hierarchy, body) = crate::fst::read_header(input, options)?;
107 let body = ReadBodyContinuation(ReadBodyData::Fst(Box::new(body)));
108 Ok(HeaderResult {
109 hierarchy,
110 file_format,
111 body_len: 0, body,
113 })
114 }
115 }
116}
117
118pub struct ReadBodyContinuation<R: BufRead + Seek>(ReadBodyData<R>);
119
120pub(crate) enum ReadBodyData<R: BufRead + Seek> {
121 Vcd(Box<crate::vcd::ReadBodyContinuation<R>>),
122 Fst(Box<crate::fst::ReadBodyContinuation<R>>),
123 Ghw(Box<crate::ghw::ReadBodyContinuation<R>>),
124}
125
126pub struct BodyResult {
127 pub source: SignalSource,
128 pub time_table: TimeTable,
129}
130
131pub type ProgressCount = std::sync::Arc<std::sync::atomic::AtomicU64>;
132
133pub fn read_body<R: BufRead + Seek + Sync + Send + 'static>(
134 body: ReadBodyContinuation<R>,
135 hierarchy: &Hierarchy,
136 progress: Option<ProgressCount>,
137) -> Result<BodyResult> {
138 match body.0 {
139 ReadBodyData::Vcd(data) => {
140 let (source, time_table) = crate::vcd::read_body(*data, hierarchy, progress)?;
141 Ok(BodyResult { source, time_table })
142 }
143 ReadBodyData::Fst(data) => {
144 let (source, time_table) = crate::fst::read_body(*data)?;
146 Ok(BodyResult { source, time_table })
147 }
148 ReadBodyData::Ghw(data) => {
149 let (source, time_table) = crate::ghw::read_body(*data, hierarchy, progress)?;
150 Ok(BodyResult { source, time_table })
151 }
152 }
153}
154
155pub fn open_and_detect_file_format<P: AsRef<std::path::Path>>(filename: P) -> FileFormat {
157 let input_file = std::fs::File::open(filename).expect("failed to open input file!");
158 let mut reader = std::io::BufReader::new(input_file);
159 detect_file_format(&mut reader)
160}
161
162pub fn detect_file_format(input: &mut (impl BufRead + Seek)) -> FileFormat {
164 if crate::vcd::is_vcd(input) {
165 FileFormat::Vcd
166 } else if fst_reader::is_fst_file(input) {
167 FileFormat::Fst
168 } else if crate::ghw::is_ghw(input) {
169 FileFormat::Ghw
170 } else {
171 FileFormat::Unknown
172 }
173}