dup_crypto/mnemonic/
language.rs1use super::error::MnemonicError;
17use super::utils::{Bits, Bits11};
18use std::{collections::HashMap, str::FromStr};
19
20pub struct WordMap {
21 inner: HashMap<&'static str, Bits11>,
22}
23
24pub struct WordList {
25 inner: Vec<&'static str>,
26}
27
28impl WordMap {
29 pub fn get_bits(&self, word: &str) -> Result<Bits11, MnemonicError> {
30 match self.inner.get(word) {
31 Some(n) => Ok(*n),
32 None => Err(MnemonicError::InvalidWord),
33 }
34 }
35}
36
37impl WordList {
38 pub fn get_word(&self, bits: Bits11) -> &'static str {
39 self.inner[bits.bits() as usize]
40 }
41}
42
43mod lazy {
44 use super::{Bits11, WordList, WordMap};
45 use once_cell::sync::Lazy;
46
47 fn gen_wordlist(lang_words: &'static str) -> WordList {
49 let inner: Vec<_> = lang_words.split_whitespace().collect();
50
51 debug_assert!(inner.len() == 2048, "Invalid wordlist length");
52
53 WordList { inner }
54 }
55
56 fn gen_wordmap(wordlist: &WordList) -> WordMap {
58 let inner = wordlist
59 .inner
60 .iter()
61 .enumerate()
62 .map(|(i, item)| (*item, Bits11::from(i as u16)))
63 .collect();
64
65 WordMap { inner }
66 }
67
68 pub static WORDLIST_ENGLISH: Lazy<WordList> =
69 Lazy::new(|| gen_wordlist(include_str!("langs/english.txt")));
70 #[cfg(feature = "mnemonic_chinese_simplified")]
71 pub static WORDLIST_CHINESE_SIMPLIFIED: Lazy<WordList> =
72 Lazy::new(|| gen_wordlist(include_str!("langs/chinese_simplified.txt")));
73 #[cfg(feature = "mnemonic_chinese_traditional")]
74 pub static WORDLIST_CHINESE_TRADITIONAL: Lazy<WordList> =
75 Lazy::new(|| gen_wordlist(include_str!("langs/chinese_traditional.txt")));
76 #[cfg(feature = "mnemonic_french")]
77 pub static WORDLIST_FRENCH: Lazy<WordList> =
78 Lazy::new(|| gen_wordlist(include_str!("langs/french.txt")));
79 #[cfg(feature = "mnemonic_italian")]
80 pub static WORDLIST_ITALIAN: Lazy<WordList> =
81 Lazy::new(|| gen_wordlist(include_str!("langs/italian.txt")));
82 #[cfg(feature = "mnemonic_japanese")]
83 pub static WORDLIST_JAPANESE: Lazy<WordList> =
84 Lazy::new(|| gen_wordlist(include_str!("langs/japanese.txt")));
85 #[cfg(feature = "mnemonic_korean")]
86 pub static WORDLIST_KOREAN: Lazy<WordList> =
87 Lazy::new(|| gen_wordlist(include_str!("langs/korean.txt")));
88 #[cfg(feature = "mnemonic_spanish")]
89 pub static WORDLIST_SPANISH: Lazy<WordList> =
90 Lazy::new(|| gen_wordlist(include_str!("langs/spanish.txt")));
91
92 pub static WORDMAP_ENGLISH: Lazy<WordMap> = Lazy::new(|| gen_wordmap(&WORDLIST_ENGLISH));
93 #[cfg(feature = "mnemonic_chinese_simplified")]
94 pub static WORDMAP_CHINESE_SIMPLIFIED: Lazy<WordMap> =
95 Lazy::new(|| gen_wordmap(&WORDLIST_CHINESE_SIMPLIFIED));
96 #[cfg(feature = "mnemonic_chinese_traditional")]
97 pub static WORDMAP_CHINESE_TRADITIONAL: Lazy<WordMap> =
98 Lazy::new(|| gen_wordmap(&WORDLIST_CHINESE_TRADITIONAL));
99 #[cfg(feature = "mnemonic_french")]
100 pub static WORDMAP_FRENCH: Lazy<WordMap> = Lazy::new(|| gen_wordmap(&WORDLIST_FRENCH));
101 #[cfg(feature = "mnemonic_italian")]
102 pub static WORDMAP_ITALIAN: Lazy<WordMap> = Lazy::new(|| gen_wordmap(&WORDLIST_ITALIAN));
103 #[cfg(feature = "mnemonic_japanese")]
104 pub static WORDMAP_JAPANESE: Lazy<WordMap> = Lazy::new(|| gen_wordmap(&WORDLIST_JAPANESE));
105 #[cfg(feature = "mnemonic_korean")]
106 pub static WORDMAP_KOREAN: Lazy<WordMap> = Lazy::new(|| gen_wordmap(&WORDLIST_KOREAN));
107 #[cfg(feature = "mnemonic_spanish")]
108 pub static WORDMAP_SPANISH: Lazy<WordMap> = Lazy::new(|| gen_wordmap(&WORDLIST_SPANISH));
109}
110
111#[derive(Clone, Copy, Debug, PartialEq)]
120pub enum Language {
121 English,
123 #[cfg(feature = "mnemonic_chinese_simplified")]
124 ChineseSimplified,
126 #[cfg(feature = "mnemonic_chinese_traditional")]
127 ChineseTraditional,
129 #[cfg(feature = "mnemonic_french")]
130 French,
132 #[cfg(feature = "mnemonic_italian")]
133 Italian,
135 #[cfg(feature = "mnemonic_japanese")]
136 Japanese,
138 #[cfg(feature = "mnemonic_korean")]
139 Korean,
141 #[cfg(feature = "mnemonic_spanish")]
142 Spanish,
144}
145
146impl Language {
147 pub fn wordlist(self) -> &'static WordList {
149 match self {
150 Language::English => &lazy::WORDLIST_ENGLISH,
151 #[cfg(feature = "mnemonic_chinese_simplified")]
152 Language::ChineseSimplified => &lazy::WORDLIST_CHINESE_SIMPLIFIED,
153 #[cfg(feature = "mnemonic_chinese_traditional")]
154 Language::ChineseTraditional => &lazy::WORDLIST_CHINESE_TRADITIONAL,
155 #[cfg(feature = "mnemonic_french")]
156 Language::French => &lazy::WORDLIST_FRENCH,
157 #[cfg(feature = "mnemonic_italian")]
158 Language::Italian => &lazy::WORDLIST_ITALIAN,
159 #[cfg(feature = "mnemonic_japanese")]
160 Language::Japanese => &lazy::WORDLIST_JAPANESE,
161 #[cfg(feature = "mnemonic_korean")]
162 Language::Korean => &lazy::WORDLIST_KOREAN,
163 #[cfg(feature = "mnemonic_spanish")]
164 Language::Spanish => &lazy::WORDLIST_SPANISH,
165 }
166 }
167
168 pub fn wordmap(self) -> &'static WordMap {
173 match self {
174 Language::English => &lazy::WORDMAP_ENGLISH,
175 #[cfg(feature = "mnemonic_chinese_simplified")]
176 Language::ChineseSimplified => &lazy::WORDMAP_CHINESE_SIMPLIFIED,
177 #[cfg(feature = "mnemonic_chinese_traditional")]
178 Language::ChineseTraditional => &lazy::WORDMAP_CHINESE_TRADITIONAL,
179 #[cfg(feature = "mnemonic_french")]
180 Language::French => &lazy::WORDMAP_FRENCH,
181 #[cfg(feature = "mnemonic_italian")]
182 Language::Italian => &lazy::WORDMAP_ITALIAN,
183 #[cfg(feature = "mnemonic_japanese")]
184 Language::Japanese => &lazy::WORDMAP_JAPANESE,
185 #[cfg(feature = "mnemonic_korean")]
186 Language::Korean => &lazy::WORDMAP_KOREAN,
187 #[cfg(feature = "mnemonic_spanish")]
188 Language::Spanish => &lazy::WORDMAP_SPANISH,
189 }
190 }
191
192 #[allow(dead_code)]
193 pub(crate) fn from_u8(source: u8) -> Result<Self, MnemonicError> {
194 match source {
195 0 => Ok(Self::English),
196 #[cfg(feature = "mnemonic_chinese_simplified")]
197 1 => Ok(Self::ChineseSimplified),
198 #[cfg(feature = "mnemonic_chinese_traditional")]
199 2 => Ok(Self::ChineseTraditional),
200 #[cfg(feature = "mnemonic_french")]
201 3 => Ok(Self::French),
202 #[cfg(feature = "mnemonic_italian")]
203 4 => Ok(Self::Italian),
204 #[cfg(feature = "mnemonic_japanese")]
205 5 => Ok(Self::Japanese),
206 #[cfg(feature = "mnemonic_korean")]
207 6 => Ok(Self::Korean),
208 #[cfg(feature = "mnemonic_spanish")]
209 7 => Ok(Self::Spanish),
210 _ => Err(MnemonicError::UnknownLanguage),
211 }
212 }
213
214 #[allow(dead_code)]
215 pub(crate) fn to_u8(self) -> u8 {
216 match self {
217 Language::English => 0,
218 #[cfg(feature = "mnemonic_chinese_simplified")]
219 Language::ChineseSimplified => 1,
220 #[cfg(feature = "mnemonic_chinese_traditional")]
221 Language::ChineseTraditional => 2,
222 #[cfg(feature = "mnemonic_french")]
223 Language::French => 3,
224 #[cfg(feature = "mnemonic_italian")]
225 Language::Italian => 4,
226 #[cfg(feature = "mnemonic_japanese")]
227 Language::Japanese => 5,
228 #[cfg(feature = "mnemonic_korean")]
229 Language::Korean => 6,
230 #[cfg(feature = "mnemonic_spanish")]
231 Language::Spanish => 7,
232 }
233 }
234}
235
236impl Default for Language {
237 fn default() -> Language {
238 Language::English
239 }
240}
241
242impl FromStr for Language {
243 type Err = MnemonicError;
244
245 fn from_str(source: &str) -> Result<Self, Self::Err> {
246 match source {
247 "en" => Ok(Self::English),
248 #[cfg(feature = "mnemonic_chinese_simplified")]
249 "zh_HANS" => Ok(Self::ChineseSimplified),
250 #[cfg(feature = "mnemonic_chinese_traditional")]
251 "zh_HANT" => Ok(Self::ChineseTraditional),
252 #[cfg(feature = "mnemonic_french")]
253 "fr" => Ok(Self::French),
254 #[cfg(feature = "mnemonic_italian")]
255 "it" => Ok(Self::Italian),
256 #[cfg(feature = "mnemonic_japanese")]
257 "ja" => Ok(Self::Japanese),
258 #[cfg(feature = "mnemonic_korean")]
259 "ko" => Ok(Self::Korean),
260 #[cfg(feature = "mnemonic_spanish")]
261 "es" => Ok(Self::Spanish),
262 _ => unreachable!(),
263 }
264 }
265}