1 use std::convert::TryFrom;
2 use std::error;
3 use std::io::{self, BufRead, BufReader, Cursor, Read};
4 use std::str::{self, FromStr};
5 use std::fmt::{self, Display};
6 use std::marker::PhantomData;
7 use std::mem;
8 use std::num::ParseIntError;
9 
10 use super::{ArbitraryHeader, ArbitraryTuplType, BitmapHeader, GraymapHeader, PixmapHeader};
11 use super::{HeaderRecord, PnmHeader, PNMSubtype, SampleEncoding};
12 use crate::color::{ColorType, ExtendedColorType};
13 use crate::error::{
14     DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
15 };
16 use crate::image::{self, ImageDecoder, ImageFormat};
17 use crate::utils;
18 
19 use byteorder::{BigEndian, ByteOrder, NativeEndian};
20 
21 /// All errors that can occur when attempting to parse a PNM
22 #[derive(Debug, Clone)]
23 enum DecoderError {
24     /// PNM's "P[123456]" signature wrong or missing
25     PnmMagicInvalid([u8; 2]),
26     /// Couldn't parse the specified string as an integer from the specified source
27     UnparsableValue(ErrorDataSource, String, ParseIntError),
28 
29     /// More than the exactly one allowed plane specified by the format
30     NonAsciiByteInHeader(u8),
31     /// The PAM header contained a non-ASCII byte
32     NonAsciiLineInPamHeader,
33     /// A sample string contained a non-ASCII byte
34     NonAsciiSample,
35 
36     /// The byte after the P7 magic was not 0x0A NEWLINE
37     NotNewlineAfterP7Magic(u8),
38     /// The PNM header had too few lines
39     UnexpectedPnmHeaderEnd,
40 
41     /// The specified line was specified twice
42     HeaderLineDuplicated(PnmHeaderLine),
43     /// The line with the specified ID was not understood
44     HeaderLineUnknown(String),
45     /// At least one of the required lines were missing from the header (are `None` here)
46     ///
47     /// Same names as [`PnmHeaderLine`](enum.PnmHeaderLine.html)
48     #[allow(missing_docs)]
49     HeaderLineMissing {
50         height: Option<u32>,
51         width: Option<u32>,
52         depth: Option<u32>,
53         maxval: Option<u32>,
54     },
55 
56     /// Not enough data was provided to the Decoder to decode the image
57     InputTooShort,
58     /// Sample raster contained unexpected byte
59     UnexpectedByteInRaster(u8),
60     /// Specified sample was out of bounds (e.g. >1 in B&W)
61     SampleOutOfBounds(u8),
62     /// The image's maxval exceeds 0xFFFF
63     MaxvalTooBig(u32),
64 
65     /// The specified tuple type supports restricted depths and maxvals, those restrictions were not met
66     InvalidDepthOrMaxval {
67         tuple_type: ArbitraryTuplType,
68         depth: u32,
69         maxval: u32,
70     },
71     /// The specified tuple type supports restricted depths, those restrictions were not met
72     InvalidDepth {
73         tuple_type: ArbitraryTuplType,
74         depth: u32,
75     },
76     /// The tuple type was not recognised by the parser
77     TupleTypeUnrecognised,
78 }
79 
80 impl Display for DecoderError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result81     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82         match self {
83             DecoderError::PnmMagicInvalid(magic) =>
84                 f.write_fmt(format_args!("Expected magic constant for PNM: P1..P7, got [{:#04X?}, {:#04X?}]", magic[0], magic[1])),
85             DecoderError::UnparsableValue(src, data, err) =>
86                 f.write_fmt(format_args!("Error parsing {:?} as {}: {}", data, src, err)),
87 
88             DecoderError::NonAsciiByteInHeader(c) =>
89                 f.write_fmt(format_args!("Non-ASCII character {:#04X?} in header", c)),
90             DecoderError::NonAsciiLineInPamHeader =>
91                 f.write_str("Non-ASCII line in PAM header"),
92             DecoderError::NonAsciiSample =>
93                 f.write_str("Non-ASCII character where sample value was expected"),
94 
95             DecoderError::NotNewlineAfterP7Magic(c) =>
96                 f.write_fmt(format_args!("Expected newline after P7 magic, got {:#04X?}", c)),
97             DecoderError::UnexpectedPnmHeaderEnd =>
98                 f.write_str("Unexpected end of PNM header"),
99 
100             DecoderError::HeaderLineDuplicated(line) =>
101                 f.write_fmt(format_args!("Duplicate {} line", line)),
102             DecoderError::HeaderLineUnknown(identifier) =>
103                 f.write_fmt(format_args!("Unknown header line with identifier {:?}", identifier)),
104             DecoderError::HeaderLineMissing { height, width, depth, maxval } =>
105                 f.write_fmt(format_args!("Missing header line: have height={:?}, width={:?}, depth={:?}, maxval={:?}", height, width, depth, maxval)),
106 
107             DecoderError::InputTooShort =>
108                 f.write_str("Not enough data was provided to the Decoder to decode the image"),
109             DecoderError::UnexpectedByteInRaster(c) =>
110                 f.write_fmt(format_args!("Unexpected character {:#04X?} within sample raster", c)),
111             DecoderError::SampleOutOfBounds(val) =>
112                 f.write_fmt(format_args!("Sample value {} outside of bounds", val)),
113             DecoderError::MaxvalTooBig(maxval) =>
114                 f.write_fmt(format_args!("Image MAXVAL exceeds {}: {}", 0xFFFF, maxval)),
115 
116             DecoderError::InvalidDepthOrMaxval { tuple_type, depth, maxval } =>
117                 f.write_fmt(format_args!("Invalid depth ({}) or maxval ({}) for tuple type {}", depth, maxval, tuple_type.name())),
118             DecoderError::InvalidDepth { tuple_type, depth } =>
119                 f.write_fmt(format_args!("Invalid depth ({}) for tuple type {}", depth, tuple_type.name())),
120             DecoderError::TupleTypeUnrecognised =>
121                 f.write_str("Tuple type not recognized"),
122         }
123     }
124 }
125 
126 /// Note: should `pnm` be extracted into a separate crate,
127 /// this will need to be hidden until that crate hits version `1.0`.
128 impl From<DecoderError> for ImageError {
from(e: DecoderError) -> ImageError129     fn from(e: DecoderError) -> ImageError {
130         ImageError::Decoding(DecodingError::new(ImageFormat::Pnm.into(), e))
131     }
132 }
133 
134 impl error::Error for DecoderError {
source(&self) -> Option<&(dyn error::Error + 'static)>135     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
136         match self {
137             DecoderError::UnparsableValue(_, _, err) => Some(err),
138             _ => None,
139         }
140     }
141 }
142 
143 /// Single-value lines in a PNM header
144 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
145 enum PnmHeaderLine {
146     /// "HEIGHT"
147     Height,
148     /// "WIDTH"
149     Width,
150     /// "DEPTH"
151     Depth,
152     /// "MAXVAL", a.k.a. `maxwhite`
153     Maxval,
154 }
155 
156 impl Display for PnmHeaderLine {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result157     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158         f.write_str(match self {
159             PnmHeaderLine::Height => "HEIGHT",
160             PnmHeaderLine::Width => "WIDTH",
161             PnmHeaderLine::Depth => "DEPTH",
162             PnmHeaderLine::Maxval => "MAXVAL",
163         })
164     }
165 }
166 
167 /// Single-value lines in a PNM header
168 #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
169 enum ErrorDataSource {
170     /// One of the header lines
171     Line(PnmHeaderLine),
172     /// Value in the preamble
173     Preamble,
174     /// Sample/pixel data
175     Sample,
176 }
177 
178 impl Display for ErrorDataSource {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result179     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180         match self {
181             ErrorDataSource::Line(l) => l.fmt(f),
182             ErrorDataSource::Preamble => f.write_str("number in preamble"),
183             ErrorDataSource::Sample => f.write_str("sample"),
184         }
185     }
186 }
187 
188 /// Dynamic representation, represents all decodable (sample, depth) combinations.
189 #[derive(Clone, Copy)]
190 enum TupleType {
191     PbmBit,
192     BWBit,
193     GrayU8,
194     GrayU16,
195     RGBU8,
196     RGBU16,
197 }
198 
199 trait Sample {
bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>200     fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>;
201 
202     /// It is guaranteed that `bytes.len() == bytelen(width, height, samples)`
from_bytes(bytes: &[u8], width: u32, height: u32, samples: u32) -> ImageResult<Vec<u8>>203     fn from_bytes(bytes: &[u8], width: u32, height: u32, samples: u32)
204         -> ImageResult<Vec<u8>>;
205 
from_ascii(reader: &mut dyn Read, width: u32, height: u32, samples: u32) -> ImageResult<Vec<u8>>206     fn from_ascii(reader: &mut dyn Read, width: u32, height: u32, samples: u32)
207         -> ImageResult<Vec<u8>>;
208 }
209 
210 struct U8;
211 struct U16;
212 struct PbmBit;
213 struct BWBit;
214 
215 trait DecodableImageHeader {
tuple_type(&self) -> ImageResult<TupleType>216     fn tuple_type(&self) -> ImageResult<TupleType>;
217 }
218 
219 /// PNM decoder
220 pub struct PnmDecoder<R> {
221     reader: BufReader<R>,
222     header: PnmHeader,
223     tuple: TupleType,
224 }
225 
226 impl<R: Read> PnmDecoder<R> {
227     /// Create a new decoder that decodes from the stream ```read```
new(read: R) -> ImageResult<PnmDecoder<R>>228     pub fn new(read: R) -> ImageResult<PnmDecoder<R>> {
229         let mut buf = BufReader::new(read);
230         let magic = buf.read_magic_constant()?;
231 
232         let subtype = match magic {
233             [b'P', b'1'] => PNMSubtype::Bitmap(SampleEncoding::Ascii),
234             [b'P', b'2'] => PNMSubtype::Graymap(SampleEncoding::Ascii),
235             [b'P', b'3'] => PNMSubtype::Pixmap(SampleEncoding::Ascii),
236             [b'P', b'4'] => PNMSubtype::Bitmap(SampleEncoding::Binary),
237             [b'P', b'5'] => PNMSubtype::Graymap(SampleEncoding::Binary),
238             [b'P', b'6'] => PNMSubtype::Pixmap(SampleEncoding::Binary),
239             [b'P', b'7'] => PNMSubtype::ArbitraryMap,
240             _ => return Err(DecoderError::PnmMagicInvalid(magic).into()),
241         };
242 
243         let decoder = match subtype {
244             PNMSubtype::Bitmap(enc) => PnmDecoder::read_bitmap_header(buf, enc),
245             PNMSubtype::Graymap(enc) => PnmDecoder::read_graymap_header(buf, enc),
246             PNMSubtype::Pixmap(enc) => PnmDecoder::read_pixmap_header(buf, enc),
247             PNMSubtype::ArbitraryMap => PnmDecoder::read_arbitrary_header(buf),
248         }?;
249 
250         if utils::check_dimension_overflow(
251             decoder.dimensions().0,
252             decoder.dimensions().1,
253             decoder.color_type().bytes_per_pixel(),
254         ) {
255             return Err(ImageError::Unsupported(
256                 UnsupportedError::from_format_and_kind(
257                     ImageFormat::Pnm.into(),
258                     UnsupportedErrorKind::GenericFeature(format!(
259                         "Image dimensions ({}x{}) are too large",
260                         decoder.dimensions().0,
261                         decoder.dimensions().1
262                     )),
263                 ),
264             ));
265         }
266 
267         Ok(decoder)
268     }
269 
270     /// Extract the reader and header after an image has been read.
into_inner(self) -> (R, PnmHeader)271     pub fn into_inner(self) -> (R, PnmHeader) {
272         (self.reader.into_inner(), self.header)
273     }
274 
read_bitmap_header( mut reader: BufReader<R>, encoding: SampleEncoding, ) -> ImageResult<PnmDecoder<R>>275     fn read_bitmap_header(
276         mut reader: BufReader<R>,
277         encoding: SampleEncoding,
278     ) -> ImageResult<PnmDecoder<R>> {
279         let header = reader.read_bitmap_header(encoding)?;
280         Ok(PnmDecoder {
281             reader,
282             tuple: TupleType::PbmBit,
283             header: PnmHeader {
284                 decoded: HeaderRecord::Bitmap(header),
285                 encoded: None,
286             },
287         })
288     }
289 
read_graymap_header( mut reader: BufReader<R>, encoding: SampleEncoding, ) -> ImageResult<PnmDecoder<R>>290     fn read_graymap_header(
291         mut reader: BufReader<R>,
292         encoding: SampleEncoding,
293     ) -> ImageResult<PnmDecoder<R>> {
294         let header = reader.read_graymap_header(encoding)?;
295         let tuple_type = header.tuple_type()?;
296         Ok(PnmDecoder {
297             reader,
298             tuple: tuple_type,
299             header: PnmHeader {
300                 decoded: HeaderRecord::Graymap(header),
301                 encoded: None,
302             },
303         })
304     }
305 
read_pixmap_header( mut reader: BufReader<R>, encoding: SampleEncoding, ) -> ImageResult<PnmDecoder<R>>306     fn read_pixmap_header(
307         mut reader: BufReader<R>,
308         encoding: SampleEncoding,
309     ) -> ImageResult<PnmDecoder<R>> {
310         let header = reader.read_pixmap_header(encoding)?;
311         let tuple_type = header.tuple_type()?;
312         Ok(PnmDecoder {
313             reader,
314             tuple: tuple_type,
315             header: PnmHeader {
316                 decoded: HeaderRecord::Pixmap(header),
317                 encoded: None,
318             },
319         })
320     }
321 
read_arbitrary_header(mut reader: BufReader<R>) -> ImageResult<PnmDecoder<R>>322     fn read_arbitrary_header(mut reader: BufReader<R>) -> ImageResult<PnmDecoder<R>> {
323         let header = reader.read_arbitrary_header()?;
324         let tuple_type = header.tuple_type()?;
325         Ok(PnmDecoder {
326             reader,
327             tuple: tuple_type,
328             header: PnmHeader {
329                 decoded: HeaderRecord::Arbitrary(header),
330                 encoded: None,
331             },
332         })
333     }
334 }
335 
336 trait HeaderReader: BufRead {
337     /// Reads the two magic constant bytes
read_magic_constant(&mut self) -> ImageResult<[u8; 2]>338     fn read_magic_constant(&mut self) -> ImageResult<[u8; 2]> {
339         let mut magic: [u8; 2] = [0, 0];
340         self.read_exact(&mut magic)?;
341         Ok(magic)
342     }
343 
344     /// Reads a string as well as a single whitespace after it, ignoring comments
read_next_string(&mut self) -> ImageResult<String>345     fn read_next_string(&mut self) -> ImageResult<String> {
346         let mut bytes = Vec::new();
347 
348         // pair input bytes with a bool mask to remove comments
349         let mark_comments = self.bytes().scan(true, |partof, read| {
350             let byte = match read {
351                 Err(err) => return Some((*partof, Err(err))),
352                 Ok(byte) => byte,
353             };
354             let cur_enabled = *partof && byte != b'#';
355             let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
356             *partof = next_enabled;
357             Some((cur_enabled, Ok(byte)))
358         });
359 
360         for (_, byte) in mark_comments.filter(|ref e| e.0) {
361             match byte {
362                 Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
363                     if !bytes.is_empty() {
364                         break; // We're done as we already have some content
365                     }
366                 }
367                 Ok(byte) if !byte.is_ascii() => return Err(DecoderError::NonAsciiByteInHeader(byte).into()),
368                 Ok(byte) => {
369                     bytes.push(byte);
370                 },
371                 Err(_) => break,
372             }
373         }
374 
375         if bytes.is_empty() {
376             return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into()));
377         }
378 
379         if !bytes.as_slice().is_ascii() {
380             // We have only filled the buffer with characters for which `byte.is_ascii()` holds.
381             unreachable!("Non-ASCII character should have returned sooner")
382         }
383 
384         let string = String::from_utf8(bytes)
385             // We checked the precondition ourselves a few lines before, `bytes.as_slice().is_ascii()`.
386             .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded"));
387 
388         Ok(string)
389     }
390 
391     /// Read the next line
read_next_line(&mut self) -> ImageResult<String>392     fn read_next_line(&mut self) -> ImageResult<String> {
393         let mut buffer = String::new();
394         self.read_line(&mut buffer)?;
395         Ok(buffer)
396     }
397 
read_next_u32(&mut self) -> ImageResult<u32>398     fn read_next_u32(&mut self) -> ImageResult<u32> {
399         let s = self.read_next_string()?;
400         s.parse::<u32>()
401             .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Preamble, s, err).into())
402     }
403 
read_bitmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<BitmapHeader>404     fn read_bitmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<BitmapHeader> {
405         let width = self.read_next_u32()?;
406         let height = self.read_next_u32()?;
407         Ok(BitmapHeader {
408             encoding,
409             width,
410             height,
411         })
412     }
413 
read_graymap_header(&mut self, encoding: SampleEncoding) -> ImageResult<GraymapHeader>414     fn read_graymap_header(&mut self, encoding: SampleEncoding) -> ImageResult<GraymapHeader> {
415         self.read_pixmap_header(encoding).map(
416             |PixmapHeader {
417                  encoding,
418                  width,
419                  height,
420                  maxval,
421              }| GraymapHeader {
422                 encoding,
423                 width,
424                 height,
425                 maxwhite: maxval,
426             },
427         )
428     }
429 
read_pixmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<PixmapHeader>430     fn read_pixmap_header(&mut self, encoding: SampleEncoding) -> ImageResult<PixmapHeader> {
431         let width = self.read_next_u32()?;
432         let height = self.read_next_u32()?;
433         let maxval = self.read_next_u32()?;
434         Ok(PixmapHeader {
435             encoding,
436             width,
437             height,
438             maxval,
439         })
440     }
441 
read_arbitrary_header(&mut self) -> ImageResult<ArbitraryHeader>442     fn read_arbitrary_header(&mut self) -> ImageResult<ArbitraryHeader> {
443         fn parse_single_value_line(line_val: &mut Option<u32>, rest: &str, line: PnmHeaderLine) -> ImageResult<()> {
444             if line_val.is_some() {
445                 Err(DecoderError::HeaderLineDuplicated(line).into())
446             } else {
447                 let v = rest.trim().parse().map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Line(line), rest.to_owned(), err))?;
448                 *line_val = Some(v);
449                 Ok(())
450             }
451         }
452 
453         match self.bytes().next() {
454             None => return Err(ImageError::IoError(io::ErrorKind::UnexpectedEof.into())),
455             Some(Err(io)) => return Err(ImageError::IoError(io)),
456             Some(Ok(b'\n')) => (),
457             Some(Ok(c)) => return Err(DecoderError::NotNewlineAfterP7Magic(c).into()),
458         }
459 
460         let mut line = String::new();
461         let mut height: Option<u32> = None;
462         let mut width: Option<u32> = None;
463         let mut depth: Option<u32> = None;
464         let mut maxval: Option<u32> = None;
465         let mut tupltype: Option<String> = None;
466         loop {
467             line.truncate(0);
468             let len = self.read_line(&mut line)?;
469             if len == 0 {
470                 return Err(DecoderError::UnexpectedPnmHeaderEnd.into());
471             }
472             if line.as_bytes()[0] == b'#' {
473                 continue;
474             }
475             if !line.is_ascii() {
476                 return Err(DecoderError::NonAsciiLineInPamHeader.into());
477             }
478             #[allow(deprecated)]
479             let (identifier, rest) = line.trim_left()
480                 .split_at(line.find(char::is_whitespace).unwrap_or_else(|| line.len()));
481             match identifier {
482                 "ENDHDR" => break,
483                 "HEIGHT" => parse_single_value_line(&mut height, rest, PnmHeaderLine::Height)?,
484                 "WIDTH" => parse_single_value_line(&mut width, rest, PnmHeaderLine::Width)?,
485                 "DEPTH" => parse_single_value_line(&mut depth, rest, PnmHeaderLine::Depth)?,
486                 "MAXVAL" => parse_single_value_line(&mut maxval, rest, PnmHeaderLine::Maxval)?,
487                 "TUPLTYPE" => {
488                     let identifier = rest.trim();
489                     if tupltype.is_some() {
490                         let appended = tupltype.take().map(|mut v| {
491                             v.push(' ');
492                             v.push_str(identifier);
493                             v
494                         });
495                         tupltype = appended;
496                     } else {
497                         tupltype = Some(identifier.to_string());
498                     }
499                 }
500                 _ => return Err(DecoderError::HeaderLineUnknown(identifier.to_string()).into()),
501             }
502         }
503 
504         let (h, w, d, m) = match (height, width, depth, maxval) {
505             (Some(h), Some(w), Some(d), Some(m)) => (h, w, d, m),
506             _ => return Err(DecoderError::HeaderLineMissing { height, width, depth, maxval }.into()),
507         };
508 
509         let tupltype = match tupltype {
510             None => None,
511             Some(ref t) if t == "BLACKANDWHITE" => Some(ArbitraryTuplType::BlackAndWhite),
512             Some(ref t) if t == "BLACKANDWHITE_ALPHA" => Some(ArbitraryTuplType::BlackAndWhiteAlpha),
513             Some(ref t) if t == "GRAYSCALE" => Some(ArbitraryTuplType::Grayscale),
514             Some(ref t) if t == "GRAYSCALE_ALPHA" => Some(ArbitraryTuplType::GrayscaleAlpha),
515             Some(ref t) if t == "RGB" => Some(ArbitraryTuplType::RGB),
516             Some(ref t) if t == "RGB_ALPHA" => Some(ArbitraryTuplType::RGBAlpha),
517             Some(other) => Some(ArbitraryTuplType::Custom(other)),
518         };
519 
520         Ok(ArbitraryHeader {
521             height: h,
522             width: w,
523             depth: d,
524             maxval: m,
525             tupltype,
526         })
527     }
528 }
529 
530 impl<R: Read> HeaderReader for BufReader<R> {}
531 
532 /// Wrapper struct around a `Cursor<Vec<u8>>`
533 pub struct PnmReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
534 impl<R> Read for PnmReader<R> {
read(&mut self, buf: &mut [u8]) -> io::Result<usize>535     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
536         self.0.read(buf)
537     }
read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize>538     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
539         if self.0.position() == 0 && buf.is_empty() {
540             mem::swap(buf, self.0.get_mut());
541             Ok(buf.len())
542         } else {
543             self.0.read_to_end(buf)
544         }
545     }
546 }
547 
548 impl<'a, R: 'a + Read> ImageDecoder<'a> for PnmDecoder<R> {
549     type Reader = PnmReader<R>;
550 
dimensions(&self) -> (u32, u32)551     fn dimensions(&self) -> (u32, u32) {
552         (self.header.width(), self.header.height())
553     }
554 
color_type(&self) -> ColorType555     fn color_type(&self) -> ColorType {
556         match self.tuple {
557             TupleType::PbmBit => ColorType::L8,
558             TupleType::BWBit => ColorType::L8,
559             TupleType::GrayU8 => ColorType::L8,
560             TupleType::GrayU16 => ColorType::L16,
561             TupleType::RGBU8 => ColorType::Rgb8,
562             TupleType::RGBU16 => ColorType::Rgb16,
563         }
564     }
565 
original_color_type(&self) -> ExtendedColorType566     fn original_color_type(&self) -> ExtendedColorType {
567         match self.tuple {
568             TupleType::PbmBit => ExtendedColorType::L1,
569             TupleType::BWBit => ExtendedColorType::L1,
570             TupleType::GrayU8 => ExtendedColorType::L8,
571             TupleType::GrayU16 => ExtendedColorType::L16,
572             TupleType::RGBU8 => ExtendedColorType::Rgb8,
573             TupleType::RGBU16 => ExtendedColorType::Rgb16,
574         }
575     }
576 
into_reader(self) -> ImageResult<Self::Reader>577     fn into_reader(self) -> ImageResult<Self::Reader> {
578         Ok(PnmReader(Cursor::new(image::decoder_to_vec(self)?), PhantomData))
579     }
580 
read_image(mut self, buf: &mut [u8]) -> ImageResult<()>581     fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
582         assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
583         buf.copy_from_slice(&match self.tuple {
584             TupleType::PbmBit => self.read_samples::<PbmBit>(1),
585             TupleType::BWBit => self.read_samples::<BWBit>(1),
586             TupleType::RGBU8 => self.read_samples::<U8>(3),
587             TupleType::RGBU16 => self.read_samples::<U16>(3),
588             TupleType::GrayU8 => self.read_samples::<U8>(1),
589             TupleType::GrayU16 => self.read_samples::<U16>(1),
590         }?);
591         Ok(())
592     }
593 }
594 
595 impl<R: Read> PnmDecoder<R> {
read_samples<S: Sample>(&mut self, components: u32) -> ImageResult<Vec<u8>>596     fn read_samples<S: Sample>(&mut self, components: u32) -> ImageResult<Vec<u8>> {
597         match self.subtype().sample_encoding() {
598             SampleEncoding::Binary => {
599                 let width = self.header.width();
600                 let height = self.header.height();
601                 let bytecount = S::bytelen(width, height, components)?;
602                 let mut bytes = vec![];
603 
604                 self.reader
605                     .by_ref()
606                     // This conversion is potentially lossy but unlikely and in that case we error
607                     // later anyways.
608                     .take(bytecount as u64)
609                     .read_to_end(&mut bytes)?;
610 
611                 if bytes.len() != bytecount {
612                     return Err(DecoderError::InputTooShort.into());
613                 }
614 
615                 let samples = S::from_bytes(&bytes, width, height, components)?;
616                 Ok(samples)
617             }
618             SampleEncoding::Ascii => {
619                 let samples = self.read_ascii::<S>(components)?;
620                 Ok(samples)
621             }
622         }
623     }
624 
read_ascii<Basic: Sample>(&mut self, components: u32) -> ImageResult<Vec<u8>>625     fn read_ascii<Basic: Sample>(&mut self, components: u32) -> ImageResult<Vec<u8>> {
626         Basic::from_ascii(&mut self.reader, self.header.width(), self.header.height(), components)
627     }
628 
629     /// Get the pnm subtype, depending on the magic constant contained in the header
subtype(&self) -> PNMSubtype630     pub fn subtype(&self) -> PNMSubtype {
631         self.header.subtype()
632     }
633 }
634 
read_separated_ascii<T: FromStr<Err = ParseIntError>>(reader: &mut dyn Read) -> ImageResult<T> where T::Err: Display635 fn read_separated_ascii<T: FromStr<Err = ParseIntError>>(reader: &mut dyn Read) -> ImageResult<T>
636     where T::Err: Display
637 {
638     let is_separator = |v: &u8| match *v {
639         b'\t' | b'\n' | b'\x0b' | b'\x0c' | b'\r' | b' ' => true,
640         _ => false,
641     };
642 
643     let token = reader
644         .bytes()
645         .skip_while(|v| v.as_ref().ok().map(&is_separator).unwrap_or(false))
646         .take_while(|v| v.as_ref().ok().map(|c| !is_separator(c)).unwrap_or(false))
647         .collect::<Result<Vec<u8>, _>>()?;
648 
649     if !token.is_ascii() {
650         return Err(DecoderError::NonAsciiSample.into());
651     }
652 
653     let string = str::from_utf8(&token)
654         // We checked the precondition ourselves a few lines before with `token.is_ascii()`.
655         .unwrap_or_else(|_| unreachable!("Only ASCII characters should be decoded"));
656 
657     string.parse()
658           .map_err(|err| DecoderError::UnparsableValue(ErrorDataSource::Sample, string.to_owned(), err).into())
659 }
660 
661 impl Sample for U8 {
bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>662     fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> {
663         Ok((width * height * samples) as usize)
664     }
665 
from_bytes( bytes: &[u8], width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>666     fn from_bytes(
667         bytes: &[u8],
668         width: u32,
669         height: u32,
670         samples: u32,
671     ) -> ImageResult<Vec<u8>> {
672         assert_eq!(bytes.len(), Self::bytelen(width, height, samples).unwrap());
673         Ok(bytes.to_vec())
674     }
675 
from_ascii( reader: &mut dyn Read, width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>676     fn from_ascii(
677         reader: &mut dyn Read,
678         width: u32,
679         height: u32,
680         samples: u32,
681     ) -> ImageResult<Vec<u8>> {
682         (0..width*height*samples)
683             .map(|_| read_separated_ascii(reader))
684             .collect()
685     }
686 }
687 
688 impl Sample for U16 {
bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>689     fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> {
690         Ok((width * height * samples * 2) as usize)
691     }
692 
from_bytes( bytes: &[u8], width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>693     fn from_bytes(
694         bytes: &[u8],
695         width: u32,
696         height: u32,
697         samples: u32,
698     ) -> ImageResult<Vec<u8>> {
699         assert_eq!(bytes.len(), Self::bytelen(width, height, samples).unwrap());
700 
701         let mut buffer = bytes.to_vec();
702         for chunk in buffer.chunks_mut(2) {
703             let v = BigEndian::read_u16(chunk);
704             NativeEndian::write_u16(chunk, v);
705         }
706         Ok(buffer)
707     }
708 
from_ascii( reader: &mut dyn Read, width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>709     fn from_ascii(
710         reader: &mut dyn Read,
711         width: u32,
712         height: u32,
713         samples: u32,
714     ) -> ImageResult<Vec<u8>> {
715         let mut buffer = vec![0; (width * height * samples * 2) as usize];
716         for i in 0..(width*height*samples) as usize {
717             let v = read_separated_ascii::<u16>(reader)?;
718             NativeEndian::write_u16(&mut buffer[2*i..][..2], v);
719         }
720         Ok(buffer)
721     }
722 }
723 
724 // The image is encoded in rows of bits, high order bits first. Any bits beyond the row bits should
725 // be ignored. Also, contrary to rgb, black pixels are encoded as a 1 while white is 0. This will
726 // need to be reversed for the grayscale output.
727 impl Sample for PbmBit {
bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>728     fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> {
729         let count = width * samples;
730         let linelen = (count / 8) + ((count % 8) != 0) as u32;
731         Ok((linelen * height) as usize)
732     }
733 
from_bytes( bytes: &[u8], width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>734     fn from_bytes(
735         bytes: &[u8],
736         width: u32,
737         height: u32,
738         samples: u32,
739     ) -> ImageResult<Vec<u8>> {
740         assert_eq!(bytes.len(), Self::bytelen(width, height, samples).unwrap());
741 
742         let mut expanded = utils::expand_bits(1, width * samples, bytes);
743         for b in expanded.iter_mut() {
744             *b = !*b;
745         }
746         Ok(expanded)
747     }
748 
from_ascii( reader: &mut dyn Read, width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>749     fn from_ascii(
750         reader: &mut dyn Read,
751         width: u32,
752         height: u32,
753         samples: u32,
754     ) -> ImageResult<Vec<u8>> {
755         let count = (width*height*samples) as usize;
756         let raw_samples = reader.bytes()
757             .filter_map(|ascii| match ascii {
758                 Ok(b'0') => Some(Ok(255)),
759                 Ok(b'1') => Some(Ok(0)),
760                 Err(err) => Some(Err(ImageError::IoError(err))),
761                 Ok(b'\t')
762                 | Ok(b'\n')
763                 | Ok(b'\x0b')
764                 | Ok(b'\x0c')
765                 | Ok(b'\r')
766                 | Ok(b' ') => None,
767                 Ok(c) => Some(Err(DecoderError::UnexpectedByteInRaster(c).into())),
768             })
769             .take(count)
770             .collect::<ImageResult<Vec<u8>>>()?;
771 
772         if raw_samples.len() < count {
773             return Err(DecoderError::InputTooShort.into());
774         }
775 
776         Ok(raw_samples)
777     }
778 }
779 
780 // Encoded just like a normal U8 but we check the values.
781 impl Sample for BWBit {
bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize>782     fn bytelen(width: u32, height: u32, samples: u32) -> ImageResult<usize> {
783         U8::bytelen(width, height, samples)
784     }
785 
from_bytes( bytes: &[u8], width: u32, height: u32, samples: u32, ) -> ImageResult<Vec<u8>>786     fn from_bytes(
787         bytes: &[u8],
788         width: u32,
789         height: u32,
790         samples: u32,
791     ) -> ImageResult<Vec<u8>> {
792         assert_eq!(bytes.len(), Self::bytelen(width, height, samples).unwrap());
793 
794         let values = U8::from_bytes(bytes, width, height, samples)?;
795         if let Some(val) = values.iter().find(|&val| *val > 1) {
796             return Err(DecoderError::SampleOutOfBounds(*val).into());
797         }
798         Ok(values)
799     }
800 
from_ascii( _reader: &mut dyn Read, _width: u32, _height: u32, _samples: u32, ) -> ImageResult<Vec<u8>>801     fn from_ascii(
802         _reader: &mut dyn Read,
803         _width: u32,
804         _height: u32,
805         _samples: u32,
806     ) -> ImageResult<Vec<u8>> {
807         unreachable!("BW bits from anymaps are never encoded as ASCII")
808     }
809 }
810 
811 impl DecodableImageHeader for BitmapHeader {
tuple_type(&self) -> ImageResult<TupleType>812     fn tuple_type(&self) -> ImageResult<TupleType> {
813         Ok(TupleType::PbmBit)
814     }
815 }
816 
817 impl DecodableImageHeader for GraymapHeader {
tuple_type(&self) -> ImageResult<TupleType>818     fn tuple_type(&self) -> ImageResult<TupleType> {
819         match self.maxwhite {
820             v if v <= 0xFF => Ok(TupleType::GrayU8),
821             v if v <= 0xFFFF => Ok(TupleType::GrayU16),
822             _ => Err(DecoderError::MaxvalTooBig(self.maxwhite).into()),
823         }
824     }
825 }
826 
827 impl DecodableImageHeader for PixmapHeader {
tuple_type(&self) -> ImageResult<TupleType>828     fn tuple_type(&self) -> ImageResult<TupleType> {
829         match self.maxval {
830             v if v <= 0xFF => Ok(TupleType::RGBU8),
831             v if v <= 0xFFFF => Ok(TupleType::RGBU16),
832             _ => Err(DecoderError::MaxvalTooBig(self.maxval).into()),
833         }
834     }
835 }
836 
837 impl DecodableImageHeader for ArbitraryHeader {
tuple_type(&self) -> ImageResult<TupleType>838     fn tuple_type(&self) -> ImageResult<TupleType> {
839         match self.tupltype {
840             None if self.depth == 1 => Ok(TupleType::GrayU8),
841             None if self.depth == 2 => Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
842                 ImageFormat::Pnm.into(),
843                 UnsupportedErrorKind::Color(ExtendedColorType::La8),
844             ))),
845             None if self.depth == 3 => Ok(TupleType::RGBU8),
846             None if self.depth == 4 => Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
847                 ImageFormat::Pnm.into(),
848                 UnsupportedErrorKind::Color(ExtendedColorType::Rgba8),
849             ))),
850 
851             Some(ArbitraryTuplType::BlackAndWhite) if self.maxval == 1 && self.depth == 1 => {
852                 Ok(TupleType::BWBit)
853             }
854             Some(ArbitraryTuplType::BlackAndWhite) => Err(DecoderError::InvalidDepthOrMaxval {
855                 tuple_type: ArbitraryTuplType::BlackAndWhite,
856                 maxval: self.maxval,
857                 depth: self.depth,
858             }.into()),
859 
860             Some(ArbitraryTuplType::Grayscale) if self.depth == 1 && self.maxval <= 0xFF => {
861                 Ok(TupleType::GrayU8)
862             }
863             Some(ArbitraryTuplType::Grayscale) if self.depth <= 1 && self.maxval <= 0xFFFF => {
864                 Ok(TupleType::GrayU16)
865             }
866             Some(ArbitraryTuplType::Grayscale) => Err(DecoderError::InvalidDepthOrMaxval {
867                 tuple_type: ArbitraryTuplType::Grayscale,
868                 maxval: self.maxval,
869                 depth: self.depth,
870             }.into()),
871 
872             Some(ArbitraryTuplType::RGB) if self.depth == 3 && self.maxval <= 0xFF => {
873                 Ok(TupleType::RGBU8)
874             }
875             Some(ArbitraryTuplType::RGB) if self.depth == 3 && self.maxval <= 0xFFFF => {
876                 Ok(TupleType::RGBU16)
877             }
878             Some(ArbitraryTuplType::RGB) => Err(DecoderError::InvalidDepth {
879                 tuple_type: ArbitraryTuplType::RGB,
880                 depth: self.depth,
881             }.into()),
882 
883             Some(ArbitraryTuplType::BlackAndWhiteAlpha) => {
884                 Err(ImageError::Unsupported(UnsupportedError::from_format_and_kind(
885                     ImageFormat::Pnm.into(),
886                     UnsupportedErrorKind::GenericFeature(
887                         format!("Color type {}", ArbitraryTuplType::BlackAndWhiteAlpha.name())),
888                 )))
889             }
890             Some(ArbitraryTuplType::GrayscaleAlpha) => Err(ImageError::Unsupported(
891                 UnsupportedError::from_format_and_kind(
892                     ImageFormat::Pnm.into(),
893                     UnsupportedErrorKind::Color(ExtendedColorType::La8),
894                 ),
895             )),
896             Some(ArbitraryTuplType::RGBAlpha) => Err(ImageError::Unsupported(
897                 UnsupportedError::from_format_and_kind(
898                     ImageFormat::Pnm.into(),
899                     UnsupportedErrorKind::Color(ExtendedColorType::Rgba8),
900                 ),
901             )),
902             Some(ArbitraryTuplType::Custom(ref custom)) => Err(ImageError::Unsupported(
903                 UnsupportedError::from_format_and_kind(
904                     ImageFormat::Pnm.into(),
905                     UnsupportedErrorKind::GenericFeature(format!(
906                         "Tuple type {:?}",
907                         custom
908                     )),
909                 ),
910             )),
911             None => Err(DecoderError::TupleTypeUnrecognised.into()),
912         }
913     }
914 }
915 
916 #[cfg(test)]
917 mod tests {
918     use super::*;
919     /// Tests reading of a valid blackandwhite pam
920     #[test]
pam_blackandwhite()921     fn pam_blackandwhite() {
922         let pamdata = b"P7
923 WIDTH 4
924 HEIGHT 4
925 DEPTH 1
926 MAXVAL 1
927 TUPLTYPE BLACKANDWHITE
928 # Comment line
929 ENDHDR
930 \x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01\x01\x00\x00\x01";
931         let decoder = PnmDecoder::new(&pamdata[..]).unwrap();
932         assert_eq!(decoder.color_type(), ColorType::L8);
933         assert_eq!(decoder.original_color_type(), ExtendedColorType::L1);
934         assert_eq!(decoder.dimensions(), (4, 4));
935         assert_eq!(decoder.subtype(), PNMSubtype::ArbitraryMap);
936 
937         let mut image = vec![0; decoder.total_bytes() as usize];
938         decoder.read_image(&mut image).unwrap();
939         assert_eq!(
940             image,
941             vec![0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00,
942                  0x00, 0x01]
943         );
944         match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() {
945             (
946                 _,
947                 PnmHeader {
948                     decoded:
949                         HeaderRecord::Arbitrary(ArbitraryHeader {
950                             width: 4,
951                             height: 4,
952                             maxval: 1,
953                             depth: 1,
954                             tupltype: Some(ArbitraryTuplType::BlackAndWhite),
955                         }),
956                     encoded: _,
957                 },
958             ) => (),
959             _ => panic!("Decoded header is incorrect"),
960         }
961     }
962 
963     /// Tests reading of a valid grayscale pam
964     #[test]
pam_grayscale()965     fn pam_grayscale() {
966         let pamdata = b"P7
967 WIDTH 4
968 HEIGHT 4
969 DEPTH 1
970 MAXVAL 255
971 TUPLTYPE GRAYSCALE
972 # Comment line
973 ENDHDR
974 \xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
975         let decoder = PnmDecoder::new(&pamdata[..]).unwrap();
976         assert_eq!(decoder.color_type(), ColorType::L8);
977         assert_eq!(decoder.dimensions(), (4, 4));
978         assert_eq!(decoder.subtype(), PNMSubtype::ArbitraryMap);
979 
980         let mut image = vec![0; decoder.total_bytes() as usize];
981         decoder.read_image(&mut image).unwrap();
982         assert_eq!(
983             image,
984             vec![0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad,
985                  0xbe, 0xef]
986         );
987         match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() {
988             (
989                 _,
990                 PnmHeader {
991                     decoded:
992                         HeaderRecord::Arbitrary(ArbitraryHeader {
993                             width: 4,
994                             height: 4,
995                             depth: 1,
996                             maxval: 255,
997                             tupltype: Some(ArbitraryTuplType::Grayscale),
998                         }),
999                     encoded: _,
1000                 },
1001             ) => (),
1002             _ => panic!("Decoded header is incorrect"),
1003         }
1004     }
1005 
1006     /// Tests reading of a valid rgb pam
1007     #[test]
pam_rgb()1008     fn pam_rgb() {
1009         let pamdata = b"P7
1010 # Comment line
1011 MAXVAL 255
1012 TUPLTYPE RGB
1013 DEPTH 3
1014 WIDTH 2
1015 HEIGHT 2
1016 ENDHDR
1017 \xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
1018         let decoder = PnmDecoder::new(&pamdata[..]).unwrap();
1019         assert_eq!(decoder.color_type(), ColorType::Rgb8);
1020         assert_eq!(decoder.dimensions(), (2, 2));
1021         assert_eq!(decoder.subtype(), PNMSubtype::ArbitraryMap);
1022 
1023         let mut image = vec![0; decoder.total_bytes() as usize];
1024         decoder.read_image(&mut image).unwrap();
1025         assert_eq!(image,
1026                    vec![0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef]);
1027         match PnmDecoder::new(&pamdata[..]).unwrap().into_inner() {
1028             (
1029                 _,
1030                 PnmHeader {
1031                     decoded:
1032                         HeaderRecord::Arbitrary(ArbitraryHeader {
1033                             maxval: 255,
1034                             tupltype: Some(ArbitraryTuplType::RGB),
1035                             depth: 3,
1036                             width: 2,
1037                             height: 2,
1038                         }),
1039                     encoded: _,
1040                 },
1041             ) => (),
1042             _ => panic!("Decoded header is incorrect"),
1043         }
1044     }
1045 
1046     #[test]
pbm_binary()1047     fn pbm_binary() {
1048         // The data contains two rows of the image (each line is padded to the full byte). For
1049         // comments on its format, see documentation of `impl SampleType for PbmBit`.
1050         let pbmbinary = [&b"P4 6 2\n"[..], &[0b01101100 as u8, 0b10110111]].concat();
1051         let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap();
1052         assert_eq!(decoder.color_type(), ColorType::L8);
1053         assert_eq!(decoder.original_color_type(), ExtendedColorType::L1);
1054         assert_eq!(decoder.dimensions(), (6, 2));
1055         assert_eq!(
1056             decoder.subtype(),
1057             PNMSubtype::Bitmap(SampleEncoding::Binary)
1058         );
1059         let mut image = vec![0; decoder.total_bytes() as usize];
1060         decoder.read_image(&mut image).unwrap();
1061         assert_eq!(image, vec![255, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 0]);
1062         match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() {
1063             (
1064                 _,
1065                 PnmHeader {
1066                     decoded:
1067                         HeaderRecord::Bitmap(BitmapHeader {
1068                             encoding: SampleEncoding::Binary,
1069                             width: 6,
1070                             height: 2,
1071                         }),
1072                     encoded: _,
1073                 },
1074             ) => (),
1075             _ => panic!("Decoded header is incorrect"),
1076         }
1077     }
1078 
1079     /// A previous inifite loop.
1080     #[test]
pbm_binary_ascii_termination()1081     fn pbm_binary_ascii_termination() {
1082         use std::io::{Cursor, Error, ErrorKind, Read, Result};
1083         struct FailRead(Cursor<&'static [u8]>);
1084 
1085         impl Read for FailRead {
1086             fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
1087                 match self.0.read(buf) {
1088                     Ok(n) if n > 0 => Ok(n),
1089                     _ => Err(Error::new(
1090                         ErrorKind::BrokenPipe,
1091                         "Simulated broken pipe error"
1092                     )),
1093                 }
1094             }
1095         }
1096 
1097         let pbmbinary = FailRead(Cursor::new(b"P1 1 1\n"));
1098 
1099         let decoder = PnmDecoder::new(pbmbinary).unwrap();
1100         let mut image = vec![0; decoder.total_bytes() as usize];
1101         decoder.read_image(&mut image).expect_err("Image is malformed");
1102     }
1103 
1104     #[test]
pbm_ascii()1105     fn pbm_ascii() {
1106         // The data contains two rows of the image (each line is padded to the full byte). For
1107         // comments on its format, see documentation of `impl SampleType for PbmBit`.  Tests all
1108         // whitespace characters that should be allowed (the 6 characters according to POSIX).
1109         let pbmbinary = b"P1 6 2\n 0 1 1 0 1 1\n1 0 1 1 0\t\n\x0b\x0c\r1";
1110         let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap();
1111         assert_eq!(decoder.color_type(), ColorType::L8);
1112         assert_eq!(decoder.original_color_type(), ExtendedColorType::L1);
1113         assert_eq!(decoder.dimensions(), (6, 2));
1114         assert_eq!(decoder.subtype(), PNMSubtype::Bitmap(SampleEncoding::Ascii));
1115 
1116         let mut image = vec![0; decoder.total_bytes() as usize];
1117         decoder.read_image(&mut image).unwrap();
1118         assert_eq!(image, vec![255, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 0]);
1119         match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() {
1120             (
1121                 _,
1122                 PnmHeader {
1123                     decoded:
1124                         HeaderRecord::Bitmap(BitmapHeader {
1125                             encoding: SampleEncoding::Ascii,
1126                             width: 6,
1127                             height: 2,
1128                         }),
1129                     encoded: _,
1130                 },
1131             ) => (),
1132             _ => panic!("Decoded header is incorrect"),
1133         }
1134     }
1135 
1136     #[test]
pbm_ascii_nospace()1137     fn pbm_ascii_nospace() {
1138         // The data contains two rows of the image (each line is padded to the full byte). Notably,
1139         // it is completely within specification for the ascii data not to contain separating
1140         // whitespace for the pbm format or any mix.
1141         let pbmbinary = b"P1 6 2\n011011101101";
1142         let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap();
1143         assert_eq!(decoder.color_type(), ColorType::L8);
1144         assert_eq!(decoder.original_color_type(), ExtendedColorType::L1);
1145         assert_eq!(decoder.dimensions(), (6, 2));
1146         assert_eq!(decoder.subtype(), PNMSubtype::Bitmap(SampleEncoding::Ascii));
1147 
1148         let mut image = vec![0; decoder.total_bytes() as usize];
1149         decoder.read_image(&mut image).unwrap();
1150         assert_eq!(image, vec![255, 0, 0, 255, 0, 0, 0, 255, 0, 0, 255, 0]);
1151         match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() {
1152             (
1153                 _,
1154                 PnmHeader {
1155                     decoded:
1156                         HeaderRecord::Bitmap(BitmapHeader {
1157                             encoding: SampleEncoding::Ascii,
1158                             width: 6,
1159                             height: 2,
1160                         }),
1161                     encoded: _,
1162                 },
1163             ) => (),
1164             _ => panic!("Decoded header is incorrect"),
1165         }
1166     }
1167 
1168     #[test]
pgm_binary()1169     fn pgm_binary() {
1170         // The data contains two rows of the image (each line is padded to the full byte). For
1171         // comments on its format, see documentation of `impl SampleType for PbmBit`.
1172         let elements = (0..16).collect::<Vec<_>>();
1173         let pbmbinary = [&b"P5 4 4 255\n"[..], &elements].concat();
1174         let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap();
1175         assert_eq!(decoder.color_type(), ColorType::L8);
1176         assert_eq!(decoder.dimensions(), (4, 4));
1177         assert_eq!(
1178             decoder.subtype(),
1179             PNMSubtype::Graymap(SampleEncoding::Binary)
1180         );
1181         let mut image = vec![0; decoder.total_bytes() as usize];
1182         decoder.read_image(&mut image).unwrap();
1183         assert_eq!(image, elements);
1184         match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() {
1185             (
1186                 _,
1187                 PnmHeader {
1188                     decoded:
1189                         HeaderRecord::Graymap(GraymapHeader {
1190                             encoding: SampleEncoding::Binary,
1191                             width: 4,
1192                             height: 4,
1193                             maxwhite: 255,
1194                         }),
1195                     encoded: _,
1196                 },
1197             ) => (),
1198             _ => panic!("Decoded header is incorrect"),
1199         }
1200     }
1201 
1202     #[test]
pgm_ascii()1203     fn pgm_ascii() {
1204         // The data contains two rows of the image (each line is padded to the full byte). For
1205         // comments on its format, see documentation of `impl SampleType for PbmBit`.
1206         let pbmbinary = b"P2 4 4 255\n 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15";
1207         let decoder = PnmDecoder::new(&pbmbinary[..]).unwrap();
1208         assert_eq!(decoder.color_type(), ColorType::L8);
1209         assert_eq!(decoder.dimensions(), (4, 4));
1210         assert_eq!(
1211             decoder.subtype(),
1212             PNMSubtype::Graymap(SampleEncoding::Ascii)
1213         );
1214         let mut image = vec![0; decoder.total_bytes() as usize];
1215         decoder.read_image(&mut image).unwrap();
1216         assert_eq!(image, (0..16).collect::<Vec<_>>());
1217         match PnmDecoder::new(&pbmbinary[..]).unwrap().into_inner() {
1218             (
1219                 _,
1220                 PnmHeader {
1221                     decoded:
1222                         HeaderRecord::Graymap(GraymapHeader {
1223                             encoding: SampleEncoding::Ascii,
1224                             width: 4,
1225                             height: 4,
1226                             maxwhite: 255,
1227                         }),
1228                     encoded: _,
1229                 },
1230             ) => (),
1231             _ => panic!("Decoded header is incorrect"),
1232         }
1233     }
1234 
1235     #[test]
dimension_overflow()1236     fn dimension_overflow() {
1237         let pamdata = b"P7
1238 # Comment line
1239 MAXVAL 255
1240 TUPLTYPE RGB
1241 DEPTH 3
1242 WIDTH 4294967295
1243 HEIGHT 4294967295
1244 ENDHDR
1245 \xde\xad\xbe\xef\xde\xad\xbe\xef\xde\xad\xbe\xef";
1246 
1247         assert!(PnmDecoder::new(&pamdata[..]).is_err());
1248     }
1249 }
1250