hickory_proto/serialize/binary/decoder.rs
1/*
2 * Copyright (C) 2015 Benjamin Fry <benjaminfry@me.com>
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17use crate::serialize::binary::Restrict;
18use thiserror::Error;
19
20/// This is non-destructive to the inner buffer, b/c for pointer types we need to perform a reverse
21/// seek to lookup names
22///
23/// A note on serialization, there was a thought to have this implement the Serde deserializer,
24/// but given that this is such a small subset of all the serialization which that performs
25/// this is a simpler implementation without the cruft, at least for serializing to/from the
26/// binary DNS protocols.
27pub struct BinDecoder<'a> {
28 buffer: &'a [u8], // The entire original buffer
29 remaining: &'a [u8], // The unread section of the original buffer, so that reads do not cause a bounds check at the current seek offset
30}
31
32pub(crate) type DecodeResult<T> = Result<T, DecodeError>;
33
34/// An error that can occur deep in a decoder
35/// This type is kept very small so that function that use it inline often
36#[derive(Clone, Copy, Debug, Error)]
37#[non_exhaustive]
38pub enum DecodeError {
39 /// Insufficient data in the buffer for a read operation
40 #[error("unexpected end of input reached")]
41 InsufficientBytes,
42
43 /// slice_from was called with an invalid index
44 #[error(
45 "the index passed to BinDecoder::slice_from must be greater than the decoder position"
46 )]
47 InvalidPreviousIndex,
48
49 /// Pointer points to an index within or after the current label
50 #[error("label points to data not prior to idx: {idx} ptr: {ptr}")]
51 PointerNotPriorToLabel {
52 /// index of the label containing this pointer
53 idx: usize,
54 /// location to which the pointer is directing
55 ptr: u16,
56 },
57
58 /// Label bytes exceeded the limit of 63
59 #[error("label bytes exceed 63: {0}")]
60 LabelBytesTooLong(usize),
61
62 /// An unrecognized label code was found
63 #[error("unrecognized label code: {0:b}")]
64 UnrecognizedLabelCode(u8),
65
66 /// A domain name was too long
67 #[error("name label data exceed 255: {0}")]
68 DomainNameTooLong(usize),
69
70 /// Overlapping labels
71 #[error("overlapping labels name {label} other {other}")]
72 LabelOverlapsWithOther {
73 /// Start of the label that is overlaps
74 label: usize,
75 /// Start of the other label
76 other: usize,
77 },
78}
79
80impl<'a> BinDecoder<'a> {
81 /// Creates a new BinDecoder
82 ///
83 /// # Arguments
84 ///
85 /// * `buffer` - buffer from which all data will be read
86 pub fn new(buffer: &'a [u8]) -> Self {
87 BinDecoder {
88 buffer,
89 remaining: buffer,
90 }
91 }
92
93 /// Pop one byte from the buffer
94 pub fn pop(&mut self) -> DecodeResult<Restrict<u8>> {
95 if let Some((first, remaining)) = self.remaining.split_first() {
96 self.remaining = remaining;
97 return Ok(Restrict::new(*first));
98 }
99 Err(DecodeError::InsufficientBytes)
100 }
101
102 /// Returns the number of bytes in the buffer
103 ///
104 /// ```
105 /// use hickory_proto::serialize::binary::BinDecoder;
106 ///
107 /// let deadbeef = b"deadbeef";
108 /// let mut decoder = BinDecoder::new(deadbeef);
109 /// assert_eq!(decoder.len(), 8);
110 /// decoder.read_slice(7).unwrap();
111 /// assert_eq!(decoder.len(), 1);
112 /// ```
113 pub fn len(&self) -> usize {
114 self.remaining.len()
115 }
116
117 /// Returns `true` if the buffer is empty
118 pub fn is_empty(&self) -> bool {
119 self.len() == 0
120 }
121
122 /// Peed one byte forward, without moving the current index forward
123 pub fn peek(&self) -> Option<Restrict<u8>> {
124 Some(Restrict::new(*self.remaining.first()?))
125 }
126
127 /// Returns the current index in the buffer
128 pub fn index(&self) -> usize {
129 self.buffer.len() - self.remaining.len()
130 }
131
132 /// This is a pretty efficient clone, as the buffer is never cloned, and only the index is set
133 /// to the value passed in
134 pub fn clone(&self, index_at: u16) -> Self {
135 BinDecoder {
136 buffer: self.buffer,
137 remaining: &self.buffer[index_at as usize..],
138 }
139 }
140
141 /// Reads a String from the buffer
142 ///
143 /// ```text
144 /// <character-string> is a single
145 /// length octet followed by that number of characters. <character-string>
146 /// is treated as binary information, and can be up to 256 characters in
147 /// length (including the length octet).
148 /// ```
149 ///
150 /// # Returns
151 ///
152 /// A String version of the character data
153 pub fn read_character_data(&mut self) -> DecodeResult<Restrict<&[u8]>> {
154 let length = self.pop()?.unverified() as usize;
155 self.read_slice(length)
156 }
157
158 /// Reads a Vec out of the buffer
159 ///
160 /// # Arguments
161 ///
162 /// * `len` - number of bytes to read from the buffer
163 ///
164 /// # Returns
165 ///
166 /// The Vec of the specified length, otherwise an error
167 pub fn read_vec(&mut self, len: usize) -> DecodeResult<Restrict<Vec<u8>>> {
168 self.read_slice(len).map(|s| s.map(ToOwned::to_owned))
169 }
170
171 /// Reads a slice out of the buffer, without allocating
172 ///
173 /// # Arguments
174 ///
175 /// * `len` - number of bytes to read from the buffer
176 ///
177 /// # Returns
178 ///
179 /// The slice of the specified length, otherwise an error
180 pub fn read_slice(&mut self, len: usize) -> DecodeResult<Restrict<&'a [u8]>> {
181 if len > self.remaining.len() {
182 return Err(DecodeError::InsufficientBytes);
183 }
184 let (read, remaining) = self.remaining.split_at(len);
185 self.remaining = remaining;
186 Ok(Restrict::new(read))
187 }
188
189 /// Reads a slice from a previous index to the current
190 pub fn slice_from(&self, index: usize) -> DecodeResult<&'a [u8]> {
191 if index > self.index() {
192 return Err(DecodeError::InvalidPreviousIndex);
193 }
194
195 Ok(&self.buffer[index..self.index()])
196 }
197
198 /// Reads a byte from the buffer, equivalent to `Self::pop()`
199 pub fn read_u8(&mut self) -> DecodeResult<Restrict<u8>> {
200 self.pop()
201 }
202
203 /// Reads the next 2 bytes into u16
204 ///
205 /// This performs a byte-by-byte manipulation, there
206 /// which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
207 ///
208 /// # Return
209 ///
210 /// Return the u16 from the buffer
211 pub fn read_u16(&mut self) -> DecodeResult<Restrict<u16>> {
212 Ok(self
213 .read_slice(2)?
214 .map(|s| u16::from_be_bytes([s[0], s[1]])))
215 }
216
217 /// Reads the next four bytes into i32.
218 ///
219 /// This performs a byte-by-byte manipulation, there
220 /// which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
221 ///
222 /// # Return
223 ///
224 /// Return the i32 from the buffer
225 pub fn read_i32(&mut self) -> DecodeResult<Restrict<i32>> {
226 Ok(self.read_slice(4)?.map(|s| {
227 assert!(s.len() == 4);
228 i32::from_be_bytes([s[0], s[1], s[2], s[3]])
229 }))
230 }
231
232 /// Reads the next four bytes into u32.
233 ///
234 /// This performs a byte-by-byte manipulation, there
235 /// which means endianness is implicitly handled (i.e. no network to little endian (intel), issues)
236 ///
237 /// # Return
238 ///
239 /// Return the u32 from the buffer
240 pub fn read_u32(&mut self) -> DecodeResult<Restrict<u32>> {
241 Ok(self.read_slice(4)?.map(|s| {
242 assert!(s.len() == 4);
243 u32::from_be_bytes([s[0], s[1], s[2], s[3]])
244 }))
245 }
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251
252 #[test]
253 fn test_read_slice() {
254 let deadbeef = b"deadbeef";
255 let mut decoder = BinDecoder::new(deadbeef);
256
257 let read = decoder.read_slice(4).expect("failed to read dead");
258 assert_eq!(&read.unverified(), b"dead");
259
260 let read = decoder.read_slice(2).expect("failed to read be");
261 assert_eq!(&read.unverified(), b"be");
262
263 let read = decoder.read_slice(0).expect("failed to read nothing");
264 assert_eq!(&read.unverified(), b"");
265
266 // this should fail
267 assert!(decoder.read_slice(3).is_err());
268 }
269
270 #[test]
271 fn test_read_slice_from() {
272 let deadbeef = b"deadbeef";
273 let mut decoder = BinDecoder::new(deadbeef);
274
275 decoder.read_slice(4).expect("failed to read dead");
276 let read = decoder.slice_from(0).expect("failed to get slice");
277 assert_eq!(&read, b"dead");
278
279 decoder.read_slice(2).expect("failed to read be");
280 let read = decoder.slice_from(4).expect("failed to get slice");
281 assert_eq!(&read, b"be");
282
283 decoder.read_slice(0).expect("failed to read nothing");
284 let read = decoder.slice_from(4).expect("failed to get slice");
285 assert_eq!(&read, b"be");
286
287 // this should fail
288 assert!(decoder.slice_from(10).is_err());
289 }
290}