evtc_parse/
header.rs
1use crate::{
2 util::{read_string_buffer, write_string_buffer, Endian},
3 Parse, ParseError, Save,
4};
5use byteorder::{ReadBytesExt, WriteBytesExt};
6use std::io;
7
8#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, PartialEq, Eq)]
13#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
14pub struct Header {
15 pub date: String,
17
18 pub revision: u8,
20
21 pub boss_id: u16,
26}
27
28impl Header {
29 pub const DATE_SIZE: usize = 12;
31}
32
33impl Parse for Header {
34 type Error = ParseError;
35
36 fn parse(input: &mut impl io::Read) -> Result<Self, Self::Error> {
37 let evtc = read_string_buffer::<4>(input)?;
38 if evtc != "EVTC" {
39 return Err(ParseError::NotEvtc);
40 }
41
42 let date = read_string_buffer::<{ Self::DATE_SIZE - 4 }>(input)?;
43 let revision = input.read_u8()?;
44 let boss_id = input.read_u16::<Endian>()?;
45
46 input.read_u8()?;
48
49 Ok(Self {
50 date: evtc + &date,
51 revision,
52 boss_id,
53 })
54 }
55}
56
57impl Save for Header {
58 type Error = io::Error;
59
60 fn save(&self, output: &mut impl io::Write) -> Result<(), Self::Error> {
61 write_string_buffer::<{ Self::DATE_SIZE }>(output, &self.date)?;
62 output.write_u8(self.revision)?;
63 output.write_u16::<Endian>(self.boss_id)?;
64
65 output.write_u8(0)
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use super::*;
73
74 #[test]
75 fn header() {
76 let header = Header {
77 date: "EVTC20230328".into(),
78 revision: 1,
79 boss_id: 123,
80 };
81
82 let mut vec = Vec::with_capacity(64);
83 header.save(&mut vec).unwrap();
84
85 let parsed = Header::parse(&mut vec.as_slice()).unwrap();
86 assert_eq!(parsed, header);
87 }
88}