use bytes::{Buf, BufMut, Bytes};
use http_body::Body;
use log::trace;
use std::str::FromStr;
use tonic::codegen::StdError;
const CODEC: VecCodec = VecCodec {};
const DECODER: VecDecoder = VecDecoder {};
const ENCODER: VecEncoder = VecEncoder {};
#[derive(Debug, Clone)]
pub struct GenericClient<T> {
inner: tonic::client::Grpc<T>,
}
impl<T> GenericClient<T>
where
T: tonic::client::GrpcService<tonic::body::BoxBody>,
T::ResponseBody: http_body::Body<Data = bytes::Bytes> + Send + 'static,
T::Error: Into<StdError>,
T::ResponseBody: Body<Data = Bytes> + Send + 'static,
<T::ResponseBody as Body>::Error: Into<StdError> + Send,
{
pub fn new(inner: T) -> Self {
let inner = tonic::client::Grpc::new(inner);
Self { inner }
}
pub async fn call(
&mut self,
path: &str,
payload: Vec<u8>,
) -> Result<tonic::Response<bytes::Bytes>, tonic::Status> {
trace!(
"Generic call to {} with {}bytes of payload",
path,
payload.len()
);
self.inner.ready().await.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e.into()),
)
})?;
let path = http::uri::PathAndQuery::from_str(path).unwrap();
self.inner
.unary(tonic::Request::new(payload), path, CODEC)
.await
}
pub fn max_decoding_message_size(mut self, limit: usize) -> Self
where
T: tonic::client::GrpcService<tonic::body::BoxBody>,
{
self.inner = self.inner.max_decoding_message_size(limit);
self
}
}
#[derive(Default)]
pub struct VecCodec {}
impl Codec for VecCodec {
type Encode = Vec<u8>;
type Decode = bytes::Bytes;
type Encoder = VecEncoder;
type Decoder = VecDecoder;
fn encoder(&mut self) -> Self::Encoder {
ENCODER
}
fn decoder(&mut self) -> Self::Decoder {
DECODER
}
}
use tonic::codec::{Codec, Decoder, Encoder};
#[derive(Debug, Clone, Default)]
pub struct VecEncoder;
impl Encoder for VecEncoder {
type Item = Vec<u8>;
type Error = tonic::Status;
fn encode(
&mut self,
item: Self::Item,
buf: &mut tonic::codec::EncodeBuf<'_>,
) -> Result<(), Self::Error> {
buf.put(item.as_slice());
Ok(())
}
}
#[derive(Debug, Clone, Default)]
pub struct VecDecoder;
impl Decoder for VecDecoder {
type Item = bytes::Bytes;
type Error = tonic::Status;
fn decode(
&mut self,
buf: &mut tonic::codec::DecodeBuf<'_>,
) -> Result<Option<Self::Item>, Self::Error> {
let buf = buf.copy_to_bytes(buf.remaining());
Ok(Some(buf))
}
}