loco_protocol/command/
mod.rs

1/*
2 * Created on Sat Sep 09 2023
3 *
4 * Copyright (c) storycraft. Licensed under the MIT Licence.
5 */
6
7use core::{fmt::Debug, ops::Deref};
8
9use alloc::boxed::Box;
10use serde::{
11    de::{self, Unexpected, Visitor},
12    Deserialize, Serialize,
13};
14
15pub mod client;
16
17#[derive(Clone, PartialEq, Eq)]
18/// 11 bytes string padded with `\0`
19pub struct Method {
20    len: usize,
21    buf: [u8; 11],
22}
23
24impl Method {
25    /// Create new [`Method`]
26    ///
27    /// Returns `None` if string is longer than 11 bytes
28    pub fn new(string: &str) -> Option<Self> {
29        let bytes = string.as_bytes();
30        let len = bytes.len();
31        if len > 11 {
32            return None;
33        }
34
35        let mut buf = [0_u8; 11];
36        buf[..len].copy_from_slice(bytes);
37
38        Some(Self { len, buf })
39    }
40
41    pub const fn is_empty(&self) -> bool {
42        self.len == 0
43    }
44
45    pub const fn len(&self) -> usize {
46        self.len
47    }
48}
49
50impl Debug for Method {
51    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
52        f.debug_tuple("Method").field(&self.deref()).finish()
53    }
54}
55
56impl Deref for Method {
57    type Target = str;
58
59    fn deref(&self) -> &Self::Target {
60        core::str::from_utf8(&self.buf[..self.len]).unwrap()
61    }
62}
63
64impl Serialize for Method {
65    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
66    where
67        S: serde::Serializer,
68    {
69        serializer.serialize_newtype_struct("Method", &self.buf)
70    }
71}
72
73impl<'de> Deserialize<'de> for Method {
74    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
75    where
76        D: serde::Deserializer<'de>,
77    {
78        struct MethodVisitor;
79
80        impl<'a> Visitor<'a> for MethodVisitor {
81            type Value = Method;
82
83            fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
84                write!(formatter, "utf-8 byte array that has 11 length")
85            }
86
87            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
88            where
89                D: serde::Deserializer<'a>,
90            {
91                deserializer.deserialize_tuple(11, MethodVisitor)
92            }
93
94            fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
95            where
96                A: serde::de::SeqAccess<'a>,
97            {
98                let mut buf = [0_u8; 11];
99
100                for item in &mut buf {
101                    *item = seq.next_element::<u8>()?.ok_or(de::Error::invalid_length(
102                        11,
103                        &"an array of size 11 was expected",
104                    ))?;
105                }
106
107                let len = core::str::from_utf8(&buf)
108                    .map_err(|_| {
109                        de::Error::invalid_type(
110                            Unexpected::Bytes(&buf),
111                            &"a valid utf-8 array was expected",
112                        )
113                    })?
114                    .trim_matches(char::from(0))
115                    .len();
116
117                Ok(Method { len, buf })
118            }
119        }
120
121        deserializer.deserialize_newtype_struct("Method", MethodVisitor)
122    }
123}
124
125#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
126pub struct Header {
127    pub id: u32,
128    pub status: u16,
129    pub method: Method,
130    pub data_type: u8,
131}
132
133#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
134pub struct Command<T: ?Sized> {
135    pub header: Header,
136    pub data: T,
137}
138
139pub type BoxedCommand = Command<Box<[u8]>>;