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![Object::Integer(1), Object::Integer(2), Object::Integer(3)];
250 let obj = Object::Array(arr.clone());
251
252 assert_eq!(obj.as_array(), Some(&arr));
253 assert!(obj.as_dict().is_none());
254 }
255
256 #[test]
257 fn test_object_dictionary() {
258 let mut dict = Dictionary::new();
259 dict.set("Key", "Value");
260 let obj = Object::Dictionary(dict.clone());
261
262 assert_eq!(obj.as_dict(), Some(&dict));
263 assert!(obj.as_array().is_none());
264 }
265
266 #[test]
267 fn test_object_stream() {
268 let mut dict = Dictionary::new();
269 dict.set("Length", 5);
270 let data = vec![1, 2, 3, 4, 5];
271 let obj = Object::Stream(dict, data);
272
273 if let Object::Stream(d, data) = obj {
275 assert_eq!(d.get("Length"), Some(&Object::Integer(5)));
276 assert_eq!(data.len(), 5);
277 } else {
278 panic!("Expected Stream object");
279 }
280 }
281
282 #[test]
283 fn test_object_reference() {
284 let id = ObjectId::new(10, 0);
285 let obj = Object::Reference(id);
286
287 if let Object::Reference(ref_id) = obj {
289 assert_eq!(ref_id, id);
290 } else {
291 panic!("Expected Reference object");
292 }
293 }
294
295 #[test]
296 fn test_from_bool() {
297 let obj: Object = true.into();
298 assert_eq!(obj, Object::Boolean(true));
299
300 let obj2: Object = false.into();
301 assert_eq!(obj2, Object::Boolean(false));
302 }
303
304 #[test]
305 fn test_from_integers() {
306 let obj: Object = 42i32.into();
307 assert_eq!(obj, Object::Integer(42));
308
309 let obj2: Object = 9999i64.into();
310 assert_eq!(obj2, Object::Integer(9999));
311
312 let obj3: Object = (-100i32).into();
313 assert_eq!(obj3, Object::Integer(-100));
314 }
315
316 #[test]
317 fn test_from_floats() {
318 let obj: Object = std::f32::consts::PI.into();
319 if let Object::Real(val) = obj {
320 assert!((val - std::f64::consts::PI).abs() < 0.001);
321 } else {
322 panic!("Expected Real object");
323 }
324
325 let obj2: Object = 2.71828f64.into();
326 assert_eq!(obj2, Object::Real(2.71828));
327 }
328
329 #[test]
330 fn test_from_strings() {
331 let obj: Object = "Hello".into();
332 assert_eq!(obj, Object::String("Hello".to_string()));
333
334 let obj2: Object = String::from("World").into();
335 assert_eq!(obj2, Object::String("World".to_string()));
336 }
337
338 #[test]
339 fn test_from_vec() {
340 let vec = vec![Object::Integer(1), Object::Integer(2)];
341 let obj: Object = vec.clone().into();
342 assert_eq!(obj, Object::Array(vec));
343 }
344
345 #[test]
346 fn test_from_dictionary() {
347 let mut dict = Dictionary::new();
348 dict.set("Test", 123);
349 let obj: Object = dict.clone().into();
350
351 if let Object::Dictionary(d) = obj {
352 assert_eq!(d.get("Test"), Some(&Object::Integer(123)));
353 } else {
354 panic!("Expected Dictionary object");
355 }
356 }
357
358 #[test]
359 fn test_object_equality() {
360 assert_eq!(Object::Null, Object::Null);
361 assert_eq!(Object::Boolean(true), Object::Boolean(true));
362 assert_ne!(Object::Boolean(true), Object::Boolean(false));
363 assert_eq!(Object::Integer(42), Object::Integer(42));
364 assert_ne!(Object::Integer(42), Object::Integer(43));
365 assert_eq!(
366 Object::String("A".to_string()),
367 Object::String("A".to_string())
368 );
369 assert_ne!(
370 Object::String("A".to_string()),
371 Object::String("B".to_string())
372 );
373 }
374}