1use crate::*;
10
11#[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
21pub struct Header {
22 pub msgtype: u8,
23 pub psize: u32,
24 pub pubkey: [u8; 32],
25 pub nonce: [u8; 24],
26 pub encrypted: bool,
27}
28
29impl Header {
30 pub fn new() -> Header {
32 Header::default()
33 }
34
35 pub fn set_msgtype<T: Into<u8>>(mut self, msgtype: T) -> Header {
37 self.msgtype = msgtype.into();
38 self
39 }
40
41 pub fn set_psize<T: Into<u32>>(mut self, psize: T) -> Header {
43 self.psize = psize.into();
44 self
45 }
46
47 pub fn set_pubkey<T: Into<[u8; 32]>>(mut self, pubkey: T) -> Header {
49 self.pubkey = pubkey.into();
50 self
51 }
52
53 pub fn set_nonce<T: RngCore + CryptoRng>(mut self, csprng: &mut T) -> Result<Header> {
55 let mut nonce: [u8; 24] = [0u8; 24];
56 csprng.try_fill_bytes(&mut nonce)?;
57 self.nonce = nonce;
58 Ok(self)
59 }
60
61 pub fn set_encrypted(mut self, encrypted: bool) -> Header {
63 self.encrypted = encrypted;
64 self
65 }
66
67 pub fn to_bytes(self) -> [u8; 64] {
69 let mut header_bytes = [0u8; 64];
70 let reserved = [0u8; 2];
71 [self.msgtype]
72 .iter()
73 .chain(self.psize.to_be_bytes().iter())
74 .chain(self.pubkey.iter())
75 .chain(self.nonce.iter())
76 .chain([self.encrypted as u8].iter())
77 .chain(reserved.iter())
78 .enumerate()
79 .for_each(|(i, x)| header_bytes[i] = *x);
80
81 header_bytes
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 use rmp_serde as rmps;
91
92 enum MsgType {
93 Hello,
94 Unknown,
95 }
96
97 impl From<u8> for MsgType {
98 fn from(t: u8) -> MsgType {
99 match t {
100 0 => MsgType::Hello,
101 _ => MsgType::Unknown,
102 }
103 }
104 }
105
106 impl From<MsgType> for u8 {
107 fn from(t: MsgType) -> u8 {
108 match t {
109 MsgType::Hello => 0,
110 MsgType::Unknown => 255,
111 }
112 }
113 }
114
115 #[derive(Default, Debug, Clone, PartialEq, PartialOrd, Serialize, Deserialize)]
116 pub struct Hello {
117 name: String,
118 age: u8,
119 }
120
121 impl Job for Hello {
122 fn encode(&self) -> Vec<u8> {
123 rmps::to_vec(&self).unwrap()
124 }
125
126 fn decode(input: &[u8]) -> Hello {
127 let hello: Hello = rmps::from_read(input).unwrap();
128 hello
129 }
130
131 fn ack(&self) -> Vec<u8> {
132 let name = &self.name;
133 let age = &self.age;
134 let ack_string = format!("Hello from {name}, aged {age}");
135 Vec::from(ack_string)
136 }
137
138 fn run(&self) -> std::result::Result<(), Box<dyn std::error::Error>> {
139 self.ack();
140 Ok(())
141 }
142 }
143
144 #[test]
145 fn test_header_new() {
146 let header = Header::new();
147
148 assert_eq!(header.msgtype, 0u8);
149 assert_eq!(header.psize, 0u32);
150 assert_eq!(header.pubkey, [0u8; 32]);
151 assert_eq!(header.nonce, [0u8; 24]);
152 assert!(!header.encrypted);
153 }
154
155 #[test]
156 fn test_header_msgtype() {
157 let header = Header::new().set_msgtype(MsgType::Hello);
158
159 assert_eq!(header.msgtype, 0u8)
160 }
161
162 #[test]
163 fn test_header_psize() {
164 let header = Header::new().set_psize(10u32);
165
166 assert_eq!(header.psize, 10);
167 }
168
169 #[test]
170 fn test_header_pubkey() {
171 let mut rng = rand::thread_rng();
172 let secret_key = crypto_box::SecretKey::generate(&mut rng);
173 let pubkey = secret_key.public_key().as_bytes().to_owned();
174 let header = Header::new().set_pubkey(pubkey);
175
176 assert_eq!(header.pubkey, pubkey);
177 }
178
179 #[test]
180 fn test_header_nonce() {
181 let mut rng = rand::thread_rng();
182 let header = Header::new().set_nonce(&mut rng).unwrap();
183
184 assert_ne!(header.nonce, [0u8; 24]);
185 }
186
187 #[test]
188 fn test_header_encrypted() {
189 let header = Header::new().set_encrypted(true);
190
191 assert!(header.encrypted)
192 }
193 #[test]
194 fn test_header_bytes() {
195 let mut rng = rand::thread_rng();
196 let secret_key = crypto_box::SecretKey::generate(&mut rng);
197 let pubkey = secret_key.public_key().as_bytes().to_owned();
198 let header = Header::new()
199 .set_msgtype(MsgType::Hello)
200 .set_psize(10u32)
201 .set_pubkey(pubkey)
202 .set_nonce(&mut rng)
203 .unwrap();
204
205 let header_bytes = header.to_bytes();
206 assert_eq!(header_bytes[..5], [0, 0, 0, 0, 10]);
207 assert_eq!(header_bytes[5..37], pubkey);
208 assert_ne!(header_bytes[37..61], [0u8; 24]);
209 assert_eq!(header_bytes[61], 0u8);
210 assert_eq!(header_bytes[62..], [0u8; 2]);
211 }
212}