use crate::*;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ChplEntry {
pub start: u64,
pub title: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Chpl {
pub entries: Vec<ChplEntry>,
}
impl Atom for Chpl {
const KIND: FourCC = FourCC::new(b"chpl");
fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
let version = u8::decode(buf)?;
<[u8; 3]>::decode(buf)?; if version != 0 {
<[u8; 4]>::decode(buf)?; }
let count = u8::decode(buf)?;
let mut entries = Vec::with_capacity(count as usize);
for _ in 0..count {
let start = u64::decode(buf)?;
let title = decode_length_prefixed_utf8_string::<u8>(buf)?;
entries.push(ChplEntry { start, title });
}
Ok(Self { entries })
}
fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
1u8.encode(buf)?; [0u8; 3].encode(buf)?; [0u8; 4].encode(buf)?;
let count: u8 = self
.entries
.len()
.try_into()
.map_err(|_| Error::TooLarge(Self::KIND))?;
count.encode(buf)?;
for entry in &self.entries {
entry.start.encode(buf)?;
encode_length_prefixed_string::<u8>(buf, &entry.title, Self::KIND)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_chpl_roundtrip() {
let expected = Chpl {
entries: vec![
ChplEntry {
start: 0,
title: "Intro".into(),
},
ChplEntry {
start: 30_000_000,
title: "Chapter 2".into(),
},
],
};
let mut buf = Vec::new();
expected.encode(&mut buf).unwrap();
let decoded = Chpl::decode(&mut buf.as_slice()).expect("failed to decode chpl");
assert_eq!(decoded, expected);
}
#[test]
fn test_chpl_empty() {
let expected = Chpl { entries: vec![] };
let mut buf = Vec::new();
expected.encode(&mut buf).unwrap();
let decoded = Chpl::decode(&mut buf.as_slice()).expect("failed to decode chpl");
assert_eq!(decoded, expected);
}
#[test]
fn test_chpl_version0_no_reserved_field() {
let expected = Chpl {
entries: vec![
ChplEntry {
start: 0,
title: "Intro".into(),
},
ChplEntry {
start: 30_000_000,
title: "Chapter 2".into(),
},
],
};
let mut buf = Vec::new();
0u8.encode(&mut buf).unwrap(); [0u8; 3].encode(&mut buf).unwrap(); let count: u8 = expected.entries.len().try_into().unwrap();
count.encode(&mut buf).unwrap();
for entry in &expected.entries {
entry.start.encode(&mut buf).unwrap();
let title_bytes = entry.title.as_bytes();
let title_len: u8 = title_bytes.len().try_into().unwrap();
title_len.encode(&mut buf).unwrap();
buf.extend_from_slice(title_bytes);
}
let decoded = Chpl::decode_body(&mut buf.as_slice()).expect("failed to decode chpl");
assert_eq!(decoded, expected);
}
}