commit cdcf1c49618210dba6e450fd4575e7688958c187 Author: Maciej Pędzich Date: Mon Feb 17 13:19:03 2025 +0100 Cargo project init diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/.idea/f1-game-packet-parser.iml b/.idea/f1-game-packet-parser.iml new file mode 100644 index 0000000..cf84ae4 --- /dev/null +++ b/.idea/f1-game-packet-parser.iml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..2f9af06 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..768062f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,132 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "binrw" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4bca59c20d6f40c2cc0802afbe1e788b89096f61bdf7aeea6bf00f10c2909b" +dependencies = [ + "array-init", + "binrw_derive", + "bytemuck", +] + +[[package]] +name = "binrw_derive" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8ba42866ce5bced2645bfa15e97eef2c62d2bdb530510538de8dd3d04efff3c" +dependencies = [ + "either", + "owo-colors", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + +[[package]] +name = "bytemuck" +version = "1.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "f1-game-packet-parser" +version = "0.1.0" +dependencies = [ + "binrw", + "bitflags", + "serde", +] + +[[package]] +name = "owo-colors" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" + +[[package]] +name = "proc-macro2" +version = "1.0.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.217" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.98", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..ce7d425 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "f1-game-packet-parser" +version = "0.1.0" +edition = "2021" + +[dependencies] +binrw = "0.14" +bitflags = "2.8" +serde = { version = "1.0", features = ["derive"] } diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a219540 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,72 @@ +pub mod constants; +pub mod packets; + +use crate::constants::PacketId; +use crate::packets::F1PacketMotionData; + +use binrw::io::Cursor; +use binrw::{BinRead, BinReaderExt, BinResult}; +use serde::{Deserialize, Serialize}; + +/// Attempts to extract game packet data from a slice of bytes. +/// See [`binrw::Error`] for possible error variants. +pub fn parse(data: &[u8]) -> BinResult { + let mut cursor = Cursor::new(data); + let header: F1PacketHeader = cursor.read_le()?; + let body: F1PacketBody = + cursor.read_le_args((header.packet_format, header.packet_id))?; + + Ok(F1Packet { header, body }) +} + +#[derive(PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize)] +pub struct F1Packet { + pub header: F1PacketHeader, + pub body: F1PacketBody, +} + +/// F1 game packet's header. +#[non_exhaustive] +#[derive( + BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] +#[br( + little, + assert( + (2022..=2024).contains(&packet_format), + "Invalid or unsupported packet format" + ) +)] +pub struct F1PacketHeader { + /// Value of the "UDP Format" option in the game's telemetry settings. + pub packet_format: u16, + /// Game's major version - "X.00". + pub game_major_version: u8, + /// Game's minor version - "1.XX". + pub game_minor_version: u8, + /// Version of this packet type, all start from 1. + pub packet_version: u8, + /// Identifier for the packet type. + pub packet_id: PacketId, + /// Unique identifier for the session. + pub session_uid: u64, + /// Session timestamp. + pub session_time: f32, + /// Identifier for the frame the data was retrieved on. + pub frame_identifier: u32, + /// Index of player's car in the array. + pub player_car_index: u8, + /// Index of secondary player's car in the array in splitscreen mode. + pub secondary_player_car_index: u8, +} + +/// F1 game packet's body. +#[non_exhaustive] +#[derive( + BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, +)] +#[br(little, import(packet_format: u16, packet_id: PacketId))] +pub struct F1PacketBody { + #[br(if(packet_id == PacketId::Motion), args(packet_format))] + pub motion: Option, +}