use crate::error::ParseError;
pub const VERSION: u32 = 1;
pub const LEN: usize = 12;
const CHAIN_LEN_AT: usize = 2;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Meta {
pub chain_len: u32,
}
impl Meta {
pub fn parse(version: u32, payload: &[u8]) -> Result<Meta, ParseError> {
if version != VERSION {
return Err(ParseError::AssertFail(format!(
"meta section version {version} has no layout derived from a specimen"
)));
}
let chain_len = payload
.get(CHAIN_LEN_AT..CHAIN_LEN_AT + 4)
.ok_or_else(|| {
ParseError::AssertFail(format!(
"meta section is {} bytes, not the {LEN} a chain length needs",
payload.len()
))
})?
.try_into()
.map(u32::from_be_bytes)
.expect("a four-byte slice");
Ok(Meta { chain_len })
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn meta_reads_the_chain_length_it_states() {
let mut raw = [0u8; LEN];
raw[0..2].copy_from_slice(&2u16.to_be_bytes());
raw[CHAIN_LEN_AT..CHAIN_LEN_AT + 4].copy_from_slice(&6140u32.to_be_bytes());
assert_eq!(Meta::parse(VERSION, &raw).unwrap().chain_len, 6140);
}
#[test]
fn a_short_or_unknown_meta_is_refused_rather_than_guessed() {
assert!(Meta::parse(VERSION, &[0; LEN - 8]).is_err());
assert!(Meta::parse(VERSION + 1, &[0; LEN]).is_err());
}
}