base_custom/
u8.rs

1use std::collections::HashMap;
2use crate::util::unique;
3use crate::BaseCustom;
4use std::fmt;
5
6impl BaseCustom<u8> {
7
8  /// 'new' creates a new BaseCustom instance and propogates the values for converting
9  /// numeric bases.
10  ///
11  /// `new` for `BaseCustom<u8>` requires a `&[u8]` as its parameters and units
12  /// for measuring the custom numeric base will only be one u8 long each.
13  pub fn new(bytes: &[u8]) -> BaseCustom<u8> {
14    if bytes.iter().count() < 2 { panic!("Too few numeric units! Provide two or more.") }
15    let bytes = unique(bytes.to_vec());
16
17    let mut mapped = HashMap::with_capacity(bytes.iter().count());
18    for (i,b) in bytes.iter().enumerate() {
19      mapped.insert(*b, i as u8);
20    }
21
22    let count = bytes.iter().count() as u64;
23
24    BaseCustom::<u8> {
25      primitives: bytes,
26      primitives_hash: mapped,
27      base: count,
28      delim: None,
29    }
30  }
31
32  /// `gen` returns a byte sequence computed from positional values
33  /// the given u64 parameter evalutes to for your custom base
34  ///
35  /// # Example
36  /// ```
37  /// use base_custom::BaseCustom;
38  ///
39  /// let base2 = BaseCustom::<u8>::new(&[0x00, 0x01]);
40  /// assert_eq!(base2.gen(3), vec![0x01, 0x01]);
41  /// ```
42  ///
43  /// # Output
44  /// ```text
45  /// vec![0x01, 0x01]
46  /// ```
47  pub fn gen(&self, input_val: u64) -> Vec<u8> {
48    if input_val == 0 {
49      return vec![self.primitives[0]];
50    }
51    let mut number = input_val;
52    let mut result = Vec::new();
53    loop {
54      if number == 0 { break };
55      result.insert(0, self.primitives[(number % self.base) as usize]);
56      number = number/self.base;
57    };
58    result
59  }
60
61  /// `decimal` returns a u64 value on computed from the units that form
62  /// the custom base.
63  ///
64  /// # Example
65  /// ```
66  /// use base_custom::BaseCustom;
67  ///
68  /// let base2 = BaseCustom::<u8>::new(b"01");
69  /// assert_eq!(base2.decimal(b"00011"), 3);
70  /// ```
71  ///
72  /// # Output
73  /// ```text
74  /// 3
75  /// ```
76  pub fn decimal(&self, input_val: &[u8]) -> u64 {
77    input_val.iter().rev().enumerate().fold(0, |sum, (i, byt)|
78      sum + (self.primitives_hash[&byt] as u64) * self.base.pow(i as u32)
79    )
80  }
81
82  /// Returns the zero value of your custom base
83  pub fn zero(&self) -> u8 {
84    self.primitives[0]
85  }
86
87  /// Returns the one value of your custom base
88  pub fn one(&self) -> u8 {
89    self.primitives[1]
90  }
91
92  /// Returns the nth value of your custom base
93  /// 
94  /// Like most indexing operations, the count starts from zero, so nth(0) returns the first value,
95  /// nth(1) the second, and so on.
96  pub fn nth(&self, pos: usize) -> Option<u8> {
97    if pos < self.base as usize {
98      Some(self.primitives[pos])
99    } else {
100      None
101    }
102  }
103}
104
105impl PartialEq for BaseCustom<u8> {
106  fn eq(&self, other: &BaseCustom<u8>) -> bool {
107    self.primitives == other.primitives &&
108      self.base == other.base &&
109      self.delim == other.delim
110  }
111}
112
113impl fmt::Debug for BaseCustom<u8> {
114  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115    write!(f,
116      "BaseCustom\n\tprimitives: {:?}\n\tprimitives_hash: {:?}\n\tbase: {}\n\tdelim: {:?}",
117      self.primitives, self.primitives_hash, self.base, self.delim
118    )
119  }
120}