Coverage Report

Created: 2025-10-10 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mp4san/webpsan/src/parse/lossless.rs
Line
Count
Source
1
#![allow(missing_docs)]
2
3
use std::fmt::Debug;
4
use std::io::Read;
5
use std::num::{NonZeroU32, NonZeroU8};
6
7
use bitstream_io::{Numeric, LE};
8
use derive_more::Display;
9
use mediasan_common::{ensure_attach, ensure_matches_attach};
10
use num_integer::div_ceil;
11
use num_traits::AsPrimitive;
12
13
use crate::{Error, ResultExt};
14
15
use super::bitstream::{BitBufReader, CanonicalHuffmanTree, LZ77_MAX_LEN};
16
use super::ParseError;
17
18
#[derive(Clone)]
19
pub struct LosslessImage {
20
    _image: SpatiallyCodedImage,
21
}
22
23
//
24
// private types
25
//
26
27
#[derive(Clone, Display, PartialEq, Eq)]
28
enum Transform {
29
    #[display("predictor transform: block size {block_size}")]
30
    Predictor { block_size: u16, _image: EntropyCodedImage },
31
    #[display("color transform: block size {block_size}")]
32
    Color { block_size: u16, _image: EntropyCodedImage },
33
    #[display("subtract green transform")]
34
    SubtractGreen,
35
    #[display("color indexing transform: {} colors", "image.width")]
36
    ColorIndexing { image: EntropyCodedImage },
37
}
38
39
#[repr(u8)]
40
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq, PartialOrd, Ord)]
41
enum TransformType {
42
    #[display("predictor")]
43
    Predictor = 0b00,
44
    #[display("color")]
45
    Color = 0b01,
46
    #[display("subtract green")]
47
    SubtractGreen = 0b10,
48
    #[display("color indexing")]
49
    ColorIndexing = 0b11,
50
}
51
52
#[derive(Clone, PartialEq, Eq)]
53
struct EntropyCodedImage {
54
    width: NonZeroU32,
55
    height: NonZeroU32,
56
}
57
58
#[derive(Clone, PartialEq, Eq)]
59
struct SpatiallyCodedImage;
60
61
#[derive(Clone, Copy, Debug, Display, PartialEq, Eq)]
62
#[display("distance {dist} length {len}")]
63
struct BackReference {
64
    dist: NonZeroU32,
65
    len: NonZeroU32,
66
}
67
68
#[derive(Clone, Copy, Debug, Default, Display, PartialEq, Eq)]
69
#[display("({alpha}, {red}, {green}, {blue})")]
70
struct Color {
71
    alpha: u8,
72
    red: u8,
73
    green: u8,
74
    blue: u8,
75
}
76
77
#[derive(Clone)]
78
struct ColorCache {
79
    order: Option<NonZeroU8>,
80
}
81
82
#[derive(Clone, Display, PartialEq, Eq)]
83
enum MetaPrefixCodes {
84
    #[display("single meta prefix code")]
85
    Single,
86
    #[display("multiple meta prefix codes: max code group {max_code_group}, block size {block_size}")]
87
    Multiple {
88
        block_size: u16,
89
        max_code_group: u16,
90
        _image: EntropyCodedImage,
91
    },
92
}
93
94
trait PrefixCode {
95
    type Symbol: Numeric;
96
97
    fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self;
98
99
    fn alphabet_size(color_cache_len: u16) -> u16;
100
}
101
102
struct PrefixCodeGroup {
103
    green: GreenPrefixCode,
104
    red: ARBPrefixCode,
105
    blue: ARBPrefixCode,
106
    alpha: ARBPrefixCode,
107
    distance: DistancePrefixCode,
108
}
109
110
struct CodeLengthPrefixCode {
111
    tree: CanonicalHuffmanTree<LE, u8>,
112
}
113
114
struct GreenPrefixCode {
115
    tree: CanonicalHuffmanTree<LE, u16>,
116
}
117
118
struct ARBPrefixCode {
119
    tree: CanonicalHuffmanTree<LE, u8>,
120
}
121
122
struct DistancePrefixCode {
123
    tree: CanonicalHuffmanTree<LE, u8>,
124
}
125
126
#[derive(Clone, Copy, Debug, Display)]
127
#[display("out-of-bounds color cache index `{_0}` >= `{_1}`")]
128
struct ColorCacheIndexOutOfBounds(u16, u16);
129
130
#[derive(Clone, Copy, Debug, Display)]
131
#[display("invalid back-reference distance `{_0}` at pixel `{_1}`")]
132
struct InvalidBackRefDistance(NonZeroU32, u32);
133
134
#[derive(Clone, Copy, Debug, Display)]
135
#[display("invalid back-reference length `{_0}` at pixel `{_1}` with image length `{_2}`")]
136
struct InvalidBackRefLength(NonZeroU32, u32, u32);
137
138
#[derive(Clone, Copy, Debug, Display)]
139
#[display("invalid code length repetition `{_0}` at `{_1}` with max symbols `{_2}`")]
140
struct InvalidCodeLengthRepetition(u8, usize, u16);
141
142
#[derive(Clone, Copy, Debug, Display)]
143
#[display("invalid color cache size `{_0}`")]
144
struct InvalidColorCacheSize(u8);
145
146
#[derive(Clone, Copy, Debug, Display)]
147
#[display("invalid duplicate {_0} transform")]
148
struct InvalidDuplicateTransform(TransformType);
149
150
#[derive(Clone, Copy, Debug, Display)]
151
#[display("invalid predictor `{_0}`")]
152
struct InvalidPredictor(u8);
153
154
#[derive(Clone, Copy, Debug, Display)]
155
#[display("invalid symbol count `{_0}` >= `{_1}`")]
156
struct InvalidSymbolCount(u16, u16);
157
158
#[derive(Clone, Copy, Debug, Display)]
159
#[display("while parsing {_0} transform")]
160
struct WhileParsingTransform(TransformType);
161
162
//
163
// LosslessImage impls
164
//
165
166
impl LosslessImage {
167
5.66k
    pub fn read<R: Read>(
168
5.66k
        reader: &mut BitBufReader<R, LE>,
169
5.66k
        width: NonZeroU32,
170
5.66k
        height: NonZeroU32,
171
5.66k
    ) -> Result<Self, Error> {
172
5.66k
        let mut transformed_width = width;
173
5.66k
        let mut transforms = [false; TransformType::COUNT];
174
7.99k
        while reader.read_bit()? {
175
3.97k
            let transform = Transform::read(reader, transformed_width, height).while_parsing_type()?;
176
177
2.37k
            transformed_width = transform.transformed_width(transformed_width);
178
179
2.37k
            ensure_attach!(
180
2.37k
                !transforms[transform.transform_type() as usize],
181
33
                ParseError::InvalidInput,
182
33
                InvalidDuplicateTransform(transform.transform_type()),
183
            );
184
185
2.33k
            transforms[transform.transform_type() as usize] = true;
186
2.33k
            log::info!("{transform}");
187
        }
188
189
3.93k
        let _image = SpatiallyCodedImage::read(reader, transformed_width, height).while_parsing_type()?;
190
191
597
        Ok(Self { _image })
192
5.66k
    }
193
}
194
195
//
196
// Transform impls
197
//
198
199
impl Transform {
200
3.97k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>, width: NonZeroU32, height: NonZeroU32) -> Result<Self, Error> {
201
3.97k
        match TransformType::read(reader)? {
202
862
            transform @ TransformType::Predictor => {
203
862
                let block_order = 2 + reader
204
862
                    .read::<u32>(3)
205
862
                    .attach_printable(WhileParsingTransform(transform))?;
206
852
                let block_size = 2u16.pow(block_order);
207
852
                let width_in_blocks = len_in_blocks(width, block_size);
208
852
                let height_in_blocks = len_in_blocks(height, block_size);
209
5.15M
                let _image = EntropyCodedImage::read(reader, width_in_blocks, height_in_blocks, |pixel| {
210
32
                    ensure_matches_attach!(
211
5.15M
                        pixel.green,
212
5.15M
                        0..=13,
213
32
                        ParseError::InvalidInput,
214
32
                        InvalidPredictor(pixel.green),
215
                    );
216
5.15M
                    Ok(())
217
5.15M
                })
218
852
                .while_parsing_type()
219
852
                .attach_printable(WhileParsingTransform(transform))?;
220
189
                Ok(Self::Predictor { block_size, _image })
221
            }
222
783
            transform @ TransformType::Color => {
223
783
                let block_order = 2 + reader
224
783
                    .read::<u32>(3)
225
783
                    .attach_printable(WhileParsingTransform(transform))?;
226
778
                let block_size = 2u16.pow(block_order);
227
778
                let width_in_blocks = len_in_blocks(width, block_size);
228
778
                let height_in_blocks = len_in_blocks(height, block_size);
229
21.2M
                let _image = EntropyCodedImage::read(reader, width_in_blocks, height_in_blocks, |_| Ok(()))
230
778
                    .while_parsing_type()
231
778
                    .attach_printable(WhileParsingTransform(transform))?;
232
197
                Ok(Self::Color { block_size, _image })
233
            }
234
1.21k
            TransformType::SubtractGreen => Ok(Self::SubtractGreen),
235
1.08k
            transform @ TransformType::ColorIndexing => {
236
1.08k
                let len_minus_one = reader.read(8).attach_printable(WhileParsingTransform(transform))?;
237
1.06k
                let len = NonZeroU32::MIN.saturating_add(len_minus_one);
238
121k
                let image = EntropyCodedImage::read(reader, len, NonZeroU32::MIN, |_| Ok(()))
239
1.06k
                    .while_parsing_type()
240
1.06k
                    .attach_printable(WhileParsingTransform(transform))?;
241
770
                Ok(Self::ColorIndexing { image })
242
            }
243
        }
244
3.97k
    }
