proto_rs 0.11.24

Rust-first gRPC macros collection for .proto/protobufs managment and more
use tonic::Status;
use tonic::codec::Codec;
use tonic::codec::DecodeBuf;
use tonic::codec::Decoder;
use tonic::codec::EncodeBuf;
use tonic::codec::Encoder;
mod req;
mod resp;
use bytes::BufMut;
pub use req::ProtoRequest;
pub use resp::ProtoResponse;
pub use resp::map_proto_response;
pub use resp::map_proto_stream_result;

use crate::ProtoDecode;
use crate::ProtoEncode;
use crate::ProtoExt;
use crate::alloc::boxed::Box;
use crate::alloc::sync::Arc;
use crate::coders::AsBytes;
use crate::coders::BytesMode;
use crate::coders::ProtoCodec;
use crate::coders::ProtoDecoder;
use crate::coders::ProtoEncoder;
use crate::coders::SunByRef;
use crate::coders::SunByRefDeref;
use crate::coders::SunByVal;
use crate::encoding::DecodeContext;

impl<Encode, Decode, Mode> Codec for ProtoCodec<Encode, Decode, Mode>
where
    Encode: Send + 'static,
    Decode: ProtoDecode + Send + 'static,
    Mode: Send + Sync + 'static,
    ProtoEncoder<Encode, Mode>: EncoderExt<Encode, Mode>,
{
    type Encode = Encode;
    type Decode = Decode;
    type Encoder = ProtoEncoder<Encode, Mode>;
    type Decoder = ProtoDecoder<Decode>;

    fn encoder(&mut self) -> Self::Encoder {
        ProtoEncoder::default()
    }

    fn decoder(&mut self) -> Self::Decoder {
        ProtoDecoder::default()
    }
}

pub trait EncoderExt<T, Mode> {
    fn encode_sun(&mut self, item: T, dst: &mut EncodeBuf<'_>) -> Result<(), Status>;
}

impl<T, Mode> EncoderExt<T, Mode> for ProtoEncoder<T, BytesMode>
where
    T: AsBytes,
{
    fn encode_sun(&mut self, item: T, dst: &mut EncodeBuf<'_>) -> Result<(), Status> {
        dst.put_slice(item.as_bytes());
        Ok(())
    }
}

impl<T> EncoderExt<T, SunByVal> for ProtoEncoder<T, SunByVal>
where
    T: ProtoEncode + ProtoExt,
{
    fn encode_sun(&mut self, item: T, dst: &mut EncodeBuf<'_>) -> Result<(), Status> {
        ProtoEncode::encode(&item, dst).map_err(|e| Status::internal(format!("encode failed: {e}")))
    }
}

impl<T> EncoderExt<T, SunByRef> for ProtoEncoder<T, SunByRef>
where
    T: ProtoEncode + ProtoExt,
{
    fn encode_sun(&mut self, item: T, dst: &mut EncodeBuf<'_>) -> Result<(), Status> {
        ProtoEncode::encode(&item, dst).map_err(|e| Status::internal(format!("encode failed: {e}")))
    }
}

impl<T> EncoderExt<Arc<T>, SunByRefDeref> for ProtoEncoder<Arc<T>, SunByRefDeref>
where
    T: ProtoEncode + ProtoExt,
{
    fn encode_sun(&mut self, item: Arc<T>, dst: &mut EncodeBuf<'_>) -> Result<(), Status> {
        ProtoEncode::encode(item.as_ref(), dst).map_err(|e| Status::internal(format!("encode failed: {e}")))
    }
}

impl<T> EncoderExt<Box<T>, SunByRefDeref> for ProtoEncoder<Box<T>, SunByRefDeref>
where
    T: ProtoEncode + ProtoExt,
{
    fn encode_sun(&mut self, item: Box<T>, dst: &mut EncodeBuf<'_>) -> Result<(), Status> {
        ProtoEncode::encode(item.as_ref(), dst).map_err(|e| Status::internal(format!("encode failed: {e}")))
    }
}

impl<T, Mode> Encoder for ProtoEncoder<T, Mode>
where
    ProtoEncoder<T, Mode>: EncoderExt<T, Mode>,
{
    type Item = T;
    type Error = Status;

    #[inline]
    fn encode(&mut self, item: T, dst: &mut EncodeBuf<'_>) -> Result<(), Status> {
        <Self as EncoderExt<T, Mode>>::encode_sun(self, item, dst)
    }
}

impl<T> Decoder for ProtoDecoder<T>
where
    T: ProtoDecode,
{
    type Item = T;
    type Error = Status;

    fn decode(&mut self, src: &mut DecodeBuf<'_>) -> Result<Option<Self::Item>, Self::Error> {
        match T::decode(src, DecodeContext::default()) {
            Ok(msg) => Ok(Some(msg)),
            Err(err) => Err(Status::data_loss(format!("failed to decode message: {err}"))),
        }
    }
}