use std::{any::Any, borrow::Cow, future::IntoFuture};
use vitaminc_protected::{Controlled, Protected};
use crate::BlockVisitor;
use crate::{IntoPrfContext, PrfContext, PrfEncoding, PrfError, PrfVisitor};
pub trait PrfValue {
fn prf<P>(self, prf: &P) -> P::Ok<P::Block>
where
Self: Sized,
P: Prf,
{
self.prf_visit(prf, BlockVisitor)
}
fn prf_visit<P, V>(self, prf: &P, visitor: V) -> P::Ok<V::Value>
where
Self: Sized,
P: Prf,
V: PrfVisitor<P::Block, P::Passthrough>,
{
self.prf_visit_with_context(prf, PrfContext::empty(), visitor)
}
fn prf_with_context<'a, P, C>(self, prf: &P, context: C) -> P::Ok<P::Block>
where
Self: Sized,
P: Prf,
C: IntoPrfContext<'a>,
{
self.prf_visit_with_context(prf, context, BlockVisitor)
}
fn prf_visit_with_context<'a, P, V, C>(
self,
prf: &P,
context: C,
visitor: V,
) -> P::Ok<V::Value>
where
P: Prf,
V: PrfVisitor<P::Block, P::Passthrough>,
C: IntoPrfContext<'a>;
}
pub trait PrfKeyInit: Prf {
type Key: Controlled;
type KeyError: std::error::Error + Send + Sync + 'static;
fn new(key: Self::Key) -> Self;
fn try_from_bytes(key: Protected<Vec<u8>>) -> Result<Self, Self::KeyError>;
}
pub trait Prf: Sized {
type Block: Send + 'static;
type BackendError: std::error::Error + Send + Sync + 'static;
type Passthrough: Send + 'static;
type SeqPrf<'a>: SeqPrf<
Prf = Self,
Block = Self::Block,
BackendError = Self::BackendError,
Passthrough = Self::Passthrough,
>
where
Self: 'a;
type MapPrf<'a>: MapPrf<
Prf = Self,
Block = Self::Block,
BackendError = Self::BackendError,
Passthrough = Self::Passthrough,
>
where
Self: 'a;
type Ok<T>: IntoFuture<Output = Result<T, PrfError<Self::BackendError>>>
where
T: Send + 'static;
fn prf_bytes_vec<V>(
&self,
data: Protected<Vec<u8>>,
encoding: PrfEncoding,
context: PrfContext<'static>,
visitor: V,
) -> Self::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>;
fn prf_bytes_array<const N: usize, V>(
&self,
data: Protected<[u8; N]>,
encoding: PrfEncoding,
context: PrfContext<'static>,
visitor: V,
) -> Self::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>,
{
self.prf_bytes_vec(
Protected::new(data.risky_ref().to_vec()),
encoding,
context,
visitor,
)
}
fn prf_seq(&self, size_hint: Option<usize>) -> Self::SeqPrf<'_>;
fn prf_map(&self, size_hint: Option<usize>) -> Self::MapPrf<'_>;
fn prf_some<T, V>(
&self,
value: T,
context: PrfContext<'static>,
visitor: V,
) -> Self::Ok<V::Value>
where
T: PrfValue,
V: PrfVisitor<Self::Block, Self::Passthrough>,
{
value.prf_visit_with_context(self, context, visitor)
}
fn prf_none<V>(&self, context: PrfContext<'static>, visitor: V) -> Self::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>;
fn passthrough<V>(&self, value: Self::Passthrough, visitor: V) -> Self::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>;
fn passthrough_boxed<V>(
&self,
value: Box<dyn Any + Send + 'static>,
visitor: V,
) -> Self::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>;
fn failure<T>(&self, error: PrfError<Self::BackendError>) -> Self::Ok<T>
where
T: Send + 'static;
}
pub trait SeqPrf: Sized {
type Prf: Prf<
Block = Self::Block,
BackendError = Self::BackendError,
Passthrough = Self::Passthrough,
>;
type Block: Send + 'static;
type BackendError: std::error::Error + Send + Sync + 'static;
type Passthrough: Send + 'static;
fn prf_next<T>(self, value: T, context: PrfContext<'static>) -> Self
where
T: PrfValue;
fn passthrough_next(self, value: Self::Passthrough) -> Self;
fn passthrough_next_boxed(self, value: Box<dyn Any + Send + 'static>) -> Self;
fn end<V>(self, visitor: V) -> <Self::Prf as Prf>::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>;
}
pub trait MapPrf: Sized {
type Prf: Prf<
Block = Self::Block,
BackendError = Self::BackendError,
Passthrough = Self::Passthrough,
>;
type Block: Send + 'static;
type BackendError: std::error::Error + Send + Sync + 'static;
type Passthrough: Send + 'static;
fn prf_key<K>(self, key: K) -> Self
where
K: Into<Cow<'static, str>>;
fn prf_value<T>(self, value: T, context: PrfContext<'static>) -> Self
where
T: PrfValue;
fn prf_entry<K, T>(self, key: K, value: T, context: PrfContext<'static>) -> Self
where
K: Into<Cow<'static, str>>,
T: PrfValue,
{
self.prf_key(key).prf_value(value, context)
}
fn passthrough_entry<K>(self, key: K, value: Self::Passthrough) -> Self
where
K: Into<Cow<'static, str>>;
fn passthrough_entry_boxed<K>(self, key: K, value: Box<dyn Any + Send + 'static>) -> Self
where
K: Into<Cow<'static, str>>;
fn end<V>(self, visitor: V) -> <Self::Prf as Prf>::Ok<V::Value>
where
V: PrfVisitor<Self::Block, Self::Passthrough>;
}