use crate::{signature::SignaturePrimitive, signed::Signed};
pub struct Verified<T, S: SignaturePrimitive, C> {
signed: Signed<T, S, C>,
payload: T,
}
impl<T: Clone, S: SignaturePrimitive, C> Clone for Verified<T, S, C>
where
S::VerifyingKey: Clone,
S::Signature: Clone,
{
fn clone(&self) -> Self {
Self {
signed: self.signed.clone(),
payload: self.payload.clone(),
}
}
}
impl<T: PartialEq, S: SignaturePrimitive, C> PartialEq for Verified<T, S, C>
where
S::VerifyingKey: PartialEq,
S::Signature: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.signed == other.signed && self.payload == other.payload
}
}
impl<T: Eq, S: SignaturePrimitive, C> Eq for Verified<T, S, C>
where
S::VerifyingKey: Eq,
S::Signature: Eq,
{
}
impl<T: core::hash::Hash, S: SignaturePrimitive, C> core::hash::Hash for Verified<T, S, C>
where
S::VerifyingKey: core::hash::Hash,
S::Signature: core::hash::Hash,
{
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.signed.hash(state);
self.payload.hash(state);
}
}
impl<T: core::fmt::Debug, S: SignaturePrimitive, C> core::fmt::Debug for Verified<T, S, C>
where
S::VerifyingKey: core::fmt::Debug,
S::Signature: core::fmt::Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("Verified")
.field("signed", &self.signed)
.field("payload", &self.payload)
.finish()
}
}
impl<T, S: SignaturePrimitive, C> Verified<T, S, C> {
#[must_use]
pub(crate) const fn new(signed: Signed<T, S, C>, payload: T) -> Self {
Self { signed, payload }
}
#[must_use]
pub const fn issuer(&self) -> &S::VerifyingKey {
self.signed.issuer()
}
#[must_use]
pub const fn payload(&self) -> &T {
&self.payload
}
#[must_use]
pub const fn signed(&self) -> &Signed<T, S, C> {
&self.signed
}
#[must_use]
pub fn into_payload(self) -> T {
self.payload
}
#[must_use]
pub fn into_signed(self) -> Signed<T, S, C> {
self.signed
}
#[must_use]
pub fn into_parts(self) -> (Signed<T, S, C>, T) {
(self.signed, self.payload)
}
}
pub trait VerifiedUnchecked<T, S: SignaturePrimitive, C> {
fn from_unchecked_parts(signed: Signed<T, S, C>, payload: T) -> Self;
}
impl<T, S: SignaturePrimitive, C> VerifiedUnchecked<T, S, C> for Verified<T, S, C> {
fn from_unchecked_parts(signed: Signed<T, S, C>, payload: T) -> Self {
Self::new(signed, payload)
}
}
#[cfg(feature = "serde")]
impl<T, S: SignaturePrimitive, C> serde::Serialize for Verified<T, S, C>
where
T: serde::Serialize,
S::VerifyingKey: serde::Serialize,
S::Signature: serde::Serialize,
{
fn serialize<Ser: serde::Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct("Verified", 2)?;
state.serialize_field("signed", &self.signed)?;
state.serialize_field("payload", &self.payload)?;
state.end()
}
}
#[cfg(feature = "serde")]
impl<'de, T, S: SignaturePrimitive, C> serde::Deserialize<'de> for Verified<T, S, C>
where
T: serde::Deserialize<'de>,
S::VerifyingKey: serde::Deserialize<'de>,
S::Signature: serde::Deserialize<'de>,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use core::marker::PhantomData;
use serde::de::{MapAccess, Visitor};
struct VerifiedVisitor<T, S: SignaturePrimitive, C>(PhantomData<(T, S, C)>);
impl<'de, T, S: SignaturePrimitive, C> Visitor<'de> for VerifiedVisitor<T, S, C>
where
T: serde::Deserialize<'de>,
S::VerifyingKey: serde::Deserialize<'de>,
S::Signature: serde::Deserialize<'de>,
{
type Value = Verified<T, S, C>;
fn expecting(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
formatter.write_str("struct Verified")
}
fn visit_map<V: MapAccess<'de>>(
self,
mut map: V,
) -> Result<Verified<T, S, C>, V::Error> {
let mut signed = None;
let mut payload = None;
while let Some(key) = map.next_key::<&str>()? {
match key {
"signed" => signed = Some(map.next_value()?),
"payload" => payload = Some(map.next_value()?),
_ => {
let _: serde::de::IgnoredAny = map.next_value()?;
}
}
}
let signed = signed.ok_or_else(|| serde::de::Error::missing_field("signed"))?;
let payload = payload.ok_or_else(|| serde::de::Error::missing_field("payload"))?;
Ok(Verified::new(signed, payload))
}
}
const FIELDS: &[&str] = &["signed", "payload"];
deserializer.deserialize_struct("Verified", FIELDS, VerifiedVisitor(PhantomData))
}
}
#[cfg(feature = "arbitrary")]
impl<'a, T, S: SignaturePrimitive, C> arbitrary::Arbitrary<'a> for Verified<T, S, C>
where
T: arbitrary::Arbitrary<'a>,
S::VerifyingKey: arbitrary::Arbitrary<'a>,
S::Signature: arbitrary::Arbitrary<'a>,
{
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let signed = Signed::arbitrary(u)?;
let payload = T::arbitrary(u)?;
Ok(Self::new(signed, payload))
}
}
#[cfg(feature = "bolero")]
impl<T: 'static, S: SignaturePrimitive + 'static, C: 'static> bolero_generator::TypeGenerator
for Verified<T, S, C>
where
T: bolero_generator::TypeGenerator,
S::VerifyingKey: bolero_generator::TypeGenerator,
S::Signature: bolero_generator::TypeGenerator,
{
fn generate<D: bolero_generator::Driver>(driver: &mut D) -> Option<Self> {
let signed = Signed::generate(driver)?;
let payload = T::generate(driver)?;
Some(Self::new(signed, payload))
}
}
#[cfg(feature = "proptest")]
impl<T: 'static, S: SignaturePrimitive + 'static, C: 'static> proptest::arbitrary::Arbitrary
for Verified<T, S, C>
where
T: proptest::arbitrary::Arbitrary + 'static,
S::VerifyingKey: proptest::arbitrary::Arbitrary + 'static,
S::Signature: proptest::arbitrary::Arbitrary + 'static,
{
type Parameters = ();
type Strategy = proptest::strategy::BoxedStrategy<Self>;
fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
use proptest::prelude::*;
(any::<Signed<T, S, C>>(), any::<T>())
.prop_map(|(signed, payload)| Self::new(signed, payload))
.boxed()
}
}
#[cfg(feature = "rkyv")]
pub mod archive {
use super::{SignaturePrimitive, Signed, Verified};
use alloc::vec::Vec;
use rkyv::{Archive, Archived, Deserialize, Serialize, rancor::Fallible};
impl<T, S: SignaturePrimitive, C> Archive for Verified<T, S, C>
where
T: Archive + Clone,
S::VerifyingKey: Archive + Clone,
S::Signature: Archive + Clone,
{
type Archived = ArchivedVerified<T, S::VerifyingKey, S::Signature>;
type Resolver = VerifiedResolver<T, S::VerifyingKey, S::Signature>;
fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) {
let helper = VerifiedHelper {
issuer: self.signed.issuer().clone(),
signature: self.signed.signature().clone(),
encoded_payload: self.signed.encoded_payload().to_vec(),
payload: self.payload.clone(),
};
helper.resolve(resolver, out);
}
}
impl<T, S: SignaturePrimitive, C, Ser> Serialize<Ser> for Verified<T, S, C>
where
T: Serialize<Ser> + Clone,
S::VerifyingKey: Serialize<Ser> + Clone,
S::Signature: Serialize<Ser> + Clone,
Ser: Fallible + rkyv::ser::Allocator + rkyv::ser::Writer + ?Sized,
{
fn serialize(&self, serializer: &mut Ser) -> Result<Self::Resolver, Ser::Error> {
let helper = VerifiedHelper {
issuer: self.signed.issuer().clone(),
signature: self.signed.signature().clone(),
encoded_payload: self.signed.encoded_payload().to_vec(),
payload: self.payload.clone(),
};
helper.serialize(serializer)
}
}
impl<T, S: SignaturePrimitive, C, D> Deserialize<Verified<T, S, C>, D>
for ArchivedVerified<T, S::VerifyingKey, S::Signature>
where
T: Archive,
S::VerifyingKey: Archive,
S::Signature: Archive,
Archived<T>: Deserialize<T, D>,
Archived<S::VerifyingKey>: Deserialize<S::VerifyingKey, D>,
Archived<S::Signature>: Deserialize<S::Signature, D>,
D: Fallible + ?Sized,
D::Error: rkyv::rancor::Source,
{
fn deserialize(&self, deserializer: &mut D) -> Result<Verified<T, S, C>, D::Error> {
let helper: VerifiedHelper<T, S::VerifyingKey, S::Signature> =
<ArchivedVerified<T, S::VerifyingKey, S::Signature> as Deserialize<
VerifiedHelper<T, S::VerifyingKey, S::Signature>,
D,
>>::deserialize(self, deserializer)?;
let signed = Signed::new(helper.issuer, helper.signature, helper.encoded_payload);
Ok(Verified::new(signed, helper.payload))
}
}
#[derive(Debug, Archive, Serialize, Deserialize)]
pub struct VerifiedHelper<Payload, VerifyingKey, Signature> {
issuer: VerifyingKey,
signature: Signature,
encoded_payload: Vec<u8>,
payload: Payload,
}
pub type ArchivedVerified<Payload, VerifyingKey, Signature> =
ArchivedVerifiedHelper<Payload, VerifyingKey, Signature>;
pub type VerifiedResolver<Payload, VerifyingKey, Signature> =
VerifiedHelperResolver<Payload, VerifyingKey, Signature>;
}