From 2fa96778027d7dc8ae30cef0d6dac5e4e51ad683 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kevin=20L=C3=A4ufer?= Date: Thu, 31 Oct 2024 12:07:42 -0400 Subject: [PATCH] expose reading functionality for arbitrary input types --- pywellen/src/lib.rs | 2 +- wellen/examples/load_signals.rs | 3 +- wellen/src/fst.rs | 63 ++++++++--------------------- wellen/src/ghw/mod.rs | 62 ++++++++--------------------- wellen/src/signals.rs | 4 +- wellen/src/simple.rs | 2 +- wellen/src/vcd.rs | 55 ++++++++++++++------------ wellen/src/viewers.rs | 70 +++++++++++++++------------------ 8 files changed, 100 insertions(+), 161 deletions(-) diff --git a/pywellen/src/lib.rs b/pywellen/src/lib.rs index 27d5743..d923138 100644 --- a/pywellen/src/lib.rs +++ b/pywellen/src/lib.rs @@ -199,7 +199,7 @@ impl Waveform { multi_thread: multi_threaded, remove_scopes_with_empty_name, }; - let header_result = viewers::read_header(path.as_str(), &opts).toerr()?; + let header_result = viewers::read_header_from_file(path.as_str(), &opts).toerr()?; let hier = Hierarchy(Arc::new(header_result.hierarchy)); let body = viewers::read_body(header_result.body, &hier.0, None) diff --git a/wellen/examples/load_signals.rs b/wellen/examples/load_signals.rs index 814fbb3..799f6eb 100644 --- a/wellen/examples/load_signals.rs +++ b/wellen/examples/load_signals.rs @@ -72,7 +72,8 @@ fn main() { // load header let header_start = std::time::Instant::now(); - let header = viewers::read_header(&args.filename, &LOAD_OPTS).expect("Failed to load file!"); + let header = + viewers::read_header_from_file(&args.filename, &LOAD_OPTS).expect("Failed to load file!"); let header_load_duration = header_start.elapsed(); println!( "It took {:?} to load the header of {}", diff --git a/wellen/src/fst.rs b/wellen/src/fst.rs index e7e61f2..b40127c 100644 --- a/wellen/src/fst.rs +++ b/wellen/src/fst.rs @@ -15,58 +15,27 @@ use std::io::{BufRead, Seek}; pub type Result = std::result::Result; -pub fn read_header>( - filename: P, +pub fn read_header( + input: R, _options: &LoadOptions, -) -> Result<(Hierarchy, ReadBodyContinuation)> { - let input = std::fs::File::open(filename)?; - let mut reader = FstReader::open_and_read_time_table(std::io::BufReader::new(input))?; +) -> Result<(Hierarchy, ReadBodyContinuation)> { + let mut reader = FstReader::open_and_read_time_table(input)?; let hierarchy = read_hierarchy(&mut reader)?; - let cont = ReadBodyContinuation { - reader: Reader::File(reader), - }; - Ok((hierarchy, cont)) -} - -pub fn read_header_from_bytes( - bytes: Vec, - _options: &LoadOptions, -) -> Result<(Hierarchy, ReadBodyContinuation)> { - let mut reader = FstReader::open_and_read_time_table(std::io::Cursor::new(bytes))?; - let hierarchy = read_hierarchy(&mut reader)?; - let cont = ReadBodyContinuation { - reader: Reader::Bytes(reader), - }; + let cont = ReadBodyContinuation(reader); Ok((hierarchy, cont)) } - -pub fn read_body(data: ReadBodyContinuation) -> Result<(SignalSource, TimeTable)> { - match data.reader { - Reader::File(reader) => { - let time_table = reader.get_time_table().unwrap().to_vec(); - Ok(( - SignalSource::new(Box::new(FstWaveDatabase::new(reader))), - time_table, - )) - } - Reader::Bytes(reader) => { - let time_table = reader.get_time_table().unwrap().to_vec(); - Ok(( - SignalSource::new(Box::new(FstWaveDatabase::new(reader))), - time_table, - )) - } - } +pub fn read_body( + data: ReadBodyContinuation, +) -> Result<(SignalSource, TimeTable)> { + let time_table = data.0.get_time_table().unwrap().to_vec(); + let reader = data.0; + let db = FstWaveDatabase::new(reader); + let boxed_db = Box::new(db); + let source = SignalSource::new(boxed_db); + Ok((source, time_table)) } -pub struct ReadBodyContinuation { - reader: Reader, -} - -enum Reader { - File(FstReader>), - Bytes(FstReader>>), -} +pub struct ReadBodyContinuation(FstReader); struct FstWaveDatabase { reader: FstReader, @@ -78,7 +47,7 @@ impl FstWaveDatabase { } } -impl SignalSourceImplementation for FstWaveDatabase { +impl SignalSourceImplementation for FstWaveDatabase { fn load_signals( &mut self, ids: &[SignalRef], diff --git a/wellen/src/ghw/mod.rs b/wellen/src/ghw/mod.rs index c6b44b5..28bcbc5 100644 --- a/wellen/src/ghw/mod.rs +++ b/wellen/src/ghw/mod.rs @@ -24,68 +24,38 @@ pub fn is_ghw(input: &mut (impl BufRead + Seek)) -> bool { pub type Result = std::result::Result; -pub fn read_header>( - filename: P, +pub fn read_header( + mut input: R, options: &LoadOptions, -) -> Result<(Hierarchy, ReadBodyContinuation, u64)> { - let f = std::fs::File::open(filename)?; - let mut input = std::io::BufReader::new(f); +) -> Result<(Hierarchy, ReadBodyContinuation, u64)> { let (hierarchy, header, decode_info, body_len) = read_header_internal(&mut input, options)?; let cont = ReadBodyContinuation { header, decode_info, - input: Input::File(input), + input, }; Ok((hierarchy, cont, body_len)) } -pub fn read_header_from_bytes( - bytes: Vec, - options: &LoadOptions, -) -> Result<(Hierarchy, ReadBodyContinuation, u64)> { - let mut input = std::io::Cursor::new(bytes); - let (hierarchy, header, decode_info, body_len) = read_header_internal(&mut input, options)?; - let cont = ReadBodyContinuation { - header, - decode_info, - input: Input::Bytes(input), - }; - Ok((hierarchy, cont, body_len)) -} - -pub fn read_body( - data: ReadBodyContinuation, +pub fn read_body( + data: ReadBodyContinuation, hierarchy: &Hierarchy, progress: Option, ) -> Result<(SignalSource, TimeTable)> { - let (source, time_table) = match data.input { - Input::Bytes(mut input) => match progress { - Some(p) => { - let mut wrapped = ProgressTracker::new(input, p); - signals::read_signals(&data.header, data.decode_info, hierarchy, &mut wrapped)? - } - None => signals::read_signals(&data.header, data.decode_info, hierarchy, &mut input)?, - }, - Input::File(mut input) => match progress { - Some(p) => { - let mut wrapped = ProgressTracker::new(input, p); - signals::read_signals(&data.header, data.decode_info, hierarchy, &mut wrapped)? - } - None => signals::read_signals(&data.header, data.decode_info, hierarchy, &mut input)?, - }, - }; - Ok((source, time_table)) + let mut input = data.input; + match progress { + Some(p) => { + let mut wrapped = ProgressTracker::new(input, p); + signals::read_signals(&data.header, data.decode_info, hierarchy, &mut wrapped) + } + None => signals::read_signals(&data.header, data.decode_info, hierarchy, &mut input), + } } -pub struct ReadBodyContinuation { +pub struct ReadBodyContinuation { header: HeaderData, decode_info: GhwDecodeInfo, - input: Input, -} - -enum Input { - Bytes(std::io::Cursor>), - File(std::io::BufReader), + input: R, } fn read_header_internal( diff --git a/wellen/src/signals.rs b/wellen/src/signals.rs index fd6486a..c3cf7ae 100644 --- a/wellen/src/signals.rs +++ b/wellen/src/signals.rs @@ -620,7 +620,7 @@ impl SignalChangeData { } } -pub trait SignalSourceImplementation { +pub trait SignalSourceImplementation: Sync + Send { /// Loads new signals. /// Many implementations take advantage of loading multiple signals at a time. fn load_signals( @@ -634,7 +634,7 @@ pub trait SignalSourceImplementation { } pub struct SignalSource { - inner: Box, + inner: Box, } impl SignalSource { diff --git a/wellen/src/simple.rs b/wellen/src/simple.rs index 4c41338..c396544 100644 --- a/wellen/src/simple.rs +++ b/wellen/src/simple.rs @@ -21,7 +21,7 @@ pub fn read_with_options>( filename: P, options: &LoadOptions, ) -> Result { - let header = viewers::read_header(filename, options)?; + let header = viewers::read_header_from_file(filename, options)?; let body = viewers::read_body(header.body, &header.hierarchy, None)?; Ok(Waveform::new( header.hierarchy, diff --git a/wellen/src/vcd.rs b/wellen/src/vcd.rs index ccef54a..f0a1d8a 100644 --- a/wellen/src/vcd.rs +++ b/wellen/src/vcd.rs @@ -54,10 +54,14 @@ pub enum VcdParseError { pub type Result = std::result::Result; -pub fn read_header>( +pub fn read_header_from_file>( filename: P, options: &LoadOptions, -) -> Result<(Hierarchy, ReadBodyContinuation, u64)> { +) -> Result<( + Hierarchy, + ReadBodyContinuation>, + u64, +)> { let input_file = std::fs::File::open(filename)?; let mmap = unsafe { memmap2::Mmap::map(&input_file)? }; let (header_len, hierarchy, lookup) = @@ -67,59 +71,60 @@ pub fn read_header>( multi_thread: options.multi_thread, header_len, lookup, - input: Input::File(mmap), + input: Input::Mmap(mmap), }; Ok((hierarchy, cont, body_len)) } -pub fn read_header_from_bytes( - bytes: Vec, +pub fn read_header( + mut input: R, options: &LoadOptions, -) -> Result<(Hierarchy, ReadBodyContinuation, u64)> { - let (header_len, hierarchy, lookup) = - read_hierarchy(&mut std::io::Cursor::new(&bytes), options)?; - let body_len = (bytes.len() - header_len) as u64; +) -> Result<(Hierarchy, ReadBodyContinuation, u64)> { + // determine the length of the input + let start = input.stream_position()?; + input.seek(SeekFrom::End(0))?; + let end = input.stream_position()?; + input.seek(SeekFrom::Start(start))?; + let input_len = end - start; + + // actually read the header + let (header_len, hierarchy, lookup) = read_hierarchy(&mut input, options)?; + let body_len = input_len - header_len as u64; let cont = ReadBodyContinuation { multi_thread: options.multi_thread, header_len, lookup, - input: Input::Bytes(bytes), + input: Input::Reader(input), }; Ok((hierarchy, cont, body_len)) } -pub struct ReadBodyContinuation { +pub struct ReadBodyContinuation { multi_thread: bool, header_len: usize, lookup: IdLookup, - input: Input, + input: Input, } -enum Input { - Bytes(Vec), - File(memmap2::Mmap), +enum Input { + Reader(R), + Mmap(memmap2::Mmap), } -pub fn read_body( - data: ReadBodyContinuation, +pub fn read_body( + data: ReadBodyContinuation, hierarchy: &Hierarchy, progress: Option, ) -> Result<(SignalSource, TimeTable)> { let (source, time_table) = match data.input { - Input::Bytes(mmap) => read_values( + Input::Reader(input) => todo!("parse VCD from reader"), + Input::Mmap(mmap) => read_values( &mmap[data.header_len..], data.multi_thread, hierarchy, &data.lookup, progress, )?, - Input::File(bytes) => read_values( - &bytes[data.header_len..], - data.multi_thread, - hierarchy, - &data.lookup, - progress, - )?, }; Ok((source, time_table)) } diff --git a/wellen/src/viewers.rs b/wellen/src/viewers.rs index 8987129..eab034e 100644 --- a/wellen/src/viewers.rs +++ b/wellen/src/viewers.rs @@ -25,24 +25,24 @@ impl From for WellenError { } } -pub struct HeaderResult { +pub struct HeaderResult { pub hierarchy: Hierarchy, pub file_format: FileFormat, /// Body length in bytes. pub body_len: u64, - pub body: ReadBodyContinuation, + pub body: ReadBodyContinuation, } -pub fn read_header>( +pub fn read_header_from_file>( filename: P, options: &LoadOptions, -) -> Result { +) -> Result>> { let file_format = open_and_detect_file_format(filename.as_ref()); match file_format { FileFormat::Unknown => Err(WellenError::UnknownFileFormat), FileFormat::Vcd => { - let (hierarchy, body, body_len) = crate::vcd::read_header(filename, options)?; - let body = ReadBodyContinuation::new(ReadBodyData::Vcd(body)); + let (hierarchy, body, body_len) = crate::vcd::read_header_from_file(filename, options)?; + let body = ReadBodyContinuation(ReadBodyData::Vcd(body)); Ok(HeaderResult { hierarchy, file_format, @@ -51,8 +51,9 @@ pub fn read_header>( }) } FileFormat::Ghw => { - let (hierarchy, body, body_len) = crate::ghw::read_header(filename, options)?; - let body = ReadBodyContinuation::new(ReadBodyData::Ghw(body)); + let input = std::io::BufReader::new(std::fs::File::open(filename)?); + let (hierarchy, body, body_len) = crate::ghw::read_header(input, options)?; + let body = ReadBodyContinuation(ReadBodyData::Ghw(body)); Ok(HeaderResult { hierarchy, file_format, @@ -61,8 +62,9 @@ pub fn read_header>( }) } FileFormat::Fst => { - let (hierarchy, body) = crate::fst::read_header(filename, options)?; - let body = ReadBodyContinuation::new(ReadBodyData::Fst(body)); + let input = std::io::BufReader::new(std::fs::File::open(filename)?); + let (hierarchy, body) = crate::fst::read_header(input, options)?; + let body = ReadBodyContinuation(ReadBodyData::Fst(body)); Ok(HeaderResult { hierarchy, file_format, @@ -73,16 +75,16 @@ pub fn read_header>( } } -pub fn read_header_from_bytes(bytes: Vec, options: &LoadOptions) -> Result { - let file_format = { - let mut cursor = &mut std::io::Cursor::new(&bytes); - detect_file_format(&mut cursor) - }; +pub fn read_header( + mut input: R, + options: &LoadOptions, +) -> Result> { + let file_format = detect_file_format(&mut input); match file_format { FileFormat::Unknown => Err(WellenError::UnknownFileFormat), FileFormat::Vcd => { - let (hierarchy, body, body_len) = crate::vcd::read_header_from_bytes(bytes, options)?; - let body = ReadBodyContinuation::new(ReadBodyData::Vcd(body)); + let (hierarchy, body, body_len) = crate::vcd::read_header(input, options)?; + let body = ReadBodyContinuation(ReadBodyData::Vcd(body)); Ok(HeaderResult { hierarchy, file_format, @@ -91,8 +93,8 @@ pub fn read_header_from_bytes(bytes: Vec, options: &LoadOptions) -> Result { - let (hierarchy, body, body_len) = crate::ghw::read_header_from_bytes(bytes, options)?; - let body = ReadBodyContinuation::new(ReadBodyData::Ghw(body)); + let (hierarchy, body, body_len) = crate::ghw::read_header(input, options)?; + let body = ReadBodyContinuation(ReadBodyData::Ghw(body)); Ok(HeaderResult { hierarchy, file_format, @@ -101,8 +103,8 @@ pub fn read_header_from_bytes(bytes: Vec, options: &LoadOptions) -> Result { - let (hierarchy, body) = crate::fst::read_header_from_bytes(bytes, options)?; - let body = ReadBodyContinuation::new(ReadBodyData::Fst(body)); + let (hierarchy, body) = crate::fst::read_header(input, options)?; + let body = ReadBodyContinuation(ReadBodyData::Fst(body)); Ok(HeaderResult { hierarchy, file_format, @@ -113,20 +115,12 @@ pub fn read_header_from_bytes(bytes: Vec, options: &LoadOptions) -> Result Self { - Self { data } - } -} +pub struct ReadBodyContinuation(ReadBodyData); -enum ReadBodyData { - Vcd(crate::vcd::ReadBodyContinuation), - Fst(crate::fst::ReadBodyContinuation), - Ghw(crate::ghw::ReadBodyContinuation), +enum ReadBodyData { + Vcd(crate::vcd::ReadBodyContinuation), + Fst(crate::fst::ReadBodyContinuation), + Ghw(crate::ghw::ReadBodyContinuation), } pub struct BodyResult { @@ -136,18 +130,18 @@ pub struct BodyResult { pub type ProgressCount = std::sync::Arc; -pub fn read_body( - body: ReadBodyContinuation, +pub fn read_body( + body: ReadBodyContinuation, hierarchy: &Hierarchy, progress: Option, ) -> Result { - match body.data { + match body.0 { ReadBodyData::Vcd(data) => { let (source, time_table) = crate::vcd::read_body(data, hierarchy, progress)?; Ok(BodyResult { source, time_table }) } ReadBodyData::Fst(data) => { - // fst does not support a progress count since it is no actually reading the body + // fst does not support a progress count since it is not actually reading the body let (source, time_table) = crate::fst::read_body(data)?; Ok(BodyResult { source, time_table }) }