1use std::io::{Cursor, Error, ErrorKind};
7use std::time::Duration;
8
9use bytes::{Buf, BytesMut};
10
11use crate::nineteen::header::decode_header;
12use crate::packet::ensure_packet_size;
13use crate::packet::event::{
14 Event, EventPacket, FastestLap, RaceWinner, Retirement, TeammateInPits,
15};
16
17pub const PACKET_SIZE: usize = 32;
22
23pub fn decode_event(cursor: &mut Cursor<&mut BytesMut>) -> Result<EventPacket, Error> {
30 ensure_packet_size(PACKET_SIZE, cursor)?;
31
32 let header = decode_header(cursor)?;
33 let event_code = decode_event_code(cursor);
34
35 let payload = match event_code.as_str() {
36 "SSTA" => Event::SessionStarted,
37 "SEND" => Event::SessionEnded,
38 "FTLP" => decode_fastest_lap(cursor),
39 "RTMT" => decode_retirement(cursor),
40 "DRSE" => Event::DrsEnabled,
41 "DRSD" => Event::DrsDisabled,
42 "TMPT" => decode_teammate_pits(cursor),
43 "CHQF" => Event::ChequeredFlag,
44 "RCWN" => decode_race_winner(cursor),
45 event_code => {
46 return Err(Error::new(
47 ErrorKind::InvalidData,
48 format!("Unexpected event code {}", event_code),
49 ))
50 }
51 };
52
53 Ok(EventPacket::new(header, payload))
54}
55
56fn decode_event_code(cursor: &mut Cursor<&mut BytesMut>) -> String {
61 [
62 cursor.get_u8() as char,
63 cursor.get_u8() as char,
64 cursor.get_u8() as char,
65 cursor.get_u8() as char,
66 ]
67 .iter()
68 .collect()
69}
70
71fn decode_fastest_lap(cursor: &mut Cursor<&mut BytesMut>) -> Event {
73 Event::FastestLap(FastestLap::new(
74 cursor.get_u8(),
75 Duration::from_secs_f32(cursor.get_f32_le()),
76 ))
77}
78
79fn decode_retirement(cursor: &mut Cursor<&mut BytesMut>) -> Event {
81 Event::Retirement(Retirement::new(cursor.get_u8()))
82}
83
84fn decode_teammate_pits(cursor: &mut Cursor<&mut BytesMut>) -> Event {
86 Event::TeammatesInPits(TeammateInPits::new(cursor.get_u8()))
87}
88
89fn decode_race_winner(cursor: &mut Cursor<&mut BytesMut>) -> Event {
91 Event::RaceWinner(RaceWinner::new(cursor.get_u8()))
92}
93
94#[cfg(test)]
95mod tests {
96 use std::io::Cursor;
97
98 use bytes::{BufMut, BytesMut};
99
100 use crate::nineteen::event::{decode_event, PACKET_SIZE};
101 use crate::packet::event::Event;
102
103 fn put_packet_header(mut bytes: BytesMut) -> BytesMut {
104 bytes.put_u16_le(2019);
105 bytes.put_u8(1);
106 bytes.put_u8(2);
107 bytes.put_u8(3);
108 bytes.put_u8(0);
109 bytes.put_u64_le(u64::max_value());
110 bytes.put_f32_le(1.0);
111 bytes.put_u32_le(u32::max_value());
112 bytes.put_u8(0);
113
114 bytes
115 }
116
117 #[test]
118 fn decode_event_with_error() {
119 let mut bytes = BytesMut::with_capacity(0);
120 let mut cursor = Cursor::new(&mut bytes);
121
122 let packet = decode_event(&mut cursor);
123 assert!(packet.is_err());
124 }
125
126 #[test]
127 fn decode_ftlp_event() {
128 let bytes = BytesMut::with_capacity(PACKET_SIZE);
129 let mut bytes = put_packet_header(bytes);
130
131 bytes.put_u8(b'F');
132 bytes.put_u8(b'T');
133 bytes.put_u8(b'L');
134 bytes.put_u8(b'P');
135 bytes.put_u8(1);
136 bytes.put_f32_le(2.0);
137
138 let mut cursor = Cursor::new(&mut bytes);
139
140 let packet = decode_event(&mut cursor).unwrap();
141 match packet.event() {
142 Event::FastestLap(fastest_lap) => assert_eq!(2, fastest_lap.time().as_secs()),
143 _ => panic!("Expected a fastest lap event"),
144 }
145 }
146
147 #[test]
148 fn decode_ssta_event() {
149 let bytes = BytesMut::with_capacity(PACKET_SIZE);
150 let mut bytes = put_packet_header(bytes);
151
152 bytes.put_u8(b'S');
153 bytes.put_u8(b'S');
154 bytes.put_u8(b'T');
155 bytes.put_u8(b'A');
156 let padding = vec![0u8; 5];
157 bytes.put(padding.as_slice());
158
159 let mut cursor = Cursor::new(&mut bytes);
160
161 let packet = decode_event(&mut cursor).unwrap();
162 assert_eq!(Event::SessionStarted, *packet.event())
163 }
164}