use std::io::{Read, Seek, SeekFrom};
use std::vec::Vec;
extern crate alloc;
use super::compressed::read_compressed;
use super::headers::parse_headers;
use super::interleaved::read_interleaved;
use super::markers::parse_markers_and_journal;
use crate::domain::Datafile;
use crate::error::{BiopacError, ParseResult, Warning};
pub fn read_stream<R: Read + Seek>(mut reader: R) -> Result<ParseResult<Datafile>, BiopacError> {
let headers = parse_headers(&mut reader)?;
let display_orders: Vec<u16> = headers
.channel_metadata
.iter()
.map(|m| m.display_order)
.collect();
let file_revision = headers.graph_metadata.file_revision.0;
let compressed = headers.graph_metadata.compressed;
let mut extra_warnings: Vec<Warning> = Vec::new();
let (channels, markers, journal) = if compressed {
let mj = parse_markers_and_journal(&mut reader, file_revision, &display_orders);
let (markers, journal) = match mj {
Ok(r) => {
extra_warnings.extend(r.warnings);
(r.markers, r.journal)
}
Err(e) => {
extra_warnings.push(Warning::new(alloc::format!(
"Marker/journal section unreadable: {e}"
)));
(Vec::new(), None)
}
};
let (channels, ch_warnings) = read_compressed(&mut reader, &headers)?;
extra_warnings.extend(ch_warnings);
(channels, markers, journal)
} else {
let (channels, ch_warnings) = read_interleaved(&mut reader, &headers)?;
extra_warnings.extend(ch_warnings);
if let Some(data_bytes) = headers.uncompressed_data_byte_count() {
let marker_start = headers.data_start_offset.saturating_add(data_bytes);
reader
.seek(SeekFrom::Start(marker_start))
.map_err(BiopacError::Io)?;
}
let mj = parse_markers_and_journal(&mut reader, file_revision, &display_orders);
let (markers, journal) = match mj {
Ok(r) => {
extra_warnings.extend(r.warnings);
(r.markers, r.journal)
}
Err(e) => {
extra_warnings.push(Warning::new(alloc::format!(
"Marker/journal section unreadable: {e}"
)));
(Vec::new(), None)
}
};
(channels, markers, journal)
};
let metadata = headers.graph_metadata;
let mut warnings = headers.warnings;
warnings.extend(extra_warnings);
let datafile = Datafile {
metadata,
channels,
markers,
journal,
};
Ok(ParseResult {
value: datafile,
warnings,
})
}
#[cfg(feature = "std")]
pub fn read_file(path: impl AsRef<std::path::Path>) -> Result<ParseResult<Datafile>, BiopacError> {
let file = std::fs::File::open(path)?;
let reader = std::io::BufReader::new(file);
read_stream(reader)
}
#[cfg(feature = "std")]
pub fn read_bytes(bytes: &[u8]) -> Result<ParseResult<Datafile>, BiopacError> {
read_stream(std::io::Cursor::new(bytes))
}