Skip to main content

pdf_lib_rs/core/document/
pdf_trailer_dict.rs

1use std::fmt;
2use crate::core::objects::PdfDict;
3use crate::core::objects::pdf_object::PdfObjectTrait;
4use crate::core::syntax::CharCodes;
5
6/// PDF trailer dictionary — `trailer` keyword followed by a dictionary.
7#[derive(Debug, Clone)]
8pub struct PdfTrailerDict {
9    pub dict: PdfDict,
10}
11
12impl PdfTrailerDict {
13    pub fn of(dict: PdfDict) -> Self {
14        PdfTrailerDict { dict }
15    }
16}
17
18impl fmt::Display for PdfTrailerDict {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        write!(f, "trailer\n{}", self.dict)
21    }
22}
23
24impl PdfObjectTrait for PdfTrailerDict {
25    fn size_in_bytes(&self) -> usize {
26        // "trailer\n" (8) + dict
27        8 + self.dict.size_in_bytes()
28    }
29
30    fn copy_bytes_into(&self, buffer: &mut [u8], offset: usize) -> usize {
31        let initial_offset = offset;
32        let mut off = offset;
33
34        // "trailer\n"
35        buffer[off] = CharCodes::LowerT;
36        off += 1;
37        buffer[off] = CharCodes::LowerR;
38        off += 1;
39        buffer[off] = CharCodes::LowerA;
40        off += 1;
41        buffer[off] = CharCodes::LowerI;
42        off += 1;
43        buffer[off] = CharCodes::LowerL;
44        off += 1;
45        buffer[off] = CharCodes::LowerE;
46        off += 1;
47        buffer[off] = CharCodes::LowerR;
48        off += 1;
49        buffer[off] = CharCodes::Newline;
50        off += 1;
51
52        off += self.dict.copy_bytes_into(buffer, off);
53
54        off - initial_offset
55    }
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use crate::core::objects::{PdfName, PdfObject};
62    use crate::utils::typed_array_for;
63
64    fn make_test_dict() -> PdfDict {
65        let mut dict = PdfDict::new();
66        dict.set(PdfName::of("Foo"), PdfObject::Name(PdfName::of("Bar")));
67        dict
68    }
69
70    #[test]
71    fn can_be_converted_to_string() {
72        let td = PdfTrailerDict::of(make_test_dict());
73        assert_eq!(td.to_string(), "trailer\n<<\n/Foo /Bar\n>>");
74    }
75
76    #[test]
77    fn can_provide_size_in_bytes() {
78        let td = PdfTrailerDict::of(make_test_dict());
79        assert_eq!(td.size_in_bytes(), 23);
80    }
81
82    #[test]
83    fn can_be_serialized() {
84        let td = PdfTrailerDict::of(make_test_dict());
85        let mut buffer = vec![b' '; 27];
86        assert_eq!(td.copy_bytes_into(&mut buffer, 3), 23);
87        assert_eq!(buffer, typed_array_for("   trailer\n<<\n/Foo /Bar\n>> "));
88    }
89}