/src/mp4san/webpsan/src/parse/bitstream.rs
Line | Count | Source |
1 | | #![allow(missing_docs)] |
2 | | |
3 | | use std::fmt::Debug; |
4 | | use std::io::{Cursor, Read}; |
5 | | use std::mem::replace; |
6 | | use std::num::NonZeroU32; |
7 | | |
8 | | use bitstream_io::huffman::{compile_read_tree, ReadHuffmanTree}; |
9 | | use bitstream_io::{BitRead, BitReader, Endianness, HuffmanRead, Numeric}; |
10 | | use derive_more::Display; |
11 | | use mediasan_common::util::IoResultExt; |
12 | | use mediasan_common::{bail_attach, report_attach}; |
13 | | |
14 | | use crate::parse::ParseError; |
15 | | use crate::Error; |
16 | | |
17 | | pub struct BitBufReader<R, E: Endianness> { |
18 | | input: Option<R>, |
19 | | reader: BitReader<Cursor<Vec<u8>>, E>, |
20 | | buf_len: usize, |
21 | | } |
22 | | |
23 | | pub struct CanonicalHuffmanTree<E: Endianness, S: Clone> { |
24 | | read_tree: Box<[ReadHuffmanTree<E, S>]>, |
25 | | longest_code_len: u32, |
26 | | } |
27 | | |
28 | | #[derive(Display)] |
29 | | #[display("invalid lz77 prefix code `{_0}`")] |
30 | | struct InvalidLz77PrefixCode(u16); |
31 | | |
32 | | pub const LZ77_MAX_LEN: u16 = (LZ77_MAX_SYMBOL - 2) >> 1; |
33 | | |
34 | | const LZ77_MAX_SYMBOL: u16 = 39; |
35 | | |
36 | | // |
37 | | // BitBufReader impls |
38 | | // |
39 | | |
40 | | impl<R: Read, E: Endianness> BitBufReader<R, E> { |
41 | 5.67k | pub fn with_capacity(input: R, capacity: usize) -> Self { |
42 | 5.67k | Self { input: Some(input), reader: BitReader::new(Cursor::new(Vec::with_capacity(capacity))), buf_len: 0 } |
43 | 5.67k | } |
44 | | |
45 | 27.2k | pub fn fill_buf(&mut self) -> Result<(), Error> { |
46 | 27.2k | let bit_pos = self.buf_bit_pos(); |
47 | 27.2k | let byte_pos = (bit_pos / 8) as usize; |
48 | | |
49 | 27.2k | let Some(input) = self.input.as_mut() else { |
50 | 12.8k | return Ok(()); |
51 | | }; |
52 | | |
53 | 14.3k | let reader = replace(&mut self.reader, BitReader::new(Cursor::new(Vec::new()))); |
54 | 14.3k | let mut buf = reader.into_reader().into_inner(); |
55 | | |
56 | 14.3k | buf.drain(..byte_pos); |
57 | 14.3k | input.take((buf.capacity() - buf.len()) as u64).read_to_end(&mut buf)?; |
58 | 14.3k | if self.buf_len - byte_pos == buf.len() { |
59 | 3.62k | self.input = None; |
60 | 10.7k | } |
61 | 14.3k | self.buf_len = buf.len(); |
62 | | |
63 | 14.3k | self.reader = BitReader::new(Cursor::new(buf)); |
64 | 14.3k | self.reader.skip((bit_pos % 8) as u32)?; |
65 | 14.3k | Ok(()) |
66 | 27.2k | } |
67 | | |
68 | 56.1M | pub fn buf_bits(&mut self) -> u64 { |
69 | 56.1M | self.buf_len as u64 * 8 - self.buf_bit_pos() |
70 | 56.1M | } |
71 | | |
72 | 4.90M | pub fn buf_read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { |
73 | 4.90M | self.reader |
74 | 4.90M | .read(bits) |
75 | 4.90M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) <webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read::<u8>::{closure#0}Line | Count | Source | 75 | 898 | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read::<u32>::{closure#0}Line | Count | Source | 75 | 373 | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read::<u16>::{closure#0}Line | Count | Source | 75 | 260 | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) |
|
76 | 4.90M | } <webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read::<u8> Line | Count | Source | 72 | 1.68M | pub fn buf_read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { | 73 | 1.68M | self.reader | 74 | 1.68M | .read(bits) | 75 | 1.68M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) | 76 | 1.68M | } |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read::<u32> Line | Count | Source | 72 | 2.93M | pub fn buf_read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { | 73 | 2.93M | self.reader | 74 | 2.93M | .read(bits) | 75 | 2.93M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) | 76 | 2.93M | } |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read::<u16> Line | Count | Source | 72 | 274k | pub fn buf_read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { | 73 | 274k | self.reader | 74 | 274k | .read(bits) | 75 | 274k | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) | 76 | 274k | } |
|
77 | | |
78 | 4.27M | pub fn buf_read_bit(&mut self) -> Result<bool, Error> { |
79 | 4.27M | self.reader |
80 | 4.27M | .read_bit() |
81 | 4.27M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) |
82 | 4.27M | } |
83 | | |
84 | 181M | pub fn buf_read_huffman<T: Clone>(&mut self, tree: &CanonicalHuffmanTree<E, T>) -> Result<T, Error> { |
85 | 181M | self.reader |
86 | 181M | .read_huffman(&tree.read_tree) |
87 | 181M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) <webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read_huffman::<u8>::{closure#0}Line | Count | Source | 87 | 355 | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read_huffman::<u16>::{closure#0}Line | Count | Source | 87 | 582 | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) |
|
88 | 181M | } <webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read_huffman::<u8> Line | Count | Source | 84 | 133M | pub fn buf_read_huffman<T: Clone>(&mut self, tree: &CanonicalHuffmanTree<E, T>) -> Result<T, Error> { | 85 | 133M | self.reader | 86 | 133M | .read_huffman(&tree.read_tree) | 87 | 133M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) | 88 | 133M | } |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::buf_read_huffman::<u16> Line | Count | Source | 84 | 48.5M | pub fn buf_read_huffman<T: Clone>(&mut self, tree: &CanonicalHuffmanTree<E, T>) -> Result<T, Error> { | 85 | 48.5M | self.reader | 86 | 48.5M | .read_huffman(&tree.read_tree) | 87 | 48.5M | .map_eof(|_| Error::Parse(report_attach!(ParseError::TruncatedChunk))) | 88 | 48.5M | } |
|
89 | | |
90 | 8.20M | pub fn buf_read_lz77(&mut self, prefix_code: u16) -> Result<NonZeroU32, Error> { |
91 | 8.20M | match prefix_code { |
92 | 8.20M | 0..=3 => Ok(NonZeroU32::MIN.saturating_add(prefix_code.into())), |
93 | 2.75M | 4..=LZ77_MAX_SYMBOL => { |
94 | 2.75M | let extra_bits = (u32::from(prefix_code) - 2) >> 1; |
95 | 2.75M | let offset = (2 + (u32::from(prefix_code) & 1)) << extra_bits; |
96 | 2.75M | Ok(NonZeroU32::MIN.saturating_add(offset + self.buf_read::<u32>(extra_bits)?)) |
97 | | } |
98 | 4 | _ => bail_attach!(ParseError::InvalidInput, InvalidLz77PrefixCode(prefix_code)), |
99 | | } |
100 | 8.20M | } |
101 | | |
102 | 2.14M | pub fn read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { |
103 | 2.14M | if self.buf_bits() < bits.into() { |
104 | 1.48k | self.fill_buf()?; |
105 | 2.14M | } |
106 | 2.14M | self.buf_read(bits) |
107 | 2.14M | } <webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::read::<u8> Line | Count | Source | 102 | 1.68M | pub fn read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { | 103 | 1.68M | if self.buf_bits() < bits.into() { | 104 | 1.07k | self.fill_buf()?; | 105 | 1.68M | } | 106 | 1.68M | self.buf_read(bits) | 107 | 1.68M | } |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::read::<u32> Line | Count | Source | 102 | 179k | pub fn read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { | 103 | 179k | if self.buf_bits() < bits.into() { | 104 | 76 | self.fill_buf()?; | 105 | 179k | } | 106 | 179k | self.buf_read(bits) | 107 | 179k | } |
<webpsan::parse::bitstream::BitBufReader<webpsan::reader::ChunkDataReader<dyn webpsan::ReadSkip>, bitstream_io::LittleEndian>>::read::<u16> Line | Count | Source | 102 | 274k | pub fn read<T: Numeric>(&mut self, bits: u32) -> Result<T, Error> { | 103 | 274k | if self.buf_bits() < bits.into() { | 104 | 340 | self.fill_buf()?; | 105 | 273k | } | 106 | 274k | self.buf_read(bits) | 107 | 274k | } |
|
108 | | |
109 | 4.27M | pub fn read_bit(&mut self) -> Result<bool, Error> { |
110 | 4.27M | if self.buf_bits() < 1 { |
111 | 6.49k | self.fill_buf()?; |
112 | 4.27M | } |
113 | 4.27M | self.buf_read_bit() |
114 | 4.27M | } |
115 | | |
116 | 1.14M | pub fn read_huffman<T: Clone>(&mut self, tree: &CanonicalHuffmanTree<E, T>) -> Result<T, Error> { |
117 | 1.14M | if self.buf_bits() < tree.longest_code_len.into() { |
118 | 565 | self.fill_buf()?; |
119 | 1.14M | } |
120 | 1.14M | self.buf_read_huffman(tree) |
121 | 1.14M | } |
122 | | |
123 | 56.1M | fn buf_bit_pos(&mut self) -> u64 { |
124 | 56.1M | self.reader.position_in_bits().unwrap_or_else(|_| unreachable!()) |
125 | 56.1M | } |
126 | | } |
127 | | |
128 | | // |
129 | | // CanonicalHuffmanTree impls |
130 | | // |
131 | | |
132 | | impl<E: Endianness, S: Clone> CanonicalHuffmanTree<E, S> { |
133 | 358k | pub fn new(code_lengths: &mut [(S, u8)]) -> Result<Self, Error> |
134 | 358k | where |
135 | 358k | S: Copy + Debug + Ord + 'static, |
136 | | { |
137 | 358k | let symbols = Self::symbols(code_lengths); |
138 | 358k | log::debug!("symbols: {symbols:?}"); |
139 | 358k | Self::from_symbols(symbols) |
140 | 358k | } <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::new Line | Count | Source | 133 | 318k | pub fn new(code_lengths: &mut [(S, u8)]) -> Result<Self, Error> | 134 | 318k | where | 135 | 318k | S: Copy + Debug + Ord + 'static, | 136 | | { | 137 | 318k | let symbols = Self::symbols(code_lengths); | 138 | 318k | log::debug!("symbols: {symbols:?}"); | 139 | 318k | Self::from_symbols(symbols) | 140 | 318k | } |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::new Line | Count | Source | 133 | 40.5k | pub fn new(code_lengths: &mut [(S, u8)]) -> Result<Self, Error> | 134 | 40.5k | where | 135 | 40.5k | S: Copy + Debug + Ord + 'static, | 136 | | { | 137 | 40.5k | let symbols = Self::symbols(code_lengths); | 138 | 40.5k | log::debug!("symbols: {symbols:?}"); | 139 | 40.5k | Self::from_symbols(symbols) | 140 | 40.5k | } |
|
141 | | |
142 | 1.35M | pub fn from_symbols(symbols: Vec<(S, Vec<u8>)>) -> Result<Self, Error> { |
143 | 1.35M | let longest_code_len = match &symbols[..] { |
144 | 604k | [_symbol] => 0, |
145 | 2.78M | _ => symbols.iter().map(|(_, code)| code.len()).max().unwrap_or_default() as u32, <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::from_symbols::{closure#0}Line | Count | Source | 145 | 2.23M | _ => symbols.iter().map(|(_, code)| code.len()).max().unwrap_or_default() as u32, |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::from_symbols::{closure#0}Line | Count | Source | 145 | 542k | _ => symbols.iter().map(|(_, code)| code.len()).max().unwrap_or_default() as u32, |
|
146 | | }; |
147 | 1.35M | let read_tree = |
148 | 1.35M | compile_read_tree(symbols).map_err(|err| report_attach!(ParseError::InvalidVp8lPrefixCode, err))?; <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::from_symbols::{closure#1}Line | Count | Source | 148 | 895 | compile_read_tree(symbols).map_err(|err| report_attach!(ParseError::InvalidVp8lPrefixCode, err))?; |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::from_symbols::{closure#1}Line | Count | Source | 148 | 425 | compile_read_tree(symbols).map_err(|err| report_attach!(ParseError::InvalidVp8lPrefixCode, err))?; |
|
149 | 1.35M | Ok(Self { read_tree, longest_code_len }) |
150 | 1.35M | } <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::from_symbols Line | Count | Source | 142 | 1.11M | pub fn from_symbols(symbols: Vec<(S, Vec<u8>)>) -> Result<Self, Error> { | 143 | 1.11M | let longest_code_len = match &symbols[..] { | 144 | 488k | [_symbol] => 0, | 145 | 627k | _ => symbols.iter().map(|(_, code)| code.len()).max().unwrap_or_default() as u32, | 146 | | }; | 147 | 1.11M | let read_tree = | 148 | 1.11M | compile_read_tree(symbols).map_err(|err| report_attach!(ParseError::InvalidVp8lPrefixCode, err))?; | 149 | 1.11M | Ok(Self { read_tree, longest_code_len }) | 150 | 1.11M | } |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::from_symbols Line | Count | Source | 142 | 236k | pub fn from_symbols(symbols: Vec<(S, Vec<u8>)>) -> Result<Self, Error> { | 143 | 236k | let longest_code_len = match &symbols[..] { | 144 | 116k | [_symbol] => 0, | 145 | 119k | _ => symbols.iter().map(|(_, code)| code.len()).max().unwrap_or_default() as u32, | 146 | | }; | 147 | 235k | let read_tree = | 148 | 236k | compile_read_tree(symbols).map_err(|err| report_attach!(ParseError::InvalidVp8lPrefixCode, err))?; | 149 | 235k | Ok(Self { read_tree, longest_code_len }) | 150 | 236k | } |
|
151 | | |
152 | | pub fn read_tree(&self) -> &[ReadHuffmanTree<E, S>] { |
153 | | &self.read_tree |
154 | | } |
155 | | |
156 | 24.1k | pub fn longest_code_len(&self) -> u32 { |
157 | 24.1k | self.longest_code_len |
158 | 24.1k | } <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::longest_code_len Line | Count | Source | 156 | 16.0k | pub fn longest_code_len(&self) -> u32 { | 157 | 16.0k | self.longest_code_len | 158 | 16.0k | } |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::longest_code_len Line | Count | Source | 156 | 8.03k | pub fn longest_code_len(&self) -> u32 { | 157 | 8.03k | self.longest_code_len | 158 | 8.03k | } |
|
159 | | |
160 | 358k | fn symbols(code_lengths: &mut [(S, u8)]) -> Vec<(S, Vec<u8>)> |
161 | 358k | where |
162 | 358k | S: Copy + Ord + 'static, |
163 | | { |
164 | 81.5M | code_lengths.sort_unstable_by_key(|&(symbol, code_length)| (code_length, symbol)); <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::symbols::{closure#0}Line | Count | Source | 164 | 49.5M | code_lengths.sort_unstable_by_key(|&(symbol, code_length)| (code_length, symbol)); |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::symbols::{closure#0}Line | Count | Source | 164 | 32.0M | code_lengths.sort_unstable_by_key(|&(symbol, code_length)| (code_length, symbol)); |
|
165 | 1.88M | let zero_code_length_count = code_lengths.partition_point(|&(_, code_length)| code_length == 0); <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::symbols::{closure#1}Line | Count | Source | 165 | 1.68M | let zero_code_length_count = code_lengths.partition_point(|&(_, code_length)| code_length == 0); |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::symbols::{closure#1}Line | Count | Source | 165 | 201k | let zero_code_length_count = code_lengths.partition_point(|&(_, code_length)| code_length == 0); |
|
166 | | |
167 | 358k | match (&code_lengths[zero_code_length_count..], &*code_lengths) { |
168 | 26.0k | (&[(first_symbol, 1)], _) => vec![(first_symbol, vec![])], |
169 | | |
170 | 332k | (&[(first_symbol, first_code_length), ref rest_code_lengths @ ..], &[.., (_, last_code_length)]) => { |
171 | 332k | let mut code = Vec::with_capacity(last_code_length.into()); |
172 | 332k | code.resize(first_code_length.into(), 0); |
173 | | |
174 | 332k | let mut symbols = Vec::with_capacity(code_lengths.len()); |
175 | 332k | symbols.push((first_symbol, code.clone())); |
176 | 1.95M | for &(symbol, code_length) in rest_code_lengths { |
177 | 2.21M | for code_bit in code.iter_mut().rev() { |
178 | 2.21M | *code_bit ^= 1; |
179 | 2.21M | if *code_bit == 1 { |
180 | 1.59M | break; |
181 | 617k | } |
182 | | } |
183 | 1.61M | code.resize(code_length.into(), 0); |
184 | 1.61M | symbols.push((symbol, code.clone())); |
185 | | } |
186 | 332k | symbols |
187 | | } |
188 | 66 | _ => vec![], |
189 | | } |
190 | 358k | } <webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u8>>::symbols Line | Count | Source | 160 | 318k | fn symbols(code_lengths: &mut [(S, u8)]) -> Vec<(S, Vec<u8>)> | 161 | 318k | where | 162 | 318k | S: Copy + Ord + 'static, | 163 | | { | 164 | 318k | code_lengths.sort_unstable_by_key(|&(symbol, code_length)| (code_length, symbol)); | 165 | 318k | let zero_code_length_count = code_lengths.partition_point(|&(_, code_length)| code_length == 0); | 166 | | | 167 | 318k | match (&code_lengths[zero_code_length_count..], &*code_lengths) { | 168 | 21.2k | (&[(first_symbol, 1)], _) => vec![(first_symbol, vec![])], | 169 | | | 170 | 296k | (&[(first_symbol, first_code_length), ref rest_code_lengths @ ..], &[.., (_, last_code_length)]) => { | 171 | 296k | let mut code = Vec::with_capacity(last_code_length.into()); | 172 | 296k | code.resize(first_code_length.into(), 0); | 173 | | | 174 | 296k | let mut symbols = Vec::with_capacity(code_lengths.len()); | 175 | 296k | symbols.push((first_symbol, code.clone())); | 176 | 1.57M | for &(symbol, code_length) in rest_code_lengths { | 177 | 1.65M | for code_bit in code.iter_mut().rev() { | 178 | 1.65M | *code_bit ^= 1; | 179 | 1.65M | if *code_bit == 1 { | 180 | 1.27M | break; | 181 | 383k | } | 182 | | } | 183 | 1.28M | code.resize(code_length.into(), 0); | 184 | 1.28M | symbols.push((symbol, code.clone())); | 185 | | } | 186 | 296k | symbols | 187 | | } | 188 | 52 | _ => vec![], | 189 | | } | 190 | 318k | } |
<webpsan::parse::bitstream::CanonicalHuffmanTree<bitstream_io::LittleEndian, u16>>::symbols Line | Count | Source | 160 | 40.5k | fn symbols(code_lengths: &mut [(S, u8)]) -> Vec<(S, Vec<u8>)> | 161 | 40.5k | where | 162 | 40.5k | S: Copy + Ord + 'static, | 163 | | { | 164 | 40.5k | code_lengths.sort_unstable_by_key(|&(symbol, code_length)| (code_length, symbol)); | 165 | 40.5k | let zero_code_length_count = code_lengths.partition_point(|&(_, code_length)| code_length == 0); | 166 | | | 167 | 40.5k | match (&code_lengths[zero_code_length_count..], &*code_lengths) { | 168 | 4.84k | (&[(first_symbol, 1)], _) => vec![(first_symbol, vec![])], | 169 | | | 170 | 35.7k | (&[(first_symbol, first_code_length), ref rest_code_lengths @ ..], &[.., (_, last_code_length)]) => { | 171 | 35.7k | let mut code = Vec::with_capacity(last_code_length.into()); | 172 | 35.7k | code.resize(first_code_length.into(), 0); | 173 | | | 174 | 35.7k | let mut symbols = Vec::with_capacity(code_lengths.len()); | 175 | 35.7k | symbols.push((first_symbol, code.clone())); | 176 | 374k | for &(symbol, code_length) in rest_code_lengths { | 177 | 555k | for code_bit in code.iter_mut().rev() { | 178 | 555k | *code_bit ^= 1; | 179 | 555k | if *code_bit == 1 { | 180 | 321k | break; | 181 | 234k | } | 182 | | } | 183 | 338k | code.resize(code_length.into(), 0); | 184 | 338k | symbols.push((symbol, code.clone())); | 185 | | } | 186 | 35.7k | symbols | 187 | | } | 188 | 14 | _ => vec![], | 189 | | } | 190 | 40.5k | } |
|
191 | | } |
192 | | |
193 | | impl<E: Endianness, S: Clone + Default> Default for CanonicalHuffmanTree<E, S> { |
194 | | fn default() -> Self { |
195 | | Self::from_symbols(vec![(S::default(), vec![])]).unwrap_or_else(|_| unreachable!()) |
196 | | } |
197 | | } |