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 if size > buf.remaining() {
36 return Err(Error::OutOfBounds);
37 }
38
39 let key_value = String::from_utf8(buf.slice(size).to_vec())
40 .map_err(|err| Error::InvalidString(err.to_string()))?;
41 buf.advance(size);
42
43 entries.push(KeyEntry {
44 key_namespace: header.kind,
45 key_value,
46 });
47 }
48
49 Ok(Self { entries })
50 }
51
52 fn encode_body_ext<B: BufMut>(&self, buf: &mut B) -> Result<()> {
53 (self.entries.len() as u32).encode(buf)?;
54
55 for entry in &self.entries {
56 let header = Header {
57 kind: entry.key_namespace,
58 size: Some(entry.key_value.len()),
59 };
60 header.encode(buf)?;
61 entry.key_value.as_bytes().encode(buf)?;
62 }
63
64 Ok(())
65 }
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71
72 #[test]
73 fn test_keys_roundtrip() {
74 let keys = Keys {
75 entries: vec![
76 KeyEntry {
77 key_namespace: FourCC::new(b"mdta"),
78 key_value: "com.apple.quicktime.make".into(),
79 },
80 KeyEntry {
81 key_namespace: FourCC::new(b"mdta"),
82 key_value: "com.apple.quicktime.model".into(),
83 },
84 ],
85 };
86
87 let mut buf = Vec::new();
88 keys.encode(&mut buf).unwrap();
89
90 let decoded = Keys::decode(&mut buf.as_slice()).expect("failed to decode keys");
91 assert_eq!(decoded, keys);
92 }
93
94 #[test]
95 fn test_keys_truncated_entry_does_not_panic() {
96 let mut buf = Vec::new();
97 buf.extend_from_slice(&24u32.to_be_bytes()); buf.extend_from_slice(b"keys");
99 buf.extend_from_slice(&0u32.to_be_bytes()); buf.extend_from_slice(&1u32.to_be_bytes()); buf.extend_from_slice(&108u32.to_be_bytes());
105 buf.extend_from_slice(b"mdta");
106
107 let result = Keys::decode(&mut buf.as_slice());
108 assert!(result.is_err());
109 }
110
111 #[test]
112 fn test_keys_empty() {
113 let keys = Keys::default();
114
115 let mut buf = Vec::new();
116 keys.encode(&mut buf).unwrap();
117
118 let decoded = Keys::decode(&mut buf.as_slice()).expect("failed to decode keys");
119 assert_eq!(decoded, keys);
120 }
121
122 #[test]
125 fn test_keys_truncated_entry() {
126 let mut buf = Vec::new();
127 0u32.encode(&mut buf).unwrap(); 1u32.encode(&mut buf).unwrap(); 100u32.encode(&mut buf).unwrap(); FourCC::new(b"mdta").encode(&mut buf).unwrap();
131 buf.extend_from_slice(b"short");
132
133 let err = Keys::decode_body(&mut buf.as_slice()).unwrap_err();
134 assert!(matches!(err, Error::OutOfBounds));
135 }
136
137 #[test]
140 fn test_keys_malformed_count() {
141 let mut buf = Vec::new();
142 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();
147 assert!(matches!(err, Error::OutOfBounds));
148 }
149}