use crate::error::{Error, Result};
pub const ANC_STREAM_TYPE: u8 = 0x06;
pub const ANC_DATA_DESCRIPTOR_TAG: u8 = 0xC4;
pub const VANC_FORMAT_IDENTIFIER: u32 = 0x5641_4E43;
pub const VANC_FORMAT_IDENTIFIER_BYTES: [u8; 4] = *b"VANC";
const HEADER_LEN: usize = 2;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct AncDataDescriptor<'a> {
#[cfg_attr(feature = "serde", serde(borrow, with = "serde_bytes_compat"))]
pub inner_descriptors: &'a [u8],
}
#[cfg(feature = "serde")]
mod serde_bytes_compat {
pub fn serialize<S: serde::Serializer>(b: &[u8], s: S) -> Result<S::Ok, S::Error> {
s.serialize_bytes(b)
}
}
impl<'a> AncDataDescriptor<'a> {
pub fn parse(b: &'a [u8]) -> Result<Self> {
if b.len() < HEADER_LEN {
return Err(Error::BufferTooShort {
need: HEADER_LEN,
have: b.len(),
what: "anc_data_descriptor header",
});
}
if b[0] != ANC_DATA_DESCRIPTOR_TAG {
return Err(Error::BadDescriptorTag(b[0]));
}
let len = usize::from(b[1]);
let end = HEADER_LEN + len;
if b.len() < end {
return Err(Error::BufferTooShort {
need: end,
have: b.len(),
what: "anc_data_descriptor body",
});
}
Ok(Self {
inner_descriptors: &b[HEADER_LEN..end],
})
}
#[must_use]
pub fn serialized_len(&self) -> usize {
HEADER_LEN + self.inner_descriptors.len()
}
pub fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
let len = self.serialized_len();
if buf.len() < len {
return Err(Error::BufferTooShort {
need: len,
have: buf.len(),
what: "anc_data_descriptor serialize output",
});
}
if self.inner_descriptors.len() > 0xFF {
return Err(Error::FieldTooWide {
what: "descriptor_length",
value: self.inner_descriptors.len() as u32,
bits: 8,
});
}
buf[0] = ANC_DATA_DESCRIPTOR_TAG;
buf[1] = self.inner_descriptors.len() as u8;
buf[HEADER_LEN..len].copy_from_slice(self.inner_descriptors);
Ok(len)
}
}
#[cfg(test)]
mod tests {
use super::*;
extern crate alloc;
use alloc::vec;
#[test]
fn vanc_identifier_is_ascii() {
assert_eq!(VANC_FORMAT_IDENTIFIER.to_be_bytes(), *b"VANC");
assert_eq!(VANC_FORMAT_IDENTIFIER_BYTES, *b"VANC");
}
#[test]
fn round_trip_empty_body() {
let b = [ANC_DATA_DESCRIPTOR_TAG, 0x00];
let d = AncDataDescriptor::parse(&b).unwrap();
assert!(d.inner_descriptors.is_empty());
let mut out = vec![0u8; d.serialized_len()];
d.serialize_into(&mut out).unwrap();
assert_eq!(out, b);
}
#[test]
fn round_trip_with_body() {
let b = [ANC_DATA_DESCRIPTOR_TAG, 0x03, 0xAA, 0xBB, 0xCC];
let d = AncDataDescriptor::parse(&b).unwrap();
assert_eq!(d.inner_descriptors, &[0xAA, 0xBB, 0xCC]);
let mut out = vec![0u8; d.serialized_len()];
d.serialize_into(&mut out).unwrap();
assert_eq!(out, b);
}
#[test]
fn rejects_bad_tag() {
let b = [0xC5, 0x00];
assert!(matches!(
AncDataDescriptor::parse(&b),
Err(Error::BadDescriptorTag(0xC5))
));
}
#[test]
fn rejects_truncated_body() {
let b = [ANC_DATA_DESCRIPTOR_TAG, 0x05, 0x01];
assert!(matches!(
AncDataDescriptor::parse(&b),
Err(Error::BufferTooShort { .. })
));
}
}