use core::hash::Hash;
#[cfg(feature = "dev")]
use arbitrary::Arbitrary;
use ed25519_dalek::VerifyingKey;
use ufotofu::codec_prelude::*;
use order_theory::{
GreatestElement, LeastElement, LowerSemilattice, PredecessorExceptForLeast,
SuccessorExceptForGreatest, TryPredecessor, TrySuccessor, UpperSemilattice,
};
#[derive(Clone, Debug)]
pub(crate) enum VerifyingKeyOrDummy {
Key(VerifyingKey),
Dummy([u8; 32]),
}
#[cfg(feature = "dev")]
impl<'a> Arbitrary<'a> for VerifyingKeyOrDummy {
fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
let bytes: [u8; 32] = Arbitrary::arbitrary(u)?;
Ok(Self::from_bytes(&bytes))
}
}
impl PartialEq for VerifyingKeyOrDummy {
fn eq(&self, other: &Self) -> bool {
let self_bytes = self.as_bytes();
let other_bytes = other.as_bytes();
constant_time_eq::constant_time_eq_n(self_bytes, other_bytes)
}
}
impl Eq for VerifyingKeyOrDummy {}
impl Hash for VerifyingKeyOrDummy {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.as_bytes().hash(state)
}
}
impl PartialOrd for VerifyingKeyOrDummy {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for VerifyingKeyOrDummy {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.as_bytes().cmp(other.as_bytes())
}
}
impl VerifyingKeyOrDummy {
pub fn from_bytes(bytes: &[u8; 32]) -> Self {
match VerifyingKey::from_bytes(bytes) {
Ok(key) => Self::Key(key),
Err(_) => Self::Dummy(*bytes),
}
}
pub fn as_bytes(&self) -> &[u8; 32] {
match self {
VerifyingKeyOrDummy::Dummy(bytes) => bytes,
VerifyingKeyOrDummy::Key(key) => key.as_bytes(),
}
}
pub fn to_bytes(&self) -> [u8; 32] {
match self {
VerifyingKeyOrDummy::Dummy(bytes) => *bytes,
VerifyingKeyOrDummy::Key(key) => key.to_bytes(),
}
}
}
impl LeastElement for VerifyingKeyOrDummy {
fn least() -> Self {
Self::from_bytes(&<[u8; 32]>::least())
}
}
impl GreatestElement for VerifyingKeyOrDummy {
fn greatest() -> Self {
Self::from_bytes(&<[u8; 32]>::greatest())
}
}
impl LowerSemilattice for VerifyingKeyOrDummy {
fn greatest_lower_bound(&self, other: &Self) -> Self {
Self::from_bytes(&self.as_bytes().greatest_lower_bound(other.as_bytes()))
}
}
impl UpperSemilattice for VerifyingKeyOrDummy {
fn least_upper_bound(&self, other: &Self) -> Self {
Self::from_bytes(&self.as_bytes().least_upper_bound(other.as_bytes()))
}
}
impl TryPredecessor for VerifyingKeyOrDummy {
fn try_predecessor(&self) -> Option<Self> {
self.as_bytes()
.try_predecessor()
.map(|bytes| Self::from_bytes(&bytes))
}
}
impl TrySuccessor for VerifyingKeyOrDummy {
fn try_successor(&self) -> Option<Self> {
self.as_bytes()
.try_successor()
.map(|bytes| Self::from_bytes(&bytes))
}
}
impl PredecessorExceptForLeast for VerifyingKeyOrDummy {}
impl SuccessorExceptForGreatest for VerifyingKeyOrDummy {}
impl Encodable for VerifyingKeyOrDummy {
async fn encode<C>(&self, consumer: &mut C) -> Result<(), C::Error>
where
C: BulkConsumer<Item = u8> + ?Sized,
{
consumer
.consume_full_slice(self.as_bytes())
.await
.map_err(|err| err.into_reason())
}
}
impl EncodableKnownLength for VerifyingKeyOrDummy {
fn len_of_encoding(&self) -> usize {
32
}
}
impl Decodable for VerifyingKeyOrDummy {
type ErrorReason = Infallible;
async fn decode<P>(
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorReason>>
where
P: BulkProducer<Item = u8> + ?Sized,
Self: Sized,
{
let mut buf = [0; 32];
producer.overwrite_full_slice(&mut buf).await?;
Ok(Self::from_bytes(&buf))
}
}
impl DecodableCanonic for VerifyingKeyOrDummy {
type ErrorCanonic = Infallible;
async fn decode_canonic<P>(
producer: &mut P,
) -> Result<Self, DecodeError<P::Final, P::Error, Self::ErrorCanonic>>
where
P: BulkProducer<Item = u8> + ?Sized,
Self: Sized,
{
Self::decode(producer).await
}
}