libbarto/message/
client.rs

1// Copyright (c) 2025 barto developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9use bincode::{
10    BorrowDecode, Decode, Encode,
11    de::{BorrowDecoder, Decoder},
12    enc::Encoder,
13    error::{AllowedEnumVariants, DecodeError, EncodeError},
14};
15
16use crate::{BartocInfo, Data};
17
18/// A supported websocket message from bartoc to bartos
19#[derive(Clone, Debug, Eq, PartialEq)]
20pub enum BartocWs {
21    /// A close message from bartoc
22    Close(Option<(u16, String)>),
23    /// A ping message from bartoc
24    Ping(Vec<u8>),
25    /// A pong message from bartos
26    Pong(Vec<u8>),
27}
28
29impl<Context> Decode<Context> for BartocWs {
30    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
31        let variant: u32 = Decode::decode(decoder)?;
32        match variant {
33            0 => {
34                let close_data: Option<(u16, String)> = Decode::decode(decoder)?;
35                Ok(BartocWs::Close(close_data))
36            }
37            1 => {
38                let ping_data: Vec<u8> = Decode::decode(decoder)?;
39                Ok(BartocWs::Ping(ping_data))
40            }
41            2 => {
42                let pong_data: Vec<u8> = Decode::decode(decoder)?;
43                Ok(BartocWs::Pong(pong_data))
44            }
45            _ => Err(DecodeError::UnexpectedVariant {
46                type_name: "BartocWs",
47                allowed: &AllowedEnumVariants::Range { min: 0, max: 2 },
48                found: variant,
49            }),
50        }
51    }
52}
53
54impl<'de, Context> BorrowDecode<'de, Context> for BartocWs {
55    fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(
56        decoder: &mut D,
57    ) -> Result<Self, DecodeError> {
58        let variant: u32 = BorrowDecode::borrow_decode(decoder)?;
59        match variant {
60            0 => {
61                let close_data: Option<(u16, String)> = BorrowDecode::borrow_decode(decoder)?;
62                Ok(BartocWs::Close(close_data))
63            }
64            1 => {
65                let ping_data: Vec<u8> = BorrowDecode::borrow_decode(decoder)?;
66                Ok(BartocWs::Ping(ping_data))
67            }
68            2 => {
69                let pong_data: Vec<u8> = BorrowDecode::borrow_decode(decoder)?;
70                Ok(BartocWs::Pong(pong_data))
71            }
72            _ => Err(DecodeError::UnexpectedVariant {
73                type_name: "BartocWs",
74                allowed: &AllowedEnumVariants::Range { min: 0, max: 2 },
75                found: variant,
76            }),
77        }
78    }
79}
80
81impl Encode for BartocWs {
82    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
83        match self {
84            BartocWs::Close(close_data) => {
85                0u32.encode(encoder)?;
86                close_data.encode(encoder)
87            }
88            BartocWs::Ping(ping_data) => {
89                1u32.encode(encoder)?;
90                ping_data.encode(encoder)
91            }
92            BartocWs::Pong(pong_data) => {
93                2u32.encode(encoder)?;
94                pong_data.encode(encoder)
95            }
96        }
97    }
98}
99
100/// A websocket binary message from bartoc to bartos
101#[derive(Clone, Debug, Eq, PartialEq)]
102pub enum Bartoc {
103    /// A close message from bartoc
104    Record(Data),
105    /// barto client info
106    ClientInfo(BartocInfo),
107}
108
109impl<Context> Decode<Context> for Bartoc {
110    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
111        let variant: u32 = Decode::decode(decoder)?;
112        match variant {
113            0 => {
114                let data: Data = Decode::decode(decoder)?;
115                Ok(Bartoc::Record(data))
116            }
117            1 => {
118                let client_info: BartocInfo = Decode::decode(decoder)?;
119                Ok(Bartoc::ClientInfo(client_info))
120            }
121            _ => Err(DecodeError::UnexpectedVariant {
122                type_name: "Bartoc",
123                allowed: &AllowedEnumVariants::Range { min: 0, max: 1 },
124                found: variant,
125            }),
126        }
127    }
128}
129
130impl<'de, Context> BorrowDecode<'de, Context> for Bartoc {
131    fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(
132        decoder: &mut D,
133    ) -> Result<Self, DecodeError> {
134        let variant: u32 = BorrowDecode::borrow_decode(decoder)?;
135        match variant {
136            0 => {
137                let data: Data = BorrowDecode::borrow_decode(decoder)?;
138                Ok(Bartoc::Record(data))
139            }
140            1 => {
141                let client_info: BartocInfo = BorrowDecode::borrow_decode(decoder)?;
142                Ok(Bartoc::ClientInfo(client_info))
143            }
144            _ => Err(DecodeError::UnexpectedVariant {
145                type_name: "Bartoc",
146                allowed: &AllowedEnumVariants::Range { min: 0, max: 1 },
147                found: variant,
148            }),
149        }
150    }
151}
152
153impl Encode for Bartoc {
154    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), EncodeError> {
155        match self {
156            Bartoc::Record(data) => {
157                0u32.encode(encoder)?;
158                data.encode(encoder)
159            }
160            Bartoc::ClientInfo(client_info) => {
161                1u32.encode(encoder)?;
162                client_info.encode(encoder)
163            }
164        }
165    }
166}
167
168#[cfg(test)]
169mod tests {
170    use super::{Bartoc, BartocWs};
171
172    use crate::{BartocInfo, Data, Output, utils::Mock as _};
173    use bincode::{borrow_decode_from_slice, config::standard, decode_from_slice, encode_to_vec};
174
175    #[test]
176    fn test_bartoc_ws_encode_decode() {
177        let original = BartocWs::Close(None);
178        let encoded = encode_to_vec(&original, standard()).unwrap();
179        let (decoded, _): (BartocWs, usize) = decode_from_slice(&encoded, standard()).unwrap();
180        let (borrow_decoded, _): (BartocWs, usize) =
181            borrow_decode_from_slice(&encoded, standard()).unwrap();
182
183        assert_eq!(original, decoded);
184        assert_eq!(original, borrow_decoded);
185    }
186
187    #[test]
188    fn test_bartoc_ws_ping_encode_decode() {
189        let ping_data = vec![1, 2, 3, 4, 5];
190        let original = BartocWs::Ping(ping_data.clone());
191        let encoded = encode_to_vec(&original, standard()).unwrap();
192        let (decoded, _): (BartocWs, usize) = decode_from_slice(&encoded, standard()).unwrap();
193        let (borrow_decoded, _): (BartocWs, usize) =
194            borrow_decode_from_slice(&encoded, standard()).unwrap();
195
196        assert_eq!(original, decoded);
197        assert_eq!(original, borrow_decoded);
198    }
199
200    #[test]
201    fn test_bartoc_ws_pong_encode_decode() {
202        let pong_data = vec![6, 7, 8, 9, 10];
203        let original = BartocWs::Pong(pong_data.clone());
204        let encoded = encode_to_vec(&original, standard()).unwrap();
205        let (decoded, _): (BartocWs, usize) = decode_from_slice(&encoded, standard()).unwrap();
206        let (borrow_decoded, _): (BartocWs, usize) =
207            borrow_decode_from_slice(&encoded, standard()).unwrap();
208
209        assert_eq!(original, decoded);
210        assert_eq!(original, borrow_decoded);
211    }
212
213    #[test]
214    fn test_bartoc_ws_bad_variant_decode() {
215        // Encode a bad variant (3) manually
216        let mut encoded = Vec::new();
217        encoded.extend_from_slice(&3u32.to_le_bytes()); // Invalid variant
218
219        let result: Result<(BartocWs, usize), _> = decode_from_slice(&encoded, standard());
220        assert!(result.is_err());
221
222        let borrow_result: Result<(BartocWs, usize), _> =
223            borrow_decode_from_slice(&encoded, standard());
224        assert!(borrow_result.is_err());
225    }
226
227    #[test]
228    fn test_bartoc_client_info_encode_decode() {
229        let client_info = BartocInfo::mock();
230        let original = Bartoc::ClientInfo(client_info);
231        let encoded = encode_to_vec(&original, standard()).unwrap();
232        let (decoded, _): (Bartoc, usize) = decode_from_slice(&encoded, standard()).unwrap();
233        let (borrow_decoded, _): (Bartoc, usize) =
234            borrow_decode_from_slice(&encoded, standard()).unwrap();
235
236        assert_eq!(original, decoded);
237        assert_eq!(original, borrow_decoded);
238    }
239
240    #[test]
241    fn test_bartoc_record_encode_decode() {
242        let output = Output::mock();
243        let original = Bartoc::Record(Data::Output(output));
244        let encoded = encode_to_vec(&original, standard()).unwrap();
245        let (decoded, _): (Bartoc, usize) = decode_from_slice(&encoded, standard()).unwrap();
246        let (borrow_decoded, _): (Bartoc, usize) =
247            borrow_decode_from_slice(&encoded, standard()).unwrap();
248
249        assert_eq!(original, decoded);
250        assert_eq!(original, borrow_decoded);
251    }
252
253    #[test]
254    fn test_bartoc_bad_variant_decode() {
255        // Encode a bad variant (2) manually
256        let mut encoded = Vec::new();
257        encoded.extend_from_slice(&2u32.to_le_bytes()); // Invalid variant
258
259        let result: Result<(Bartoc, usize), _> = decode_from_slice(&encoded, standard());
260        assert!(result.is_err());
261
262        let borrow_result: Result<(Bartoc, usize), _> =
263            borrow_decode_from_slice(&encoded, standard());
264        assert!(borrow_result.is_err());
265    }
266}