1fn words() -> Vec<&'static str> {
8 #[cfg(feature = "en")]
9 let list = include_str!("../words/en.txt");
10
11 let words : Vec<&'static str> = list.lines().collect();
12 assert_eq!(words.len(), 256);
13 for word in &words {
15 assert!(word.len() < 7);
16 }
17 words
18}
19
20pub fn encode_bytes(bytes: &[u8]) -> Vec<&'static str> {
23 let words = words();
24 let mut result = Vec::new();
25 for b in bytes {
26 result.push(words[*b as usize]);
27 }
28 result
29}
30
31pub fn encode_u32(num: u32) -> Vec<&'static str> {
35 let mut bytes = vec![
36 ((num >> 24) & 0xFF) as u8,
37 ((num >> 16) & 0xFF) as u8,
38 ((num >> 8) & 0xFF) as u8,
39 (num & 0xFF) as u8,
40 ];
41 while bytes.len() > 1 {
43 if bytes[0] == 0 {
44 bytes.remove(0);
45 } else {
46 break;
47 }
48 }
49 encode_bytes(&bytes)
50}
51
52pub fn encode_u32_joined(num: u32) -> String {
55 encode_u32(num).join(" ")
56}
57
58pub fn decode_bytes(encoded_words: &[&str]) -> Result<Vec<u8>, usize> {
66 let mut result = Vec::new();
67 let words = words();
68 for (i, encoded) in encoded_words.iter().enumerate() {
69 let ix = words.binary_search(&encoded.to_lowercase().as_str()).map_err(|_| i)?;
70 result.push(ix as u8);
71 }
72 Ok(result)
73}
74
75pub fn decode_u32(encoded_words: &[&str]) -> Result<u32, usize> {
80 let bytes = decode_bytes(encoded_words)?;
81 if bytes.len() > 4 {
82 return Err(4);
83 }
84 let mut result : u32 = 0;
85 for b in bytes {
86 result = (result << 8) | (b as u32 & 0xFF);
87 }
88 Ok(result)
89}
90
91pub fn decode_u32_joined(joined: &str) -> Result<u32, usize> {
95 decode_u32(&joined.split_whitespace().collect::<Vec<&str>>())
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_encode() {
104 assert_eq!(encode_bytes(&[]), Vec::<&str>::new());
105 assert_eq!(encode_u32(0xDEADBEEF).join(" "), "table potato school true".to_string());
106 assert_eq!(encode_u32(1234).join(" "), "ant stamp".to_string());
107 assert_eq!(encode_u32(5).join(" "), "apple".to_string());
108 assert_eq!(encode_u32(0).join(" "), "able".to_string());
109 }
110
111 #[test]
112 fn test_decode() {
113 assert_eq!(decode_bytes(&[]).unwrap(), vec![]);
114 assert_eq!(decode_bytes(&["taBLE", "potato", "school", "TRUE"]).unwrap(), vec![0xDE, 0xAD, 0xBE, 0xEF]);
115 assert_eq!(decode_u32(&["ant", "stamp"]).unwrap(), 1234);
116 assert_eq!(decode_u32_joined("table potato school true").unwrap(), 0xDEADBEEF);
117 }
118
119 #[test]
120 fn test_decode_failure() {
121 assert_eq!(decode_bytes(&["nonsense"]), Err(0));
122 assert_eq!(decode_u32(&["table", "potato", "school", "true", "true"]), Err(4));
123 }
124}