use core::fmt::{self, Display};
use crate::{
engine::{Engine, UnwrappedKey, WrappedKey},
id::BaseId,
};
pub mod fs_keystore;
pub mod memstore;
pub trait KeyStore {
type Error: Error;
type Vacant<'a, T: WrappedKey>: Vacant<T, Error = Self::Error>;
type Occupied<'a, T: WrappedKey>: Occupied<T, Error = Self::Error>;
fn entry<T: WrappedKey>(&mut self, id: BaseId) -> Result<Entry<'_, Self, T>, Self::Error>;
fn get<T: WrappedKey>(&self, id: BaseId) -> Result<Option<T>, Self::Error>;
fn try_insert<T: WrappedKey>(&mut self, id: BaseId, key: T) -> Result<(), Self::Error> {
match self.entry(id)? {
Entry::Vacant(v) => v.insert(key),
Entry::Occupied(_) => Err(<Self as KeyStore>::Error::new(
ErrorKind::AlreadyExists,
DuplicateKey,
)),
}
}
fn remove<T: WrappedKey>(&mut self, id: BaseId) -> Result<Option<T>, Self::Error> {
match self.entry(id)? {
Entry::Vacant(_) => Ok(None),
Entry::Occupied(v) => Ok(Some(v.remove()?)),
}
}
}
pub enum Entry<'a, S, T>
where
S: KeyStore + ?Sized,
T: WrappedKey,
{
Vacant(S::Vacant<'a, T>),
Occupied(S::Occupied<'a, T>),
}
pub trait Vacant<T: WrappedKey> {
type Error: Error;
fn insert(self, key: T) -> Result<(), Self::Error>;
}
pub trait Occupied<T: WrappedKey> {
type Error: Error;
fn get(&self) -> Result<T, Self::Error>;
fn remove(self) -> Result<T, Self::Error>;
}
#[derive(Debug, thiserror::Error)]
#[error("key already exists")]
struct DuplicateKey;
pub trait Error: core::error::Error + Send + Sync + 'static + Sized {
fn new<E>(kind: ErrorKind, err: E) -> Self
where
E: core::error::Error + Send + Sync + 'static;
fn other<E>(err: E) -> Self
where
E: core::error::Error + Send + Sync + 'static,
{
Self::new(ErrorKind::Other, err)
}
fn kind(&self) -> ErrorKind;
}
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[non_exhaustive]
pub enum ErrorKind {
AlreadyExists,
Other,
}
impl Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::AlreadyExists => "key entry already exists",
Self::Other => "some keystore error occurred",
})
}
}
pub trait KeyStoreExt: KeyStore {
fn insert_key<E, K>(&mut self, eng: &E, key: K) -> Result<K::Id, Self::Error>
where
E: Engine,
K: UnwrappedKey<E::CS>;
fn get_key<E, K>(&self, eng: &E, id: K::Id) -> Result<Option<K>, Self::Error>
where
E: Engine,
K: UnwrappedKey<E::CS>;
fn remove_key<E, K>(&mut self, eng: &E, id: K::Id) -> Result<Option<K>, Self::Error>
where
E: Engine,
K: UnwrappedKey<E::CS>;
}
impl<T: KeyStore> KeyStoreExt for T {
fn insert_key<E, K>(&mut self, eng: &E, key: K) -> Result<K::Id, Self::Error>
where
E: Engine,
K: UnwrappedKey<E::CS>,
{
let unwrapped_id = key.id().map_err(<<Self as KeyStore>::Error>::other)?;
let wrapped_key = eng.wrap(key).map_err(<<Self as KeyStore>::Error>::other)?;
self.try_insert(*unwrapped_id.as_ref(), wrapped_key)?;
Ok(unwrapped_id)
}
fn get_key<E, K>(&self, eng: &E, id: K::Id) -> Result<Option<K>, Self::Error>
where
E: Engine,
K: UnwrappedKey<E::CS>,
{
if let Some(wrapped) = self.get(*id.as_ref())? {
let sk = eng
.unwrap(&wrapped)
.map_err(<<Self as KeyStore>::Error>::other)?;
Ok(Some(sk))
} else {
Ok(None)
}
}
fn remove_key<E, K>(&mut self, eng: &E, id: K::Id) -> Result<Option<K>, Self::Error>
where
E: Engine,
K: UnwrappedKey<E::CS>,
{
if let Some(wrapped) = self.remove(*id.as_ref())? {
let sk = eng
.unwrap(&wrapped)
.map_err(<<Self as KeyStore>::Error>::other)?;
Ok(Some(sk))
} else {
Ok(None)
}
}
}