Skip to main content

oxidize_pdf/objects/
dictionary.rs

1use 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        // Test that iter() works the same way
211        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        // Should return Some for dictionary objects
241        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        // Should return None for non-dictionary objects
249        assert!(parent.get_dict("NotDict").is_none());
250
251        // Should return None for missing keys
252        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        // Navigate through nested dictionaries
289        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}