1use std::future::Future;
2
3use mm1_address::address::Address;
4use mm1_common::errors::error_of::ErrorOf;
5use mm1_common::impl_error_kind;
6use mm1_proto::Message;
7
8use crate::context::{Fork, ForkErrorKind, Recv, RecvErrorKind, Tell, TellErrorKind};
9use crate::envelope::Envelope;
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12pub enum AskErrorKind {
13 Fork(ForkErrorKind),
14 Tell(TellErrorKind),
15 Recv(RecvErrorKind),
16}
17
18pub trait Ask: Tell + Fork + Recv {
19 fn ask<Req>(
20 &mut self,
21 to: Address,
22 make_request: impl FnOnce(Address) -> Req + Send,
23 ) -> impl Future<Output = Result<Envelope, ErrorOf<AskErrorKind>>> + Send
24 where
25 Req: Message,
26 {
27 async move {
28 let mut forked = self
29 .fork()
30 .await
31 .map_err(|e| e.map_kind(AskErrorKind::Fork))?;
32
33 let reply_to = forked.address();
34 let request = make_request(reply_to);
35 self.tell(to, request)
36 .await
37 .map_err(|e| e.map_kind(AskErrorKind::Tell))?;
38
39 let inbound = forked
40 .recv()
41 .await
42 .map_err(|e| e.map_kind(AskErrorKind::Recv))?;
43
44 Ok(inbound)
45 }
46 }
47}
48
49impl_error_kind!(AskErrorKind);
50
51impl<T> Ask for T where T: Tell + Fork + Recv {}