huff_coding/tree/tree_inner.rs
1use crate::{
2 prelude::*,
3 utils::size_of_bits,
4 bitvec::prelude::{bitvec, BitVec, Msb0},
5};
6use super::branch_heap::HuffBranchHeap;
7
8use std::{
9 fmt,
10 mem,
11 collections::{hash_map::RandomState, HashMap},
12 hash::BuildHasher,
13};
14
15
16
17/// Struct representing a Huffman Tree with an alphabet of
18/// type implementing [`HuffLetter`][letter]
19///
20/// A `HuffTree` can be initialized in two ways:
21/// * from a struct implementing the [`Weights<L>`][weights] trait ([`from_weights`](#method.from_weights)),
22/// where `L` must implement the [`HuffLetter`][letter] trait
23/// * from a binary representation ([`try_from_bin`](#method.try_from_bin)):
24/// [`BitVec<Msb0, u8>`][bitvec::prelude::BitVec], where in order to even get it,
25/// `L` must implement the [`HuffLetterAsBytes`][letter_bytes] trait
26///
27/// Codes stored by the tree can be retrieved using the [`codes`](#method.codes) method
28///
29/// # How it works
30/// ---
31/// When initialized with the [`HuffTree::from_weights`](#method.from_weights) method it
32/// follows the steps of the [Huffman Coding algorithm][huff_wiki] (duh):
33/// 1. Creates standalone branches for every letter found in the given weights and
34/// pushes them onto a branch heap
35/// 2. Finds two branches with the lowest weights
36/// 3. Makes them children to a branch with a [`None`][None] letter and
37/// the children's summed up weight
38/// 4. Removes the two found branches from the heap and adds the newly created
39/// branch into it
40/// 5. Repeats steps 2 to 4 until there's only one branch left
41/// 6. Sets the only branch left as root
42/// 7. Recurses into the tree to set every branch's code
43/// * Every branch gets its parent's code with its own position in the parent branch (left - 0, right - 1)
44///
45/// Initializing from bits goes as follows:
46/// 1. Go through the `HuffTree` encoded in binary ([big endian][end_wiki]) bit by bit
47/// 2. Every 1 means a joint branch
48/// 3. Every 0 means a letter branch followed by [`size_of::<L> * 8`][mem::size_of] bits representing
49/// the stored letter
50///
51///
52/// # Examples
53/// ---
54/// Initialization from [`ByteWeights`][byte_weights]
55/// ```
56/// use huff_coding::{
57/// bitvec::prelude::*,
58/// prelude::{HuffTree, ByteWeights},
59/// };
60/// use std::collections::HashMap;
61///
62/// let tree = HuffTree::from_weights(
63/// ByteWeights::from_bytes(b"abbccc")
64/// );
65/// let codes = tree.read_codes();
66///
67/// assert_eq!(
68/// codes.get(&b'c').unwrap(),
69/// &bitvec![Msb0, u8; 0]
70/// );
71/// assert_eq!(
72/// codes.get(&b'b').unwrap(),
73/// &bitvec![Msb0, u8; 1, 1]
74/// );
75/// assert_eq!(
76/// codes.get(&b'a').unwrap(),
77/// &bitvec![Msb0, u8; 1, 0]
78/// );
79/// ```
80/// Initialization from [`HashMap<L, usize>`][HashMap]:
81/// ```
82/// use huff_coding::{
83/// bitvec::prelude::*,
84/// prelude::{HuffTree, Weights},
85/// };
86/// use std::collections::HashMap;
87///
88/// let mut weights = HashMap::new();
89/// weights.insert(String::from("pudzian"), 1);
90/// weights.insert(String::from("krol"), 2);
91/// weights.insert(String::from("szef"), 3);
92///
93/// let tree = HuffTree::from_weights(weights);
94/// let codes = tree.read_codes();
95///
96/// assert_eq!(
97/// codes.get("szef").unwrap(),
98/// &bitvec![Msb0, u8; 0]
99/// );
100/// assert_eq!(
101/// codes.get("krol").unwrap(),
102/// &bitvec![Msb0, u8; 1, 1]
103/// );
104/// assert_eq!(
105/// codes.get("pudzian").unwrap(),
106/// &bitvec![Msb0, u8; 1, 0]
107/// );
108/// ```
109/// Representing and reading the tree from bits:
110/// ```
111/// use huff_coding::prelude::{HuffTree, ByteWeights};
112///
113/// let tree = HuffTree::from_weights(
114/// ByteWeights::from_bytes(b"abbccc")
115/// );
116///
117/// let tree_bin = tree.as_bin();
118/// // the tree's root's left child is a letter branch, which are encoded by a 0
119/// assert_eq!(*tree_bin.get(1).unwrap(), false);
120///
121/// let new_tree = HuffTree::try_from_bin(tree_bin).unwrap();
122/// // the newly created tree is identical, except in weights
123/// assert_eq!(
124/// tree.read_codes(),
125/// new_tree.read_codes()
126/// );
127/// assert_ne!(
128/// tree
129/// .root()
130/// .leaf()
131/// .weight(),
132/// new_tree
133/// .root()
134/// .leaf()
135/// .weight()
136/// );
137/// // every weight in a HuffTree read from binary is set to 0
138/// assert_eq!(
139/// new_tree
140/// .root()
141/// .leaf()
142/// .weight(),
143/// 0
144/// );
145/// ```
146///
147/// # Panics
148/// ---
149/// When trying to create a `HuffTree<L>` from a type implementing
150/// [`Weights<L>`][weights] with len == 0:
151/// ```should_panic
152/// use huff_coding::prelude::{HuffTree, Weights};
153/// use std::collections::HashMap;
154///
155/// let weights = HashMap::<char, usize>::new();
156///
157/// // panics here at 'provided empty weights'
158/// let tree = HuffTree::from_weights(weights);
159/// ```
160///
161/// # Errors
162/// ---
163/// When trying to create a `HuffTree<L>` from binary where the original's
164/// letter type is different than the one specified to be read:
165/// ```should_panic
166/// use huff_coding::prelude::{HuffTree, ByteWeights};
167///
168/// let tree = HuffTree::from_weights(
169/// ByteWeights::from_bytes(b"abbccc")
170/// );
171/// let tree_bin = tree.as_bin();
172/// let new_tree = HuffTree::<u128>::try_from_bin(tree_bin)
173/// .expect("this will return a FromBinError");
174/// ```
175/// or when providing a too small/big BitVec to create a HuffTree<L>:
176/// ```should_panic
177/// use huff_coding::{
178/// bitvec::prelude::*,
179/// prelude::{HuffTree, ByteWeights},
180/// };
181///
182/// let tree = HuffTree::<u128>::try_from_bin(bitvec![Msb0, u8; 0, 1])
183/// .expect("this will return a FromBinError (provided BitVec is to small)");
184/// ```
185///
186/// [branch]:crate::tree::branch::HuffBranch
187/// [letter]:crate::tree::letter::HuffLetter
188/// [letter_bytes]:crate::tree::letter::HuffLetterAsBytes
189/// [weights]:crate::weights::Weights
190/// [byte_weights]:crate::weights::ByteWeights
191/// [huff_wiki]:https://en.wikipedia.org/wiki/Huffman_coding
192/// [end_wiki]:https://en.wikipedia.org/wiki/Endianness
193#[derive(Debug, Clone)]
194pub struct HuffTree<L: HuffLetter>{
195 root: HuffBranch<L>,
196}
197
198impl<L: HuffLetter> HuffTree<L>{
199 /// Initialize the `HuffTree` with a struct implementing the [`Weights<L>`][weights] trait,
200 /// where `L` implements [`HuffLetter`][letter]
201 ///
202 /// In order to get the tree represented in binary([`Bitvec<Msb0, u8>`][bitvec::prelude::BitVec]) you must ensure
203 /// that `L` also implements [`HuffLetterAsBytes`][letter_bytes]
204 ///
205 /// # Examples
206 /// ---
207 /// Initialization from [`ByteWeights`][byte_weights]
208 /// ```
209 /// use huff_coding::{
210 /// bitvec::prelude::*,
211 /// prelude::{HuffTree, ByteWeights},
212 /// };
213 /// use std::collections::HashMap;
214 ///
215 /// let tree = HuffTree::from_weights(
216 /// ByteWeights::from_bytes(b"deefff")
217 /// );
218 /// let codes = tree.read_codes();
219 ///
220 /// assert_eq!(
221 /// codes.get(&b'f').unwrap(),
222 /// &bitvec![Msb0, u8; 0]
223 /// );
224 /// assert_eq!(
225 /// codes.get(&b'e').unwrap(),
226 /// &bitvec![Msb0, u8; 1, 1]
227 /// );
228 /// assert_eq!(
229 /// codes.get(&b'd').unwrap(),
230 /// &bitvec![Msb0, u8; 1, 0]
231 /// );
232 /// ```
233 /// Initialization from [`HashMap<L, usize>`][std::collections::HashMap]:
234 /// ```
235 /// use huff_coding::{
236 /// bitvec::prelude::*,
237 /// prelude::{HuffTree, Weights},
238 /// };
239 /// use std::collections::HashMap;
240 ///
241 /// let mut weights = HashMap::new();
242 /// weights.insert('ฤ
', 1);
243 /// weights.insert('รพ', 2);
244 /// weights.insert('๐', 3);
245 ///
246 /// let tree = HuffTree::from_weights(weights);
247 /// let codes = tree.read_codes();
248 ///
249 /// assert_eq!(
250 /// codes.get(&'๐').unwrap(),
251 /// &bitvec![Msb0, u8; 0]
252 /// );
253 /// assert_eq!(
254 /// codes.get(&'รพ').unwrap(),
255 /// &bitvec![Msb0, u8; 1, 1]
256 /// );
257 /// assert_eq!(
258 /// codes.get(&'ฤ
').unwrap(),
259 /// &bitvec![Msb0, u8; 1, 0]
260 /// );
261 /// ```
262 ///
263 /// # Panics
264 /// ---
265 /// When trying to create a `HuffTree<L>` from a type implementing
266 /// [`Weights<L>`][weights] with len == 0:
267 /// ```should_panic
268 /// use huff_coding::prelude::{HuffTree, Weights};
269 /// use std::collections::HashMap;
270 ///
271 /// let weights = HashMap::<char, usize>::new();
272 ///
273 /// // panics here at 'provided empty weights'
274 /// let tree = HuffTree::from_weights(weights);
275 /// ```
276 ///
277 /// [letter]:crate::tree::letter::HuffLetter
278 /// [letter_bytes]:crate::tree::letter::HuffLetterAsBytes
279 /// [weights]:crate::weights::Weights
280 /// [byte_weights]:crate::weights::ByteWeights
281 pub fn from_weights<W: Weights<L>>(weights: W) -> Self{
282 // panic when provided with empty weights
283 if weights.is_empty(){
284 panic!("provided empty weights")
285 }
286
287 let mut branch_heap = HuffBranchHeap::from_weights(weights);
288
289 while branch_heap.len() > 1{
290 // get the min pair, removing it from the heap
291 let min = branch_heap.pop_min();
292 let next_min = branch_heap.pop_min();
293
294 // initialize a joint branch and push it onto the heap
295 let branch = HuffBranch::new(
296 HuffLeaf::new(
297 None,
298 min.leaf().weight() + next_min.leaf().weight()
299 ),
300 Some((min, next_min))
301 );
302 branch_heap.push(branch);
303 }
304
305 // last branch in branch_heap is root
306 let mut root = branch_heap.pop_min();
307
308 // set codes for all branches recursively if has children
309 // else just set the root's code to 0
310 if root.has_children(){
311 HuffTree::set_codes_in_child_branches(&mut root, None);
312 }
313 else{
314 root.set_code({let mut c = BitVec::with_capacity(1); c.push(false); c});
315 }
316
317 HuffTree{
318 root
319 }
320 }
321
322 /// Return a reference to the tree's root branch
323 pub fn root(&self) -> &HuffBranch<L>{
324 &self.root
325 }
326
327 /// Return a mutable reference to the tree's root branch
328 pub fn root_mut(&mut self) -> &mut HuffBranch<L>{
329 &mut self.root
330 }
331
332 /// Go down the tree reading every letter's code and returning
333 /// a [`HashMap<L, BitVec<Msb0, u8>>`][HashMap]
334 ///
335 /// # Example
336 /// ---
337 /// ```
338 /// use huff_coding::{
339 /// bitvec::prelude::*,
340 /// prelude::{HuffTree, ByteWeights},
341 /// };
342 /// use std::collections::HashMap;
343 ///
344 /// let tree = HuffTree::from_weights(
345 /// ByteWeights::from_bytes(b"ghhiii")
346 /// );
347 /// let codes = tree.read_codes();
348 ///
349 /// let mut cmp_codes = HashMap::new();
350 /// cmp_codes.insert(b'i', bitvec![Msb0, u8; 0]);
351 /// cmp_codes.insert(b'h', bitvec![Msb0, u8; 1, 1]);
352 /// cmp_codes.insert(b'g', bitvec![Msb0, u8; 1, 0]);
353 ///
354 /// assert_eq!(codes, cmp_codes);
355 /// ```
356 pub fn read_codes(&self) -> HashMap<L, BitVec<Msb0, u8>>{
357 self.read_codes_with_hasher(RandomState::default())
358 }
359
360 /// Go down the tree reading every letter's code and returning
361 /// a [`HashMap<L, BitVec<Msb0, u8>, S>][HashMap]` where `S`
362 /// is the provided hash builder (implementing [`BuildHasher`][BuildHasher])
363 ///
364 /// # Example
365 /// ---
366 /// ```
367 /// use huff_coding::{
368 /// bitvec::prelude::*,
369 /// prelude::{HuffTree, ByteWeights},
370 /// };
371 /// use std::collections::{
372 /// HashMap,
373 /// hash_map::RandomState,
374 /// };
375 ///
376 /// let tree = HuffTree::from_weights(
377 /// ByteWeights::from_bytes(b"ghhiii")
378 /// );
379 /// let codes = tree.read_codes_with_hasher(RandomState::default());
380 ///
381 /// let mut cmp_codes = HashMap::new();
382 /// cmp_codes.insert(b'i', bitvec![Msb0, u8; 0]);
383 /// cmp_codes.insert(b'h', bitvec![Msb0, u8; 1, 1]);
384 /// cmp_codes.insert(b'g', bitvec![Msb0, u8; 1, 0]);
385 ///
386 /// assert_eq!(codes, cmp_codes);
387 /// ```
388 pub fn read_codes_with_hasher<S: BuildHasher>(&self, hash_builder: S) -> HashMap<L, BitVec<Msb0, u8>, S>{
389 /// Recursively insert letters to codes into the given HashMap<L, BitVec<Msb0, u8>>
390 fn set_codes<L: HuffLetter, S: BuildHasher>(codes: &mut HashMap<L, BitVec<Msb0, u8>, S>, root: &HuffBranch<L>, pos_in_parent: bool){
391 if let Some(children_iter) = root.children_iter(){
392 for (pos, child) in children_iter.enumerate(){
393 let branch = child;
394 let leaf = branch.leaf();
395 if let Some(letter) = leaf.letter(){
396 codes.insert(letter.clone(), leaf.code().unwrap().clone());
397 }
398 else{
399 set_codes(codes, child, pos != 0);
400 }
401 }
402 }
403 else{
404 codes.insert(root.leaf().letter().unwrap().clone(), bitvec![Msb0, u8; pos_in_parent as u8]);
405 }
406 }
407
408 let mut codes = HashMap::with_hasher(hash_builder);
409 let root = self.root();
410 if root.has_children(){
411 set_codes(&mut codes, root.left_child().unwrap(), false);
412 set_codes(&mut codes, root.right_child().unwrap(), true);
413 codes
414 }
415 else{
416 codes.insert(root.leaf().letter().unwrap().clone(), bitvec![Msb0, u8; 0]);
417 codes
418 }
419 }
420
421 /// Recursively set the codes in every encountered branch
422 fn set_codes_in_child_branches(parent: &mut HuffBranch<L>, parent_code: Option<BitVec<Msb0, u8>>){
423 if parent.has_children(){
424 let set_code = |child: &mut HuffBranch<L>, pos|{
425 // append pos_in_parent to parent_code and set the newly created code on child
426 let mut child_code = BitVec::with_capacity(1);
427 if let Some(parent_code) = parent_code{
428 child_code = parent_code;
429 }
430 child_code.push(pos != 0);
431 child.set_code(child_code.clone());
432
433 // recurse into the child's children
434 HuffTree::set_codes_in_child_branches(child, Some(child_code));
435 };
436
437 set_code.clone()(parent.left_child_mut().unwrap(), 0);
438 set_code(parent.right_child_mut().unwrap(), 1);
439 }
440 }
441}
442
443impl<L: HuffLetterAsBytes> HuffTree<L>{
444 /// Try to read the provided [`BitVec<Msb0, u8>`][bitvec::prelude::BitVec] and
445 /// construct a `HuffTree<L>` from it.
446 /// Every weight in the newly created tree is set to 0
447 /// as they're not stored in the binary representation
448 ///
449 /// In order to call this method, `L` must implement [`HuffLetterAsBytes`][letter_bytes]
450 ///
451 /// # Decoding scheme
452 /// ---
453 /// 1. Go bit by bit
454 /// 2. Create a [`HuffBranch`][branch] with no letter (a joint branch) when a 1 is found
455 /// 3. When a 0 is found, read next [`size_of::<L>() * 8`][mem::size_of] bits and create a
456 /// value of type `L` from them, inserting it then into a [`HuffBranch`][branch]
457 ///
458 /// # Example
459 /// ---
460 /// ```
461 /// use huff_coding::prelude::{HuffTree, ByteWeights};
462 ///
463 /// let tree = HuffTree::from_weights(
464 /// ByteWeights::from_bytes(b"mnnooo")
465 /// );
466 ///
467 /// let tree_bin = tree.as_bin();
468 ///
469 /// let new_tree = HuffTree::try_from_bin(tree_bin).unwrap();
470 /// // the newly created tree is identical, except in weights
471 /// assert_eq!(
472 /// tree.read_codes(),
473 /// new_tree.read_codes()
474 /// );
475 /// assert_ne!(
476 /// tree
477 /// .root()
478 /// .leaf()
479 /// .weight(),
480 /// new_tree
481 /// .root()
482 /// .leaf()
483 /// .weight()
484 /// );
485 /// // every weight in a HuffTree read from binary is set to 0
486 /// assert_eq!(
487 /// new_tree
488 /// .root()
489 /// .leaf()
490 /// .weight(),
491 /// 0
492 /// );
493 /// ```
494 ///
495 /// # Errors
496 /// ---
497 /// When trying to create a `HuffTree<L>`from binary where the original's
498 /// letter type is different than the one specified to be read:
499 /// ```should_panic
500 /// use huff_coding::prelude::{HuffTree, ByteWeights};
501 ///
502 /// let tree = HuffTree::from_weights(
503 /// ByteWeights::from_bytes(b"abbccc")
504 /// );
505 /// let tree_bin = tree.as_bin();
506 /// let new_tree = HuffTree::<u128>::try_from_bin(tree_bin)
507 /// .expect("this will return a FromBinError");
508 /// ```
509 /// or when providing a too small/big BitVec to create a HuffTree<L>:
510 /// ```should_panic
511 /// use huff_coding::{
512 /// bitvec::prelude::*,
513 /// prelude::{HuffTree, ByteWeights},
514 /// };
515 ///
516 /// let tree = HuffTree::<u128>::try_from_bin(bitvec![Msb0, u8; 0, 1])
517 /// .expect("this will return a FromBinError (provided BitVec is to small)");
518 /// ```
519 ///
520 /// [branch]:crate::tree::branch::HuffBranch
521 /// [letter_bytes]:crate::tree::letter::HuffLetterAsBytes
522 pub fn try_from_bin(bin: BitVec<Msb0, u8>) -> Result<Self, FromBinError<L>>{
523 /// Recursively reads branches and their children from the given bits
524 /// When finding a 1 -> recurses to get children,
525 /// and when a 0 -> ends recursion returning a letter branch
526 fn read_branches_from_bits<L: HuffLetterAsBytes>(bits: &mut bitvec::slice::IterMut<Msb0, u8>) ->
527 Result<HuffBranch<L>, FromBinError<L>>{
528 // check whether the bit can be popped at all, if not return Err
529 // remove first bit, if its 1 -> joint branch
530 if if let Some(bit) = bits.next(){*bit}
531 else{
532 return Err(FromBinError::new(
533 "Provided BitVec is too small for an encoded HuffTree"
534 ))
535 }{
536 // create joint branch, recurse to get its children
537 let branch = HuffBranch::new(
538 HuffLeaf::new(None, 0),
539 Some((
540 read_branches_from_bits(bits)?,
541 read_branches_from_bits(bits)?
542 ))
543 );
544 Ok(branch)
545 }
546 // if it's 0 -> letter branch
547 else{
548 // read the letter bits and convert them to bytes
549 let mut letter_bytes = Vec::<u8>::with_capacity(mem::size_of::<L>());
550 let mut byte = 0b0000_0000;
551 let mut bit_ptr = 7;
552
553 // get an iterator over the letter bits, if not enough bits left return err
554 let letter_bits = bits.take(size_of_bits::<L>());
555 if letter_bits.len() != size_of_bits::<L>(){
556 return Err(FromBinError::new(
557 "Provided BitVec is too small for an encoded HuffTree",
558 ))
559 };
560 for bit in letter_bits{
561 byte |= (*bit as u8) << bit_ptr;
562 if bit_ptr == 0{
563 letter_bytes.push(byte);
564 byte = 0b0000_0000;
565 bit_ptr = 7;
566 }
567 else{bit_ptr -= 1};
568 }
569
570 // create letter branch (no children)
571 let branch = HuffBranch::new(
572 // create letter from letter_bytes
573 HuffLeaf::new(Some(L::try_from_be_bytes(&letter_bytes).unwrap()), 0),
574 None,
575 );
576 Ok(branch)
577 }
578 }
579 // declare bin as mutable
580 let mut bin = bin;
581 // recurse to create root, and set codes for all branches
582 let mut bin_iter_mut = bin.iter_mut();
583 let mut root = read_branches_from_bits(&mut bin_iter_mut)?;
584
585 // return Err if not all bits used
586 if bin_iter_mut.next().is_some(){
587 return Err(FromBinError::new(
588 "Provided BitVec is too big for an encoded HuffTree",
589 ))
590 }
591
592 // set codes for all branches recursively if has children
593 // else just set the root's code to 0
594 if root.has_children(){
595 HuffTree::set_codes_in_child_branches(&mut root, None);
596 }
597 else{
598 root.set_code(bitvec![Msb0, u8; 0]);
599 }
600
601 Ok(HuffTree{
602 root
603 })
604 }
605
606 /// Return a binary representation of the `HuffTree<L>`
607 /// ([`BitVec<Msb0, u8>`][bitvec::prelude::BitVec])
608 ///
609 /// In order to call this method, `L` must implement [`HuffLetterAsBytes`][letter_bytes]
610 ///
611 /// # Encoding scheme
612 /// ---
613 /// 1. Recurse down the tree
614 /// 2. Every joint branch is encoded as a 1
615 /// 3. Every letter branch is encoded as a 0
616 /// and is followed by the letter itself encoded in binary
617 ///
618 /// # Example
619 /// ---
620 /// ```
621 /// use huff_coding::prelude::{HuffTree, ByteWeights};
622 ///
623 /// let tree = HuffTree::from_weights(
624 /// ByteWeights::from_bytes(b"abbccc")
625 /// );
626 ///
627 /// let tree_bin = tree.as_bin();
628 /// assert_eq!(tree_bin.to_string(), "[10011000, 11100110, 00010011, 00010]");
629 /// ```
630 ///
631 /// [letter_bytes]:crate::tree::letter::HuffLetterAsBytes
632 pub fn as_bin(&self) -> BitVec<Msb0, u8>{
633 /// Recursively push bits to the given BitVec<Msb0, u8>
634 /// depending on the branches you encounter:
635 /// * 0 being a letter branch (followed by a letter encoded in binary)
636 /// * 1 being a joint branch
637 fn set_tree_as_bin<L: HuffLetterAsBytes>(tree_bin: &mut BitVec<Msb0, u8>, root: &HuffBranch<L>){
638 let root = root;
639 let children_iter = root.children_iter();
640
641 // has children -> joint branch
642 if let Some(children_iter) = children_iter{
643 // 1 means joint branch
644 tree_bin.push(true);
645
646 // call set_bin on children
647 for child in children_iter{
648 set_tree_as_bin(tree_bin, child);
649 }
650 }
651 // no children -> letter branch
652 else{
653 // 0 means letter branch
654 tree_bin.push(false);
655
656 // convert the letter to bytes and push the bytes' bits into the tree_bin
657 for byte in root.leaf().letter().unwrap().as_be_bytes().iter(){
658 for bit_ptr in 0..8{
659 tree_bin.push((byte >> (7 - bit_ptr)) & 1 == 1)
660 }
661 }
662 }
663 }
664
665 let mut treebin = BitVec::new();
666 set_tree_as_bin(&mut treebin, self.root());
667 treebin
668 }
669}
670
671/// [Error][std::error::Error] encountered while trying to construct a [`HuffTree`][HuffTree] from bin
672/// with the [`HuffTree::try_from_bin`](struct.HuffTree.html#method.try_from_bin) method
673#[derive(Debug)]
674pub struct FromBinError<L: HuffLetterAsBytes>{
675 message: &'static str,
676 _typebind: std::marker::PhantomData<L>,
677}
678
679impl<L: HuffLetterAsBytes> fmt::Display for FromBinError<L>{
680 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681 write!(f, "{}<{}>", self.message, std::any::type_name::<L>())
682 }
683}
684
685impl<L: HuffLetterAsBytes> std::error::Error for FromBinError<L>{}
686
687impl<L: HuffLetterAsBytes> FromBinError<L>{
688 /// Initialize a new `FromBinError` with the given message
689 pub fn new(message: &'static str) -> Self{
690 Self{
691 message,
692 _typebind: std::marker::PhantomData,
693 }
694 }
695
696 /// Return the message
697 pub fn message(&self) -> &str{
698 self.message
699 }
700}