use pdfrum_common::{Diagnostics, Limits};
use pdfrum_object::{Resolve, Stream};
#[must_use]
pub fn decoded_stream(
stream: &Stream,
r: &impl Resolve,
limits: &Limits,
diags: &mut Diagnostics,
) -> Vec<u8> {
decoded_bytes(stream, r, limits, diags)
}
pub(crate) fn decoded_bytes<R: Resolve + ?Sized>(
stream: &Stream,
r: &R,
limits: &Limits,
diags: &mut Diagnostics,
) -> Vec<u8> {
pdfrum_filters::decode_chain(stream, 0, &r, limits, diags).data
}
pub(crate) fn structural_bytes<R: Resolve + ?Sized>(
stream: &Stream,
r: &R,
limits: &Limits,
diags: &mut Diagnostics,
) -> Option<Vec<u8>> {
let decoded = pdfrum_filters::decode_chain(stream, 0, &r, limits, diags);
decoded.image.is_none().then_some(decoded.data)
}
#[cfg(test)]
mod tests {
use super::decoded_stream;
use pdfrum_common::{DiagKind, Diagnostics, Limits};
use pdfrum_object::{ByteSpan, Dict, Name, NoResolve, Object, Stream, names};
#[test]
fn an_unfiltered_stream_is_its_own_data() {
let stream = Stream::new(Dict::new(), ByteSpan::from(b"raw".to_vec()));
let mut diags = Diagnostics::default();
assert_eq!(
decoded_stream(&stream, &NoResolve, &Limits::default(), &mut diags),
b"raw"
);
}
#[test]
fn an_unusable_filter_declaration_yields_the_raw_bytes() {
let dict = Dict::from_pairs([(names::FILTER.clone(), Object::Int(7))]);
let stream = Stream::new(dict, ByteSpan::from(b"raw".to_vec()));
let mut diags = Diagnostics::default();
assert_eq!(
decoded_stream(&stream, &NoResolve, &Limits::default(), &mut diags),
b"raw"
);
assert!(diags.contains(&DiagKind::UndecodableStream));
}
#[test]
fn a_hex_filter_decodes() {
let dict = Dict::from_pairs([(
names::FILTER.clone(),
Object::Name(Name::from("ASCIIHexDecode")),
)]);
let stream = Stream::new(dict, ByteSpan::from(b"414243>".to_vec()));
let mut diags = Diagnostics::default();
assert_eq!(
decoded_stream(&stream, &NoResolve, &Limits::default(), &mut diags),
b"ABC"
);
}
}