use crate::consts::TRAILER_MAGIC;
use crate::error::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Trailer {
pub partition_table_offset: u64,
pub chain_flags: u8,
}
impl Trailer {
pub fn to_bytes(&self) -> [u8; 20] {
let mut b = [0u8; 20];
b[0..8].copy_from_slice(&self.partition_table_offset.to_le_bytes());
b[8] = self.chain_flags;
b[12..20].copy_from_slice(&TRAILER_MAGIC);
b
}
pub fn from_bytes(b: &[u8; 20]) -> Result<Self, Error> {
if b[12..20] != TRAILER_MAGIC {
return Err(Error::BadTrailer);
}
let mut o = [0u8; 8];
o.copy_from_slice(&b[0..8]);
Ok(Trailer {
partition_table_offset: u64::from_le_bytes(o),
chain_flags: b[8],
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::consts::{CHAIN_BACKWARD, CHAIN_FORWARD};
#[test]
fn trailer_roundtrip_forward() {
let t = Trailer {
partition_table_offset: 0x1234_5678,
chain_flags: CHAIN_FORWARD,
};
let b = t.to_bytes();
assert_eq!(&b[9..12], &[0, 0, 0]);
assert_eq!(&b[12..20], &TRAILER_MAGIC);
assert_eq!(Trailer::from_bytes(&b).unwrap(), t);
}
#[test]
fn trailer_roundtrip_backward() {
let t = Trailer {
partition_table_offset: 0,
chain_flags: CHAIN_BACKWARD,
};
assert_eq!(Trailer::from_bytes(&t.to_bytes()).unwrap(), t);
}
#[test]
fn rejects_bad_magic() {
let mut b = Trailer {
partition_table_offset: 20,
chain_flags: CHAIN_FORWARD,
}
.to_bytes();
b[19] = 0x00;
assert!(matches!(Trailer::from_bytes(&b), Err(Error::BadTrailer)));
}
}