toe_beans/v4/message/
slicer.rs1use std::cell::RefCell;
2
3use crate::v4::error::Result;
4use log::trace;
5
6pub struct Slicer<'de> {
15 input: &'de [u8],
16 input_index: usize,
17}
18
19impl<'de> Slicer<'de> {
20 pub fn new(input: &'de [u8]) -> Self {
22 Slicer {
23 input,
24 input_index: 0,
25 }
26 }
27
28 #[inline]
31 fn parse_unchecked(&mut self, len: usize) -> &'de [u8] {
32 trace!("parse_unchecked");
33 let slice = &self.input[self.input_index..self.input_index + len];
34 self.input_index += len;
35 slice
36 }
37
38 #[inline]
40 fn parse_remainder(&mut self) -> &'de [u8] {
41 trace!("parse_remainder");
42 let slice = &self.input[self.input_index..];
43 self.input_index += slice.len();
44 slice
45 }
46
47 #[inline]
49 pub fn parse(&mut self, len: usize) -> Option<&'de [u8]> {
50 trace!("parse");
51 let slice = self.input.get(self.input_index..self.input_index + len);
52
53 if slice.is_some() {
54 self.input_index += len;
55 }
56
57 slice
58 }
59}
60
61pub struct MessageSlicer<'de> {
67 slicer: RefCell<Slicer<'de>>,
68}
69
70impl<'de> MessageSlicer<'de> {
71 #[inline]
73 pub fn new(input: &'de [u8]) -> Result<Self> {
74 if input.len() < 240 {
75 return Err("Can't decode input less than 240 bytes");
76 }
77
78 Ok(Self {
79 slicer: RefCell::new(Slicer {
80 input,
81 input_index: 0,
82 }),
83 })
84 }
85
86 #[inline]
88 pub fn parse_op(&self) -> &'de [u8] {
89 trace!("parse_op");
90 self.slicer.borrow_mut().parse_unchecked(1)
91 }
92
93 #[inline]
95 pub fn parse_htype(&self) -> &'de [u8] {
96 trace!("parse_htypes");
97 self.slicer.borrow_mut().parse_unchecked(1)
98 }
99
100 #[inline]
102 pub fn parse_hlen(&self) -> &'de [u8] {
103 trace!("parse_hlen");
104 self.slicer.borrow_mut().parse_unchecked(1)
105 }
106
107 #[inline]
109 pub fn parse_hops(&self) -> &'de [u8] {
110 trace!("parse_hops");
111 self.slicer.borrow_mut().parse_unchecked(1)
112 }
113
114 #[inline]
116 pub fn parse_xid(&self) -> &'de [u8] {
117 trace!("parse_xid");
118 self.slicer.borrow_mut().parse_unchecked(4)
119 }
120
121 #[inline]
123 pub fn parse_secs(&self) -> &'de [u8] {
124 trace!("parse_secs");
125 self.slicer.borrow_mut().parse_unchecked(2)
126 }
127
128 #[inline]
130 pub fn parse_flags(&self) -> &'de [u8] {
131 trace!("parse_flags");
132 self.slicer.borrow_mut().parse_unchecked(2)
133 }
134
135 #[inline]
137 pub fn parse_ciaddr(&self) -> &'de [u8] {
138 trace!("parse_ciaddr");
139 self.slicer.borrow_mut().parse_unchecked(4)
140 }
141
142 #[inline]
144 pub fn parse_yiaddr(&self) -> &'de [u8] {
145 trace!("parse_yiaddr");
146 self.slicer.borrow_mut().parse_unchecked(4)
147 }
148
149 #[inline]
151 pub fn parse_siaddr(&self) -> &'de [u8] {
152 trace!("parse_siaddr");
153 self.slicer.borrow_mut().parse_unchecked(4)
154 }
155
156 #[inline]
158 pub fn parse_giaddr(&self) -> &'de [u8] {
159 trace!("parse_giaddr");
160 self.slicer.borrow_mut().parse_unchecked(4)
161 }
162
163 #[inline]
165 pub fn parse_chaddr(&self) -> &'de [u8] {
166 trace!("parse_chaddr");
167 self.slicer.borrow_mut().parse_unchecked(16)
168 }
169
170 #[inline]
172 pub fn parse_sname(&self) -> &'de [u8] {
173 trace!("parse_sname");
174 self.slicer.borrow_mut().parse_unchecked(64)
175 }
176
177 #[inline]
179 pub fn parse_file(&self) -> &'de [u8] {
180 trace!("parse_file");
181 self.slicer.borrow_mut().parse_unchecked(128)
182 }
183
184 #[inline]
186 pub fn parse_magic(&self) -> &'de [u8] {
187 trace!("parse_magic");
188 self.slicer.borrow_mut().parse_unchecked(4)
189 }
190
191 #[inline]
194 pub fn parse_options(&self) -> &'de [u8] {
195 trace!("parse_options");
196 self.slicer.borrow_mut().parse_remainder()
197 }
198}
199
200#[cfg(test)]
203mod tests {
204 use super::*;
205
206 fn init_logger() {
209 let _ = env_logger::builder().is_test(true).try_init();
210 }
211
212 #[test]
213 fn test_message_slicer_with_small_input() {
214 init_logger();
215 let input = &[0; 239];
216 let result = MessageSlicer::new(input);
217 assert!(result.is_err());
218 }
219
220 #[test]
221 fn test_message_slicer_with_large_input() {
222 init_logger();
223 let input = &[0; 240];
224 let result = MessageSlicer::new(input);
225 assert!(result.is_ok());
226 }
227}