245
246
4.74k
    fn transform_type(&self) -> TransformType {
247
4.74k
        match self {
248
378
            Transform::Predictor { .. } => TransformType::Predictor,
249
394
            Transform::Color { .. } => TransformType::Color,
250
2.43k
            Transform::SubtractGreen => TransformType::SubtractGreen,
251
1.54k
            Transform::ColorIndexing { .. } => TransformType::ColorIndexing,
252
        }
253
4.74k
    }
254
255
2.37k
    fn transformed_width(&self, width: NonZeroU32) -> NonZeroU32 {
256
2.37k
        match self {
257
770
            Transform::ColorIndexing { image } => {
258
770
                let block_size = match image.width.get() {
259
770
                    0..=2 => 8,
260
752
                    3..=4 => 4,
261
736
                    5..=16 => 2,
262
724
                    17.. => 1,
263
                };
264
770
                len_in_blocks(width, block_size)
265
            }
266
1.60k
            _ => width,
267
        }
268
2.37k
    }
269
}
270
271
impl TransformType {
272
    const PREDICTOR: u8 = TransformType::Predictor as u8;
273
    const COLOR: u8 = TransformType::Color as u8;
274
    const SUBTRACT_GREEN: u8 = TransformType::SubtractGreen as u8;
275
    const COLOR_INDEXING: u8 = TransformType::ColorIndexing as u8;
276
277
    const COUNT: usize = 4;
278
279
3.97k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>) -> Result<Self, Error> {
280
3.97k
        match reader.read(2)? {
281
862
            Self::PREDICTOR => Ok(Self::Predictor),
282
783
            Self::COLOR => Ok(Self::Color),
283
1.21k
            Self::SUBTRACT_GREEN => Ok(Self::SubtractGreen),
284
1.08k
            Self::COLOR_INDEXING => Ok(Self::ColorIndexing),
285
0
            0b100.. => unreachable!(),
286
        }
287
3.97k
    }
288
}
289
290
//
291
// EntropyCodedImage impls
292
//
293
294
impl EntropyCodedImage {
295
4.97k
    fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>(
296
4.97k
        reader: &mut BitBufReader<R, LE>,
297
4.97k
        width: NonZeroU32,
298
4.97k
        height: NonZeroU32,
299
4.97k
        mut fun: F,
300
4.97k
    ) -> Result<Self, Error> {
301
4.97k
        let color_cache = ColorCache::read(reader).while_parsing_type()?;
302
4.88k
        let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?;
303
4.09k
        let green_readahead_bits = codes.green_readahead_bits();
304
4.09k
        let arb_readahead_bits = codes.arb_readahead_bits();
305
4.09k
        let backref_readahead_bits = codes.backref_readahead_bits();
306
4.09k
        let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits);
307
308
4.09k
        let len = width.saturating_mul(height);
309
4.09k
        let mut pixel_idx = 0;
310
44.5M
        while pixel_idx < len.get() {
311
44.5M
            if reader.buf_bits() < u64::from(readahead_bits) {
312
18.2k
                reader.fill_buf()?;
313
44.5M
            }
314
44.5M
            match reader.buf_read_huffman(&codes.green.tree)? {
315
44.5M
                symbol @ 0..=255 => {
316
38.3M
                    let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?;
317
38.3M
                    log::debug!("color: {color}");
318
38.3M
                    fun(color)?;
319
38.3M
                    if green_readahead_bits + arb_readahead_bits == 0 {
320
1.50k
                        pixel_idx = len.get();
321
38.3M
                    } else {
322
38.3M
                        pixel_idx += 1;
323
38.3M
                    }
324
                }
325
6.21M
                symbol @ 256..=279 => {
326
3.40M
                    let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?;
327
3.40M
                    log::debug!("backref: {back_ref}");
328
148
                    ensure_matches_attach!(
329
3.40M
                        pixel_idx.checked_sub(back_ref.dist.get()),
330
                        Some(_),
331
148
                        ParseError::InvalidInput,
332
148
                        InvalidBackRefDistance(back_ref.dist, pixel_idx),
333
                    );
334
3.40M
                    ensure_attach!(
335
3.40M
                        back_ref.len.get() <= len.get() - pixel_idx,
336
80
                        ParseError::InvalidInput,
337
80
                        InvalidBackRefLength(back_ref.len, pixel_idx, len.get()),
338
                    );
339
3.40M
                    pixel_idx += back_ref.len.get();
340
                }
341
2.80M
                symbol @ 280.. => {
342
2.80M
                    let color_cache_index = symbol - 280;
343
2.80M
                    log::debug!("cached: {color_cache_index}");
344
2.80M
                    ensure_attach!(
345
2.80M
                        color_cache_index < color_cache.len(),
346
0
                        ParseError::InvalidInput,
347
0
                        ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()),
348
                    );
349
2.80M
                    if green_readahead_bits == 0 {
350
2
                        pixel_idx = len.get();
351
2.80M
                    } else {
352
2.80M
                        pixel_idx += 1;
353
2.80M
                    }
354
                }
355
            }
356
        }
