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}