use alloc::vec::Vec;
pub const WIRE_PASS_V1_TAG: u8 = 1;
pub const LYS_PASS_V1_TAG: u8 = 2;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum WireCredential<'a> {
PassV1(&'a [u8]),
LysPass(&'a [u8]),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum CredentialKindError {
Empty,
UnknownTag(u8),
EmptyLysPass,
}
impl core::fmt::Display for CredentialKindError {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Empty => formatter.write_str("credential is empty"),
Self::UnknownTag(tag) => write!(formatter, "credential tag {tag} is unknown"),
Self::EmptyLysPass => formatter.write_str("lys pass record carries no pass"),
}
}
}
impl core::error::Error for CredentialKindError {}
impl<'a> WireCredential<'a> {
pub const fn classify(bytes: &'a [u8]) -> Result<Self, CredentialKindError> {
match bytes {
[] => Err(CredentialKindError::Empty),
[WIRE_PASS_V1_TAG, ..] => Ok(Self::PassV1(bytes)),
[LYS_PASS_V1_TAG] => Err(CredentialKindError::EmptyLysPass),
[LYS_PASS_V1_TAG, pass @ ..] => Ok(Self::LysPass(pass)),
[tag, ..] => Err(CredentialKindError::UnknownTag(*tag)),
}
}
#[must_use]
pub fn lys_record(pass: &[u8]) -> Vec<u8> {
let mut record = Vec::with_capacity(pass.len() + 1);
record.push(LYS_PASS_V1_TAG);
record.extend_from_slice(pass);
record
}
}
#[cfg(test)]
mod tests {
use super::{CredentialKindError, LYS_PASS_V1_TAG, WIRE_PASS_V1_TAG, WireCredential};
#[test]
fn a_v1_record_keeps_its_tag_for_the_pass_checker() {
let bytes = [WIRE_PASS_V1_TAG, 7, 8];
assert_eq!(
WireCredential::classify(&bytes),
Ok(WireCredential::PassV1(&bytes))
);
}
#[test]
fn a_lys_record_hands_over_the_pass_without_its_tag() {
let record = WireCredential::lys_record(b"issued-by-lys");
assert_eq!(record[0], LYS_PASS_V1_TAG);
assert_eq!(
WireCredential::classify(&record),
Ok(WireCredential::LysPass(b"issued-by-lys"))
);
}
#[test]
fn bytes_outside_both_records_are_refused_by_name() {
assert_eq!(
WireCredential::classify(&[]),
Err(CredentialKindError::Empty)
);
assert_eq!(
WireCredential::classify(&[LYS_PASS_V1_TAG]),
Err(CredentialKindError::EmptyLysPass)
);
assert_eq!(
WireCredential::classify(&[9, 1]),
Err(CredentialKindError::UnknownTag(9))
);
}
}