1use crate::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct KeyEntry {
7 pub key_namespace: FourCC,
8 pub key_value: String,
9}
10
11#[derive(Debug, Clone, PartialEq, Eq, Default)]
18#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
19pub struct Keys {
20 pub entries: Vec<KeyEntry>,
21}
22
23impl AtomExt for Keys {
24 type Ext = ();
25
26 const KIND_EXT: FourCC = FourCC::new(b"keys");
27
28 fn decode_body_ext<B: Buf>(buf: &mut B, _ext: ()) -> Result<Self> {
29 let entry_count = u32::decode(buf)?;
30 let mut entries = Vec::with_capacity((entry_count as usize).min(4096));
31
32 for _ in 0..entry_count {
33 let header = Header::decode(buf)?;
34 let size = header.size.ok_or(Error::InvalidSize)?;
35
36 entries.push(KeyEntry {
37 key_namespace: header.kind,
38 key_value: decode_utf8_string_with_length(buf, size)?,
39 });
40 }
41
42 Ok(Self { entries })
43 }
44
45 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
46 (self.entries.len() as u32).encode(buf)?;
47
48 for entry in &self.entries {
49 let header = Header {
50 kind: entry.key_namespace,
51 size: Some(entry.key_value.len()),
52 };
53 header.encode(buf)?;
54 entry.key_value.as_bytes().encode(buf)?;
55 }
56
57 Ok(())
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::*;
64
65 #[test]
66 fn test_keys_roundtrip() {
67 let keys = Keys {
68 entries: vec![
69 KeyEntry {
70 key_namespace: FourCC::new(b"mdta"),
71 key_value: "com.apple.quicktime.make".into(),
72 },
73 KeyEntry {
74 key_namespace: FourCC::new(b"mdta"),
75 key_value: "com.apple.quicktime.model".into(),
76 },
77 ],
78 };
79
80 let mut buf = Vec::new();
81 keys.encode(&mut buf).unwrap();
82
83 let decoded = Keys::decode(&mut buf.as_slice()).expect("failed to decode keys");
84 assert_eq!(decoded, keys);
85 }
86
87 #[test]
88 fn test_keys_truncated_entry_does_not_panic() {
89 let mut buf = Vec::new();
90 buf.extend_from_slice(&24u32.to_be_bytes()); buf.extend_from_slice(b"keys");
92 buf.extend_from_slice(&0u32.to_be_bytes()); buf.extend_from_slice(&1u32.to_be_bytes()); buf.extend_from_slice(&108u32.to_be_bytes());
98 buf.extend_from_slice(b"mdta");
99
100 let result = Keys::decode(&mut buf.as_slice());
101 assert!(result.is_err());
102 }
103
104 #[test]
105 fn test_keys_empty() {
106 let keys = Keys::default();
107
108 let mut buf = Vec::new();
109 keys.encode(&mut buf).unwrap();
110
111 let decoded = Keys::decode(&mut buf.as_slice()).expect("failed to decode keys");
112 assert_eq!(decoded, keys);
113 }
114
115 #[test]
118 fn test_keys_truncated_entry() {
119 let mut buf = Vec::new();
120 0u32.encode(&mut buf).unwrap(); 1u32.encode(&mut buf).unwrap(); 100u32.encode(&mut buf).unwrap(); FourCC::new(b"mdta").encode(&mut buf).unwrap();
124 buf.extend_from_slice(b"short");
125
126 let err = Keys::decode_body(&mut buf.as_slice()).unwrap_err();
127 assert!(matches!(err, Error::OutOfBounds));
128 }
129
130 #[test]
133 fn test_keys_malformed_count() {
134 let mut buf = Vec::new();
135 0u32.encode(&mut buf).unwrap(); u32::MAX.encode(&mut buf).unwrap(); FourCC::new(b"mdta").encode(&mut buf).unwrap(); let err = Keys::decode_body(&mut buf.as_slice()).unwrap_err();
140 assert!(matches!(err, Error::OutOfBounds));
141 }
142}