Skip to main content

zestors_request/
into_recv.rs

1use crate::*;
2use futures::Future;
3use std::pin::Pin;
4use zestors_core::{
5    error::{SendError, TrySendError},
6    messaging::Message,
7    process::SendFut,
8};
9
10/// Trait that makes it easier to await a reply from a [Request].
11pub trait IntoRecv {
12    type Receives;
13
14    /// Wait for the reply of a request.
15    fn into_recv(self) -> Self::Receives;
16}
17
18impl<M, R> IntoRecv for Result<Rx<R>, SendError<M>>
19where
20    M: Send + 'static,
21    R: Send + 'static,
22{
23    type Receives = Pin<Box<dyn Future<Output = Result<R, SendRecvError<M>>> + Send + 'static>>;
24
25    fn into_recv(self) -> Self::Receives {
26        Box::pin(async move {
27            match self {
28                Ok(rx) => match rx.await {
29                    Ok(msg) => Ok(msg),
30                    Err(_) => Err(SendRecvError::NoReply),
31                },
32                Err(SendError(msg)) => Err(SendRecvError::Closed(msg)),
33            }
34        })
35    }
36}
37
38impl<'a, M, R> IntoRecv for SendFut<'a, M>
39where
40    M: Message<Type = Request<R>> + Send + 'a,
41    R: Send + 'a,
42{
43    type Receives = Pin<Box<dyn Future<Output = Result<R, SendRecvError<M>>> + Send + 'a>>;
44
45    fn into_recv(self) -> Self::Receives {
46        Box::pin(async move {
47            match self.await {
48                Ok(rx) => match rx.await {
49                    Ok(msg) => Ok(msg),
50                    Err(_) => Err(SendRecvError::NoReply),
51                },
52                Err(SendError(msg)) => Err(SendRecvError::Closed(msg)),
53            }
54        })
55    }
56}
57
58impl<M, R> IntoRecv for Result<Rx<R>, TrySendError<M>>
59where
60    M: Send + 'static,
61    R: Send + 'static,
62{
63    type Receives = Pin<Box<dyn Future<Output = Result<R, TrySendRecvError<M>>> + Send + 'static>>;
64
65    fn into_recv(self) -> Self::Receives {
66        Box::pin(async move {
67            match self {
68                Ok(rx) => match rx.await {
69                    Ok(msg) => Ok(msg),
70                    Err(_) => Err(TrySendRecvError::NoReply),
71                },
72                Err(e) => match e {
73                    TrySendError::Closed(msg) => Err(TrySendRecvError::Closed(msg)),
74                    TrySendError::Full(msg) => Err(TrySendRecvError::Full(msg)),
75                },
76            }
77        })
78    }
79}
80
81/// Error returned when using the [IntoRecv] trait.
82///
83/// This error combines failures in sending and receiving.
84#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)]
85pub enum SendRecvError<M> {
86    NoReply,
87    Closed(M),
88}
89
90/// Error returned when using the [IntoRecv] trait.
91///
92/// This error combines failures in sending and receiving.
93#[derive(Debug, thiserror::Error, Clone, Copy, PartialEq, Eq)]
94pub enum TrySendRecvError<M> {
95    NoReply,
96    Closed(M),
97    Full(M),
98}