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