1use crate::parser::ParseError;
2use crate::parser::Parsed;
3use crate::serializer::{Serializable, SerializeError};
4use crate::{byte_reader, command, version, zero_bytes};
5
6#[derive(PartialEq, Debug)]
7pub struct Header {
8 command: command::Kind,
9 version: version::Version,
10}
11
12pub fn parse(cursor: usize, bytes: &[u8]) -> Result<Parsed<Header>, ParseError> {
13 let (command, cursor) = command::Kind::parse(cursor, bytes)?;
14 let (version_byte, cursor) = byte_reader::read(cursor, bytes)?;
15 let version_value = version::Version::from_u8(version_byte);
16 let cursor = zero_bytes::skip(2, cursor, bytes)?;
17 let header = Header::new(command, version_value);
18
19 Ok((header, cursor))
20}
21
22impl Header {
23 pub fn new(command: command::Kind, version: version::Version) -> Self {
24 Header { command, version }
25 }
26
27 pub fn get_command(&self) -> command::Kind {
28 self.command
29 }
30
31 pub fn get_version(&self) -> version::Version {
32 self.version
33 }
34}
35
36impl Serializable for Header {
37 fn to_bytes(&self) -> Result<Vec<u8>, SerializeError> {
38 let command_bytes = self.get_command().to_bytes()?;
39 let version_bytes = self.get_version().to_bytes()?;
40 Ok([command_bytes, version_bytes, vec![0, 0]].concat())
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use crate::header::Header;
47 use crate::parser::ParseError;
48 use crate::serializer::Serializable;
49 use crate::{command, header, version};
50
51 #[test]
52 fn test_to_bytes() {
53 assert_eq!(
54 Header::new(command::Kind::Request, version::Version::Version2)
55 .to_bytes()
56 .unwrap(),
57 vec![0x01, 0x02, 0x00, 0x00]
58 );
59 }
60
61 #[test]
62 fn test_parse() {
63 let (header, cursor) = header::parse(0, vec![0x01, 0x02, 0x00, 0x00].as_slice()).unwrap();
64 assert_eq!(
65 header,
66 Header::new(command::Kind::Request, version::Version::Version2)
67 );
68 assert_eq!(cursor, 4);
69 }
70
71 #[test]
72 fn test_parse_has_non_zero_byte() {
73 let err = header::parse(0, vec![0x01, 0x02, 0x01, 0x00].as_slice()).unwrap_err();
74 assert_eq!(err, ParseError::NotZeroByte(0x01, 3));
75
76 let err = header::parse(0, vec![0x01, 0x02, 0x00, 0x02].as_slice()).unwrap_err();
77 assert_eq!(err, ParseError::NotZeroByte(0x02, 4));
78 }
79}