diff --git a/Cargo.toml b/Cargo.toml index 982f6a3..806836c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,10 +15,15 @@ repository = "https://github.com/quartiq/stabilizer-streaming" clap = { version = "4.3", features = ["derive"] } num_enum = "0.7" log = "0.4" -eframe = { version = "0.27", default-features = false, features = ["wayland", "x11", "glow", "default_fonts"] } +eframe = { version = "0.27", default-features = false, features = [ + "wayland", + "x11", + "glow", + "default_fonts", +] } egui_plot = "0.27" env_logger = "0.11" -bytemuck = "1.13.1" +bytemuck = { version = "1.13.1", features = ["extern_crate_std"] } thiserror = "1.0.47" anyhow = "1.0.75" socket2 = "0.5.4" diff --git a/src/de/data.rs b/src/de/data.rs index 32a5075..6cf0f91 100644 --- a/src/de/data.rs +++ b/src/de/data.rs @@ -1,12 +1,14 @@ use super::Error; +use core::fmt::Debug; -pub trait Payload<'a> { +pub trait Payload<'a>: Debug { fn new(batches: usize, data: &'a [u8]) -> Result where Self: Sized; fn traces(&self) -> Result)>, Error>; } +#[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct AdcDac<'a> { data: &'a [[[[u8; 2]; 8]; 4]], } @@ -20,8 +22,7 @@ impl<'a> Payload<'a> for AdcDac<'a> { fn new(batches: usize, data: &'a [u8]) -> Result { const CHANNELS: usize = 4; const BATCH_SIZE: usize = 8; - let data: &[[[[u8; 2]; BATCH_SIZE]; CHANNELS]] = - bytemuck::try_cast_slice(data).map_err(Error::PayloadSize)?; + let data: &[[[[u8; 2]; BATCH_SIZE]; CHANNELS]] = bytemuck::try_cast_slice(data)?; assert_eq!(data.len(), batches); Ok(Self { data }) } @@ -82,14 +83,14 @@ impl<'a> Payload<'a> for AdcDac<'a> { } } +#[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct Fls<'a> { data: &'a [[[[u8; 4]; 7]; 2]], } impl<'a> Payload<'a> for Fls<'a> { fn new(batches: usize, data: &'a [u8]) -> Result { - let data: &[[[[u8; 4]; 7]; 2]] = - bytemuck::try_cast_slice(data).map_err(Error::PayloadSize)?; + let data: &[[[[u8; 4]; 7]; 2]] = bytemuck::try_cast_slice(data)?; // demod_re, demod_im, phase[2], ftw, pow_amp, pll assert_eq!(batches, data.len()); Ok(Self { data }) @@ -140,14 +141,14 @@ impl<'a> Payload<'a> for Fls<'a> { } } +#[derive(Clone, Debug, PartialEq, PartialOrd)] pub struct ThermostatEem<'a> { data: &'a [[[u8; 4]; 16 + 4]], } impl<'a> Payload<'a> for ThermostatEem<'a> { fn new(batches: usize, data: &'a [u8]) -> Result { - let data: &[[[u8; 4]; 16 + 4]] = - bytemuck::try_cast_slice(data).map_err(Error::PayloadSize)?; + let data: &[[[u8; 4]; 16 + 4]] = bytemuck::try_cast_slice(data)?; assert_eq!(batches, data.len()); Ok(Self { data }) } diff --git a/src/de/frame.rs b/src/de/frame.rs index 5e04ebc..1090210 100644 --- a/src/de/frame.rs +++ b/src/de/frame.rs @@ -1,15 +1,13 @@ use super::data::{self, Payload}; use super::{Error, Format}; -use std::convert::TryFrom; - // The magic word at the start of each stream frame. const MAGIC_WORD: [u8; 2] = [0x7b, 0x05]; // The size of the frame header in bytes. const HEADER_SIZE: usize = 8; -#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)] pub struct Header { // The format code associated with the stream binary data. pub format: Format, @@ -40,10 +38,10 @@ impl Header { } /// A single stream frame contains multiple batches of data. -// #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Debug)] pub struct Frame<'a> { pub header: Header, - pub data: &'a [u8], + pub payload: Box + 'a>, } impl<'a> Frame<'a> { @@ -51,15 +49,12 @@ impl<'a> Frame<'a> { pub fn from_bytes(input: &'a [u8]) -> Result { let header = Header::parse(&input[..HEADER_SIZE].try_into().unwrap())?; let data = &input[HEADER_SIZE..]; - Ok(Self { header, data }) - } - - pub fn traces(&self) -> Result)>, Error> { - let batches = self.header.batches as _; - Ok(match self.header.format { - Format::AdcDac => data::AdcDac::new(batches, self.data)?.traces()?, - Format::Fls => data::Fls::new(batches, self.data)?.traces()?, - Format::ThermostatEem => data::ThermostatEem::new(batches, self.data)?.traces()?, - }) + let batches = header.batches as _; + let payload: Box = match header.format { + Format::AdcDac => Box::new(data::AdcDac::new(batches, data)?), + Format::Fls => Box::new(data::Fls::new(batches, data)?), + Format::ThermostatEem => Box::new(data::ThermostatEem::new(batches, data)?), + }; + Ok(Self { header, payload }) } } diff --git a/src/de/mod.rs b/src/de/mod.rs index 04c2cb3..ce716d4 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -22,5 +22,5 @@ pub enum Error { #[error("Unknown format ID")] UnknownFormat, #[error("Payload size")] - PayloadSize(bytemuck::PodCastError), + PayloadSize(#[from] bytemuck::PodCastError), } diff --git a/src/source.rs b/src/source.rs index 0ed74d7..1525fa6 100644 --- a/src/source.rs +++ b/src/source.rs @@ -136,7 +136,7 @@ impl Source { Ok(()) => { let frame = Frame::from_bytes(&buf[..self.opts.frame_size])?; self.loss.update(&frame); - break frame.traces()?; + break frame.payload.traces()?; } Err(e) if e.kind() == ErrorKind::UnexpectedEof && self.opts.repeat => { fil.seek(std::io::SeekFrom::Start(0))?; @@ -163,7 +163,7 @@ impl Source { let len = socket.recv(unsafe { core::mem::transmute(&mut buf[..]) })?; // meh let frame = Frame::from_bytes(&buf[..len])?; self.loss.update(&frame); - frame.traces()? + frame.payload.traces()? } }) }