penumbra_proto/
box_grpc_svc.rsuse bytes::Bytes;
use http_body::{combinators::UnsyncBoxBody, Body};
use tonic::{
body::BoxBody as ReqBody,
codegen::http as grpc,
transport::{self, Endpoint},
};
use tower::{util::BoxCloneService, Service, ServiceBuilder};
pub type BoxGrpcService =
BoxCloneService<grpc::Request<ReqBody>, grpc::Response<RspBody>, BoxError>;
pub type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
pub type RspBody = UnsyncBoxBody<Bytes, BoxError>;
pub async fn connect(ep: Endpoint) -> anyhow::Result<BoxGrpcService> {
let conn = ep.connect().await?;
let svc = ServiceBuilder::new()
.map_response(|rsp: grpc::Response<transport::Body>| rsp.map(box_rsp_body))
.map_err(BoxError::from)
.service(conn);
Ok(BoxCloneService::new(svc))
}
pub fn local<S, B>(svc: S) -> BoxGrpcService
where
S: Service<grpc::Request<ReqBody>, Response = grpc::Response<B>>,
S: Clone + Send + Sync + 'static,
S::Error: 'static,
S::Future: Send,
BoxError: From<S::Error> + From<B::Error>,
B: Body<Data = Bytes> + Send + 'static,
{
let svc = ServiceBuilder::new()
.map_response(|rsp: grpc::Response<B>| rsp.map(box_rsp_body))
.map_err(BoxError::from)
.service(svc);
BoxCloneService::new(svc)
}
fn box_rsp_body<B>(body: B) -> RspBody
where
B: Body<Data = Bytes> + Send + 'static,
BoxError: From<B::Error>,
B::Error: 'static,
{
body.map_err(BoxError::from).boxed_unsync()
}