357
2.75k
        Ok(Self { width, height })
358
4.97k
    }
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::MetaPrefixCodes>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#0}>
Line
Count
Source
295
2.27k
    fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>(
296
2.27k
        reader: &mut BitBufReader<R, LE>,
297
2.27k
        width: NonZeroU32,
298
2.27k
        height: NonZeroU32,
299
2.27k
        mut fun: F,
300
2.27k
    ) -> Result<Self, Error> {
301
2.27k
        let color_cache = ColorCache::read(reader).while_parsing_type()?;
302
2.25k
        let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?;
303
2.01k
        let green_readahead_bits = codes.green_readahead_bits();
304
2.01k
        let arb_readahead_bits = codes.arb_readahead_bits();
305
2.01k
        let backref_readahead_bits = codes.backref_readahead_bits();
306
2.01k
        let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits);
307
308
2.01k
        let len = width.saturating_mul(height);
309
2.01k
        let mut pixel_idx = 0;
310
12.9M
        while pixel_idx < len.get() {
311
12.9M
            if reader.buf_bits() < u64::from(readahead_bits) {
312
5.90k
                reader.fill_buf()?;
313
12.9M
            }
314
12.9M
            match reader.buf_read_huffman(&codes.green.tree)? {
315
12.9M
                symbol @ 0..=255 => {
316
11.8M
                    let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?;
317
11.8M
                    log::debug!("color: {color}");
318
11.8M
                    fun(color)?;
319
11.8M
                    if green_readahead_bits + arb_readahead_bits == 0 {
320
1.18k
                        pixel_idx = len.get();
321
11.8M
                    } else {
322
11.8M
                        pixel_idx += 1;
323
11.8M
                    }
324
                }
325
1.18M
                symbol @ 256..=279 => {
326
1.17M
                    let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?;
327
1.17M
                    log::debug!("backref: {back_ref}");
328
59
                    ensure_matches_attach!(
329
1.17M
                        pixel_idx.checked_sub(back_ref.dist.get()),
330
                        Some(_),
331
59
                        ParseError::InvalidInput,
332
59
                        InvalidBackRefDistance(back_ref.dist, pixel_idx),
333
                    );
334
1.17M
                    ensure_attach!(
335
1.17M
                        back_ref.len.get() <= len.get() - pixel_idx,
336
10
                        ParseError::InvalidInput,
337
10
                        InvalidBackRefLength(back_ref.len, pixel_idx, len.get()),
338
                    );
339
1.17M
                    pixel_idx += back_ref.len.get();
340
                }
341
2.08k
                symbol @ 280.. => {
342
2.08k
                    let color_cache_index = symbol - 280;
343
2.08k
                    log::debug!("cached: {color_cache_index}");
344
2.08k
                    ensure_attach!(
345
2.08k
                        color_cache_index < color_cache.len(),
346
0
                        ParseError::InvalidInput,
347
0
                        ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()),
348
                    );
349
2.08k
                    if green_readahead_bits == 0 {
350
2
                        pixel_idx = len.get();
351
2.08k
                    } else {
352
2.08k
                        pixel_idx += 1;
353
2.08k
                    }
354
                }
355
            }
356
        }
357
1.59k
        Ok(Self { width, height })
358
2.27k
    }
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::Transform>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#0}>
Line
Count
Source
295
852
    fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>(
296
852
        reader: &mut BitBufReader<R, LE>,
297
852
        width: NonZeroU32,
298
852
        height: NonZeroU32,
299
852
        mut fun: F,
300
852
    ) -> Result<Self, Error> {
301
852
        let color_cache = ColorCache::read(reader).while_parsing_type()?;
302
840
        let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?;
303
572
        let green_readahead_bits = codes.green_readahead_bits();
304
572
        let arb_readahead_bits = codes.arb_readahead_bits();
305
572
        let backref_readahead_bits = codes.backref_readahead_bits();
306
572
        let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits);
307
308
572
        let len = width.saturating_mul(height);
309
572
        let mut pixel_idx = 0;
310
9.65M
        while pixel_idx < len.get() {
311
9.65M
            if reader.buf_bits() < u64::from(readahead_bits) {
312
4.36k
                reader.fill_buf()?;
313
9.64M
            }
314
9.65M
            match reader.buf_read_huffman(&codes.green.tree)? {
315
9.64M
                symbol @ 0..=255 => {
316
5.15M
                    let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?;
317
5.15M
                    log::debug!("color: {color}");
318
5.15M
                    fun(color)?;
319
5.15M
                    if green_readahead_bits + arb_readahead_bits == 0 {
320
114
                        pixel_idx = len.get();
321
5.15M
                    } else {
322
5.15M
                        pixel_idx += 1;
323
5.15M
                    }
324
                }
325
4.49M
                symbol @ 256..=279 => {
326
1.68M
                    let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?;
327
1.68M
                    log::debug!("backref: {back_ref}");
328
51
                    ensure_matches_attach!(
329
1.68M
                        pixel_idx.checked_sub(back_ref.dist.get()),
330
                        Some(_),
331
51
                        ParseError::InvalidInput,
332
51
                        InvalidBackRefDistance(back_ref.dist, pixel_idx),
333
                    );
334
1.68M
                    ensure_attach!(
335
1.68M
                        back_ref.len.get() <= len.get() - pixel_idx,
336
19
                        ParseError::InvalidInput,
337
19
                        InvalidBackRefLength(back_ref.len, pixel_idx, len.get()),
338
                    );
339
1.68M
                    pixel_idx += back_ref.len.get();
340
                }
341
2.80M
                symbol @ 280.. => {
342
2.80M
                    let color_cache_index = symbol - 280;
343
2.80M
                    log::debug!("cached: {color_cache_index}");
344
2.80M
                    ensure_attach!(
345
2.80M
                        color_cache_index < color_cache.len(),
346
0
                        ParseError::InvalidInput,
347
0
                        ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()),
348
                    );
349
2.80M
                    if green_readahead_bits == 0 {
350
0
                        pixel_idx = len.get();
351
2.80M
                    } else {
352
2.80M
                        pixel_idx += 1;
353
2.80M
                    }
354
                }
355
            }
356
        }
357
189
        Ok(Self { width, height })
