1use super::MAGIC;
2use log::trace;
3use std::fmt::Debug;
4
5pub trait Encodable: EncodeMessage + Debug {}
8
9pub trait EncodeMessage {
20 fn encode_op(&self) -> u8;
22 fn encode_htype(&self) -> u8;
24 fn encode_hlen(&self) -> u8;
26 fn encode_hops(&self) -> u8;
28 fn encode_xid(&self) -> [u8; 4];
30 fn encode_secs(&self) -> [u8; 2];
32 fn encode_flags(&self) -> [u8; 2];
34 fn encode_ciaddr(&self) -> [u8; 4];
36 fn encode_yiaddr(&self) -> [u8; 4];
38 fn encode_siaddr(&self) -> [u8; 4];
40 fn encode_giaddr(&self) -> [u8; 4];
42 fn encode_chaddr(&self) -> [u8; 16];
44 fn encode_sname(&self) -> [u8; 64];
46 fn encode_file(&self) -> [u8; 128];
48 fn encode_options(&self) -> Vec<u8>;
50
51 fn encode_magic(&self) -> [u8; 4] {
53 MAGIC
54 }
55
56 fn to_bytes(&self) -> Vec<u8> {
60 trace!("to_bytes");
61
62 let mut encoder = Encoder {
63 output: Vec::with_capacity(552),
64 };
65
66 trace!("encode op");
67 encoder.encode_byte(self.encode_op());
68 trace!("encode htype");
69 encoder.encode_byte(self.encode_htype());
70 trace!("encode hlen");
71 encoder.encode_byte(self.encode_hlen());
72 trace!("encode hops");
73 encoder.encode_byte(self.encode_hops());
74 trace!("encode xid");
75 encoder.encode_bytes(&self.encode_xid());
76 trace!("encode secs");
77 encoder.encode_bytes(&self.encode_secs());
78 trace!("encode flags");
79 encoder.encode_bytes(&self.encode_flags());
80 trace!("encode ciaddr");
81 encoder.encode_bytes(&self.encode_ciaddr());
82 trace!("encode yiaddr");
83 encoder.encode_bytes(&self.encode_yiaddr());
84 trace!("encode siaddr");
85 encoder.encode_bytes(&self.encode_siaddr());
86 trace!("encode giaddr");
87 encoder.encode_bytes(&self.encode_giaddr());
88 trace!("encode chaddr");
89 encoder.encode_bytes(&self.encode_chaddr());
90 trace!("encode sname");
91 encoder.encode_bytes(&self.encode_sname());
92 trace!("encode file");
93 encoder.encode_bytes(&self.encode_file());
94 trace!("encode magic");
95 encoder.encode_bytes(&self.encode_magic());
96 trace!("encode options");
97 encoder.encode_bytes(self.encode_options().as_slice());
98
99 encoder.encode_byte(255);
101
102 encoder.output
103 }
104}
105
106pub struct Encoder {
108 output: Vec<u8>,
110}
111
112impl Encoder {
114 #[inline]
115 fn encode_bytes(&mut self, v: &[u8]) {
116 trace!("encode_bytes");
117 self.output.extend_from_slice(v);
118 }
119
120 #[inline]
121 fn encode_byte(&mut self, v: u8) {
122 trace!("encode_byte");
123 self.output.push(v);
124 }
125}
126
127#[cfg(test)]
130mod tests {
131 use std::net::Ipv4Addr;
132
133 use super::*;
134 use crate::v4::*;
135
136 fn init_logger() {
139 let _ = env_logger::builder().is_test(true).try_init();
140 }
141
142 #[test]
143 fn test_to_bytes() {
144 init_logger();
145
146 let message = Message {
147 op: Ops::Request,
148 htype: HTypes::Ethernet,
149 hlen: 6,
150 hops: 1,
151 xid: 4,
152 secs: 2,
153 flags: Flags { broadcast: true },
154 ciaddr: Ipv4Addr::new(1, 1, 1, 1),
155 yiaddr: Ipv4Addr::new(1, 1, 1, 1),
156 siaddr: Ipv4Addr::new(1, 1, 1, 1),
157 giaddr: Ipv4Addr::new(1, 1, 1, 1),
158 chaddr: [3; 16],
159 sname: SName::new(c"000000000000000000000000000000000000000000000000000000000000000").unwrap(),
160 file: File::new(c"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@").unwrap(),
161 magic: [99, 130, 83, 99],
162 options: vec![
163 MessageOptions::MessageType(MessageTypes::Discover),
164 ],
165 };
166
167 let expected = vec![
168 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,
169 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,
170 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
171 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
172 48, 48, 48, 48, 48, 48, 48, 48, 48, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
173 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
174 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 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, 0, 99, 130, 83, 99, 53, 1, 1, 255,
179 ];
180
181 assert_eq!(message.to_bytes(), expected);
182 }
183}