1use crate::objects::Dictionary;
2use std::fmt;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub struct ObjectId {
6 number: u32,
7 generation: u16,
8}
9
10impl ObjectId {
11 pub fn new(number: u32, generation: u16) -> Self {
12 Self { number, generation }
13 }
14
15 pub fn number(&self) -> u32 {
16 self.number
17 }
18
19 pub fn generation(&self) -> u16 {
20 self.generation
21 }
22}
23
24impl fmt::Display for ObjectId {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 write!(f, "{} {} R", self.number, self.generation)
27 }
28}
29
30#[derive(Debug, Clone, PartialEq)]
31pub enum Object {
32 Null,
33 Boolean(bool),
34 Integer(i64),
35 Real(f64),
36 String(String),
37 Name(String),
38 Array(Vec<Object>),
39 Dictionary(Dictionary),
40 Stream(Dictionary, Vec<u8>),
41 Reference(ObjectId),
42}
43
44impl Object {
45 pub fn is_null(&self) -> bool {
46 matches!(self, Object::Null)
47 }
48
49 pub fn as_bool(&self) -> Option<bool> {
50 match self {
51 Object::Boolean(b) => Some(*b),
52 _ => None,
53 }
54 }
55
56 pub fn as_integer(&self) -> Option<i64> {
57 match self {
58 Object::Integer(i) => Some(*i),
59 _ => None,
60 }
61 }
62
63 pub fn as_real(&self) -> Option<f64> {
64 match self {
65 Object::Real(f) => Some(*f),
66 Object::Integer(i) => Some(*i as f64),
67 _ => None,
68 }
69 }
70
71 pub fn as_string(&self) -> Option<&str> {
72 match self {
73 Object::String(s) => Some(s),
74 _ => None,
75 }
76 }
77
78 pub fn as_name(&self) -> Option<&str> {
79 match self {
80 Object::Name(n) => Some(n),
81 _ => None,
82 }
83 }
84
85 pub fn as_array(&self) -> Option<&Vec<Object>> {
86 match self {
87 Object::Array(arr) => Some(arr),
88 _ => None,
89 }
90 }
91
92 pub fn as_dict(&self) -> Option<&Dictionary> {
93 match self {
94 Object::Dictionary(dict) => Some(dict),
95 _ => None,
96 }
97 }
98}
99
100impl From<bool> for Object {
101 fn from(b: bool) -> Self {
102 Object::Boolean(b)
103 }
104}
105
106impl From<i32> for Object {
107 fn from(i: i32) -> Self {
108 Object::Integer(i as i64)
109 }
110}
111
112impl From<i64> for Object {
113 fn from(i: i64) -> Self {
114 Object::Integer(i)
115 }
116}
117
118impl From<f32> for Object {
119 fn from(f: f32) -> Self {
120 Object::Real(f as f64)
121 }
122}
123
124impl From<f64> for Object {
125 fn from(f: f64) -> Self {
126 Object::Real(f)
127 }
128}
129
130impl From<String> for Object {
131 fn from(s: String) -> Self {
132 Object::String(s)
133 }
134}
135
136impl From<&str> for Object {
137 fn from(s: &str) -> Self {
138 Object::String(s.to_string())
139 }
140}
141
142impl From<Vec<Object>> for Object {
143 fn from(v: Vec<Object>) -> Self {
144 Object::Array(v)
145 }
146}
147
148impl From<Dictionary> for Object {
149 fn from(d: Dictionary) -> Self {
150 Object::Dictionary(d)
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn test_object_id_new() {
160 let id = ObjectId::new(42, 5);
161 assert_eq!(id.number(), 42);
162 assert_eq!(id.generation(), 5);
163 }
164
165 #[test]
166 fn test_object_id_display() {
167 let id = ObjectId::new(10, 0);
168 assert_eq!(format!("{}", id), "10 0 R");
169
170 let id2 = ObjectId::new(999, 65535);
171 assert_eq!(format!("{}", id2), "999 65535 R");
172 }
173
174 #[test]
175 fn test_object_id_equality() {
176 let id1 = ObjectId::new(1, 0);
177 let id2 = ObjectId::new(1, 0);
178 let id3 = ObjectId::new(2, 0);
179 let id4 = ObjectId::new(1, 1);
180
181 assert_eq!(id1, id2);
182 assert_ne!(id1, id3);
183 assert_ne!(id1, id4);
184 }
185
186 #[test]
187 fn test_object_null() {
188 let obj = Object::Null;
189 assert!(obj.is_null());
190 assert!(obj.as_bool().is_none());
191 assert!(obj.as_integer().is_none());
192 assert!(obj.as_real().is_none());
193 assert!(obj.as_string().is_none());
194 assert!(obj.as_name().is_none());
195 assert!(obj.as_array().is_none());
196 assert!(obj.as_dict().is_none());
197 }
198
199 #[test]
200 fn test_object_boolean() {
201 let obj_true = Object::Boolean(true);
202 let obj_false = Object::Boolean(false);
203
204 assert!(!obj_true.is_null());
205 assert_eq!(obj_true.as_bool(), Some(true));
206 assert_eq!(obj_false.as_bool(), Some(false));
207 assert!(obj_true.as_integer().is_none());
208 }
209
210 #[test]
211 fn test_object_integer() {
212 let obj = Object::Integer(42);
213
214 assert_eq!(obj.as_integer(), Some(42));
215 assert_eq!(obj.as_real(), Some(42.0));
216 assert!(obj.as_bool().is_none());
217 assert!(obj.as_string().is_none());
218 }
219
220 #[test]
221 fn test_object_real() {
222 let obj = Object::Real(3.14159);
223
224 assert_eq!(obj.as_real(), Some(3.14159));
225 assert!(obj.as_integer().is_none());
226 assert!(obj.as_bool().is_none());
227 }
228
229 #[test]
230 fn test_object_string() {
231 let obj = Object::String("Hello PDF".to_string());
232
233 assert_eq!(obj.as_string(), Some("Hello PDF"));
234 assert!(obj.as_name().is_none());
235 assert!(obj.as_integer().is_none());
236 }
237
238 #[test]
239 fn test_object_name() {
240 let obj = Object::Name("Type".to_string());
241
242 assert_eq!(obj.as_name(), Some("Type"));
243 assert!(obj.as_string().is_none());
244 assert!(obj.as_integer().is_none());
245 }
246
247 #[test]
248 fn test_object_array() {
249 let arr = vec![
250 Object::Integer(1),
251 Object::Integer(2),
252 Object::Integer(3),
253 ];
254 let obj = Object::Array(arr.clone());
255
256 assert_eq!(obj.as_array(), Some(&arr));
257 assert!(obj.as_dict().is_none());
258 }
259
260 #[test]
261 fn test_object_dictionary() {
262 let mut dict = Dictionary::new();
263 dict.set("Key", "Value");
264 let obj = Object::Dictionary(dict.clone());
265
266 assert_eq!(obj.as_dict(), Some(&dict));
267 assert!(obj.as_array().is_none());
268 }
269
270 #[test]
271 fn test_object_stream() {
272 let mut dict = Dictionary::new();
273 dict.set("Length", 5);
274 let data = vec![1, 2, 3, 4, 5];
275 let obj = Object::Stream(dict, data);
276
277 if let Object::Stream(d, data) = obj {
279 assert_eq!(d.get("Length"), Some(&Object::Integer(5)));
280 assert_eq!(data.len(), 5);
281 } else {
282 panic!("Expected Stream object");
283 }
284 }
285
286 #[test]
287 fn test_object_reference() {
288 let id = ObjectId::new(10, 0);
289 let obj = Object::Reference(id);
290
291 if let Object::Reference(ref_id) = obj {
293 assert_eq!(ref_id, id);
294 } else {
295 panic!("Expected Reference object");
296 }
297 }
298
299 #[test]
300 fn test_from_bool() {
301 let obj: Object = true.into();
302 assert_eq!(obj, Object::Boolean(true));
303
304 let obj2: Object = false.into();
305 assert_eq!(obj2, Object::Boolean(false));
306 }
307
308 #[test]
309 fn test_from_integers() {
310 let obj: Object = 42i32.into();
311 assert_eq!(obj, Object::Integer(42));
312
313 let obj2: Object = 9999i64.into();
314 assert_eq!(obj2, Object::Integer(9999));
315
316 let obj3: Object = (-100i32).into();
317 assert_eq!(obj3, Object::Integer(-100));
318 }
319
320 #[test]
321 fn test_from_floats() {
322 let obj: Object = 3.14f32.into();
323 if let Object::Real(val) = obj {
324 assert!((val - 3.14).abs() < 0.001);
325 } else {
326 panic!("Expected Real object");
327 }
328
329 let obj2: Object = 2.71828f64.into();
330 assert_eq!(obj2, Object::Real(2.71828));
331 }
332
333 #[test]
334 fn test_from_strings() {
335 let obj: Object = "Hello".into();
336 assert_eq!(obj, Object::String("Hello".to_string()));
337
338 let obj2: Object = String::from("World").into();
339 assert_eq!(obj2, Object::String("World".to_string()));
340 }
341
342 #[test]
343 fn test_from_vec() {
344 let vec = vec![Object::Integer(1), Object::Integer(2)];
345 let obj: Object = vec.clone().into();
346 assert_eq!(obj, Object::Array(vec));
347 }
348
349 #[test]
350 fn test_from_dictionary() {
351 let mut dict = Dictionary::new();
352 dict.set("Test", 123);
353 let obj: Object = dict.clone().into();
354
355 if let Object::Dictionary(d) = obj {
356 assert_eq!(d.get("Test"), Some(&Object::Integer(123)));
357 } else {
358 panic!("Expected Dictionary object");
359 }
360 }
361
362 #[test]
363 fn test_object_equality() {
364 assert_eq!(Object::Null, Object::Null);
365 assert_eq!(Object::Boolean(true), Object::Boolean(true));
366 assert_ne!(Object::Boolean(true), Object::Boolean(false));
367 assert_eq!(Object::Integer(42), Object::Integer(42));
368 assert_ne!(Object::Integer(42), Object::Integer(43));
369 assert_eq!(Object::String("A".to_string()), Object::String("A".to_string()));
370 assert_ne!(Object::String("A".to_string()), Object::String("B".to_string()));
371 }
372}