1- use std:: borrow:: Cow ;
21use std:: fmt;
2+ use std:: sync:: Arc ;
33
44use crate :: { error:: FilterError , predictor:: PredictorParams } ;
55
@@ -260,24 +260,25 @@ impl Filter {
260260 }
261261}
262262
263- /// Decodes borrowed stream data by applying the filter chain from its dictionary.
263+ /// Decodes stream data by applying the filter chain from its dictionary.
264264///
265265/// Reads the `/Filter` entry from `dictionary` and applies each filter in order.
266- /// Returns the fully decoded bytes, or `Cow::Borrowed` if no filters are present.
266+ /// Returns shared ownership of the fully decoded bytes.
267+ /// Unfiltered input retains the original shared allocation.
267268///
268- /// This entry point accepts a dictionary and data slice separately so callers
269+ /// This entry point accepts a dictionary and shared data separately so callers
269270/// such as inline-image decoders do not need to construct a temporary
270271/// [`StreamObject`].
271272///
272273/// # Errors
273274///
274275/// Returns [`FilterError`] if any filter in the chain fails or is unsupported.
275- pub fn decode_data_with_resolver < ' a > (
276+ pub fn decode_data_with_resolver (
276277 dictionary : & Dictionary ,
277- stream_data : & ' a [ u8 ] ,
278+ stream_data : Arc < Vec < u8 > > ,
278279 objects : & dyn ObjectResolver ,
279- ) -> Result < Cow < ' a , [ u8 ] > , FilterError > {
280- let mut data: Cow < ' a , [ u8 ] > = Cow :: Borrowed ( stream_data) ;
280+ ) -> Result < Arc < Vec < u8 > > , FilterError > {
281+ let mut data = stream_data;
281282 let filters = Filter :: from_dictionary ( dictionary, objects) ?;
282283
283284 let Some ( filters) = & filters else {
@@ -289,14 +290,14 @@ pub fn decode_data_with_resolver<'a>(
289290 for ( filter, params) in filters. iter ( ) . zip ( decode_params. iter ( ) ) {
290291 match filter {
291292 Filter :: FlateDecode => {
292- let decoded = Filter :: decode_flate ( & data) ?;
293+ let decoded = Filter :: decode_flate ( data. as_slice ( ) ) ?;
293294 let decoded = match params {
294295 DecodeParms :: Flate { predictor } if !predictor. is_none ( ) => {
295296 crate :: predictor:: apply_predictor ( & decoded, predictor) ?
296297 }
297298 _ => decoded,
298299 } ;
299- data = Cow :: Owned ( decoded) ;
300+ data = Arc :: new ( decoded) ;
300301 }
301302 Filter :: LZWDecode => {
302303 let ( early_change, predictor) = match params {
@@ -306,49 +307,49 @@ pub fn decode_data_with_resolver<'a>(
306307 } => ( * early_change, Some ( predictor) ) ,
307308 _ => ( true , None ) ,
308309 } ;
309- let decoded = crate :: lzw:: decode ( & data, early_change) ?;
310+ let decoded = crate :: lzw:: decode ( data. as_slice ( ) , early_change) ?;
310311 let decoded = match predictor {
311312 Some ( p) if !p. is_none ( ) => crate :: predictor:: apply_predictor ( & decoded, p) ?,
312313 _ => decoded,
313314 } ;
314- data = Cow :: Owned ( decoded) ;
315+ data = Arc :: new ( decoded) ;
315316 }
316317 Filter :: JPXDecode => {
317- let decoded = Filter :: decode_jpeg2000 ( & data) ?;
318- data = Cow :: Owned ( decoded) ;
318+ let decoded = Filter :: decode_jpeg2000 ( data. as_slice ( ) ) ?;
319+ data = Arc :: new ( decoded) ;
319320 }
320321 Filter :: DCTDecode => {
321- let decoded = Filter :: decode_jpeg_baseline ( & data) ?;
322- data = Cow :: Owned ( decoded) ;
322+ let decoded = Filter :: decode_jpeg_baseline ( data. as_slice ( ) ) ?;
323+ data = Arc :: new ( decoded) ;
323324 }
324325 Filter :: ASCII85Decode => {
325- let decoded = crate :: ascii85:: decode_ascii85 ( & data) ?;
326- data = Cow :: Owned ( decoded) ;
326+ let decoded = crate :: ascii85:: decode_ascii85 ( data. as_slice ( ) ) ?;
327+ data = Arc :: new ( decoded) ;
327328 }
328329 Filter :: ASCIIHexDecode => {
329- let decoded = crate :: asciihex:: decode_ascii_hex ( & data) ?;
330- data = Cow :: Owned ( decoded) ;
330+ let decoded = crate :: asciihex:: decode_ascii_hex ( data. as_slice ( ) ) ?;
331+ data = Arc :: new ( decoded) ;
331332 }
332333 Filter :: RunLengthDecode => {
333- let decoded = crate :: runlength:: decode_run_length ( & data) ?;
334- data = Cow :: Owned ( decoded) ;
334+ let decoded = crate :: runlength:: decode_run_length ( data. as_slice ( ) ) ?;
335+ data = Arc :: new ( decoded) ;
335336 }
336337 Filter :: JBIG2Decode => {
337338 let ( width, height) = resolve_jbig2_dimensions ( dictionary, objects) ?;
338339 let globals = match params {
339340 DecodeParms :: Jbig2 { globals } => globals. as_deref ( ) ,
340341 _ => None ,
341342 } ;
342- let decoded = pdf_jbig2:: decode ( & data, width, height, globals) ?;
343- data = Cow :: Owned ( decoded) ;
343+ let decoded = pdf_jbig2:: decode ( data. as_slice ( ) , width, height, globals) ?;
344+ data = Arc :: new ( decoded) ;
344345 }
345346 Filter :: CCITTFaxDecode => {
346347 let ccitt_params = match params {
347348 DecodeParms :: CcittFax ( p) => p,
348349 _ => & CCITTFaxParams :: DEFAULT ,
349350 } ;
350- let decoded = pdf_ccitt:: decode ( & data, ccitt_params) ?;
351- data = Cow :: Owned ( decoded) ;
351+ let decoded = pdf_ccitt:: decode ( data. as_slice ( ) , ccitt_params) ?;
352+ data = Arc :: new ( decoded) ;
352353 }
353354 Filter :: Unsupported ( name) => {
354355 return Err ( FilterError :: UnsupportedFilter ( name. clone ( ) ) ) ;
@@ -360,24 +361,24 @@ pub fn decode_data_with_resolver<'a>(
360361
361362/// Decodes a [`StreamObject`] by applying its full filter chain.
362363///
363- /// This compatibility entry point forwards the stream's dictionary and raw
364- /// data to [`decode_data_with_resolver`] .
364+ /// Unfiltered data shares the stream's existing allocation. Filtered data is
365+ /// returned in a newly allocated shared buffer .
365366///
366367/// # Errors
367368///
368369/// Returns [`FilterError`] if any filter in the chain fails or is unsupported.
369- pub fn decode_with_resolver < ' a > (
370- stream : & ' a StreamObject ,
370+ pub fn decode_with_resolver (
371+ stream : & StreamObject ,
371372 objects : & dyn ObjectResolver ,
372- ) -> Result < Cow < ' a , [ u8 ] > , FilterError > {
373- decode_data_with_resolver ( & stream. dictionary , stream. raw_data ( ) , objects)
373+ ) -> Result < Arc < Vec < u8 > > , FilterError > {
374+ decode_data_with_resolver ( & stream. dictionary , stream. shared_data ( ) , objects)
374375}
375376
376377/// Decodes a [`StreamObject`] by applying its full filter chain.
377378///
378379/// This convenience wrapper uses a passthrough resolver, so it only supports
379380/// direct `/Filter` and `/DecodeParms` values.
380- pub fn decode ( stream : & StreamObject ) -> Result < Cow < ' _ , [ u8 ] > , FilterError > {
381+ pub fn decode ( stream : & StreamObject ) -> Result < Arc < Vec < u8 > > , FilterError > {
381382 let objects = PassthroughResolver ;
382383 decode_with_resolver ( stream, & objects)
383384}
@@ -550,31 +551,49 @@ mod tests {
550551 }
551552
552553 #[ test]
553- fn decode_data_without_filters_borrows_input ( ) {
554+ fn decode_data_without_filters_preserves_shared_data ( ) {
554555 let dictionary = Dictionary :: new ( BTreeMap :: new ( ) ) ;
555- let data = b"borrowed stream data";
556+ let data = Arc :: new ( b" stream data". to_vec ( ) ) ;
556557
557- let decoded = decode_data_with_resolver ( & dictionary, data, & PassthroughResolver )
558- . expect ( "unfiltered data should decode" ) ;
558+ let decoded =
559+ decode_data_with_resolver ( & dictionary, Arc :: clone ( & data) , & PassthroughResolver )
560+ . expect ( "unfiltered data should decode" ) ;
559561
560- assert ! ( matches!( & decoded, Cow :: Borrowed ( _) ) ) ;
561- assert_eq ! ( decoded. as_ref( ) . as_ptr( ) , data. as_ptr( ) ) ;
562- assert_eq ! ( decoded. as_ref( ) , data) ;
562+ assert ! ( Arc :: ptr_eq( & decoded, & data) ) ;
563+ assert_eq ! ( decoded. as_slice( ) , b"stream data" ) ;
563564 }
564565
565566 #[ test]
566- fn decode_data_with_filter_returns_decoded_owned_data ( ) {
567+ fn decode_data_with_filter_returns_shared_decoded_data ( ) {
567568 let dictionary = Dictionary :: new ( BTreeMap :: from ( [ (
568569 "Filter" . to_string ( ) ,
569570 ObjectVariant :: Name ( b"ASCIIHexDecode" . to_vec ( ) ) ,
570571 ) ] ) ) ;
571572
573+ let encoded = Arc :: new ( b"48 65 6c 6c 6f>" . to_vec ( ) ) ;
572574 let decoded =
573- decode_data_with_resolver ( & dictionary, b"48 65 6c 6c 6f>" , & PassthroughResolver )
575+ decode_data_with_resolver ( & dictionary, Arc :: clone ( & encoded ) , & PassthroughResolver )
574576 . expect ( "filtered data should decode" ) ;
575577
576- assert ! ( matches!( & decoded, Cow :: Owned ( _) ) ) ;
577- assert_eq ! ( decoded. as_ref( ) , b"Hello" ) ;
578+ assert_eq ! ( Arc :: strong_count( & decoded) , 1 ) ;
579+ assert ! ( !Arc :: ptr_eq( & decoded, & encoded) ) ;
580+ assert_eq ! ( decoded. as_slice( ) , b"Hello" ) ;
581+ }
582+
583+ #[ test]
584+ fn decode_unfiltered_stream_shares_data ( ) {
585+ let stream = StreamObject :: new (
586+ 1 ,
587+ 0 ,
588+ Box :: new ( Dictionary :: new ( BTreeMap :: new ( ) ) ) ,
589+ b"shared stream data" . to_vec ( ) ,
590+ ) ;
591+
592+ let decoded = decode_with_resolver ( & stream, & PassthroughResolver )
593+ . expect ( "unfiltered data should decode" ) ;
594+
595+ assert ! ( Arc :: ptr_eq( & decoded, & stream. data) ) ;
596+ assert_eq ! ( decoded. as_slice( ) , b"shared stream data" ) ;
578597 }
579598
580599 #[ test]
0 commit comments