use std::io::{Cursor, Error, ErrorKind};
use std::time::Duration;
use bytes::{Buf, BytesMut};
use crate::nineteen::header::decode_header;
use crate::packet::ensure_packet_size;
use crate::packet::event::{
Event, EventPacket, FastestLap, RaceWinner, Retirement, TeammateInPits,
};
pub const PACKET_SIZE: usize = 32;
pub fn decode_event(cursor: &mut Cursor<&mut BytesMut>) -> Result<EventPacket, Error> {
ensure_packet_size(PACKET_SIZE, cursor)?;
let header = decode_header(cursor)?;
let event_code = decode_event_code(cursor);
let payload = match event_code.as_str() {
"SSTA" => Event::SessionStarted,
"SEND" => Event::SessionEnded,
"FTLP" => decode_fastest_lap(cursor),
"RTMT" => decode_retirement(cursor),
"DRSE" => Event::DrsEnabled,
"DRSD" => Event::DrsDisabled,
"TMPT" => decode_teammate_pits(cursor),
"CHQF" => Event::ChequeredFlag,
"RCWN" => decode_race_winner(cursor),
event_code => {
return Err(Error::new(
ErrorKind::InvalidData,
format!("Unexpected event code {}", event_code),
))
}
};
Ok(EventPacket::new(header, payload))
}
fn decode_event_code(cursor: &mut Cursor<&mut BytesMut>) -> String {
[
cursor.get_u8() as char,
cursor.get_u8() as char,
cursor.get_u8() as char,
cursor.get_u8() as char,
]
.iter()
.collect()
}
fn decode_fastest_lap(cursor: &mut Cursor<&mut BytesMut>) -> Event {
Event::FastestLap(FastestLap::new(
cursor.get_u8(),
Duration::from_secs_f32(cursor.get_f32_le()),
))
}
fn decode_retirement(cursor: &mut Cursor<&mut BytesMut>) -> Event {
Event::Retirement(Retirement::new(cursor.get_u8()))
}
fn decode_teammate_pits(cursor: &mut Cursor<&mut BytesMut>) -> Event {
Event::TeammatesInPits(TeammateInPits::new(cursor.get_u8()))
}
fn decode_race_winner(cursor: &mut Cursor<&mut BytesMut>) -> Event {
Event::RaceWinner(RaceWinner::new(cursor.get_u8()))
}
#[cfg(test)]
mod tests {
use std::io::Cursor;
use bytes::{BufMut, BytesMut};
use crate::nineteen::event::{decode_event, PACKET_SIZE};
use crate::packet::event::Event;
fn put_packet_header(mut bytes: BytesMut) -> BytesMut {
bytes.put_u16_le(2019);
bytes.put_u8(1);
bytes.put_u8(2);
bytes.put_u8(3);
bytes.put_u8(0);
bytes.put_u64_le(u64::max_value());
bytes.put_f32_le(1.0);
bytes.put_u32_le(u32::max_value());
bytes.put_u8(0);
bytes
}
#[test]
fn decode_event_with_error() {
let mut bytes = BytesMut::with_capacity(0);
let mut cursor = Cursor::new(&mut bytes);
let packet = decode_event(&mut cursor);
assert!(packet.is_err());
}
#[test]
fn decode_ftlp_event() {
let bytes = BytesMut::with_capacity(PACKET_SIZE);
let mut bytes = put_packet_header(bytes);
bytes.put_u8(b'F');
bytes.put_u8(b'T');
bytes.put_u8(b'L');
bytes.put_u8(b'P');
bytes.put_u8(1);
bytes.put_f32_le(2.0);
let mut cursor = Cursor::new(&mut bytes);
let packet = decode_event(&mut cursor).unwrap();
match packet.event() {
Event::FastestLap(fastest_lap) => assert_eq!(2, fastest_lap.time().as_secs()),
_ => panic!("Expected a fastest lap event"),
}
}
#[test]
fn decode_ssta_event() {
let bytes = BytesMut::with_capacity(PACKET_SIZE);
let mut bytes = put_packet_header(bytes);
bytes.put_u8(b'S');
bytes.put_u8(b'S');
bytes.put_u8(b'T');
bytes.put_u8(b'A');
let padding = vec![0u8; 5];
bytes.put(padding.as_slice());
let mut cursor = Cursor::new(&mut bytes);
let packet = decode_event(&mut cursor).unwrap();
assert_eq!(Event::SessionStarted, *packet.event())
}
}