use core::marker::PhantomData;
use crate::encoding::Encoding;
pub trait Payload<E: Encoding>: Sized {
const MAX_SIZE: usize;
type View<'a>;
fn encode<'o>(&self, out: &'o mut [u8]) -> Result<Encoded<'o, Self::View<'o>>, EncodeError>;
fn verify(buf: &[u8]) -> Result<Self::View<'_>, VerifyError>;
fn decode(r: Ref<'_, Self, E>) -> Self;
}
pub trait View<'a> {
fn bytes(&self) -> &'a [u8];
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Encoded<'a, V> {
pub bytes: &'a [u8],
pub view: V,
}
pub struct Ref<'a, T: Payload<E>, E: Encoding> {
bytes: &'a [u8],
view: T::View<'a>,
_e: PhantomData<E>,
}
impl<'a, T: Payload<E>, E: Encoding> Ref<'a, T, E> {
pub fn verify(buf: &'a [u8]) -> Result<Self, VerifyError> {
let view = T::verify(buf)?;
Ok(Ref {
bytes: buf,
view,
_e: PhantomData,
})
}
pub fn encode(value: &T, out: &'a mut [u8]) -> Result<Self, EncodeError> {
let Encoded { bytes, view } = value.encode(out)?;
Ok(Ref {
bytes,
view,
_e: PhantomData,
})
}
pub fn bytes(&self) -> &'a [u8] {
self.bytes
}
pub fn view(&self) -> &T::View<'a> {
&self.view
}
pub fn into_view(self) -> T::View<'a> {
self.view
}
pub fn decode(self) -> T {
T::decode(self)
}
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EncodeError {
Capacity {
needed: usize,
available: usize,
},
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum VerifyError {
Structure(Malformed),
Contract(Violation),
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Malformed {
OutOfBounds,
Unaligned,
MissingRequired,
Utf8,
Union,
TooDeep,
TooManyTables,
TooLarge,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Violation {
pub type_name: &'static str,
pub rule: Rule,
}
#[non_exhaustive]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Rule {
Range,
Step,
Length,
Pattern,
Variant,
Unique,
}
#[cfg(test)]
mod tests {
use core::marker::PhantomData;
use super::{EncodeError, Encoded, Payload, Ref, Rule, VerifyError};
use crate::encoding::ReprC;
struct Raw;
impl Payload<ReprC> for Raw {
const MAX_SIZE: usize = 0;
type View<'a> = &'a [u8];
fn encode<'o>(&self, out: &'o mut [u8]) -> Result<Encoded<'o, &'o [u8]>, EncodeError> {
let bytes: &'o [u8] = &out[..0];
Ok(Encoded { bytes, view: bytes })
}
fn verify(buf: &[u8]) -> Result<&[u8], VerifyError> {
Ok(buf)
}
fn decode(_: Ref<'_, Self, ReprC>) -> Self {
Raw
}
}
#[test]
fn a_ref_is_built_from_exactly_its_three_fields() {
let bytes: &[u8] = &[1, 2];
let proof: Ref<'_, Raw, ReprC> = Ref {
bytes,
view: bytes,
_e: PhantomData,
};
assert_eq!(proof.bytes(), bytes);
}
#[test]
fn rule_is_exactly_these_six_variants() {
fn all(r: Rule) {
match r {
Rule::Range => {}
Rule::Step => {}
Rule::Length => {}
Rule::Pattern => {}
Rule::Variant => {}
Rule::Unique => {}
}
}
all(Rule::Range);
all(Rule::Unique);
}
}