1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
//! Packets that are sent by modern F1 games //! //! This library implements a single packet format for all the F1 games it supports. The API //! specification has been slowly evolving from game to game, but without such significant changes //! that it would require a different packet format. use bytes::{Buf, BytesMut}; use std::io::{Cursor, Error, ErrorKind}; pub mod event; pub mod header; pub mod lap; pub mod motion; pub mod participants; pub mod session; pub mod setup; pub mod status; pub mod telemetry; /// A packet published by an F1 game. /// /// The F1 games publish different packets with different data at different intervals. Each of these /// packets is decoded from UDP to their respective representation in this Rust crate. The `Packet` /// enum lists all packets that can be expected, and that a client should handle. #[derive(Debug, PartialEq, Clone, PartialOrd)] pub enum Packet { /// The F1 games send event packets whenever certain events occur in a session. Some event /// packets carry a payload with more information about the event. Event(event::EventPacket), /// Lap data packets provide information about each car in a session, and are sent at an /// interval that can be configured in the game. Lap(lap::LapPacket), /// The motion data packet describes the movement and position of each car in the session, with /// additional details being provided for the player's car. Motion(motion::MotionPacket), /// Packet with information on all participants in the session, for example their name, team, /// and nationality. Participants(participants::ParticipantsPacket), /// The F1 games provide information about the current session on a regular basis. Session(session::SessionPacket), /// Car setup packets publish the setup of each car in the session. In multiplayer sessions, the /// setups of other player's cars are redacted to enable a fair competition. Setup(setup::CarSetupPacket), /// The F1 games send packets with data about the status of each car in a session at a /// configurable interval. Status(status::CarStatusPacket), /// Telemetry data is provided for all cars in the session. Telemetry(telemetry::TelemetryPacket), } /// Ensure a packet has the expected size /// /// Modern F1 games send their packets over UDP. Depending on their size, these packets might be /// split into multiple UDP fragments. The decoder collects these fragments, and asks the codec if /// enough data has been received to decode a packet. /// /// The sizes of the packets sent by F1 games are part of the API specification, and can be used to /// determine if a full packet has ben received. This function takes a cursor to the raw data and /// the expected size of the packet, and returns an error if not enough data is ready to decode the /// complete packet. pub(crate) fn ensure_packet_size( expected_size: usize, cursor: &mut Cursor<&mut BytesMut>, ) -> Result<(), Error> { if cursor.remaining() < expected_size { Err(Error::new( ErrorKind::UnexpectedEof, format!( "Packet is expected to have a size of {} bytes, but was {}.", expected_size, cursor.remaining() ), )) } else { Ok(()) } } #[cfg(test)] mod tests { use crate::packet::ensure_packet_size; use bytes::{Buf, BufMut, BytesMut}; use std::io::{Cursor, Error}; struct Packet { counter: u8, } const PACKET_SIZE: usize = 1; fn decode_packet(cursor: &mut Cursor<&mut BytesMut>) -> Result<Packet, Error> { ensure_packet_size(PACKET_SIZE, cursor)?; Ok(Packet { counter: cursor.get_u8(), }) } #[test] fn ensure_packet_size_correctly() { let mut bytes = BytesMut::with_capacity(1); bytes.put_u8(0); let mut cursor = Cursor::new(&mut bytes); let packet = decode_packet(&mut cursor).unwrap(); assert_eq!(0, packet.counter); } #[test] fn ensure_packet_size_with_error() { let mut bytes = BytesMut::with_capacity(0); let mut cursor = Cursor::new(&mut bytes); let packet = decode_packet(&mut cursor); assert!(packet.is_err()); } }