use crate::pb::{self, *}; use async_stream::try_stream; use futures_util::{stream, StreamExt, TryStreamExt}; use std::pin::Pin; use std::time::{Duration, Instant}; use tonic::{Code, Request, Response, Status}; pub use pb::server::{TestServiceServer, UnimplementedServiceServer}; #[derive(Default, Clone)] pub struct TestService; type Result = std::result::Result, Status>; type Streaming = Request>; type Stream = Pin> + Send + 'static>>; #[tonic::async_trait] impl pb::server::TestService for TestService { async fn empty_call(&self, _request: Request) -> Result { Ok(Response::new(Empty {})) } async fn unary_call(&self, request: Request) -> Result { let req = request.into_inner(); if let Some(echo_status) = req.response_status { let status = Status::new(Code::from_i32(echo_status.code), echo_status.message); return Err(status); } let res_size = if req.response_size >= 0 { req.response_size as usize } else { let status = Status::new(Code::InvalidArgument, "response_size cannot be negative"); return Err(status); }; let res = SimpleResponse { payload: Some(Payload { body: vec![0; res_size], ..Default::default() }), ..Default::default() }; Ok(Response::new(res)) } async fn cacheable_unary_call(&self, _: Request) -> Result { unimplemented!() } type StreamingOutputCallStream = Stream; async fn streaming_output_call( &self, req: Request, ) -> Result { let StreamingOutputCallRequest { response_parameters, .. } = req.into_inner(); let stream = try_stream! { for param in response_parameters { let deadline = Instant::now() + Duration::from_micros(param.interval_us as u64); tokio::timer::delay(deadline).await; let payload = crate::server_payload(param.size as usize); yield StreamingOutputCallResponse { payload: Some(payload) }; } }; Ok(Response::new( Box::pin(stream) as Self::StreamingOutputCallStream )) } async fn streaming_input_call( &self, req: Streaming, ) -> Result { let mut stream = req.into_inner(); let mut aggregated_payload_size = 0 as i32; while let Some(msg) = stream.try_next().await? { aggregated_payload_size += msg.payload.unwrap().body.len() as i32; } let res = StreamingInputCallResponse { aggregated_payload_size, }; Ok(Response::new(res)) } type FullDuplexCallStream = Stream; async fn full_duplex_call( &self, req: Streaming, ) -> Result { let mut stream = req.into_inner(); if let Some(first_msg) = stream.message().await? { if let Some(echo_status) = first_msg.response_status { let status = Status::new(Code::from_i32(echo_status.code), echo_status.message); return Err(status); } let single_message = stream::iter(vec![Ok(first_msg)]); let mut stream = single_message.chain(stream); let stream = try_stream! { while let Some(msg) = stream.try_next().await? { if let Some(echo_status) = msg.response_status { let status = Status::new(Code::from_i32(echo_status.code), echo_status.message); Err(status)?; } for param in msg.response_parameters { let deadline = Instant::now() + Duration::from_micros(param.interval_us as u64); tokio::timer::delay(deadline).await; let payload = crate::server_payload(param.size as usize); yield StreamingOutputCallResponse { payload: Some(payload) }; } } }; Ok(Response::new(Box::pin(stream) as Self::FullDuplexCallStream)) } else { let stream = stream::empty(); Ok(Response::new(Box::pin(stream) as Self::FullDuplexCallStream)) } } type HalfDuplexCallStream = Stream; async fn half_duplex_call( &self, _: Streaming, ) -> Result { Err(Status::unimplemented("TODO")) } async fn unimplemented_call(&self, _: Request) -> Result { Err(Status::unimplemented("")) } } pub struct UnimplementedService; #[tonic::async_trait] impl pb::server::UnimplementedService for UnimplementedService { async fn unimplemented_call(&self, _req: Request) -> Result { Err(Status::unimplemented("")) } }