use crate::buf::ReverseBuf;
use crate::encoding::{
check_wire_type, Capped, DecodeContext, ForOverwrite, RestrictedDecodeContext, TagMeasurer,
TagRevWriter, TagWriter, WireType,
};
use crate::{Canonicity, DecodeError};
use bytes::{Buf, BufMut};
use core::ops::Deref;
pub trait Encoder<E, T: ?Sized> {
fn encode<B: BufMut + ?Sized>(tag: u32, value: &T, buf: &mut B, tw: &mut TagWriter);
fn prepend_encode<B: ReverseBuf + ?Sized>(
tag: u32,
value: &T,
buf: &mut B,
tw: &mut TagRevWriter,
);
fn encoded_len(tag: u32, value: &T, tm: &mut impl TagMeasurer) -> usize;
}
pub trait Decoder<E, T>: Encoder<E, T> {
fn decode<B: Buf + ?Sized>(
wire_type: WireType,
value: &mut T,
buf: Capped<B>,
ctx: DecodeContext,
) -> Result<(), DecodeError>;
}
pub trait DistinguishedDecoder<E, T>: Encoder<E, T> {
fn decode_distinguished<B: Buf + ?Sized>(
wire_type: WireType,
value: &mut T,
buf: Capped<B>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError>;
}
pub trait BorrowDecoder<'a, E, T>: Encoder<E, T> {
fn borrow_decode(
wire_type: WireType,
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: DecodeContext,
) -> Result<(), DecodeError>;
}
pub trait DistinguishedBorrowDecoder<'a, E, T>: Encoder<E, T> {
fn borrow_decode_distinguished(
wire_type: WireType,
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError>;
}
pub trait Wiretyped<E, T: ?Sized> {
const WIRE_TYPE: WireType;
}
pub trait ValueEncoder<E, T: ?Sized>: Wiretyped<E, T> {
fn encode_value<B: BufMut + ?Sized>(value: &T, buf: &mut B);
fn prepend_value<B: ReverseBuf + ?Sized>(value: &T, buf: &mut B);
fn value_encoded_len(value: &T) -> usize;
#[inline]
fn many_values_encoded_len<I>(values: I) -> usize
where
I: ExactSizeIterator,
I::Item: Deref<Target = T>,
{
let len = values.len();
Self::WIRE_TYPE.fixed_size().map_or_else(
|| values.map(|val| Self::value_encoded_len(&val)).sum(),
|fixed_size| fixed_size * len, )
}
}
pub trait ValueDecoder<E, T>: ValueEncoder<E, T> {
fn decode_value<B: Buf + ?Sized>(
value: &mut T,
buf: Capped<B>,
ctx: DecodeContext,
) -> Result<(), DecodeError>;
}
pub trait DistinguishedValueDecoder<E, T>: ValueEncoder<E, T> + Eq {
const CHECKS_EMPTY: bool;
fn decode_value_distinguished<const ALLOW_EMPTY: bool>(
value: &mut T,
buf: Capped<impl Buf + ?Sized>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError>;
}
pub trait ValueBorrowDecoder<'a, E, T>: ValueEncoder<E, T> {
fn borrow_decode_value(
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: DecodeContext,
) -> Result<(), DecodeError>;
}
pub trait DistinguishedValueBorrowDecoder<'a, E, T>: ValueEncoder<E, T> + Eq {
const CHECKS_EMPTY: bool;
fn borrow_decode_value_distinguished<const ALLOW_EMPTY: bool>(
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError>;
}
pub trait FieldEncoder<E, T: ?Sized>: ValueEncoder<E, T> {
fn encode_field<B: BufMut + ?Sized>(tag: u32, value: &T, buf: &mut B, tw: &mut TagWriter);
fn prepend_field<B: ReverseBuf + ?Sized>(
tag: u32,
value: &T,
buf: &mut B,
tw: &mut TagRevWriter,
);
fn field_encoded_len(tag: u32, value: &T, tm: &mut impl TagMeasurer) -> usize;
}
pub trait FieldDecoder<E, T>: ValueDecoder<E, T> {
fn decode_field<B: Buf + ?Sized>(
wire_type: WireType,
value: &mut T,
buf: Capped<B>,
ctx: DecodeContext,
) -> Result<(), DecodeError>;
}
pub trait DistinguishedFieldDecoder<E, T>: DistinguishedValueDecoder<E, T> {
fn decode_field_distinguished<const ALLOW_EMPTY: bool>(
wire_type: WireType,
value: &mut T,
buf: Capped<impl Buf + ?Sized>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError>;
}
pub trait FieldBorrowDecoder<'a, E, T>: ValueBorrowDecoder<'a, E, T> {
fn borrow_decode_field(
wire_type: WireType,
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: DecodeContext,
) -> Result<(), DecodeError>;
}
pub trait DistinguishedFieldBorrowDecoder<'a, E, T>:
DistinguishedValueBorrowDecoder<'a, E, T>
{
fn borrow_decode_field_distinguished<const ALLOW_EMPTY: bool>(
wire_type: WireType,
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError>;
}
impl<E, T: ?Sized> FieldEncoder<E, T> for ()
where
(): ValueEncoder<E, T>,
{
#[inline]
fn encode_field<B: BufMut + ?Sized>(tag: u32, value: &T, buf: &mut B, tw: &mut TagWriter) {
tw.encode_key(tag, <() as Wiretyped<E, T>>::WIRE_TYPE, buf);
<() as ValueEncoder<E, T>>::encode_value(value, buf);
}
#[inline]
fn prepend_field<B: ReverseBuf + ?Sized>(
tag: u32,
value: &T,
buf: &mut B,
tw: &mut TagRevWriter,
) {
tw.begin_field(tag, <() as Wiretyped<E, T>>::WIRE_TYPE, buf);
<() as ValueEncoder<E, T>>::prepend_value(value, buf);
}
#[inline]
fn field_encoded_len(tag: u32, value: &T, tm: &mut impl TagMeasurer) -> usize {
tm.key_len(tag) + <() as ValueEncoder<E, T>>::value_encoded_len(value)
}
}
impl<T, E> FieldDecoder<E, T> for ()
where
(): ValueDecoder<E, T>,
{
#[inline]
fn decode_field<B: Buf + ?Sized>(
wire_type: WireType,
value: &mut T,
buf: Capped<B>,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
<() as ValueDecoder<E, T>>::decode_value(value, buf, ctx)
}
}
impl<T, E> DistinguishedFieldDecoder<E, T> for ()
where
(): DistinguishedValueDecoder<E, T>,
{
#[inline(always)]
fn decode_field_distinguished<const ALLOW_EMPTY: bool>(
wire_type: WireType,
value: &mut T,
buf: Capped<impl Buf + ?Sized>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError> {
check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
<() as DistinguishedValueDecoder<E, T>>::decode_value_distinguished::<ALLOW_EMPTY>(
value, buf, ctx,
)
}
}
impl<'a, T, E> FieldBorrowDecoder<'a, E, T> for ()
where
(): ValueBorrowDecoder<'a, E, T>,
{
#[inline]
fn borrow_decode_field(
wire_type: WireType,
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
<() as ValueBorrowDecoder<E, T>>::borrow_decode_value(value, buf, ctx)
}
}
impl<'a, T, E> DistinguishedFieldBorrowDecoder<'a, E, T> for ()
where
(): DistinguishedValueBorrowDecoder<'a, E, T>,
{
#[inline(always)]
fn borrow_decode_field_distinguished<const ALLOW_EMPTY: bool>(
wire_type: WireType,
value: &mut T,
buf: Capped<&'a [u8]>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError> {
check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
<() as DistinguishedValueBorrowDecoder<E, T>>::borrow_decode_value_distinguished::<
ALLOW_EMPTY,
>(value, buf, ctx)
}
}
mod generic_optional {
use super::*;
impl<T, E> Encoder<E, Option<T>> for ()
where
(): ValueEncoder<E, T> + ForOverwrite<E, T>,
{
#[inline]
fn encode<B: BufMut + ?Sized>(
tag: u32,
value: &Option<T>,
buf: &mut B,
tw: &mut TagWriter,
) {
if let Some(value) = value {
<() as FieldEncoder<E, T>>::encode_field(tag, value, buf, tw);
}
}
#[inline]
fn prepend_encode<B: ReverseBuf + ?Sized>(
tag: u32,
value: &Option<T>,
buf: &mut B,
tw: &mut TagRevWriter,
) {
if let Some(value) = value {
<() as FieldEncoder<E, T>>::prepend_field(tag, value, buf, tw)
}
}
#[inline]
fn encoded_len(tag: u32, value: &Option<T>, tm: &mut impl TagMeasurer) -> usize {
if let Some(value) = value {
<() as FieldEncoder<E, T>>::field_encoded_len(tag, value, tm)
} else {
0
}
}
}
impl<T, E> Decoder<E, Option<T>> for ()
where
(): ValueDecoder<E, T> + ForOverwrite<E, T>,
{
#[inline]
fn decode<B: Buf + ?Sized>(
wire_type: WireType,
value: &mut Option<T>,
buf: Capped<B>,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
<() as FieldDecoder<E, T>>::decode_field(
wire_type,
value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
buf,
ctx,
)
}
}
impl<T, E> DistinguishedDecoder<E, Option<T>> for ()
where
Option<T>: Eq,
(): DistinguishedValueDecoder<E, T> + ForOverwrite<E, T>,
{
#[inline]
fn decode_distinguished<B: Buf + ?Sized>(
wire_type: WireType,
value: &mut Option<T>,
buf: Capped<B>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError> {
check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
<() as DistinguishedValueDecoder<E, T>>::decode_value_distinguished::<true>(
value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
buf,
ctx,
)
}
}
impl<'a, T, E> BorrowDecoder<'a, E, Option<T>> for ()
where
(): ValueBorrowDecoder<'a, E, T> + ForOverwrite<E, T>,
{
#[inline]
fn borrow_decode(
wire_type: WireType,
value: &mut Option<T>,
buf: Capped<&'a [u8]>,
ctx: DecodeContext,
) -> Result<(), DecodeError> {
<() as FieldBorrowDecoder<E, T>>::borrow_decode_field(
wire_type,
value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
buf,
ctx,
)
}
}
impl<'a, T, E> DistinguishedBorrowDecoder<'a, E, Option<T>> for ()
where
Option<T>: Eq,
(): DistinguishedValueBorrowDecoder<'a, E, T> + ForOverwrite<E, T>,
{
#[inline]
fn borrow_decode_distinguished(
wire_type: WireType,
value: &mut Option<T>,
buf: Capped<&'a [u8]>,
ctx: RestrictedDecodeContext,
) -> Result<Canonicity, DecodeError> {
check_wire_type(<() as Wiretyped<E, T>>::WIRE_TYPE, wire_type)?;
<() as DistinguishedValueBorrowDecoder<E, T>>::borrow_decode_value_distinguished::<true>(
value.get_or_insert_with(<() as ForOverwrite<E, T>>::for_overwrite),
buf,
ctx,
)
}
}
}