png/decoder/
read_decoder.rs1use super::stream::{DecodeOptions, Decoded, DecodingError, FormatErrorInner, StreamingDecoder};
2use super::zlib::UnfilterBuf;
3use super::Limits;
4
5use std::io::{BufRead, ErrorKind, Read, Seek};
6
7use crate::chunk;
8use crate::common::Info;
9
10pub(crate) struct ReadDecoder<R: Read> {
20 reader: R,
21 decoder: StreamingDecoder,
22}
23
24impl<R: BufRead + Seek> ReadDecoder<R> {
25 pub fn new(r: R) -> Self {
26 Self {
27 reader: r,
28 decoder: StreamingDecoder::new(),
29 }
30 }
31
32 pub fn with_options(r: R, options: DecodeOptions) -> Self {
33 let mut decoder = StreamingDecoder::new_with_options(options);
34 decoder.limits = Limits::default();
35
36 Self { reader: r, decoder }
37 }
38
39 pub fn set_limits(&mut self, limits: Limits) {
40 self.decoder.limits = limits;
41 }
42
43 pub fn reserve_bytes(&mut self, bytes: usize) -> Result<(), DecodingError> {
44 self.decoder.limits.reserve_bytes(bytes)
45 }
46
47 pub fn set_ignore_text_chunk(&mut self, ignore_text_chunk: bool) {
48 self.decoder.set_ignore_text_chunk(ignore_text_chunk);
49 }
50
51 pub fn set_ignore_iccp_chunk(&mut self, ignore_iccp_chunk: bool) {
52 self.decoder.set_ignore_iccp_chunk(ignore_iccp_chunk);
53 }
54
55 pub fn ignore_checksums(&mut self, ignore_checksums: bool) {
56 self.decoder.set_ignore_adler32(ignore_checksums);
57 self.decoder.set_ignore_crc(ignore_checksums);
58 }
59
60 fn decode_next(
63 &mut self,
64 image_data: Option<&mut UnfilterBuf<'_>>,
65 ) -> Result<Decoded, DecodingError> {
66 let (consumed, result) = {
67 let buf = self.reader.fill_buf()?;
68 if buf.is_empty() {
69 return Err(DecodingError::IoError(ErrorKind::UnexpectedEof.into()));
70 }
71 self.decoder.update(buf, image_data)?
72 };
73 self.reader.consume(consumed);
74 Ok(result)
75 }
76
77 pub fn read_header_info(&mut self) -> Result<&Info<'static>, DecodingError> {
81 while self.info().is_none() {
82 if let Decoded::ChunkComplete(chunk::IEND) = self.decode_next(None)? {
83 unreachable!()
84 }
85 }
86 Ok(self.info().unwrap())
87 }
88
89 pub fn read_until_image_data(&mut self) -> Result<(), DecodingError> {
93 loop {
94 match self.decode_next(None)? {
95 Decoded::ChunkBegin(_, chunk::IDAT) | Decoded::ChunkBegin(_, chunk::fdAT) => break,
96 Decoded::ChunkComplete(chunk::IEND) => {
97 return Err(DecodingError::Format(
98 FormatErrorInner::MissingImageData.into(),
99 ))
100 }
101 _ => {}
104 }
105 }
106 Ok(())
107 }
108
109 pub fn decode_image_data(
114 &mut self,
115 image_data: Option<&mut UnfilterBuf<'_>>,
116 ) -> Result<ImageDataCompletionStatus, DecodingError> {
117 match self.decode_next(image_data)? {
118 Decoded::ImageData => Ok(ImageDataCompletionStatus::ExpectingMoreData),
119 Decoded::ImageDataFlushed => Ok(ImageDataCompletionStatus::Done),
120 _ => Ok(ImageDataCompletionStatus::ExpectingMoreData),
122 }
123 }
124
125 pub fn finish_decoding_image_data(&mut self) -> Result<(), DecodingError> {
129 loop {
130 if let ImageDataCompletionStatus::Done = self.decode_image_data(None)? {
131 return Ok(());
132 }
133 }
134 }
135
136 pub fn read_until_end_of_input(&mut self) -> Result<(), DecodingError> {
140 while !matches!(self.decode_next(None)?, Decoded::ChunkComplete(chunk::IEND)) {}
141 Ok(())
142 }
143
144 pub fn info(&self) -> Option<&Info<'static>> {
145 self.decoder.info.as_ref()
146 }
147}
148
149#[derive(Debug, Eq, PartialEq)]
150pub(crate) enum ImageDataCompletionStatus {
151 ExpectingMoreData,
152 Done,
153}