opencomputers_stem/
lib.rs1#![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}