#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
pub const SERI_RECORD_SIZE: usize = 256;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct SeriRecord {
pub alpha_tilt: f32,
#[cfg_attr(feature = "serde", serde(with = "crate::serde_byte_array"))]
pub raw: [u8; SERI_RECORD_SIZE],
}
impl SeriRecord {
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() < SERI_RECORD_SIZE {
return None;
}
let mut raw = [0u8; SERI_RECORD_SIZE];
raw.copy_from_slice(&bytes[..SERI_RECORD_SIZE]);
let alpha_tilt = f32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]);
Some(Self { raw, alpha_tilt })
}
}
pub fn parse_seri_records(bytes: &[u8]) -> Option<Vec<SeriRecord>> {
if bytes.is_empty() || bytes.len() % SERI_RECORD_SIZE != 0 {
return None;
}
let count = bytes.len() / SERI_RECORD_SIZE;
let mut records = Vec::with_capacity(count);
for i in 0..count {
let start = i * SERI_RECORD_SIZE;
records.push(SeriRecord::from_bytes(
&bytes[start..start + SERI_RECORD_SIZE],
)?);
}
Some(records)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn seri_roundtrip() {
let mut buf = vec![0u8; SERI_RECORD_SIZE];
buf[0..4].copy_from_slice(&(-35.5f32).to_le_bytes());
buf[4] = 99;
let records = super::parse_seri_records(&buf).unwrap();
assert_eq!(records.len(), 1);
assert!((records[0].alpha_tilt - (-35.5)).abs() < 1e-6);
assert_eq!(records[0].raw[4], 99);
}
#[test]
fn seri_empty() {
assert!(super::parse_seri_records(&[]).is_none());
}
}