Coverage Report

Created: 2025-07-18 06:49

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