1use crate::constants::*;
2
3pub fn decode(mut code: &str) -> Option<i64> {
4 let mut value: i64 = 0;
5 let negative_factor = if code.starts_with(NEGATIVE_SYLLABLE) {
6 code = &code[NEGATIVE_SYLLABLE.len()..];
7 -1
8 } else {
9 1
10 };
11
12 while code.len() > 0 {
13 match SYLLABLES
14 .iter()
15 .position(|&syllable| code.starts_with(syllable))
16 {
17 Some(index) => {
18 value *= SYLLABLES.len() as i64;
19 value += index as i64;
20 code = &code[SYLLABLES[index].len()..];
21 }
22 None => return None,
23 };
24 }
25 Some(value * negative_factor)
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31 use rand::Rng;
32
33 #[test]
34 fn single_syllable() {
35 let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
36 let value = units as i64;
37
38 assert_eq!(decode(SYLLABLES[units]).unwrap(), value);
39 }
40
41 #[test]
42 fn unknown_syllable() {
43 assert_eq!(decode("aa"), None);
44 }
45
46 #[test]
47 fn many_tens() {
48 let tens = rand::thread_rng().gen_range(1, SYLLABLES.len());
49 let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
50 let value = (tens * SYLLABLES.len() + units) as i64;
51
52 assert_eq!(
53 decode(&[SYLLABLES[tens], SYLLABLES[units]].concat()).unwrap(),
54 value
55 );
56 }
57
58 #[test]
59 fn many_hundreds() {
60 let hundreds = rand::thread_rng().gen_range(1, SYLLABLES.len());
61 let tens = rand::thread_rng().gen_range(0, SYLLABLES.len());
62 let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
63 let value =
64 (hundreds * SYLLABLES.len() * SYLLABLES.len() + tens * SYLLABLES.len() + units) as i64;
65
66 assert_eq!(
67 decode(&[SYLLABLES[hundreds], SYLLABLES[tens], SYLLABLES[units]].concat()).unwrap(),
68 value
69 );
70 }
71
72 #[test]
73 fn negative() {
74 let units = rand::thread_rng().gen_range(0, SYLLABLES.len());
75 let value = (units as i64) * -1;
76
77 assert_eq!(
78 decode(&[NEGATIVE_SYLLABLE, SYLLABLES[units]].concat()).unwrap(),
79 value
80 );
81 }
82}