pdf_lib_rs/core/objects/
pdf_raw_stream.rs1use std::fmt;
2use crate::core::syntax::CharCodes;
3use crate::utils::array_as_string;
4use super::pdf_dict::PdfDict;
5use super::pdf_name::PdfName;
6use super::pdf_number::PdfNumber;
7use super::pdf_object::{PdfObject, PdfObjectTrait};
8
9#[derive(Debug, Clone)]
11pub struct PdfRawStream {
12 pub dict: PdfDict,
13 pub contents: Vec<u8>,
14}
15
16impl PdfRawStream {
17 pub fn of(dict: PdfDict, contents: Vec<u8>) -> Self {
18 PdfRawStream { dict, contents }
19 }
20
21 pub fn as_uint8_array(&self) -> Vec<u8> {
22 self.contents.clone()
23 }
24
25 pub fn get_contents_string(&self) -> String {
26 array_as_string(&self.contents)
27 }
28
29 #[allow(dead_code)]
30 fn update_dict(&mut self) {
31 self.dict.set(
32 PdfName::length(),
33 PdfObject::Number(PdfNumber::of(self.contents.len() as f64)),
34 );
35 }
36}
37
38impl PartialEq for PdfRawStream {
39 fn eq(&self, _other: &Self) -> bool {
40 false
41 }
42}
43
44impl fmt::Display for PdfRawStream {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 write!(
47 f,
48 "{}\nstream\n{}\nendstream",
49 self.dict,
50 self.get_contents_string()
51 )
52 }
53}
54
55impl PdfObjectTrait for PdfRawStream {
56 fn size_in_bytes(&self) -> usize {
57 self.dict.size_in_bytes() + self.contents.len() + 18
59 }
60
61 fn copy_bytes_into(&self, buffer: &mut [u8], offset: usize) -> usize {
62 let initial_offset = offset;
63 let mut off = offset;
64
65 off += self.dict.copy_bytes_into(buffer, off);
67
68 buffer[off] = CharCodes::Newline;
70 off += 1;
71 for &b in b"stream" {
72 buffer[off] = b;
73 off += 1;
74 }
75 buffer[off] = CharCodes::Newline;
76 off += 1;
77
78 buffer[off..off + self.contents.len()].copy_from_slice(&self.contents);
80 off += self.contents.len();
81
82 buffer[off] = CharCodes::Newline;
84 off += 1;
85 for &b in b"endstream" {
86 buffer[off] = b;
87 off += 1;
88 }
89
90 off - initial_offset
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn can_be_constructed() {
100 let dict = PdfDict::new();
101 let contents = vec![1, 2, 3, 4, 5];
102 let stream = PdfRawStream::of(dict, contents.clone());
103 assert_eq!(stream.contents, contents);
104 }
105
106 #[test]
107 fn can_get_contents() {
108 let dict = PdfDict::new();
109 let stream = PdfRawStream::of(dict, b"hello".to_vec());
110 assert_eq!(stream.get_contents_string(), "hello");
111 assert_eq!(stream.as_uint8_array(), b"hello".to_vec());
112 }
113
114 #[test]
115 fn can_be_serialized() {
116 let dict = PdfDict::new();
117 let stream = PdfRawStream::of(dict, b"data".to_vec());
118 let size = stream.size_in_bytes();
119 let mut buffer = vec![0u8; size];
120 stream.copy_bytes_into(&mut buffer, 0);
121 let result = String::from_utf8(buffer).unwrap();
122 assert!(result.contains("stream\n"));
123 assert!(result.contains("data"));
124 assert!(result.contains("endstream"));
125 }
126}