Skip to main content

audio_code/net/
packet.rs

1//! [`Packet`]: one message between players, and its binary encoding.
2
3use glam::{Vec2, Vec3};
4
5use super::PeerId;
6
7/// One value inside a [`Packet`]. Made automatically by [`Packet::with`] from numbers,
8/// `bool`, text, [`Vec2`], [`Vec3`], [`PeerId`] and byte vectors.
9#[derive(Debug, Clone, PartialEq)]
10pub enum Arg {
11    /// A whole number (all integer types).
12    Int(i64),
13    /// A decimal number (`f32` and `f64`).
14    Float(f64),
15    /// `true` or `false`.
16    Bool(bool),
17    /// Text.
18    Text(String),
19    /// A 2D vector.
20    Vec2(Vec2),
21    /// A 3D vector, e.g. a position.
22    Vec3(Vec3),
23    /// Raw bytes for your own formats.
24    Bytes(Vec<u8>),
25}
26
27macro_rules! int_args {
28    ($($t:ty),*) => {$(
29        impl From<$t> for Arg {
30            fn from(v: $t) -> Self {
31                Arg::Int(v as i64)
32            }
33        }
34    )*};
35}
36int_args!(i8, i16, i32, i64, u8, u16, u32, u64, usize, isize);
37
38impl From<PeerId> for Arg {
39    fn from(v: PeerId) -> Self {
40        Arg::Int(v.number() as i64)
41    }
42}
43
44impl From<f32> for Arg {
45    fn from(v: f32) -> Self {
46        Arg::Float(v as f64)
47    }
48}
49
50impl From<f64> for Arg {
51    fn from(v: f64) -> Self {
52        Arg::Float(v)
53    }
54}
55
56impl From<bool> for Arg {
57    fn from(v: bool) -> Self {
58        Arg::Bool(v)
59    }
60}
61
62impl From<&str> for Arg {
63    fn from(v: &str) -> Self {
64        Arg::Text(v.to_string())
65    }
66}
67
68impl From<String> for Arg {
69    fn from(v: String) -> Self {
70        Arg::Text(v)
71    }
72}
73
74impl From<&String> for Arg {
75    fn from(v: &String) -> Self {
76        Arg::Text(v.clone())
77    }
78}
79
80impl From<Vec2> for Arg {
81    fn from(v: Vec2) -> Self {
82        Arg::Vec2(v)
83    }
84}
85
86impl From<Vec3> for Arg {
87    fn from(v: Vec3) -> Self {
88        Arg::Vec3(v)
89    }
90}
91
92impl From<Vec<u8>> for Arg {
93    fn from(v: Vec<u8>) -> Self {
94        Arg::Bytes(v)
95    }
96}
97
98impl From<&[u8]> for Arg {
99    fn from(v: &[u8]) -> Self {
100        Arg::Bytes(v.to_vec())
101    }
102}
103
104/// One message between players: a kind (what it is about) and a list of values.
105///
106/// ```
107/// use audio_code::prelude::*;
108///
109/// let packet = Packet::new("move").with(vec3(3.0, 4.0, 0.0)).with(90.0).with("running");
110/// assert_eq!(packet.kind(), "move");
111/// assert_eq!(packet.vec3(0), vec3(3.0, 4.0, 0.0));
112/// assert_eq!(packet.float(1), 90.0);
113/// assert_eq!(packet.text(2), "running");
114/// // Missing or other values give a neutral result instead of a crash:
115/// assert_eq!(packet.int(7), 0);
116/// ```
117///
118/// Text converts into a packet without values, so `ctx.net.send_all("ready")` works.
119#[derive(Debug, Clone, PartialEq, Default)]
120pub struct Packet {
121    kind: String,
122    args: Vec<Arg>,
123}
124
125impl Packet {
126    /// A packet of the given kind without values.
127    pub fn new(kind: impl Into<String>) -> Self {
128        Self { kind: kind.into(), args: Vec::new() }
129    }
130
131    /// Adds a value (builder style).
132    pub fn with(mut self, value: impl Into<Arg>) -> Self {
133        self.args.push(value.into());
134        self
135    }
136
137    /// Adds a value.
138    pub fn push(&mut self, value: impl Into<Arg>) {
139        self.args.push(value.into());
140    }
141
142    /// What the packet is about, e.g. `"move"` or `"chat"`.
143    pub fn kind(&self) -> &str {
144        &self.kind
145    }
146
147    /// Whether the packet is of this kind.
148    pub fn is(&self, kind: &str) -> bool {
149        self.kind == kind
150    }
151
152    /// All values.
153    pub fn args(&self) -> &[Arg] {
154        &self.args
155    }
156
157    /// Number of values.
158    pub fn len(&self) -> usize {
159        self.args.len()
160    }
161
162    /// Whether the packet has no values.
163    pub fn is_empty(&self) -> bool {
164        self.args.is_empty()
165    }
166
167    /// The value at `index`, if there is one.
168    pub fn get(&self, index: usize) -> Option<&Arg> {
169        self.args.get(index)
170    }
171
172    /// The value at `index` as a whole number. Decimals are cut off, `bool` gives 0 or 1,
173    /// text is parsed. Anything else gives 0.
174    pub fn int(&self, index: usize) -> i64 {
175        match self.get(index) {
176            Some(Arg::Int(v)) => *v,
177            Some(Arg::Float(v)) => *v as i64,
178            Some(Arg::Bool(v)) => *v as i64,
179            Some(Arg::Text(v)) => v.trim().parse().unwrap_or(0),
180            _ => 0,
181        }
182    }
183
184    /// The value at `index` as a decimal number. Whole numbers and `bool` convert, text is
185    /// parsed. Anything else gives 0.0.
186    pub fn float(&self, index: usize) -> f32 {
187        match self.get(index) {
188            Some(Arg::Int(v)) => *v as f32,
189            Some(Arg::Float(v)) => *v as f32,
190            Some(Arg::Bool(v)) => *v as u8 as f32,
191            Some(Arg::Text(v)) => v.trim().parse().unwrap_or(0.0),
192            _ => 0.0,
193        }
194    }
195
196    /// The value at `index` as `bool`. Numbers are `true` when not zero, text when it is
197    /// `"true"`. Anything else gives `false`.
198    pub fn bool(&self, index: usize) -> bool {
199        match self.get(index) {
200            Some(Arg::Bool(v)) => *v,
201            Some(Arg::Int(v)) => *v != 0,
202            Some(Arg::Float(v)) => *v != 0.0,
203            Some(Arg::Text(v)) => v.trim() == "true",
204            _ => false,
205        }
206    }
207
208    /// The value at `index` as text, or `""` if it is not text.
209    pub fn text(&self, index: usize) -> &str {
210        match self.get(index) {
211            Some(Arg::Text(v)) => v,
212            _ => "",
213        }
214    }
215
216    /// The value at `index` as a 2D vector. A 3D vector loses its z. Anything else gives
217    /// `Vec2::ZERO`.
218    pub fn vec2(&self, index: usize) -> Vec2 {
219        match self.get(index) {
220            Some(Arg::Vec2(v)) => *v,
221            Some(Arg::Vec3(v)) => v.truncate(),
222            _ => Vec2::ZERO,
223        }
224    }
225
226    /// The value at `index` as a 3D vector. A 2D vector gets z = 0. Anything else gives
227    /// `Vec3::ZERO`.
228    pub fn vec3(&self, index: usize) -> Vec3 {
229        match self.get(index) {
230            Some(Arg::Vec3(v)) => *v,
231            Some(Arg::Vec2(v)) => v.extend(0.0),
232            _ => Vec3::ZERO,
233        }
234    }
235
236    /// The value at `index` as a player id (stored with `.with(peer)`). Anything that is not
237    /// a valid number gives [`PeerId::SERVER`].
238    pub fn peer(&self, index: usize) -> PeerId {
239        PeerId::from_number(u32::try_from(self.int(index)).unwrap_or(0))
240    }
241
242    /// The value at `index` as bytes, or an empty slice if it is not bytes.
243    pub fn bytes(&self, index: usize) -> &[u8] {
244        match self.get(index) {
245            Some(Arg::Bytes(v)) => v,
246            _ => &[],
247        }
248    }
249
250    pub(crate) fn encode(&self, out: &mut Vec<u8>) {
251        put_str(out, &self.kind);
252        out.extend_from_slice(&(self.args.len() as u32).to_le_bytes());
253        for arg in &self.args {
254            match arg {
255                Arg::Int(v) => {
256                    out.push(0);
257                    out.extend_from_slice(&v.to_le_bytes());
258                }
259                Arg::Float(v) => {
260                    out.push(1);
261                    out.extend_from_slice(&v.to_le_bytes());
262                }
263                Arg::Bool(v) => {
264                    out.push(2);
265                    out.push(*v as u8);
266                }
267                Arg::Text(v) => {
268                    out.push(3);
269                    put_str(out, v);
270                }
271                Arg::Vec2(v) => {
272                    out.push(4);
273                    for c in v.to_array() {
274                        out.extend_from_slice(&c.to_le_bytes());
275                    }
276                }
277                Arg::Vec3(v) => {
278                    out.push(5);
279                    for c in v.to_array() {
280                        out.extend_from_slice(&c.to_le_bytes());
281                    }
282                }
283                Arg::Bytes(v) => {
284                    out.push(6);
285                    put_bytes(out, v);
286                }
287            }
288        }
289    }
290
291    pub(crate) fn decode(r: &mut Reader) -> Option<Self> {
292        let kind = r.str()?;
293        let count = r.u32()? as usize;
294        // Every value takes at least two bytes, so a huge count is rejected early.
295        if count > r.remaining() / 2 {
296            return None;
297        }
298        let mut args = Vec::with_capacity(count);
299        for _ in 0..count {
300            args.push(match r.u8()? {
301                0 => Arg::Int(i64::from_le_bytes(r.array()?)),
302                1 => Arg::Float(f64::from_le_bytes(r.array()?)),
303                2 => Arg::Bool(r.u8()? != 0),
304                3 => Arg::Text(r.str()?),
305                4 => Arg::Vec2(Vec2::new(r.f32()?, r.f32()?)),
306                5 => Arg::Vec3(Vec3::new(r.f32()?, r.f32()?, r.f32()?)),
307                6 => Arg::Bytes(r.bytes()?.to_vec()),
308                _ => return None,
309            });
310        }
311        Some(Self { kind, args })
312    }
313}
314
315impl From<&str> for Packet {
316    fn from(kind: &str) -> Self {
317        Packet::new(kind)
318    }
319}
320
321impl From<String> for Packet {
322    fn from(kind: String) -> Self {
323        Packet::new(kind)
324    }
325}
326
327impl From<&Packet> for Packet {
328    fn from(packet: &Packet) -> Self {
329        packet.clone()
330    }
331}
332
333pub(crate) fn put_bytes(out: &mut Vec<u8>, bytes: &[u8]) {
334    out.extend_from_slice(&(bytes.len() as u32).to_le_bytes());
335    out.extend_from_slice(bytes);
336}
337
338pub(crate) fn put_str(out: &mut Vec<u8>, text: &str) {
339    put_bytes(out, text.as_bytes());
340}
341
342/// Reads values from a received frame. Every method returns `None` when the data ends early.
343pub(crate) struct Reader<'a> {
344    data: &'a [u8],
345}
346
347impl<'a> Reader<'a> {
348    pub(crate) fn new(data: &'a [u8]) -> Self {
349        Self { data }
350    }
351
352    pub(crate) fn remaining(&self) -> usize {
353        self.data.len()
354    }
355
356    fn take(&mut self, n: usize) -> Option<&'a [u8]> {
357        if n > self.data.len() {
358            return None;
359        }
360        let (head, tail) = self.data.split_at(n);
361        self.data = tail;
362        Some(head)
363    }
364
365    fn array<const N: usize>(&mut self) -> Option<[u8; N]> {
366        self.take(N)?.try_into().ok()
367    }
368
369    pub(crate) fn u8(&mut self) -> Option<u8> {
370        Some(self.take(1)?[0])
371    }
372
373    pub(crate) fn u16(&mut self) -> Option<u16> {
374        Some(u16::from_le_bytes(self.array()?))
375    }
376
377    pub(crate) fn u32(&mut self) -> Option<u32> {
378        Some(u32::from_le_bytes(self.array()?))
379    }
380
381    pub(crate) fn u64(&mut self) -> Option<u64> {
382        Some(u64::from_le_bytes(self.array()?))
383    }
384
385    fn f32(&mut self) -> Option<f32> {
386        Some(f32::from_le_bytes(self.array()?))
387    }
388
389    pub(crate) fn bytes(&mut self) -> Option<&'a [u8]> {
390        let len = self.u32()? as usize;
391        self.take(len)
392    }
393
394    pub(crate) fn str(&mut self) -> Option<String> {
395        Some(String::from_utf8_lossy(self.bytes()?).into_owned())
396    }
397}
398
399#[cfg(test)]
400mod tests {
401    use super::*;
402
403    #[test]
404    fn round_trip() {
405        let packet = Packet::new("all")
406            .with(-5)
407            .with(2.5)
408            .with(true)
409            .with("hä?")
410            .with(Vec2::new(1.0, 2.0))
411            .with(Vec3::new(1.0, 2.0, 3.0))
412            .with(vec![1u8, 2, 3]);
413        let mut bytes = Vec::new();
414        packet.encode(&mut bytes);
415        let decoded = Packet::decode(&mut Reader::new(&bytes)).unwrap();
416        assert_eq!(decoded, packet);
417        assert!(Packet::decode(&mut Reader::new(&bytes[..bytes.len() - 1])).is_none());
418    }
419
420    #[test]
421    fn lenient_getters() {
422        let p = Packet::new("x").with(3).with("4.5").with(Vec2::new(1.0, 2.0));
423        assert_eq!(p.float(0), 3.0);
424        assert_eq!(p.float(1), 4.5);
425        assert_eq!(p.int(1), 0);
426        assert_eq!(p.text(0), "");
427        assert_eq!(p.vec3(2), Vec3::new(1.0, 2.0, 0.0));
428        assert!(p.bool(0));
429        assert!(!p.bool(9));
430    }
431}