1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
use crate::v4::{MAX_MESSAGE_SIZE, MagicBuffer, MessageBuffer, OptionsBuffer};
use log::trace;
/// UndecodedMessage takes a message's byte array from the socket. It can return smaller slices that
/// can be later decoded into a Message's field via `DecodeMessage`.
///
/// An advantage to using this over `Slicer` is that this doesn't process input from start to end,
/// so you may call its methods in any order and as many times as desired without needing to reset.
#[derive(Debug)]
pub struct UndecodedMessage(MessageBuffer);
impl UndecodedMessage {
/// `input` must be at least 240 bytes,
/// where 240 is the sum of all fixed Message field's bytes
/// and the first 4 ("magic") bytes of the variable options field.
#[inline]
pub fn new(buffer: MessageBuffer) -> Self {
Self(buffer)
}
/// Slices 1 byte to be used for the op field
#[inline]
pub fn slice_op(&self) -> u8 {
trace!("slice_op");
self.0[0] // PANIC: this won't panic because it is always within the fixed-size array.
}
/// Slices 1 byte to be used for the htype field
#[inline]
pub fn slice_htype(&self) -> u8 {
trace!("slice_htypes");
self.0[1] // PANIC: this won't panic because it is always within the fixed-size array.
}
/// Slices 1 byte to be used for the hlen field
#[inline]
pub fn slice_hlen(&self) -> u8 {
trace!("slice_hlen");
self.0[2] // PANIC: this won't panic because it is always within the fixed-size array.
}
/// Slices 1 byte to be used for the hops field
#[inline]
pub fn slice_hops(&self) -> u8 {
trace!("slice_hops");
self.0[3] // PANIC: this won't panic because it is always within the fixed-size array.
}
/// Slices 4 bytes to be used for the xid field
#[inline]
pub fn slice_xid(&self) -> [u8; 4] {
trace!("slice_xid");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[4..8].try_into().unwrap()
}
/// Slices 2 bytes to be used for the secs field
#[inline]
pub fn slice_secs(&self) -> [u8; 2] {
trace!("slice_secs");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[8..10].try_into().unwrap()
}
/// Slices 2 bytes to be used for the flags field
#[inline]
pub fn slice_flags(&self) -> [u8; 2] {
trace!("slice_flags");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[10..12].try_into().unwrap()
}
/// Slices the only byte currently used by the flags field.
///
/// Warning: If more bit flags are added via RFC then this may
/// need to change or be removed.
#[inline]
pub fn slice_flags_temporary(&self) -> u8 {
trace!("slice_flags_temporary");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[10]
}
/// Slices 4 bytes to be used for the ciaddr field
#[inline]
pub fn slice_ciaddr(&self) -> [u8; 4] {
trace!("slice_ciaddr");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[12..16].try_into().unwrap()
}
/// Slices 4 bytes to be used for the yiaddr field
#[inline]
pub fn slice_yiaddr(&self) -> [u8; 4] {
trace!("slice_yiaddr");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[16..20].try_into().unwrap()
}
/// Slices 4 bytes to be used for the siaddr field
#[inline]
pub fn slice_siaddr(&self) -> [u8; 4] {
trace!("slice_siaddr");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[20..24].try_into().unwrap()
}
/// Slices 4 bytes to be used for the giaddr field
#[inline]
pub fn slice_giaddr(&self) -> [u8; 4] {
trace!("slice_giaddr");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[24..28].try_into().unwrap()
}
/// Slices 16 bytes to be used for the chaddr field
#[inline]
pub fn slice_chaddr(&self) -> [u8; 16] {
trace!("slice_chaddr");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[28..44].try_into().unwrap()
}
/// Slices 64 bytes to be used for the sname field
#[inline]
pub fn slice_sname(&self) -> [u8; 64] {
trace!("slice_sname");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[44..108].try_into().unwrap()
}
/// Slices 128 bytes to be used for the file field
#[inline]
pub fn slice_file(&self) -> [u8; 128] {
trace!("slice_file");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[108..236].try_into().unwrap()
}
/// Slices 4 bytes to be used as the magic field
#[inline]
pub fn slice_magic(&self) -> MagicBuffer {
trace!("slice_magic");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[236..240].try_into().unwrap()
}
/// Slices remaining bytes in the input to be used as the options field
#[inline]
pub fn slice_options(&self) -> OptionsBuffer {
trace!("slice_options");
// PANIC: this won't panic because it is always within the fixed-size array.
self.0[240..MAX_MESSAGE_SIZE].try_into().unwrap()
}
}