358
852
    }
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::Transform>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#2}>
Line
Count
Source
295
1.06k
    fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>(
296
1.06k
        reader: &mut BitBufReader<R, LE>,
297
1.06k
        width: NonZeroU32,
298
1.06k
        height: NonZeroU32,
299
1.06k
        mut fun: F,
300
1.06k
    ) -> Result<Self, Error> {
301
1.06k
        let color_cache = ColorCache::read(reader).while_parsing_type()?;
302
1.03k
        let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?;
303
920
        let green_readahead_bits = codes.green_readahead_bits();
304
920
        let arb_readahead_bits = codes.arb_readahead_bits();
305
920
        let backref_readahead_bits = codes.backref_readahead_bits();
306
920
        let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits);
307
308
920
        let len = width.saturating_mul(height);
309
920
        let mut pixel_idx = 0;
310
123k
        while pixel_idx < len.get() {
311
122k
            if reader.buf_bits() < u64::from(readahead_bits) {
312
2.09k
                reader.fill_buf()?;
313
120k
            }
314
122k
            match reader.buf_read_huffman(&codes.green.tree)? {
315
122k
                symbol @ 0..=255 => {
316
121k
                    let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?;
317
121k
                    log::debug!("color: {color}");
318
121k
                    fun(color)?;
319
121k
                    if green_readahead_bits + arb_readahead_bits == 0 {
320
96
                        pixel_idx = len.get();
321
121k
                    } else {
322
121k
                        pixel_idx += 1;
323
121k
                    }
324
                }
325
1.38k
                symbol @ 256..=279 => {
326
606
                    let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?;
327
604
                    log::debug!("backref: {back_ref}");
328
8
                    ensure_matches_attach!(
329
604
                        pixel_idx.checked_sub(back_ref.dist.get()),
330
                        Some(_),
331
8
                        ParseError::InvalidInput,
332
8
                        InvalidBackRefDistance(back_ref.dist, pixel_idx),
333
                    );
334
596
                    ensure_attach!(
335
596
                        back_ref.len.get() <= len.get() - pixel_idx,
336
21
                        ParseError::InvalidInput,
337
21
                        InvalidBackRefLength(back_ref.len, pixel_idx, len.get()),
338
                    );
339
575
                    pixel_idx += back_ref.len.get();
340
                }
341
781
                symbol @ 280.. => {
342
781
                    let color_cache_index = symbol - 280;
343
781
                    log::debug!("cached: {color_cache_index}");
344
781
                    ensure_attach!(
345
781
                        color_cache_index < color_cache.len(),
346
0
                        ParseError::InvalidInput,
347
0
                        ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()),
348
                    );
349
781
                    if green_readahead_bits == 0 {
350
0
                        pixel_idx = len.get();
351
781
                    } else {
352
781
                        pixel_idx += 1;
353
781
                    }
354
                }
355
            }
356
        }
357
770
        Ok(Self { width, height })
358
1.06k
    }
<webpsan::parse::lossless::EntropyCodedImage>::read::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, <webpsan::parse::lossless::Transform>::read<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>>::{closure#1}>
Line
Count
Source
295
778
    fn read<R: Read, F: FnMut(Color) -> Result<(), Error>>(
296
778
        reader: &mut BitBufReader<R, LE>,
297
778
        width: NonZeroU32,
298
778
        height: NonZeroU32,
299
778
        mut fun: F,
300
778
    ) -> Result<Self, Error> {
301
778
        let color_cache = ColorCache::read(reader).while_parsing_type()?;
302
748
        let codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?;
303
590
        let green_readahead_bits = codes.green_readahead_bits();
304
590
        let arb_readahead_bits = codes.arb_readahead_bits();
305
590
        let backref_readahead_bits = codes.backref_readahead_bits();
306
590
        let readahead_bits = green_readahead_bits + arb_readahead_bits.max(backref_readahead_bits);
307
308
590
        let len = width.saturating_mul(height);
309
590
        let mut pixel_idx = 0;
310
21.7M
        while pixel_idx < len.get() {
311
21.7M
            if reader.buf_bits() < u64::from(readahead_bits) {
312
5.87k
                reader.fill_buf()?;
313
21.7M
            }
314
21.7M
            match reader.buf_read_huffman(&codes.green.tree)? {
315
21.7M
                symbol @ 0..=255 => {
316
21.2M
                    let color = Color::buf_read(reader, symbol as u8, &codes).while_parsing_type()?;
317
21.2M
                    log::debug!("color: {color}");
318
21.2M
                    fun(color)?;
319
21.2M
                    if green_readahead_bits + arb_readahead_bits == 0 {
320
117
                        pixel_idx = len.get();
321
21.2M
                    } else {
322
21.2M
                        pixel_idx += 1;
323
21.2M
                    }
324
                }
325
544k
                symbol @ 256..=279 => {
326
539k
                    let back_ref = BackReference::buf_read(reader, symbol - 256, &codes, width).while_parsing_type()?;
327
539k
                    log::debug!("backref: {back_ref}");
328
30
                    ensure_matches_attach!(
329
539k
                        pixel_idx.checked_sub(back_ref.dist.get()),
330
                        Some(_),
331
30
                        ParseError::InvalidInput,
332
30
                        InvalidBackRefDistance(back_ref.dist, pixel_idx),
333
                    );
334
539k
                    ensure_attach!(
335
539k
                        back_ref.len.get() <= len.get() - pixel_idx,
336
30
                        ParseError::InvalidInput,
337
30
                        InvalidBackRefLength(back_ref.len, pixel_idx, len.get()),
338
                    );
339
539k
                    pixel_idx += back_ref.len.get();
340
                }
341
4.34k
                symbol @ 280.. => {
342
4.34k
                    let color_cache_index = symbol - 280;
343
4.34k
                    log::debug!("cached: {color_cache_index}");
344
4.34k
                    ensure_attach!(
345
4.34k
                        color_cache_index < color_cache.len(),
346
0
                        ParseError::InvalidInput,
347
0
                        ColorCacheIndexOutOfBounds(color_cache_index, color_cache.len()),
348
                    );
349
4.34k
                    if green_readahead_bits == 0 {
350
0
                        pixel_idx = len.get();
351
4.34k
                    } else {
352
4.34k
                        pixel_idx += 1;
353
4.34k
                    }
354
                }
355
            }
356
        }
357
197
        Ok(Self { width, height })
358
778
    }
359
}
360
361
//
362
// SpatiallyCodedImage impls
363
//
364
365
impl SpatiallyCodedImage {
366
3.93k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>, width: NonZeroU32, height: NonZeroU32) -> Result<Self, Error> {
367
3.93k
        let color_cache = ColorCache::read(reader).while_parsing_type()?;
368
3.91k
        let meta = MetaPrefixCodes::read(reader, width, height).while_parsing_type()?;
369
3.21k
        log::info!("{meta}");
370
371
3.21k
        for _ in 0..=meta.max_code_group() {
372
207k
            let _codes = PrefixCodeGroup::read(reader, &color_cache).while_parsing_type()?;
373
        }
374
597
        Ok(Self)
375
3.93k
    }
