#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
pub const MRCO_RECORD_SIZE: usize = 80;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq)]
pub struct MrcoRecord {
#[cfg_attr(feature = "serde", serde(with = "crate::serde_byte_array"))]
pub raw: [u8; MRCO_RECORD_SIZE],
}
impl MrcoRecord {
pub fn from_bytes(bytes: &[u8]) -> Option<Self> {
if bytes.len() < MRCO_RECORD_SIZE {
return None;
}
let mut raw = [0u8; MRCO_RECORD_SIZE];
raw.copy_from_slice(&bytes[..MRCO_RECORD_SIZE]);
Some(Self { raw })
}
}
pub fn parse_mrco_records(bytes: &[u8]) -> Option<Vec<MrcoRecord>> {
if bytes.is_empty() || bytes.len() % MRCO_RECORD_SIZE != 0 {
return None;
}
let count = bytes.len() / MRCO_RECORD_SIZE;
let mut records = Vec::with_capacity(count);
for i in 0..count {
let start = i * MRCO_RECORD_SIZE;
records.push(MrcoRecord::from_bytes(
&bytes[start..start + MRCO_RECORD_SIZE],
)?);
}
Some(records)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mrco_roundtrip() {
let buf = vec![42u8; MRCO_RECORD_SIZE];
let records = super::parse_mrco_records(&buf).unwrap();
assert_eq!(records.len(), 1);
assert_eq!(records[0].raw[0], 42);
}
#[test]
fn mrco_empty() {
assert!(super::parse_mrco_records(&[]).is_none());
}
}