1use crate::*;
2
3pub trait UuidAtom: Sized {
4 const EXTENDED_TYPE: ExtendedType;
5
6 fn decode_uuid_body<B: Buf>(buf: &mut B) -> Result<Self>;
7 fn encode_uuid_body<B: BufMut>(&self, buf: &mut B) -> Result<()>;
8}
9
10pub(crate) trait UuidAtomExt: Sized {
11 const EXTENDED_TYPE_EXT: ExtendedType;
12 type Ext: Ext;
13
14 fn decode_uuid_body_ext<B: Buf>(buf: &mut B, ext: Self::Ext) -> Result<Self>;
15 fn encode_uuid_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<Self::Ext>;
16}
17
18impl<T: UuidAtomExt> UuidAtom for T {
19 const EXTENDED_TYPE: ExtendedType = Self::EXTENDED_TYPE_EXT;
20
21 fn decode_uuid_body<B: Buf>(buf: &mut B) -> Result<Self> {
23 let ext = Ext::decode(u32::decode(buf)?)?;
24 UuidAtomExt::decode_uuid_body_ext(buf, ext)
25 }
26
27 fn encode_uuid_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
28 let start = buf.len();
30 0u32.encode(buf)?;
31
32 let ext = self.encode_uuid_body_ext(buf)?;
34
35 let header = ext.encode()?;
37 buf.set_slice(start, &header.to_be_bytes());
38
39 Ok(())
40 }
41}
42
43#[derive(Clone, Eq, PartialEq, Debug)]
46#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
47#[non_exhaustive]
48pub enum Uuid {
49 C2pa(C2pa),
50 Unknown(ExtendedType, Vec<u8>),
51}
52
53impl Atom for Uuid {
54 const KIND: FourCC = FourCC::new(b"uuid");
55
56 fn decode_body<B: Buf>(buf: &mut B) -> Result<Self> {
57 let et = ExtendedType::decode(buf)?;
58
59 match et {
60 C2pa::EXTENDED_TYPE => Ok(Uuid::C2pa(C2pa::decode_uuid_body(buf)?)),
61 _ => {
62 let payload = Vec::<u8>::decode(buf)?;
63 Ok(Uuid::Unknown(et, payload))
64 }
65 }
66 }
67
68 fn encode_body<B: BufMut>(&self, buf: &mut B) -> Result<()> {
69 match self {
70 Uuid::C2pa(c2pa) => {
71 C2pa::EXTENDED_TYPE.encode(buf)?;
72 c2pa.encode_uuid_body(buf)?;
73 }
74 Uuid::Unknown(et, payload) => {
75 et.encode(buf)?;
76 payload.encode(buf)?;
77 }
78 }
79
80 Ok(())
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87
88 #[test]
89 fn test_c2pa_round_trip() -> Result<()> {
90 let original = Uuid::C2pa(C2pa {
91 box_purpose: "urn:uuid:...".to_string(),
92 data: vec![1, 2, 3, 4],
93 });
94
95 let mut buf = Vec::new();
97 original.encode_body(&mut buf)?;
98
99 let mut cursor = &buf[..];
101 let decoded = Uuid::decode_body(&mut cursor)?;
102
103 assert_eq!(original, decoded, "They werent equal");
105 Ok(())
106 }
107
108 #[test]
109 fn test_c2pa_uuid_golden_vector() -> Result<()> {
110 let mut bytes = Vec::new();
111
112 bytes.extend_from_slice(&[
114 0xD8, 0xFE, 0xC3, 0xD6, 0x1B, 0x0E, 0x48, 0x3C, 0x92, 0x97, 0x58, 0x28, 0x87, 0x7E,
115 0xC4, 0x81,
116 ]);
117
118 bytes.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]);
120
121 bytes.extend_from_slice(b"urn:uuid:test\0");
123
124 bytes.extend_from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]);
126
127 let mut cursor = &bytes[..];
128 let decoded = Uuid::decode_body(&mut cursor)?;
129
130 let expected = Uuid::C2pa(C2pa {
131 box_purpose: "urn:uuid:test".to_string(),
132 data: vec![0xDE, 0xAD, 0xBE, 0xEF],
133 });
134
135 assert_eq!(decoded, expected);
136 Ok(())
137 }
138}