376
}
377
378
//
379
// BackReference impls
380
//
381
382
impl BackReference {
383
    #[rustfmt::skip]
384
    const DISTANCE_MAP: [(i8, u8); 120] = [
385
        (0, 1),  (1, 0),  (1, 1),  (-1, 1), (0, 2),  (2, 0),  (1, 2),
386
        (-1, 2), (2, 1),  (-2, 1), (2, 2),  (-2, 2), (0, 3),  (3, 0),
387
        (1, 3),  (-1, 3), (3, 1),  (-3, 1), (2, 3),  (-2, 3), (3, 2),
388
        (-3, 2), (0, 4),  (4, 0),  (1, 4),  (-1, 4), (4, 1),  (-4, 1),
389
        (3, 3),  (-3, 3), (2, 4),  (-2, 4), (4, 2),  (-4, 2), (0, 5),
390
        (3, 4),  (-3, 4), (4, 3),  (-4, 3), (5, 0),  (1, 5),  (-1, 5),
391
        (5, 1),  (-5, 1), (2, 5),  (-2, 5), (5, 2),  (-5, 2), (4, 4),
392
        (-4, 4), (3, 5),  (-3, 5), (5, 3),  (-5, 3), (0, 6),  (6, 0),
393
        (1, 6),  (-1, 6), (6, 1),  (-6, 1), (2, 6),  (-2, 6), (6, 2),
394
        (-6, 2), (4, 5),  (-4, 5), (5, 4),  (-5, 4), (3, 6),  (-3, 6),
395
        (6, 3),  (-6, 3), (0, 7),  (7, 0),  (1, 7),  (-1, 7), (5, 5),
396
        (-5, 5), (7, 1),  (-7, 1), (4, 6),  (-4, 6), (6, 4),  (-6, 4),
397
        (2, 7),  (-2, 7), (7, 2),  (-7, 2), (3, 7),  (-3, 7), (7, 3),
398
        (-7, 3), (5, 6),  (-5, 6), (6, 5),  (-6, 5), (8, 0),  (4, 7),
399
        (-4, 7), (7, 4),  (-7, 4), (8, 1),  (8, 2),  (6, 6),  (-6, 6),
400
        (8, 3),  (5, 7),  (-5, 7), (7, 5),  (-7, 5), (8, 4),  (6, 7),
401
        (-6, 7), (7, 6),  (-7, 6), (8, 5),  (7, 7),  (-7, 7), (8, 6),
402
        (8, 7)
403
    ];
404
    const DISTANCE_MAP_LEN: u32 = Self::DISTANCE_MAP.len() as u32;
405
406
3.40M
    fn buf_read<R: Read>(
407
3.40M
        reader: &mut BitBufReader<R, LE>,
408
3.40M
        len_symbol: u16,
409
3.40M
        codes: &PrefixCodeGroup,
410
3.40M
        width: NonZeroU32,
411
3.40M
    ) -> Result<Self, Error> {
412
3.40M
        let len = reader.buf_read_lz77(len_symbol)?;
413
3.40M
        let dist_symbol = reader.buf_read_huffman(&codes.distance.tree)?;
414
3.40M
        let dist_code = reader.buf_read_lz77(dist_symbol.into())?;
415
3.40M
        let dist = match dist_code.get() {
416
0
            0 => unreachable!(),
417
3.40M
            dist_code @ 1..=Self::DISTANCE_MAP_LEN => {
418
3.38M
                let (dx, dy) = Self::DISTANCE_MAP[dist_code as usize - 1];
419
3.38M
                (u32::from(dy) * u32::from(width))
420
3.38M
                    .checked_add_signed(dx.into())
421
3.38M
                    .and_then(NonZeroU32::new)
422
3.38M
                    .unwrap_or(NonZeroU32::MIN)
423
            }
424
24.2k
            _ => NonZeroU32::new(dist_code.get() - Self::DISTANCE_MAP_LEN).unwrap_or_else(|| unreachable!()),
425
        };
426
3.40M
        Ok(Self { dist, len })
427
3.40M
    }
428
429
4.09k
    fn readahead_bits(codes: &PrefixCodeGroup) -> u32 {
430
4.09k
        2 * u32::from(LZ77_MAX_LEN) + codes.distance.tree.longest_code_len()
431
4.09k
    }
432
}
433
434
//
435
// Color impls
436
//
437
438
impl Color {
439
38.3M
    fn buf_read<R: Read>(reader: &mut BitBufReader<R, LE>, green: u8, codes: &PrefixCodeGroup) -> Result<Self, Error> {
440
        Ok(Self {
441
38.3M
            green,
442
38.3M
            red: reader.buf_read_huffman(&codes.red.tree)?,
443
38.3M
            blue: reader.buf_read_huffman(&codes.blue.tree)?,
444
38.3M
            alpha: reader.buf_read_huffman(&codes.alpha.tree)?,
445
        })
446
38.3M
    }
447
}
448
449
impl From<Color> for u32 {
450
0
    fn from(color: Color) -> Self {
451
0
        (color.alpha as u32) << 24 | (color.red as u32) << 16 | (color.green as u32) << 8 | color.blue as u32
452
0
    }
453
}
454
455
//
456
// ColorCache impls
457
//
458
459
impl ColorCache {
460
8.90k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>) -> Result<Self, Error> {
461
8.90k
        let has_color_cache = reader.read_bit()?;
462
8.88k
        if has_color_cache {
463
2.52k
            let order = reader.read::<u8>(4)?;
464
2.47k
            ensure_attach!(order <= 11, ParseError::InvalidInput, InvalidColorCacheSize(order));
465
9
            ensure_matches_attach!(
466
2.44k
                NonZeroU8::new(order),
467
2.43k
                Some(order),
468
9
                ParseError::InvalidInput,
469
9
                InvalidColorCacheSize(order),
470
            );
471
2.43k
            Ok(Self { order: Some(order) })
472
        } else {
473
6.36k
            Ok(Self { order: None })
474
        }
475
8.90k
    }
476
477
2.98M
    fn len(&self) -> u16 {
478
2.98M
        self.order.map(|order| 2u16.pow(order.get().into())).unwrap_or_default()
479
2.98M
    }
480
}
481
482
//
483
// MetaPrefixCodes impls
484
//
485
486
impl MetaPrefixCodes {
487
3.91k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>, width: NonZeroU32, height: NonZeroU32) -> Result<Self, Error> {
488
3.91k
        let has_meta = reader.read_bit()?;
489
3.90k
        if has_meta {
490
2.29k
            let block_order = 2 + reader.read::<u32>(3)?;
491
2.27k
            let block_size = 2u16.pow(block_order);
492
2.27k
            let width_in_blocks = len_in_blocks(width, block_size);
493
2.27k
            let height_in_blocks = len_in_blocks(height, block_size);
494
2.27k
            let mut max_code_group = 0;
495
11.8M
            let _image = EntropyCodedImage::read(reader, width_in_blocks, height_in_blocks, |color| {
496
11.8M
                max_code_group = max_code_group.max(u16::from(color.red) << 8 | u16::from(color.green));
497
11.8M
                Ok(())
498
11.8M
            })
499
2.27k
            .while_parsing_type()?;
500
1.59k
            Ok(Self::Multiple { block_size, max_code_group, _image })
501
        } else {
502
1.61k
            Ok(Self::Single)
503
        }
504
3.91k
    }
