use crate::format::{FormatError, FormatResult};
const MTIME_VERSION: u8 = 1;
pub const MTIME_MESSAGE_SIZE: usize = 8;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ModificationTime(pub u32);
impl ModificationTime {
pub fn encode(self) -> Vec<u8> {
let mut buf = Vec::with_capacity(MTIME_MESSAGE_SIZE);
buf.push(MTIME_VERSION);
buf.extend_from_slice(&[0, 0, 0]);
buf.extend_from_slice(&self.0.to_le_bytes());
buf
}
pub fn decode(buf: &[u8]) -> FormatResult<Self> {
if buf.len() < MTIME_MESSAGE_SIZE {
return Err(FormatError::BufferTooShort {
needed: MTIME_MESSAGE_SIZE,
available: buf.len(),
});
}
if buf[0] != MTIME_VERSION {
return Err(FormatError::InvalidVersion(buf[0]));
}
Ok(Self(u32::from_le_bytes([buf[4], buf[5], buf[6], buf[7]])))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn round_trips_through_the_eight_bytes_upstream_writes() {
let encoded = ModificationTime(0x5F00_1234).encode();
assert_eq!(encoded.len(), MTIME_MESSAGE_SIZE);
assert_eq!(&encoded[..4], &[1, 0, 0, 0], "version then three reserved");
assert_eq!(ModificationTime::decode(&encoded).unwrap().0, 0x5F00_1234);
}
#[test]
fn a_foreign_version_is_refused() {
let mut encoded = ModificationTime(1).encode();
encoded[0] = 2;
assert!(ModificationTime::decode(&encoded).is_err());
}
#[test]
fn a_short_body_is_refused() {
assert!(ModificationTime::decode(&[1, 0, 0, 0, 0]).is_err());
}
}