use thiserror::Error;
pub const PUBLIC_KEY_FIELD: &str = "_public_key";
pub const KEY_SIZE: usize = 32;
pub type WalkAction<'a> = &'a (dyn Fn(&[u8]) -> Result<Vec<u8>, String> + 'a);
#[derive(Error, Debug)]
pub enum FormatError {
#[error("public key not present in file")]
PublicKeyMissing,
#[error("public key has invalid format")]
PublicKeyInvalid,
#[error("invalid {format} syntax: {message}")]
InvalidSyntax {
format: &'static str,
message: String,
},
#[error("action failed: {0}")]
ActionFailed(String),
}
pub trait FormatHandler: Send + Sync {
fn format_name(&self) -> &'static str;
fn extract_public_key(&self, data: &[u8]) -> Result<[u8; KEY_SIZE], FormatError>;
fn walk(&self, data: &[u8], action: WalkAction<'_>) -> Result<Vec<u8>, FormatError>;
fn trim_underscore_prefix_from_keys(&self, data: &[u8]) -> Result<Vec<u8>, FormatError>;
fn preprocess(&self, data: &[u8]) -> Result<Vec<u8>, FormatError> {
Ok(data.to_vec())
}
}
impl FormatHandler for Box<dyn FormatHandler> {
fn format_name(&self) -> &'static str {
(**self).format_name()
}
fn extract_public_key(&self, data: &[u8]) -> Result<[u8; KEY_SIZE], FormatError> {
(**self).extract_public_key(data)
}
fn walk(&self, data: &[u8], action: WalkAction<'_>) -> Result<Vec<u8>, FormatError> {
(**self).walk(data, action)
}
fn trim_underscore_prefix_from_keys(&self, data: &[u8]) -> Result<Vec<u8>, FormatError> {
(**self).trim_underscore_prefix_from_keys(data)
}
fn preprocess(&self, data: &[u8]) -> Result<Vec<u8>, FormatError> {
(**self).preprocess(data)
}
}
#[cfg(test)]
mod tests {
use super::*;
struct TestHandler;
impl FormatHandler for TestHandler {
fn format_name(&self) -> &'static str {
"TEST"
}
fn extract_public_key(&self, _data: &[u8]) -> Result<[u8; KEY_SIZE], FormatError> {
Err(FormatError::PublicKeyMissing)
}
fn walk(&self, data: &[u8], _action: WalkAction<'_>) -> Result<Vec<u8>, FormatError> {
Ok(data.to_vec())
}
fn trim_underscore_prefix_from_keys(&self, data: &[u8]) -> Result<Vec<u8>, FormatError> {
Ok(data.to_vec())
}
}
#[test]
fn test_format_handler_trait() {
let handler = TestHandler;
assert_eq!(handler.format_name(), "TEST");
assert!(matches!(
handler.extract_public_key(b"test"),
Err(FormatError::PublicKeyMissing)
));
}
#[test]
fn test_default_preprocess() {
let handler = TestHandler;
let data = b"unchanged data";
let result = handler.preprocess(data).unwrap();
assert_eq!(result, data);
}
}