use crate::consts::VALID_ENTR_LENGTHS;
use crate::error::{Error, Result};
use crate::tag::Tag;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum PayloadKind {
Entr,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Payload {
Entr(Vec<u8>),
}
impl Payload {
pub fn validate(&self) -> Result<()> {
match self {
Payload::Entr(data) => {
if !VALID_ENTR_LENGTHS.contains(&data.len()) {
return Err(Error::PayloadLengthMismatch {
tag: *Tag::ENTR.as_bytes(),
expected: VALID_ENTR_LENGTHS,
got: data.len(),
});
}
Ok(())
}
}
}
pub fn kind(&self) -> PayloadKind {
match self {
Payload::Entr(_) => PayloadKind::Entr,
}
}
pub fn as_bytes(&self) -> &[u8] {
match self {
Payload::Entr(data) => data,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn entr_accepts_all_bip39_lengths() {
for len in [16usize, 20, 24, 28, 32] {
let p = Payload::Entr(vec![0u8; len]);
p.validate()
.unwrap_or_else(|e| panic!("expected ok for len {}, got {:?}", len, e));
}
}
#[test]
fn entr_rejects_off_by_one_lengths() {
for len in [15usize, 17, 19, 21, 23, 25, 31, 33] {
let p = Payload::Entr(vec![0u8; len]);
assert!(
matches!(p.validate(), Err(Error::PayloadLengthMismatch { .. })),
"expected reject for len {}",
len
);
}
}
#[test]
fn entr_rejects_zero_length() {
let p = Payload::Entr(vec![]);
assert!(matches!(
p.validate(),
Err(Error::PayloadLengthMismatch { .. })
));
}
#[test]
fn kind_returns_entr() {
assert_eq!(Payload::Entr(vec![0u8; 16]).kind(), PayloadKind::Entr);
}
}