enet_client/
conn.rs

1use crate::enc::{EnetDecoder, EnetDecoderError, EnetEncoder, EnetEncoderError};
2use enet_proto::{RequestEnvelope, Response};
3use futures::{SinkExt, StreamExt};
4use thiserror::Error;
5use tokio::{
6  io,
7  net::{
8    tcp::{OwnedReadHalf, OwnedWriteHalf},
9    TcpStream, ToSocketAddrs,
10  },
11};
12use tokio_util::codec::{FramedRead, FramedWrite};
13use tracing::instrument;
14
15pub(crate) struct Connection {
16  reader: FramedRead<OwnedReadHalf, EnetDecoder>,
17  writer: FramedWrite<OwnedWriteHalf, EnetEncoder>,
18}
19
20impl Connection {
21  pub(crate) async fn new(addr: impl ToSocketAddrs) -> Result<Self, ConnectError> {
22    let stream = TcpStream::connect(addr).await?;
23    let (reader, writer) = stream.into_split();
24
25    Ok(Self {
26      reader: FramedRead::new(reader, EnetDecoder::new()),
27      writer: FramedWrite::new(writer, EnetEncoder::new()),
28    })
29  }
30
31  #[instrument(level = "debug", target = "enet-client::con", skip(self, message), err)]
32  pub(crate) async fn send(&mut self, message: &RequestEnvelope) -> Result<(), SendError> {
33    Ok(self.writer.send(message).await?)
34  }
35
36  #[instrument(level = "debug", target = "enet-client::con", skip(self), err)]
37  pub(crate) async fn recv(&mut self) -> Result<Response, RecvError> {
38    match self.reader.next().await {
39      Some(result) => Ok(result?),
40      None => bail!(ConnectionClosed),
41    }
42  }
43}
44
45#[non_exhaustive]
46#[derive(Debug, Error)]
47#[error("Failed to connect to gateway.")]
48pub enum ConnectError {
49  FailedToConnect(#[from] io::Error),
50}
51
52#[non_exhaustive]
53#[derive(Debug, Error)]
54#[error("Failed to send message.")]
55pub enum SendError {
56  FailedToSend(#[from] EnetEncoderError),
57}
58
59#[non_exhaustive]
60#[derive(Debug, Error)]
61#[error("Failed to receive response.")]
62pub enum RecvError {
63  DecoderError(#[from] EnetDecoderError),
64
65  Closed(#[from] ConnectionClosed),
66}
67
68#[derive(Debug, Error)]
69#[error("Connection closed.")]
70pub struct ConnectionClosed;