1use super::MAGIC;
2use crate::v4::{MAX_MESSAGE_SIZE, MagicBuffer};
3use log::trace;
4use std::fmt::Debug;
5
6pub trait Encodable: EncodeMessage + Debug {}
9
10pub trait EncodeMessage {
21 fn encode_op(&self) -> u8;
23 fn encode_htype(&self) -> u8;
25 fn encode_hlen(&self) -> u8;
27 fn encode_hops(&self) -> u8;
29 fn encode_xid(&self) -> [u8; 4];
31 fn encode_secs(&self) -> [u8; 2];
33 fn encode_flags(&self) -> [u8; 2];
35 fn encode_ciaddr(&self) -> [u8; 4];
37 fn encode_yiaddr(&self) -> [u8; 4];
39 fn encode_siaddr(&self) -> [u8; 4];
41 fn encode_giaddr(&self) -> [u8; 4];
43 fn encode_chaddr(&self) -> [u8; 16];
45 fn encode_sname(&self) -> [u8; 64];
47 fn encode_file(&self) -> [u8; 128];
49 fn encode_options(&self) -> Vec<u8>;
51
52 fn encode_magic(&self) -> MagicBuffer {
54 MAGIC
55 }
56
57 fn to_bytes(&self) -> Vec<u8> {
61 trace!("to_bytes");
62
63 let mut encoder = Encoder {
64 output: Vec::with_capacity(MAX_MESSAGE_SIZE),
65 };
66
67 trace!("encode op");
68 encoder.encode_byte(self.encode_op());
69 trace!("encode htype");
70 encoder.encode_byte(self.encode_htype());
71 trace!("encode hlen");
72 encoder.encode_byte(self.encode_hlen());
73 trace!("encode hops");
74 encoder.encode_byte(self.encode_hops());
75 trace!("encode xid");
76 encoder.encode_bytes(&self.encode_xid());
77 trace!("encode secs");
78 encoder.encode_bytes(&self.encode_secs());
79 trace!("encode flags");
80 encoder.encode_bytes(&self.encode_flags());
81 trace!("encode ciaddr");
82 encoder.encode_bytes(&self.encode_ciaddr());
83 trace!("encode yiaddr");
84 encoder.encode_bytes(&self.encode_yiaddr());
85 trace!("encode siaddr");
86 encoder.encode_bytes(&self.encode_siaddr());
87 trace!("encode giaddr");
88 encoder.encode_bytes(&self.encode_giaddr());
89 trace!("encode chaddr");
90 encoder.encode_bytes(&self.encode_chaddr());
91 trace!("encode sname");
92 encoder.encode_bytes(&self.encode_sname());
93 trace!("encode file");
94 encoder.encode_bytes(&self.encode_file());
95 trace!("encode magic");
96 encoder.encode_bytes(&self.encode_magic());
97 trace!("encode options");
98 encoder.encode_bytes(self.encode_options().as_slice());
99
100 encoder.encode_byte(255);
102
103 encoder.output
104 }
105}
106
107#[derive(Debug)]
109pub struct Encoder {
110 output: Vec<u8>,
112}
113
114impl Encoder {
116 #[inline]
117 fn encode_bytes(&mut self, v: &[u8]) {
118 trace!("encode_bytes");
119 self.output.extend_from_slice(v);
120 }
121
122 #[inline]
123 fn encode_byte(&mut self, v: u8) {
124 trace!("encode_byte");
125 self.output.push(v);
126 }
127}
128
129#[cfg(test)]
132mod tests {
133 use std::net::Ipv4Addr;
134
135 use super::*;
136 use crate::v4::*;
137
138 fn init_logger() {
141 let _ = env_logger::builder().is_test(true).try_init();
142 }
143
144 #[test]
145 fn test_to_bytes() {
146 init_logger();
147
148 let message = Message {
149 op: Ops::Request,
150 htype: HTypes::Ethernet,
151 hlen: 6,
152 hops: 1,
153 xid: 4,
154 secs: 2,
155 flags: Flags { broadcast: true },
156 ciaddr: Ipv4Addr::new(1, 1, 1, 1),
157 yiaddr: Ipv4Addr::new(1, 1, 1, 1),
158 siaddr: Ipv4Addr::new(1, 1, 1, 1),
159 giaddr: Ipv4Addr::new(1, 1, 1, 1),
160 chaddr: [3; 16],
161 sname: SName::new(c"000000000000000000000000000000000000000000000000000000000000000").unwrap(),
162 file: File::new(c"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@").unwrap(),
163 magic: [99, 130, 83, 99],
164 options: vec![
165 MessageOptions::MessageType(MessageTypes::Discover),
166 ],
167 };
168
169 let expected = vec![
170 1, 1, 6, 1, 0, 0, 0, 4, 0, 2, 128, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
171 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
172 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
173 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
174 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
175 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
176 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
177 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
178 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
179 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
180 64, 64, 64, 64, 64, 0, 99, 130, 83, 99, 53, 1, 1, 255,
181 ];
182
183 assert_eq!(message.to_bytes(), expected);
184 }
185}