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