net_stream/client/
actor_handle.rs

1//! Client actor task handle.
2
3use super::actor::Message;
4use crate::message_types::MessageTypes;
5use assert_let_bind::assert_let;
6use futures::channel::mpsc;
7use std::sync::Arc;
8use tokio::task::JoinHandle;
9
10/// Handle to the client actor task.
11#[derive(Debug, Clone)]
12pub struct ActorHandle<M: MessageTypes> {
13    sender: mpsc::Sender<Message<M>>,
14    _join_handle: Arc<JoinHandle<()>>,
15}
16
17/// Error communicating message to actor. The message is returned.
18#[derive(thiserror::Error, Debug)]
19pub enum Error<M> {
20    /// Actor cannot keep up, channel is currently full.
21    #[error("Actor cannot keep up, channel is currently full.")]
22    ChannelFull(M),
23
24    /// Actor is unreachable - channel is disconnected.
25    #[error("Actor is unreachable, channel disconnected.")]
26    ActorUnreachable(M),
27}
28
29impl<M> ActorHandle<M>
30where
31    M: MessageTypes,
32{
33    /// Create new actor handle.
34    pub(crate) fn new(join_handle: JoinHandle<()>, sender: mpsc::Sender<Message<M>>) -> ActorHandle<M> {
35        Self {
36            _join_handle: Arc::new(join_handle),
37            sender,
38        }
39    }
40
41    /// Send message to server on TCP.
42    pub fn send_message_tcp(&mut self, msg: M::TcpToServer) -> Result<(), Error<M::TcpToServer>> {
43        self.sender.try_send(Message::ToServerTcp { msg }).map_err(|err| {
44            if err.is_full() {
45                assert_let!(Message::ToServerTcp { msg }, err.into_inner());
46                Error::ChannelFull(msg)
47            } else if err.is_disconnected() {
48                assert_let!(Message::ToServerTcp { msg }, err.into_inner());
49                Error::ActorUnreachable(msg)
50            } else {
51                unreachable!()
52            }
53        })
54    }
55
56    /// Send message to server on UDP (lossy).
57    pub fn send_message_udp(&mut self, msg: M::UdpToServer) -> Result<(), Error<M::UdpToServer>> {
58        self.sender.try_send(Message::ToServerUdp { msg }).map_err(|err| {
59            if err.is_full() {
60                assert_let!(Message::ToServerUdp { msg }, err.into_inner());
61                Error::ChannelFull(msg)
62            } else if err.is_disconnected() {
63                assert_let!(Message::ToServerUdp { msg }, err.into_inner());
64                Error::ActorUnreachable(msg)
65            } else {
66                unreachable!()
67            }
68        })
69    }
70
71    /// Get status
72    pub async fn get_status(&mut self) -> Result<crate::client::Status, Error<()>> {
73        let (tx, rx) = futures::channel::oneshot::channel();
74        self.sender.try_send(Message::GetStatus { tx }).map_err(|err| {
75            if err.is_full() {
76                Error::ChannelFull(())
77            } else if err.is_disconnected() {
78                Error::ActorUnreachable(())
79            } else {
80                unreachable!()
81            }
82        })?;
83
84        let status = rx.await.expect("Expected response from actor");
85        Ok(status)
86    }
87}