1+ use std:: ops:: Deref ;
2+
13use super :: Primitive ;
24
3- /// Additional methods for byte buffers.
4- pub trait BufExt {
5- fn push_val < T : Primitive > ( & mut self , value : T ) ;
6- fn push_int ( & mut self , value : i32 ) ;
7- fn push_float ( & mut self , value : f32 ) ;
8- fn push_decimal ( & mut self , value : f32 ) ;
9- fn push_hex ( & mut self , value : u8 ) ;
10- fn push_hex_u16 ( & mut self , value : u16 ) ;
11- fn push_octal ( & mut self , value : u8 ) ;
5+ /// A buffer of arbitrary PDF content.
6+ #[ derive( Debug , Clone , PartialEq ) ]
7+ pub struct Buf {
8+ pub ( crate ) inner : Vec < u8 > ,
9+ pub ( crate ) limits : Limits ,
1210}
1311
14- impl BufExt for Vec < u8 > {
12+ impl 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+ /// Get the underlying bytes of the buffer.
25+ pub fn into_vec ( self ) -> Vec < u8 > {
26+ self . inner
27+ }
28+
29+ /// Get the underlying bytes of the buffer as a slice.
30+ pub fn as_slice ( & self ) -> & [ u8 ] {
31+ self . inner . as_slice ( )
32+ }
33+
34+ /// Return the limits of the buffer.
35+ pub fn limits ( & self ) -> & Limits {
36+ & self . limits
37+ }
38+
1539 #[ inline]
16- fn push_val < T : Primitive > ( & mut self , value : T ) {
40+ pub ( crate ) fn push_val < T : Primitive > ( & mut self , value : T ) {
1741 value. write ( self ) ;
1842 }
1943
2044 #[ inline]
21- fn push_int ( & mut self , value : i32 ) {
45+ pub ( crate ) fn push_int ( & mut self , value : i32 ) {
46+ self . limits . register_int ( value) ;
2247 self . extend ( itoa:: Buffer :: new ( ) . format ( value) . as_bytes ( ) ) ;
2348 }
2449
2550 #[ inline]
26- fn push_float ( & mut self , value : f32 ) {
51+ pub ( crate ) fn push_float ( & mut self , value : f32 ) {
2752 // Don't write the decimal point if we don't need it.
2853 // Also, integer formatting is way faster.
2954 if value as i32 as f32 == value {
@@ -35,22 +60,35 @@ impl BufExt for Vec<u8> {
3560
3661 /// Like `push_float`, but forces the decimal point.
3762 #[ inline]
38- fn push_decimal ( & mut self , value : f32 ) {
63+ pub ( crate ) fn push_decimal ( & mut self , value : f32 ) {
64+ self . limits . register_real ( value) ;
65+
3966 if value == 0.0 || ( value. abs ( ) > 1e-6 && value. abs ( ) < 1e12 ) {
4067 self . extend ( ryu:: Buffer :: new ( ) . format ( value) . as_bytes ( ) ) ;
4168 } else {
4269 #[ inline( never) ]
43- fn write_extreme ( buf : & mut Vec < u8 > , value : f32 ) {
70+ fn write_extreme ( buf : & mut Buf , value : f32 ) {
4471 use std:: io:: Write ;
45- write ! ( buf, "{}" , value) . unwrap ( ) ;
72+ write ! ( buf. inner , "{}" , value) . unwrap ( ) ;
4673 }
4774
4875 write_extreme ( self , value) ;
4976 }
5077 }
5178
5279 #[ inline]
53- fn push_hex ( & mut self , value : u8 ) {
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 ) {
5492 fn hex ( b : u8 ) -> u8 {
5593 if b < 10 {
5694 b'0' + b
@@ -64,13 +102,13 @@ impl BufExt for Vec<u8> {
64102 }
65103
66104 #[ inline]
67- fn push_hex_u16 ( & mut self , value : u16 ) {
105+ pub ( crate ) fn push_hex_u16 ( & mut self , value : u16 ) {
68106 self . push_hex ( ( value >> 8 ) as u8 ) ;
69107 self . push_hex ( value as u8 ) ;
70108 }
71109
72110 #[ inline]
73- fn push_octal ( & mut self , value : u8 ) {
111+ pub ( crate ) fn push_octal ( & mut self , value : u8 ) {
74112 fn octal ( b : u8 ) -> u8 {
75113 b'0' + b
76114 }
@@ -79,4 +117,182 @@ impl BufExt for Vec<u8> {
79117 self . push ( octal ( ( value >> 3 ) & 7 ) ) ;
80118 self . push ( octal ( value & 7 ) ) ;
81119 }
120+
121+ #[ inline]
122+ pub ( crate ) fn reserve ( & mut self , additional : usize ) {
123+ self . inner . reserve ( additional)
124+ }
125+ }
126+
127+ impl Deref for Buf {
128+ type Target = [ u8 ] ;
129+
130+ fn deref ( & self ) -> & Self :: Target {
131+ & self . inner
132+ }
133+ }
134+
135+ impl Extend < u8 > for Buf {
136+ fn extend < T : IntoIterator < Item = u8 > > ( & mut self , iter : T ) {
137+ self . inner . extend ( iter)
138+ }
139+ }
140+
141+ impl < ' 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+ /// Tracks the limits of data types used in a buffer.
148+ #[ derive( Debug , Default , Clone , PartialEq ) ]
149+ pub 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+
158+ impl Limits {
159+ /// Create a new `Limits` struct with all values initialized to zero.
160+ pub fn new ( ) -> Self {
161+ Self :: default ( )
162+ }
163+
164+ /// Get the absolute value of the largest positive/negative integer number.
165+ pub fn int ( & self ) -> i32 {
166+ self . int
167+ }
168+
169+ /// Get the absolute value of the largest positive/negative real number.
170+ pub fn real ( & self ) -> f32 {
171+ self . real
172+ }
173+
174+ /// Get the maximum length of any used name.
175+ pub fn name_len ( & self ) -> usize {
176+ self . name_len
177+ }
178+
179+ /// Get the maximum length of any used string.
180+ pub fn str_len ( & self ) -> usize {
181+ self . str_len
182+ }
183+
184+ /// Get the maximum length of any used array.
185+ pub fn array_len ( & self ) -> usize {
186+ self . array_len
187+ }
188+
189+ /// Get the maximum number of entries in any dictionary.
190+ 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+ /// Merge two `Limits` with each other, taking the maximum
219+ /// of each field from both.
220+ 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) ]
231+ mod 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+ }
82298}
0 commit comments