oxidize_pdf/objects/
dictionary.rs1use crate::objects::Object;
2use std::collections::HashMap;
3
4#[derive(Debug, Clone, PartialEq)]
5pub struct Dictionary {
6 entries: HashMap<String, Object>,
7}
8
9impl Dictionary {
10 pub fn new() -> Self {
11 Self {
12 entries: HashMap::new(),
13 }
14 }
15
16 pub fn with_capacity(capacity: usize) -> Self {
17 Self {
18 entries: HashMap::with_capacity(capacity),
19 }
20 }
21
22 pub fn set(&mut self, key: impl Into<String>, value: impl Into<Object>) {
23 self.entries.insert(key.into(), value.into());
24 }
25
26 pub fn get(&self, key: &str) -> Option<&Object> {
27 self.entries.get(key)
28 }
29
30 pub fn get_mut(&mut self, key: &str) -> Option<&mut Object> {
31 self.entries.get_mut(key)
32 }
33
34 pub fn remove(&mut self, key: &str) -> Option<Object> {
35 self.entries.remove(key)
36 }
37
38 pub fn contains_key(&self, key: &str) -> bool {
39 self.entries.contains_key(key)
40 }
41
42 pub fn len(&self) -> usize {
43 self.entries.len()
44 }
45
46 pub fn is_empty(&self) -> bool {
47 self.entries.is_empty()
48 }
49
50 pub fn clear(&mut self) {
51 self.entries.clear();
52 }
53
54 pub fn keys(&self) -> impl Iterator<Item = &String> {
55 self.entries.keys()
56 }
57
58 pub fn values(&self) -> impl Iterator<Item = &Object> {
59 self.entries.values()
60 }
61
62 pub fn entries(&self) -> impl Iterator<Item = (&String, &Object)> {
63 self.entries.iter()
64 }
65
66 pub fn entries_mut(&mut self) -> impl Iterator<Item = (&String, &mut Object)> {
67 self.entries.iter_mut()
68 }
69
70 pub fn iter(&self) -> impl Iterator<Item = (&String, &Object)> {
71 self.entries.iter()
72 }
73
74 pub fn get_dict(&self, key: &str) -> Option<&Dictionary> {
75 self.get(key).and_then(|obj| {
76 if let Object::Dictionary(dict) = obj {
77 Some(dict)
78 } else {
79 None
80 }
81 })
82 }
83}
84
85impl Default for Dictionary {
86 fn default() -> Self {
87 Self::new()
88 }
89}
90
91impl FromIterator<(String, Object)> for Dictionary {
92 fn from_iter<T: IntoIterator<Item = (String, Object)>>(iter: T) -> Self {
93 let mut dict = Dictionary::new();
94 for (key, value) in iter {
95 dict.set(key, value);
96 }
97 dict
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104
105 #[test]
106 fn test_new_dictionary() {
107 let dict = Dictionary::new();
108 assert!(dict.is_empty());
109 assert_eq!(dict.len(), 0);
110 }
111
112 #[test]
113 fn test_with_capacity() {
114 let dict = Dictionary::with_capacity(10);
115 assert!(dict.is_empty());
116 assert_eq!(dict.len(), 0);
117 }
118
119 #[test]
120 fn test_set_and_get() {
121 let mut dict = Dictionary::new();
122 dict.set("Name", "Test");
123 dict.set("Age", 42);
124 dict.set("Active", true);
125
126 assert_eq!(dict.get("Name"), Some(&Object::String("Test".to_string())));
127 assert_eq!(dict.get("Age"), Some(&Object::Integer(42)));
128 assert_eq!(dict.get("Active"), Some(&Object::Boolean(true)));
129 assert_eq!(dict.get("Missing"), None);
130 }
131
132 #[test]
133 fn test_get_mut() {
134 let mut dict = Dictionary::new();
135 dict.set("Counter", 1);
136
137 if let Some(Object::Integer(val)) = dict.get_mut("Counter") {
138 *val = 2;
139 }
140
141 assert_eq!(dict.get("Counter"), Some(&Object::Integer(2)));
142 }
143
144 #[test]
145 fn test_remove() {
146 let mut dict = Dictionary::new();
147 dict.set("Temp", "Value");
148
149 assert!(dict.contains_key("Temp"));
150 let removed = dict.remove("Temp");
151 assert_eq!(removed, Some(Object::String("Value".to_string())));
152 assert!(!dict.contains_key("Temp"));
153 assert_eq!(dict.remove("Temp"), None);
154 }
155
156 #[test]
157 fn test_contains_key() {
158 let mut dict = Dictionary::new();
159 dict.set("Exists", true);
160
161 assert!(dict.contains_key("Exists"));
162 assert!(!dict.contains_key("NotExists"));
163 }
164
165 #[test]
166 fn test_clear() {
167 let mut dict = Dictionary::new();
168 dict.set("A", 1);
169 dict.set("B", 2);
170 dict.set("C", 3);
171
172 assert_eq!(dict.len(), 3);
173 dict.clear();
174 assert_eq!(dict.len(), 0);
175 assert!(dict.is_empty());
176 }
177
178 #[test]
179 fn test_keys() {
180 let mut dict = Dictionary::new();
181 dict.set("First", 1);
182 dict.set("Second", 2);
183 dict.set("Third", 3);
184
185 let mut keys: Vec<_> = dict.keys().collect();
186 keys.sort();
187 assert_eq!(keys, vec!["First", "Second", "Third"]);
188 }
189
190 #[test]
191 fn test_values() {
192 let mut dict = Dictionary::new();
193 dict.set("A", 100);
194 dict.set("B", 200);
195
196 let values: Vec<_> = dict.values().collect();
197 assert!(values.contains(&&Object::Integer(100)));
198 assert!(values.contains(&&Object::Integer(200)));
199 }
200
201 #[test]
202 fn test_entries_and_iter() {
203 let mut dict = Dictionary::new();
204 dict.set("Name", "Test");
205 dict.set("Value", 42);
206
207 let entries: Vec<_> = dict.entries().collect();
208 assert_eq!(entries.len(), 2);
209
210 let iter_entries: Vec<_> = dict.iter().collect();
212 assert_eq!(entries, iter_entries);
213 }
214
215 #[test]
216 fn test_entries_mut() {
217 let mut dict = Dictionary::new();
218 dict.set("X", 10);
219 dict.set("Y", 20);
220
221 for (_, value) in dict.entries_mut() {
222 if let Object::Integer(val) = value {
223 *val *= 2;
224 }
225 }
226
227 assert_eq!(dict.get("X"), Some(&Object::Integer(20)));
228 assert_eq!(dict.get("Y"), Some(&Object::Integer(40)));
229 }
230
231 #[test]
232 fn test_get_dict() {
233 let mut parent = Dictionary::new();
234 let mut child = Dictionary::new();
235 child.set("ChildKey", "ChildValue");
236
237 parent.set("Child", Object::Dictionary(child));
238 parent.set("NotDict", "String");
239
240 let child_dict = parent.get_dict("Child");
242 assert!(child_dict.is_some());
243 assert_eq!(
244 child_dict.unwrap().get("ChildKey"),
245 Some(&Object::String("ChildValue".to_string()))
246 );
247
248 assert!(parent.get_dict("NotDict").is_none());
250
251 assert!(parent.get_dict("Missing").is_none());
253 }
254
255 #[test]
256 fn test_from_iterator() {
257 let items = vec![
258 ("Name".to_string(), Object::String("Test".to_string())),
259 ("Count".to_string(), Object::Integer(5)),
260 ("Enabled".to_string(), Object::Boolean(true)),
261 ];
262
263 let dict: Dictionary = items.into_iter().collect();
264
265 assert_eq!(dict.len(), 3);
266 assert_eq!(dict.get("Name"), Some(&Object::String("Test".to_string())));
267 assert_eq!(dict.get("Count"), Some(&Object::Integer(5)));
268 assert_eq!(dict.get("Enabled"), Some(&Object::Boolean(true)));
269 }
270
271 #[test]
272 fn test_default() {
273 let dict: Dictionary = Default::default();
274 assert!(dict.is_empty());
275 assert_eq!(dict.len(), 0);
276 }
277
278 #[test]
279 fn test_nested_dictionaries() {
280 let mut root = Dictionary::new();
281 let mut level1 = Dictionary::new();
282 let mut level2 = Dictionary::new();
283
284 level2.set("DeepValue", "Found");
285 level1.set("Level2", Object::Dictionary(level2));
286 root.set("Level1", Object::Dictionary(level1));
287
288 let deep_value = root
290 .get_dict("Level1")
291 .and_then(|l1| l1.get_dict("Level2"))
292 .and_then(|l2| l2.get("DeepValue"));
293
294 assert_eq!(deep_value, Some(&Object::String("Found".to_string())));
295 }
296}