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;