1use std::collections::HashMap;
2use crate::util::unique;
3use crate::BaseCustom;
4use std::ops::Range;
5use std::fmt;
6
7impl BaseCustom<char> {
8
9 pub fn new(chars: Vec<char>) -> BaseCustom<char> {
15 if chars.iter().count() < 2 { panic!("Too few numeric units! Provide two or more.") }
16 if chars.iter().count() > 255 { panic!("Too many numeric units!") }
17
18 let chars = unique(chars);
19
20 let mut mapped = HashMap::with_capacity(chars.iter().count());
21 for (i,c) in chars.iter().enumerate() {
22 mapped.insert(c.clone(), i as u8);
23 }
24 BaseCustom::<char> {
25 primitives: chars.clone(),
26 primitives_hash: mapped,
27 base: chars.iter().count() as u64,
28 delim: None,
29 }
30 }
31
32 pub fn gen(&self, input_val: u64) -> String {
49 if input_val == 0 {
50 return format!("{}", self.primitives[0]);
51 }
52 let mut number = input_val;
53 let mut result = String::new();
54 loop {
55 if number == 0 { break };
56 result.insert(0, self.primitives[(number % self.base) as usize]);
57 number = number/self.base;
58 };
59 format!("{}", result)
60 }
61
62 pub fn char(&self, input_val: usize) -> Option<char> {
78 if input_val > self.primitives.len() { return None }
79 Some(self.primitives[input_val])
80 }
81
82
83 pub fn decimal<S>(&self, input_val: S) -> u64
99 where S: Into<String> {
100 let input_val = input_val.into();
101
102 input_val.chars().rev().enumerate().fold(0, |sum, (i, chr)|
103 sum + (self.primitives_hash[&chr] as u64) * self.base.pow(i as u32)
104 )
105 }
106
107 pub fn zero(&self) -> &char {
109 &self.primitives[0]
110 }
111
112 pub fn one(&self) -> &char {
114 &self.primitives[1]
115 }
116
117 pub fn nth(&self, pos: usize) -> Option<&char> {
122 if pos < self.base as usize {
123 Some(&self.primitives[pos])
124 } else {
125 None
126 }
127 }
128
129 pub fn from_ordinal_range(range: Range<u32>) -> BaseCustom<char> {
135 let min = std::cmp::max(32, range.start);
136 let max = std::cmp::min(127, range.end);
137 let mut chars: Vec<char> = Vec::with_capacity(std::cmp::min(range.len(), 95));
138 for chr in min..max {
139 chars.push(std::char::from_u32(chr).unwrap());
140 }
141 BaseCustom::<char>::new(chars)
142 }
143}
144
145impl PartialEq for BaseCustom<char> {
146 fn eq(&self, other: &BaseCustom<char>) -> bool {
147 self.primitives == other.primitives &&
148 self.base == other.base &&
149 self.delim == other.delim
150 }
151}
152
153impl fmt::Debug for BaseCustom<char> {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
155 write!(f,
156 "BaseCustom\n\tprimitives: {:?}\n\tprimitives_hash: {:?}\n\tbase: {}\n\tdelim: {:?}",
157 self.primitives, self.primitives_hash, self.base, self.delim
158 )
159 }
160}