use std::collections::HashMap;
use super::{E2ECheckStatus, E2EKey, E2EProfile, E2EState, Error, e2e_check, e2e_protect};
#[derive(Debug)]
pub struct E2ERegistry {
map: HashMap<E2EKey, (E2EProfile, E2EState)>,
}
impl E2ERegistry {
#[must_use]
pub fn new() -> Self {
Self {
map: HashMap::new(),
}
}
pub fn register(&mut self, key: E2EKey, profile: E2EProfile) {
let state = E2EState::from_profile(&profile);
self.map.insert(key, (profile, state));
}
pub fn unregister(&mut self, key: &E2EKey) {
self.map.remove(key);
}
#[must_use]
pub fn contains_key(&self, key: &E2EKey) -> bool {
self.map.contains_key(key)
}
pub fn check<'a>(
&mut self,
key: E2EKey,
payload: &'a [u8],
upper_header: [u8; 8],
) -> Option<(E2ECheckStatus, &'a [u8])> {
let (profile, state) = self.map.get_mut(&key)?;
Some(e2e_check(profile, state, payload, upper_header))
}
pub fn protect(
&mut self,
key: E2EKey,
payload: &[u8],
upper_header: [u8; 8],
output: &mut [u8],
) -> Option<Result<usize, Error>> {
let (profile, state) = self.map.get_mut(&key)?;
Some(e2e_protect(profile, state, payload, upper_header, output))
}
}
impl Default for E2ERegistry {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::e2e::{Profile4Config, Profile5Config};
fn make_key() -> E2EKey {
E2EKey::new(0x1234, 0x5678)
}
#[test]
fn register_and_check_profile4() {
let mut reg = E2ERegistry::new();
let key = make_key();
let config = Profile4Config::new(0x12345678, 15);
reg.register(key, E2EProfile::Profile4(config.clone()));
assert!(reg.contains_key(&key));
let payload = b"Hello";
let mut out = [0u8; 64];
let len = reg
.protect(key, payload, [0; 8], &mut out)
.unwrap()
.unwrap();
let (status, stripped) = reg.check(key, &out[..len], [0; 8]).unwrap();
assert_eq!(status, E2ECheckStatus::Ok);
assert_eq!(stripped, payload);
}
#[test]
fn register_and_check_profile5() {
let mut reg = E2ERegistry::new();
let key = make_key();
let config = Profile5Config::new(0x1234, 20, 15);
reg.register(key, E2EProfile::Profile5(config));
let mut payload = [0u8; 20];
payload[..5].copy_from_slice(b"Hello");
let mut out = [0u8; 64];
let len = reg
.protect(key, &payload, [0; 8], &mut out)
.unwrap()
.unwrap();
let (status, stripped) = reg.check(key, &out[..len], [0; 8]).unwrap();
assert_eq!(status, E2ECheckStatus::Ok);
assert_eq!(stripped, &payload);
}
#[test]
fn unregistered_key_returns_none() {
let mut reg = E2ERegistry::new();
let key = make_key();
assert!(!reg.contains_key(&key));
assert!(reg.check(key, b"test", [0; 8]).is_none());
assert!(reg.protect(key, b"test", [0; 8], &mut [0; 64]).is_none());
}
#[test]
fn unregister_removes_key() {
let mut reg = E2ERegistry::new();
let key = make_key();
reg.register(key, E2EProfile::Profile4(Profile4Config::new(0, 15)));
assert!(reg.contains_key(&key));
reg.unregister(&key);
assert!(!reg.contains_key(&key));
}
#[test]
fn default_is_empty() {
let reg = E2ERegistry::default();
assert!(!reg.contains_key(&make_key()));
}
}