use crate::buf::ReverseBuf;
use crate::encoding::{
Capped, DecodeContext, DistinguishedValueBorrowDecoder, DistinguishedValueDecoder,
ForOverwrite, RestrictedDecodeContext, ValueBorrowDecoder, ValueDecoder, ValueEncoder,
WireType, Wiretyped,
};
use crate::{Canonicity, DecodeError, DecodeErrorKind};
use bytes::{Buf, BufMut};
use core::ops::Deref;
pub struct Proxied<E, Tag = ()>(E, Tag);
pub(crate) struct SealedBilrostTag;
pub trait Proxiable<Tag = ()> {
type Proxy;
fn encode_proxy(&self) -> Self::Proxy;
fn decode_proxy(&mut self, proxy: Self::Proxy) -> Result<(), DecodeErrorKind>;
}
pub trait DistinguishedProxiable<Tag = ()>: Proxiable<Tag> {
fn decode_proxy_distinguished(
&mut self,
proxy: Self::Proxy,
) -> Result<Canonicity, DecodeErrorKind>;
}
impl<T, E, Tag> Wiretyped<Proxied<E, Tag>, T> for ()
where
T: Proxiable<Tag>,
(): Wiretyped<E, T::Proxy> + ForOverwrite<E, T::Proxy>,
{
const WIRE_TYPE: WireType = <() as Wiretyped<E, T::Proxy>>::WIRE_TYPE;
}
impl<T, E, Tag> ValueEncoder<Proxied<E, Tag>, T> for ()
where
T: Proxiable<Tag>,
(): ForOverwrite<E, T::Proxy> + ValueEncoder<E, T::Proxy>,
{
#[inline]
fn encode_value<B: BufMut + ?Sized>(value: &T, buf: &mut B) {
<() as ValueEncoder<E, _>>::encode_value(&value.encode_proxy(), buf);
}
#[inline]
fn prepend_value<B: ReverseBuf + ?Sized>(value: &T, buf: &mut B) {
<() as ValueEncoder<E, _>>::prepend_value(&value.encode_proxy(), buf);
}
#[inline]
fn value_encoded_len(value: &T) -> usize {
<() as ValueEncoder<E, _>>::value_encoded_len(&value.encode_proxy())
}
#[inline]
fn many_values_encoded_len<I>(values: I) -> usize
where
I: ExactSizeIterator,
I::Item: Deref<Target = T>,
{
#[repr(transparent)]
struct WrapDeref<T>(T);
impl<T> Deref for WrapDeref<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
<() as ValueEncoder<E, _>>::many_values_encoded_len(
values.map(|item| WrapDeref(item.encode_proxy())),
)
}
}
impl<T, E, Tag> ValueDecoder<Proxied<E, Tag>, T> for ()
where
T: Proxiable<Tag>,
(): ForOverwrite<E, T::Proxy> + ValueDecoder<E, T::Proxy>,
{
#[inline]
fn decode_value<B: Buf + ?Sized>(
value: &mut T,
buf: Capped<B>,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
let mut proxy = <() as ForOverwrite<E, T::Proxy>>::for_overwrite();
<() as ValueDecoder<E, _>>::decode_value(&mut proxy, buf, ctx)?;
Ok(value.decode_proxy(proxy)?)
}
}
impl<T, E, Tag> DistinguishedValueDecoder<Proxied<E, Tag>, T> for ()
where
T: DistinguishedProxiable<Tag> + Eq,
(): ForOverwrite<E, T::Proxy> + DistinguishedValueDecoder<E, T::Proxy>,
{
const CHECKS_EMPTY: bool = <() as DistinguishedValueDecoder<E, T::Proxy>>::CHECKS_EMPTY;
fn decode_value_distinguished<const ALLOW_EMPTY: bool>(
value: &mut T,
buf: Capped<impl Buf + ?Sized>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError> {
let mut proxy = <() as ForOverwrite<E, T::Proxy>>::for_overwrite();
let mut canon = <() as DistinguishedValueDecoder<E, _>>::decode_value_distinguished::<
ALLOW_EMPTY,
>(&mut proxy, buf, ctx.clone())?;
canon.update(ctx.check(value.decode_proxy_distinguished(proxy)?)?);
Ok(canon)
}
}
impl<'a, T, E, Tag> ValueBorrowDecoder<'a, Proxied<E, Tag>, T> for ()
where
T: Proxiable<Tag>,
(): ForOverwrite<E, T::Proxy> + ValueBorrowDecoder<'a, E, T::Proxy>,
{
#[inline]
fn borrow_decode_value(
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
let mut proxy = <() as ForOverwrite<E, T::Proxy>>::for_overwrite();
<() as ValueBorrowDecoder<E, _>>::borrow_decode_value(&mut proxy, buf, ctx)?;
Ok(value.decode_proxy(proxy)?)
}
}
impl<'a, T, E, Tag> DistinguishedValueBorrowDecoder<'a, Proxied<E, Tag>, T> for ()
where
T: DistinguishedProxiable<Tag> + Eq,
(): ForOverwrite<E, T::Proxy> + DistinguishedValueBorrowDecoder<'a, E, T::Proxy>,
{
const CHECKS_EMPTY: bool = <() as DistinguishedValueBorrowDecoder<E, T::Proxy>>::CHECKS_EMPTY;
fn borrow_decode_value_distinguished<const ALLOW_EMPTY: bool>(
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError> {
let mut proxy = <() as ForOverwrite<E, T::Proxy>>::for_overwrite();
let mut canon =
<() as DistinguishedValueBorrowDecoder<E, _>>::borrow_decode_value_distinguished::<
ALLOW_EMPTY,
>(&mut proxy, buf, ctx.clone())?;
canon.update(ctx.check(value.decode_proxy_distinguished(proxy)?)?);
Ok(canon)
}
}