use std::io::Write;
use ms_codec::Payload;
use zeroize::Zeroizing;
use crate::language::CliLanguage;
pub(crate) fn payload_entropy_and_language(
payload: Payload,
cli_lang: CliLanguage,
cli_lang_defaulted: bool,
stderr: &mut impl Write,
) -> (Zeroizing<Vec<u8>>, CliLanguage, bool) {
match payload {
Payload::Entr(b) => (Zeroizing::new(b), cli_lang, cli_lang_defaulted),
Payload::Mnem {
language: wire_code,
entropy,
} => {
let wire_cli = CliLanguage::from_code(wire_code).unwrap_or(CliLanguage::English);
if !cli_lang_defaulted && wire_cli != cli_lang {
let _ = writeln!(
stderr,
"note: this ms1 carries wordlist language '{}'; ignoring --language {}",
wire_cli.as_str(),
cli_lang.as_str()
);
}
(Zeroizing::new(entropy), wire_cli, false)
}
_ => unreachable!("ms-codec decode returned unknown Payload variant"),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn entr_pass_through_defaulted() {
let mut buf: Vec<u8> = Vec::new();
let (entropy, lang, defaulted) = payload_entropy_and_language(
Payload::Entr(vec![0u8; 16]),
CliLanguage::English,
true,
&mut buf,
);
assert_eq!(&entropy[..], &[0u8; 16]);
assert_eq!(lang, CliLanguage::English);
assert!(defaulted);
assert!(buf.is_empty(), "no note for Entr");
}
#[test]
fn entr_pass_through_explicit_french() {
let mut buf: Vec<u8> = Vec::new();
let (entropy, lang, defaulted) = payload_entropy_and_language(
Payload::Entr(vec![0u8; 16]),
CliLanguage::French,
false,
&mut buf,
);
assert_eq!(&entropy[..], &[0u8; 16]);
assert_eq!(lang, CliLanguage::French);
assert!(!defaulted);
assert!(buf.is_empty(), "no note for Entr");
}
#[test]
fn mnem_wire_wins_no_flag() {
let mut buf: Vec<u8> = Vec::new();
let (entropy, lang, defaulted) = payload_entropy_and_language(
Payload::Mnem {
language: 6, entropy: vec![0u8; 16],
},
CliLanguage::English,
true, &mut buf,
);
assert_eq!(&entropy[..], &[0u8; 16]);
assert_eq!(lang, CliLanguage::French);
assert!(!defaulted, "a real wire language is never 'defaulted'");
assert!(buf.is_empty(), "no disagreement note when flag omitted");
}
#[test]
fn mnem_disagreement_note() {
let mut buf: Vec<u8> = Vec::new();
let (_entropy, lang, defaulted) = payload_entropy_and_language(
Payload::Mnem {
language: 6, entropy: vec![0u8; 16],
},
CliLanguage::English,
false, &mut buf,
);
assert_eq!(lang, CliLanguage::French);
assert!(!defaulted);
let s = String::from_utf8(buf).unwrap();
assert_eq!(
s,
"note: this ms1 carries wordlist language 'french'; ignoring --language english\n"
);
}
#[test]
fn mnem_agreement_no_note() {
let mut buf: Vec<u8> = Vec::new();
let (_entropy, lang, defaulted) = payload_entropy_and_language(
Payload::Mnem {
language: 6, entropy: vec![0u8; 16],
},
CliLanguage::French,
false, &mut buf,
);
assert_eq!(lang, CliLanguage::French);
assert!(!defaulted);
assert!(buf.is_empty(), "wire == cli → no note");
}
}