use crate::*;
pub trait UuidAtom: Sized {
const EXTENDED_TYPE: ExtendedType;
fn decode_uuid_body<B: Buf>(buf: &mut B) -> Result<Self>;
fn encode_uuid_body<B: BufMut>(&self, buf: &mut B) -> Result<()>;
}
pub(crate) trait UuidAtomExt: Sized {
const EXTENDED_TYPE_EXT: ExtendedType;
type Ext: Ext;
fn decode_uuid_body_ext<B: Buf>(buf: &mut B, ext: Self::Ext) -> Result<Self>;
fn encode_uuid_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<Self::Ext>;
}
impl<T: UuidAtomExt> UuidAtom for T {
const EXTENDED_TYPE: ExtendedType = Self::EXTENDED_TYPE_EXT;
fn decode_uuid_body<B: Buf>(buf: &mut B) -> Result<Self> {
let ext = Ext::decode(u32::decode(buf)?)?;
UuidAtomExt::decode_uuid_body_ext(buf, ext)
}
fn encode_uuid_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
let start = buf.len();
0u32.encode(buf)?;
let ext = self.encode_uuid_body_ext(buf)?;
let header = ext.encode()?;
buf.set_slice(start, &header.to_be_bytes());
Ok(())
}
}
#[derive(Clone, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum Uuid {
C2pa(C2pa),
Unknown(ExtendedType, Vec<u8>),
}
impl Atom for Uuid {
const KIND: FourCC = FourCC::new(b"uuid");
fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
let et = ExtendedType::decode(buf)?;
match et {
C2pa::EXTENDED_TYPE => Ok(Uuid::C2pa(C2pa::decode_uuid_body(buf)?)),
_ => {
let payload = Vec::<u8>::decode(buf)?;
Ok(Uuid::Unknown(et, payload))
}
}
}
fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
match self {
Uuid::C2pa(c2pa) => {
C2pa::EXTENDED_TYPE.encode(buf)?;
c2pa.encode_uuid_body(buf)?;
}
Uuid::Unknown(et, payload) => {
et.encode(buf)?;
payload.encode(buf)?;
}
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_c2pa_round_trip() -> Result<()> {
let original = Uuid::C2pa(C2pa {
box_purpose: "urn:uuid:...".to_string(),
data: vec![1, 2, 3, 4],
});
let mut buf = Vec::new();
original.encode_body(&mut buf)?;
let mut cursor = &buf[..];
let decoded = Uuid::decode_body(&mut cursor)?;
assert_eq!(original, decoded, "They werent equal");
Ok(())
}
#[test]
fn test_c2pa_uuid_golden_vector() -> Result<()> {
let mut bytes = Vec::new();
bytes.extend_from_slice(&[
0xD8, 0xFE, 0xC3, 0xD6, 0x1B, 0x0E, 0x48, 0x3C, 0x92, 0x97, 0x58, 0x28, 0x87, 0x7E,
0xC4, 0x81,
]);
bytes.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
bytes.extend_from_slice(b"urn:uuid:test\0");
bytes.extend_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]);
let mut cursor = &bytes[..];
let decoded = Uuid::decode_body(&mut cursor)?;
let expected = Uuid::C2pa(C2pa {
box_purpose: "urn:uuid:test".to_string(),
data: vec![0xDE, 0xAD, 0xBE, 0xEF],
});
assert_eq!(decoded, expected);
Ok(())
}
}