fix: resolve 7 code review issues from v0.4.x

- Fix KSUDP clutch field reading fuel at offset 59 (KSUDP has no clutch input)
- Replace Notify with watch::channel for reliable shutdown (no missed wakeups)
- Deduplicate read_u16 from parser_pcars into shared binary_utils
- Remove dead Display impl for FeedSource
- Remove unused read_i8 helper from binary_utils
- Change Vec<Instant> to [Instant; 50] in FeedState (eliminate heap alloc)
- Cache rarely-changing strings by driver_id in Telemetry Tool parser
This commit is contained in:
Jan-Peter von Hunnius 2026-06-04 11:12:55 +02:00
parent 8f50302a78
commit 56d3169033
7 changed files with 98 additions and 45 deletions

View file

@ -104,6 +104,7 @@ pub fn parse_packet(data: &[u8]) -> Result<TelemetryToolPacket, TelemetryToolPar
///
/// Avoids allocating a `Vec` for all drivers when only the local player's
/// telemetry is needed.
#[allow(dead_code)]
pub fn parse_first_driver(data: &[u8]) -> Result<TelemetryFrame, TelemetryToolParseError> {
if data.is_empty() {
return Err(TelemetryToolParseError::TooShort { actual: 0, needed: 1 });
@ -125,8 +126,56 @@ pub fn parse_first_driver(data: &[u8]) -> Result<TelemetryFrame, TelemetryToolPa
parse_driver(&payload[..DRIVER_STRUCT_SIZE])
}
/// Parse only the first driver, skipping rarely-changing string fields.
///
/// Returns a tuple of (frame, raw_driver_id). Strings can be populated
/// from a cache keyed by `raw_driver_id`.
pub fn parse_first_driver_no_strings(data: &[u8]) -> Result<(TelemetryFrame, u32), TelemetryToolParseError> {
if data.is_empty() {
return Err(TelemetryToolParseError::TooShort { actual: 0, needed: 1 });
}
let packet_type = data[0];
if packet_type != PACKET_TYPE_TELEMETRY {
return Err(TelemetryToolParseError::UnknownPacketType { got: packet_type });
}
let payload = &data[1..];
if payload.len() < DRIVER_STRUCT_SIZE {
return Err(TelemetryToolParseError::TooShort {
actual: data.len(),
needed: 1 + DRIVER_STRUCT_SIZE,
});
}
let driver_data = &payload[..DRIVER_STRUCT_SIZE];
let driver_id = read_u32(driver_data, 0);
let mut frame = parse_driver_core(driver_data)?;
frame.driver_id = Some(driver_id);
Ok((frame, driver_id))
}
pub const STRING_OFFSET_DRIVER_NAME: usize = 1 + 97;
pub const STRING_LEN_DRIVER_NAME: usize = 33;
pub const STRING_OFFSET_NATIONALITY: usize = 1 + 130;
pub const STRING_LEN_NATIONALITY: usize = 4;
pub const STRING_OFFSET_CAR_NAME: usize = 1 + 134;
pub const STRING_LEN_CAR_NAME: usize = 33;
pub const STRING_OFFSET_TYRE_COMPOUND: usize = 1 + 167;
pub const STRING_LEN_TYRE_COMPOUND: usize = 10;
/// Parse a single 357-byte driver structure.
fn parse_driver(data: &[u8]) -> Result<TelemetryFrame, TelemetryToolParseError> {
let mut frame = parse_driver_core(data)?;
frame.driver_id = Some(read_u32(data, 0));
frame.driver_name = Some(read_string(data, 97, 33));
frame.nationality = Some(read_string(data, 130, 4));
frame.car_name = Some(read_string(data, 134, 33));
frame.tyre_compound = Some(read_string(data, 167, 10));
Ok(frame)
}
fn parse_driver_core(data: &[u8]) -> Result<TelemetryFrame, TelemetryToolParseError> {
// Validation: check test_float at offset 93
let test_float_val = read_f32(data, 93);
if (test_float_val - TEST_FLOAT).abs() > 1.0 {
@ -195,11 +244,6 @@ fn parse_driver(data: &[u8]) -> Result<TelemetryFrame, TelemetryToolParseError>
tyre_slip: read_f32_4(data, 305),
// Telemetry Tool-specific fields
driver_id: Some(read_u32(data, 0)),
driver_name: Some(read_string(data, 97, 33)),
nationality: Some(read_string(data, 130, 4)),
car_name: Some(read_string(data, 134, 33)),
tyre_compound: Some(read_string(data, 167, 10)),
track_position: Some(read_i16(data, 67)),
leaderboard_position: Some(read_i16(data, 69)),
is_connected: Some(read_bool(data, 181)),