#![doc = include_str!("../README.md")]
use std::collections::BTreeSet;
use uuid::Uuid;
mod critical;
mod form;
mod gzip;
mod identity;
#[cfg(test)]
mod ietf_examples;
mod json;
mod signed;
pub const CRATE_NAME: &str = env!("CARGO_PKG_NAME");
pub const MAX_SIGNED_LAYERS: usize = 64;
pub const MAX_JSON_DEPTH: usize = 64;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Limits {
pub inflated: u64,
}
pub fn parse_uuid(text: &str) -> Option<Uuid> {
identity::parse_uuid_text(text).ok()
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Inspection {
pub form: Form,
pub gzip: bool,
pub uuid: Uuid,
}
pub fn inspect(
body: &[u8],
content_type: Option<&str>,
limits: &Limits,
supported: &BTreeSet<String>,
) -> Result<Inspection, Rejection> {
let (inflated, gzip) = gzip::inflate(body, content_type, limits.inflated)?;
let mut budget = limits.inflated;
if gzip {
budget -= inflated.len() as u64;
}
let object = json::parse_object(&inflated)?;
let form = form::form_of(&object)?;
let uuid = match form {
Form::Unsigned => {
let uuid = identity::unsigned_identity(&object)?;
critical::check_critical(&object, supported)?;
uuid
}
Form::Signed => signed::signed_identity(&object, &mut budget, supported)?,
Form::Encrypted => identity::encrypted_identity(&object)?,
};
Ok(Inspection { form, gzip, uuid })
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Form {
Unsigned,
Signed,
Encrypted,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Rejection {
TooLarge,
TooDeep,
BadGzip,
NotJson,
DuplicateKey,
AmbiguousForm,
NoForm,
MissingUuid,
BadUuid,
MissingCreatedAt,
BadPayload,
UuidMismatch,
BadCritical,
UnsupportedCritical(Vec<String>),
}