token_identifier/
lib.rs

1#[cfg(test)]
2mod tests;
3
4mod parser;
5
6use parser::{parse_token, parse_token_id};
7use std::fmt;
8use std::fmt::{Display, Formatter};
9use std::iter::repeat_with;
10use std::rc::Rc;
11use rand::thread_rng;
12use rand::Rng;
13
14/// radix for convert the digits 0-9,a-v
15const RADIX : u32 = 32;
16
17/// simple 32 bit token, that can be displayed as a 7 char string.
18#[derive(Copy)]
19#[derive(Debug)]
20pub struct Token {
21    value : u32
22}
23
24/// a token identifier, that is a combination of 1 to n 32 bit token
25#[derive(Debug)]
26pub struct TokenId {
27    tokens : Rc<Box<[Token]>>
28}
29
30impl Token {
31    /// generate a token with random value
32    pub fn new() -> Self {
33        Self::create(thread_rng().gen())
34    }
35
36    /// generate a token with a specific value
37    pub fn create(value : u32) -> Self {
38        Token {
39            value : value
40        }
41    }
42
43    /// parse a token string
44    pub fn decode(token : &str) -> Result<Self, &str> {
45        parse_token(token)
46    }
47
48    /// get token value
49    pub fn get_value(&self) -> u32 {
50        self.value
51    }
52
53    /// calculate die string representation with error correction
54    pub fn encode(&self) -> String {
55        let mask : u64 = 0b11111;
56        let block : u64 = self.block();
57
58        let iter = [30,25,20,15,10,5,0].into_iter()
59            .map(|bits| char::from_digit((block >> bits & mask).try_into().unwrap(),RADIX).unwrap());
60
61        String::from_iter(iter)
62    }
63
64    /// generate 35 bit block of value and check bits
65    fn block(&self) -> u64 {
66        (u64::from(self.checksum()) << 32)
67            + u64::from(self.value)
68    }
69
70    /// checksum for token is a 3 bit value
71    fn checksum(&self) -> u32 {
72        let mask : u32 = 0b111;
73
74        (0..11).into_iter()
75                .map(|i| self.value >> i*3 & mask)
76                .reduce(|c1,c2| c1 ^ c2)
77                .expect("build checksum")
78    }
79}
80
81impl TokenId {
82    /// generate a 64 bit token identifier with random value
83    pub fn new_64() -> Self {
84        Self::new(2)
85    }
86
87    /// generate a 128 bit token identifier with random value
88    pub fn new_128() -> Self {
89        Self::new(4)
90    }
91
92    /// generate a 256 bit token identifier with random value
93    pub fn new_256() -> Self {
94        Self::new(8)
95    }
96
97    /// generate a token identifier with random value of variable length
98    pub fn new(token_len : usize) -> Self {
99        let token : Vec<Token> = repeat_with(|| Token::new()).take(token_len).collect();
100
101        Self::create(token.into_boxed_slice())
102    }
103
104    /// generate a token identifier with spezific value
105    pub fn create(tokens : Box<[Token]>) -> Self {
106        TokenId {
107            tokens : Rc::new(tokens)
108        }
109    }
110
111    /// decode a string to a token identifier
112    pub fn decode(tokenid : &str) -> Result<Self,&str> {
113        parse_token_id(tokenid)
114    }
115
116    /// get list of simple tokens
117    pub fn get_tokens(&self) -> Vec<Token> {
118        self.tokens.into_iter()
119            .map(|b| *b)
120            .collect()
121    }
122
123    /// get numeric values of the token identifier
124    pub fn get_values(&self) -> Vec<u32> {
125        self.tokens.into_iter()
126            .map(|t| t.get_value())
127            .collect()
128    }
129
130    /// calculate die string representation of token identifier
131    fn encode(&self) -> String {
132        self.tokens.into_iter()
133            .map(|t| t.encode())
134            .reduce(|s1,s2| s1 + "-" + &s2)
135            .unwrap()
136    }
137}
138
139impl Clone for Token {
140    fn clone(&self) -> Token {
141        *self
142    }
143}
144
145impl Clone for TokenId {
146    fn clone(&self) -> Self {
147        Self {
148            tokens : self.tokens.clone()
149        }
150    }
151}
152
153impl Default for Token {
154    fn default() -> Self {
155        Self::create(0)
156    }
157}
158
159impl Into<u32> for Token {
160    fn into(self) -> u32 {
161        self.value
162    }
163}
164
165impl Into<String> for Token {
166    fn into(self) -> String {
167        self.encode()
168    }
169}
170
171impl Into<String> for TokenId {
172    fn into(self) -> String {
173        self.encode()
174    }
175}
176
177impl From<u32> for Token {
178    fn from(value : u32) -> Self {
179        Self::create(value)
180    }
181}
182
183/*
184impl From<String> for Token {
185    fn from(value : String) -> Self {
186        Self::decode(&value)
187    }
188}
189
190impl From<&str> for Token {
191    fn from(value : &str) -> Self {
192        Self::decode(value)
193    }
194}
195
196impl From<String> for TokenId {
197    fn from(value : String) -> Self {
198        Self::decode(&value)
199    }
200}
201
202impl From<&str> for TokenId {
203    fn from(value : &str) -> Self {
204        Self::decode(value)
205    }
206}
207*/
208
209impl Display for Token {
210    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
211        write!(f, "{}", self.encode())
212    }
213}
214
215impl Display for TokenId {
216    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
217        write!(f, "{}", self.encode())
218    }
219}