1use core::fmt;
2use core::str;
3
4use crate::Error;
5
6#[derive(Debug, Clone)]
8pub struct Name<'a> {
9 pub(crate) buf: &'a [u8],
10 pub(crate) start: usize,
11}
12
13impl<'a> Name<'a> {
14 #[cfg(test)]
15 pub(crate) fn from_bytes(bytes: &'a [u8]) -> Self {
16 Self { buf: bytes, start: 0 }
17 }
18
19 pub(crate) fn create_pointer(&self, sub_name: &Name<'_>) -> Option<[u8; 2]> {
20 let mut labels = self.labels();
21
22 loop {
23 let i = labels.buf_i;
24
25 if labels.next().is_some() {
26 if self.equal_from(i, sub_name) {
27 let [ptr_1, ptr_2] = (i as u16).to_be_bytes();
28 return Some([ptr_1 | PTR_MASK, ptr_2]);
29 }
30
31 continue;
32 }
33
34 break;
35 }
36
37 None
38 }
39
40 fn equal_from(&self, i: usize, sub_name: &Name<'_>) -> bool {
41 let mut this = Labels { buf: self.buf, buf_i: i };
42 let mut other = sub_name.labels();
43
44 loop {
45 match (this.next(), other.next()) {
46 (Some(t), Some(o)) => if !t.as_str().eq_ignore_ascii_case(o.as_str()) {
47 break;
48 },
49 (None, None) => return true,
50 _ => break,
51 }
52 }
53
54 false
55 }
56
57 pub(crate) fn read(buf: &'a [u8], i: &'_ mut usize) -> Result<Self, Error> {
58 let mut j = *i;
59 let mut maximum = *i;
60 let mut ptr = None;
61
62 let mut len: u8 = 0;
63
64 loop {
65 match LabelType::read(buf, ptr.as_mut().unwrap_or(&mut j))? {
66 LabelType::Pointer(p) => {
67 let p = p as usize;
68
69 if p >= maximum {
71 return Err(Error::Pointer)
72 }
73
74 maximum = p;
75 ptr = Some(p);
76 },
77 LabelType::Part(part_len) => {
78 if part_len == 0 {
79 let name = Name {
80 buf,
81 start: *i,
82 };
83
84 *i = j;
85 return Ok(name)
86 }
87
88 if let Some(l) = len.checked_add(part_len) {
90 len = l;
91 } else {
92 return Err(Error::NameTooLong)
93 };
94 },
95 }
96 }
97 }
98
99 pub(crate) fn split(&self) -> (Label<'a>, Option<Name<'a>>) {
100 let mut labels = self.labels();
101
102 let label = labels.next().unwrap();
103 let name = labels.next().map(|l| Name { buf: l.buf, start: l.buf_i });
104
105 (label, name)
106 }
107
108 pub(crate) fn labels(&self) -> Labels<'a> {
109 Labels {
110 buf: self.buf,
111 buf_i: self.start,
112 }
113 }
114}
115
116impl fmt::Display for Name<'_> {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 let mut print_dot = false;
119
120 for label in self.labels() {
121 if print_dot {
122 '.'.fmt(f)?;
123 }
124
125 label.as_str().fmt(f)?;
126
127 print_dot = true;
128 }
129
130 Ok(())
131 }
132}
133
134impl PartialEq<str> for Name<'_> {
135 fn eq(&self, other: &str) -> bool {
136 let mut other_i = 0;
137
138 let other = other.as_bytes();
139
140 for label in self.labels() {
141 if other_i != 0 {
142 if other.get(other_i) != Some(&b'.') {
143 return false
144 } else {
145 other_i += 1;
146 }
147 }
148
149 if let Some(substring) = other.get(other_i..(other_i + label.len())) {
150 if !label.as_bytes().eq_ignore_ascii_case(substring) {
151 return false
152 }
153 } else {
154 return false
155 }
156
157 other_i += label.len();
158 }
159
160 other_i == other.len()
161 }
162}
163
164#[derive(Debug, Clone)]
165pub(crate) struct Labels<'a> {
166 buf: &'a [u8],
167 buf_i: usize,
168}
169
170impl<'a> Iterator for Labels<'a> {
171 type Item = Label<'a>;
172
173 fn next(&mut self) -> Option<Self::Item> {
174 loop {
175 match LabelType::read(self.buf, &mut self.buf_i).ok()? {
176 LabelType::Pointer(ptr) => {
177 self.buf_i = ptr as usize;
178 continue;
179 },
180 LabelType::Part(len) => {
181 if len == 0 {
182 return None
183 }
184
185 let label = Label {
186 buf: self.buf,
187 buf_i: self.buf_i - len as usize - 1,
188 };
189
190 return Some(label)
191 },
192 }
193 }
194 }
195}
196
197#[derive(Debug)]
198pub(crate) struct Label<'a> {
199 pub(crate) buf: &'a [u8],
200 pub(crate) buf_i: usize,
201}
202
203impl<'a> Label<'a> {
204 #[inline]
205 pub fn as_bytes(&self) -> &[u8] {
206 &self.buf[(self.buf_i + 1)..(self.buf_i + 1 + self.len())]
207 }
208
209 #[inline]
210 pub fn as_str(&self) -> &str {
211 unsafe { str::from_utf8_unchecked(self.as_bytes()) }
212 }
213
214 #[inline]
215 pub fn len(&self) -> usize {
216 self.buf[self.buf_i] as usize
217 }
218}
219
220#[derive(Debug)]
221pub(crate) enum LabelType {
222 Pointer(u16),
223 Part(u8),
224}
225
226const PTR_MASK: u8 = 0b11000000;
227const LEN_MASK: u8 = !PTR_MASK;
228
229impl LabelType {
230 pub(crate) fn read(buf: &[u8], i: &mut usize) -> Result<Self, Error> {
232 if let Some(&ptr_or_len) = buf.get(*i) {
233 if ptr_or_len & PTR_MASK == PTR_MASK {
236 if let Some(&ptr) = buf.get(*i + 1) {
237 *i += 1 + 1;
238 return Ok(Self::Pointer(u16::from_be_bytes([ptr_or_len & LEN_MASK, ptr])))
239 }
240 } else {
241 let len = ptr_or_len & LEN_MASK;
242
243 let j = *i + 1 + len as usize;
244 if j <= buf.len() {
245 *i = j;
246 return Ok(Self::Part(len))
247 }
248 }
249 }
250
251 Err(Error::MessageTooShort)
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_name_create_pointer() {
261 let name = Name::from_bytes(&[1, b'a', 1, b'b', 1, b'c', 0]);
262 let name_uppercase = Name::from_bytes(&[1, b'A', 1, b'B', 1, b'C', 0]);
263 let sub_name = Name::from_bytes(&[1, b'b', 1, b'c', 0]);
264 let sub_sub_name = Name::from_bytes(&[1, b'c', 0]);
265
266 assert_eq!(name.create_pointer(&name), Some([0b11000000, 0]));
267 assert_eq!(name_uppercase.create_pointer(&name), Some([0b11000000, 0]));
268 assert_eq!(name.create_pointer(&name_uppercase), Some([0b11000000, 0]));
269 assert_eq!(name.create_pointer(&sub_name), Some([0b11000000, 2]));
270 assert_eq!(sub_name.create_pointer(&name), None);
271 assert_eq!(sub_name.create_pointer(&sub_sub_name), Some([0b11000000, 2]));
272 assert_eq!(name.create_pointer(&sub_sub_name), Some([0b11000000, 4]));
273 assert_eq!(sub_sub_name.create_pointer(&name), None);
274 assert_eq!(sub_sub_name.create_pointer(&sub_name), None);
275 }
276}