keramics_compression/
zlib.rs

1/* Copyright 2024-2025 Joachim Metz <joachim.metz@gmail.com>
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may
5 * obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software
8 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10 * License for the specific language governing permissions and limitations
11 * under the License.
12 */
13
14//! ZLIB decompression.
15//!
16//! Provides decompression support for ZLIB compressed data (RFC 1950).
17
18use keramics_checksums::Adler32Context;
19use keramics_core::ErrorTrace;
20use keramics_core::mediator::{Mediator, MediatorReference};
21use keramics_types::bytes_to_u32_be;
22
23use super::deflate::{DeflateBitstream, DeflateContext};
24
25/// Data header used by ZLIB compressed data.
26struct ZlibDataHeader {
27    /// Header size.
28    header_size: usize,
29}
30
31impl ZlibDataHeader {
32    /// Creates a new data header.
33    pub fn new() -> Self {
34        Self { header_size: 0 }
35    }
36
37    /// Reads the data header for debugging.
38    pub fn debug_read_data(data: &[u8]) -> String {
39        let mut string_parts: Vec<String> = Vec::new();
40        string_parts.push(format!("ZlibDataHeader {{\n"));
41
42        let compression_data: u8 = data[0];
43
44        let compression_method: u8 = compression_data & 0x0f;
45        string_parts.push(format!("    compression_method: {},\n", compression_method));
46
47        let compression_window_bits: u8 = (compression_data >> 4) + 8;
48        let compression_window_size: u32 = 1u32 << compression_window_bits;
49        string_parts.push(format!(
50            "    compression_window_size: {} bytes ({}),\n",
51            compression_window_size, compression_window_bits,
52        ));
53
54        let flags: u8 = data[1];
55        string_parts.push(format!("    check_bits: 0x{:02x},\n", flags & 0x1f));
56        string_parts.push(format!(
57            "    preset_dictionary_flag: {},\n",
58            (flags & 0x20) >> 5
59        ));
60        string_parts.push(format!("    compression_level: {},\n", flags >> 6));
61
62        if flags & 0x20 != 0 {
63            let preset_dictionary_identifier: u32 = bytes_to_u32_be!(data, 0);
64            string_parts.push(format!(
65                "    preset_dictionary_identifier: {},\n",
66                preset_dictionary_identifier
67            ));
68        }
69        string_parts.push(format!("}}\n\n"));
70
71        string_parts.join("")
72    }
73
74    /// Reads the data header.
75    pub fn read_data(&mut self, data: &[u8]) -> Result<(), ErrorTrace> {
76        if data.len() < 2 {
77            return Err(keramics_core::error_trace_new!(
78                "Unsupported zlib data header data size"
79            ));
80        }
81        let compression_data: u8 = data[0];
82
83        let compression_method: u8 = compression_data & 0x0f;
84
85        if compression_method != 8 {
86            return Err(keramics_core::error_trace_new!(format!(
87                "Unsupported compression method: {}",
88                compression_method
89            )));
90        }
91        let compression_window_bits: u8 = (compression_data >> 4) + 8;
92        let compression_window_size: u32 = 1u32 << compression_window_bits;
93
94        if compression_window_size > 32768 {
95            return Err(keramics_core::error_trace_new!(format!(
96                "Unsupported compression window size: {}",
97                compression_window_size
98            )));
99        }
100        self.header_size = 2;
101
102        let flags: u8 = data[1];
103
104        if flags & 0x20 != 0 {
105            if data.len() < 6 {
106                return Err(keramics_core::error_trace_new!(
107                    "Unsupported zlib data header data size"
108                ));
109            }
110            self.header_size += 4;
111        }
112        Ok(())
113    }
114}
115
116/// Context for decompressing ZLIB compressed data.
117pub struct ZlibContext {
118    /// Mediator.
119    mediator: MediatorReference,
120
121    /// Uncompressed data size.
122    pub uncompressed_data_size: usize,
123}
124
125impl ZlibContext {
126    /// Creates a new context.
127    pub fn new() -> Self {
128        Self {
129            mediator: Mediator::current(),
130            uncompressed_data_size: 0,
131        }
132    }
133
134    /// Decompress data.
135    pub fn decompress(
136        &mut self,
137        compressed_data: &[u8],
138        uncompressed_data: &mut [u8],
139    ) -> Result<(), ErrorTrace> {
140        let mut data_header: ZlibDataHeader = ZlibDataHeader::new();
141
142        if self.mediator.debug_output {
143            let header_size: usize = if compressed_data[1] & 0x20 == 0 { 2 } else { 6 };
144
145            self.mediator.debug_print(format!(
146                "ZlibDataHeader data of size: {} at offset: 0 (0x00000000)\n",
147                header_size,
148            ));
149            self.mediator
150                .debug_print_data(&compressed_data[0..header_size], true);
151            self.mediator
152                .debug_print(ZlibDataHeader::debug_read_data(compressed_data));
153        }
154        data_header.read_data(compressed_data)?;
155
156        let mut bitstream: DeflateBitstream =
157            DeflateBitstream::new(&compressed_data, data_header.header_size);
158        let mut deflate_context: DeflateContext = DeflateContext::new();
159        deflate_context.decompress_bitstream(&mut bitstream, uncompressed_data)?;
160
161        bitstream.unread_data();
162
163        if 4 < bitstream.data_size - bitstream.data_offset {
164            let stored_checksum: u32 = bytes_to_u32_be!(compressed_data, bitstream.data_offset);
165
166            let mut adler32_context: Adler32Context = Adler32Context::new(1);
167            adler32_context.update(uncompressed_data);
168            let calculated_checksum: u32 = adler32_context.finalize();
169
170            if stored_checksum != calculated_checksum {
171                return Err(keramics_core::error_trace_new!(format!(
172                    "Mismatch between stored: 0x{:08x} and calculated: 0x{:08x} checksums",
173                    stored_checksum, calculated_checksum
174                )));
175            }
176        }
177        self.uncompressed_data_size = deflate_context.uncompressed_data_size;
178
179        Ok(())
180    }
181}
182
183#[cfg(test)]
184mod tests {
185    use super::*;
186
187    use std::fs;
188
189    fn get_test_data() -> Vec<u8> {
190        return vec![
191            0x78, 0x9c, 0xdd, 0x5a, 0x4b, 0x73, 0xdc, 0xc6, 0x11, 0xbe, 0xeb, 0x57, 0x74, 0xb6,
192            0x2a, 0x15, 0xb2, 0x0a, 0x5a, 0x29, 0xce, 0xdb, 0x3e, 0xd1, 0x22, 0x15, 0x6f, 0x22,
193            0x2f, 0x55, 0x24, 0x15, 0xc5, 0xe5, 0xf2, 0x61, 0x16, 0x68, 0x2c, 0x26, 0x1a, 0xcc,
194            0xc0, 0x33, 0x03, 0x2e, 0x91, 0x5f, 0x9f, 0xea, 0x9e, 0x07, 0x06, 0xbb, 0x4b, 0x59,
195            0xa9, 0xdc, 0xe2, 0x83, 0x4b, 0x24, 0x81, 0x9e, 0x9e, 0x7e, 0x7c, 0xfd, 0x75, 0x37,
196            0x5e, 0xc0, 0x2f, 0xfd, 0x77, 0x35, 0x88, 0xba, 0x43, 0x78, 0x27, 0x6b, 0xd4, 0x0e,
197            0x5f, 0x7c, 0xe6, 0xc9, 0x7f, 0xa0, 0x75, 0xd2, 0x68, 0xf8, 0x6a, 0xfd, 0xba, 0x82,
198            0xbf, 0x09, 0x3d, 0x0a, 0x3b, 0xc1, 0x57, 0xaf, 0x5f, 0xff, 0xfe, 0xd9, 0x97, 0x3a,
199            0xef, 0x87, 0xaf, 0x5f, 0xbd, 0x3a, 0x1c, 0x0e, 0x6b, 0xc1, 0xc7, 0xac, 0x8d, 0xdd,
200            0xbf, 0x52, 0xe1, 0x28, 0xf7, 0xea, 0x05, 0xbd, 0xf8, 0x70, 0x73, 0xf7, 0xfd, 0x3d,
201            0x5c, 0x6d, 0xaf, 0xe1, 0xcd, 0xed, 0xf6, 0x7a, 0xf3, 0xb0, 0xb9, 0xdd, 0xde, 0xc3,
202            0xdb, 0xdb, 0x3b, 0xf8, 0x70, 0x7f, 0x53, 0xc1, 0xdd, 0xcd, 0xfb, 0xbb, 0xdb, 0xeb,
203            0x0f, 0x6f, 0xe8, 0xd7, 0x15, 0x3f, 0x75, 0xbd, 0xb9, 0x7f, 0xb8, 0xdb, 0x7c, 0xfb,
204            0x81, 0x7e, 0xc3, 0x02, 0x7e, 0xbb, 0x86, 0x6b, 0x6c, 0xa5, 0x96, 0x5e, 0x1a, 0xed,
205            0xd6, 0x2f, 0xa2, 0x36, 0xab, 0x78, 0xa3, 0x15, 0xb8, 0x4e, 0x28, 0x05, 0x3d, 0x0a,
206            0x0d, 0xbe, 0x43, 0xf0, 0x68, 0x7b, 0x07, 0x42, 0x37, 0x50, 0x1b, 0xdd, 0x84, 0xb7,
207            0xa0, 0x35, 0x16, 0x46, 0x87, 0x15, 0x58, 0x1c, 0xac, 0x69, 0xc6, 0x9a, 0x7e, 0x5d,
208            0x45, 0x51, 0xf4, 0x6c, 0x23, 0x9d, 0xb7, 0x72, 0x37, 0xd2, 0xef, 0x41, 0x38, 0x68,
209            0xe8, 0x48, 0x6c, 0x60, 0x37, 0xc1, 0x3d, 0xd6, 0x41, 0xc8, 0x6f, 0xc1, 0x77, 0xd6,
210            0x8c, 0xfb, 0x0e, 0xfe, 0x02, 0xa6, 0x05, 0xdf, 0x49, 0x07, 0x8d, 0xa9, 0xc7, 0x1e,
211            0xb5, 0x3f, 0xd6, 0xcb, 0xd8, 0x13, 0xc5, 0x6a, 0x33, 0x4c, 0x56, 0xee, 0x3b, 0x0f,
212            0xe6, 0xa0, 0xd1, 0x82, 0xb1, 0x80, 0xda, 0x4b, 0x3f, 0x81, 0x18, 0x7d, 0x67, 0xac,
213            0xfc, 0x37, 0x9f, 0x17, 0xe5, 0x9c, 0x7b, 0xc3, 0x77, 0xc2, 0x83, 0x74, 0xb0, 0xb7,
214            0x42, 0x7b, 0xa9, 0xf7, 0xfc, 0x50, 0xb4, 0x43, 0xa1, 0x00, 0xee, 0x85, 0x82, 0x1b,
215            0x16, 0x7d, 0xa2, 0xc4, 0xa8, 0xe9, 0x82, 0xac, 0x3d, 0x82, 0xa8, 0x59, 0x4a, 0xd2,
216            0x42, 0x37, 0x20, 0x94, 0x8a, 0x62, 0x8c, 0xef, 0x30, 0x2a, 0x28, 0xd1, 0x85, 0xa3,
217            0x6b, 0xa3, 0xbd, 0x35, 0xaa, 0x02, 0x61, 0x31, 0xfd, 0xa0, 0x58, 0xe9, 0x8a, 0x6e,
218            0x43, 0xbf, 0x1d, 0x75, 0x83, 0x16, 0x6a, 0xd3, 0xf7, 0x46, 0x47, 0x49, 0xf1, 0x41,
219            0x38, 0x48, 0xdf, 0x05, 0x39, 0xe1, 0xc0, 0x35, 0xbc, 0x35, 0x96, 0xf5, 0x18, 0x46,
220            0x3b, 0x18, 0x87, 0x6e, 0xb6, 0x6a, 0x76, 0x78, 0xf2, 0xd1, 0x2a, 0x4a, 0x59, 0xf1,
221            0x55, 0x1c, 0x5c, 0xc8, 0xcb, 0xf0, 0xaa, 0x39, 0xa0, 0xad, 0xa0, 0x91, 0x16, 0x6b,
222            0x4f, 0x4a, 0x48, 0x1d, 0xfe, 0x5d, 0x81, 0x37, 0x50, 0x8b, 0xd1, 0x21, 0x3d, 0x17,
223            0xa5, 0x84, 0x3f, 0xb1, 0x05, 0x2c, 0xf4, 0x42, 0x8b, 0x3d, 0x92, 0xf3, 0xe8, 0x5c,
224            0x37, 0xd6, 0x5d, 0x54, 0xac, 0x82, 0x43, 0x87, 0x7c, 0xfd, 0xdd, 0x14, 0xb4, 0x17,
225            0x2c, 0xbb, 0xb4, 0xcc, 0x41, 0x52, 0x34, 0x19, 0x0b, 0x17, 0x52, 0x5e, 0x06, 0xf7,
226            0xb8, 0x4e, 0x0e, 0x24, 0xa9, 0x95, 0xad, 0x9f, 0x60, 0x40, 0x5b, 0x93, 0xe8, 0x8b,
227            0x3f, 0xbc, 0xfe, 0xf5, 0x25, 0x1f, 0x67, 0x2c, 0x46, 0xc3, 0x27, 0x41, 0xa3, 0x77,
228            0x5e, 0xe8, 0x86, 0x7c, 0xe0, 0x3a, 0x61, 0xd1, 0x25, 0x89, 0xf2, 0x12, 0x76, 0xa8,
229            0xb1, 0x95, 0xb5, 0x14, 0x6a, 0x29, 0xbd, 0xd0, 0x73, 0x76, 0xf9, 0x0f, 0x66, 0x5c,
230            0xc1, 0x85, 0xb1, 0xfc, 0x2f, 0xbb, 0xba, 0x2c, 0xbd, 0x2e, 0x34, 0xdb, 0xe4, 0x51,
231            0x36, 0x23, 0xc9, 0xb2, 0x50, 0xc6, 0x47, 0x14, 0x80, 0x4f, 0x68, 0x6b, 0xe9, 0x48,
232            0x91, 0x01, 0x6d, 0x2f, 0x9d, 0xe3, 0x80, 0xe7, 0x38, 0x0b, 0x49, 0xc0, 0x6e, 0x39,
233            0x09, 0xb5, 0x7b, 0x33, 0xda, 0x1a, 0x57, 0x94, 0x5e, 0xfd, 0x71, 0xa4, 0x0d, 0x16,
234            0x5b, 0xb4, 0x16, 0x9b, 0xf0, 0xd7, 0x96, 0x2d, 0xfe, 0x89, 0x8e, 0xe8, 0x4d, 0x23,
235            0x5b, 0x59, 0x0b, 0xce, 0xaa, 0xe4, 0x60, 0xa9, 0x6b, 0x35, 0xb2, 0x29, 0x76, 0xa3,
236            0x07, 0x6d, 0x3c, 0x28, 0xd9, 0x4b, 0x3a, 0xdd, 0x1b, 0x70, 0xa6, 0xf5, 0x07, 0x0a,
237            0x2f, 0xc7, 0x07, 0x42, 0x6d, 0x1a, 0xac, 0x72, 0xee, 0xb1, 0xa0, 0x28, 0x26, 0x3c,
238            0x50, 0xa5, 0xfc, 0x6f, 0xe5, 0x7e, 0xb4, 0xfc, 0x77, 0x68, 0xa5, 0xc2, 0x02, 0x3e,
239            0x6e, 0x77, 0xff, 0xc2, 0xda, 0x9f, 0xaa, 0x2e, 0xf4, 0x14, 0x7e, 0x67, 0xd1, 0x8d,
240            0x8a, 0xf3, 0xa3, 0xb5, 0xa6, 0x87, 0x1e, 0xeb, 0x4e, 0x68, 0x59, 0x8b, 0x94, 0x20,
241            0xde, 0x0a, 0xed, 0xe8, 0x49, 0x91, 0x02, 0x8a, 0x7f, 0xa3, 0xe2, 0x8f, 0x2d, 0x08,
242            0x08, 0xe6, 0x61, 0x71, 0xd5, 0xf2, 0x82, 0x51, 0xc6, 0xd1, 0x35, 0x6b, 0xd3, 0x0f,
243            0x92, 0x12, 0xca, 0xb0, 0x72, 0xf1, 0x9a, 0x7b, 0xd4, 0x68, 0x05, 0x3d, 0xb2, 0xb8,
244            0x70, 0x89, 0x5e, 0xb5, 0xd1, 0x8f, 0x01, 0xbd, 0x1d, 0xc9, 0x09, 0xb9, 0xdb, 0x63,
245            0x23, 0x05, 0xf8, 0x69, 0x28, 0xaf, 0xfd, 0xd1, 0xd8, 0x4f, 0x27, 0xa0, 0x70, 0x30,
246            0xf6, 0x13, 0x6b, 0xcc, 0x38, 0x44, 0x91, 0x36, 0xa7, 0x80, 0xd4, 0xe9, 0x1a, 0x39,
247            0x01, 0x82, 0xe9, 0xe2, 0xb5, 0x7a, 0xd1, 0x20, 0x88, 0x47, 0x21, 0x95, 0xd8, 0xa9,
248            0x94, 0xff, 0x05, 0x2e, 0x55, 0x84, 0xa6, 0x14, 0x80, 0xb5, 0x88, 0xa1, 0x24, 0x32,
249            0x2e, 0x24, 0x74, 0xd3, 0xc6, 0xcb, 0x1a, 0x33, 0xbc, 0x05, 0x4b, 0x61, 0x43, 0x67,
250            0x13, 0xac, 0x78, 0x4f, 0xb5, 0x85, 0x2d, 0x94, 0xb4, 0x8d, 0x22, 0x2e, 0x84, 0x06,
251            0x7c, 0x12, 0xfd, 0xa0, 0x90, 0x5e, 0x1c, 0xac, 0x79, 0x94, 0xf1, 0x45, 0x7a, 0xf2,
252            0x6a, 0x18, 0x50, 0x37, 0xf2, 0x09, 0x76, 0xa8, 0xcc, 0xe1, 0x72, 0xb6, 0xc2, 0x35,
253            0x5a, 0xf9, 0x28, 0xbc, 0x7c, 0x44, 0x20, 0x83, 0xb8, 0xd5, 0x71, 0x04, 0xd0, 0x19,
254            0xe7, 0x6d, 0x10, 0x6f, 0x1f, 0x25, 0x05, 0x1b, 0x24, 0xc5, 0x77, 0xc2, 0x91, 0xf3,
255            0x34, 0xa7, 0x62, 0x43, 0x67, 0x50, 0xf4, 0x5b, 0xd3, 0x07, 0xac, 0xa2, 0xa3, 0xd8,
256            0x5d, 0x94, 0x0b, 0x87, 0x4e, 0xd6, 0x5d, 0x01, 0x06, 0xd8, 0x48, 0x6f, 0x2c, 0xa5,
257            0xbb, 0xc5, 0x47, 0xc9, 0xae, 0xa4, 0x28, 0xd6, 0xc6, 0xc7, 0x3c, 0x01, 0x54, 0x62,
258            0x67, 0x6c, 0xfa, 0xc9, 0xd8, 0xe4, 0xe6, 0x32, 0x9b, 0xa2, 0x30, 0xaa, 0x72, 0xe8,
259            0x50, 0x7b, 0xb6, 0xbe, 0x80, 0x43, 0x67, 0x14, 0x27, 0x05, 0x18, 0x2b, 0xf7, 0x52,
260            0x0b, 0x75, 0xc6, 0xe7, 0xa7, 0x78, 0x9c, 0x70, 0xaa, 0x5d, 0xa4, 0x7f, 0x05, 0xc7,
261            0xe6, 0x8b, 0xd6, 0xa3, 0x68, 0x8e, 0xbe, 0x63, 0xf1, 0xb1, 0x6a, 0x58, 0xec, 0x85,
262            0xcc, 0xf9, 0x89, 0x83, 0xb0, 0x1c, 0x29, 0x64, 0x17, 0xbe, 0x46, 0x8f, 0x16, 0xd5,
263            0x04, 0x4a, 0xea, 0x4f, 0x6c, 0xb8, 0x9d, 0xd4, 0x1c, 0x27, 0x5a, 0xf4, 0x78, 0x99,
264            0x9c, 0x2e, 0xb5, 0x47, 0xdb, 0x8a, 0x9a, 0x8b, 0x44, 0x55, 0xd4, 0xc8, 0x6c, 0xd4,
265            0x13, 0xa5, 0xc8, 0x3a, 0x68, 0xda, 0xd9, 0xeb, 0x6f, 0x08, 0xca, 0x63, 0x8d, 0x3f,
266            0xeb, 0xf1, 0xe3, 0x1c, 0xc8, 0x29, 0x5b, 0x9c, 0x97, 0x0d, 0x18, 0x13, 0x2e, 0xd5,
267            0xd2, 0xac, 0x07, 0x09, 0x5b, 0xf8, 0x84, 0x63, 0xb8, 0x89, 0x4c, 0x24, 0x49, 0x32,
268            0xc1, 0x36, 0xfc, 0x96, 0xb1, 0xcf, 0x2a, 0x5f, 0x15, 0x49, 0xe1, 0x09, 0xf5, 0x8d,
269            0x16, 0x4a, 0x25, 0xd8, 0x76, 0xe3, 0xae, 0x97, 0x3e, 0x82, 0x47, 0xe2, 0x1d, 0x1c,
270            0x5d, 0xac, 0x39, 0xab, 0x17, 0x53, 0x81, 0x0f, 0x62, 0x1c, 0x3f, 0xa1, 0x15, 0xc9,
271            0xcb, 0x5c, 0xee, 0x3e, 0x5b, 0x2d, 0x4a, 0xa2, 0x42, 0xa8, 0xcc, 0xc7, 0x53, 0xbc,
272            0xef, 0xb0, 0x13, 0xaa, 0x05, 0xd3, 0x3e, 0x4f, 0x5e, 0xbe, 0xac, 0xda, 0xc3, 0x2a,
273            0xdf, 0x69, 0x15, 0x65, 0x85, 0x7a, 0x9f, 0x61, 0xd9, 0xb4, 0x80, 0x0a, 0x6b, 0x6f,
274            0x8d, 0x96, 0x75, 0x45, 0x5e, 0xd8, 0x09, 0xc5, 0x71, 0x74, 0xb0, 0xf4, 0x9e, 0x66,
275            0xf2, 0x31, 0xea, 0x68, 0x7d, 0xa0, 0x2c, 0x28, 0x8d, 0x8e, 0xb3, 0xa1, 0xc8, 0x4e,
276            0xde, 0xcd, 0xc9, 0xc2, 0xf6, 0x77, 0xd5, 0x67, 0x4b, 0x51, 0xc6, 0xae, 0xf2, 0x0c,
277            0xa3, 0x0b, 0x9d, 0xa0, 0x17, 0x52, 0xd1, 0xcb, 0x4a, 0x3a, 0xef, 0xaa, 0xb2, 0x64,
278            0x65, 0x2a, 0xe4, 0x26, 0xe7, 0xb1, 0x77, 0x25, 0x84, 0x4b, 0xe7, 0x46, 0xa4, 0x12,
279            0x52, 0x73, 0x8d, 0x8c, 0x4f, 0x04, 0xf7, 0x53, 0xe5, 0x0b, 0x6c, 0x25, 0x73, 0xad,
280            0xd2, 0xe8, 0x55, 0x01, 0x23, 0x8b, 0x28, 0x28, 0xac, 0x4d, 0x76, 0x6b, 0xa4, 0xab,
281            0x47, 0xc7, 0x55, 0x9e, 0x4f, 0xec, 0x19, 0x2f, 0x23, 0x8d, 0xfc, 0xc8, 0x88, 0x37,
282            0x97, 0x26, 0x7c, 0x4a, 0x46, 0x58, 0xde, 0x35, 0xc5, 0x63, 0x6d, 0xb4, 0x1b, 0x64,
283            0x3d, 0x9a, 0xd1, 0xa9, 0x09, 0x7a, 0x61, 0x3f, 0x11, 0xf4, 0xd9, 0x99, 0x1d, 0x25,
284            0xca, 0x85, 0x4e, 0xee, 0x35, 0x63, 0xbf, 0xd4, 0xec, 0x23, 0x36, 0xec, 0xd9, 0x48,
285            0x24, 0xb0, 0x5a, 0x6d, 0x8d, 0x07, 0x01, 0x65, 0xae, 0xae, 0x57, 0xa7, 0x29, 0x7c,
286            0xc4, 0xaf, 0xf3, 0xb5, 0x53, 0x06, 0xfe, 0x22, 0xe5, 0x29, 0x0d, 0x48, 0xf8, 0xd8,
287            0x1f, 0x1d, 0x0a, 0x9d, 0x70, 0xb0, 0x43, 0xd4, 0x60, 0xb1, 0x46, 0x46, 0xf2, 0xdd,
288            0xb4, 0x38, 0x67, 0x4e, 0x42, 0x87, 0x3f, 0x8f, 0xa8, 0xbd, 0xa2, 0x63, 0x6b, 0x63,
289            0x07, 0x13, 0xca, 0x35, 0x11, 0xde, 0x22, 0xfd, 0x02, 0x10, 0x7d, 0xb5, 0x86, 0xbf,
290            0x12, 0xad, 0xa2, 0x63, 0xdf, 0xe4, 0xeb, 0x27, 0x66, 0x05, 0xf7, 0x63, 0x28, 0xae,
291            0x31, 0x56, 0xcf, 0x36, 0x33, 0x45, 0x9a, 0x95, 0xa8, 0x8c, 0xa2, 0xee, 0xa0, 0x30,
292            0x10, 0x10, 0x84, 0xec, 0xa6, 0xc0, 0xe2, 0x98, 0x17, 0xfc, 0x60, 0x46, 0x10, 0xc4,
293            0xf0, 0x06, 0xf4, 0xa3, 0x50, 0x29, 0xfc, 0x0e, 0xc6, 0xaa, 0xe6, 0x20, 0x89, 0x6b,
294            0x68, 0xa3, 0x5f, 0xb2, 0xe7, 0x9d, 0x7c, 0xe4, 0x1f, 0x5f, 0xd6, 0x9d, 0xb0, 0x7b,
295            0x6a, 0x9c, 0xcc, 0x24, 0x94, 0x9f, 0x5e, 0xb6, 0x16, 0xb1, 0x02, 0x69, 0x2d, 0x3e,
296            0x9a, 0x9a, 0x80, 0xfc, 0xa4, 0x9a, 0xc7, 0xfe, 0x8f, 0x0e, 0x4c, 0xdd, 0x16, 0x56,
297            0x44, 0x07, 0x07, 0x8a, 0xe3, 0x13, 0xa4, 0x9b, 0xe1, 0x7c, 0x18, 0x77, 0x4a, 0xd6,
298            0x6a, 0xa2, 0x40, 0x1d, 0x94, 0x98, 0xaa, 0xf9, 0x37, 0x03, 0xda, 0x50, 0x6a, 0x1d,
299            0xff, 0x26, 0x12, 0x8b, 0xb2, 0x6f, 0x2b, 0x69, 0x7e, 0xc6, 0x62, 0x26, 0xcb, 0x27,
300            0x27, 0x9e, 0x29, 0xe7, 0x8c, 0x2d, 0xc1, 0x41, 0xbf, 0x2b, 0x1c, 0xf4, 0x5e, 0x10,
301            0xe8, 0xfe, 0x1f, 0x78, 0xe7, 0x02, 0x9f, 0x6a, 0x1c, 0x3c, 0x25, 0x98, 0xf3, 0x29,
302            0x19, 0x59, 0x41, 0x17, 0x1a, 0xa2, 0x4b, 0x18, 0xc2, 0x5d, 0x0b, 0xef, 0xf5, 0xe2,
303            0x13, 0x56, 0xd0, 0x89, 0x47, 0x64, 0x96, 0x97, 0x14, 0xe2, 0x3e, 0xda, 0xb4, 0x2d,
304            0xf1, 0x3c, 0x03, 0x0e, 0x95, 0xaa, 0xe2, 0xff, 0x65, 0x3f, 0x18, 0xeb, 0x83, 0x63,
305            0x32, 0x0e, 0x44, 0xa2, 0x1c, 0x59, 0x21, 0xc3, 0x4c, 0xba, 0x19, 0x99, 0x20, 0xf8,
306            0x28, 0x9d, 0x2a, 0x86, 0x41, 0x51, 0xbb, 0x69, 0xb4, 0x9a, 0x82, 0x95, 0x09, 0xbb,
307            0xa2, 0x6a, 0xb5, 0x12, 0xb2, 0x77, 0xf1, 0xd9, 0xe2, 0x72, 0xbb, 0x29, 0x08, 0x29,
308            0xad, 0x9b, 0x71, 0x53, 0x63, 0x8d, 0xce, 0x09, 0x2b, 0x39, 0x3b, 0x5b, 0x2b, 0xf5,
309            0x3e, 0x75, 0x34, 0x28, 0x53, 0xed, 0x2b, 0x13, 0xff, 0xc2, 0x5d, 0x82, 0x50, 0x46,
310            0x63, 0xac, 0x88, 0xb5, 0xe9, 0x77, 0x52, 0x67, 0x56, 0xcf, 0xaf, 0x1d, 0xbf, 0x90,
311            0x2e, 0x14, 0x3a, 0xdc, 0x58, 0x6d, 0xbd, 0x89, 0x24, 0x6f, 0xa9, 0x5c, 0x3c, 0xe2,
312            0x40, 0xae, 0x48, 0xb5, 0x6e, 0x0d, 0x9b, 0x96, 0xfc, 0x9f, 0x7b, 0x21, 0xe7, 0xa5,
313            0xa7, 0x98, 0xce, 0x4e, 0xf1, 0x72, 0x1f, 0x54, 0x10, 0x7b, 0x41, 0x7f, 0x66, 0x90,
314            0x8b, 0x8d, 0xfb, 0xc5, 0x5c, 0xb0, 0x32, 0xb7, 0xb6, 0xc6, 0xb9, 0x97, 0x6c, 0x30,
315            0xba, 0x46, 0x6d, 0x46, 0xe2, 0x4f, 0xe1, 0x67, 0xa9, 0x41, 0x80, 0x12, 0x07, 0x37,
316            0x4a, 0x4f, 0x57, 0x55, 0xb8, 0x0f, 0x45, 0x40, 0xf8, 0xac, 0xfc, 0xcc, 0x09, 0x8e,
317            0x50, 0xf1, 0x73, 0x00, 0xc7, 0x35, 0x21, 0x28, 0xee, 0x62, 0xab, 0x3d, 0xcb, 0xa9,
318            0x67, 0xe7, 0x4c, 0xe9, 0x5a, 0xc9, 0x1f, 0x3d, 0x33, 0x55, 0xdf, 0x61, 0xa0, 0x62,
319            0xcb, 0x48, 0x4c, 0x94, 0x29, 0x35, 0xa3, 0x31, 0x53, 0x52, 0xa3, 0x31, 0xe7, 0x58,
320            0x2c, 0x79, 0x89, 0x55, 0x85, 0xea, 0x40, 0x29, 0x4a, 0xde, 0x4b, 0xb1, 0x22, 0x5c,
321            0x22, 0x6c, 0x8d, 0xf0, 0x39, 0xf8, 0xb2, 0x75, 0xa5, 0xe3, 0x3e, 0xb1, 0x09, 0x50,
322            0xf0, 0xfb, 0x35, 0xdc, 0x61, 0x39, 0x19, 0x5a, 0xf3, 0xd1, 0xbd, 0x98, 0x66, 0x64,
323            0x3b, 0x46, 0xa1, 0xda, 0x0c, 0x32, 0x71, 0x9b, 0x05, 0x1e, 0x7d, 0x86, 0xe5, 0xb1,
324            0x4b, 0x88, 0x36, 0x62, 0x23, 0xc7, 0xbe, 0x0a, 0x71, 0x44, 0x8c, 0x46, 0xfa, 0xce,
325            0xe4, 0x8a, 0xbc, 0x6c, 0x9b, 0x43, 0x09, 0x7f, 0x06, 0xc9, 0xaa, 0xb9, 0x15, 0x62,
326            0x83, 0xcc, 0xa1, 0xd5, 0x23, 0x06, 0x2f, 0xb7, 0x46, 0x29, 0x73, 0x08, 0xf5, 0x3d,
327            0x61, 0xd7, 0xd7, 0xa9, 0xce, 0x5e, 0x88, 0xcb, 0x70, 0xd3, 0xd1, 0x79, 0xd8, 0x93,
328            0xbe, 0xa4, 0x5e, 0xe8, 0x37, 0x2c, 0xd6, 0x72, 0x90, 0x48, 0xa0, 0x55, 0x52, 0xdf,
329            0xdc, 0x1d, 0xd2, 0x7f, 0x27, 0x17, 0x15, 0x5c, 0x1f, 0x8e, 0x3b, 0x89, 0x6f, 0xb8,
330            0x8c, 0xa6, 0x33, 0x77, 0xc5, 0x99, 0x61, 0x70, 0x33, 0x53, 0x69, 0xea, 0xa3, 0xa8,
331            0x7f, 0x0f, 0x43, 0x1d, 0x4b, 0x21, 0x64, 0x4d, 0x2f, 0x35, 0xc5, 0x49, 0xe8, 0x1e,
332            0x5d, 0x71, 0x3c, 0x41, 0x5c, 0x0e, 0x69, 0x92, 0x49, 0xad, 0xfb, 0x9e, 0x8d, 0x81,
333            0x41, 0xce, 0xf2, 0xe4, 0xba, 0x38, 0xd9, 0xa2, 0x17, 0x52, 0x57, 0x89, 0x37, 0x17,
334            0x2d, 0x3c, 0x77, 0x07, 0x7a, 0x3a, 0xb9, 0x5c, 0x71, 0x70, 0x3e, 0x70, 0x0e, 0x88,
335            0x8a, 0x32, 0x6c, 0xae, 0x8e, 0x55, 0x8c, 0xee, 0x8a, 0x60, 0xb1, 0x41, 0xe2, 0x4d,
336            0x55, 0x41, 0x26, 0x38, 0x44, 0xfd, 0x9c, 0x6e, 0xf1, 0x6e, 0x61, 0x04, 0x71, 0x46,
337            0x9f, 0x63, 0x48, 0x5d, 0x32, 0xb7, 0x80, 0x9e, 0x49, 0x06, 0x2b, 0xd7, 0x18, 0x26,
338            0xb4, 0x03, 0x5a, 0xba, 0x26, 0x99, 0x33, 0x64, 0x9c, 0xf5, 0x73, 0xe1, 0x82, 0xc8,
339            0xe0, 0x8f, 0x2f, 0xba, 0x34, 0x5a, 0x73, 0x49, 0xa0, 0x95, 0xfd, 0x1f, 0x1b, 0x3f,
340            0x72, 0xf5, 0x6a, 0x7b, 0xfb, 0xb0, 0x79, 0x73, 0xb3, 0x02, 0x8f, 0x4f, 0x9e, 0xed,
341            0x4d, 0x69, 0x17, 0xcf, 0x20, 0xca, 0x5d, 0x9c, 0x53, 0x66, 0x57, 0x01, 0x01, 0x67,
342            0x32, 0xe5, 0xc4, 0xb2, 0xec, 0xaf, 0x42, 0x54, 0x6a, 0x3d, 0x05, 0x58, 0x14, 0x0d,
343            0xf7, 0x98, 0x73, 0xd0, 0xe1, 0x59, 0xb3, 0x12, 0x28, 0x09, 0x9a, 0xf3, 0x16, 0x62,
344            0x22, 0xa8, 0x31, 0x32, 0x84, 0x8b, 0xf0, 0x15, 0xaa, 0x2f, 0xb1, 0x6b, 0x21, 0xe6,
345            0xbc, 0x85, 0xcf, 0xda, 0x95, 0x83, 0x4d, 0x78, 0x50, 0x28, 0x1c, 0xb5, 0x53, 0xe5,
346            0x94, 0x3e, 0xbe, 0x32, 0x67, 0xeb, 0xa0, 0xa8, 0x09, 0xfe, 0x3a, 0xa9, 0x29, 0x92,
347            0x8e, 0xb3, 0xad, 0x67, 0x0b, 0x2d, 0xa2, 0xca, 0x7d, 0x56, 0x87, 0x6f, 0x4a, 0x30,
348            0x5f, 0x04, 0x59, 0x99, 0xd7, 0xcb, 0x01, 0x14, 0xc8, 0x76, 0xc6, 0x19, 0x2a, 0x99,
349            0xfb, 0xb9, 0x02, 0x9e, 0xca, 0x37, 0xb6, 0x3a, 0xb5, 0xb2, 0x48, 0x5c, 0xaf, 0x98,
350            0x72, 0xc5, 0xde, 0xe0, 0x8c, 0x95, 0xda, 0xa3, 0x4c, 0x61, 0x02, 0xf1, 0x88, 0x36,
351            0x38, 0xcb, 0x77, 0xd2, 0x36, 0x2f, 0xe9, 0x92, 0x53, 0xf6, 0x8d, 0xa6, 0xf9, 0x9c,
352            0x52, 0x13, 0x11, 0x0b, 0x14, 0x76, 0x0d, 0x0f, 0x5d, 0xe8, 0xc2, 0x08, 0xbf, 0x4e,
353            0xcd, 0x5c, 0xf8, 0x9b, 0xc9, 0x43, 0x68, 0xa5, 0xf3, 0x90, 0x4f, 0xa8, 0xa2, 0x79,
354            0x25, 0x86, 0xb2, 0x54, 0x27, 0xe6, 0x16, 0x23, 0xd6, 0xb4, 0x98, 0xcd, 0xe7, 0xb2,
355            0x21, 0x9a, 0x86, 0xfe, 0x6d, 0xa9, 0xdf, 0x29, 0x23, 0xb2, 0x90, 0x92, 0x54, 0x8f,
356            0x16, 0xfa, 0x92, 0x4c, 0xa8, 0x82, 0xf5, 0x9d, 0x6c, 0x16, 0xa1, 0xc3, 0xfd, 0x14,
357            0x8d, 0x37, 0x9a, 0x06, 0x75, 0x33, 0xf6, 0x89, 0xb6, 0x2e, 0x22, 0x26, 0x01, 0x4b,
358            0xe8, 0xff, 0x92, 0x3b, 0x8f, 0x31, 0x8d, 0x0d, 0x9c, 0x86, 0x18, 0x42, 0x9d, 0x4f,
359            0x26, 0x9e, 0x56, 0xc1, 0x0e, 0x03, 0x0f, 0xb0, 0xe3, 0x71, 0xfc, 0x05, 0xc3, 0x3c,
360            0xb7, 0xb7, 0x38, 0x6b, 0xa2, 0xb9, 0xab, 0x60, 0xda, 0xca, 0xc3, 0xfa, 0x40, 0x00,
361            0x8e, 0x06, 0x5f, 0x85, 0x2b, 0x48, 0x48, 0xbc, 0x47, 0xa9, 0x32, 0x8d, 0xe4, 0x24,
362            0xb1, 0xd6, 0x05, 0xcb, 0x3d, 0xc3, 0xe0, 0xe7, 0xd1, 0xde, 0x99, 0x95, 0x51, 0x10,
363            0x53, 0xec, 0x8a, 0x4c, 0x7b, 0x46, 0x9b, 0x6a, 0x4e, 0x9b, 0x96, 0x9b, 0xc5, 0xe9,
364            0x99, 0x56, 0xa4, 0x9c, 0xce, 0xe5, 0x54, 0x62, 0x79, 0x74, 0x74, 0x31, 0xcd, 0x9b,
365            0x15, 0x38, 0xd9, 0x56, 0x2d, 0xaa, 0x70, 0x66, 0xdd, 0x34, 0x4b, 0x66, 0x2a, 0x4d,
366            0x71, 0xb4, 0x18, 0xcb, 0xe4, 0x4e, 0xe5, 0xa8, 0x13, 0x58, 0x38, 0xe4, 0x0f, 0xdc,
367            0xec, 0xc4, 0x4d, 0x40, 0xe8, 0x55, 0x67, 0x16, 0xe8, 0xd6, 0xf0, 0x41, 0x2b, 0x74,
368            0x8e, 0x9d, 0x86, 0x4f, 0x83, 0x92, 0xb5, 0xa4, 0xf6, 0x97, 0x25, 0x16, 0x0b, 0x92,
369            0x3c, 0xdf, 0x98, 0x8e, 0x59, 0x64, 0x31, 0xcc, 0x2a, 0xc6, 0x58, 0xcf, 0x8e, 0xae,
370            0x66, 0xa6, 0x4f, 0x27, 0x1e, 0x0f, 0x72, 0x02, 0xd5, 0xdb, 0x95, 0xd3, 0xe7, 0xff,
371            0xa6, 0x35, 0x8b, 0x34, 0x8b, 0xd5, 0x2c, 0x02, 0x26, 0x88, 0x08, 0xd4, 0xb5, 0x49,
372            0xdb, 0xc7, 0xf0, 0xfe, 0xd6, 0x78, 0x7a, 0x29, 0x6f, 0x6f, 0xb8, 0xbe, 0xec, 0x4c,
373            0x68, 0xca, 0x28, 0x6d, 0xf7, 0xdc, 0xde, 0x51, 0x19, 0x61, 0xd5, 0xdc, 0x38, 0xa0,
374            0x75, 0xd8, 0x60, 0x58, 0x04, 0x51, 0x1a, 0x14, 0x2e, 0x89, 0x07, 0x05, 0x76, 0x11,
375            0x06, 0xa4, 0x1e, 0xe7, 0x96, 0x68, 0x6f, 0x31, 0x04, 0xfe, 0x14, 0x33, 0x84, 0x3b,
376            0x32, 0x7c, 0xc2, 0xba, 0x80, 0x78, 0x06, 0xde, 0x6c, 0x10, 0x8b, 0x7b, 0x61, 0xc3,
377            0x5e, 0xe9, 0xb8, 0xf7, 0x88, 0xbb, 0x80, 0x3f, 0xae, 0xe1, 0x21, 0x11, 0x10, 0x47,
378            0xb0, 0x58, 0xf0, 0xe8, 0xc6, 0x30, 0x72, 0xfa, 0x40, 0xb9, 0x8b, 0x8d, 0x10, 0x19,
379            0x3e, 0x2e, 0xd4, 0x02, 0x7d, 0x49, 0x6b, 0x0c, 0xd1, 0xd3, 0xdc, 0x2c, 0x33, 0x1a,
380            0x9a, 0x7a, 0xa1, 0x7d, 0xa4, 0x99, 0x7e, 0xfc, 0xd1, 0x58, 0x88, 0x31, 0x1c, 0x1e,
381            0x4e, 0x41, 0x9b, 0x34, 0x4e, 0x91, 0x32, 0xb7, 0xa9, 0x16, 0x7f, 0x1e, 0x65, 0xdc,
382            0x1e, 0x51, 0x41, 0x77, 0x46, 0x73, 0x49, 0x67, 0x97, 0x8e, 0xce, 0x9b, 0x9e, 0xd6,
383            0xd3, 0xa4, 0x8d, 0xd4, 0x34, 0x64, 0xaa, 0xad, 0xdc, 0x45, 0x57, 0xe4, 0xa6, 0x83,
384            0x26, 0xb5, 0x27, 0xf3, 0xd9, 0x94, 0x4d, 0xc9, 0x6f, 0xb1, 0x1a, 0x9c, 0x29, 0x01,
385            0xc1, 0x52, 0x7f, 0x5a, 0xc3, 0xb5, 0x74, 0xdc, 0x3a, 0xd1, 0xd2, 0xb6, 0x85, 0x8f,
386            0xc2, 0x92, 0x5d, 0xa6, 0x9c, 0x04, 0x59, 0xd5, 0xdd, 0x14, 0x1a, 0x58, 0xee, 0xbc,
387            0xa9, 0xc5, 0x9a, 0x61, 0x80, 0xbd, 0xc8, 0xcd, 0xcb, 0x3c, 0x05, 0xab, 0x66, 0x87,
388            0xc5, 0xdc, 0x77, 0xb3, 0xaa, 0x17, 0xa4, 0x2b, 0x0d, 0x0d, 0x8e, 0x5b, 0xd4, 0xf2,
389            0x69, 0x1a, 0x5f, 0x2e, 0x9c, 0x7b, 0x49, 0x73, 0x2d, 0xa1, 0x61, 0x75, 0x75, 0x0f,
390            0x9b, 0xfb, 0x15, 0x7c, 0x7b, 0x75, 0xbf, 0xb9, 0x4f, 0xc6, 0xfd, 0xb8, 0x79, 0xf8,
391            0xee, 0xf6, 0xc3, 0x03, 0x7c, 0xbc, 0xba, 0xbb, 0xbb, 0xda, 0x3e, 0x6c, 0x6e, 0xee,
392            0xe1, 0xf6, 0xae, 0x5c, 0xcb, 0xdf, 0xbe, 0x85, 0xab, 0xed, 0x0f, 0xf0, 0xf7, 0xcd,
393            0xf6, 0xba, 0x02, 0x94, 0x61, 0x03, 0xfc, 0x44, 0xd3, 0x51, 0x37, 0xdf, 0x44, 0x32,
394            0xae, 0x34, 0xc5, 0x98, 0x74, 0xce, 0x20, 0x9e, 0x93, 0x8a, 0x84, 0x53, 0x13, 0x1c,
395            0x82, 0xa9, 0xb8, 0x21, 0xb2, 0xa7, 0x10, 0x6b, 0x5a, 0x78, 0xd8, 0x3c, 0xbc, 0xbb,
396            0xa9, 0x60, 0x7b, 0xbb, 0x7d, 0xb9, 0xd9, 0xbe, 0xbd, 0xdb, 0x6c, 0xff, 0x7a, 0xf3,
397            0xfd, 0xcd, 0xf6, 0xa1, 0x82, 0xef, 0x6f, 0xee, 0xde, 0x7c, 0x77, 0xb5, 0x7d, 0xb8,
398            0xfa, 0x76, 0xf3, 0x6e, 0xf3, 0xf0, 0x03, 0x87, 0xd0, 0xdb, 0xcd, 0xc3, 0xf6, 0xe6,
399            0x3e, 0x7c, 0x3e, 0x70, 0x15, 0x65, 0xbc, 0xbf, 0xba, 0x7b, 0xd8, 0xbc, 0xf9, 0xf0,
400            0xee, 0xea, 0x0e, 0xde, 0x7f, 0xb8, 0x7b, 0x7f, 0x7b, 0x7f, 0x13, 0xaa, 0x6d, 0xd8,
401            0x16, 0x2a, 0xda, 0x2c, 0x58, 0x74, 0x83, 0xd1, 0x4e, 0xf2, 0xd6, 0x81, 0x37, 0x33,
402            0xa1, 0x2b, 0x5c, 0x86, 0x8b, 0x18, 0x06, 0x6b, 0x06, 0x2b, 0x89, 0x9e, 0xf3, 0x85,
403            0x5b, 0x18, 0x79, 0x56, 0xca, 0xf1, 0x37, 0x23, 0x6e, 0x31, 0x2f, 0x0d, 0xd3, 0x46,
404            0xe7, 0xc6, 0x9e, 0x7b, 0x95, 0x04, 0xd7, 0xd2, 0x31, 0xb2, 0x3b, 0x53, 0xcb, 0xdc,
405            0x26, 0x07, 0x50, 0x8f, 0x7b, 0x56, 0x9e, 0xc6, 0x96, 0x8b, 0xd6, 0xd3, 0x66, 0x36,
406            0xc4, 0xde, 0x9f, 0xd7, 0xf0, 0x2e, 0x9b, 0x94, 0x5e, 0x7a, 0x27, 0xc5, 0x4e, 0x2a,
407            0x5e, 0x9e, 0x6f, 0xa8, 0xf2, 0x02, 0x3e, 0x52, 0xec, 0x92, 0x1e, 0x41, 0x86, 0x36,
408            0xa0, 0x78, 0xd8, 0xe9, 0x3b, 0x34, 0x76, 0x2a, 0x46, 0x2d, 0x69, 0x93, 0xe5, 0x8d,
409            0xf5, 0xe5, 0xc8, 0x40, 0xe3, 0x5e, 0xc9, 0x3d, 0xea, 0x1a, 0x2f, 0xab, 0xbc, 0xed,
410            0xae, 0x16, 0xa3, 0xdc, 0x3c, 0xf9, 0xf9, 0xc5, 0x78, 0xbf, 0x08, 0x44, 0x81, 0x66,
411            0xfa, 0x4a, 0xee, 0x98, 0xd0, 0xb1, 0x72, 0x7b, 0x9a, 0x47, 0xe4, 0xbd, 0x45, 0x3a,
412            0xd2, 0xd3, 0x17, 0x08, 0x8e, 0xb7, 0xe3, 0xe7, 0xf3, 0x23, 0xa0, 0xe7, 0xa2, 0x7c,
413            0xd0, 0x50, 0x26, 0xb9, 0x4c, 0x49, 0x3e, 0x38, 0x4e, 0x04, 0xd8, 0xb5, 0xa2, 0x17,
414            0xfb, 0xe5, 0x0c, 0x9f, 0xde, 0x4e, 0x9f, 0x04, 0xcc, 0x1f, 0x07, 0xb8, 0x01, 0x69,
415            0xb7, 0x5e, 0x6c, 0x9f, 0x65, 0x43, 0xc4, 0x36, 0xac, 0x12, 0x88, 0xc0, 0x84, 0x99,
416            0x2e, 0x2d, 0xe4, 0xa2, 0xd0, 0x84, 0xd0, 0x34, 0x73, 0x13, 0xb5, 0xa7, 0x71, 0xb5,
417            0x0d, 0x3b, 0x73, 0xaa, 0xe2, 0xb9, 0x56, 0xd3, 0xd6, 0xf8, 0xb8, 0xd1, 0x65, 0x6b,
418            0x8e, 0x19, 0x63, 0xc6, 0xf0, 0x1b, 0xa9, 0xa3, 0x33, 0x0b, 0x5c, 0x2d, 0x27, 0x06,
419            0x17, 0x9f, 0xdd, 0x89, 0x27, 0xad, 0xe8, 0xda, 0xca, 0x84, 0x80, 0xdd, 0x1b, 0xd3,
420            0x1c, 0xa4, 0x2a, 0x67, 0x87, 0x9f, 0xc0, 0x79, 0x33, 0x0c, 0x82, 0xa6, 0x84, 0xc4,
421            0x09, 0x46, 0x52, 0xbc, 0x15, 0x52, 0x8d, 0x36, 0x54, 0x23, 0xa1, 0xda, 0x51, 0xcf,
422            0xe4, 0x86, 0x8b, 0xe0, 0x99, 0x2f, 0x41, 0x68, 0x0b, 0x40, 0xc1, 0x5b, 0xda, 0x23,
423            0x1c, 0x8c, 0xee, 0xb2, 0xe2, 0x38, 0x24, 0x82, 0x7e, 0x3c, 0x88, 0x8b, 0x32, 0xf2,
424            0x30, 0x5d, 0x34, 0x8f, 0x92, 0x97, 0xa4, 0x6d, 0xfc, 0x7c, 0xc3, 0x39, 0x19, 0x8d,
425            0x90, 0x3e, 0x6e, 0x88, 0xe2, 0x43, 0x06, 0xfc, 0x65, 0x0d, 0x57, 0x35, 0xd5, 0x04,
426            0xb2, 0x42, 0x42, 0x5e, 0x3a, 0xf9, 0x6a, 0x2e, 0xd4, 0x45, 0x52, 0x7c, 0xec, 0x88,
427            0xba, 0x2f, 0xd3, 0xf5, 0x78, 0x59, 0xf8, 0xd9, 0x75, 0x5b, 0x62, 0xa1, 0x75, 0x67,
428            0x4c, 0x98, 0x82, 0xf2, 0xa4, 0x73, 0xb1, 0x6c, 0xe7, 0x99, 0x2b, 0x08, 0x68, 0x91,
429            0xf1, 0xa4, 0x02, 0xc1, 0x1a, 0x0a, 0x5d, 0x63, 0xb8, 0xc4, 0x10, 0xc6, 0xa0, 0x11,
430            0xfd, 0x26, 0x8e, 0x3b, 0xec, 0x35, 0x7d, 0x5a, 0x32, 0x0f, 0xc4, 0x82, 0x59, 0x55,
431            0xd2, 0x1d, 0xcc, 0x4e, 0xc5, 0x29, 0x14, 0xf3, 0x96, 0x57, 0x04, 0x3b, 0xc4, 0x7c,
432            0xc3, 0xaa, 0x45, 0x3a, 0x2e, 0x52, 0xb1, 0xbf, 0x92, 0x09, 0x41, 0x73, 0x83, 0xf1,
433            0x9d, 0x39, 0x50, 0x27, 0x14, 0x5a, 0xc9, 0x6c, 0x30, 0xb6, 0x67, 0x21, 0x78, 0xbe,
434            0x1f, 0x7f, 0xd1, 0xa2, 0x55, 0xb1, 0x0d, 0xc9, 0x9c, 0x3b, 0xae, 0x45, 0x78, 0x88,
435            0x1b, 0x7f, 0x4d, 0x40, 0x3a, 0xc3, 0x28, 0xeb, 0xcb, 0x4c, 0x67, 0xde, 0xa2, 0xcc,
436            0x88, 0x3e, 0x4f, 0x8a, 0x8a, 0x30, 0x88, 0x33, 0x61, 0xea, 0x99, 0x64, 0x1b, 0xf0,
437            0x99, 0x12, 0x3e, 0xe4, 0x3b, 0xdb, 0xa6, 0xcd, 0xb6, 0x69, 0xb0, 0x45, 0xdd, 0x84,
438            0x37, 0x3a, 0xa3, 0x9a, 0x33, 0xa3, 0x73, 0x61, 0x7b, 0x46, 0xa2, 0x44, 0xae, 0xb3,
439            0x15, 0xe7, 0x74, 0x1e, 0xad, 0x9d, 0xb7, 0x65, 0x71, 0x72, 0x2c, 0x9c, 0x43, 0x4b,
440            0xe9, 0x13, 0x87, 0xa8, 0xd5, 0xe9, 0xdc, 0x78, 0x37, 0x45, 0xb2, 0x31, 0x5f, 0x68,
441            0x22, 0x0b, 0xcc, 0x36, 0xcd, 0x64, 0xfe, 0x50, 0x44, 0x63, 0x41, 0x1b, 0xb3, 0x2e,
442            0x21, 0x80, 0x6f, 0xb6, 0xd7, 0x54, 0x57, 0xcf, 0x7d, 0x06, 0xc7, 0x7f, 0xbf, 0x7a,
443            0xff, 0xfe, 0x66, 0x7b, 0xbd, 0xf9, 0xe7, 0xd7, 0xe4, 0x42, 0x9e, 0x16, 0x0c, 0x83,
444            0x9a, 0xe2, 0xe7, 0x0b, 0xe5, 0xa7, 0x7b, 0xf4, 0x37, 0x56, 0xe5, 0x90, 0x77, 0x49,
445            0xf4, 0x79, 0xdd, 0x17, 0xbe, 0x50, 0xc5, 0xcf, 0x28, 0x96, 0xd3, 0x84, 0x44, 0xab,
446            0x8d, 0x54, 0x68, 0x07, 0x45, 0x68, 0x1d, 0xba, 0xb9, 0x6a, 0xee, 0xe4, 0x5b, 0x89,
447            0xaa, 0x71, 0x80, 0xba, 0x56, 0xc6, 0x05, 0xd0, 0xdf, 0xd1, 0x96, 0x12, 0xbd, 0x83,
448            0xd5, 0x8f, 0x3f, 0xad, 0x32, 0xf0, 0xf1, 0x64, 0x22, 0x56, 0xbb, 0x29, 0x05, 0x13,
449            0xa3, 0x6a, 0xec, 0xfa, 0x8a, 0x4e, 0x7a, 0x0d, 0x17, 0xd7, 0x46, 0xff, 0x26, 0x7f,
450            0x2f, 0x50, 0xe4, 0x68, 0x12, 0xfe, 0xab, 0x4b, 0xe0, 0x6e, 0x9d, 0xdb, 0x54, 0xd7,
451            0x99, 0x51, 0x35, 0x44, 0xf1, 0xb3, 0x1e, 0xb1, 0x3b, 0x28, 0xca, 0x76, 0xb1, 0x9b,
452            0xa5, 0x5c, 0x71, 0x93, 0xf6, 0xe2, 0x29, 0x2f, 0x42, 0xb9, 0xa9, 0x0f, 0x0a, 0xac,
453            0xe1, 0x23, 0x82, 0x50, 0x8e, 0x16, 0x54, 0xe1, 0xe9, 0x38, 0x27, 0x4d, 0x28, 0xce,
454            0xcf, 0x86, 0xb8, 0x71, 0x8e, 0x19, 0x6b, 0x68, 0xbb, 0x98, 0x66, 0x0e, 0xa9, 0x18,
455            0xa7, 0xd5, 0xea, 0x0e, 0xe7, 0x4f, 0x56, 0x78, 0x43, 0x9a, 0x34, 0x71, 0xf4, 0xe2,
456            0x6a, 0xb0, 0x92, 0x07, 0xd7, 0x84, 0xc1, 0x2b, 0xaa, 0x15, 0xcb, 0xcd, 0x67, 0xfc,
457            0xf8, 0x85, 0xd4, 0x44, 0xe1, 0x64, 0xde, 0xc7, 0x47, 0xcb, 0xa5, 0xbd, 0x6b, 0x1e,
458            0xcf, 0xcc, 0x43, 0x0e, 0x61, 0xeb, 0x8e, 0x36, 0xd6, 0x21, 0x18, 0xe6, 0x65, 0xe2,
459            0x8f, 0xd3, 0x34, 0x4d, 0x3f, 0xc1, 0x8f, 0xac, 0xb7, 0x69, 0x8f, 0xb7, 0xac, 0x3f,
460            0xf1, 0xe3, 0x31, 0x48, 0x9a, 0xa2, 0x67, 0x5a, 0x86, 0x4f, 0x55, 0x7e, 0x10, 0x0a,
461            0x17, 0xf4, 0x40, 0xfe, 0xe6, 0xf2, 0xf2, 0x1b, 0x12, 0x91, 0xfa, 0x11, 0x02, 0x82,
462            0x50, 0xbe, 0xe2, 0xf8, 0x3c, 0xd1, 0x78, 0xa9, 0x63, 0x1b, 0xca, 0xd0, 0x98, 0x23,
463            0x2a, 0x53, 0x9c, 0xa2, 0xeb, 0x37, 0x3b, 0x9e, 0x96, 0x89, 0xc5, 0xc8, 0x2e, 0x05,
464            0xb2, 0xf0, 0x29, 0xdc, 0x7f, 0xe9, 0x93, 0xd3, 0x77, 0x9b, 0x37, 0x37, 0xdb, 0xfb,
465            0x9b, 0x97, 0x5f, 0xad, 0x5f, 0xf3, 0x2b, 0x5f, 0xc2, 0xd0, 0x9f, 0xe3, 0x1e, 0xf1,
466            0x9b, 0xb3, 0x17, 0xe5, 0x94, 0x72, 0x61, 0xaf, 0xa4, 0x1e, 0x7d, 0xc2, 0x50, 0x3c,
467            0xf0, 0x1c, 0x03, 0xff, 0x1f, 0xe9, 0x77, 0x22, 0xde, 0x6c, 0xb6, 0x7b, 0xc4, 0x85,
468            0x0a, 0x29, 0xc8, 0x99, 0xd6, 0xb4, 0xb2, 0x06, 0x25, 0xf4, 0x7e, 0x14, 0x7b, 0x84,
469            0xbd, 0x79, 0x44, 0xab, 0x8f, 0xbf, 0xec, 0x8b, 0xd3, 0x92, 0x99, 0xaf, 0xbb, 0xd3,
470            0x7b, 0xad, 0x5f, 0xfc, 0x07, 0x3a, 0x27, 0xec, 0x70,
471        ];
472    }
473
474    #[test]
475    fn test_read_data_header() -> Result<(), ErrorTrace> {
476        let mut data_header: ZlibDataHeader = ZlibDataHeader::new();
477
478        let test_data: Vec<u8> = get_test_data();
479        data_header.read_data(&test_data)?;
480
481        assert_eq!(data_header.header_size, 2);
482
483        Ok(())
484    }
485
486    #[test]
487    fn test_decompress() -> Result<(), ErrorTrace> {
488        let mut test_context: ZlibContext = ZlibContext::new();
489
490        let test_data: Vec<u8> = get_test_data();
491        let mut uncompressed_data: Vec<u8> = vec![0; 11358];
492        test_context.decompress(&test_data, &mut uncompressed_data)?;
493        assert_eq!(test_context.uncompressed_data_size, 11358);
494
495        let expected_data: Vec<u8> = match fs::read("../LICENSE") {
496            Ok(data) => data,
497            Err(error) => {
498                return Err(keramics_core::error_trace_new_with_error!(
499                    "Unable read test reference file",
500                    error
501                ));
502            }
503        };
504        assert_eq!(&uncompressed_data, &expected_data);
505
506        Ok(())
507    }
508}