opencomputers_stem/
lib.rs

1#![allow(dead_code)]
2#![allow(unused_variables)]
3
4
5use tokio::net::{TcpStream, ToSocketAddrs, tcp::OwnedReadHalf, tcp::OwnedWriteHalf};
6use tokio_util::codec::{Framed, FramedRead, FramedWrite, Decoder, Encoder};
7use bytes::{BufMut, BytesMut, Buf};
8
9
10mod default_server;
11
12
13pub struct Stem {
14    stream: TcpStream
15}
16
17impl Stem {
18    pub async fn new<T: ToSocketAddrs>(addr: T) -> std::io::Result<Stem> {
19        Ok(Stem {
20            stream: TcpStream::connect(addr).await?
21        })
22    }
23    pub async fn with_server() -> std::io::Result<Stem> {
24        Ok(Stem {
25            stream: TcpStream::connect(default_server::DEFAULT_SERVER).await?
26        })
27    }
28
29    pub fn framed_split(self) -> (FramedRead<OwnedReadHalf, StemCodec>, FramedWrite<OwnedWriteHalf, StemCodec>) {
30        let (read, write) = self.stream.into_split();
31        (FramedRead::new(read, StemCodec), FramedWrite::new(write, StemCodec))
32    }
33
34    pub fn framed(self) -> Framed<TcpStream, StemCodec> {
35        Framed::new(self.stream, StemCodec {})
36    }
37}
38
39pub struct StemCodec;
40
41impl Decoder for StemCodec {
42
43    type Item = StemPacket;
44    type Error = std::io::Error;
45
46    fn decode(&mut self, src: &mut bytes::BytesMut) -> Result<Option<Self::Item>, Self::Error> {
47        if src.len() < 2 {
48            return Ok(None)
49        }
50        let size = src.get_u16();
51        let id = src.get_u8();
52        match id {
53            0x00 => {
54                let channel_len = src.get_u8();
55
56                let mut buf = vec![0; channel_len as usize];
57                src.copy_to_slice(buf.as_mut_slice());
58                let channel = String::from_utf8(buf).unwrap();
59
60                let mut buf = vec![0; (size - 3 - channel_len as u16) as usize];
61                src.copy_to_slice(buf.as_mut_slice());
62                let message = String::from_utf8(buf).unwrap();
63
64                Ok(Some(StemPacket::Message(channel, message)))
65            }
66            0x01 | 0x02 => {
67                let channel_len = src.get_u8();
68
69                let mut buf = vec![0; channel_len as usize];
70                src.copy_to_slice(buf.as_mut_slice());
71                let channel = String::from_utf8(buf).unwrap();
72
73                if id == 0x01 {
74                    Ok(Some(StemPacket::Sub(channel)))
75                } else {
76                    Ok(Some(StemPacket::UnSub(channel)))
77                }
78            }
79            0x03 | 0x04 => {
80                let mut buf = vec![0; usize::from(size - 1)];
81                src.copy_to_slice(buf.as_mut_slice());
82                if id == 0x03 {
83                    Ok(Some(StemPacket::Ping(buf)))
84                } else {
85                    Ok(Some(StemPacket::Pong(buf)))
86                }
87            }
88            _ => {
89                Ok(Some(StemPacket::Unknown))
90            }
91        }
92    }
93    
94}
95
96impl Encoder<StemPacket> for StemCodec {
97
98    type Error = std::io::Error;
99
100    fn encode(&mut self, item: StemPacket, dst: &mut BytesMut) -> Result<(), Self::Error> {
101        match item {
102            StemPacket::Message(channel, message) => {
103                let size = 2 + channel.len() + message.len();
104                dst.put_u16(size as u16);
105                dst.put_u8(0x00);
106                dst.put_u8(channel.len() as u8);
107                dst.put_slice(channel.as_bytes());
108                dst.put_slice(message.as_bytes());
109            }
110            StemPacket::Sub(channel) => {
111                let size = 2 + channel.len();
112                dst.put_u16(size as u16);
113                dst.put_u8(0x01);
114                dst.put_u8(channel.len() as u8);
115                dst.put_slice(channel.as_bytes());
116            }
117            StemPacket::UnSub(channel) => {
118                let size = 2 + channel.len();
119                dst.put_u16(size as u16);
120                dst.put_u8(0x02);
121                dst.put_u8(channel.len() as u8);
122                dst.put_slice(channel.as_bytes());
123            }
124            StemPacket::Ping(data) => {
125                let size = 1 + data.len();
126                dst.put_u16(size as u16);
127                dst.put_u8(0x03);
128                dst.put_slice(data.as_slice());
129            }
130            StemPacket::Pong(data) => {
131                let size = 1 + data.len();
132                dst.put_u16(size as u16);
133                dst.put_u8(0x03);
134                dst.put_slice(data.as_slice());
135            }
136            _ => {}
137        }
138        Ok(())
139    }
140
141}
142
143#[derive(Debug)]
144pub enum StemPacket {
145    Message(String, String),
146    Sub(String),
147    UnSub(String),
148    Ping(Vec<u8>),
149    Pong(Vec<u8>),
150    Unknown
151}