Skip to content

Commit

Permalink
make it possible to read from anything that implements Read + Seek
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiwi committed Nov 2, 2024
1 parent 245214a commit 3965035
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 205 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ members = ["wellen", "pywellen"]
default-members = ["wellen"]

[workspace.package]
version = "0.12.2"
version = "0.13.0"
edition = "2021"
# we require the `div_ceil` method on integers
rust-version = "1.73.0"
Expand Down
2 changes: 1 addition & 1 deletion pywellen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
3 changes: 2 additions & 1 deletion wellen/examples/load_signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}",
Expand Down
63 changes: 16 additions & 47 deletions wellen/src/fst.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,58 +15,27 @@ use std::io::{BufRead, Seek};

pub type Result<T> = std::result::Result<T, WellenError>;

pub fn read_header<P: AsRef<std::path::Path>>(
filename: P,
pub fn read_header<R: BufRead + Seek>(
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<R>)> {
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<u8>,
_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<R: BufRead + Seek + Sync + Send + 'static>(
data: ReadBodyContinuation<R>,
) -> 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<std::io::BufReader<std::fs::File>>),
Bytes(FstReader<std::io::Cursor<Vec<u8>>>),
}
pub struct ReadBodyContinuation<R: BufRead + Seek>(FstReader<R>);

struct FstWaveDatabase<R: BufRead + Seek> {
reader: FstReader<R>,
Expand All @@ -78,7 +47,7 @@ impl<R: BufRead + Seek> FstWaveDatabase<R> {
}
}

impl<R: BufRead + Seek> SignalSourceImplementation for FstWaveDatabase<R> {
impl<R: BufRead + Seek + Sync + Send> SignalSourceImplementation for FstWaveDatabase<R> {
fn load_signals(
&mut self,
ids: &[SignalRef],
Expand Down
62 changes: 16 additions & 46 deletions wellen/src/ghw/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,68 +24,38 @@ pub fn is_ghw(input: &mut (impl BufRead + Seek)) -> bool {

pub type Result<T> = std::result::Result<T, GhwParseError>;

pub fn read_header<P: AsRef<std::path::Path>>(
filename: P,
pub fn read_header<R: BufRead + Seek>(
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<R>, 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<u8>,
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<R: BufRead + Seek>(
data: ReadBodyContinuation<R>,
hierarchy: &Hierarchy,
progress: Option<ProgressCount>,
) -> 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<R: BufRead + Seek> {
header: HeaderData,
decode_info: GhwDecodeInfo,
input: Input,
}

enum Input {
Bytes(std::io::Cursor<Vec<u8>>),
File(std::io::BufReader<std::fs::File>),
input: R,
}

fn read_header_internal(
Expand Down
4 changes: 2 additions & 2 deletions wellen/src/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -634,7 +634,7 @@ pub trait SignalSourceImplementation {
}

pub struct SignalSource {
inner: Box<dyn SignalSourceImplementation + Send + Sync>,
inner: Box<dyn SignalSourceImplementation>,
}

impl SignalSource {
Expand Down
15 changes: 14 additions & 1 deletion wellen/src/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::{
};
use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
use std::io::{BufRead, Seek};

/// Read a waveform file with the default options. Reads in header and body at once.
pub fn read<P: AsRef<std::path::Path>>(filename: P) -> Result<Waveform> {
Expand All @@ -21,7 +22,19 @@ pub fn read_with_options<P: AsRef<std::path::Path>>(
filename: P,
options: &LoadOptions,
) -> Result<Waveform> {
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,
body.source,
body.time_table,
))
}

/// Read from something that is not a file.
pub fn read_from_reader<R: BufRead + Seek + Send + Sync + 'static>(input: R) -> Result<Waveform> {
let options = LoadOptions::default();
let header = viewers::read_header(input, &options)?;
let body = viewers::read_body(header.body, &header.hierarchy, None)?;
Ok(Waveform::new(
header.hierarchy,
Expand Down
Loading

0 comments on commit 3965035

Please sign in to comment.