//! This module defines common request/response types as well as the JsonCodec that is used by the //! json.helloworld.Greeter service which is defined manually (instead of via proto files) by the //! `build_json_codec_service` function in the `examples/build.rs` file. use bytes::{Buf, BufMut}; use serde::{Deserialize, Serialize}; use std::marker::PhantomData; use tonic::{ codec::{Codec, DecodeBuf, Decoder, EncodeBuf, Encoder}, Status, }; #[derive(Debug, Deserialize, Serialize)] pub struct HelloRequest { pub name: String, } #[derive(Debug, Deserialize, Serialize)] pub struct HelloResponse { pub message: String, } #[derive(Debug)] pub struct JsonEncoder(PhantomData); impl Encoder for JsonEncoder { type Item = T; type Error = Status; fn encode(&mut self, item: Self::Item, buf: &mut EncodeBuf<'_>) -> Result<(), Self::Error> { serde_json::to_writer(buf.writer(), &item).map_err(|e| Status::internal(e.to_string())) } } #[derive(Debug)] pub struct JsonDecoder(PhantomData); impl Decoder for JsonDecoder { type Item = U; type Error = Status; fn decode(&mut self, buf: &mut DecodeBuf<'_>) -> Result, Self::Error> { if !buf.has_remaining() { return Ok(None); } let item: Self::Item = serde_json::from_reader(buf.reader()).map_err(|e| Status::internal(e.to_string()))?; Ok(Some(item)) } } /// A [`Codec`] that implements `application/grpc+json` via the serde library. #[derive(Debug, Clone)] pub struct JsonCodec(PhantomData<(T, U)>); impl Default for JsonCodec { fn default() -> Self { Self(PhantomData) } } impl Codec for JsonCodec where T: serde::Serialize + Send + 'static, U: serde::de::DeserializeOwned + Send + 'static, { type Encode = T; type Decode = U; type Encoder = JsonEncoder; type Decoder = JsonDecoder; fn encoder(&mut self) -> Self::Encoder { JsonEncoder(PhantomData) } fn decoder(&mut self) -> Self::Decoder { JsonDecoder(PhantomData) } }