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