From dd881a66c05b570f0748b75591c023df9dcb243f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20P=C4=99dzich?= Date: Thu, 20 Feb 2025 13:02:14 +0100 Subject: [PATCH] refactor: change u8_to_bool return type to Result with custom error --- src/constants/mod.rs | 3 +- src/packets/car_damage.rs | 9 +++--- src/packets/car_setups.rs | 1 + src/packets/car_status.rs | 7 +++-- src/packets/car_telemetry.rs | 2 +- src/packets/event.rs | 6 ++-- src/packets/lap.rs | 6 ++-- src/packets/lobby.rs | 2 +- src/packets/mod.rs | 53 ++++++++++++++++++++++------------ src/packets/motion.rs | 48 +++++++++++++++--------------- src/packets/participants.rs | 6 ++-- src/packets/session.rs | 2 ++ src/packets/session_history.rs | 2 ++ src/packets/tyre_sets.rs | 5 ++-- 14 files changed, 89 insertions(+), 63 deletions(-) diff --git a/src/constants/mod.rs b/src/constants/mod.rs index 9538cc0..338aa94 100644 --- a/src/constants/mod.rs +++ b/src/constants/mod.rs @@ -1,5 +1,6 @@ pub mod driver_id; pub mod team_id; +/// The wheel order is: `REAR_LEFT`, `REAR_RIGHT`, `FRONT_LEFT`, `FRONT_RIGHT`. pub mod wheel_index; use binrw::BinRead; @@ -385,7 +386,7 @@ pub enum GameMode { Deserialize, )] #[br(little, repr(u8))] -pub enum Ruleset { +pub enum RuleSet { PracticeAndQualifying = 0, Race = 1, TimeTrial = 2, diff --git a/src/packets/car_damage.rs b/src/packets/car_damage.rs index b296c92..beee31e 100644 --- a/src/packets/car_damage.rs +++ b/src/packets/car_damage.rs @@ -2,6 +2,7 @@ use super::u8_to_bool; use binrw::BinRead; use serde::{Deserialize, Serialize}; +#[non_exhaustive] #[derive( BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, )] @@ -32,10 +33,10 @@ pub struct CarDamageData { /// Sidepod damage (percentage) pub sidepod_damage: u8, /// Whether DRS has failed - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub drs_fault: bool, /// Whether ERS has failed - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub ers_fault: bool, /// Gearbox damage (percentage) pub gearbox_damage: u8, @@ -54,9 +55,9 @@ pub struct CarDamageData { /// Engine TC wear (percentage) pub engine_tc_wear: u8, /// Whether the engine has blown - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub engine_blown: bool, /// Whether the engine has seized - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub engine_seized: bool, } diff --git a/src/packets/car_setups.rs b/src/packets/car_setups.rs index 0f2140c..fabe39f 100644 --- a/src/packets/car_setups.rs +++ b/src/packets/car_setups.rs @@ -1,6 +1,7 @@ use binrw::BinRead; use serde::{Deserialize, Serialize}; +#[non_exhaustive] #[derive( BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, )] diff --git a/src/packets/car_status.rs b/src/packets/car_status.rs index 61aa41c..fb74f8e 100644 --- a/src/packets/car_status.rs +++ b/src/packets/car_status.rs @@ -7,6 +7,7 @@ use crate::constants::{ use binrw::BinRead; use serde::{Deserialize, Serialize}; +#[non_exhaustive] #[derive( BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, )] @@ -23,14 +24,14 @@ pub struct CarStatusData { /// How much traction control is enabled. pub traction_control: TractionControl, /// Whether ABS is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub anti_lock_brakes: bool, /// Fuel mix currently in use. pub fuel_mix: FuelMix, /// Front brake bias (percentage). pub front_brake_bias: u8, /// Whether the pit limiter is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub pit_limiter_enabled: bool, /// Current fuel mass. pub fuel_in_tank: f32, @@ -75,6 +76,6 @@ pub struct CarStatusData { /// ERS energy deployed this lap. pub ers_deployed_this_lap: f32, /// Whether the car has paused in a network game. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub network_paused: bool, } diff --git a/src/packets/car_telemetry.rs b/src/packets/car_telemetry.rs index d8df6bd..f9b45b6 100644 --- a/src/packets/car_telemetry.rs +++ b/src/packets/car_telemetry.rs @@ -58,7 +58,7 @@ pub struct CarTelemetryData { /// Engine RPM. pub engine_rpm: u16, /// Whether DRS is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub drs_enabled: bool, /// Rev lights indicator (percentage). pub rev_lights_percent: u8, diff --git a/src/packets/event.rs b/src/packets/event.rs index 4fdb7c2..d3d161d 100644 --- a/src/packets/event.rs +++ b/src/packets/event.rs @@ -84,10 +84,10 @@ pub enum EventDataDetails { /// Top speed achieved in kilometres per hour. speed: f32, /// Whether the driver is overall fastest in the session. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] is_overall_fastest_in_session: bool, /// Whether this speed is personal fastest in the session. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] is_driver_fastest_in_session: bool, /// Index of the vehicle that's the fastest in the session. #[br(map(u8_to_usize))] @@ -129,7 +129,7 @@ pub enum EventDataDetails { /// Sent when the button status has changed. #[br(magic = b"BUTN")] Buttons { - /// Bit flags specifying which buttons are currently pressed. + /// Bitmap specifying which buttons are currently pressed. #[br(map(ButtonStatus::from_bits_truncate))] button_status: ButtonStatus, }, diff --git a/src/packets/lap.rs b/src/packets/lap.rs index 5da26fe..a11d6b7 100644 --- a/src/packets/lap.rs +++ b/src/packets/lap.rs @@ -63,7 +63,7 @@ pub struct LapData { /// S1 = 0, S2 = 1, S3 = 2. pub sector: u8, /// Whether the current lap is invalid. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub current_lap_invalid: bool, /// Accumulated time penalties to be added in seconds. pub penalties: u8, @@ -90,13 +90,13 @@ pub struct LapData { /// Status of the driver's result. pub result_status: ResultStatus, /// Whether the pit lane timer is active. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub pit_lane_timer_active: bool, /// Current time spent in the pit lane in milliseconds. pub pit_lane_time_in_lane_ms: u16, /// Time of the actual pit stop in milliseconds. pub pit_stop_timer_ms: u16, /// Whether the car should serve a penalty at this stop. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub pit_stop_should_serve_pen: bool, } diff --git a/src/packets/lobby.rs b/src/packets/lobby.rs index b9d9ac1..e3546fb 100644 --- a/src/packets/lobby.rs +++ b/src/packets/lobby.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; #[br(little, import(packet_format: u16))] pub struct LobbyInfoData { /// Whether the vehicle is controlled by AI. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub ai_controlled: bool, /// Team's ID. pub team_id: u8, diff --git a/src/packets/mod.rs b/src/packets/mod.rs index ab121b6..8280ad2 100644 --- a/src/packets/mod.rs +++ b/src/packets/mod.rs @@ -14,7 +14,7 @@ pub mod tyre_sets; use crate::constants::{ BrakingAssist, DynamicRacingLine, DynamicRacingLineType, ForecastAccuracy, - Formula, GameMode, GearboxAssist, MfdPanelIndex, Ruleset, SafetyCarStatus, + Formula, GameMode, GearboxAssist, MfdPanelIndex, RuleSet, SafetyCarStatus, SessionLength, SessionType, SpeedUnit, TemperatureUnit, TrackId, Weather, MAX_NUM_CARS, }; @@ -32,7 +32,7 @@ use crate::packets::session::{MarshalZone, WeatherForecastSample}; use crate::packets::session_history::{LapHistoryData, TyreStintHistoryData}; use crate::packets::tyre_sets::TyreSetData; -use binrw::BinRead; +use binrw::{BinRead, BinResult}; use serde::{Deserialize, Serialize}; use std::string::FromUtf8Error; @@ -101,16 +101,16 @@ pub struct F1PacketSession { /// Pit lane's speed limit in kilometres per hour. pub pit_speed_limit: u8, /// Whether the game is paused. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub game_paused: bool, /// Whether the player is spectating. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub is_spectating: bool, /// Index of the car being spectated. #[br(map(u8_to_usize))] pub spectator_car_index: usize, /// Whether SLI Pro support is active. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub sli_pro_native_support: bool, /// Number of marshal zones to follow (no greater than 21). #[br(map(u8_to_usize))] @@ -123,7 +123,7 @@ pub struct F1PacketSession { /// Safety car deployment status. pub safety_car_status: SafetyCarStatus, /// Whether this game is online. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub network_game: bool, /// Number of weather samples to follow (no greater than 56). #[br(map(u8_to_usize))] @@ -151,23 +151,23 @@ pub struct F1PacketSession { /// Predicted position for the player to rejoin at. pub pit_stop_rejoin_position: u8, /// Whether the steering assist is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub steering_assist: bool, /// Type of braking assist enabled. pub braking_assist: BrakingAssist, /// Type of gearbox assist enabled. pub gearbox_assist: GearboxAssist, /// Whether the pit assist is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub pit_assist: bool, /// Whether the pit release assist is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub pit_release_assist: bool, /// Whether the ERS assist is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub ers_assist: bool, /// Whether the DRS assist is enabled. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub drs_assist: bool, /// Type of the dynamic racing line assist. pub dynamic_racing_line: DynamicRacingLine, @@ -175,9 +175,9 @@ pub struct F1PacketSession { pub dynamic_racing_line_type: DynamicRacingLineType, /// Game mode's identifier. pub game_mode: GameMode, - /// Ruleset's identifier. - pub ruleset: Ruleset, - /// Local time of day - minutes since midnight. + /// Rule set's identifier. + pub rule_set: RuleSet, + /// Local time of day as minutes since midnight. pub time_of_day: u32, /// Session's length. pub session_length: SessionLength, @@ -209,6 +209,10 @@ pub struct F1PacketSession { /// Available from the 2023 format onwards. #[br(if(packet_format >= 2023))] pub num_red_flag_periods: u8, + /// Whether equal car performance is enabled. + /// Available from the 2024 format onwards. + #[br(try_map(u8_to_bool))] + pub equal_car_performance: bool, } /// Data about all the lap times of cars in the session. @@ -345,7 +349,7 @@ pub struct F1PacketFinalClassification { pub num_cars: usize, /// Final classification data for all cars. /// Should have a size equal to - /// [`num_cars`](field@F1PacketFinalClassificationData::num_cars). + /// [`num_cars`](field@F1PacketFinalClassification::num_cars). #[br(count(num_cars), args{ inner: (packet_format,) })] pub final_classification_data: Vec, } @@ -370,7 +374,7 @@ pub struct F1PacketLobbyInfo { pub num_players: usize, /// Lobby info data for all players. /// Should have a size equal to - /// [`num_players`](field@F1PacketLobbyInfoData::num_players). + /// [`num_players`](field@F1PacketLobbyInfo::num_players). #[br(count(num_players), args{ inner: (packet_format,) })] pub lobby_info_data: Vec, } @@ -517,8 +521,21 @@ pub struct F1PacketMotionEx { pub wheel_vert_force: [f32; 4], } -pub(crate) fn u8_to_bool(value: u8) -> bool { - value == 1 +#[derive(Debug, PartialEq)] +pub(crate) struct InvalidBoolValue(u8); + +impl core::fmt::Display for InvalidBoolValue { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Invalid bool value: {}", self.0) + } +} + +pub(crate) fn u8_to_bool(value: u8) -> Result { + match value { + 0 => Ok(false), + 1 => Ok(true), + _ => Err(InvalidBoolValue(value)), + } } pub(crate) fn u8_to_usize(value: u8) -> usize { diff --git a/src/packets/motion.rs b/src/packets/motion.rs index dec83c5..7a33e97 100644 --- a/src/packets/motion.rs +++ b/src/packets/motion.rs @@ -6,71 +6,71 @@ use serde::{Deserialize, Serialize}; )] #[br(little, import(_packet_format: u16))] pub struct CarMotionData { - /// World space X position in metres + /// World space X position in metres. pub world_position_x: f32, - /// World space Y position in metres + /// World space Y position in metres. pub world_position_y: f32, - /// World space Z position in metres + /// World space Z position in metres. pub world_position_z: f32, - /// Velocity in world space X position + /// Velocity in world space X position in metres per second. pub world_velocity_x: f32, - /// Velocity in world space Y position + /// Velocity in world space Y position in metres per second. pub world_velocity_y: f32, - /// Velocity in world space Z position + /// Velocity in world space Z position in metres per second. pub world_velocity_z: f32, - /// World space forward X direction (normalised) + /// World space forward X direction (normalised). pub world_forward_dir_x: i16, - /// World space forward Y direction (normalised) + /// World space forward Y direction (normalised). pub world_forward_dir_y: i16, - /// World space forward Z direction (normalised) + /// World space forward Z direction (normalised). pub world_forward_dir_z: i16, - /// World space right X direction (normalised) + /// World space right X direction (normalised). pub world_right_dir_x: i16, - /// World space right Y direction (normalised) + /// World space right Y direction (normalised). pub world_right_dir_y: i16, - /// World space right Z direction (normalised) + /// World space right Z direction (normalised). pub world_right_dir_z: i16, - /// Lateral G-Force component + /// Lateral G-Force component. pub g_force_lateral: f32, - /// Longitudinal G-Force component + /// Longitudinal G-Force component. pub g_force_longitudinal: f32, - /// Vertical G-Force component + /// Vertical G-Force component. pub g_force_vertical: f32, - /// Yaw angle in radians + /// Yaw angle in radians. pub yaw: f32, - /// Pitch angle in radians + /// Pitch angle in radians. pub pitch: f32, - /// Roll angle in radians + /// Roll angle in radians. pub roll: f32, } impl CarMotionData { - /// Returns [`self.world_forward_dir_x`] divided by `32767.0f32` + /// Returns [`self.world_forward_dir_x`] divided by `32767.0f32`. pub fn world_forward_dir_x_as_f32(&self) -> f32 { self.world_forward_dir_x as f32 / 32767.0 } - /// Returns [`self.world_forward_dir_y`] divided by `32767.0f32` + /// Returns [`self.world_forward_dir_y`] divided by `32767.0f32`. pub fn world_forward_dir_y_as_f32(&self) -> f32 { self.world_forward_dir_y as f32 / 32767.0 } - /// Returns [`self.world_forward_dir_z`] divided by `32767.0f32` + /// Returns [`self.world_forward_dir_z`] divided by `32767.0f32`. pub fn world_forward_dir_z_as_f32(&self) -> f32 { self.world_forward_dir_z as f32 / 32767.0 } - /// Returns [`self.world_right_dir_x`] divided by `32767.0f32` + /// Returns [`self.world_right_dir_x`] divided by `32767.0f32`. pub fn world_right_dir_x_as_f32(&self) -> f32 { self.world_right_dir_x as f32 / 32767.0 } - /// Returns [`self.world_right_dir_y`] divided by `32767.0f32` + /// Returns [`self.world_right_dir_y`] divided by `32767.0f32`. pub fn world_right_dir_y_as_f32(&self) -> f32 { self.world_right_dir_y as f32 / 32767.0 } - /// Returns [`self.world_right_dir_z`] divided by `32767.0f32` + /// Returns [`self.world_right_dir_z`] divided by `32767.0f32`. pub fn world_right_dir_z_as_f32(&self) -> f32 { self.world_right_dir_z as f32 / 32767.0 } diff --git a/src/packets/participants.rs b/src/packets/participants.rs index 89f8b08..c10337d 100644 --- a/src/packets/participants.rs +++ b/src/packets/participants.rs @@ -11,7 +11,7 @@ use serde::{Deserialize, Serialize}; #[br(little, import(packet_format: u16))] pub struct ParticipantsData { /// Whether the vehicle is controlled by AI - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub ai_controlled: bool, /// Driver's ID pub driver_id: u8, @@ -20,7 +20,7 @@ pub struct ParticipantsData { /// Team's ID pub team_id: u8, /// Whether my team is being used - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub my_team: bool, /// Race number of the car pub race_number: u8, @@ -33,7 +33,7 @@ pub struct ParticipantsData { pub your_telemetry: Option, /// Whether this player's "show online names" setting is on. /// Available from the 2023 format onwards. - #[br(if(packet_format >= 2023), map(u8_to_bool))] + #[br(if(packet_format >= 2023), try_map(u8_to_bool))] pub show_online_names: bool, /// Player's platform. /// Available from the 2023 format onwards. diff --git a/src/packets/session.rs b/src/packets/session.rs index 305f675..59dbd4d 100644 --- a/src/packets/session.rs +++ b/src/packets/session.rs @@ -5,6 +5,7 @@ use binrw::BinRead; use serde::{Deserialize, Serialize}; /// Section of the track supervised by marshals. +#[non_exhaustive] #[derive( BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, )] @@ -24,6 +25,7 @@ pub struct MarshalZone { pub zone_flag: MarshalZoneFlag, } +#[non_exhaustive] /// Weather forecast sample for a given session. #[derive( BinRead, PartialEq, PartialOrd, Copy, Clone, Debug, Serialize, Deserialize, diff --git a/src/packets/session_history.rs b/src/packets/session_history.rs index 049372a..dc60505 100644 --- a/src/packets/session_history.rs +++ b/src/packets/session_history.rs @@ -4,6 +4,7 @@ use crate::constants::{ActualTyreCompound, LapValid, VisualTyreCompound}; use binrw::BinRead; use serde::{Deserialize, Serialize}; +#[non_exhaustive] #[derive( BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, )] @@ -34,6 +35,7 @@ pub struct LapHistoryData { pub lap_valid_bit_flags: LapValid, } +#[non_exhaustive] #[derive( BinRead, PartialEq, PartialOrd, Clone, Debug, Serialize, Deserialize, )] diff --git a/src/packets/tyre_sets.rs b/src/packets/tyre_sets.rs index 3b78a0f..21068ce 100644 --- a/src/packets/tyre_sets.rs +++ b/src/packets/tyre_sets.rs @@ -4,6 +4,7 @@ use crate::constants::{ActualTyreCompound, SessionType, VisualTyreCompound}; use binrw::BinRead; use serde::{Deserialize, Serialize}; +#[non_exhaustive] #[derive( BinRead, Eq, @@ -33,7 +34,7 @@ pub struct TyreSetData { /// Tyre wear (percentage). pub wear: u8, /// Whether this set is currently available. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub available: bool, /// Recommended session for this tyre set. pub recommended_session: SessionType, @@ -44,6 +45,6 @@ pub struct TyreSetData { /// Lap time delta in milliseconds compared to fitted set. pub lap_delta_time: i16, /// Whether this set is fitted or not. - #[br(map(u8_to_bool))] + #[br(try_map(u8_to_bool))] pub fitted: bool, }