505
506
3.21k
    fn max_code_group(&self) -> u16 {
507
3.21k
        match self {
508
1.61k
            MetaPrefixCodes::Single => 0,
509
1.59k
            &MetaPrefixCodes::Multiple { max_code_group, .. } => max_code_group,
510
        }
511
3.21k
    }
512
}
513
514
//
515
// PrefixCodeGroup impls
516
//
517
518
impl PrefixCodeGroup {
519
212k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>, color_cache: &ColorCache) -> Result<Self, Error> {
520
212k
        let green = Self::read_prefix_code(reader, color_cache).while_parsing_type()?;
521
211k
        let red = Self::read_prefix_code(reader, color_cache).while_parsing_type()?;
522
210k
        let blue = Self::read_prefix_code(reader, color_cache).while_parsing_type()?;
523
209k
        let alpha = Self::read_prefix_code(reader, color_cache).while_parsing_type()?;
524
209k
        let distance = Self::read_prefix_code(reader, color_cache).while_parsing_type()?;
525
208k
        Ok(Self { green, red, blue, alpha, distance })
526
212k
    }
527
528
1.05M
    fn read_prefix_code<R: Read, T: PrefixCode>(
529
1.05M
        reader: &mut BitBufReader<R, LE>,
530
1.05M
        color_cache: &ColorCache,
531
1.05M
    ) -> Result<T, Error>
532
1.05M
    where
533
1.05M
        usize: AsPrimitive<T::Symbol>,
534
1.05M
        T::Symbol: Copy + Ord + 'static,
535
    {
536
1.05M
        let simple_code_length_code = reader.read_bit()?;
537
1.05M
        let tree = if simple_code_length_code {
538
877k
            let has_second_symbol = reader.read_bit()?;
539
540
877k
            let is_first_symbol_8bits = reader.read_bit()?;
541
876k
            let first_symbol = if is_first_symbol_8bits {
542
69.4k
                reader.read(8)?
543
            } else {
544
807k
                Numeric::from_u8(reader.read_bit()? as u8)
545
            };
546
876k
            let symbols = if has_second_symbol {
547
332k
                let second_symbol = reader.read(8)?;
548
332k
                vec![(first_symbol, vec![0]), (second_symbol, vec![1])]
549
            } else {
550
544k
                vec![(first_symbol, vec![])]
551
            };
552
876k
            CanonicalHuffmanTree::from_symbols(symbols)?
553
        } else {
554
175k
            let code_length_code = CodeLengthPrefixCode::read(reader)?;
555
556
174k
            let max_symbol_count = T::alphabet_size(color_cache.len());
557
174k
            let max_symbol_reads = if reader.read_bit()? {
558
169k
                let length_bit_len = 2 + 2 * reader.read::<u32>(3)?;
559
169k
                log::debug!("length_bit_len: {length_bit_len:?}");
560
169k
                2u16.saturating_add(reader.read(length_bit_len)?)
561
            } else {
562
4.91k
                max_symbol_count
563
            };
564
174k
            log::debug!("max_symbol_count: {max_symbol_count:?}");
565
174k
            log::debug!("max_symbol_reads: {max_symbol_reads:?}");
566
567
174k
            ensure_attach!(
568
174k
                max_symbol_reads <= max_symbol_count,
569
111
                ParseError::InvalidInput,
570
111
                InvalidSymbolCount(max_symbol_reads, max_symbol_count),
571
            );
572
573
173k
            let mut code_lengths = Vec::with_capacity(max_symbol_count as usize);
574
173k
            let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!());
Unexecuted instantiation: <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::ARBPrefixCode>::{closure#0}
Unexecuted instantiation: <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::GreenPrefixCode>::{closure#0}
Unexecuted instantiation: <webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::DistancePrefixCode>::{closure#0}
575
173k
            for _ in 0..max_symbol_reads {
576
1.06M
                if code_lengths.len() == max_symbol_count.into() {
577
5.47k
                    break;
578
1.05M
                }
579
580
1.05M
                let code_length_code = reader.read_huffman(&code_length_code.tree)?;
581
1.05M
                let (code_length, repeat_times) = match code_length_code {
582
1.05M
                    0..=15 => (code_length_code, 1),
583
63.4k
                    16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?),
584
78.0k
                    17 => (0, 3 + reader.read::<u8>(3)?),
585
50.5k
                    18 => (0, 11 + reader.read::<u8>(7)?),
586
0
                    19.. => unreachable!(),
587
                };
588
1.05M
                if let Some(non_zero_code_length) = NonZeroU8::new(code_length) {
589
785k
                    last_non_zero_code_length = non_zero_code_length;
590
785k
                }
591
592
1.05M
                let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times);
593
1.05M
                ensure_attach!(
594
1.05M
                    new_code_lengths_len <= usize::from(max_symbol_count),
595
93
                    ParseError::InvalidVp8lPrefixCode,
596
93
                    InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count)
597
                );
598
1.05M
                let new_code_lengths =
599
5.87M
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::ARBPrefixCode>::{closure#1}
Line
Count
Source
599
3.21M
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::GreenPrefixCode>::{closure#1}
Line
Count
Source
599
2.40M
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::DistancePrefixCode>::{closure#1}
Line
Count
Source
599
256k
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
600
1.05M
                code_lengths.extend(new_code_lengths);
601
            }
602
603
173k
            log::debug!("code_lengths: {code_lengths:?}");
604
173k
            CanonicalHuffmanTree::new(&mut code_lengths)?
605
        };
606
1.04M
        Ok(T::new(tree))
607
1.05M
    }
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::ARBPrefixCode>
Line
Count
Source
528
630k
    fn read_prefix_code<R: Read, T: PrefixCode>(
529
630k
        reader: &mut BitBufReader<R, LE>,
530
630k
        color_cache: &ColorCache,
531
630k
    ) -> Result<T, Error>
532
630k
    where
533
630k
        usize: AsPrimitive<T::Symbol>,
534
630k
        T::Symbol: Copy + Ord + 'static,
535
    {
536
630k
        let simple_code_length_code = reader.read_bit()?;
537
630k
        let tree = if simple_code_length_code {
538
527k
            let has_second_symbol = reader.read_bit()?;
539
540
527k
            let is_first_symbol_8bits = reader.read_bit()?;
541
527k
            let first_symbol = if is_first_symbol_8bits {
542
40.3k
                reader.read(8)?
543
            } else {
544
487k
                Numeric::from_u8(reader.read_bit()? as u8)
545
            };
546
527k
            let symbols = if has_second_symbol {
547
199k
                let second_symbol = reader.read(8)?;
548
199k
                vec![(first_symbol, vec![0]), (second_symbol, vec![1])]
549
            } else {
550
328k
                vec![(first_symbol, vec![])]
551
            };
552
527k
            CanonicalHuffmanTree::from_symbols(symbols)?
553
        } else {
554
102k
            let code_length_code = CodeLengthPrefixCode::read(reader)?;
555
556
102k
            let max_symbol_count = T::alphabet_size(color_cache.len());
557
102k
            let max_symbol_reads = if reader.read_bit()? {
558
100k
                let length_bit_len = 2 + 2 * reader.read::<u32>(3)?;
559
100k
                log::debug!("length_bit_len: {length_bit_len:?}");
560
100k
                2u16.saturating_add(reader.read(length_bit_len)?)
561
            } else {
562
2.10k
                max_symbol_count
563
            };
564
102k
            log::debug!("max_symbol_count: {max_symbol_count:?}");
565
102k
            log::debug!("max_symbol_reads: {max_symbol_reads:?}");
566
567
102k
            ensure_attach!(
568
102k
                max_symbol_reads <= max_symbol_count,
569
51
                ParseError::InvalidInput,
570
51
                InvalidSymbolCount(max_symbol_reads, max_symbol_count),
571
            );
572
573
102k
            let mut code_lengths = Vec::with_capacity(max_symbol_count as usize);
574
102k
            let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!());
575
102k
            for _ in 0..max_symbol_reads {
576
548k
                if code_lengths.len() == max_symbol_count.into() {
577
2.02k
                    break;
578
546k
                }
579
580
546k
                let code_length_code = reader.read_huffman(&code_length_code.tree)?;
581
546k
                let (code_length, repeat_times) = match code_length_code {
582
546k
                    0..=15 => (code_length_code, 1),
583
31.3k
                    16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?),
584
41.9k
                    17 => (0, 3 + reader.read::<u8>(3)?),
585
28.3k
                    18 => (0, 11 + reader.read::<u8>(7)?),
586
0
                    19.. => unreachable!(),
587
                };
588
546k
                if let Some(non_zero_code_length) = NonZeroU8::new(code_length) {
589
400k
                    last_non_zero_code_length = non_zero_code_length;
590
400k
                }
591
592
546k
                let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times);
593
546k
                ensure_attach!(
594
546k
                    new_code_lengths_len <= usize::from(max_symbol_count),
595
31
                    ParseError::InvalidVp8lPrefixCode,
596
31
                    InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count)
597
                );
598
546k
                let new_code_lengths =
599
546k
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
600
546k
                code_lengths.extend(new_code_lengths);
601
            }
