use thiserror::Error;
use warg_crypto::hash::AnyHash;
mod wasm;
pub use wasm::*;
#[derive(Debug, Error)]
pub enum ContentPolicyError {
#[error("content was rejected by policy: {0}")]
Rejection(String),
}
pub type ContentPolicyResult<T> = Result<T, ContentPolicyError>;
pub trait ContentPolicy: Send + Sync {
fn new_stream_policy(
&self,
digest: &AnyHash,
) -> ContentPolicyResult<Box<dyn ContentStreamPolicy>>;
}
pub trait ContentStreamPolicy: Send + Sync {
fn check(&mut self, bytes: &[u8]) -> ContentPolicyResult<()>;
fn finalize(&mut self) -> ContentPolicyResult<()>;
}
#[derive(Default)]
pub struct ContentPolicyCollection {
policies: Vec<Box<dyn ContentPolicy>>,
}
impl ContentPolicyCollection {
pub fn new() -> Self {
Self::default()
}
pub fn push(&mut self, policy: impl ContentPolicy + 'static) {
self.policies.push(Box::new(policy));
}
}
impl ContentPolicy for ContentPolicyCollection {
fn new_stream_policy(
&self,
digest: &AnyHash,
) -> ContentPolicyResult<Box<dyn ContentStreamPolicy>> {
Ok(Box::new(ContentStreamPolicyCollection {
policies: self
.policies
.iter()
.map(|p| p.new_stream_policy(digest))
.collect::<ContentPolicyResult<_>>()?,
}))
}
}
pub struct ContentStreamPolicyCollection {
policies: Vec<Box<dyn ContentStreamPolicy>>,
}
impl ContentStreamPolicy for ContentStreamPolicyCollection {
fn check(&mut self, bytes: &[u8]) -> ContentPolicyResult<()> {
for policy in &mut self.policies {
policy.check(bytes)?;
}
Ok(())
}
fn finalize(&mut self) -> ContentPolicyResult<()> {
for policy in &mut self.policies {
policy.finalize()?;
}
Ok(())
}
}