use core::marker::PhantomData;
use bytes::Buf;
use crate::encoding::DecodeContext;
use crate::encoding::WireType;
use crate::encoding::{self};
use crate::error::DecodeError;
use crate::traits::ArchivedProtoField; use crate::traits::ProtoArchive; use crate::traits::ProtoDecode;
use crate::traits::ProtoDefault;
use crate::traits::ProtoEncode;
use crate::traits::ProtoExt;
use crate::traits::ProtoFieldMerge;
use crate::traits::ProtoKind;
use crate::traits::ProtoShadowDecode;
use crate::traits::buffer::RevWriter; use crate::traits::decode::ProtoDecoder;
use crate::traits::encode::ProtoShadowEncode;
#[expect(dead_code)]
pub struct ID<'b, K, V> {
pub id: u64,
pub k: K,
pub v: V,
pub _pd: PhantomData<&'b ()>,
}
pub struct IDShadow<'a, K: ProtoEncode, V: ProtoEncode> {
pub id: u64,
pub k: <K as ProtoEncode>::Shadow<'a>,
pub v: <V as ProtoEncode>::Shadow<'a>,
pub _pd: PhantomData<&'a ()>,
}
pub struct IDDecoded<Kd, Vd> {
pub id: u64,
pub k: Kd,
pub v: Vd,
}
impl<K, V> ProtoExt for ID<'_, K, V> {
const KIND: ProtoKind = ProtoKind::Message;
}
impl<K: ProtoEncode, V: ProtoEncode> ProtoExt for IDShadow<'_, K, V> {
const KIND: ProtoKind = ProtoKind::Message;
}
impl<Kd, Vd> ProtoExt for IDDecoded<Kd, Vd> {
const KIND: ProtoKind = ProtoKind::Message;
}
impl<'a, 'b, K, V> ProtoShadowEncode<'a, ID<'b, K, V>> for IDShadow<'a, K, V>
where
K: ProtoEncode,
V: ProtoEncode,
{
#[inline]
fn from_sun(value: &'a ID<'b, K, V>) -> Self {
Self {
id: value.id,
k: <K as ProtoEncode>::Shadow::from_sun(&value.k),
v: <V as ProtoEncode>::Shadow::from_sun(&value.v),
_pd: PhantomData,
}
}
}
impl<K, V> ProtoEncode for ID<'_, K, V>
where
K: ProtoEncode,
V: ProtoEncode,
for<'a> <K as ProtoEncode>::Shadow<'a>: ProtoArchive + ProtoExt + ProtoShadowEncode<'a, K>,
for<'a> <V as ProtoEncode>::Shadow<'a>: ProtoArchive + ProtoExt + ProtoShadowEncode<'a, V>,
{
type Shadow<'a> = IDShadow<'a, K, V>;
}
impl<'a, K, V> ProtoArchive for IDShadow<'a, K, V>
where
K: ProtoEncode,
V: ProtoEncode,
<K as ProtoEncode>::Shadow<'a>: ProtoArchive + ProtoExt,
<V as ProtoEncode>::Shadow<'a>: ProtoArchive + ProtoExt,
u64: ProtoArchive + ProtoExt,
{
#[inline]
fn is_default(&self) -> bool {
self.id == 0 && <K as ProtoEncode>::Shadow::is_default(&self.k) && <V as ProtoEncode>::Shadow::is_default(&self.v)
}
#[inline]
fn archive<const TAG: u32>(&self, w: &mut impl RevWriter) {
let mark = w.mark();
ArchivedProtoField::<3, <V as ProtoEncode>::Shadow<'a>>::archive(&self.v, w);
ArchivedProtoField::<2, <K as ProtoEncode>::Shadow<'a>>::archive(&self.k, w);
ArchivedProtoField::<1, u64>::archive(&self.id, w);
if TAG != 0 {
let payload_len = w.written_since(mark);
w.put_varint(payload_len as u64);
ArchivedProtoField::<TAG, Self>::put_key(w);
}
}
}
impl<Kd, Vd> ProtoDecoder for IDDecoded<Kd, Vd>
where
Kd: ProtoDecoder,
Vd: ProtoDecoder,
{
#[inline]
fn merge_field(value: &mut Self, tag: u32, wire_type: WireType, buf: &mut impl Buf, ctx: DecodeContext) -> Result<(), DecodeError> {
match tag {
1 => value.id.merge(wire_type, buf, ctx),
2 => ProtoFieldMerge::merge_value(&mut value.k, wire_type, buf, ctx),
3 => ProtoFieldMerge::merge_value(&mut value.v, wire_type, buf, ctx),
_ => {
encoding::skip_field(wire_type, tag, buf, ctx)?;
Ok(())
}
}
}
}
impl<Kd, Vd> ProtoDefault for IDDecoded<Kd, Vd>
where
Kd: ProtoDefault,
Vd: ProtoDefault,
{
#[inline]
fn proto_default() -> Self {
Self {
id: 0,
k: <Kd as ProtoDefault>::proto_default(),
v: <Vd as ProtoDefault>::proto_default(),
}
}
}
impl<'b, K, V> ProtoShadowDecode<ID<'b, K, V>> for IDDecoded<<K as ProtoDecode>::ShadowDecoded, <V as ProtoDecode>::ShadowDecoded>
where
K: ProtoDecode,
V: ProtoDecode,
<K as ProtoDecode>::ShadowDecoded: ProtoShadowDecode<K>,
<V as ProtoDecode>::ShadowDecoded: ProtoShadowDecode<V>,
{
#[inline]
fn to_sun(self) -> Result<ID<'b, K, V>, DecodeError> {
let k = <K as ProtoDecode>::ShadowDecoded::to_sun(self.k)?;
let v = <V as ProtoDecode>::ShadowDecoded::to_sun(self.v)?;
Ok(ID {
id: self.id,
k,
v,
_pd: PhantomData,
})
}
}
impl<K, V> ProtoDecode for ID<'_, K, V>
where
K: ProtoDecode,
V: ProtoDecode,
{
type ShadowDecoded = IDDecoded<<K as ProtoDecode>::ShadowDecoded, <V as ProtoDecode>::ShadowDecoded>;
}