602
603
102k
            log::debug!("code_lengths: {code_lengths:?}");
604
102k
            CanonicalHuffmanTree::new(&mut code_lengths)?
605
        };
606
629k
        Ok(T::new(tree))
607
630k
    }
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::GreenPrefixCode>
Line
Count
Source
528
212k
    fn read_prefix_code<R: Read, T: PrefixCode>(
529
212k
        reader: &mut BitBufReader<R, LE>,
530
212k
        color_cache: &ColorCache,
531
212k
    ) -> Result<T, Error>
532
212k
    where
533
212k
        usize: AsPrimitive<T::Symbol>,
534
212k
        T::Symbol: Copy + Ord + 'static,
535
    {
536
212k
        let simple_code_length_code = reader.read_bit()?;
537
212k
        let tree = if simple_code_length_code {
538
172k
            let has_second_symbol = reader.read_bit()?;
539
540
172k
            let is_first_symbol_8bits = reader.read_bit()?;
541
172k
            let first_symbol = if is_first_symbol_8bits {
542
12.0k
                reader.read(8)?
543
            } else {
544
160k
                Numeric::from_u8(reader.read_bit()? as u8)
545
            };
546
172k
            let symbols = if has_second_symbol {
547
67.1k
                let second_symbol = reader.read(8)?;
548
67.0k
                vec![(first_symbol, vec![0]), (second_symbol, vec![1])]
549
            } else {
550
105k
                vec![(first_symbol, vec![])]
551
            };
552
172k
            CanonicalHuffmanTree::from_symbols(symbols)?
553
        } else {
554
40.0k
            let code_length_code = CodeLengthPrefixCode::read(reader)?;
555
556
39.7k
            let max_symbol_count = T::alphabet_size(color_cache.len());
557
39.7k
            let max_symbol_reads = if reader.read_bit()? {
558
37.3k
                let length_bit_len = 2 + 2 * reader.read::<u32>(3)?;
559
37.3k
                log::debug!("length_bit_len: {length_bit_len:?}");
560
37.3k
                2u16.saturating_add(reader.read(length_bit_len)?)
561
            } else {
562
2.37k
                max_symbol_count
563
            };
564
39.6k
            log::debug!("max_symbol_count: {max_symbol_count:?}");
565
39.6k
            log::debug!("max_symbol_reads: {max_symbol_reads:?}");
566
567
39.6k
            ensure_attach!(
568
39.6k
                max_symbol_reads <= max_symbol_count,
569
25
                ParseError::InvalidInput,
570
25
                InvalidSymbolCount(max_symbol_reads, max_symbol_count),
571
            );
572
573
39.6k
            let mut code_lengths = Vec::with_capacity(max_symbol_count as usize);
574
39.6k
            let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!());
575
39.6k
            for _ in 0..max_symbol_reads {
576
372k
                if code_lengths.len() == max_symbol_count.into() {
577
2.11k
                    break;
578
370k
                }
579
580
370k
                let code_length_code = reader.read_huffman(&code_length_code.tree)?;
581
370k
                let (code_length, repeat_times) = match code_length_code {
582
370k
                    0..=15 => (code_length_code, 1),
583
32.0k
                    16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?),
584
26.1k
                    17 => (0, 3 + reader.read::<u8>(3)?),
585
20.4k
                    18 => (0, 11 + reader.read::<u8>(7)?),
586
0
                    19.. => unreachable!(),
587
                };
588
369k
                if let Some(non_zero_code_length) = NonZeroU8::new(code_length) {
589
281k
                    last_non_zero_code_length = non_zero_code_length;
590
281k
                }
591
592
369k
                let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times);
593
369k
                ensure_attach!(
594
369k
                    new_code_lengths_len <= usize::from(max_symbol_count),
595
23
                    ParseError::InvalidVp8lPrefixCode,
596
23
                    InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count)
597
                );
598
369k
                let new_code_lengths =
599
369k
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
600
369k
                code_lengths.extend(new_code_lengths);
601
            }
602
603
39.4k
            log::debug!("code_lengths: {code_lengths:?}");
604
39.4k
            CanonicalHuffmanTree::new(&mut code_lengths)?
605
        };
606
211k
        Ok(T::new(tree))
607
212k
    }
<webpsan::parse::lossless::PrefixCodeGroup>::read_prefix_code::<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, webpsan::parse::lossless::DistancePrefixCode>
Line
Count
Source
528
209k
    fn read_prefix_code<R: Read, T: PrefixCode>(
529
209k
        reader: &mut BitBufReader<R, LE>,
530
209k
        color_cache: &ColorCache,
531
209k
    ) -> Result<T, Error>
532
209k
    where
533
209k
        usize: AsPrimitive<T::Symbol>,
534
209k
        T::Symbol: Copy + Ord + 'static,
