Skip to main content

pdf_lib_rs/core/document/
pdf_header.rs

1use std::fmt;
2use crate::core::syntax::CharCodes;
3use crate::core::objects::pdf_object::PdfObjectTrait;
4use crate::utils::copy_string_into_buffer;
5
6/// PDF file header, e.g., `%PDF-1.7` followed by a binary comment.
7#[derive(Debug, Clone)]
8pub struct PdfHeader {
9    major: String,
10    minor: String,
11}
12
13impl PdfHeader {
14    pub fn for_version(major: u8, minor: u8) -> Self {
15        PdfHeader {
16            major: major.to_string(),
17            minor: minor.to_string(),
18        }
19    }
20
21    pub fn major(&self) -> &str {
22        &self.major
23    }
24
25    pub fn minor(&self) -> &str {
26        &self.minor
27    }
28}
29
30impl fmt::Display for PdfHeader {
31    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32        let bc = 129u8 as char;
33        write!(f, "%PDF-{}.{}\n%{}{}{}{}", self.major, self.minor, bc, bc, bc, bc)
34    }
35}
36
37impl PdfObjectTrait for PdfHeader {
38    fn size_in_bytes(&self) -> usize {
39        // "%PDF-" (5) + major + "." (1) + minor + "\n%" (2) + 4 binary chars = 12 + major.len + minor.len
40        12 + self.major.len() + self.minor.len()
41    }
42
43    fn copy_bytes_into(&self, buffer: &mut [u8], offset: usize) -> usize {
44        let initial_offset = offset;
45        let mut off = offset;
46
47        buffer[off] = CharCodes::Percent;
48        off += 1;
49        buffer[off] = CharCodes::UpperP;
50        off += 1;
51        buffer[off] = CharCodes::UpperD;
52        off += 1;
53        buffer[off] = CharCodes::UpperF;
54        off += 1;
55        buffer[off] = CharCodes::Minus;
56        off += 1;
57
58        off += copy_string_into_buffer(&self.major, buffer, off);
59        buffer[off] = CharCodes::Period;
60        off += 1;
61        off += copy_string_into_buffer(&self.minor, buffer, off);
62        buffer[off] = CharCodes::Newline;
63        off += 1;
64
65        buffer[off] = CharCodes::Percent;
66        off += 1;
67        buffer[off] = 129;
68        off += 1;
69        buffer[off] = 129;
70        off += 1;
71        buffer[off] = 129;
72        off += 1;
73        buffer[off] = 129;
74        off += 1;
75
76        off - initial_offset
77    }
78}
79
80#[cfg(test)]
81mod tests {
82    use super::*;
83    use crate::utils::typed_array_for;
84
85    #[test]
86    fn can_be_constructed() {
87        let _ = PdfHeader::for_version(1, 2);
88    }
89
90    #[test]
91    fn can_provide_size_in_bytes() {
92        assert_eq!(PdfHeader::for_version(81, 79).size_in_bytes(), 16);
93    }
94
95    #[test]
96    fn can_be_serialized() {
97        let mut buffer = vec![b' '; 20];
98        assert_eq!(PdfHeader::for_version(79, 81).copy_bytes_into(&mut buffer, 3), 16);
99        let mut expected = typed_array_for("   %PDF-79.81\n%");
100        expected.push(129);
101        expected.push(129);
102        expected.push(129);
103        expected.push(129);
104        expected.push(b' ');
105        assert_eq!(buffer, expected);
106    }
107}