use bytes::Buf;
use crate::encoding::DecodeContext;
use crate::encoding::WireType;
use crate::encoding::decode_key;
use crate::encoding::decode_varint;
use crate::error::DecodeError;
use crate::traits::ProtoExt;
pub trait ProtoShadowDecode<T> {
fn to_sun(self) -> Result<T, DecodeError>;
}
pub trait ProtoDecoder: ProtoExt {
fn merge_field(value: &mut Self, tag: u32, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError>;
#[inline]
fn merge(&mut self, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError> {
if wire_type != WireType::LengthDelimited {
return Err(DecodeError::new(format!("invalid wire type {}", Self::KIND.dbg_name())));
}
ctx.limit_reached()?;
let len = decode_varint(buf)? as usize;
let remaining = buf.remaining();
if len > remaining {
return Err(DecodeError::new("buffer underflow"));
}
let limit = remaining - len;
while buf.remaining() > limit {
Self::decode_one_field(self, buf, ctx)?;
}
Ok(())
}
#[inline]
fn decode(mut buf: impl Buf, ctx: DecodeContext) -> Result<Self, DecodeError>
where
Self: ProtoDefault,
{
ctx.limit_reached()?;
let mut sh = <Self as ProtoDefault>::proto_default();
Self::decode_into(&mut sh, &mut buf, ctx)?;
Ok(sh)
}
#[inline]
fn decode_into(value: &mut Self, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError> {
while buf.has_remaining() {
Self::decode_one_field(value, buf, ctx)?;
}
Ok(())
}
#[inline]
fn decode_one_field(value: &mut Self, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError> {
let (tag, wire) = decode_key(buf)?;
if tag == 0 {
return Err(DecodeError::new("invalid tag 0"));
}
Self::merge_field(value, tag, wire, buf, ctx)
}
}
pub trait ProtoDecode: Sized {
type ShadowDecoded: ProtoDecoder + ProtoExt + ProtoShadowDecode<Self> + ProtoDefault;
#[inline]
fn decode(mut buf: impl Buf, ctx: DecodeContext) -> Result<Self, DecodeError> {
let mut sh = <Self::ShadowDecoded as ProtoDefault>::proto_default();
Self::ShadowDecoded::decode_into(&mut sh, &mut buf, ctx)?;
Self::post_decode(sh)
}
#[inline]
fn post_decode(value: Self::ShadowDecoded) -> Result<Self, DecodeError> {
Self::ShadowDecoded::to_sun(value)
}
const VALIDATE_WITH_EXT: bool = false;
#[cfg(feature = "tonic")]
#[inline]
fn validate_with_ext(_value: &mut Self, _ext: &tonic::Extensions) -> Result<(), DecodeError> {
Ok(())
}
}
pub trait ProtoFieldMerge: ProtoExt {
fn merge_value(&mut self, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError>;
}
pub trait ProtoDefault: Sized {
fn proto_default() -> Self;
}
impl<T> ProtoFieldMerge for T
where
T: ProtoDecoder,
{
#[inline]
fn merge_value(&mut self, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError> {
<T as ProtoDecoder>::merge(self, wire_type, buf, ctx)
}
}
pub trait DecodeIrBuilder<T> {
fn build_ir(&self) -> Result<T, ::proto_rs::DecodeError>;
}