Improve Mnemonic::language_of

This commit is contained in:
Steven Roose 2021-03-08 10:50:04 +00:00
parent 7771fd8244
commit 125a287a05
No known key found for this signature in database
GPG Key ID: 2F2A88D7F8D68E87
1 changed files with 24 additions and 16 deletions

View File

@ -223,17 +223,9 @@ impl Mnemonic {
self.0.iter().take_while(|w| !w.is_empty()).map(|w| *w) self.0.iter().take_while(|w| !w.is_empty()).map(|w| *w)
} }
/// Determine the language of the mnemonic. /// Determine the language of the mnemonic as a word iterator.
/// /// See documentation on [Mnemonic::language_of] for more info.
/// NOTE: This method only guarantees that the returned language is the fn language_of_iter<'a, W: Iterator<Item = &'a str>>(words: W) -> Result<Language, Error> {
/// correct language on the assumption that the mnemonic is valid.
/// It does not itself validate the mnemonic.
///
/// Some word lists don't guarantee that their words don't occur in other
/// word lists. In the extremely unlikely case that a word list can be
/// interpreted in multiple languages, an [Error::AmbiguousLanguages] is
/// returned, containing the possible languages.
fn language_of<'a, W: Iterator<Item = &'a str>>(words: W) -> Result<Language, Error> {
let mut words = words.peekable(); let mut words = words.peekable();
let langs = Language::all(); let langs = Language::all();
{ // Start scope to drop first_word so that words can be reborrowed later. { // Start scope to drop first_word so that words can be reborrowed later.
@ -293,6 +285,20 @@ impl Mnemonic {
return Err(Error::AmbiguousLanguages(AmbiguousLanguages(possible))); return Err(Error::AmbiguousLanguages(AmbiguousLanguages(possible)));
} }
/// Determine the language of the mnemonic.
///
/// NOTE: This method only guarantees that the returned language is the
/// correct language on the assumption that the mnemonic is valid.
/// It does not itself validate the mnemonic.
///
/// Some word lists don't guarantee that their words don't occur in other
/// word lists. In the extremely unlikely case that a word list can be
/// interpreted in multiple languages, an [Error::AmbiguousLanguages] is
/// returned, containing the possible languages.
fn language_of<S: AsRef<str>>(mnemonic: S) -> Result<Language, Error> {
Mnemonic::language_of_iter(mnemonic.as_ref().split_whitespace())
}
/// Parse a mnemonic in normalized UTF8 in the given language. /// Parse a mnemonic in normalized UTF8 in the given language.
pub fn parse_in_normalized(language: Language, s: &str) -> Result<Mnemonic, Error> { pub fn parse_in_normalized(language: Language, s: &str) -> Result<Mnemonic, Error> {
let nb_words = s.split_whitespace().count(); let nb_words = s.split_whitespace().count();
@ -340,7 +346,7 @@ impl Mnemonic {
/// Parse a mnemonic in normalized UTF8. /// Parse a mnemonic in normalized UTF8.
pub fn parse_normalized(s: &str) -> Result<Mnemonic, Error> { pub fn parse_normalized(s: &str) -> Result<Mnemonic, Error> {
let lang = Mnemonic::language_of(s.split_whitespace())?; let lang = Mnemonic::language_of(s)?;
Mnemonic::parse_in_normalized(lang, s) Mnemonic::parse_in_normalized(lang, s)
} }
@ -361,7 +367,7 @@ impl Mnemonic {
let language = if Language::all().len() == 1 { let language = if Language::all().len() == 1 {
Language::all()[0] Language::all()[0]
} else { } else {
Mnemonic::language_of(cow.as_ref().split_whitespace())? Mnemonic::language_of(cow.as_ref())?
}; };
Ok(Mnemonic::parse_in_normalized(language, cow.as_ref())?) Ok(Mnemonic::parse_in_normalized(language, cow.as_ref())?)
@ -399,7 +405,7 @@ impl Mnemonic {
// We unwrap errors here because this method can only be called on // We unwrap errors here because this method can only be called on
// values that were already previously validated. // values that were already previously validated.
let language = Mnemonic::language_of(self.word_iter()).unwrap(); let language = Mnemonic::language_of_iter(self.word_iter()).unwrap();
// Preallocate enough space for the longest possible word list // Preallocate enough space for the longest possible word list
let mut entropy = Vec::with_capacity(33); let mut entropy = Vec::with_capacity(33);
@ -479,8 +485,10 @@ mod tests {
fn test_language_of() { fn test_language_of() {
for lang in Language::all() { for lang in Language::all() {
let m = Mnemonic::generate_in(*lang, 24).unwrap(); let m = Mnemonic::generate_in(*lang, 24).unwrap();
assert_eq!(*lang, Mnemonic::language_of(m.word_iter()).unwrap()); assert_eq!(*lang, Mnemonic::language_of_iter(m.word_iter()).unwrap());
assert_eq!(*lang, Mnemonic::language_of(m.to_string().split_whitespace()).unwrap()); assert_eq!(*lang, Mnemonic::language_of_iter(m.to_string().split_whitespace()).unwrap());
assert_eq!(*lang, Mnemonic::language_of(m.to_string()).unwrap());
assert_eq!(*lang, Mnemonic::language_of(&m.to_string()).unwrap());
} }
} }