1use std::io::{Read, Write};
2
3use crate::constants::*;
4use crate::error::Result;
5
6#[derive(Debug, Default)]
7pub struct Header {
8 signature: u64,
9 payload_length: u64,
10 expect_reponse: bool,
11 command: u32,
12 return_code: u32,
13 flags: u32,
14 version: u32,
15}
16
17impl Header {
18 pub fn new_request(command: u32) -> Self {
19 Self::new_unfragmented(true, command, 0, LevinMessage::Request)
20 }
21
22 pub fn new_response(command: u32, return_code: u32) -> Self {
23 Self::new_unfragmented(false, command, return_code, LevinMessage::Response)
24 }
25
26 pub fn new_notification(command: u32) -> Self {
27 Self::new_unfragmented(false, command, 0, LevinMessage::Notification)
28 }
29
30 pub fn from_reader<R: Read>(mut reader: R) -> Result<Self> {
31 let mut res = Self::default();
32 res.signature = read_fixed_u64(&mut reader)?;
33 res.payload_length = read_fixed_u64(&mut reader)?;
34 res.expect_reponse = read_bool(&mut reader)?;
35 res.command = read_fixed_u32(&mut reader)?;
36 res.return_code = read_fixed_u32(&mut reader)?;
37 res.flags = read_fixed_u32(&mut reader)?;
38 res.version = read_fixed_u32(&mut reader)?;
39 Ok(res)
40 }
41
42 pub fn to_writer<W: Write>(&self, mut writer: W) -> Result<()> {
43 write_fixed_u64(&mut writer, self.signature)?;
44 write_fixed_u64(&mut writer, self.payload_length)?;
45 write_bool(&mut writer, self.expect_reponse)?;
46 write_fixed_u32(&mut writer, self.command)?;
47 write_fixed_u32(&mut writer, self.return_code)?;
48 write_fixed_u32(&mut writer, self.flags)?;
49 write_fixed_u32(&mut writer, self.version)?;
50 Ok(())
51 }
52
53 pub fn set_payload_length(&mut self, length: usize) {
54 self.payload_length = length as u64;
55 }
56
57 fn new_unfragmented(
58 expect_reponse: bool,
59 command: u32,
60 return_code: u32,
61 msg_type: LevinMessage,
62 ) -> Self {
63 Self {
64 signature: u64::from_le_bytes(LEVIN_SIGNATURE),
65 payload_length: 0,
66 expect_reponse,
67 command,
68 return_code,
69 flags: make_flags(msg_type, LevinFragment::Unfragmented),
70 version: LEVIN_VERSION,
71 }
72 }
73}
74
75fn make_flags(msg_type: LevinMessage, frag_type: LevinFragment) -> u32 {
76 let msg_mask = match msg_type {
77 LevinMessage::Request => LEVIN_REQUEST_BIT,
78 LevinMessage::Notification => LEVIN_REQUEST_BIT,
79 LevinMessage::Response => LEVIN_RESPONSE_BIT,
80 LevinMessage::Dummy => 0,
81 };
82
83 let frag_mask = match frag_type {
84 LevinFragment::Begin => LEVIN_FRAG_BEGIN_BIT,
85 LevinFragment::Middle => 0,
86 LevinFragment::Unfragmented => 0,
87 LevinFragment::End => LEVIN_FRAG_END_BIT,
88 LevinFragment::Dummy => LEVIN_FRAG_BEGIN_BIT | LEVIN_FRAG_END_BIT,
89 };
90
91 return msg_mask | frag_mask;
92}
93
94fn read_fixed_u32<R: Read>(r: &mut R) -> std::io::Result<u32> {
95 let mut ibytes = [0u8; 4];
96 r.read_exact(&mut ibytes)?;
97 Ok(u32::from_le_bytes(ibytes))
98}
99
100fn read_fixed_u64<R: Read>(r: &mut R) -> std::io::Result<u64> {
101 let mut ibytes = [0u8; 8];
102 r.read_exact(&mut ibytes)?;
103 Ok(u64::from_le_bytes(ibytes))
104}
105
106fn read_bool<R: Read>(r: &mut R) -> std::io::Result<bool> {
107 let mut bbyte = 0u8;
108 r.read_exact(std::slice::from_mut(&mut bbyte))?;
109 Ok(bbyte != 0)
110}
111
112fn write_fixed_u32<W: Write>(w: &mut W, val: u32) -> std::io::Result<()> {
113 let ibytes = val.to_le_bytes();
114 w.write_all(&ibytes)
115}
116
117fn write_fixed_u64<W: Write>(w: &mut W, val: u64) -> std::io::Result<()> {
118 let ibytes = val.to_le_bytes();
119 w.write_all(&ibytes)
120}
121
122fn write_bool<W: Write>(w: &mut W, val: bool) -> std::io::Result<()> {
123 let bbyte = if val { 1u8 } else { 0 };
124 w.write(std::slice::from_ref(&bbyte))?;
125 Ok(())
126}