Skip to content

Commit

Permalink
expose reading functionality for arbitrary input types
Browse files Browse the repository at this point in the history
  • Loading branch information
ekiwi committed Oct 31, 2024
1 parent 04b308c commit 2fa9677
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 161 deletions.
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
2 changes: 1 addition & 1 deletion wellen/src/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ 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,
Expand Down
55 changes: 30 additions & 25 deletions wellen/src/vcd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ pub enum VcdParseError {

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

pub fn read_header<P: AsRef<std::path::Path>>(
pub fn read_header_from_file<P: AsRef<std::path::Path>>(
filename: P,
options: &LoadOptions,
) -> Result<(Hierarchy, ReadBodyContinuation, u64)> {
) -> Result<(
Hierarchy,
ReadBodyContinuation<std::io::BufReader<std::fs::File>>,
u64,
)> {
let input_file = std::fs::File::open(filename)?;
let mmap = unsafe { memmap2::Mmap::map(&input_file)? };
let (header_len, hierarchy, lookup) =
Expand All @@ -67,59 +71,60 @@ pub fn read_header<P: AsRef<std::path::Path>>(
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<u8>,
pub fn read_header<R: BufRead + Seek>(
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<R>, 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<R: BufRead + Seek> {
multi_thread: bool,
header_len: usize,
lookup: IdLookup,
input: Input,
input: Input<R>,
}

enum Input {
Bytes(Vec<u8>),
File(memmap2::Mmap),
enum Input<R: BufRead + Seek> {
Reader(R),
Mmap(memmap2::Mmap),
}

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(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))
}
Expand Down
Loading

0 comments on commit 2fa9677

Please sign in to comment.