1extern crate self as ts3;
58
59mod client;
60pub mod event;
61pub mod request;
62pub mod response;
63pub mod shared;
64mod types;
65
66pub use async_trait::async_trait;
67pub use client::Client;
68pub use ts3_derive::Decode;
69
70use std::{
71 convert::{Infallible, TryFrom},
72 fmt::{Debug, Write},
73 io,
74 num::ParseIntError,
75 str::{from_utf8, Utf8Error},
76};
77
78use thiserror::Error;
79
80#[derive(Debug, Error)]
82#[error(transparent)]
83pub struct Error(ErrorKind);
84
85impl From<Infallible> for Error {
86 fn from(value: Infallible) -> Self {
87 match value {}
88 }
89}
90
91#[derive(Debug, Error)]
92enum ErrorKind {
93 #[error("TS3 error {id}: {msg}")]
95 TS3 { id: u16, msg: String },
96 #[error("io: {0}")]
98 Io(#[from] io::Error),
99 #[error("failed to decode stream: {0}")]
101 Decode(#[from] DecodeError),
102 #[error("failed to parse integer: {0}")]
103 ParseInt(#[from] ParseIntError),
104 #[error("recevied invalid utf8: {0}")]
105 Utf8(#[from] Utf8Error),
106 #[error("send error")]
107 SendError,
108 #[error("no field")]
109 NoField,
110}
111
112#[derive(Debug, Error)]
113enum DecodeError {
114 #[error("unexpected eof")]
115 UnexpectedEof,
116 #[error("unexpected byte: {0}")]
117 UnexpectedByte(u8),
118 #[error("invalid reasonid: {0}")]
119 InvalidReasonId(u8),
120 #[error("invalid apikey scope: {0}")]
121 InvalidApiKeyScope(String),
122}
123
124pub trait Decode: Sized {
127 type Error: std::error::Error;
128
129 fn decode(buf: &[u8]) -> Result<Self, Self::Error>;
130}
131
132pub trait Encode {
133 fn encode(&self, buf: &mut String);
134}
135
136macro_rules! impl_serialize {
138 ($t:ty) => {
139 impl crate::Encode for $t {
140 fn encode(&self, writer: &mut ::std::string::String) {
141 write!(writer, "{}", self).unwrap();
142 }
143 }
144 };
145}
146
147macro_rules! impl_decode {
149 ($t:ty) => {
150 impl Decode for $t {
151 type Error = Error;
152
153 fn decode(buf: &[u8]) -> std::result::Result<$t, Self::Error> {
154 Ok(from_utf8(buf)
155 .map_err(|e| Error(ErrorKind::Utf8(e)))?
156 .parse()
157 .map_err(|e| Error(ErrorKind::ParseInt(e)))?)
158 }
159 }
160 };
161}
162
163impl Decode for () {
166 type Error = Infallible;
167
168 fn decode(_: &[u8]) -> Result<(), Self::Error> {
169 Ok(())
170 }
171}
172
173impl Decode for String {
175 type Error = Error;
176
177 fn decode(buf: &[u8]) -> Result<String, Self::Error> {
178 let mut string = String::with_capacity(buf.len());
181
182 let mut iter = buf.into_iter().peekable();
185 while let Some(b) = iter.next() {
186 match b {
187 b'\\' => {
189 match iter.peek() {
190 Some(c) => match c {
191 b'\\' => string.push('\\'),
192 b'/' => string.push('/'),
193 b's' => string.push(' '),
194 b'p' => string.push('|'),
195 b'a' => string.push(7u8 as char),
196 b'b' => string.push(8u8 as char),
197 b'f' => string.push(12u8 as char),
198 b'n' => string.push(10u8 as char),
199 b'r' => string.push(13u8 as char),
200 b't' => string.push(9u8 as char),
201 b'v' => string.push(11u8 as char),
202 _ => {
203 return Err(Error(ErrorKind::Decode(DecodeError::UnexpectedByte(
204 **c,
205 ))))
206 }
207 },
208 None => {
209 return Err(Error(ErrorKind::Decode(DecodeError::UnexpectedEof.into())))
210 }
211 }
212 iter.next();
213 }
214 _ => string.push(char::try_from(*b).unwrap()),
215 }
216 }
217
218 string.shrink_to_fit();
220 Ok(string)
221 }
222}
223
224impl Encode for &str {
225 fn encode(&self, writer: &mut String) {
226 for c in self.chars() {
227 match c {
228 '\\' => writer.write_str("\\\\").unwrap(),
229 '/' => writer.write_str("\\/").unwrap(),
230 ' ' => writer.write_str("\\s").unwrap(),
231 '|' => writer.write_str("\\p").unwrap(),
232 c if c == 7u8 as char => writer.write_str("\\a").unwrap(),
233 c if c == 8u8 as char => writer.write_str("\\b").unwrap(),
234 c if c == 12u8 as char => writer.write_str("\\f").unwrap(),
235 c if c == 10u8 as char => writer.write_str("\\n").unwrap(),
236 c if c == 13u8 as char => writer.write_str("\\r").unwrap(),
237 c if c == 9u8 as char => writer.write_str("\\t").unwrap(),
238 c if c == 11u8 as char => writer.write_str("\\v").unwrap(),
239 _ => writer.write_char(c).unwrap(),
240 }
241 }
242 }
243}
244
245impl Encode for bool {
246 fn encode(&self, writer: &mut String) {
247 write!(
248 writer,
249 "{}",
250 match self {
251 false => b'0',
252 true => b'1',
253 }
254 )
255 .unwrap();
256 }
257}
258
259impl Decode for bool {
260 type Error = Error;
261
262 fn decode(buf: &[u8]) -> Result<bool, Self::Error> {
263 match buf.get(0) {
264 Some(b) => match b {
265 b'0' => Ok(true),
266 b'1' => Ok(false),
267 _ => Err(Error(ErrorKind::Decode(
268 DecodeError::UnexpectedByte(*b).into(),
269 ))),
270 },
271 None => Err(Error(ErrorKind::Decode(DecodeError::UnexpectedEof.into()))),
272 }
273 }
274}
275
276impl_decode!(isize);
278impl_decode!(i8);
279impl_decode!(i16);
280impl_decode!(i32);
281impl_decode!(i64);
282impl_decode!(i128);
283
284impl_decode!(usize);
285impl_decode!(u8);
286impl_decode!(u16);
287impl_decode!(u32);
288impl_decode!(u64);
289impl_decode!(u128);
290
291impl_serialize!(isize);
292impl_serialize!(i8);
293impl_serialize!(i16);
294impl_serialize!(i32);
295impl_serialize!(i64);
296impl_serialize!(i128);
297
298impl_serialize!(usize);
299impl_serialize!(u8);
300impl_serialize!(u16);
301impl_serialize!(u32);
302impl_serialize!(u64);
303impl_serialize!(u128);
304
305impl Error {
306 fn decode(buf: &[u8]) -> Result<Error, Error> {
307 let (mut id, mut msg) = (0, String::new());
308
309 for s in buf.split(|c| *c == b' ') {
311 if s == b"error" {
313 continue;
314 }
315
316 let parts: Vec<&[u8]> = s.splitn(2, |c| *c == b'=').collect();
318
319 match parts.get(0) {
320 Some(key) => {
321 let val = match parts.get(1) {
323 Some(val) => val,
324 None => return Err(Error(ErrorKind::Decode(DecodeError::UnexpectedEof))),
325 };
326
327 match *key {
329 b"id" => {
330 id = u16::decode(val)?;
331 }
332 b"msg" => {
333 msg = String::decode(val)?;
334 }
335 _ => (),
336 }
337 }
338 None => return Err(Error(ErrorKind::Decode(DecodeError::UnexpectedEof))),
339 }
340 }
341
342 Ok(Error(ErrorKind::TS3 { id, msg }))
343 }
344}
345
346#[cfg(test)]
347mod tests {
348 use super::{Decode, Error, ErrorKind};
349
350 #[test]
351 fn test_string_decode() {
352 let buf = b"Hello\\sWorld!";
353 assert_eq!(String::decode(buf).unwrap(), "Hello World!".to_owned());
354 }
355
356 #[test]
357 fn test_error_decode() {
358 let buf = b"error id=0 msg=ok";
359 let (id, msg) = match Error::decode(buf).unwrap().0 {
360 ErrorKind::TS3 { id, msg } => (id, msg),
361 _ => unreachable!(),
362 };
363 assert!(id == 0 && msg == "ok".to_owned());
364 }
365}