535
    {
536
209k
        let simple_code_length_code = reader.read_bit()?;
537
209k
        let tree = if simple_code_length_code {
538
177k
            let has_second_symbol = reader.read_bit()?;
539
540
177k
            let is_first_symbol_8bits = reader.read_bit()?;
541
177k
            let first_symbol = if is_first_symbol_8bits {
542
16.9k
                reader.read(8)?
543
            } else {
544
160k
                Numeric::from_u8(reader.read_bit()? as u8)
545
            };
546
177k
            let symbols = if has_second_symbol {
547
65.8k
                let second_symbol = reader.read(8)?;
548
65.8k
                vec![(first_symbol, vec![0]), (second_symbol, vec![1])]
549
            } else {
550
111k
                vec![(first_symbol, vec![])]
551
            };
552
177k
            CanonicalHuffmanTree::from_symbols(symbols)?
553
        } else {
554
32.0k
            let code_length_code = CodeLengthPrefixCode::read(reader)?;
555
556
31.9k
            let max_symbol_count = T::alphabet_size(color_cache.len());
557
31.9k
            let max_symbol_reads = if reader.read_bit()? {
558
31.5k
                let length_bit_len = 2 + 2 * reader.read::<u32>(3)?;
559
31.5k
                log::debug!("length_bit_len: {length_bit_len:?}");
560
31.5k
                2u16.saturating_add(reader.read(length_bit_len)?)
561
            } else {
562
430
                max_symbol_count
563
            };
564
31.8k
            log::debug!("max_symbol_count: {max_symbol_count:?}");
565
31.8k
            log::debug!("max_symbol_reads: {max_symbol_reads:?}");
566
567
31.8k
            ensure_attach!(
568
31.8k
                max_symbol_reads <= max_symbol_count,
569
35
                ParseError::InvalidInput,
570
35
                InvalidSymbolCount(max_symbol_reads, max_symbol_count),
571
            );
572
573
31.8k
            let mut code_lengths = Vec::with_capacity(max_symbol_count as usize);
574
31.8k
            let mut last_non_zero_code_length = NonZeroU8::new(8).unwrap_or_else(|| unreachable!());
575
31.8k
            for _ in 0..max_symbol_reads {
576
142k
                if code_lengths.len() == max_symbol_count.into() {
577
1.32k
                    break;
578
141k
                }
579
580
141k
                let code_length_code = reader.read_huffman(&code_length_code.tree)?;
581
141k
                let (code_length, repeat_times) = match code_length_code {
582
141k
                    0..=15 => (code_length_code, 1),
583
78
                    16 => (last_non_zero_code_length.get(), 3 + reader.read::<u8>(2)?),
584
9.97k
                    17 => (0, 3 + reader.read::<u8>(3)?),
585
1.72k
                    18 => (0, 11 + reader.read::<u8>(7)?),
586
0
                    19.. => unreachable!(),
587
                };
588
141k
                if let Some(non_zero_code_length) = NonZeroU8::new(code_length) {
589
104k
                    last_non_zero_code_length = non_zero_code_length;
590
104k
                }
591
592
141k
                let new_code_lengths_len = code_lengths.len() + usize::from(repeat_times);
593
141k
                ensure_attach!(
594
141k
                    new_code_lengths_len <= usize::from(max_symbol_count),
595
39
                    ParseError::InvalidVp8lPrefixCode,
596
39
                    InvalidCodeLengthRepetition(repeat_times, code_lengths.len(), max_symbol_count)
597
                );
598
141k
                let new_code_lengths =
599
141k
                    (code_lengths.len()..new_code_lengths_len).map(|symbol| (symbol.as_(), code_length));
600
141k
                code_lengths.extend(new_code_lengths);
601
            }
602
603
31.7k
            log::debug!("code_lengths: {code_lengths:?}");
604
31.7k
            CanonicalHuffmanTree::new(&mut code_lengths)?
605
        };
606
208k
        Ok(T::new(tree))
607
209k
    }
608
609
4.09k
    pub fn green_readahead_bits(&self) -> u32 {
610
4.09k
        self.green.tree.longest_code_len()
611
4.09k
    }
612
613
4.09k
    pub fn arb_readahead_bits(&self) -> u32 {
614
4.09k
        self.alpha.tree.longest_code_len() + self.red.tree.longest_code_len() + self.blue.tree.longest_code_len()
615
4.09k
    }
616
617
4.09k
    pub fn backref_readahead_bits(&self) -> u32 {
618
4.09k
        self.green.tree.longest_code_len() + BackReference::readahead_bits(self)
619
4.09k
    }
620
}
621
622
//
623
// CodeLengthPrefixCode impls
624
//
625
626
impl CodeLengthPrefixCode {
627
175k
    fn read<R: Read>(reader: &mut BitBufReader<R, LE>) -> Result<Self, Error> {
628
        const CODE_ORDER: [u8; 19] = [17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
629
630
175k
        let code_length_count = 4 + usize::from(reader.read::<u8>(4)?);
631
632
174k
        let mut code_lengths = [Default::default(); CODE_ORDER.len()];
633
174k
        let mut code_order_iter = CODE_ORDER.iter();
634
896k
        for &code_length_idx in code_order_iter.by_ref().take(code_length_count) {
635
896k
            code_lengths[usize::from(code_length_idx)] = (code_length_idx, reader.read(3)?);
636
        }
637
2.59M
        for &code_length_idx in code_order_iter {
638
2.42M
            code_lengths[usize::from(code_length_idx)] = (code_length_idx, 0);
639
2.42M
        }
640
641
174k
        let tree = CanonicalHuffmanTree::new(&mut code_lengths).attach_printable("while parsing code length code")?;
642
174k
        Ok(Self { tree })
643
175k
    }
644
}
645
646
//
647
// GreenPrefixCode impls
648
//
649
650
impl PrefixCode for GreenPrefixCode {
651
    type Symbol = u16;
652
653
211k
    fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self {
654
211k
        Self { tree }
655
211k
    }
656
657
39.7k
    fn alphabet_size(color_cache_len: u16) -> u16 {
658
39.7k
        256 + 24 + color_cache_len
659
39.7k
    }
660
}
661
662
//
663
// ARBPrefixCode impls
664
//
665
666
impl PrefixCode for ARBPrefixCode {
667
    type Symbol = u8;
668
669
629k
    fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self {
670
629k
        Self { tree }
671
629k
    }
672
673
102k
    fn alphabet_size(_color_cache_len: u16) -> u16 {
674
102k
        256
675
102k
    }
676
}
677
678
//
679
// DistancePrefixCode impls
680
//
681
682
impl PrefixCode for DistancePrefixCode {
683
    type Symbol = u8;
684
685
208k
    fn new(tree: CanonicalHuffmanTree<LE, Self::Symbol>) -> Self {
686
208k
        Self { tree }
687
208k
    }
688
689
31.9k
    fn alphabet_size(_color_cache_len: u16) -> u16 {
690
31.9k
        40
691
31.9k
    }
692
}
693
694
//
695
// private functions
696
//
697
698
8.58k
fn len_in_blocks(len: NonZeroU32, block_size: u16) -> NonZeroU32 {
699
8.58k
    NonZeroU32::new(div_ceil(len.get(), block_size.into())).unwrap_or_else(|| unreachable!())
700
8.58k
}