f1_api/
codec.rs

1//! Codec for modern F1 games
2
3use std::io::{Cursor, Error, ErrorKind};
4
5use bytes::{Buf, BytesMut};
6use tokio_util::codec::Decoder;
7
8use crate::nineteen::decode_nineteen;
9use crate::packet::Packet;
10
11/// Codec to decode UDP packets published by modern F1 games.
12///
13/// This struct implements the `Decoder` trait for tokio-utils. It can be used to decode incoming
14/// UDP packets, and convert them into internal data representations. The F1 codec can decode the
15/// packets of all F1 games that are supported by this library.
16pub struct F1Codec;
17
18impl Decoder for F1Codec {
19    type Item = Packet;
20    type Error = Error;
21
22    /// Decode a UDP packet and return its data.
23    ///
24    /// The `decode` method is called whenever a new data frame is received on a UDP socket, and the
25    /// data frame is passed as an argument. This method has to make a few decisions then:
26    ///
27    /// 1. Does the data form a complete packet so that it can be decoded?
28    /// 2. Is the packet a valid packet sent by an F1 game?
29    /// 3. Can the packet be parsed?
30    ///
31    /// To answer these questions, the following process is used. First, the packet header is read
32    /// to determine the game that sent the packet. With the game and the packet type from the
33    /// header, the expected size of the packet can be determined by calling `buffer_size` from the
34    /// `FromBytes` trait. If the packet is too small, `Ok(None)` is returned to signal that more
35    /// data needs to be retrieved from the UDP socket.
36    ///
37    /// If the packet is complete, it is decoded using the `from_bytes` method in the `FromBytes`
38    /// trait. If the packet can be decoded successfully, it is returned. Otherwise, the error from
39    /// the decoding is returned, signaling that the UDP stream is corrupted and should be shut
40    /// down.
41    fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
42        let mut cursor = Cursor::new(src);
43
44        // Not enough data yet to decode the packet format.
45        if cursor.remaining() < 2 {
46            return Ok(None);
47        }
48
49        let packet_format = cursor.get_u16_le();
50
51        let packet = match packet_format {
52            2019 => decode_nineteen(&mut cursor),
53            format => Err(Error::new(
54                ErrorKind::InvalidData,
55                format!("Unknown packet format {}.", format),
56            )),
57        };
58
59        match packet {
60            Ok(packet) => Ok(Some(packet)),
61            Err(error) => match error.kind() {
62                ErrorKind::UnexpectedEof => Ok(None),
63                _ => Err(error),
64            },
65        }
66    }
67}