1use std::ops::Deref;
2
3use super::Primitive;
4
5#[derive(Debug, Clone, PartialEq)]
7pub struct Buf {
8 pub(crate) inner: Vec<u8>,
9 pub(crate) limits: Limits,
10}
11
12impl Buf {
13 pub(crate) fn new() -> Self {
14 Self { inner: Vec::new(), limits: Limits::new() }
15 }
16
17 pub(crate) fn with_capacity(capacity: usize) -> Self {
18 Self {
19 inner: Vec::with_capacity(capacity),
20 limits: Limits::new(),
21 }
22 }
23
24 pub fn into_vec(self) -> Vec<u8> {
26 self.inner
27 }
28
29 pub fn as_slice(&self) -> &[u8] {
31 self.inner.as_slice()
32 }
33
34 pub fn limits(&self) -> &Limits {
36 &self.limits
37 }
38
39 #[inline]
40 pub(crate) fn push_val<T: Primitive>(&mut self, value: T) {
41 value.write(self);
42 }
43
44 #[inline]
45 pub(crate) fn push_int(&mut self, value: i32) {
46 self.limits.register_int(value);
47 self.extend(itoa::Buffer::new().format(value).as_bytes());
48 }
49
50 #[inline]
51 pub(crate) fn push_float(&mut self, value: f32) {
52 if value as i32 as f32 == value {
55 self.push_int(value as i32);
56 } else {
57 self.push_decimal(value);
58 }
59 }
60
61 #[inline]
63 pub(crate) fn push_decimal(&mut self, value: f32) {
64 self.limits.register_real(value);
65
66 if value == 0.0 || (value.abs() > 1e-6 && value.abs() < 1e12) {
67 self.extend(ryu::Buffer::new().format(value).as_bytes());
68 } else {
69 #[inline(never)]
70 fn write_extreme(buf: &mut Buf, value: f32) {
71 use std::io::Write;
72 write!(buf.inner, "{value}").unwrap();
73 }
74
75 write_extreme(self, value);
76 }
77 }
78
79 #[inline]
80 pub(crate) fn extend_buf(&mut self, other: &Buf) {
81 self.limits.merge(&other.limits);
82 self.inner.extend(&other.inner);
83 }
84
85 #[inline]
86 pub(crate) fn push(&mut self, b: u8) {
87 self.inner.push(b);
88 }
89
90 #[inline]
91 pub(crate) fn push_hex(&mut self, value: u8) {
92 fn hex(b: u8) -> u8 {
93 if b < 10 {
94 b'0' + b
95 } else {
96 b'A' + (b - 10)
97 }
98 }
99
100 self.push(hex(value >> 4));
101 self.push(hex(value & 0xF));
102 }
103
104 #[inline]
105 pub(crate) fn push_hex_u16(&mut self, value: u16) {
106 self.push_hex((value >> 8) as u8);
107 self.push_hex(value as u8);
108 }
109
110 #[inline]
111 pub(crate) fn push_octal(&mut self, value: u8) {
112 fn octal(b: u8) -> u8 {
113 b'0' + b
114 }
115
116 self.push(octal(value >> 6));
117 self.push(octal((value >> 3) & 7));
118 self.push(octal(value & 7));
119 }
120
121 #[inline]
122 pub(crate) fn reserve(&mut self, additional: usize) {
123 self.inner.reserve(additional)
124 }
125}
126
127impl Deref for Buf {
128 type Target = [u8];
129
130 fn deref(&self) -> &Self::Target {
131 &self.inner
132 }
133}
134
135impl Extend<u8> for Buf {
136 fn extend<T: IntoIterator<Item = u8>>(&mut self, iter: T) {
137 self.inner.extend(iter)
138 }
139}
140
141impl<'a> Extend<&'a u8> for Buf {
142 fn extend<T: IntoIterator<Item = &'a u8>>(&mut self, iter: T) {
143 self.inner.extend(iter)
144 }
145}
146
147#[derive(Debug, Default, Clone, PartialEq)]
149pub struct Limits {
150 int: i32,
151 real: f32,
152 name_len: usize,
153 str_len: usize,
154 array_len: usize,
155 dict_entries: usize,
156}
157
158impl Limits {
159 pub fn new() -> Self {
161 Self::default()
162 }
163
164 pub fn int(&self) -> i32 {
166 self.int
167 }
168
169 pub fn real(&self) -> f32 {
171 self.real
172 }
173
174 pub fn name_len(&self) -> usize {
176 self.name_len
177 }
178
179 pub fn str_len(&self) -> usize {
181 self.str_len
182 }
183
184 pub fn array_len(&self) -> usize {
186 self.array_len
187 }
188
189 pub fn dict_entries(&self) -> usize {
191 self.dict_entries
192 }
193
194 pub(crate) fn register_int(&mut self, val: i32) {
195 self.int = self.int.max(val.abs());
196 }
197
198 pub(crate) fn register_real(&mut self, val: f32) {
199 self.real = self.real.max(val.abs());
200 }
201
202 pub(crate) fn register_name_len(&mut self, len: usize) {
203 self.name_len = self.name_len.max(len);
204 }
205
206 pub(crate) fn register_str_len(&mut self, len: usize) {
207 self.str_len = self.str_len.max(len);
208 }
209
210 pub(crate) fn register_array_len(&mut self, len: usize) {
211 self.array_len = self.array_len.max(len);
212 }
213
214 pub(crate) fn register_dict_entries(&mut self, len: usize) {
215 self.dict_entries = self.dict_entries.max(len);
216 }
217
218 pub fn merge(&mut self, other: &Limits) {
221 self.register_int(other.int);
222 self.register_real(other.real);
223 self.register_name_len(other.name_len);
224 self.register_str_len(other.str_len);
225 self.register_array_len(other.array_len);
226 self.register_dict_entries(other.dict_entries);
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use super::*;
233 use crate::{Chunk, Content, Finish, Name, Rect, Ref, Str, TextStr};
234
235 #[test]
236 fn test_content_limits() {
237 let mut limits = Limits::default();
238
239 let mut content = Content::new();
240 content.cubic_to(14.3, 16.2, 22.6, 30.9, 50.1, 40.0);
241 content.show(Str(b"Some text"));
242 content.set_font(Name(b"NotoSans"), 10.0);
243 let buf = content.finish();
244 limits.merge(buf.limits());
245
246 let mut content = Content::new();
247 content.line_to(55.0, -75.3);
248 content.set_font(Name(b"Noto"), 10.0);
249 content
250 .show_positioned()
251 .items()
252 .show(Str(b"A"))
253 .show(Str(b"B"))
254 .adjust(32.0);
255 content
256 .marked_content_point_with_properties(Name(b"Hi"))
257 .properties()
258 .actual_text(TextStr("text"));
259 let buf = content.finish();
260 limits.merge(buf.limits());
261
262 assert_eq!(
263 limits,
264 Limits {
265 int: 55,
266 real: 75.3,
267 name_len: 10,
268 str_len: 9,
269 array_len: 3,
270 dict_entries: 1,
271 }
272 )
273 }
274
275 #[test]
276 fn test_chunk_limits() {
277 let mut limits = Limits::default();
278
279 let mut chunk = Chunk::new();
280 let mut x_object = chunk.form_xobject(Ref::new(1), &[]);
281 x_object.bbox(Rect::new(4.0, 6.0, 22.1, 31.0));
282 x_object.finish();
283
284 limits.merge(chunk.limits());
285
286 assert_eq!(
287 limits,
288 Limits {
289 int: 31,
290 real: 22.1,
291 name_len: 7,
292 str_len: 0,
293 array_len: 4,
294 dict_entries: 4,
295 }
296 )
297 }
298}