Skip to main content

pdf_lib_rs/core/objects/
pdf_ref.rs

1use std::fmt;
2use crate::utils::copy_string_into_buffer;
3use super::pdf_object::PdfObjectTrait;
4
5/// A PDF indirect reference (e.g., "5 0 R").
6#[derive(Clone, PartialEq, Eq, Hash)]
7pub struct PdfRef {
8    pub object_number: u32,
9    pub generation_number: u16,
10    tag: String,
11}
12
13impl PdfRef {
14    pub fn of(object_number: u32, generation_number: u16) -> Self {
15        let tag = format!("{} {} R", object_number, generation_number);
16        PdfRef {
17            object_number,
18            generation_number,
19            tag,
20        }
21    }
22
23    /// Shorthand for generation 0 ref.
24    pub fn of_num(object_number: u32) -> Self {
25        Self::of(object_number, 0)
26    }
27
28    pub fn tag(&self) -> &str {
29        &self.tag
30    }
31}
32
33impl fmt::Display for PdfRef {
34    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35        write!(f, "{}", self.tag)
36    }
37}
38
39impl fmt::Debug for PdfRef {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        write!(f, "PdfRef({})", self.tag)
42    }
43}
44
45impl PdfObjectTrait for PdfRef {
46    fn size_in_bytes(&self) -> usize {
47        self.tag.len()
48    }
49
50    fn copy_bytes_into(&self, buffer: &mut [u8], offset: usize) -> usize {
51        copy_string_into_buffer(&self.tag, buffer, offset)
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58    use crate::utils::typed_array_for;
59
60    #[test]
61    fn can_be_constructed() {
62        let _ = PdfRef::of(0, 0);
63        let _ = PdfRef::of(0, 21);
64        let _ = PdfRef::of(94, 0);
65        let _ = PdfRef::of(4678, 9120);
66    }
67
68    #[test]
69    fn returns_same_value_for_same_numbers() {
70        assert_eq!(PdfRef::of(0, 0), PdfRef::of(0, 0));
71        assert_eq!(PdfRef::of(0, 21), PdfRef::of(0, 21));
72        assert_eq!(PdfRef::of(94, 0), PdfRef::of(94, 0));
73        assert_eq!(PdfRef::of(4678, 9120), PdfRef::of(4678, 9120));
74    }
75
76    #[test]
77    fn can_be_converted_to_string() {
78        assert_eq!(PdfRef::of(0, 0).to_string(), "0 0 R");
79        assert_eq!(PdfRef::of(0, 21).to_string(), "0 21 R");
80        assert_eq!(PdfRef::of(94, 0).to_string(), "94 0 R");
81        assert_eq!(PdfRef::of(4678, 9120).to_string(), "4678 9120 R");
82    }
83
84    #[test]
85    fn can_provide_size_in_bytes() {
86        assert_eq!(PdfRef::of(0, 0).size_in_bytes(), 5);
87        assert_eq!(PdfRef::of(0, 21).size_in_bytes(), 6);
88        assert_eq!(PdfRef::of(94, 0).size_in_bytes(), 6);
89        assert_eq!(PdfRef::of(4678, 9120).size_in_bytes(), 11);
90    }
91
92    #[test]
93    fn can_be_serialized() {
94        let mut buffer1 = vec![b' '; 9];
95        assert_eq!(PdfRef::of(0, 0).copy_bytes_into(&mut buffer1, 3), 5);
96        assert_eq!(buffer1, typed_array_for("   0 0 R "));
97
98        let mut buffer2 = vec![b' '; 9];
99        assert_eq!(PdfRef::of(0, 21).copy_bytes_into(&mut buffer2, 1), 6);
100        assert_eq!(buffer2, typed_array_for(" 0 21 R  "));
101
102        let mut buffer3 = vec![b' '; 9];
103        assert_eq!(PdfRef::of(94, 0).copy_bytes_into(&mut buffer3, 2), 6);
104        assert_eq!(buffer3, typed_array_for("  94 0 R "));
105
106        let mut buffer4 = vec![b' '; 13];
107        assert_eq!(PdfRef::of(4678, 9120).copy_bytes_into(&mut buffer4, 0), 11);
108        assert_eq!(buffer4, typed_array_for("4678 9120 R  "));
109    }
110}