1use keramics_core::ErrorTrace;
19use keramics_core::mediator::Mediator;
20
21use super::huffman::HuffmanTree;
22use super::traits::Bitstream;
23
24const DEFLATE_BLOCK_TYPE_UNCOMPRESED: u32 = 0;
26
27const DEFLATE_BLOCK_TYPE_HUFFMAN_FIXED: u32 = 1;
29
30const DEFLATE_BLOCK_TYPE_HUFFMAN_DYNAMIC: u32 = 2;
32
33const DEFLATE_CODE_SIZES_SEQUENCE: [u8; 19] = [
35 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15,
36];
37
38const DEFLATE_LITERAL_CODES_BASE: [u16; 29] = [
40 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131,
41 163, 195, 227, 258,
42];
43
44const DEFLATE_LITERAL_CODES_NUMBER_OF_EXTRA_BITS: [u16; 29] = [
46 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0,
47];
48
49const DEFLATE_DISTANCE_CODES_BASE: [u16; 30] = [
51 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537,
52 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577,
53];
54
55const DEFLATE_DISTANCE_CODES_NUMBER_OF_EXTRA_BITS: [u16; 30] = [
57 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13,
58 13,
59];
60
61pub(super) struct DeflateBitstream<'a> {
63 data: &'a [u8],
65
66 pub data_offset: usize,
68
69 pub data_size: usize,
71
72 bits: u32,
74
75 pub number_of_bits: usize,
77}
78
79impl<'a> DeflateBitstream<'a> {
80 pub fn new(data: &'a [u8], data_offset: usize) -> Self {
82 let data_size: usize = data.len();
83 Self {
84 data: data,
85 data_offset: data_offset,
86 data_size: data_size,
87 bits: 0,
88 number_of_bits: 0,
89 }
90 }
91
92 pub fn copy_bytes(
95 &mut self,
96 read_size: usize,
97 output_data: &mut [u8],
98 output_data_offset: usize,
99 output_data_size: usize,
100 ) -> Result<(), ErrorTrace> {
101 let data_end_offset: usize = self.data_offset + read_size;
102 let output_data_end_offset: usize = output_data_offset + read_size;
103
104 if data_end_offset > self.data_size {
105 return Err(keramics_core::error_trace_new!(
106 "Invalid compressed data value too small"
107 ));
108 }
109 if output_data_end_offset > output_data_size {
110 return Err(keramics_core::error_trace_new!(
111 "Invalid uncompressed data value too small"
112 ));
113 }
114 output_data[output_data_offset..output_data_end_offset]
115 .copy_from_slice(&self.data[self.data_offset..data_end_offset]);
116
117 self.data_offset = data_end_offset;
118
119 self.bits = 0;
121 self.number_of_bits = 0;
122
123 Ok(())
124 }
125
126 #[inline(always)]
128 fn read_data(&mut self, number_of_bits: usize) {
129 while self.number_of_bits < number_of_bits {
130 if self.data_offset < self.data_size {
132 self.bits |= (self.data[self.data_offset] as u32) << self.number_of_bits;
133 self.data_offset += 1;
134 }
135 self.number_of_bits += 8;
136 }
137 }
138
139 #[inline(always)]
141 pub(super) fn unread_data(&mut self) {
142 while self.number_of_bits > 8 {
143 self.bits >>= 8;
144 self.number_of_bits -= 8;
145
146 self.data_offset -= 1;
147 }
148 }
149}
150
151impl<'a> Bitstream for DeflateBitstream<'a> {
152 fn get_value(&mut self, number_of_bits: usize) -> u32 {
154 let mut bit_value: u32 = 0;
156
157 let mut bit_offset: usize = 0;
158 while bit_offset < number_of_bits {
159 let mut read_size: usize = number_of_bits - bit_offset;
160 if read_size > 24 {
161 read_size = 24;
162 }
163 if self.number_of_bits < read_size {
164 self.read_data(read_size);
165 }
166 let mut value_32bit: u32 = self.bits;
167
168 if read_size == 32 {
169 self.bits = 0;
170 } else {
171 value_32bit &= !(0xffffffff << read_size);
172
173 self.bits >>= read_size;
174 }
175 self.number_of_bits -= read_size;
176
177 if bit_offset > 0 {
178 value_32bit <<= bit_offset;
179 }
180 bit_value |= value_32bit;
181 bit_offset += read_size;
182 }
183 bit_value
184 }
185
186 fn skip_bits(&mut self, number_of_bits: usize) {
188 let mut bit_offset: usize = 0;
190 while bit_offset < number_of_bits {
191 let mut read_size: usize = number_of_bits - bit_offset;
192 if read_size > 24 {
193 read_size = 24;
194 }
195 if self.number_of_bits < read_size {
196 self.read_data(read_size);
197 }
198 if read_size == 32 {
199 self.bits = 0;
200 } else {
201 self.bits >>= read_size;
202 }
203 self.number_of_bits -= read_size;
204
205 bit_offset += read_size;
206 }
207 }
208}
209
210struct DeflateBlockHeader {
212 pub block_type: u32,
214
215 pub last_block_flag: u32,
217}
218
219impl DeflateBlockHeader {
220 pub fn new() -> Self {
222 Self {
223 block_type: 0,
224 last_block_flag: 0,
225 }
226 }
227
228 pub fn read_from_bitstream(
230 &mut self,
231 bitstream: &mut DeflateBitstream,
232 ) -> Result<(), ErrorTrace> {
233 let value_32bit: u32 = bitstream.get_value(3);
234
235 self.last_block_flag = value_32bit & 0x00000001;
236 self.block_type = value_32bit >> 1;
237
238 let mediator = Mediator::current();
239 if mediator.debug_output {
240 let mut string_parts: Vec<String> = Vec::new();
241 string_parts.push(format!("DeflateBlockHeader {{\n"));
242 string_parts.push(format!(" last_block_flag: {},\n", self.last_block_flag));
243 string_parts.push(format!(" block_type: {},\n", self.block_type));
244 string_parts.push(format!("}}\n\n"));
245
246 mediator.debug_print(string_parts.join(""));
247 }
248 Ok(())
249 }
250}
251
252pub struct DeflateContext {
256 fixed_literals_huffman_tree: HuffmanTree,
258
259 fixed_distances_huffman_tree: HuffmanTree,
261
262 build_fixed_huffman_trees: bool,
264
265 pub uncompressed_data_size: usize,
267}
268
269impl DeflateContext {
270 pub fn new() -> Self {
272 Self {
273 fixed_literals_huffman_tree: HuffmanTree::new(288, 15),
274 fixed_distances_huffman_tree: HuffmanTree::new(30, 15),
275 build_fixed_huffman_trees: false,
276 uncompressed_data_size: 0,
277 }
278 }
279
280 fn build_dynamic_huffman_trees(
282 &mut self,
283 bitstream: &mut DeflateBitstream,
284 literals_huffman_tree: &mut HuffmanTree,
285 distances_huffman_tree: &mut HuffmanTree,
286 ) -> Result<(), ErrorTrace> {
287 let mut code_sizes: Vec<u8> = vec![0; 316];
288
289 let mut value_32bit: u32 = bitstream.get_value(14);
290
291 let number_of_literal_codes: usize = (value_32bit & 0x0000001f) as usize + 257;
292
293 if number_of_literal_codes > 286 {
294 return Err(keramics_core::error_trace_new!(format!(
295 "Invalid number of literal codes: {} value out of bounds",
296 number_of_literal_codes
297 )));
298 }
299 value_32bit >>= 5;
300
301 let number_of_distance_codes: usize = (value_32bit & 0x0000001f) as usize + 1;
302
303 if number_of_distance_codes > 30 {
304 return Err(keramics_core::error_trace_new!(format!(
305 "Invalid number of distance codes: {} value out of bounds",
306 number_of_distance_codes
307 )));
308 }
309 value_32bit >>= 5;
310
311 let number_of_code_sizes: usize = (value_32bit as usize) + 4;
312
313 let mediator = Mediator::current();
314 if mediator.debug_output {
315 let mut string_parts: Vec<String> = Vec::new();
316 string_parts.push(format!("DeflateContext::build_dynamic_huffman_trees {{\n"));
317 string_parts.push(format!(
318 " number_of_literal_codes: {},\n",
319 number_of_literal_codes
320 ));
321 string_parts.push(format!(
322 " number_of_distance_codes: {},\n",
323 number_of_distance_codes
324 ));
325 string_parts.push(format!(
326 " number_of_code_sizes: {},\n",
327 number_of_code_sizes
328 ));
329 string_parts.push(format!("}}\n\n"));
330
331 mediator.debug_print(string_parts.join(""));
332 }
333 for sequence_index in 0..number_of_code_sizes {
334 let code_size: u32 = bitstream.get_value(3);
335 let code_size_index: usize = DEFLATE_CODE_SIZES_SEQUENCE[sequence_index] as usize;
336
337 code_sizes[code_size_index] = code_size as u8;
338 }
339 for sequence_index in number_of_code_sizes..19 {
340 let code_size_index: usize = DEFLATE_CODE_SIZES_SEQUENCE[sequence_index] as usize;
341
342 code_sizes[code_size_index] = 0;
343 }
344 let mut codes_huffman_tree: HuffmanTree = HuffmanTree::new(19, 15);
345 codes_huffman_tree.build(&code_sizes[0..19])?;
346
347 let number_of_codes: usize = number_of_literal_codes + number_of_distance_codes;
348 let mut code_size_index: usize = 0;
349
350 while code_size_index < number_of_codes {
351 let symbol: u16 = codes_huffman_tree.decode_symbol(bitstream)?;
352
353 if symbol < 16 {
354 code_sizes[code_size_index] = symbol as u8;
355
356 code_size_index += 1;
357
358 continue;
359 }
360 if code_size_index == 0 && symbol == 16 {
361 return Err(keramics_core::error_trace_new!(format!(
362 "Invalid code size index: {} value out of bounds",
363 code_size_index
364 )));
365 }
366 if symbol > 18 {
367 return Err(keramics_core::error_trace_new!(format!(
368 "Invalid symbol: {} value out of bounds",
369 symbol
370 )));
371 }
372 let code_size: u8 = if symbol == 16 {
373 code_sizes[code_size_index - 1]
374 } else {
375 0
376 };
377 let mut times_to_repeat: u32 = if symbol == 16 {
378 bitstream.get_value(2) + 3
379 } else if symbol == 17 {
380 bitstream.get_value(3) + 3
381 } else {
382 bitstream.get_value(7) + 11
383 };
384 if code_size_index + times_to_repeat as usize > number_of_codes {
385 return Err(keramics_core::error_trace_new!(format!(
386 "Invalid times to repeat: {} value out of bounds",
387 times_to_repeat
388 )));
389 }
390 while times_to_repeat > 0 {
391 code_sizes[code_size_index] = code_size;
392
393 code_size_index += 1;
394 times_to_repeat -= 1;
395 }
396 }
397 if code_sizes[256] == 0 {
398 return Err(keramics_core::error_trace_new!(
399 "End-of-block code value missing in literal codes"
400 ));
401 }
402 literals_huffman_tree.build(&code_sizes[0..number_of_literal_codes])?;
403 distances_huffman_tree.build(&code_sizes[number_of_literal_codes..number_of_codes])?;
404
405 Ok(())
406 }
407
408 fn build_fixed_huffman_trees(&mut self) -> Result<(), ErrorTrace> {
410 let mut code_sizes: Vec<u8> = vec![0; 318];
411
412 for symbol in 0..318 {
413 if symbol < 144 {
414 code_sizes[symbol] = 8;
415 } else if symbol < 256 {
416 code_sizes[symbol] = 9;
417 } else if symbol < 280 {
418 code_sizes[symbol] = 7;
419 } else if symbol < 288 {
420 code_sizes[symbol] = 8;
421 } else {
422 code_sizes[symbol] = 5;
423 }
424 }
425 self.fixed_literals_huffman_tree
426 .build(&code_sizes[0..288])?;
427 self.fixed_distances_huffman_tree
428 .build(&code_sizes[288..318])?;
429 self.build_fixed_huffman_trees = true;
430
431 Ok(())
432 }
433
434 pub fn decompress(
436 &mut self,
437 compressed_data: &[u8],
438 uncompressed_data: &mut [u8],
439 ) -> Result<(), ErrorTrace> {
440 let mut bitstream: DeflateBitstream = DeflateBitstream::new(compressed_data, 0);
441
442 self.decompress_bitstream(&mut bitstream, uncompressed_data)
443 }
444
445 pub(super) fn decompress_bitstream(
447 &mut self,
448 bitstream: &mut DeflateBitstream,
449 uncompressed_data: &mut [u8],
450 ) -> Result<(), ErrorTrace> {
451 let mut uncompressed_data_offset: usize = 0;
452 let uncompressed_data_size: usize = uncompressed_data.len();
453
454 while bitstream.data_offset < bitstream.data_size {
455 let mut block_header: DeflateBlockHeader = DeflateBlockHeader::new();
456 block_header.read_from_bitstream(bitstream)?;
457
458 match block_header.block_type {
459 DEFLATE_BLOCK_TYPE_UNCOMPRESED => {
460 let skip_bits: usize = bitstream.number_of_bits & 0x07;
462
463 if skip_bits > 0 {
464 bitstream.skip_bits(skip_bits);
465 }
466 let value_32bit: u32 = bitstream.get_value(32);
467 let block_size: usize = (value_32bit & 0x0000ffff) as usize;
468 let block_size_copy: usize = ((value_32bit >> 16) ^ 0xffff) as usize;
469
470 if block_size != block_size_copy {
471 return Err(keramics_core::error_trace_new!(format!(
472 "Mismatch in uncompressed block size: {} and copy: {}",
473 block_size, block_size_copy
474 )));
475 }
476 if block_size > 0 {
477 bitstream.copy_bytes(
478 block_size,
479 uncompressed_data,
480 uncompressed_data_offset,
481 uncompressed_data_size,
482 )?;
483 uncompressed_data_offset += block_size;
484 }
485 }
486 DEFLATE_BLOCK_TYPE_HUFFMAN_FIXED => {
487 if !self.build_fixed_huffman_trees {
488 self.build_fixed_huffman_trees()?;
489 }
490 self.decompress_huffmann_encoded_block(
491 bitstream,
492 &self.fixed_literals_huffman_tree,
493 &self.fixed_distances_huffman_tree,
494 uncompressed_data,
495 &mut uncompressed_data_offset,
496 uncompressed_data_size,
497 )?;
498 }
499 DEFLATE_BLOCK_TYPE_HUFFMAN_DYNAMIC => {
500 let mut dynamic_literals_huffman_tree: HuffmanTree = HuffmanTree::new(288, 15);
501 let mut dynamic_distances_huffman_tree: HuffmanTree = HuffmanTree::new(30, 15);
502
503 self.build_dynamic_huffman_trees(
504 bitstream,
505 &mut dynamic_literals_huffman_tree,
506 &mut dynamic_distances_huffman_tree,
507 )?;
508 self.decompress_huffmann_encoded_block(
509 bitstream,
510 &dynamic_literals_huffman_tree,
511 &dynamic_distances_huffman_tree,
512 uncompressed_data,
513 &mut uncompressed_data_offset,
514 uncompressed_data_size,
515 )?;
516 }
517 _ => {
518 return Err(keramics_core::error_trace_new!("Unsupported block type"));
519 }
520 }
521 if block_header.last_block_flag != 0 {
522 break;
523 }
524 }
525 self.uncompressed_data_size = uncompressed_data_offset;
526
527 Ok(())
528 }
529
530 fn decompress_huffmann_encoded_block(
532 &self,
533 bitstream: &mut DeflateBitstream,
534 literals_huffman_tree: &HuffmanTree,
535 distances_huffman_tree: &HuffmanTree,
536 uncompressed_data: &mut [u8],
537 uncompressed_data_offset: &mut usize,
538 uncompressed_data_size: usize,
539 ) -> Result<(), ErrorTrace> {
540 let mut data_offset: usize = *uncompressed_data_offset;
541
542 let mediator = Mediator::current();
543 if mediator.debug_output {
544 mediator.debug_print(format!(
545 "DeflateContext::decompress_huffmann_encoded_block {{\n"
546 ));
547 }
548 loop {
549 let mut symbol: u16 = literals_huffman_tree.decode_symbol(bitstream)?;
550
551 if mediator.debug_output {
552 mediator.debug_print(format!(" uncompressed_data_offset: {},\n", data_offset));
553 mediator.debug_print(format!(" symbol: {},\n", symbol));
554 }
555 if symbol == 256 {
556 break;
557 }
558 if symbol < 256 {
559 if data_offset >= uncompressed_data_size {
560 return Err(keramics_core::error_trace_new!(
561 "Invalid uncompressed data value too small"
562 ));
563 }
564 uncompressed_data[data_offset] = symbol as u8;
565
566 data_offset += 1;
567 } else if symbol > 256 && symbol < 286 {
568 symbol -= 257;
569
570 let number_of_extra_bits: u16 =
571 DEFLATE_LITERAL_CODES_NUMBER_OF_EXTRA_BITS[symbol as usize];
572 let extra_bits: u32 = bitstream.get_value(number_of_extra_bits as usize);
573
574 if mediator.debug_output {
575 mediator.debug_print(format!(" extra_bits: 0x{:04x},\n", extra_bits));
576 }
577 let compression_size: usize =
578 ((DEFLATE_LITERAL_CODES_BASE[symbol as usize] as u32) + extra_bits) as usize;
579
580 symbol = distances_huffman_tree.decode_symbol(bitstream)?;
581
582 if mediator.debug_output {
583 mediator.debug_print(format!(" symbol: {},\n", symbol));
584 }
585 let number_of_extra_bits: u16 =
586 DEFLATE_DISTANCE_CODES_NUMBER_OF_EXTRA_BITS[symbol as usize];
587 let extra_bits: u32 = bitstream.get_value(number_of_extra_bits as usize);
588
589 if mediator.debug_output {
590 mediator.debug_print(format!(" extra_bits: 0x{:04x},\n", extra_bits));
591 }
592 let compression_offset: usize =
593 ((DEFLATE_DISTANCE_CODES_BASE[symbol as usize] as u32) + extra_bits) as usize;
594
595 if compression_offset > data_offset {
596 return Err(keramics_core::error_trace_new!(format!(
597 "Invalid compression offset: {} value out of bounds",
598 compression_offset
599 )));
600 }
601 if compression_size > uncompressed_data_size - data_offset {
602 return Err(keramics_core::error_trace_new!(format!(
603 "Invalid compression size: {} value out of bounds",
604 compression_size
605 )));
606 }
607 if mediator.debug_output {
608 mediator
609 .debug_print(format!(" compression_offset: {},\n", compression_offset));
610 mediator.debug_print(format!(" compression_size: {},\n", compression_size));
611 }
612 let mut compression_data_offset: usize = data_offset - compression_offset;
613
614 for _ in 0..compression_size {
615 uncompressed_data[data_offset] = uncompressed_data[compression_data_offset];
616
617 data_offset += 1;
618 compression_data_offset += 1;
619 }
620 } else {
621 return Err(keramics_core::error_trace_new!(format!(
622 "Invalid symbol: {}",
623 symbol
624 )));
625 }
626 }
627 if mediator.debug_output {
628 mediator.debug_print(format!("}}\n\n"));
629 }
630 *uncompressed_data_offset = data_offset;
631
632 Ok(())
633 }
634}
635
636#[cfg(test)]
637mod tests {
638 use super::*;
639
640 use std::fs;
641
642 fn get_test_data() -> Vec<u8> {
643 return vec![
644 0xdd, 0x5a, 0x6d, 0x73, 0x1b, 0xb7, 0x11, 0xfe, 0xee, 0x5f, 0x81, 0x72, 0xa6, 0x53,
645 0x69, 0xe6, 0x4c, 0x3b, 0x69, 0xd2, 0x36, 0xce, 0x27, 0xc5, 0x92, 0x13, 0xb6, 0x8e,
646 0xa4, 0x11, 0xe5, 0xba, 0x99, 0x4c, 0x3e, 0x80, 0x47, 0x1c, 0x89, 0xfa, 0x78, 0x60,
647 0x81, 0x3b, 0x51, 0xec, 0xaf, 0xef, 0xb3, 0x8b, 0xd7, 0x23, 0x29, 0xd9, 0x9d, 0x7e,
648 0xab, 0xc7, 0x93, 0x98, 0xe4, 0x01, 0x58, 0xec, 0xcb, 0xb3, 0xcf, 0xee, 0xde, 0x0b,
649 0xf1, 0xb9, 0x3f, 0x17, 0x5b, 0x59, 0xaf, 0x95, 0x78, 0xaf, 0x6b, 0xd5, 0x39, 0xf5,
650 0xe2, 0x99, 0x27, 0xff, 0xae, 0xac, 0xd3, 0xa6, 0x13, 0x5f, 0x4f, 0x5f, 0x57, 0xe2,
651 0xaf, 0xb2, 0x1b, 0xa4, 0xdd, 0x8b, 0xaf, 0x5f, 0xbf, 0xfe, 0xe6, 0xc9, 0x45, 0xeb,
652 0xbe, 0xdf, 0xbe, 0x79, 0xf5, 0x6a, 0xb7, 0xdb, 0x4d, 0x25, 0x1f, 0x33, 0x35, 0x76,
653 0xf5, 0xaa, 0xf5, 0x47, 0xb9, 0x57, 0x2f, 0x68, 0xe1, 0xfd, 0xd5, 0xdd, 0xcf, 0x73,
654 0x71, 0x71, 0x7d, 0x29, 0xde, 0xde, 0x5c, 0x5f, 0xce, 0xee, 0x67, 0x37, 0xd7, 0x73,
655 0xf1, 0xee, 0xe6, 0x4e, 0x7c, 0x98, 0x5f, 0x55, 0xe2, 0xee, 0xea, 0xf6, 0xee, 0xe6,
656 0xf2, 0xc3, 0x5b, 0xfa, 0xba, 0xe2, 0xa7, 0x2e, 0x67, 0xf3, 0xfb, 0xbb, 0xd9, 0x0f,
657 0x1f, 0xe8, 0x1b, 0xde, 0xe0, 0xab, 0xa9, 0xb8, 0x54, 0x8d, 0xee, 0x74, 0x0f, 0xe1,
658 0xdc, 0xf4, 0x45, 0x90, 0x66, 0x12, 0x6e, 0x34, 0x11, 0x6e, 0x2d, 0xdb, 0x56, 0x6c,
659 0x94, 0xec, 0x44, 0x8f, 0x9b, 0xf6, 0xca, 0x6e, 0x9c, 0x90, 0xdd, 0x52, 0xd4, 0xa6,
660 0x5b, 0xfa, 0x55, 0xa2, 0x31, 0x56, 0x0c, 0x4e, 0x55, 0xc2, 0xaa, 0xad, 0x35, 0xcb,
661 0xa1, 0xa6, 0xaf, 0xab, 0xb0, 0x15, 0x3d, 0xbb, 0xd4, 0xae, 0xb7, 0x7a, 0x31, 0xd0,
662 0xf7, 0x42, 0x3a, 0xb1, 0xa4, 0x23, 0xd5, 0x52, 0x2c, 0xf6, 0x62, 0xae, 0x6a, 0xbf,
663 0xc9, 0x57, 0xd8, 0xdf, 0x9a, 0x61, 0xb5, 0x16, 0xdf, 0x09, 0xd3, 0xe0, 0x83, 0xc6,
664 0x73, 0xa6, 0x1e, 0x36, 0xaa, 0xeb, 0x0f, 0xe5, 0x32, 0xf6, 0x48, 0xb0, 0xda, 0x6c,
665 0xf7, 0x56, 0xaf, 0xd6, 0xbd, 0x30, 0xbb, 0x4e, 0x59, 0x01, 0x91, 0xb0, 0x50, 0xf7,
666 0x7b, 0x21, 0x87, 0x7e, 0x6d, 0xac, 0xfe, 0x37, 0x9f, 0x17, 0xf6, 0x39, 0xb5, 0xa2,
667 0x5f, 0xcb, 0x5e, 0xe0, 0xd0, 0x95, 0x95, 0x58, 0xd8, 0xad, 0xf8, 0xa1, 0xa0, 0x87,
668 0x42, 0x00, 0xb5, 0x92, 0xad, 0xb8, 0xe2, 0xad, 0x8f, 0x84, 0x18, 0x3a, 0xba, 0x20,
669 0x4b, 0xaf, 0x84, 0xac, 0x79, 0x97, 0x28, 0x05, 0xd4, 0x80, 0x67, 0xc3, 0x36, 0x06,
670 0x0f, 0x04, 0x01, 0xb5, 0x72, 0xfe, 0x68, 0x28, 0xb4, 0xb7, 0xa6, 0xad, 0x84, 0xb4,
671 0x2a, 0x7e, 0x68, 0x59, 0xe8, 0x8a, 0x6e, 0x43, 0xdf, 0x0e, 0xdd, 0x12, 0xcb, 0x6a,
672 0xb3, 0xd9, 0x98, 0x2e, 0xec, 0x14, 0x1e, 0x14, 0x3b, 0xdd, 0xaf, 0xfd, 0x3e, 0xfe,
673 0xc0, 0xa9, 0x78, 0x67, 0x2c, 0xcb, 0xb1, 0x1d, 0xec, 0xd6, 0xc0, 0x63, 0xb2, 0x56,
674 0x93, 0xc1, 0xa3, 0x8d, 0x26, 0x61, 0x97, 0x09, 0x5f, 0xc5, 0x89, 0x33, 0x7d, 0xee,
675 0x97, 0x9a, 0x9d, 0xb2, 0x15, 0xcc, 0x67, 0x61, 0x25, 0x12, 0x42, 0x77, 0xfe, 0xdf,
676 0x95, 0xe8, 0x8d, 0xa8, 0x25, 0x8c, 0x4e, 0xcf, 0x85, 0x5d, 0xfc, 0x4f, 0xac, 0x01,
677 0x2b, 0x36, 0xb2, 0x93, 0x2b, 0x45, 0xc6, 0xa3, 0x73, 0xdd, 0x50, 0xaf, 0x83, 0x60,
678 0x95, 0xd8, 0xad, 0x15, 0x5f, 0x1f, 0xd6, 0xe7, 0x73, 0x25, 0xef, 0x5d, 0x6a, 0x66,
679 0xa7, 0xc9, 0x9b, 0xb0, 0xcb, 0x99, 0x86, 0x24, 0x6c, 0x1e, 0xb7, 0xd6, 0x5b, 0xda,
680 0xa9, 0xd1, 0x0d, 0xb4, 0xb9, 0x55, 0xb6, 0xa6, 0xad, 0xcf, 0xbe, 0x7d, 0xfd, 0xfb,
681 0x73, 0x3e, 0xce, 0x40, 0x3d, 0x5e, 0xf1, 0x71, 0xa3, 0xa1, 0x77, 0x3d, 0xb4, 0x4e,
682 0x36, 0x80, 0x99, 0xac, 0x72, 0x71, 0x47, 0x6c, 0xb9, 0x50, 0x1d, 0x94, 0x50, 0x6b,
683 0x98, 0x72, 0xb4, 0x7b, 0x21, 0x67, 0x36, 0xf9, 0x2f, 0x66, 0x98, 0x88, 0x33, 0xac,
684 0xa5, 0x7f, 0xd9, 0xc9, 0x79, 0x69, 0x75, 0xfc, 0x25, 0x9d, 0x3c, 0xe8, 0xe5, 0x40,
685 0x7b, 0x59, 0x51, 0xfa, 0x47, 0xd8, 0x40, 0x3d, 0x42, 0x5a, 0xed, 0x48, 0x10, 0xc8,
686 0xbd, 0xd1, 0xce, 0xb1, 0xc3, 0xb3, 0x9f, 0xf9, 0x20, 0x60, 0xb3, 0x1c, 0xb9, 0xda,
687 0x1c, 0xa7, 0xd5, 0x08, 0x41, 0x84, 0xd7, 0xe6, 0xd0, 0xd3, 0xb6, 0x56, 0x35, 0xca,
688 0x5a, 0x2c, 0xe7, 0x5f, 0x1b, 0xd6, 0xf8, 0x27, 0x3a, 0x62, 0x63, 0x96, 0x1a, 0x57,
689 0x93, 0x1c, 0x55, 0xd1, 0xc0, 0xba, 0xab, 0xdb, 0x81, 0x55, 0x81, 0x20, 0x14, 0x9d,
690 0xe9, 0x45, 0xab, 0x37, 0x9a, 0x4e, 0x87, 0x1d, 0x9d, 0x69, 0xfa, 0x1d, 0xb9, 0x97,
691 0xe3, 0x03, 0x61, 0x94, 0x25, 0xb4, 0x1f, 0x63, 0x8f, 0x37, 0x0a, 0xdb, 0xf8, 0x07,
692 0xaa, 0x18, 0xff, 0x8d, 0x5e, 0x0d, 0x96, 0x7f, 0x87, 0x59, 0x5a, 0x55, 0xc0, 0xc7,
693 0xcd, 0xe2, 0x9f, 0x70, 0x85, 0x63, 0xd1, 0x65, 0xb7, 0xf7, 0xdf, 0xc1, 0x1c, 0x43,
694 0xcb, 0xf1, 0xd1, 0x58, 0xb3, 0xc1, 0x8f, 0xf5, 0x5a, 0x76, 0x90, 0x3a, 0x06, 0x08,
695 0xbc, 0xa2, 0x73, 0xf4, 0xa4, 0x8c, 0x0e, 0xc5, 0xdf, 0xb4, 0xe1, 0x63, 0x23, 0xa4,
696 0xf0, 0xea, 0xe1, 0xed, 0xaa, 0xf1, 0x05, 0xc3, 0x1e, 0x07, 0xd7, 0x44, 0xd8, 0x6c,
697 0x35, 0x05, 0x94, 0x61, 0xe1, 0xc2, 0x35, 0x57, 0xf0, 0x04, 0xdc, 0x01, 0x5f, 0x8f,
698 0x2e, 0x5c, 0xa2, 0x17, 0x6e, 0xfa, 0xe0, 0xd1, 0xdb, 0xd1, 0x3e, 0x3e, 0x76, 0x37,
699 0x6a, 0xa9, 0xa5, 0xe8, 0xf7, 0xdb, 0xf2, 0xda, 0x1f, 0x8d, 0xfd, 0x74, 0x04, 0x0a,
700 0x3b, 0x7c, 0xc9, 0x12, 0x33, 0x0e, 0x91, 0xa7, 0xe5, 0x10, 0xd0, 0x5d, 0xbc, 0x46,
701 0x0a, 0x00, 0xaf, 0xba, 0x70, 0xad, 0x8d, 0x5c, 0x02, 0x48, 0x1e, 0xa4, 0x6e, 0xe5,
702 0xa2, 0x8d, 0xf1, 0x5f, 0xe0, 0x52, 0x45, 0x68, 0x4a, 0x0e, 0x58, 0xcb, 0xe0, 0x4a,
703 0x32, 0xe1, 0x42, 0x44, 0x37, 0xa8, 0x01, 0x0f, 0x27, 0x78, 0xf3, 0x9a, 0xc2, 0xc3,
704 0x9a, 0xd5, 0x2a, 0xfb, 0x9e, 0x72, 0x0b, 0x6b, 0x28, 0x4a, 0x1b, 0xb6, 0x38, 0xc3,
705 0x05, 0xd4, 0xa3, 0xdc, 0x6c, 0x71, 0x32, 0x16, 0x02, 0xda, 0xe1, 0xe6, 0x7e, 0x21,
706 0x3d, 0x79, 0xb1, 0xdd, 0x2a, 0x9c, 0xfc, 0x88, 0x60, 0x6a, 0xcd, 0xee, 0x3c, 0x6b,
707 0xe1, 0x52, 0x59, 0xfd, 0x00, 0x2d, 0x3e, 0x28, 0x41, 0x0a, 0x71, 0x93, 0x43, 0x0f,
708 0xa0, 0x33, 0x4e, 0xeb, 0x20, 0xdc, 0x3e, 0xec, 0xe4, 0x75, 0x10, 0x05, 0x5f, 0x48,
709 0x47, 0xc6, 0xeb, 0x38, 0x14, 0x97, 0x74, 0x06, 0x79, 0x3f, 0xbc, 0xc7, 0x63, 0x15,
710 0x1d, 0xc5, 0xe6, 0xa2, 0x58, 0xd8, 0xad, 0x75, 0xbd, 0x2e, 0xc0, 0x00, 0xc6, 0xea,
711 0x91, 0x03, 0x10, 0x99, 0x56, 0x3d, 0x68, 0x36, 0x25, 0x79, 0x31, 0x54, 0x13, 0xe2,
712 0x44, 0x28, 0x68, 0xd8, 0xd8, 0xf8, 0x09, 0x5b, 0x04, 0x33, 0x97, 0xd1, 0x14, 0x36,
713 0xa3, 0x2c, 0xa7, 0x1c, 0x3c, 0x85, 0xb5, 0x2f, 0x71, 0x98, 0x69, 0x39, 0x28, 0xb0,
714 0x4c, 0xaf, 0x74, 0x87, 0x53, 0x8e, 0x6d, 0x7e, 0x8c, 0xc7, 0x11, 0xa7, 0x9a, 0x51,
715 0xf8, 0x57, 0xe2, 0x50, 0x7d, 0x41, 0x7b, 0xe4, 0xcd, 0xc1, 0x76, 0xbc, 0x7d, 0xc8,
716 0x1a, 0x56, 0x6d, 0xa4, 0x4e, 0xf1, 0xa9, 0xb6, 0xd2, 0xb2, 0xa7, 0x90, 0x5e, 0xf8,
717 0x1a, 0x1b, 0x65, 0x55, 0xbb, 0x47, 0x1c, 0x74, 0x9f, 0x58, 0x71, 0x0b, 0x78, 0x0b,
718 0xf9, 0x49, 0x27, 0x37, 0xea, 0x3c, 0x1a, 0x5d, 0x03, 0x88, 0x6c, 0x23, 0x6b, 0x4e,
719 0x12, 0x55, 0x91, 0x23, 0x93, 0x52, 0x8f, 0x84, 0x22, 0xed, 0x28, 0xd3, 0x64, 0xab,
720 0xbf, 0x25, 0x28, 0x0f, 0x39, 0xfe, 0xa4, 0xc5, 0x0f, 0x63, 0x20, 0x85, 0x6c, 0x71,
721 0x5e, 0x52, 0x60, 0x08, 0xb8, 0x98, 0x4b, 0x93, 0x1c, 0xb4, 0xd9, 0xc8, 0x26, 0xec,
722 0xc3, 0xcb, 0xc0, 0x44, 0xe2, 0x4e, 0xc6, 0xeb, 0x86, 0x57, 0xe1, 0xf7, 0xa7, 0x84,
723 0xaf, 0x8a, 0xa0, 0xe8, 0x09, 0xf5, 0x0d, 0x8e, 0x6e, 0x23, 0x6c, 0xbb, 0x61, 0x01,
724 0xec, 0x08, 0xe0, 0x11, 0x79, 0x07, 0x7b, 0x17, 0x4b, 0xce, 0xe2, 0x85, 0x50, 0xe0,
725 0x83, 0x18, 0xc7, 0x8f, 0x68, 0x45, 0xb4, 0x32, 0xa7, 0xbb, 0x67, 0xb3, 0x45, 0x49,
726 0x54, 0x08, 0x95, 0xf9, 0x78, 0xf2, 0xf7, 0x85, 0x82, 0x32, 0x1b, 0xa8, 0xe2, 0x69,
727 0xf2, 0xf2, 0x65, 0xd9, 0x5e, 0x4c, 0xd2, 0x9d, 0x26, 0x61, 0x2f, 0x9f, 0xef, 0x13,
728 0x2c, 0x63, 0x91, 0x6a, 0x11, 0x80, 0xd6, 0x00, 0x8c, 0x2b, 0xb2, 0xc2, 0x42, 0xb6,
729 0xec, 0x47, 0x3b, 0x4b, 0xeb, 0x3a, 0x26, 0x1f, 0x43, 0x17, 0xb4, 0x2f, 0x28, 0x0a,
730 0x4a, 0xa5, 0xab, 0xac, 0x28, 0xd2, 0x53, 0xef, 0x72, 0xb0, 0xb0, 0xfe, 0x5d, 0xf5,
731 0x6c, 0x2a, 0x4a, 0xd8, 0x55, 0x9e, 0x81, 0xbf, 0x59, 0x26, 0x20, 0xa2, 0x6e, 0x69,
732 0x71, 0x0b, 0x4a, 0x89, 0xdd, 0x8a, 0x94, 0x95, 0xa8, 0x90, 0xdb, 0xbb, 0x5e, 0x6d,
733 0x5c, 0x09, 0xe1, 0xc8, 0xb9, 0x83, 0xa2, 0x14, 0x52, 0x73, 0x8e, 0x0c, 0x4f, 0x78,
734 0xf3, 0x53, 0xe6, 0xf3, 0x6c, 0x25, 0x71, 0xad, 0x52, 0xe9, 0x55, 0x01, 0x23, 0x23,
735 0x2f, 0x28, 0xb4, 0x4d, 0x7a, 0x03, 0xc7, 0xad, 0x07, 0xc7, 0x59, 0x9e, 0x4f, 0xdc,
736 0x30, 0x5e, 0x06, 0x1a, 0xf9, 0x91, 0x11, 0x2f, 0xa7, 0x26, 0xf5, 0x18, 0x95, 0x30,
737 0xbe, 0x6b, 0xf4, 0x47, 0x5c, 0xc5, 0x6d, 0x75, 0x3d, 0x98, 0xc1, 0x21, 0x78, 0x37,
738 0xd2, 0x7e, 0x22, 0xe8, 0xb3, 0x99, 0x1d, 0x45, 0xca, 0xa5, 0x9c, 0x5e, 0x75, 0x8c,
739 0xfd, 0x70, 0x45, 0xb2, 0x11, 0x2b, 0xf6, 0xa4, 0x27, 0x12, 0x58, 0x4d, 0xae, 0xa1,
740 0x6f, 0x29, 0xca, 0x58, 0x9d, 0x4e, 0x8e, 0x43, 0xf8, 0x80, 0x5f, 0xa7, 0x6b, 0xc7,
741 0x08, 0xfc, 0x2c, 0xe5, 0x29, 0x15, 0x48, 0xf8, 0xb8, 0x39, 0x38, 0x54, 0xac, 0x21,
742 0xcc, 0x42, 0xc1, 0x9f, 0x40, 0x19, 0x15, 0x23, 0x39, 0x84, 0x2e, 0xcf, 0xc9, 0x41,
743 0xe8, 0xd4, 0xbf, 0x06, 0xf8, 0x4f, 0x4b, 0xc7, 0xd6, 0x06, 0xfa, 0xf6, 0xe9, 0x9a,
744 0x08, 0x6f, 0x11, 0x7e, 0x1e, 0x88, 0xbe, 0x9e, 0x8a, 0x1f, 0x89, 0x56, 0xd1, 0xb1,
745 0x6f, 0xd3, 0xf5, 0x23, 0xb3, 0x12, 0xf3, 0xc1, 0x27, 0xd7, 0xe0, 0xab, 0x27, 0x8b,
746 0x99, 0x22, 0xcc, 0x4a, 0x54, 0x56, 0xc8, 0x92, 0xa2, 0x50, 0x90, 0x20, 0x08, 0x81,
747 0xcc, 0xcc, 0xe2, 0x98, 0x17, 0x80, 0x1c, 0xe2, 0x96, 0x60, 0x78, 0x5b, 0xd5, 0x43,
748 0x33, 0xd1, 0xfd, 0x00, 0x7d, 0xed, 0x72, 0xa7, 0x89, 0x6b, 0x74, 0xa6, 0x7b, 0xc9,
749 0x96, 0x77, 0xb8, 0x31, 0x7d, 0x7c, 0x09, 0xd6, 0x63, 0x57, 0x54, 0x38, 0x99, 0xbd,
750 0x6c, 0xfb, 0xfd, 0xcb, 0xc6, 0x2a, 0x7c, 0xd2, 0x20, 0x76, 0x0f, 0xa6, 0x26, 0x20,
751 0x3f, 0xca, 0xe6, 0xa1, 0xfe, 0xa3, 0x03, 0x63, 0xb5, 0x85, 0x15, 0x88, 0xb1, 0x2d,
752 0xf9, 0xf1, 0x11, 0xd2, 0x65, 0x38, 0xdf, 0x0e, 0x0b, 0xac, 0x85, 0x16, 0xe1, 0xa8,
753 0xdb, 0x56, 0xc2, 0xd1, 0xd3, 0x37, 0x90, 0xd9, 0xa7, 0x5a, 0xc7, 0xdf, 0x04, 0x62,
754 0x51, 0xd6, 0x6d, 0x25, 0xcd, 0x4f, 0x58, 0xcc, 0x64, 0xf9, 0xe8, 0xc4, 0x13, 0xe9,
755 0x9c, 0xb1, 0xc5, 0x1b, 0xe8, 0x8f, 0x85, 0x81, 0x6e, 0x25, 0x81, 0xee, 0xff, 0x81,
756 0x75, 0xce, 0xb0, 0x4c, 0x6d, 0x7b, 0x0a, 0x30, 0x94, 0x1c, 0x7d, 0xa4, 0x48, 0x10,
757 0xd0, 0xf9, 0x82, 0xe8, 0x5c, 0x6c, 0xfd, 0x5d, 0x0b, 0xeb, 0x81, 0xae, 0x63, 0xb3,
758 0xb5, 0x7c, 0x50, 0xcc, 0xf2, 0xa2, 0x40, 0x5c, 0x47, 0x9b, 0xa6, 0x21, 0x9e, 0x87,
759 0x24, 0xa0, 0x5a, 0xc0, 0xaf, 0xff, 0x2f, 0x10, 0xc5, 0xd8, 0xde, 0x1b, 0x26, 0xe1,
760 0x40, 0x20, 0xca, 0x81, 0x15, 0x32, 0xcc, 0xc4, 0x9b, 0x91, 0x0a, 0xbc, 0x8d, 0xe2,
761 0xa9, 0x72, 0xbb, 0x6d, 0xa9, 0xdc, 0x34, 0x1d, 0x8c, 0xce, 0x5a, 0x26, 0xec, 0x0a,
762 0xa2, 0xd5, 0xad, 0xd4, 0xd0, 0xb7, 0x7f, 0xb6, 0xb8, 0x1c, 0xb4, 0xc8, 0x9b, 0x94,
763 0xda, 0x4d, 0xb8, 0xd9, 0x21, 0x7a, 0x9d, 0x93, 0x56, 0x73, 0x74, 0x36, 0x16, 0xe8,
764 0x13, 0x2b, 0x1a, 0xa5, 0x63, 0xee, 0x2b, 0x03, 0xff, 0xcc, 0x9d, 0xa3, 0x0c, 0x36,
765 0x9d, 0x0a, 0x19, 0x11, 0xf0, 0x07, 0x46, 0x92, 0x58, 0x3d, 0x2f, 0x3b, 0x5c, 0x10,
766 0x2f, 0xe4, 0x2b, 0xdc, 0x90, 0x6d, 0x21, 0xbe, 0x27, 0x79, 0x63, 0xe1, 0xc2, 0x11,
767 0x3b, 0x32, 0x45, 0xcc, 0x75, 0x53, 0x31, 0x6b, 0xc8, 0xfe, 0xa9, 0x16, 0x72, 0x40,
768 0x2a, 0xf2, 0xe9, 0x64, 0x94, 0x5e, 0xaf, 0xbc, 0x08, 0x72, 0x25, 0xe9, 0x67, 0x06,
769 0xb9, 0x50, 0xb8, 0x9f, 0xe5, 0x84, 0x95, 0xb8, 0xb5, 0x35, 0xce, 0xbd, 0x64, 0x85,
770 0xd1, 0x35, 0x6a, 0x33, 0x10, 0x7f, 0xf2, 0x9f, 0x61, 0x79, 0x29, 0x5a, 0xb9, 0x73,
771 0x83, 0xee, 0xe9, 0xaa, 0xad, 0x5a, 0xf9, 0x24, 0x00, 0x8d, 0x45, 0xe1, 0x33, 0x27,
772 0x38, 0x40, 0xc5, 0xe7, 0x00, 0x8e, 0x73, 0x82, 0x17, 0xdc, 0x85, 0x52, 0x3b, 0xef,
773 0x53, 0x67, 0xe3, 0xec, 0xe3, 0xb5, 0xa2, 0x3d, 0x36, 0xcc, 0x54, 0xb1, 0x8d, 0xa7,
774 0x62, 0x63, 0x4f, 0x8c, 0x94, 0x29, 0x16, 0xa3, 0x21, 0x52, 0x62, 0xa1, 0x91, 0x63,
775 0x2c, 0xa4, 0xbc, 0xc8, 0xaa, 0x7c, 0x76, 0xa0, 0x10, 0x25, 0xeb, 0x45, 0x5f, 0x91,
776 0x2e, 0x12, 0xb6, 0x25, 0xbe, 0x8c, 0xce, 0x97, 0xb4, 0x8b, 0xdd, 0xa8, 0x4e, 0x5c,
777 0x7a, 0x28, 0xf8, 0x66, 0x2a, 0xee, 0x54, 0xd9, 0x19, 0x9a, 0xf2, 0xd1, 0x1b, 0xb9,
778 0xcf, 0xc8, 0x76, 0x88, 0x42, 0xc0, 0x41, 0x1d, 0xb9, 0xcd, 0x08, 0x8f, 0x9e, 0x61,
779 0x79, 0x6c, 0x12, 0xa2, 0x8d, 0x38, 0x6c, 0x00, 0xc8, 0xb1, 0x1f, 0x11, 0xa3, 0xc1,
780 0xff, 0x4d, 0xca, 0xc8, 0xe3, 0xb2, 0xd9, 0xa7, 0xf0, 0x27, 0x90, 0xac, 0xca, 0xa5,
781 0x10, 0x2b, 0x24, 0xbb, 0xd6, 0x46, 0x29, 0x6f, 0xe5, 0x06, 0xad, 0x1b, 0xb3, 0xf3,
782 0xf9, 0x3d, 0x62, 0xd7, 0x9b, 0x17, 0xa9, 0xae, 0x3a, 0xf7, 0x37, 0x1d, 0xe0, 0x69,
783 0x2b, 0x92, 0x97, 0xc4, 0xf3, 0xf5, 0x06, 0xcc, 0xaa, 0x71, 0x45, 0x02, 0xad, 0x92,
784 0xfa, 0xa6, 0xea, 0x90, 0xfe, 0x1c, 0x5d, 0x54, 0x72, 0x7e, 0x38, 0xac, 0x24, 0xbe,
785 0xe7, 0x34, 0x1a, 0xcf, 0x5c, 0x14, 0x67, 0xfa, 0xc6, 0x4d, 0xa6, 0xd2, 0x54, 0x47,
786 0x51, 0xfd, 0xee, 0x9b, 0x3a, 0x96, 0x5c, 0x08, 0xe5, 0x03, 0x3a, 0x74, 0x5d, 0xac,
787 0x1e, 0x5d, 0x71, 0x3c, 0x41, 0x5c, 0x72, 0x69, 0xda, 0x93, 0x4a, 0xf7, 0x15, 0x2b,
788 0x43, 0xf9, 0x7d, 0xc6, 0x27, 0xd7, 0xc5, 0xc9, 0x56, 0xf5, 0x08, 0xb0, 0x2a, 0xf2,
789 0xe6, 0xa2, 0x84, 0xe7, 0xea, 0x00, 0x12, 0x1d, 0x5e, 0xae, 0x38, 0x38, 0x1d, 0x98,
790 0x1d, 0xa2, 0xa2, 0x08, 0xcb, 0xd9, 0xb1, 0x0a, 0xde, 0x5d, 0x11, 0x2c, 0x2e, 0x15,
791 0xf1, 0xa6, 0xaa, 0x20, 0x13, 0xec, 0xa2, 0x7d, 0x0e, 0xb7, 0x70, 0x37, 0xdf, 0x82,
792 0x38, 0x21, 0xcf, 0x21, 0xa4, 0x8e, 0x99, 0x9b, 0x47, 0xcf, 0xb8, 0x07, 0x0b, 0xb7,
793 0x34, 0x4c, 0x68, 0x91, 0x65, 0xe8, 0x9a, 0xa4, 0x4e, 0x1f, 0x71, 0xb6, 0xcf, 0x89,
794 0x2b, 0x32, 0xf8, 0xc3, 0x8b, 0x8e, 0x95, 0xb6, 0x3c, 0x27, 0xd0, 0x4a, 0xf6, 0x0f,
795 0x85, 0x1f, 0x99, 0x7a, 0x72, 0x7d, 0x73, 0x3f, 0x7b, 0x7b, 0x35, 0x41, 0xf0, 0x3d,
796 0xf6, 0xac, 0x6f, 0x0a, 0xbb, 0x70, 0x06, 0x51, 0xee, 0xe2, 0x9c, 0x32, 0xba, 0x0a,
797 0x08, 0x38, 0x11, 0x29, 0x47, 0x9a, 0x65, 0x7b, 0x15, 0x5b, 0xc5, 0xd2, 0x53, 0xc2,
798 0x86, 0x72, 0xc9, 0x35, 0x66, 0x76, 0x3a, 0x75, 0x52, 0xad, 0x04, 0x4a, 0x92, 0xfa,
799 0xbc, 0xc5, 0x36, 0x01, 0xd4, 0x18, 0x19, 0xfc, 0x45, 0xf8, 0x0a, 0xd5, 0x97, 0xe8,
800 0xb5, 0xd8, 0xe6, 0xb4, 0x86, 0x4f, 0xea, 0x95, 0x9d, 0x0d, 0x7b, 0xb4, 0x4a, 0x3a,
801 0x2a, 0xa7, 0xca, 0x2e, 0x7d, 0x58, 0x92, 0xa3, 0x15, 0xc4, 0x08, 0x87, 0xbe, 0x89,
802 0x62, 0xca, 0x28, 0x63, 0xd6, 0x75, 0xd6, 0xd0, 0xc8, 0xab, 0xdc, 0xb3, 0x32, 0x7c,
803 0x5f, 0x82, 0xf9, 0xc8, 0xc9, 0xca, 0xb8, 0x1e, 0x37, 0xa0, 0x84, 0x6e, 0x32, 0xce,
804 0x50, 0xca, 0x5c, 0xe5, 0x0c, 0x78, 0xbc, 0xbf, 0xb1, 0xd5, 0xb1, 0x96, 0x65, 0xe4,
805 0x7a, 0x45, 0x97, 0x2b, 0xd4, 0x06, 0x27, 0xb4, 0xd4, 0x1c, 0x44, 0x0a, 0x13, 0x08,
806 0x54, 0x80, 0xde, 0x58, 0xd8, 0xd0, 0x2e, 0x5f, 0xd2, 0x25, 0xf7, 0xc9, 0x36, 0x1d,
807 0xf5, 0xe7, 0x50, 0x30, 0x13, 0xb1, 0x50, 0x12, 0x45, 0xe8, 0xfd, 0xda, 0x57, 0x61,
808 0x84, 0x5f, 0xc7, 0x6a, 0x2e, 0xec, 0xcd, 0xe4, 0xc1, 0x97, 0xd2, 0xa9, 0xc9, 0x87,
809 0x1a, 0x22, 0x17, 0xaf, 0xc4, 0x50, 0xc6, 0xe2, 0x84, 0xd8, 0x62, 0xc4, 0xda, 0x8f,
810 0x7a, 0xf3, 0x29, 0x6d, 0xa0, 0x0f, 0x40, 0xff, 0xb6, 0x54, 0xef, 0x94, 0x1e, 0x59,
811 0xec, 0x12, 0x45, 0x0f, 0x1a, 0xfa, 0x92, 0x48, 0xa8, 0xbc, 0xf6, 0x1d, 0x0c, 0x51,
812 0xde, 0x89, 0xeb, 0x29, 0x6a, 0x6f, 0x2c, 0x97, 0x68, 0x83, 0x0d, 0x9b, 0x48, 0x5b,
813 0x47, 0x1e, 0x13, 0x81, 0xc5, 0xd7, 0x7f, 0xd1, 0x9c, 0x87, 0x98, 0xc6, 0x0a, 0x8e,
814 0x4d, 0x0c, 0xa8, 0xe1, 0x64, 0x30, 0x71, 0xb7, 0x0a, 0x35, 0x93, 0xe7, 0x01, 0x76,
815 0x38, 0xf4, 0x3f, 0xaf, 0x98, 0xa7, 0xe6, 0x16, 0x27, 0x55, 0x94, 0xab, 0x0a, 0xa6,
816 0xad, 0xdc, 0xac, 0xf7, 0x04, 0xe0, 0xa0, 0xf1, 0x55, 0x98, 0x82, 0x36, 0x09, 0xf7,
817 0x28, 0x45, 0xa6, 0x96, 0x9c, 0x26, 0xd6, 0x3a, 0x62, 0xb9, 0x27, 0x18, 0x7c, 0x6e,
818 0xed, 0x9d, 0x18, 0x19, 0xf9, 0x6d, 0x8a, 0x59, 0x91, 0x69, 0x4e, 0x48, 0x53, 0xe5,
819 0xb0, 0x69, 0xb8, 0x58, 0xdc, 0x3f, 0x51, 0x8a, 0x94, 0xdd, 0xb9, 0x14, 0x4a, 0xbc,
820 0x1f, 0x1d, 0x5d, 0x74, 0xf3, 0xb2, 0x00, 0x47, 0xd3, 0xaa, 0x51, 0x16, 0x4e, 0xac,
821 0x9b, 0x7a, 0xc9, 0x4c, 0xa5, 0xc9, 0x8f, 0x46, 0x6d, 0x99, 0x54, 0xa9, 0x1c, 0x54,
822 0x02, 0x23, 0x83, 0x7c, 0xcb, 0xc5, 0x4e, 0x98, 0x04, 0xf8, 0x5a, 0x35, 0xb3, 0x40,
823 0x37, 0x15, 0x1f, 0x3a, 0x64, 0x51, 0xc7, 0x46, 0x53, 0x8f, 0x38, 0xa8, 0xd6, 0x54,
824 0xfe, 0xf2, 0x8e, 0xc5, 0x80, 0x24, 0xf5, 0x37, 0xf6, 0x87, 0x2c, 0xb2, 0x68, 0x66,
825 0x15, 0x6d, 0xac, 0x27, 0x5b, 0x57, 0x99, 0xe9, 0xd3, 0x89, 0x87, 0x8d, 0x1c, 0x4f,
826 0xf5, 0x16, 0x65, 0xf7, 0xf9, 0xbf, 0x29, 0xcd, 0x02, 0xcd, 0x62, 0x31, 0x0b, 0x87,
827 0xf1, 0x5b, 0x78, 0xea, 0xba, 0x8c, 0xd3, 0x47, 0xbf, 0x1e, 0x3d, 0x0a, 0x5a, 0x94,
828 0xa6, 0x37, 0x9c, 0x5f, 0x16, 0xc6, 0x17, 0x65, 0x14, 0xb6, 0x2b, 0x2e, 0xef, 0x28,
829 0x8d, 0xb0, 0x68, 0x6e, 0x40, 0x3a, 0x40, 0x6f, 0x58, 0xf9, 0x41, 0x10, 0x85, 0x41,
830 0x61, 0x92, 0x70, 0x90, 0x67, 0x17, 0xbe, 0x41, 0x0a, 0x2d, 0xa6, 0x92, 0x68, 0x85,
831 0x9a, 0x8e, 0x1d, 0x7f, 0x1f, 0x22, 0x84, 0x2b, 0x32, 0x8c, 0x6c, 0xea, 0x02, 0xe2,
832 0x19, 0x78, 0x93, 0x42, 0x2c, 0xfa, 0x1d, 0xd6, 0xcf, 0x95, 0x0e, 0x6b, 0x8f, 0x30,
833 0x0b, 0xf8, 0x13, 0xa0, 0x30, 0x12, 0x10, 0x47, 0xb0, 0x58, 0xf0, 0xe8, 0xa5, 0x61,
834 0xe4, 0xec, 0x3d, 0xe5, 0x2e, 0x26, 0x42, 0xa4, 0xf8, 0x30, 0x50, 0xf3, 0xf4, 0x25,
835 0x8e, 0x31, 0xd0, 0xa9, 0x75, 0x05, 0xa3, 0xa1, 0xae, 0x97, 0xb2, 0x0f, 0xd4, 0xd3,
836 0x0f, 0x1f, 0x21, 0x53, 0xf0, 0x61, 0xff, 0x70, 0x74, 0xda, 0x28, 0x71, 0x95, 0xbb,
837 0x4e, 0xa1, 0x4c, 0xb5, 0xe8, 0xa9, 0xe8, 0x30, 0x3d, 0xa2, 0x84, 0xee, 0x60, 0x13,
838 0x4a, 0xe9, 0x6c, 0x52, 0x24, 0x7e, 0xb3, 0xa1, 0xf1, 0x34, 0x49, 0x03, 0x2d, 0x83,
839 0x77, 0xd4, 0xb8, 0x60, 0x30, 0x45, 0x2a, 0x3a, 0xa8, 0x53, 0x7b, 0xd4, 0x9f, 0x8d,
840 0xd1, 0x14, 0xed, 0x16, 0xb2, 0xc1, 0x89, 0x14, 0xe0, 0x35, 0xf5, 0x67, 0xcc, 0x9f,
841 0xd1, 0x38, 0xa3, 0xd2, 0x89, 0x86, 0xb6, 0x8d, 0xf8, 0x08, 0xfe, 0x09, 0xbd, 0xec,
842 0x53, 0x10, 0x24, 0x51, 0x17, 0x7b, 0x5f, 0xc0, 0x72, 0xe5, 0x4d, 0x25, 0x56, 0x86,
843 0x01, 0xb6, 0x22, 0x17, 0x2f, 0xb9, 0x0b, 0x56, 0x65, 0x83, 0x85, 0xd8, 0x77, 0x59,
844 0xd4, 0x33, 0x92, 0x95, 0x9a, 0x06, 0x87, 0x25, 0x6a, 0xf9, 0x34, 0xb5, 0x2f, 0x47,
845 0xc6, 0x3d, 0xa7, 0xbe, 0x16, 0x20, 0x7f, 0x72, 0x31, 0x17, 0xb3, 0xf9, 0x44, 0xfc,
846 0x70, 0x31, 0x9f, 0xcd, 0xa3, 0x72, 0x3f, 0xce, 0xee, 0x7f, 0xba, 0xf9, 0x70, 0x2f,
847 0x3e, 0x5e, 0xdc, 0xdd, 0x5d, 0x5c, 0xdf, 0xcf, 0xae, 0xe6, 0x02, 0x73, 0xf8, 0x62,
848 0x2c, 0x7f, 0xf3, 0x0e, 0x23, 0xf8, 0x5f, 0xc4, 0xdf, 0x66, 0xd7, 0x97, 0xa0, 0x3b,
849 0xda, 0x4f, 0x80, 0x1f, 0xa9, 0x3b, 0xea, 0xf2, 0x4d, 0x34, 0xe3, 0xca, 0xb2, 0x68,
850 0x93, 0xe6, 0x08, 0xe2, 0x3e, 0xa9, 0x8c, 0x38, 0x85, 0xa6, 0xba, 0x57, 0x15, 0x17,
851 0x44, 0xf6, 0x18, 0x62, 0xa1, 0xcc, 0xfb, 0xd9, 0xfd, 0x7b, 0xbc, 0x07, 0x70, 0x7d,
852 0x73, 0xfd, 0x72, 0x76, 0xfd, 0xee, 0x6e, 0x76, 0xfd, 0xe3, 0xd5, 0xcf, 0x57, 0xd7,
853 0xf7, 0x95, 0xf8, 0xf9, 0xea, 0xee, 0xed, 0x4f, 0x90, 0xf2, 0xe2, 0x87, 0xd9, 0xfb,
854 0xd9, 0xfd, 0x2f, 0xec, 0x42, 0xef, 0x66, 0xf7, 0xd7, 0x57, 0x73, 0xff, 0xfa, 0xc0,
855 0x45, 0xd8, 0xe3, 0xf6, 0xe2, 0x0e, 0x06, 0xfb, 0xf0, 0xfe, 0xe2, 0x4e, 0xdc, 0x7e,
856 0xb8, 0xbb, 0xbd, 0x99, 0x5f, 0xf9, 0x6c, 0xeb, 0xa7, 0x85, 0x2d, 0x4d, 0x16, 0x20,
857 0xff, 0x16, 0x87, 0x6a, 0x9e, 0x3a, 0xf0, 0x64, 0xc6, 0x57, 0x85, 0x63, 0x77, 0x81,
858 0xe5, 0xac, 0xd9, 0x62, 0x02, 0x03, 0x6f, 0xe0, 0x0b, 0x37, 0xf0, 0x2e, 0x7a, 0x84,
859 0xfd, 0x2f, 0x23, 0x6e, 0xd1, 0x2f, 0xf5, 0xdd, 0x46, 0x34, 0x6e, 0x37, 0x5c, 0xab,
860 0x44, 0xb8, 0xd6, 0x8e, 0x91, 0xdd, 0x99, 0x5a, 0xa7, 0x32, 0xd9, 0x83, 0x7a, 0x98,
861 0xb3, 0x72, 0x37, 0xb6, 0x1c, 0xb4, 0x1e, 0x17, 0xb3, 0xde, 0xf7, 0xfe, 0x32, 0xc5,
862 0xe7, 0xa8, 0x52, 0x5a, 0xf4, 0x5e, 0xcb, 0x05, 0xba, 0xcb, 0xe4, 0x7c, 0x33, 0xca,
863 0xbc, 0x02, 0xf4, 0xa7, 0xeb, 0x59, 0x0e, 0xbf, 0x07, 0xbe, 0x6a, 0xb9, 0xd9, 0x09,
864 0x19, 0x51, 0x69, 0x17, 0xad, 0x96, 0x38, 0xc9, 0x82, 0x03, 0xf5, 0x65, 0xcb, 0xa0,
865 0x53, 0xab, 0x56, 0x83, 0x7d, 0xd5, 0xea, 0xbc, 0x4a, 0xd3, 0xee, 0x6a, 0xd4, 0xca,
866 0x4d, 0x9d, 0x9f, 0xcf, 0xfa, 0xfb, 0x99, 0x27, 0x0a, 0xd4, 0xd3, 0x6f, 0xf5, 0x82,
867 0x09, 0x1d, 0x0b, 0xb7, 0xa2, 0x7e, 0x44, 0x9a, 0x5b, 0xc4, 0x23, 0x7b, 0x7a, 0x03,
868 0xc1, 0xf1, 0x74, 0xfc, 0x74, 0x7c, 0x78, 0xf4, 0x1c, 0xa5, 0x0f, 0x6a, 0xca, 0x44,
869 0x93, 0xb5, 0x9a, 0x0f, 0x0e, 0x1d, 0x01, 0x36, 0xad, 0xdc, 0xa0, 0x4b, 0x3e, 0xea,
870 0xe1, 0xd3, 0xea, 0xf8, 0x4a, 0x40, 0x7e, 0x39, 0xc0, 0x6d, 0x15, 0xcd, 0xd6, 0x8b,
871 0xe9, 0x33, 0x02, 0x0a, 0xc4, 0xd6, 0x8f, 0x12, 0x88, 0xc0, 0xf8, 0x9e, 0x2e, 0x0d,
872 0xe4, 0xc2, 0xa6, 0x11, 0xa1, 0xa9, 0xe7, 0x06, 0xb9, 0xa9, 0x5d, 0x6d, 0xfd, 0xcc,
873 0x9c, 0xb2, 0x78, 0xca, 0xd5, 0x34, 0x35, 0x3e, 0x2c, 0x74, 0x59, 0x9b, 0x43, 0xc2,
874 0x98, 0xc1, 0x7f, 0x83, 0xbe, 0x84, 0x37, 0x66, 0x81, 0xab, 0x65, 0xc7, 0xe0, 0xec,
875 0xd9, 0x99, 0x78, 0x94, 0x8a, 0xae, 0xdd, 0x1a, 0xef, 0xb0, 0x2b, 0x63, 0xd0, 0x2a,
876 0x6c, 0xcb, 0xde, 0x21, 0x1a, 0x21, 0xbd, 0xd9, 0x6e, 0x25, 0x75, 0x09, 0x89, 0x13,
877 0x0c, 0x24, 0x78, 0x83, 0x11, 0xc5, 0x60, 0x7d, 0x36, 0x42, 0x0b, 0x7c, 0xe8, 0x32,
878 0xb9, 0xe1, 0x24, 0x78, 0xe2, 0x4d, 0x10, 0x9a, 0x02, 0x90, 0xf3, 0x96, 0xfa, 0xf0,
879 0x07, 0x2b, 0x07, 0xc7, 0x21, 0x3f, 0x24, 0x82, 0x7e, 0xd8, 0x88, 0x0b, 0x7b, 0xa4,
880 0x66, 0xba, 0x5c, 0x62, 0xb8, 0x49, 0x93, 0x82, 0x26, 0xbc, 0xbe, 0x81, 0x08, 0x08,
881 0x4a, 0x88, 0x2f, 0x37, 0x84, 0xed, 0x7d, 0x04, 0x7c, 0x37, 0x15, 0x17, 0x35, 0xe5,
882 0x04, 0xd2, 0x42, 0x44, 0x5e, 0x3a, 0xf9, 0x22, 0x27, 0xea, 0x22, 0x28, 0x3e, 0xae,
883 0x89, 0xba, 0x8f, 0xc3, 0xf5, 0x70, 0x58, 0xf8, 0xec, 0xb8, 0x2d, 0xb2, 0xd0, 0x7a,
884 0x6d, 0x8c, 0xef, 0x82, 0x72, 0xa7, 0x73, 0x34, 0x6c, 0xe7, 0x9e, 0x2b, 0x78, 0x5b,
885 0xa3, 0x18, 0x4f, 0x00, 0x75, 0x2c, 0xa1, 0xec, 0x6a, 0xe5, 0x2f, 0xb1, 0xf5, 0x6d,
886 0xd0, 0x80, 0x7e, 0x7b, 0xf6, 0x3b, 0xb5, 0xe9, 0xe8, 0xd5, 0x92, 0xdc, 0x10, 0xf3,
887 0x6a, 0x6d, 0xa3, 0xec, 0x98, 0xf9, 0xb7, 0xa1, 0x0b, 0xc5, 0xbc, 0xe5, 0x15, 0xc1,
888 0x0e, 0x31, 0x5f, 0x3f, 0x6a, 0xc1, 0x7d, 0x28, 0x5e, 0x42, 0x7d, 0xa5, 0xdd, 0x68,
889 0xdc, 0x83, 0x02, 0xe3, 0x27, 0xbc, 0x07, 0xf3, 0x40, 0x6f, 0xc2, 0x50, 0x51, 0x95,
890 0x14, 0xc6, 0xfa, 0x2c, 0x36, 0xce, 0xf7, 0xe3, 0x37, 0x5a, 0xba, 0xb6, 0x98, 0x86,
891 0x24, 0xce, 0x1d, 0xc6, 0x22, 0xdc, 0xc4, 0x0d, 0x5f, 0x13, 0x90, 0x66, 0x18, 0x65,
892 0x79, 0x99, 0xe9, 0xe4, 0x29, 0x4a, 0x46, 0xf4, 0xdc, 0x29, 0x2a, 0xdc, 0x20, 0xf4,
893 0x84, 0xa9, 0x66, 0xd2, 0x8d, 0xc7, 0x67, 0x0a, 0x78, 0x1f, 0xef, 0xac, 0x9b, 0x26,
894 0xe9, 0x06, 0xe3, 0x40, 0x94, 0x2b, 0x7e, 0x05, 0x98, 0xf1, 0xf2, 0x44, 0xeb, 0x5c,
895 0xda, 0x0d, 0x23, 0x51, 0x24, 0xd7, 0x49, 0x8b, 0x39, 0x9c, 0x07, 0x6b, 0xf3, 0xb4,
896 0x2c, 0x74, 0x8e, 0x81, 0xc9, 0xa8, 0xca, 0xa9, 0x58, 0xf5, 0x4d, 0xd4, 0xea, 0xb8,
897 0x6f, 0xbc, 0xd8, 0x07, 0xb2, 0x91, 0x2f, 0xb4, 0x27, 0x0d, 0x64, 0x9d, 0x26, 0x32,
898 0xbf, 0x2b, 0xbc, 0xb1, 0xa0, 0x8d, 0x49, 0x16, 0xef, 0xc0, 0x57, 0x78, 0xa7, 0x0d,
899 0x79, 0xf5, 0xd4, 0x6b, 0x70, 0xfc, 0xfb, 0xc5, 0xed, 0x2d, 0x1e, 0x99, 0xfd, 0xe3,
900 0x0d, 0x99, 0x90, 0xbb, 0x05, 0x40, 0xd4, 0x7d, 0x78, 0x7d, 0xa1, 0x7c, 0x75, 0x8f,
901 0x7e, 0x63, 0x51, 0x76, 0x69, 0x96, 0x44, 0xaf, 0xd7, 0x7d, 0xe1, 0x82, 0x2a, 0xbc,
902 0x46, 0x31, 0xee, 0x26, 0x44, 0x5a, 0x6d, 0x10, 0x35, 0x16, 0x65, 0x78, 0x1f, 0xbb,
903 0x1a, 0x55, 0xae, 0xe4, 0xd1, 0x7c, 0x6b, 0x97, 0x0e, 0xbd, 0xe6, 0x1a, 0xc1, 0xee,
904 0x41, 0x7f, 0x41, 0x53, 0x4a, 0x05, 0xcf, 0x9c, 0xfc, 0xfa, 0xdb, 0x24, 0x17, 0x29,
905 0xd4, 0x99, 0x08, 0xd9, 0x6e, 0x1f, 0x9d, 0x89, 0x51, 0x35, 0x54, 0x7d, 0x45, 0x25,
906 0x3d, 0x15, 0x67, 0x97, 0xa6, 0xfb, 0x43, 0x7a, 0x5f, 0xa0, 0x88, 0xd1, 0xb8, 0xf9,
907 0xef, 0xce, 0x05, 0x57, 0xeb, 0x5c, 0xa6, 0x3a, 0xd0, 0x0b, 0x78, 0x02, 0x28, 0x7e,
908 0x92, 0x23, 0x54, 0x07, 0x45, 0xda, 0x2e, 0x66, 0xb3, 0x14, 0x2b, 0x6e, 0x0f, 0x3c,
909 0x7f, 0x4c, 0x83, 0x50, 0x2e, 0xea, 0xbd, 0x00, 0xc0, 0x09, 0x2c, 0x6c, 0x1d, 0x0d,
910 0xa8, 0xfc, 0xd3, 0xa1, 0x4f, 0x1a, 0x51, 0x9c, 0x9f, 0xf5, 0x7e, 0x03, 0x2f, 0x23,
911 0xc6, 0xea, 0xcb, 0x2e, 0xa6, 0x99, 0xdb, 0x98, 0x8c, 0xe3, 0x68, 0x75, 0xa1, 0xf2,
912 0x2b, 0x2b, 0x3c, 0x21, 0x8d, 0x92, 0x38, 0x5a, 0x38, 0x81, 0x70, 0xdc, 0xb8, 0x26,
913 0x0c, 0x9e, 0x50, 0xae, 0x18, 0x4f, 0x3e, 0xc3, 0xcb, 0x2f, 0x24, 0x26, 0x1c, 0x4f,
914 0xa7, 0x79, 0x7c, 0xd0, 0x5c, 0x9c, 0xbb, 0xa6, 0xf6, 0x4c, 0x6e, 0x72, 0x48, 0x5b,
915 0xaf, 0x69, 0x62, 0xed, 0x9d, 0x21, 0x0f, 0x13, 0x7f, 0xdd, 0xe3, 0xcf, 0x6f, 0xe2,
916 0x57, 0x96, 0x1b, 0x72, 0x1e, 0x4c, 0x59, 0x7f, 0xe3, 0xc7, 0x83, 0x93, 0x2c, 0x8b,
917 0x9a, 0x69, 0xec, 0x3e, 0x55, 0xf9, 0x42, 0xa8, 0x38, 0xa3, 0x07, 0xd2, 0x3b, 0x97,
918 0xe7, 0xdf, 0xd3, 0x16, 0xb1, 0x1e, 0x21, 0x20, 0xf0, 0xe9, 0x2b, 0xb4, 0xcf, 0x23,
919 0x8d, 0xd7, 0x5d, 0x28, 0x43, 0x19, 0x1a, 0x93, 0x47, 0x25, 0x8a, 0x53, 0x54, 0xfd,
920 0x66, 0xc1, 0xdd, 0x32, 0x39, 0x6a, 0xd9, 0x45, 0x47, 0x96, 0x7d, 0x74, 0xf7, 0xcf,
921 0xbd, 0x72, 0xfa, 0x1e, 0xdc, 0xfd, 0x7a, 0x7e, 0xf5, 0x12, 0x22, 0xf3, 0x92, 0x2f,
922 0x61, 0xe8, 0x4f, 0x71, 0x8f, 0xf0, 0xce, 0xd9, 0x8b, 0xb2, 0x4b, 0x39, 0xd2, 0x57,
923 0x14, 0x8f, 0x5e, 0x61, 0x28, 0x1e, 0x78, 0x8a, 0x81, 0xff, 0x8f, 0xf4, 0x3b, 0x12,
924 0x6f, 0x56, 0xdb, 0x5c, 0xa9, 0x91, 0x08, 0xd1, 0xc9, 0x99, 0xd6, 0xc0, 0x67, 0x70,
925 0xb5, 0x6e, 0x35, 0xc0, 0xe1, 0x40, 0x09, 0x90, 0x16, 0xba, 0xc3, 0x37, 0xfb, 0x42,
926 0xb7, 0x24, 0xf3, 0x75, 0x77, 0x7c, 0xaf, 0xe9, 0x8b, 0xff, 0x00,
927 ];
928 }
929
930 #[test]
931 fn test_bitstream_copy_bytes() -> Result<(), ErrorTrace> {
932 let test_data: [u8; 16] = [
933 0x78, 0xda, 0xbd, 0x59, 0x6d, 0x8f, 0xdb, 0xb8, 0x11, 0xfe, 0x7c, 0xfa, 0x15, 0xc4,
934 0x7e, 0xb9,
935 ];
936 let mut test_bitstream: DeflateBitstream = DeflateBitstream::new(&test_data, 0);
937
938 let test_value: u32 = test_bitstream.get_value(4);
939 assert_eq!(test_value, 0x00000008);
940
941 let mut output_data: [u8; 6] = [0; 6];
942 test_bitstream.copy_bytes(5, &mut output_data, 0, 6)?;
943 assert_eq!(output_data, [0xda, 0xbd, 0x59, 0x6d, 0x8f, 0x00]);
944
945 let test_value: u32 = test_bitstream.get_value(16);
946 assert_eq!(test_value, 0x0000b8db);
947
948 Ok(())
949 }
950
951 #[test]
952 fn test_bitstream_get_value() {
953 let test_data: [u8; 16] = [
954 0x78, 0xda, 0xbd, 0x59, 0x6d, 0x8f, 0xdb, 0xb8, 0x11, 0xfe, 0x7c, 0xfa, 0x15, 0xc4,
955 0x7e, 0xb9,
956 ];
957 let mut test_bitstream: DeflateBitstream = DeflateBitstream::new(&test_data, 0);
958
959 let test_value: u32 = test_bitstream.get_value(0);
960 assert_eq!(test_value, 0);
961
962 let test_value: u32 = test_bitstream.get_value(4);
963 assert_eq!(test_value, 0x00000008);
964
965 let test_value: u32 = test_bitstream.get_value(12);
966 assert_eq!(test_value, 0x00000da7);
967
968 let test_value: u32 = test_bitstream.get_value(32);
969 assert_eq!(test_value, 0x8f6d59bd);
970
971 let mut test_bitstream: DeflateBitstream = DeflateBitstream::new(&test_data, 0);
972
973 let test_value: u32 = test_bitstream.get_value(12);
974 assert_eq!(test_value, 0x000000a78);
975
976 let test_value: u32 = test_bitstream.get_value(32);
977 assert_eq!(test_value, 0xf6d59bdd);
978 }
979
980 #[test]
981 fn test_bitstream_skip_bits() {
982 let test_data: [u8; 16] = [
983 0x78, 0xda, 0xbd, 0x59, 0x6d, 0x8f, 0xdb, 0xb8, 0x11, 0xfe, 0x7c, 0xfa, 0x15, 0xc4,
984 0x7e, 0xb9,
985 ];
986 let mut test_bitstream: DeflateBitstream = DeflateBitstream::new(&test_data, 0);
987
988 test_bitstream.skip_bits(4);
989 let test_value: u32 = test_bitstream.get_value(12);
990 assert_eq!(test_value, 0x00000da7);
991 }
992
993 #[test]
994 fn test_build_dynamic_huffman_trees() -> Result<(), ErrorTrace> {
995 let test_data: Vec<u8> = get_test_data();
996 let mut test_context: DeflateContext = DeflateContext::new();
997
998 let mut test_bitstream: DeflateBitstream = DeflateBitstream::new(&test_data, 0);
999
1000 let mut test_literals_huffman_tree: HuffmanTree = HuffmanTree::new(288, 15);
1001 let mut test_distances_huffman_tree: HuffmanTree = HuffmanTree::new(30, 15);
1002
1003 let test_value: u32 = test_bitstream.get_value(3);
1005 assert_eq!(test_value, 0x00000005);
1006
1007 test_context.build_dynamic_huffman_trees(
1008 &mut test_bitstream,
1009 &mut test_literals_huffman_tree,
1010 &mut test_distances_huffman_tree,
1011 )?;
1012 Ok(())
1013 }
1014
1015 #[test]
1016 fn test_decompress() -> Result<(), ErrorTrace> {
1017 let mut test_context: DeflateContext = DeflateContext::new();
1018
1019 let test_data: Vec<u8> = get_test_data();
1020 let mut uncompressed_data: Vec<u8> = vec![0; 11358];
1021 test_context.decompress(&test_data, &mut uncompressed_data)?;
1022 assert_eq!(test_context.uncompressed_data_size, 11358);
1023
1024 let expected_data: Vec<u8> = match fs::read("../LICENSE") {
1025 Ok(data) => data,
1026 Err(error) => {
1027 return Err(keramics_core::error_trace_new_with_error!(
1028 "Unable read test reference file",
1029 error
1030 ));
1031 }
1032 };
1033 assert_eq!(&uncompressed_data, &expected_data);
1034
1035 Ok(())
1036 }
1037}