1use std::pin::Pin;
26use std::sync::Arc;
27
28use buffa::Message;
29use buffa::view::MessageView;
30use buffa::view::OwnedView;
31use bytes::Bytes;
32use futures::Stream;
33
34use crate::codec::CodecFormat;
35use crate::codec::decode_json;
36use crate::codec::{JsonDeserialize, JsonSerialize};
37use crate::error::ConnectError;
38use crate::response::{
39 Encodable, EncodedResponse, RequestContext, Response, ServiceResult, ServiceStream,
40};
41
42fn decode_request_error(e: &buffa::DecodeError) -> ConnectError {
50 match e {
51 buffa::DecodeError::ElementMemoryLimitExceeded => ConnectError::invalid_argument(format!(
52 "failed to decode proto request: {e}; if this peer is trusted, \
53 raise Limits::element_memory_limit"
54 )),
55 _ => ConnectError::invalid_argument(format!("failed to decode proto request: {e}")),
56 }
57}
58
59pub(crate) fn decode_request<Req>(
61 request: &Bytes,
62 format: CodecFormat,
63 options: &buffa::DecodeOptions,
64) -> Result<Req, ConnectError>
65where
66 Req: Message + JsonDeserialize,
67{
68 match format {
69 CodecFormat::Proto => options
70 .decode_from_slice(&request[..])
71 .map_err(|e| decode_request_error(&e)),
72 CodecFormat::Json => decode_json(&request[..]),
73 }
74}
75
76pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
78
79pub type BoxStream<T> = Pin<Box<dyn Stream<Item = T> + Send>>;
81
82fn encode_body_stream<Res, B, S>(
94 stream: S,
95 format: CodecFormat,
96) -> BoxStream<Result<Bytes, ConnectError>>
97where
98 Res: Message + Send + 'static,
99 B: Encodable<Res> + Send + 'static,
100 S: Stream<Item = Result<B, ConnectError>> + Send + 'static,
101{
102 crate::dispatcher::codegen::encode_response_stream::<Res, B, S>(stream, format)
103}
104
105pub(crate) trait ErasedHandler: Send + Sync {
111 fn call_erased(
116 &self,
117 ctx: RequestContext,
118 request: crate::Payload,
119 format: CodecFormat,
120 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>>;
121
122 #[allow(dead_code)]
124 fn is_streaming(&self) -> bool;
125}
126
127pub(crate) type StreamingHandlerResult =
129 BoxFuture<'static, Result<Response<BoxStream<Result<Bytes, ConnectError>>>, ConnectError>>;
130
131pub(crate) trait ErasedStreamingHandler: Send + Sync {
133 fn call_erased(
135 &self,
136 ctx: RequestContext,
137 request: Bytes,
138 format: CodecFormat,
139 ) -> StreamingHandlerResult;
140}
141
142pub(crate) trait ErasedClientStreamingHandler: Send + Sync {
144 fn call_erased(
146 &self,
147 ctx: RequestContext,
148 requests: BoxStream<Result<Bytes, ConnectError>>,
149 format: CodecFormat,
150 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>>;
151}
152
153pub(crate) trait ErasedBidiStreamingHandler: Send + Sync {
155 fn call_erased(
157 &self,
158 ctx: RequestContext,
159 requests: BoxStream<Result<Bytes, ConnectError>>,
160 format: CodecFormat,
161 ) -> StreamingHandlerResult;
162}
163
164pub trait Handler<Req, Res>: Send + Sync + 'static
174where
175 Req: Message + Send + 'static,
176 Res: Message + Send + 'static,
177{
178 type Body: Encodable<Res> + Send + 'static;
182
183 fn call(
185 &self,
186 ctx: RequestContext,
187 request: Req,
188 ) -> BoxFuture<'static, ServiceResult<Self::Body>>;
189}
190
191pub struct FnHandler<F> {
193 f: Arc<F>,
194}
195
196impl<F> FnHandler<F> {
197 pub fn new(f: F) -> Self {
199 Self { f: Arc::new(f) }
200 }
201}
202
203impl<F, Fut, Req, Res, B> Handler<Req, Res> for FnHandler<F>
204where
205 F: Fn(RequestContext, Req) -> Fut + Send + Sync + 'static,
206 Fut: Future<Output = ServiceResult<B>> + Send + 'static,
207 Req: Message + Send + 'static,
208 Res: Message + Send + 'static,
209 B: Encodable<Res> + Send + 'static,
210{
211 type Body = B;
212
213 fn call(&self, ctx: RequestContext, request: Req) -> BoxFuture<'static, ServiceResult<B>> {
214 let f = Arc::clone(&self.f);
215 Box::pin(async move { f(ctx, request).await })
216 }
217}
218
219pub fn handler_fn<F, Fut, Req, Res, B>(f: F) -> FnHandler<F>
221where
222 F: Fn(RequestContext, Req) -> Fut + Send + Sync + 'static,
223 Fut: Future<Output = ServiceResult<B>> + Send + 'static,
224 Req: Message + Send + 'static,
225 Res: Message + Send + 'static,
226 B: Encodable<Res> + Send + 'static,
227{
228 FnHandler::new(f)
229}
230
231pub(crate) struct UnaryHandlerWrapper<H, Req, Res>
233where
234 H: Handler<Req, Res>,
235 Req: Message + JsonDeserialize + Send + 'static,
236 Res: Message + JsonSerialize + Send + 'static,
237{
238 handler: Arc<H>,
239 _phantom: std::marker::PhantomData<fn(Req) -> Res>,
240}
241
242impl<H, Req, Res> UnaryHandlerWrapper<H, Req, Res>
243where
244 H: Handler<Req, Res>,
245 Req: Message + JsonDeserialize + Send + 'static,
246 Res: Message + JsonSerialize + Send + 'static,
247{
248 pub fn new(handler: H) -> Self {
250 Self {
251 handler: Arc::new(handler),
252 _phantom: std::marker::PhantomData,
253 }
254 }
255}
256
257impl<H, Req, Res> ErasedHandler for UnaryHandlerWrapper<H, Req, Res>
258where
259 H: Handler<Req, Res>,
260 Req: Message + JsonDeserialize + Send + 'static,
261 Res: Message + JsonSerialize + Send + 'static,
262{
263 fn call_erased(
264 &self,
265 ctx: RequestContext,
266 request: crate::Payload,
267 format: CodecFormat,
268 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>> {
269 let handler = Arc::clone(&self.handler);
270 Box::pin(async move {
271 let req: Req = request.take_message()?;
274 handler.call(ctx, req).await?.encode::<Res>(format)
275 })
276 }
277
278 fn is_streaming(&self) -> bool {
279 false
280 }
281}
282
283pub trait StreamingHandler<Req, Res>: Send + Sync + 'static
296where
297 Req: Message + Send + 'static,
298 Res: Message + Send + 'static,
299{
300 type Item: Encodable<Res> + Send + 'static;
309
310 fn call(
312 &self,
313 ctx: RequestContext,
314 request: Req,
315 ) -> BoxFuture<'static, ServiceResult<ServiceStream<Self::Item>>>;
316}
317
318pub struct FnStreamingHandler<F> {
320 f: Arc<F>,
321}
322
323impl<F> FnStreamingHandler<F> {
324 pub fn new(f: F) -> Self {
326 Self { f: Arc::new(f) }
327 }
328}
329
330impl<F, Fut, Req, Res, B> StreamingHandler<Req, Res> for FnStreamingHandler<F>
331where
332 F: Fn(RequestContext, Req) -> Fut + Send + Sync + 'static,
333 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
334 Req: Message + Send + 'static,
335 Res: Message + Send + 'static,
336 B: Encodable<Res> + Send + 'static,
337{
338 type Item = B;
339
340 fn call(
341 &self,
342 ctx: RequestContext,
343 request: Req,
344 ) -> BoxFuture<'static, ServiceResult<ServiceStream<B>>> {
345 let f = Arc::clone(&self.f);
346 Box::pin(async move { f(ctx, request).await })
347 }
348}
349
350pub fn streaming_handler_fn<F, Fut, Req, Res, B>(f: F) -> FnStreamingHandler<F>
372where
373 F: Fn(RequestContext, Req) -> Fut + Send + Sync + 'static,
374 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
375 Req: Message + Send + 'static,
376 Res: Message + Send + 'static,
377 B: Encodable<Res> + Send + 'static,
378{
379 FnStreamingHandler::new(f)
380}
381
382pub(crate) struct ServerStreamingHandlerWrapper<H, Req, Res>
384where
385 H: StreamingHandler<Req, Res>,
386 Req: Message + JsonDeserialize + Send + 'static,
387 Res: Message + Send + 'static,
388{
389 handler: Arc<H>,
390 _phantom: std::marker::PhantomData<fn(Req) -> Res>,
391}
392
393impl<H, Req, Res> ServerStreamingHandlerWrapper<H, Req, Res>
394where
395 H: StreamingHandler<Req, Res>,
396 Req: Message + JsonDeserialize + Send + 'static,
397 Res: Message + Send + 'static,
398{
399 pub fn new(handler: H) -> Self {
401 Self {
402 handler: Arc::new(handler),
403 _phantom: std::marker::PhantomData,
404 }
405 }
406}
407
408impl<H, Req, Res> ErasedStreamingHandler for ServerStreamingHandlerWrapper<H, Req, Res>
409where
410 H: StreamingHandler<Req, Res>,
411 Req: Message + JsonDeserialize + Send + 'static,
412 Res: Message + Send + 'static,
413{
414 fn call_erased(
415 &self,
416 ctx: RequestContext,
417 request: Bytes,
418 format: CodecFormat,
419 ) -> StreamingHandlerResult {
420 let handler = Arc::clone(&self.handler);
421 Box::pin(async move {
422 let req: Req = decode_request(&request, format, ctx.decode_options())?;
423 let resp = handler.call(ctx, req).await?;
424 Ok(resp.map_body(|s| encode_body_stream(s, format)))
425 })
426 }
427}
428
429pub trait ClientStreamingHandler<Req, Res>: Send + Sync + 'static
435where
436 Req: Message + Send + 'static,
437 Res: Message + Send + 'static,
438{
439 type Body: Encodable<Res> + Send + 'static;
441
442 fn call(
444 &self,
445 ctx: RequestContext,
446 requests: ServiceStream<Req>,
447 ) -> BoxFuture<'static, ServiceResult<Self::Body>>;
448}
449
450pub struct FnClientStreamingHandler<F> {
452 f: Arc<F>,
453}
454
455impl<F> FnClientStreamingHandler<F> {
456 pub fn new(f: F) -> Self {
458 Self { f: Arc::new(f) }
459 }
460}
461
462impl<F, Fut, Req, Res, B> ClientStreamingHandler<Req, Res> for FnClientStreamingHandler<F>
463where
464 F: Fn(RequestContext, ServiceStream<Req>) -> Fut + Send + Sync + 'static,
465 Fut: Future<Output = ServiceResult<B>> + Send + 'static,
466 Req: Message + Send + 'static,
467 Res: Message + Send + 'static,
468 B: Encodable<Res> + Send + 'static,
469{
470 type Body = B;
471
472 fn call(
473 &self,
474 ctx: RequestContext,
475 requests: ServiceStream<Req>,
476 ) -> BoxFuture<'static, ServiceResult<B>> {
477 let f = Arc::clone(&self.f);
478 Box::pin(async move { f(ctx, requests).await })
479 }
480}
481
482pub fn client_streaming_handler_fn<F, Fut, Req, Res, B>(f: F) -> FnClientStreamingHandler<F>
484where
485 F: Fn(RequestContext, ServiceStream<Req>) -> Fut + Send + Sync + 'static,
486 Fut: Future<Output = ServiceResult<B>> + Send + 'static,
487 Req: Message + Send + 'static,
488 Res: Message + Send + 'static,
489 B: Encodable<Res> + Send + 'static,
490{
491 FnClientStreamingHandler::new(f)
492}
493
494pub(crate) struct ClientStreamingHandlerWrapper<H, Req, Res>
496where
497 H: ClientStreamingHandler<Req, Res>,
498 Req: Message + JsonDeserialize + Send + 'static,
499 Res: Message + JsonSerialize + Send + 'static,
500{
501 handler: Arc<H>,
502 _phantom: std::marker::PhantomData<fn(Req) -> Res>,
503}
504
505impl<H, Req, Res> ClientStreamingHandlerWrapper<H, Req, Res>
506where
507 H: ClientStreamingHandler<Req, Res>,
508 Req: Message + JsonDeserialize + Send + 'static,
509 Res: Message + JsonSerialize + Send + 'static,
510{
511 pub fn new(handler: H) -> Self {
513 Self {
514 handler: Arc::new(handler),
515 _phantom: std::marker::PhantomData,
516 }
517 }
518}
519
520impl<H, Req, Res> ErasedClientStreamingHandler for ClientStreamingHandlerWrapper<H, Req, Res>
521where
522 H: ClientStreamingHandler<Req, Res>,
523 Req: Message + JsonDeserialize + Send + 'static,
524 Res: Message + JsonSerialize + Send + 'static,
525{
526 fn call_erased(
527 &self,
528 ctx: RequestContext,
529 requests: BoxStream<Result<Bytes, ConnectError>>,
530 format: CodecFormat,
531 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>> {
532 use futures::StreamExt as _;
533 let handler = Arc::clone(&self.handler);
534 Box::pin(async move {
535 let options = ctx.decode_options().clone();
538 let request_stream: ServiceStream<Req> =
539 Box::pin(requests.map(move |result| {
540 result.and_then(|raw| decode_request(&raw, format, &options))
541 }));
542 handler
543 .call(ctx, request_stream)
544 .await?
545 .encode::<Res>(format)
546 })
547 }
548}
549
550pub trait BidiStreamingHandler<Req, Res>: Send + Sync + 'static
561where
562 Req: Message + Send + 'static,
563 Res: Message + Send + 'static,
564{
565 type Item: Encodable<Res> + Send + 'static;
570
571 fn call(
573 &self,
574 ctx: RequestContext,
575 requests: ServiceStream<Req>,
576 ) -> BoxFuture<'static, ServiceResult<ServiceStream<Self::Item>>>;
577}
578
579pub struct FnBidiStreamingHandler<F> {
581 f: Arc<F>,
582}
583
584impl<F> FnBidiStreamingHandler<F> {
585 pub fn new(f: F) -> Self {
587 Self { f: Arc::new(f) }
588 }
589}
590
591impl<F, Fut, Req, Res, B> BidiStreamingHandler<Req, Res> for FnBidiStreamingHandler<F>
592where
593 F: Fn(RequestContext, ServiceStream<Req>) -> Fut + Send + Sync + 'static,
594 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
595 Req: Message + Send + 'static,
596 Res: Message + Send + 'static,
597 B: Encodable<Res> + Send + 'static,
598{
599 type Item = B;
600
601 fn call(
602 &self,
603 ctx: RequestContext,
604 requests: ServiceStream<Req>,
605 ) -> BoxFuture<'static, ServiceResult<ServiceStream<B>>> {
606 let f = Arc::clone(&self.f);
607 Box::pin(async move { f(ctx, requests).await })
608 }
609}
610
611pub fn bidi_streaming_handler_fn<F, Fut, Req, Res, B>(f: F) -> FnBidiStreamingHandler<F>
613where
614 F: Fn(RequestContext, ServiceStream<Req>) -> Fut + Send + Sync + 'static,
615 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
616 Req: Message + Send + 'static,
617 Res: Message + Send + 'static,
618 B: Encodable<Res> + Send + 'static,
619{
620 FnBidiStreamingHandler::new(f)
621}
622
623pub(crate) struct BidiStreamingHandlerWrapper<H, Req, Res>
625where
626 H: BidiStreamingHandler<Req, Res>,
627 Req: Message + JsonDeserialize + Send + 'static,
628 Res: Message + Send + 'static,
629{
630 handler: Arc<H>,
631 _phantom: std::marker::PhantomData<fn(Req) -> Res>,
632}
633
634impl<H, Req, Res> BidiStreamingHandlerWrapper<H, Req, Res>
635where
636 H: BidiStreamingHandler<Req, Res>,
637 Req: Message + JsonDeserialize + Send + 'static,
638 Res: Message + Send + 'static,
639{
640 pub fn new(handler: H) -> Self {
642 Self {
643 handler: Arc::new(handler),
644 _phantom: std::marker::PhantomData,
645 }
646 }
647}
648
649impl<H, Req, Res> ErasedBidiStreamingHandler for BidiStreamingHandlerWrapper<H, Req, Res>
650where
651 H: BidiStreamingHandler<Req, Res>,
652 Req: Message + JsonDeserialize + Send + 'static,
653 Res: Message + Send + 'static,
654{
655 fn call_erased(
656 &self,
657 ctx: RequestContext,
658 requests: BoxStream<Result<Bytes, ConnectError>>,
659 format: CodecFormat,
660 ) -> StreamingHandlerResult {
661 use futures::StreamExt as _;
662 let handler = Arc::clone(&self.handler);
663 Box::pin(async move {
664 let options = ctx.decode_options().clone();
667 let request_stream: ServiceStream<Req> =
668 Box::pin(requests.map(move |result| {
669 result.and_then(|raw| decode_request(&raw, format, &options))
670 }));
671 let resp = handler.call(ctx, request_stream).await?;
672 Ok(resp.map_body(|s| encode_body_stream(s, format)))
673 })
674 }
675}
676
677pub(crate) fn decode_request_view<ReqView>(
688 request: Bytes,
689 format: CodecFormat,
690 options: &buffa::DecodeOptions,
691) -> Result<OwnedView<ReqView>, ConnectError>
692where
693 ReqView: MessageView<'static> + Send,
694 ReqView::Owned: Message + JsonDeserialize,
695{
696 let body = request_proto_bytes::<ReqView::Owned>(request, format)?;
697 OwnedView::<ReqView>::decode_with_options(body, options).map_err(|e| decode_request_error(&e))
698}
699
700#[doc(hidden)] pub fn request_proto_bytes<Req>(request: Bytes, format: CodecFormat) -> Result<Bytes, ConnectError>
716where
717 Req: Message + JsonDeserialize,
718{
719 match format {
720 CodecFormat::Proto => Ok(request),
721 CodecFormat::Json => {
722 let owned: Req = decode_json(&request[..])?;
723 Ok(Bytes::from(owned.encode_to_vec()))
724 }
725 }
726}
727
728#[doc(hidden)] pub fn decode_borrowed_request_view<'a, ReqView>(
745 body: &'a [u8],
746 options: &buffa::DecodeOptions,
747) -> Result<ReqView, ConnectError>
748where
749 ReqView: MessageView<'a>,
750{
751 options
752 .decode_view(body)
753 .map_err(|e| decode_request_error(&e))
754}
755
756pub trait ViewHandler<ReqView>: Send + Sync + 'static
762where
763 ReqView: MessageView<'static> + Send + Sync + 'static,
764{
765 fn call(
768 &self,
769 ctx: RequestContext,
770 request: OwnedView<ReqView>,
771 format: CodecFormat,
772 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>>;
773}
774
775pub struct FnViewHandler<F> {
777 f: Arc<F>,
778}
779
780impl<F> FnViewHandler<F> {
781 pub fn new(f: F) -> Self {
783 Self { f: Arc::new(f) }
784 }
785}
786
787impl<F, Fut, ReqView> ViewHandler<ReqView> for FnViewHandler<F>
788where
789 F: Fn(RequestContext, OwnedView<ReqView>, CodecFormat) -> Fut + Send + Sync + 'static,
790 Fut: Future<Output = Result<EncodedResponse, ConnectError>> + Send + 'static,
791 ReqView: MessageView<'static> + Send + Sync + 'static,
792{
793 fn call(
794 &self,
795 ctx: RequestContext,
796 request: OwnedView<ReqView>,
797 format: CodecFormat,
798 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>> {
799 let f = Arc::clone(&self.f);
800 Box::pin(async move { f(ctx, request, format).await })
801 }
802}
803
804pub fn view_handler_fn<F, Fut, ReqView>(f: F) -> FnViewHandler<F>
811where
812 F: Fn(RequestContext, OwnedView<ReqView>, CodecFormat) -> Fut + Send + Sync + 'static,
813 Fut: Future<Output = Result<EncodedResponse, ConnectError>> + Send + 'static,
814 ReqView: MessageView<'static> + Send + Sync + 'static,
815{
816 FnViewHandler::new(f)
817}
818
819pub(crate) struct UnaryViewHandlerWrapper<H, ReqView>
821where
822 H: ViewHandler<ReqView>,
823 ReqView: MessageView<'static> + Send + Sync + 'static,
824 ReqView::Owned: Message + JsonDeserialize,
825{
826 handler: Arc<H>,
827 _phantom: std::marker::PhantomData<fn(ReqView)>,
828}
829
830impl<H, ReqView> UnaryViewHandlerWrapper<H, ReqView>
831where
832 H: ViewHandler<ReqView>,
833 ReqView: MessageView<'static> + Send + Sync + 'static,
834 ReqView::Owned: Message + JsonDeserialize,
835{
836 pub fn new(handler: H) -> Self {
837 Self {
838 handler: Arc::new(handler),
839 _phantom: std::marker::PhantomData,
840 }
841 }
842}
843
844impl<H, ReqView> ErasedHandler for UnaryViewHandlerWrapper<H, ReqView>
845where
846 H: ViewHandler<ReqView>,
847 ReqView: MessageView<'static> + Send + Sync + 'static,
848 ReqView::Owned: Message + JsonDeserialize,
849{
850 fn call_erased(
851 &self,
852 ctx: RequestContext,
853 request: crate::Payload,
854 format: CodecFormat,
855 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>> {
856 let handler = Arc::clone(&self.handler);
857 Box::pin(async move {
858 let req =
863 decode_request_view::<ReqView>(request.encoded()?, format, ctx.decode_options())?;
864 handler.call(ctx, req, format).await
865 })
866 }
867
868 fn is_streaming(&self) -> bool {
869 false
870 }
871}
872
873pub trait ViewStreamingHandler<ReqView, Res>: Send + Sync + 'static
875where
876 ReqView: MessageView<'static> + Send + Sync + 'static,
877 Res: Message + Send + 'static,
878{
879 type Item: Encodable<Res> + Send + 'static;
884
885 fn call(
887 &self,
888 ctx: RequestContext,
889 request: OwnedView<ReqView>,
890 ) -> BoxFuture<'static, ServiceResult<ServiceStream<Self::Item>>>;
891}
892
893pub struct FnViewStreamingHandler<F> {
895 f: Arc<F>,
896}
897
898impl<F> FnViewStreamingHandler<F> {
899 pub fn new(f: F) -> Self {
901 Self { f: Arc::new(f) }
902 }
903}
904
905impl<F, Fut, ReqView, Res, B> ViewStreamingHandler<ReqView, Res> for FnViewStreamingHandler<F>
906where
907 F: Fn(RequestContext, OwnedView<ReqView>) -> Fut + Send + Sync + 'static,
908 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
909 ReqView: MessageView<'static> + Send + Sync + 'static,
910 Res: Message + Send + 'static,
911 B: Encodable<Res> + Send + 'static,
912{
913 type Item = B;
914
915 fn call(
916 &self,
917 ctx: RequestContext,
918 request: OwnedView<ReqView>,
919 ) -> BoxFuture<'static, ServiceResult<ServiceStream<B>>> {
920 let f = Arc::clone(&self.f);
921 Box::pin(async move { f(ctx, request).await })
922 }
923}
924
925pub fn view_streaming_handler_fn<F, Fut, ReqView, Res, B>(f: F) -> FnViewStreamingHandler<F>
927where
928 F: Fn(RequestContext, OwnedView<ReqView>) -> Fut + Send + Sync + 'static,
929 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
930 ReqView: MessageView<'static> + Send + Sync + 'static,
931 Res: Message + Send + 'static,
932 B: Encodable<Res> + Send + 'static,
933{
934 FnViewStreamingHandler::new(f)
935}
936
937pub(crate) struct ServerStreamingViewHandlerWrapper<H, ReqView, Res>
939where
940 H: ViewStreamingHandler<ReqView, Res>,
941 ReqView: MessageView<'static> + Send + Sync + 'static,
942 ReqView::Owned: Message + JsonDeserialize,
943 Res: Message + Send + 'static,
944{
945 handler: Arc<H>,
946 _phantom: std::marker::PhantomData<fn(ReqView) -> Res>,
947}
948
949impl<H, ReqView, Res> ServerStreamingViewHandlerWrapper<H, ReqView, Res>
950where
951 H: ViewStreamingHandler<ReqView, Res>,
952 ReqView: MessageView<'static> + Send + Sync + 'static,
953 ReqView::Owned: Message + JsonDeserialize,
954 Res: Message + Send + 'static,
955{
956 pub fn new(handler: H) -> Self {
957 Self {
958 handler: Arc::new(handler),
959 _phantom: std::marker::PhantomData,
960 }
961 }
962}
963
964impl<H, ReqView, Res> ErasedStreamingHandler for ServerStreamingViewHandlerWrapper<H, ReqView, Res>
965where
966 H: ViewStreamingHandler<ReqView, Res>,
967 ReqView: MessageView<'static> + Send + Sync + 'static,
968 ReqView::Owned: Message + JsonDeserialize,
969 Res: Message + Send + 'static,
970{
971 fn call_erased(
972 &self,
973 ctx: RequestContext,
974 request: Bytes,
975 format: CodecFormat,
976 ) -> StreamingHandlerResult {
977 let handler = Arc::clone(&self.handler);
978 Box::pin(async move {
979 let req = decode_request_view::<ReqView>(request, format, ctx.decode_options())?;
980 let resp = handler.call(ctx, req).await?;
981 Ok(resp.map_body(|s| encode_body_stream(s, format)))
982 })
983 }
984}
985
986pub trait ViewClientStreamingHandler<ReqView>: Send + Sync + 'static
990where
991 ReqView: MessageView<'static> + Send + Sync + 'static,
992{
993 fn call(
996 &self,
997 ctx: RequestContext,
998 requests: ServiceStream<OwnedView<ReqView>>,
999 format: CodecFormat,
1000 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>>;
1001}
1002
1003pub struct FnViewClientStreamingHandler<F> {
1005 f: Arc<F>,
1006}
1007
1008impl<F> FnViewClientStreamingHandler<F> {
1009 pub fn new(f: F) -> Self {
1011 Self { f: Arc::new(f) }
1012 }
1013}
1014
1015impl<F, Fut, ReqView> ViewClientStreamingHandler<ReqView> for FnViewClientStreamingHandler<F>
1016where
1017 F: Fn(RequestContext, ServiceStream<OwnedView<ReqView>>, CodecFormat) -> Fut
1018 + Send
1019 + Sync
1020 + 'static,
1021 Fut: Future<Output = Result<EncodedResponse, ConnectError>> + Send + 'static,
1022 ReqView: MessageView<'static> + Send + Sync + 'static,
1023{
1024 fn call(
1025 &self,
1026 ctx: RequestContext,
1027 requests: ServiceStream<OwnedView<ReqView>>,
1028 format: CodecFormat,
1029 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>> {
1030 let f = Arc::clone(&self.f);
1031 Box::pin(async move { f(ctx, requests, format).await })
1032 }
1033}
1034
1035pub fn view_client_streaming_handler_fn<F, Fut, ReqView>(f: F) -> FnViewClientStreamingHandler<F>
1037where
1038 F: Fn(RequestContext, ServiceStream<OwnedView<ReqView>>, CodecFormat) -> Fut
1039 + Send
1040 + Sync
1041 + 'static,
1042 Fut: Future<Output = Result<EncodedResponse, ConnectError>> + Send + 'static,
1043 ReqView: MessageView<'static> + Send + Sync + 'static,
1044{
1045 FnViewClientStreamingHandler::new(f)
1046}
1047
1048pub(crate) struct ClientStreamingViewHandlerWrapper<H, ReqView>
1050where
1051 H: ViewClientStreamingHandler<ReqView>,
1052 ReqView: MessageView<'static> + Send + Sync + 'static,
1053 ReqView::Owned: Message + JsonDeserialize,
1054{
1055 handler: Arc<H>,
1056 _phantom: std::marker::PhantomData<fn(ReqView)>,
1057}
1058
1059impl<H, ReqView> ClientStreamingViewHandlerWrapper<H, ReqView>
1060where
1061 H: ViewClientStreamingHandler<ReqView>,
1062 ReqView: MessageView<'static> + Send + Sync + 'static,
1063 ReqView::Owned: Message + JsonDeserialize,
1064{
1065 pub fn new(handler: H) -> Self {
1066 Self {
1067 handler: Arc::new(handler),
1068 _phantom: std::marker::PhantomData,
1069 }
1070 }
1071}
1072
1073impl<H, ReqView> ErasedClientStreamingHandler for ClientStreamingViewHandlerWrapper<H, ReqView>
1074where
1075 H: ViewClientStreamingHandler<ReqView>,
1076 ReqView: MessageView<'static> + Send + Sync + 'static,
1077 ReqView::Owned: Message + JsonDeserialize,
1078{
1079 fn call_erased(
1080 &self,
1081 ctx: RequestContext,
1082 requests: BoxStream<Result<Bytes, ConnectError>>,
1083 format: CodecFormat,
1084 ) -> BoxFuture<'static, Result<EncodedResponse, ConnectError>> {
1085 use futures::StreamExt as _;
1086 let handler = Arc::clone(&self.handler);
1087 Box::pin(async move {
1088 let options = ctx.decode_options().clone();
1091 let request_stream: ServiceStream<OwnedView<ReqView>> =
1092 Box::pin(requests.map(move |result| {
1093 result.and_then(|raw| decode_request_view::<ReqView>(raw, format, &options))
1094 }));
1095 handler.call(ctx, request_stream, format).await
1096 })
1097 }
1098}
1099
1100pub trait ViewBidiStreamingHandler<ReqView, Res>: Send + Sync + 'static
1102where
1103 ReqView: MessageView<'static> + Send + Sync + 'static,
1104 Res: Message + Send + 'static,
1105{
1106 type Item: Encodable<Res> + Send + 'static;
1111
1112 fn call(
1114 &self,
1115 ctx: RequestContext,
1116 requests: ServiceStream<OwnedView<ReqView>>,
1117 ) -> BoxFuture<'static, ServiceResult<ServiceStream<Self::Item>>>;
1118}
1119
1120pub struct FnViewBidiStreamingHandler<F> {
1122 f: Arc<F>,
1123}
1124
1125impl<F> FnViewBidiStreamingHandler<F> {
1126 pub fn new(f: F) -> Self {
1128 Self { f: Arc::new(f) }
1129 }
1130}
1131
1132impl<F, Fut, ReqView, Res, B> ViewBidiStreamingHandler<ReqView, Res>
1133 for FnViewBidiStreamingHandler<F>
1134where
1135 F: Fn(RequestContext, ServiceStream<OwnedView<ReqView>>) -> Fut + Send + Sync + 'static,
1136 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
1137 ReqView: MessageView<'static> + Send + Sync + 'static,
1138 Res: Message + Send + 'static,
1139 B: Encodable<Res> + Send + 'static,
1140{
1141 type Item = B;
1142
1143 fn call(
1144 &self,
1145 ctx: RequestContext,
1146 requests: ServiceStream<OwnedView<ReqView>>,
1147 ) -> BoxFuture<'static, ServiceResult<ServiceStream<B>>> {
1148 let f = Arc::clone(&self.f);
1149 Box::pin(async move { f(ctx, requests).await })
1150 }
1151}
1152
1153pub fn view_bidi_streaming_handler_fn<F, Fut, ReqView, Res, B>(
1155 f: F,
1156) -> FnViewBidiStreamingHandler<F>
1157where
1158 F: Fn(RequestContext, ServiceStream<OwnedView<ReqView>>) -> Fut + Send + Sync + 'static,
1159 Fut: Future<Output = ServiceResult<ServiceStream<B>>> + Send + 'static,
1160 ReqView: MessageView<'static> + Send + Sync + 'static,
1161 Res: Message + Send + 'static,
1162 B: Encodable<Res> + Send + 'static,
1163{
1164 FnViewBidiStreamingHandler::new(f)
1165}
1166
1167pub(crate) struct BidiStreamingViewHandlerWrapper<H, ReqView, Res>
1169where
1170 H: ViewBidiStreamingHandler<ReqView, Res>,
1171 ReqView: MessageView<'static> + Send + Sync + 'static,
1172 ReqView::Owned: Message + JsonDeserialize,
1173 Res: Message + Send + 'static,
1174{
1175 handler: Arc<H>,
1176 _phantom: std::marker::PhantomData<fn(ReqView) -> Res>,
1177}
1178
1179impl<H, ReqView, Res> BidiStreamingViewHandlerWrapper<H, ReqView, Res>
1180where
1181 H: ViewBidiStreamingHandler<ReqView, Res>,
1182 ReqView: MessageView<'static> + Send + Sync + 'static,
1183 ReqView::Owned: Message + JsonDeserialize,
1184 Res: Message + Send + 'static,
1185{
1186 pub fn new(handler: H) -> Self {
1187 Self {
1188 handler: Arc::new(handler),
1189 _phantom: std::marker::PhantomData,
1190 }
1191 }
1192}
1193
1194impl<H, ReqView, Res> ErasedBidiStreamingHandler
1195 for BidiStreamingViewHandlerWrapper<H, ReqView, Res>
1196where
1197 H: ViewBidiStreamingHandler<ReqView, Res>,
1198 ReqView: MessageView<'static> + Send + Sync + 'static,
1199 ReqView::Owned: Message + JsonDeserialize,
1200 Res: Message + Send + 'static,
1201{
1202 fn call_erased(
1203 &self,
1204 ctx: RequestContext,
1205 requests: BoxStream<Result<Bytes, ConnectError>>,
1206 format: CodecFormat,
1207 ) -> StreamingHandlerResult {
1208 use futures::StreamExt as _;
1209 let handler = Arc::clone(&self.handler);
1210 Box::pin(async move {
1211 let options = ctx.decode_options().clone();
1214 let request_stream: ServiceStream<OwnedView<ReqView>> =
1215 Box::pin(requests.map(move |result| {
1216 result.and_then(|raw| decode_request_view::<ReqView>(raw, format, &options))
1217 }));
1218 let resp = handler.call(ctx, request_stream).await?;
1219 Ok(resp.map_body(|s| encode_body_stream(s, format)))
1220 })
1221 }
1222}
1223
1224#[cfg(test)]
1225mod tests {
1226 use super::*;
1227 use crate::test_budget::elements_over_default_budget;
1228 use buffa_types::google::protobuf::__buffa::view::StringValueView;
1229 use buffa_types::google::protobuf::StringValue;
1230
1231 #[test]
1232 fn test_decode_request_proto() {
1233 let msg = StringValue::from("hello");
1234 let encoded = Bytes::from(msg.encode_to_vec());
1235 let decoded: StringValue =
1236 decode_request(&encoded, CodecFormat::Proto, &buffa::DecodeOptions::new()).unwrap();
1237 assert_eq!(decoded.value, "hello");
1238 }
1239
1240 #[cfg(feature = "json")]
1241 #[test]
1242 fn test_decode_request_json() {
1243 let encoded = Bytes::from_static(b"\"world\"");
1244 let decoded: StringValue =
1245 decode_request(&encoded, CodecFormat::Json, &buffa::DecodeOptions::new()).unwrap();
1246 assert_eq!(decoded.value, "world");
1247 }
1248
1249 #[test]
1250 fn test_decode_request_proto_invalid() {
1251 let garbage = Bytes::from_static(&[0xFF, 0xFF, 0xFF]);
1252 let err = decode_request::<StringValue>(
1253 &garbage,
1254 CodecFormat::Proto,
1255 &buffa::DecodeOptions::new(),
1256 )
1257 .unwrap_err();
1258 assert_eq!(err.code, crate::error::ErrorCode::InvalidArgument);
1259 }
1260
1261 #[cfg(feature = "json")]
1262 #[test]
1263 fn test_decode_request_json_invalid() {
1264 let garbage = Bytes::from_static(b"not json");
1265 let err = decode_request::<StringValue>(
1266 &garbage,
1267 CodecFormat::Json,
1268 &buffa::DecodeOptions::new(),
1269 )
1270 .unwrap_err();
1271 assert_eq!(err.code, crate::error::ErrorCode::InvalidArgument);
1272 }
1273
1274 #[test]
1275 fn overflow_payload_is_invalid_argument_at_decode_boundary() {
1276 let body = crate::request::tests::unknown_field_overflow_body();
1281 let err = decode_request_view::<StringValueView<'static>>(
1282 body,
1283 CodecFormat::Proto,
1284 &buffa::DecodeOptions::new(),
1285 )
1286 .unwrap_err();
1287 assert_eq!(err.code, crate::error::ErrorCode::InvalidArgument);
1288 }
1289
1290 #[test]
1291 fn test_decode_request_view_proto() {
1292 let msg = StringValue::from("view-test");
1293 let encoded = Bytes::from(msg.encode_to_vec());
1294 let view = decode_request_view::<StringValueView>(
1295 encoded,
1296 CodecFormat::Proto,
1297 &buffa::DecodeOptions::new(),
1298 )
1299 .unwrap();
1300 assert_eq!(view.reborrow().value, "view-test");
1301 }
1302
1303 #[cfg(feature = "json")]
1304 #[test]
1305 fn test_decode_request_view_json() {
1306 let encoded = Bytes::from_static(b"\"json-view\"");
1307 let view = decode_request_view::<StringValueView>(
1308 encoded,
1309 CodecFormat::Json,
1310 &buffa::DecodeOptions::new(),
1311 )
1312 .unwrap();
1313 assert_eq!(view.reborrow().value, "json-view");
1314 }
1315
1316 #[cfg(not(feature = "json"))]
1322 #[test]
1323 fn decode_request_json_is_unimplemented_without_feature() {
1324 let body = Bytes::from_static(b"\"world\"");
1325 let err =
1326 decode_request::<StringValue>(&body, CodecFormat::Json, &buffa::DecodeOptions::new())
1327 .unwrap_err();
1328 assert_eq!(err.code, crate::error::ErrorCode::Unimplemented);
1329 }
1330
1331 #[cfg(not(feature = "json"))]
1332 #[test]
1333 fn decode_request_view_json_is_unimplemented_without_feature() {
1334 let body = Bytes::from_static(b"\"world\"");
1335 let err = decode_request_view::<StringValueView>(
1336 body,
1337 CodecFormat::Json,
1338 &buffa::DecodeOptions::new(),
1339 )
1340 .unwrap_err();
1341 assert_eq!(err.code, crate::error::ErrorCode::Unimplemented);
1342 }
1343
1344 #[test]
1345 fn test_decode_request_view_proto_invalid() {
1346 let garbage = Bytes::from_static(&[0xFF, 0xFF, 0xFF]);
1347 let err = decode_request_view::<StringValueView>(
1348 garbage,
1349 CodecFormat::Proto,
1350 &buffa::DecodeOptions::new(),
1351 )
1352 .unwrap_err();
1353 assert_eq!(err.code, crate::error::ErrorCode::InvalidArgument);
1354 }
1355
1356 #[tokio::test]
1357 async fn encode_body_stream_owned_items() {
1358 use futures::StreamExt as _;
1359 let s = futures::stream::iter([
1360 Ok(StringValue::from("a")),
1361 Ok(StringValue::from("b")),
1362 Err(ConnectError::internal("boom")),
1363 ]);
1364 let mut out = encode_body_stream::<StringValue, _, _>(s, CodecFormat::Proto);
1365 let a = out.next().await.unwrap().unwrap();
1366 let b = out.next().await.unwrap().unwrap();
1367 assert_eq!(StringValue::decode_from_slice(&a).unwrap().value, "a");
1368 assert_eq!(StringValue::decode_from_slice(&b).unwrap().value, "b");
1369 assert!(out.next().await.unwrap().is_err());
1370 assert!(out.next().await.is_none());
1371 }
1372
1373 #[tokio::test]
1374 async fn encode_body_stream_pre_encoded_items() {
1375 use crate::PreEncoded;
1376 use futures::StreamExt as _;
1377 let bytes_a = StringValue::from("a").encode_to_bytes();
1381 let bytes_b = StringValue::from("b").encode_to_bytes();
1382 let s = futures::stream::iter([
1383 Ok(PreEncoded::<StringValue>::from_bytes_unchecked(
1384 bytes_a.clone(),
1385 )),
1386 Ok(PreEncoded::<StringValue>::from_bytes_unchecked(
1387 bytes_b.clone(),
1388 )),
1389 ]);
1390 let mut out =
1391 encode_body_stream::<StringValue, PreEncoded<StringValue>, _>(s, CodecFormat::Proto);
1392 assert_eq!(out.next().await.unwrap().unwrap(), bytes_a);
1393 assert_eq!(out.next().await.unwrap().unwrap(), bytes_b);
1394 assert!(out.next().await.is_none());
1395 }
1396
1397 #[cfg(feature = "json")]
1398 #[tokio::test]
1399 async fn encode_body_stream_pre_encoded_json_decodes_per_item() {
1400 use crate::PreEncoded;
1401 use futures::StreamExt as _;
1402 let m_a = StringValue::from("a");
1406 let m_b = StringValue::from("b");
1407 let s = futures::stream::iter([
1408 Ok(PreEncoded::<StringValue>::from_bytes_unchecked(
1409 m_a.encode_to_bytes(),
1410 )),
1411 Ok(PreEncoded::<StringValue>::from_bytes_unchecked(
1412 m_b.encode_to_bytes(),
1413 )),
1414 ]);
1415 let mut out =
1416 encode_body_stream::<StringValue, PreEncoded<StringValue>, _>(s, CodecFormat::Json);
1417 assert_eq!(
1418 out.next().await.unwrap().unwrap(),
1419 Bytes::from(serde_json::to_vec(&m_a).unwrap())
1420 );
1421 assert_eq!(
1422 out.next().await.unwrap().unwrap(),
1423 Bytes::from(serde_json::to_vec(&m_b).unwrap())
1424 );
1425 assert!(out.next().await.is_none());
1426 }
1427
1428 #[test]
1429 fn streaming_handler_item_is_inferred_from_closure() {
1430 use crate::PreEncoded;
1435
1436 fn assert_handler<H, Req, Res, B>(_: &H)
1437 where
1438 H: StreamingHandler<Req, Res, Item = B>,
1439 Req: Message + Send + 'static,
1440 Res: Message + Send + 'static,
1441 B: Encodable<Res> + Send + 'static,
1442 {
1443 }
1444
1445 let owned = streaming_handler_fn(|_ctx: RequestContext, _req: StringValue| async move {
1446 Response::stream_ok(futures::stream::iter([Ok(StringValue::from("x"))]))
1447 });
1448 assert_handler::<_, StringValue, StringValue, StringValue>(&owned);
1449
1450 let pre = streaming_handler_fn(|_ctx: RequestContext, _req: StringValue| async move {
1457 Response::stream_ok(futures::stream::iter([Ok(
1458 PreEncoded::<StringValue>::from_bytes_unchecked(
1459 StringValue::from("x").encode_to_bytes(),
1460 ),
1461 )]))
1462 });
1463 assert_handler::<_, StringValue, StringValue, PreEncoded<StringValue>>(&pre);
1464 }
1465
1466 #[test]
1472 fn owned_message_decoding_honours_the_configured_limit() {
1473 use buffa_types::google::protobuf::{ListValue, Value};
1474
1475 let n = elements_over_default_budget::<Value>();
1477 let list = ListValue {
1478 values: (0..n).map(|_| Value::default()).collect(),
1479 ..Default::default()
1480 };
1481 let encoded = Bytes::from(buffa::Message::encode_to_vec(&list));
1482 let raised = crate::Limits::default().element_memory_limit(usize::MAX);
1483
1484 assert!(
1486 decode_request::<ListValue>(
1487 &encoded,
1488 CodecFormat::Proto,
1489 &crate::Limits::default().decode_options()
1490 )
1491 .is_err(),
1492 "the default budget must still reject"
1493 );
1494 let decoded: ListValue =
1495 decode_request(&encoded, CodecFormat::Proto, &raised.decode_options())
1496 .expect("raised budget must admit");
1497 assert_eq!(decoded.values.len(), n);
1498
1499 let payload = crate::Payload::new(encoded.clone(), CodecFormat::Proto);
1501 assert!(
1502 payload.take_message::<ListValue>().is_err(),
1503 "a payload with no limits attached decodes under buffa defaults"
1504 );
1505 let payload = crate::Payload::new(encoded, CodecFormat::Proto)
1506 .with_decode_options(raised.decode_options());
1507 let decoded: ListValue = payload
1508 .take_message()
1509 .expect("a payload carrying raised limits must admit");
1510 assert_eq!(decoded.values.len(), n);
1511 }
1512
1513 #[test]
1516 fn an_over_budget_decode_says_which_limit_to_raise() {
1517 use buffa_types::google::protobuf::__buffa::view::{ListValueView, ValueView};
1518 use buffa_types::google::protobuf::{ListValue, Value};
1519
1520 let list = ListValue {
1523 values: (0..elements_over_default_budget::<ValueView<'_>>())
1524 .map(|_| Value::default())
1525 .collect(),
1526 ..Default::default()
1527 };
1528 let encoded = Bytes::from(buffa::Message::encode_to_vec(&list));
1529 let err = decode_borrowed_request_view::<ListValueView<'_>>(
1530 &encoded,
1531 &crate::Limits::default().decode_options(),
1532 )
1533 .expect_err("over budget");
1534 let message = err.message.unwrap_or_default();
1535 assert!(
1536 message.contains("element_memory_limit"),
1537 "the budget rejection must name the knob, got {message:?}"
1538 );
1539
1540 let garbage = Bytes::from_static(&[0xFF, 0xFF, 0xFF]);
1543 let err = decode_borrowed_request_view::<ListValueView<'_>>(
1544 &garbage,
1545 &crate::Limits::default().decode_options(),
1546 )
1547 .expect_err("malformed");
1548 let message = err.message.unwrap_or_default();
1549 assert!(
1550 !message.contains("element_memory_limit"),
1551 "a malformed request must not point at a limit, got {message:?}"
1552 );
1553 }
1554
1555 #[test]
1560 fn element_memory_limit_is_taken_from_the_configured_limits() {
1561 use buffa_types::google::protobuf::__buffa::view::{ListValueView, ValueView};
1562 use buffa_types::google::protobuf::{ListValue, Value};
1563
1564 let n = elements_over_default_budget::<ValueView<'_>>();
1567 let list = ListValue {
1568 values: (0..n).map(|_| Value::default()).collect(),
1569 ..Default::default()
1570 };
1571 let encoded = Bytes::from(buffa::Message::encode_to_vec(&list));
1572
1573 let defaults = crate::Limits::default();
1574 let err =
1575 decode_borrowed_request_view::<ListValueView<'_>>(&encoded, &defaults.decode_options())
1576 .expect_err("the fixture must exceed the default element-memory budget");
1577 assert_eq!(err.code, crate::error::ErrorCode::InvalidArgument);
1578
1579 let raised = crate::Limits::default().element_memory_limit(usize::MAX);
1580 let view =
1581 decode_borrowed_request_view::<ListValueView<'_>>(&encoded, &raised.decode_options())
1582 .expect("raising the limit must admit the same bytes");
1583 assert_eq!(view.values.len(), n);
1584 }
1585
1586 #[test]
1590 fn unlimited_limits_lift_the_element_budget() {
1591 assert_eq!(crate::Limits::unlimited().element_memory_limit, usize::MAX);
1592 }
1593
1594 #[test]
1597 fn a_bare_request_context_decodes_under_buffa_defaults() {
1598 let ctx = RequestContext::new(http::HeaderMap::new());
1599 let listing = format!("{:?}", ctx.decode_options());
1600 assert!(
1601 listing.contains(&buffa::DEFAULT_ELEMENT_MEMORY_LIMIT.to_string()),
1602 "expected buffa's default element-memory budget, got {listing}"
1603 );
1604 }
1605}