/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/arrayvec-0.7.4/src/arrayvec.rs
Line
Count
Source (jump to first uncovered line)
1
2
use std::cmp;
3
use std::iter;
4
use std::mem;
5
use std::ops::{Bound, Deref, DerefMut, RangeBounds};
6
use std::ptr;
7
use std::slice;
8
9
// extra traits
10
use std::borrow::{Borrow, BorrowMut};
11
use std::hash::{Hash, Hasher};
12
use std::fmt;
13
14
#[cfg(feature="std")]
15
use std::io;
16
17
use std::mem::ManuallyDrop;
18
use std::mem::MaybeUninit;
19
20
#[cfg(feature="serde")]
21
use serde::{Serialize, Deserialize, Serializer, Deserializer};
22
23
use crate::LenUint;
24
use crate::errors::CapacityError;
25
use crate::arrayvec_impl::ArrayVecImpl;
26
use crate::utils::MakeMaybeUninit;
27
28
/// A vector with a fixed capacity.
29
///
30
/// The `ArrayVec` is a vector backed by a fixed size array. It keeps track of
31
/// the number of initialized elements. The `ArrayVec<T, CAP>` is parameterized
32
/// by `T` for the element type and `CAP` for the maximum capacity.
33
///
34
/// `CAP` is of type `usize` but is range limited to `u32::MAX`; attempting to create larger
35
/// arrayvecs with larger capacity will panic.
36
///
37
/// The vector is a contiguous value (storing the elements inline) that you can store directly on
38
/// the stack if needed.
39
///
40
/// It offers a simple API but also dereferences to a slice, so that the full slice API is
41
/// available. The ArrayVec can be converted into a by value iterator.
42
pub struct ArrayVec<T, const CAP: usize> {
43
    // the `len` first elements of the array are initialized
44
    xs: [MaybeUninit<T>; CAP],
45
    len: LenUint,
46
}
47
48
impl<T, const CAP: usize> Drop for ArrayVec<T, CAP> {
49
2.25k
    fn drop(&mut self) {
50
2.25k
        self.clear();
51
2.25k
52
2.25k
        // MaybeUninit inhibits array's drop
53
2.25k
    }
_RNvXNtCskQaAGJdWXwX_8arrayvec8arrayvecINtB2_8ArrayVechKj1000_ENtNtNtCs6xNykbTfrCs_4core3ops4drop4Drop4dropCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
49
1.12k
    fn drop(&mut self) {
50
1.12k
        self.clear();
51
1.12k
52
1.12k
        // MaybeUninit inhibits array's drop
53
1.12k
    }
_RNvXNtCskQaAGJdWXwX_8arrayvec8arrayvecINtB2_8ArrayVecjKj10_ENtNtNtCs6xNykbTfrCs_4core3ops4drop4Drop4dropCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
49
1.12k
    fn drop(&mut self) {
50
1.12k
        self.clear();
51
1.12k
52
1.12k
        // MaybeUninit inhibits array's drop
53
1.12k
    }
Unexecuted instantiation: _RNvXNtCskQaAGJdWXwX_8arrayvec8arrayvecINtB2_8ArrayVecjKj80_ENtNtNtCs6xNykbTfrCs_4core3ops4drop4Drop4dropCslLTLXfmDngu_8flex_dns
54
}
55
56
macro_rules! panic_oob {
57
    ($method_name:expr, $index:expr, $len:expr) => {
58
        panic!(concat!("ArrayVec::", $method_name, ": index {} is out of bounds in vector of length {}"),
59
               $index, $len)
60
    }
61
}
62
63
impl<T, const CAP: usize> ArrayVec<T, CAP> {
64
    /// Capacity
65
    const CAPACITY: usize = CAP;
66
67
    /// Create a new empty `ArrayVec`.
68
    ///
69
    /// The maximum capacity is given by the generic parameter `CAP`.
70
    ///
71
    /// ```
72
    /// use arrayvec::ArrayVec;
73
    ///
74
    /// let mut array = ArrayVec::<_, 16>::new();
75
    /// array.push(1);
76
    /// array.push(2);
77
    /// assert_eq!(&array[..], &[1, 2]);
78
    /// assert_eq!(array.capacity(), 16);
79
    /// ```
80
    #[inline]
81
    #[track_caller]
82
2.25k
    pub fn new() -> ArrayVec<T, CAP> {
83
2.25k
        assert_capacity_limit!(CAP);
84
        unsafe {
85
2.25k
            ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 }
86
2.25k
        }
87
2.25k
    }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVechKj1000_E3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
82
1.12k
    pub fn new() -> ArrayVec<T, CAP> {
83
1.12k
        assert_capacity_limit!(CAP);
84
        unsafe {
85
1.12k
            ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 }
86
1.12k
        }
87
1.12k
    }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj10_E3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
82
1.12k
    pub fn new() -> ArrayVec<T, CAP> {
83
1.12k
        assert_capacity_limit!(CAP);
84
        unsafe {
85
1.12k
            ArrayVec { xs: MaybeUninit::uninit().assume_init(), len: 0 }
86
1.12k
        }
87
1.12k
    }
Unexecuted instantiation: _RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj80_E3newCslLTLXfmDngu_8flex_dns
88
89
    /// Create a new empty `ArrayVec` (const fn).
90
    ///
91
    /// The maximum capacity is given by the generic parameter `CAP`.
92
    ///
93
    /// ```
94
    /// use arrayvec::ArrayVec;
95
    ///
96
    /// static ARRAY: ArrayVec<u8, 1024> = ArrayVec::new_const();
97
    /// ```
98
    pub const fn new_const() -> ArrayVec<T, CAP> {
99
        assert_capacity_limit_const!(CAP);
100
        ArrayVec { xs: MakeMaybeUninit::ARRAY, len: 0 }
101
    }
102
103
    /// Return the number of elements in the `ArrayVec`.
104
    ///
105
    /// ```
106
    /// use arrayvec::ArrayVec;
107
    ///
108
    /// let mut array = ArrayVec::from([1, 2, 3]);
109
    /// array.pop();
110
    /// assert_eq!(array.len(), 2);
111
    /// ```
112
    #[inline(always)]
113
30.5k
    pub const fn len(&self) -> usize { self.len as usize }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVechKj1000_E3lenCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
113
29.4k
    pub const fn len(&self) -> usize { self.len as usize }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj10_E3lenCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
113
1.12k
    pub const fn len(&self) -> usize { self.len as usize }
Unexecuted instantiation: _RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj80_E3lenCslLTLXfmDngu_8flex_dns
114
115
    /// Returns whether the `ArrayVec` is empty.
116
    ///
117
    /// ```
118
    /// use arrayvec::ArrayVec;
119
    ///
120
    /// let mut array = ArrayVec::from([1]);
121
    /// array.pop();
122
    /// assert_eq!(array.is_empty(), true);
123
    /// ```
124
    #[inline]
125
    pub const fn is_empty(&self) -> bool { self.len() == 0 }
126
127
    /// Return the capacity of the `ArrayVec`.
128
    ///
129
    /// ```
130
    /// use arrayvec::ArrayVec;
131
    ///
132
    /// let array = ArrayVec::from([1, 2, 3]);
133
    /// assert_eq!(array.capacity(), 3);
134
    /// ```
135
    #[inline(always)]
136
2.29k
    pub const fn capacity(&self) -> usize { CAP }
137
138
    /// Return true if the `ArrayVec` is completely filled to its capacity, false otherwise.
139
    ///
140
    /// ```
141
    /// use arrayvec::ArrayVec;
142
    ///
143
    /// let mut array = ArrayVec::<_, 1>::new();
144
    /// assert!(!array.is_full());
145
    /// array.push(1);
146
    /// assert!(array.is_full());
147
    /// ```
148
    pub const fn is_full(&self) -> bool { self.len() == self.capacity() }
149
150
    /// Returns the capacity left in the `ArrayVec`.
151
    ///
152
    /// ```
153
    /// use arrayvec::ArrayVec;
154
    ///
155
    /// let mut array = ArrayVec::from([1, 2, 3]);
156
    /// array.pop();
157
    /// assert_eq!(array.remaining_capacity(), 1);
158
    /// ```
159
1.16k
    pub const fn remaining_capacity(&self) -> usize {
160
1.16k
        self.capacity() - self.len()
161
1.16k
    }
162
163
    /// Push `element` to the end of the vector.
164
    ///
165
    /// ***Panics*** if the vector is already full.
166
    ///
167
    /// ```
168
    /// use arrayvec::ArrayVec;
169
    ///
170
    /// let mut array = ArrayVec::<_, 2>::new();
171
    ///
172
    /// array.push(1);
173
    /// array.push(2);
174
    ///
175
    /// assert_eq!(&array[..], &[1, 2]);
176
    /// ```
177
    #[track_caller]
178
0
    pub fn push(&mut self, element: T) {
179
0
        ArrayVecImpl::push(self, element)
180
0
    }
181
182
    /// Push `element` to the end of the vector.
183
    ///
184
    /// Return `Ok` if the push succeeds, or return an error if the vector
185
    /// is already full.
186
    ///
187
    /// ```
188
    /// use arrayvec::ArrayVec;
189
    ///
190
    /// let mut array = ArrayVec::<_, 2>::new();
191
    ///
192
    /// let push1 = array.try_push(1);
193
    /// let push2 = array.try_push(2);
194
    ///
195
    /// assert!(push1.is_ok());
196
    /// assert!(push2.is_ok());
197
    ///
198
    /// assert_eq!(&array[..], &[1, 2]);
199
    ///
200
    /// let overflow = array.try_push(3);
201
    ///
202
    /// assert!(overflow.is_err());
203
    /// ```
204
    pub fn try_push(&mut self, element: T) -> Result<(), CapacityError<T>> {
205
        ArrayVecImpl::try_push(self, element)
206
    }
207
208
    /// Push `element` to the end of the vector without checking the capacity.
209
    ///
210
    /// It is up to the caller to ensure the capacity of the vector is
211
    /// sufficiently large.
212
    ///
213
    /// This method uses *debug assertions* to check that the arrayvec is not full.
214
    ///
215
    /// ```
216
    /// use arrayvec::ArrayVec;
217
    ///
218
    /// let mut array = ArrayVec::<_, 2>::new();
219
    ///
220
    /// if array.len() + 2 <= array.capacity() {
221
    ///     unsafe {
222
    ///         array.push_unchecked(1);
223
    ///         array.push_unchecked(2);
224
    ///     }
225
    /// }
226
    ///
227
    /// assert_eq!(&array[..], &[1, 2]);
228
    /// ```
229
    pub unsafe fn push_unchecked(&mut self, element: T) {
230
        ArrayVecImpl::push_unchecked(self, element)
231
    }
232
233
    /// Shortens the vector, keeping the first `len` elements and dropping
234
    /// the rest.
235
    ///
236
    /// If `len` is greater than the vector’s current length this has no
237
    /// effect.
238
    ///
239
    /// ```
240
    /// use arrayvec::ArrayVec;
241
    ///
242
    /// let mut array = ArrayVec::from([1, 2, 3, 4, 5]);
243
    /// array.truncate(3);
244
    /// assert_eq!(&array[..], &[1, 2, 3]);
245
    /// array.truncate(4);
246
    /// assert_eq!(&array[..], &[1, 2, 3]);
247
    /// ```
248
    pub fn truncate(&mut self, new_len: usize) {
249
        ArrayVecImpl::truncate(self, new_len)
250
    }
251
252
    /// Remove all elements in the vector.
253
2.25k
    pub fn clear(&mut self) {
254
2.25k
        ArrayVecImpl::clear(self)
255
2.25k
    }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVechKj1000_E5clearCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
253
1.12k
    pub fn clear(&mut self) {
254
1.12k
        ArrayVecImpl::clear(self)
255
1.12k
    }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj10_E5clearCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
253
1.12k
    pub fn clear(&mut self) {
254
1.12k
        ArrayVecImpl::clear(self)
255
1.12k
    }
Unexecuted instantiation: _RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj80_E5clearCslLTLXfmDngu_8flex_dns
256
257
258
    /// Get pointer to where element at `index` would be
259
1.16k
    unsafe fn get_unchecked_ptr(&mut self, index: usize) -> *mut T {
260
1.16k
        self.as_mut_ptr().add(index)
261
1.16k
    }
262
263
    /// Insert `element` at position `index`.
264
    ///
265
    /// Shift up all elements after `index`.
266
    ///
267
    /// It is an error if the index is greater than the length or if the
268
    /// arrayvec is full.
269
    ///
270
    /// ***Panics*** if the array is full or the `index` is out of bounds. See
271
    /// `try_insert` for fallible version.
272
    ///
273
    /// ```
274
    /// use arrayvec::ArrayVec;
275
    ///
276
    /// let mut array = ArrayVec::<_, 2>::new();
277
    ///
278
    /// array.insert(0, "x");
279
    /// array.insert(0, "y");
280
    /// assert_eq!(&array[..], &["y", "x"]);
281
    ///
282
    /// ```
283
    #[track_caller]
284
    pub fn insert(&mut self, index: usize, element: T) {
285
        self.try_insert(index, element).unwrap()
286
    }
287
288
    /// Insert `element` at position `index`.
289
    ///
290
    /// Shift up all elements after `index`; the `index` must be less than
291
    /// or equal to the length.
292
    ///
293
    /// Returns an error if vector is already at full capacity.
294
    ///
295
    /// ***Panics*** `index` is out of bounds.
296
    ///
297
    /// ```
298
    /// use arrayvec::ArrayVec;
299
    ///
300
    /// let mut array = ArrayVec::<_, 2>::new();
301
    ///
302
    /// assert!(array.try_insert(0, "x").is_ok());
303
    /// assert!(array.try_insert(0, "y").is_ok());
304
    /// assert!(array.try_insert(0, "z").is_err());
305
    /// assert_eq!(&array[..], &["y", "x"]);
306
    ///
307
    /// ```
308
    pub fn try_insert(&mut self, index: usize, element: T) -> Result<(), CapacityError<T>> {
309
        if index > self.len() {
310
            panic_oob!("try_insert", index, self.len())
311
        }
312
        if self.len() == self.capacity() {
313
            return Err(CapacityError::new(element));
314
        }
315
        let len = self.len();
316
317
        // follows is just like Vec<T>
318
        unsafe { // infallible
319
            // The spot to put the new value
320
            {
321
                let p: *mut _ = self.get_unchecked_ptr(index);
322
                // Shift everything over to make space. (Duplicating the
323
                // `index`th element into two consecutive places.)
324
                ptr::copy(p, p.offset(1), len - index);
325
                // Write it in, overwriting the first copy of the `index`th
326
                // element.
327
                ptr::write(p, element);
328
            }
329
            self.set_len(len + 1);
330
        }
331
        Ok(())
332
    }
333
334
    /// Remove the last element in the vector and return it.
335
    ///
336
    /// Return `Some(` *element* `)` if the vector is non-empty, else `None`.
337
    ///
338
    /// ```
339
    /// use arrayvec::ArrayVec;
340
    ///
341
    /// let mut array = ArrayVec::<_, 2>::new();
342
    ///
343
    /// array.push(1);
344
    ///
345
    /// assert_eq!(array.pop(), Some(1));
346
    /// assert_eq!(array.pop(), None);
347
    /// ```
348
    pub fn pop(&mut self) -> Option<T> {
349
        ArrayVecImpl::pop(self)
350
    }
351
352
    /// Remove the element at `index` and swap the last element into its place.
353
    ///
354
    /// This operation is O(1).
355
    ///
356
    /// Return the *element* if the index is in bounds, else panic.
357
    ///
358
    /// ***Panics*** if the `index` is out of bounds.
359
    ///
360
    /// ```
361
    /// use arrayvec::ArrayVec;
362
    ///
363
    /// let mut array = ArrayVec::from([1, 2, 3]);
364
    ///
365
    /// assert_eq!(array.swap_remove(0), 1);
366
    /// assert_eq!(&array[..], &[3, 2]);
367
    ///
368
    /// assert_eq!(array.swap_remove(1), 2);
369
    /// assert_eq!(&array[..], &[3]);
370
    /// ```
371
    pub fn swap_remove(&mut self, index: usize) -> T {
372
        self.swap_pop(index)
373
            .unwrap_or_else(|| {
374
                panic_oob!("swap_remove", index, self.len())
375
            })
376
    }
377
378
    /// Remove the element at `index` and swap the last element into its place.
379
    ///
380
    /// This is a checked version of `.swap_remove`.  
381
    /// This operation is O(1).
382
    ///
383
    /// Return `Some(` *element* `)` if the index is in bounds, else `None`.
384
    ///
385
    /// ```
386
    /// use arrayvec::ArrayVec;
387
    ///
388
    /// let mut array = ArrayVec::from([1, 2, 3]);
389
    ///
390
    /// assert_eq!(array.swap_pop(0), Some(1));
391
    /// assert_eq!(&array[..], &[3, 2]);
392
    ///
393
    /// assert_eq!(array.swap_pop(10), None);
394
    /// ```
395
    pub fn swap_pop(&mut self, index: usize) -> Option<T> {
396
        let len = self.len();
397
        if index >= len {
398
            return None;
399
        }
400
        self.swap(index, len - 1);
401
        self.pop()
402
    }
403
404
    /// Remove the element at `index` and shift down the following elements.
405
    ///
406
    /// The `index` must be strictly less than the length of the vector.
407
    ///
408
    /// ***Panics*** if the `index` is out of bounds.
409
    ///
410
    /// ```
411
    /// use arrayvec::ArrayVec;
412
    ///
413
    /// let mut array = ArrayVec::from([1, 2, 3]);
414
    ///
415
    /// let removed_elt = array.remove(0);
416
    /// assert_eq!(removed_elt, 1);
417
    /// assert_eq!(&array[..], &[2, 3]);
418
    /// ```
419
    pub fn remove(&mut self, index: usize) -> T {
420
        self.pop_at(index)
421
            .unwrap_or_else(|| {
422
                panic_oob!("remove", index, self.len())
423
            })
424
    }
425
426
    /// Remove the element at `index` and shift down the following elements.
427
    ///
428
    /// This is a checked version of `.remove(index)`. Returns `None` if there
429
    /// is no element at `index`. Otherwise, return the element inside `Some`.
430
    ///
431
    /// ```
432
    /// use arrayvec::ArrayVec;
433
    ///
434
    /// let mut array = ArrayVec::from([1, 2, 3]);
435
    ///
436
    /// assert!(array.pop_at(0).is_some());
437
    /// assert_eq!(&array[..], &[2, 3]);
438
    ///
439
    /// assert!(array.pop_at(2).is_none());
440
    /// assert!(array.pop_at(10).is_none());
441
    /// ```
442
    pub fn pop_at(&mut self, index: usize) -> Option<T> {
443
        if index >= self.len() {
444
            None
445
        } else {
446
            self.drain(index..index + 1).next()
447
        }
448
    }
449
450
    /// Retains only the elements specified by the predicate.
451
    ///
452
    /// In other words, remove all elements `e` such that `f(&mut e)` returns false.
453
    /// This method operates in place and preserves the order of the retained
454
    /// elements.
455
    ///
456
    /// ```
457
    /// use arrayvec::ArrayVec;
458
    ///
459
    /// let mut array = ArrayVec::from([1, 2, 3, 4]);
460
    /// array.retain(|x| *x & 1 != 0 );
461
    /// assert_eq!(&array[..], &[1, 3]);
462
    /// ```
463
    pub fn retain<F>(&mut self, mut f: F)
464
        where F: FnMut(&mut T) -> bool
465
    {
466
        // Check the implementation of
467
        // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.retain
468
        // for safety arguments (especially regarding panics in f and when
469
        // dropping elements). Implementation closely mirrored here.
470
471
        let original_len = self.len();
472
        unsafe { self.set_len(0) };
473
474
        struct BackshiftOnDrop<'a, T, const CAP: usize> {
475
            v: &'a mut ArrayVec<T, CAP>,
476
            processed_len: usize,
477
            deleted_cnt: usize,
478
            original_len: usize,
479
        }
480
481
        impl<T, const CAP: usize> Drop for BackshiftOnDrop<'_, T, CAP> {
482
            fn drop(&mut self) {
483
                if self.deleted_cnt > 0 {
484
                    unsafe {
485
                        ptr::copy(
486
                            self.v.as_ptr().add(self.processed_len),
487
                            self.v.as_mut_ptr().add(self.processed_len - self.deleted_cnt),
488
                            self.original_len - self.processed_len
489
                        );
490
                    }
491
                }
492
                unsafe {
493
                    self.v.set_len(self.original_len - self.deleted_cnt);
494
                }
495
            }
496
        }
497
498
        let mut g = BackshiftOnDrop { v: self, processed_len: 0, deleted_cnt: 0, original_len };
499
500
        #[inline(always)]
501
        fn process_one<F: FnMut(&mut T) -> bool, T, const CAP: usize, const DELETED: bool>(
502
            f: &mut F,
503
            g: &mut BackshiftOnDrop<'_, T, CAP>
504
        ) -> bool {
505
            let cur = unsafe { g.v.as_mut_ptr().add(g.processed_len) };
506
            if !f(unsafe { &mut *cur }) {
507
                g.processed_len += 1;
508
                g.deleted_cnt += 1;
509
                unsafe { ptr::drop_in_place(cur) };
510
                return false;
511
            }
512
            if DELETED {
513
                unsafe {
514
                    let hole_slot = cur.sub(g.deleted_cnt);
515
                    ptr::copy_nonoverlapping(cur, hole_slot, 1);
516
                }
517
            }
518
            g.processed_len += 1;
519
            true
520
        }
521
522
        // Stage 1: Nothing was deleted.
523
        while g.processed_len != original_len {
524
            if !process_one::<F, T, CAP, false>(&mut f, &mut g) {
525
                break;
526
            }
527
        }
528
529
        // Stage 2: Some elements were deleted.
530
        while g.processed_len != original_len {
531
            process_one::<F, T, CAP, true>(&mut f, &mut g);
532
        }
533
534
        drop(g);
535
    }
536
537
    /// Set the vector’s length without dropping or moving out elements
538
    ///
539
    /// This method is `unsafe` because it changes the notion of the
540
    /// number of “valid” elements in the vector. Use with care.
541
    ///
542
    /// This method uses *debug assertions* to check that `length` is
543
    /// not greater than the capacity.
544
1.16k
    pub unsafe fn set_len(&mut self, length: usize) {
545
        // type invariant that capacity always fits in LenUint
546
0
        debug_assert!(length <= self.capacity());
547
1.16k
        self.len = length as LenUint;
548
1.16k
    }
549
550
    /// Copy all elements from the slice and append to the `ArrayVec`.
551
    ///
552
    /// ```
553
    /// use arrayvec::ArrayVec;
554
    ///
555
    /// let mut vec: ArrayVec<usize, 10> = ArrayVec::new();
556
    /// vec.push(1);
557
    /// vec.try_extend_from_slice(&[2, 3]).unwrap();
558
    /// assert_eq!(&vec[..], &[1, 2, 3]);
559
    /// ```
560
    ///
561
    /// # Errors
562
    ///
563
    /// This method will return an error if the capacity left (see
564
    /// [`remaining_capacity`]) is smaller then the length of the provided
565
    /// slice.
566
    ///
567
    /// [`remaining_capacity`]: #method.remaining_capacity
568
1.16k
    pub fn try_extend_from_slice(&mut self, other: &[T]) -> Result<(), CapacityError>
569
1.16k
        where T: Copy,
570
1.16k
    {
571
1.16k
        if self.remaining_capacity() < other.len() {
572
0
            return Err(CapacityError::new(()));
573
1.16k
        }
574
1.16k
575
1.16k
        let self_len = self.len();
576
1.16k
        let other_len = other.len();
577
1.16k
578
1.16k
        unsafe {
579
1.16k
            let dst = self.get_unchecked_ptr(self_len);
580
1.16k
            ptr::copy_nonoverlapping(other.as_ptr(), dst, other_len);
581
1.16k
            self.set_len(self_len + other_len);
582
1.16k
        }
583
1.16k
        Ok(())
584
1.16k
    }
585
586
    /// Create a draining iterator that removes the specified range in the vector
587
    /// and yields the removed items from start to end. The element range is
588
    /// removed even if the iterator is not consumed until the end.
589
    ///
590
    /// Note: It is unspecified how many elements are removed from the vector,
591
    /// if the `Drain` value is leaked.
592
    ///
593
    /// **Panics** if the starting point is greater than the end point or if
594
    /// the end point is greater than the length of the vector.
595
    ///
596
    /// ```
597
    /// use arrayvec::ArrayVec;
598
    ///
599
    /// let mut v1 = ArrayVec::from([1, 2, 3]);
600
    /// let v2: ArrayVec<_, 3> = v1.drain(0..2).collect();
601
    /// assert_eq!(&v1[..], &[3]);
602
    /// assert_eq!(&v2[..], &[1, 2]);
603
    /// ```
604
    pub fn drain<R>(&mut self, range: R) -> Drain<T, CAP>
605
        where R: RangeBounds<usize>
606
    {
607
        // Memory safety
608
        //
609
        // When the Drain is first created, it shortens the length of
610
        // the source vector to make sure no uninitialized or moved-from elements
611
        // are accessible at all if the Drain's destructor never gets to run.
612
        //
613
        // Drain will ptr::read out the values to remove.
614
        // When finished, remaining tail of the vec is copied back to cover
615
        // the hole, and the vector length is restored to the new length.
616
        //
617
        let len = self.len();
618
        let start = match range.start_bound() {
619
            Bound::Unbounded => 0,
620
            Bound::Included(&i) => i,
621
            Bound::Excluded(&i) => i.saturating_add(1),
622
        };
623
        let end = match range.end_bound() {
624
            Bound::Excluded(&j) => j,
625
            Bound::Included(&j) => j.saturating_add(1),
626
            Bound::Unbounded => len,
627
        };
628
        self.drain_range(start, end)
629
    }
630
631
    fn drain_range(&mut self, start: usize, end: usize) -> Drain<T, CAP>
632
    {
633
        let len = self.len();
634
635
        // bounds check happens here (before length is changed!)
636
        let range_slice: *const _ = &self[start..end];
637
638
        // Calling `set_len` creates a fresh and thus unique mutable references, making all
639
        // older aliases we created invalid. So we cannot call that function.
640
        self.len = start as LenUint;
641
642
        unsafe {
643
            Drain {
644
                tail_start: end,
645
                tail_len: len - end,
646
                iter: (*range_slice).iter(),
647
                vec: self as *mut _,
648
            }
649
        }
650
    }
651
652
    /// Return the inner fixed size array, if it is full to its capacity.
653
    ///
654
    /// Return an `Ok` value with the array if length equals capacity,
655
    /// return an `Err` with self otherwise.
656
    pub fn into_inner(self) -> Result<[T; CAP], Self> {
657
        if self.len() < self.capacity() {
658
            Err(self)
659
        } else {
660
            unsafe { Ok(self.into_inner_unchecked()) }
661
        }
662
    }
663
664
    /// Return the inner fixed size array.
665
    ///
666
    /// Safety:
667
    /// This operation is safe if and only if length equals capacity.
668
    pub unsafe fn into_inner_unchecked(self) -> [T; CAP] {
669
        debug_assert_eq!(self.len(), self.capacity());
670
        let self_ = ManuallyDrop::new(self);
671
        let array = ptr::read(self_.as_ptr() as *const [T; CAP]);
672
        array
673
    }
674
675
    /// Returns the ArrayVec, replacing the original with a new empty ArrayVec.
676
    ///
677
    /// ```
678
    /// use arrayvec::ArrayVec;
679
    ///
680
    /// let mut v = ArrayVec::from([0, 1, 2, 3]);
681
    /// assert_eq!([0, 1, 2, 3], v.take().into_inner().unwrap());
682
    /// assert!(v.is_empty());
683
    /// ```
684
    pub fn take(&mut self) -> Self  {
685
        mem::replace(self, Self::new())
686
    }
687
688
    /// Return a slice containing all elements of the vector.
689
11.2k
    pub fn as_slice(&self) -> &[T] {
690
11.2k
        ArrayVecImpl::as_slice(self)
691
11.2k
    }
_RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVechKj1000_E8as_sliceCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
689
11.2k
    pub fn as_slice(&self) -> &[T] {
690
11.2k
        ArrayVecImpl::as_slice(self)
691
11.2k
    }
Unexecuted instantiation: _RNvMs_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB4_8ArrayVecjKj80_E8as_sliceCslLTLXfmDngu_8flex_dns
692
693
    /// Return a mutable slice containing all elements of the vector.
694
    pub fn as_mut_slice(&mut self) -> &mut [T] {
695
        ArrayVecImpl::as_mut_slice(self)
696
    }
697
698
    /// Return a raw pointer to the vector's buffer.
699
    pub fn as_ptr(&self) -> *const T {
700
        ArrayVecImpl::as_ptr(self)
701
    }
702
703
    /// Return a raw mutable pointer to the vector's buffer.
704
1.16k
    pub fn as_mut_ptr(&mut self) -> *mut T {
705
1.16k
        ArrayVecImpl::as_mut_ptr(self)
706
1.16k
    }
707
}
708
709
impl<T, const CAP: usize> ArrayVecImpl for ArrayVec<T, CAP> {
710
    type Item = T;
711
    const CAPACITY: usize = CAP;
712
713
13.5k
    fn len(&self) -> usize { self.len() }
_RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj10_ENtNtB7_13arrayvec_impl12ArrayVecImpl3lenCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
713
1.12k
    fn len(&self) -> usize { self.len() }
_RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl3lenCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
713
12.4k
    fn len(&self) -> usize { self.len() }
Unexecuted instantiation: _RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl3lenCslLTLXfmDngu_8flex_dns
714
715
1.12k
    unsafe fn set_len(&mut self, length: usize) {
716
0
        debug_assert!(length <= CAP);
717
1.12k
        self.len = length as LenUint;
718
1.12k
    }
_RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl7set_lenCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
715
1.12k
    unsafe fn set_len(&mut self, length: usize) {
716
0
        debug_assert!(length <= CAP);
717
1.12k
        self.len = length as LenUint;
718
1.12k
    }
Unexecuted instantiation: _RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj10_ENtNtB7_13arrayvec_impl12ArrayVecImpl7set_lenCsgg978DXfVXR_13fuzz_target_1
Unexecuted instantiation: _RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl7set_lenCslLTLXfmDngu_8flex_dns
719
720
11.2k
    fn as_ptr(&self) -> *const Self::Item {
721
11.2k
        self.xs.as_ptr() as _
722
11.2k
    }
_RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl6as_ptrCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
720
11.2k
    fn as_ptr(&self) -> *const Self::Item {
721
11.2k
        self.xs.as_ptr() as _
722
11.2k
    }
Unexecuted instantiation: _RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl6as_ptrCslLTLXfmDngu_8flex_dns
723
724
2.29k
    fn as_mut_ptr(&mut self) -> *mut Self::Item {
725
2.29k
        self.xs.as_mut_ptr() as _
726
2.29k
    }
Unexecuted instantiation: _RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj10_ENtNtB7_13arrayvec_impl12ArrayVecImpl10as_mut_ptrCsgg978DXfVXR_13fuzz_target_1
_RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl10as_mut_ptrCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
724
2.29k
    fn as_mut_ptr(&mut self) -> *mut Self::Item {
725
2.29k
        self.xs.as_mut_ptr() as _
726
2.29k
    }
Unexecuted instantiation: _RNvXs0_NtCskQaAGJdWXwX_8arrayvec8arrayvecINtB5_8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl10as_mut_ptrCslLTLXfmDngu_8flex_dns
727
}
728
729
impl<T, const CAP: usize> Deref for ArrayVec<T, CAP> {
730
    type Target = [T];
731
    #[inline]
732
0
    fn deref(&self) -> &Self::Target {
733
0
        self.as_slice()
734
0
    }
735
}
736
737
impl<T, const CAP: usize> DerefMut for ArrayVec<T, CAP> {
738
    #[inline]
739
    fn deref_mut(&mut self) -> &mut Self::Target {
740
        self.as_mut_slice()
741
    }
742
}
743
744
745
/// Create an `ArrayVec` from an array.
746
///
747
/// ```
748
/// use arrayvec::ArrayVec;
749
///
750
/// let mut array = ArrayVec::from([1, 2, 3]);
751
/// assert_eq!(array.len(), 3);
752
/// assert_eq!(array.capacity(), 3);
753
/// ```
754
impl<T, const CAP: usize> From<[T; CAP]> for ArrayVec<T, CAP> {
755
    #[track_caller]
756
    fn from(array: [T; CAP]) -> Self {
757
        let array = ManuallyDrop::new(array);
758
        let mut vec = <ArrayVec<T, CAP>>::new();
759
        unsafe {
760
            (&*array as *const [T; CAP] as *const [MaybeUninit<T>; CAP])
761
                .copy_to_nonoverlapping(&mut vec.xs as *mut [MaybeUninit<T>; CAP], 1);
762
            vec.set_len(CAP);
763
        }
764
        vec
765
    }
766
}
767
768
769
/// Try to create an `ArrayVec` from a slice. This will return an error if the slice was too big to
770
/// fit.
771
///
772
/// ```
773
/// use arrayvec::ArrayVec;
774
/// use std::convert::TryInto as _;
775
///
776
/// let array: ArrayVec<_, 4> = (&[1, 2, 3] as &[_]).try_into().unwrap();
777
/// assert_eq!(array.len(), 3);
778
/// assert_eq!(array.capacity(), 4);
779
/// ```
780
impl<T, const CAP: usize> std::convert::TryFrom<&[T]> for ArrayVec<T, CAP>
781
    where T: Clone,
782
{
783
    type Error = CapacityError;
784
785
    fn try_from(slice: &[T]) -> Result<Self, Self::Error> {
786
        if Self::CAPACITY < slice.len() {
787
            Err(CapacityError::new(()))
788
        } else {
789
            let mut array = Self::new();
790
            array.extend_from_slice(slice);
791
            Ok(array)
792
        }
793
    }
794
}
795
796
797
/// Iterate the `ArrayVec` with references to each element.
798
///
799
/// ```
800
/// use arrayvec::ArrayVec;
801
///
802
/// let array = ArrayVec::from([1, 2, 3]);
803
///
804
/// for elt in &array {
805
///     // ...
806
/// }
807
/// ```
808
impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a ArrayVec<T, CAP> {
809
    type Item = &'a T;
810
    type IntoIter = slice::Iter<'a, T>;
811
    fn into_iter(self) -> Self::IntoIter { self.iter() }
812
}
813
814
/// Iterate the `ArrayVec` with mutable references to each element.
815
///
816
/// ```
817
/// use arrayvec::ArrayVec;
818
///
819
/// let mut array = ArrayVec::from([1, 2, 3]);
820
///
821
/// for elt in &mut array {
822
///     // ...
823
/// }
824
/// ```
825
impl<'a, T: 'a, const CAP: usize> IntoIterator for &'a mut ArrayVec<T, CAP> {
826
    type Item = &'a mut T;
827
    type IntoIter = slice::IterMut<'a, T>;
828
    fn into_iter(self) -> Self::IntoIter { self.iter_mut() }
829
}
830
831
/// Iterate the `ArrayVec` with each element by value.
832
///
833
/// The vector is consumed by this operation.
834
///
835
/// ```
836
/// use arrayvec::ArrayVec;
837
///
838
/// for elt in ArrayVec::from([1, 2, 3]) {
839
///     // ...
840
/// }
841
/// ```
842
impl<T, const CAP: usize> IntoIterator for ArrayVec<T, CAP> {
843
    type Item = T;
844
    type IntoIter = IntoIter<T, CAP>;
845
    fn into_iter(self) -> IntoIter<T, CAP> {
846
        IntoIter { index: 0, v: self, }
847
    }
848
}
849
850
851
#[cfg(feature = "zeroize")]
852
/// "Best efforts" zeroing of the `ArrayVec`'s buffer when the `zeroize` feature is enabled.
853
///
854
/// The length is set to 0, and the buffer is dropped and zeroized.
855
/// Cannot ensure that previous moves of the `ArrayVec` did not leave values on the stack.
856
///
857
/// ```
858
/// use arrayvec::ArrayVec;
859
/// use zeroize::Zeroize;
860
/// let mut array = ArrayVec::from([1, 2, 3]);
861
/// array.zeroize();
862
/// assert_eq!(array.len(), 0);
863
/// let data = unsafe { core::slice::from_raw_parts(array.as_ptr(), array.capacity()) };
864
/// assert_eq!(data, [0, 0, 0]);
865
/// ```
866
impl<Z: zeroize::Zeroize, const CAP: usize> zeroize::Zeroize for ArrayVec<Z, CAP> {
867
    fn zeroize(&mut self) {
868
        // Zeroize all the contained elements.
869
        self.iter_mut().zeroize();
870
        // Drop all the elements and set the length to 0.
871
        self.clear();
872
        // Zeroize the backing array.
873
        self.xs.zeroize();
874
    }
875
}
876
877
/// By-value iterator for `ArrayVec`.
878
pub struct IntoIter<T, const CAP: usize> {
879
    index: usize,
880
    v: ArrayVec<T, CAP>,
881
}
882
883
impl<T, const CAP: usize> Iterator for IntoIter<T, CAP> {
884
    type Item = T;
885
886
    fn next(&mut self) -> Option<Self::Item> {
887
        if self.index == self.v.len() {
888
            None
889
        } else {
890
            unsafe {
891
                let index = self.index;
892
                self.index = index + 1;
893
                Some(ptr::read(self.v.get_unchecked_ptr(index)))
894
            }
895
        }
896
    }
897
898
    fn size_hint(&self) -> (usize, Option<usize>) {
899
        let len = self.v.len() - self.index;
900
        (len, Some(len))
901
    }
902
}
903
904
impl<T, const CAP: usize> DoubleEndedIterator for IntoIter<T, CAP> {
905
    fn next_back(&mut self) -> Option<Self::Item> {
906
        if self.index == self.v.len() {
907
            None
908
        } else {
909
            unsafe {
910
                let new_len = self.v.len() - 1;
911
                self.v.set_len(new_len);
912
                Some(ptr::read(self.v.get_unchecked_ptr(new_len)))
913
            }
914
        }
915
    }
916
}
917
918
impl<T, const CAP: usize> ExactSizeIterator for IntoIter<T, CAP> { }
919
920
impl<T, const CAP: usize> Drop for IntoIter<T, CAP> {
921
    fn drop(&mut self) {
922
        // panic safety: Set length to 0 before dropping elements.
923
        let index = self.index;
924
        let len = self.v.len();
925
        unsafe {
926
            self.v.set_len(0);
927
            let elements = slice::from_raw_parts_mut(
928
                self.v.get_unchecked_ptr(index),
929
                len - index);
930
            ptr::drop_in_place(elements);
931
        }
932
    }
933
}
934
935
impl<T, const CAP: usize> Clone for IntoIter<T, CAP>
936
where T: Clone,
937
{
938
    fn clone(&self) -> IntoIter<T, CAP> {
939
        let mut v = ArrayVec::new();
940
        v.extend_from_slice(&self.v[self.index..]);
941
        v.into_iter()
942
    }
943
}
944
945
impl<T, const CAP: usize> fmt::Debug for IntoIter<T, CAP>
946
where
947
    T: fmt::Debug,
948
{
949
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
950
        f.debug_list()
951
            .entries(&self.v[self.index..])
952
            .finish()
953
    }
954
}
955
956
/// A draining iterator for `ArrayVec`.
957
pub struct Drain<'a, T: 'a, const CAP: usize> {
958
    /// Index of tail to preserve
959
    tail_start: usize,
960
    /// Length of tail
961
    tail_len: usize,
962
    /// Current remaining range to remove
963
    iter: slice::Iter<'a, T>,
964
    vec: *mut ArrayVec<T, CAP>,
965
}
966
967
unsafe impl<'a, T: Sync, const CAP: usize> Sync for Drain<'a, T, CAP> {}
968
unsafe impl<'a, T: Send, const CAP: usize> Send for Drain<'a, T, CAP> {}
969
970
impl<'a, T: 'a, const CAP: usize> Iterator for Drain<'a, T, CAP> {
971
    type Item = T;
972
973
    fn next(&mut self) -> Option<Self::Item> {
974
        self.iter.next().map(|elt|
975
            unsafe {
976
                ptr::read(elt as *const _)
977
            }
978
        )
979
    }
980
981
    fn size_hint(&self) -> (usize, Option<usize>) {
982
        self.iter.size_hint()
983
    }
984
}
985
986
impl<'a, T: 'a, const CAP: usize> DoubleEndedIterator for Drain<'a, T, CAP>
987
{
988
    fn next_back(&mut self) -> Option<Self::Item> {
989
        self.iter.next_back().map(|elt|
990
            unsafe {
991
                ptr::read(elt as *const _)
992
            }
993
        )
994
    }
995
}
996
997
impl<'a, T: 'a, const CAP: usize> ExactSizeIterator for Drain<'a, T, CAP> {}
998
999
impl<'a, T: 'a, const CAP: usize> Drop for Drain<'a, T, CAP> {
1000
    fn drop(&mut self) {
1001
        // len is currently 0 so panicking while dropping will not cause a double drop.
1002
1003
        // exhaust self first
1004
        while let Some(_) = self.next() { }
1005
1006
        if self.tail_len > 0 {
1007
            unsafe {
1008
                let source_vec = &mut *self.vec;
1009
                // memmove back untouched tail, update to new length
1010
                let start = source_vec.len();
1011
                let tail = self.tail_start;
1012
                let ptr = source_vec.as_mut_ptr();
1013
                ptr::copy(ptr.add(tail), ptr.add(start), self.tail_len);
1014
                source_vec.set_len(start + self.tail_len);
1015
            }
1016
        }
1017
    }
1018
}
1019
1020
struct ScopeExitGuard<T, Data, F>
1021
    where F: FnMut(&Data, &mut T)
1022
{
1023
    value: T,
1024
    data: Data,
1025
    f: F,
1026
}
1027
1028
impl<T, Data, F> Drop for ScopeExitGuard<T, Data, F>
1029
    where F: FnMut(&Data, &mut T)
1030
{
1031
    fn drop(&mut self) {
1032
        (self.f)(&self.data, &mut self.value)
1033
    }
1034
}
1035
1036
1037
1038
/// Extend the `ArrayVec` with an iterator.
1039
/// 
1040
/// ***Panics*** if extending the vector exceeds its capacity.
1041
impl<T, const CAP: usize> Extend<T> for ArrayVec<T, CAP> {
1042
    /// Extend the `ArrayVec` with an iterator.
1043
    /// 
1044
    /// ***Panics*** if extending the vector exceeds its capacity.
1045
    #[track_caller]
1046
    fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
1047
        unsafe {
1048
            self.extend_from_iter::<_, true>(iter)
1049
        }
1050
    }
1051
}
1052
1053
#[inline(never)]
1054
#[cold]
1055
#[track_caller]
1056
fn extend_panic() {
1057
    panic!("ArrayVec: capacity exceeded in extend/from_iter");
1058
}
1059
1060
impl<T, const CAP: usize> ArrayVec<T, CAP> {
1061
    /// Extend the arrayvec from the iterable.
1062
    ///
1063
    /// ## Safety
1064
    ///
1065
    /// Unsafe because if CHECK is false, the length of the input is not checked.
1066
    /// The caller must ensure the length of the input fits in the capacity.
1067
    #[track_caller]
1068
    pub(crate) unsafe fn extend_from_iter<I, const CHECK: bool>(&mut self, iterable: I)
1069
        where I: IntoIterator<Item = T>
1070
    {
1071
        let take = self.capacity() - self.len();
1072
        let len = self.len();
1073
        let mut ptr = raw_ptr_add(self.as_mut_ptr(), len);
1074
        let end_ptr = raw_ptr_add(ptr, take);
1075
        // Keep the length in a separate variable, write it back on scope
1076
        // exit. To help the compiler with alias analysis and stuff.
1077
        // We update the length to handle panic in the iteration of the
1078
        // user's iterator, without dropping any elements on the floor.
1079
        let mut guard = ScopeExitGuard {
1080
            value: &mut self.len,
1081
            data: len,
1082
            f: move |&len, self_len| {
1083
                **self_len = len as LenUint;
1084
            }
1085
        };
1086
        let mut iter = iterable.into_iter();
1087
        loop {
1088
            if let Some(elt) = iter.next() {
1089
                if ptr == end_ptr && CHECK { extend_panic(); }
1090
                debug_assert_ne!(ptr, end_ptr);
1091
                ptr.write(elt);
1092
                ptr = raw_ptr_add(ptr, 1);
1093
                guard.data += 1;
1094
            } else {
1095
                return; // success
1096
            }
1097
        }
1098
    }
1099
1100
    /// Extend the ArrayVec with clones of elements from the slice;
1101
    /// the length of the slice must be <= the remaining capacity in the arrayvec.
1102
    pub(crate) fn extend_from_slice(&mut self, slice: &[T])
1103
        where T: Clone
1104
    {
1105
        let take = self.capacity() - self.len();
1106
        debug_assert!(slice.len() <= take);
1107
        unsafe {
1108
            let slice = if take < slice.len() { &slice[..take] } else { slice };
1109
            self.extend_from_iter::<_, false>(slice.iter().cloned());
1110
        }
1111
    }
1112
}
1113
1114
/// Rawptr add but uses arithmetic distance for ZST
1115
unsafe fn raw_ptr_add<T>(ptr: *mut T, offset: usize) -> *mut T {
1116
    if mem::size_of::<T>() == 0 {
1117
        // Special case for ZST
1118
        ptr.cast::<u8>().wrapping_add(offset).cast()
1119
    } else {
1120
        ptr.add(offset)
1121
    }
1122
}
1123
1124
/// Create an `ArrayVec` from an iterator.
1125
/// 
1126
/// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity.
1127
impl<T, const CAP: usize> iter::FromIterator<T> for ArrayVec<T, CAP> {
1128
    /// Create an `ArrayVec` from an iterator.
1129
    /// 
1130
    /// ***Panics*** if the number of elements in the iterator exceeds the arrayvec's capacity.
1131
    fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> Self {
1132
        let mut array = ArrayVec::new();
1133
        array.extend(iter);
1134
        array
1135
    }
1136
}
1137
1138
impl<T, const CAP: usize> Clone for ArrayVec<T, CAP>
1139
    where T: Clone
1140
{
1141
    fn clone(&self) -> Self {
1142
        self.iter().cloned().collect()
1143
    }
1144
1145
    fn clone_from(&mut self, rhs: &Self) {
1146
        // recursive case for the common prefix
1147
        let prefix = cmp::min(self.len(), rhs.len());
1148
        self[..prefix].clone_from_slice(&rhs[..prefix]);
1149
1150
        if prefix < self.len() {
1151
            // rhs was shorter
1152
            self.truncate(prefix);
1153
        } else {
1154
            let rhs_elems = &rhs[self.len()..];
1155
            self.extend_from_slice(rhs_elems);
1156
        }
1157
    }
1158
}
1159
1160
impl<T, const CAP: usize> Hash for ArrayVec<T, CAP>
1161
    where T: Hash
1162
{
1163
    fn hash<H: Hasher>(&self, state: &mut H) {
1164
        Hash::hash(&**self, state)
1165
    }
1166
}
1167
1168
impl<T, const CAP: usize> PartialEq for ArrayVec<T, CAP>
1169
    where T: PartialEq
1170
{
1171
    fn eq(&self, other: &Self) -> bool {
1172
        **self == **other
1173
    }
1174
}
1175
1176
impl<T, const CAP: usize> PartialEq<[T]> for ArrayVec<T, CAP>
1177
    where T: PartialEq
1178
{
1179
    fn eq(&self, other: &[T]) -> bool {
1180
        **self == *other
1181
    }
1182
}
1183
1184
impl<T, const CAP: usize> Eq for ArrayVec<T, CAP> where T: Eq { }
1185
1186
impl<T, const CAP: usize> Borrow<[T]> for ArrayVec<T, CAP> {
1187
    fn borrow(&self) -> &[T] { self }
1188
}
1189
1190
impl<T, const CAP: usize> BorrowMut<[T]> for ArrayVec<T, CAP> {
1191
    fn borrow_mut(&mut self) -> &mut [T] { self }
1192
}
1193
1194
impl<T, const CAP: usize> AsRef<[T]> for ArrayVec<T, CAP> {
1195
    fn as_ref(&self) -> &[T] { self }
1196
}
1197
1198
impl<T, const CAP: usize> AsMut<[T]> for ArrayVec<T, CAP> {
1199
    fn as_mut(&mut self) -> &mut [T] { self }
1200
}
1201
1202
impl<T, const CAP: usize> fmt::Debug for ArrayVec<T, CAP> where T: fmt::Debug {
1203
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { (**self).fmt(f) }
1204
}
1205
1206
impl<T, const CAP: usize> Default for ArrayVec<T, CAP> {
1207
    /// Return an empty array
1208
    fn default() -> ArrayVec<T, CAP> {
1209
        ArrayVec::new()
1210
    }
1211
}
1212
1213
impl<T, const CAP: usize> PartialOrd for ArrayVec<T, CAP> where T: PartialOrd {
1214
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
1215
        (**self).partial_cmp(other)
1216
    }
1217
1218
    fn lt(&self, other: &Self) -> bool {
1219
        (**self).lt(other)
1220
    }
1221
1222
    fn le(&self, other: &Self) -> bool {
1223
        (**self).le(other)
1224
    }
1225
1226
    fn ge(&self, other: &Self) -> bool {
1227
        (**self).ge(other)
1228
    }
1229
1230
    fn gt(&self, other: &Self) -> bool {
1231
        (**self).gt(other)
1232
    }
1233
}
1234
1235
impl<T, const CAP: usize> Ord for ArrayVec<T, CAP> where T: Ord {
1236
    fn cmp(&self, other: &Self) -> cmp::Ordering {
1237
        (**self).cmp(other)
1238
    }
1239
}
1240
1241
#[cfg(feature="std")]
1242
/// `Write` appends written data to the end of the vector.
1243
///
1244
/// Requires `features="std"`.
1245
impl<const CAP: usize> io::Write for ArrayVec<u8, CAP> {
1246
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
1247
        let len = cmp::min(self.remaining_capacity(), data.len());
1248
        let _result = self.try_extend_from_slice(&data[..len]);
1249
        debug_assert!(_result.is_ok());
1250
        Ok(len)
1251
    }
1252
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
1253
}
1254
1255
#[cfg(feature="serde")]
1256
/// Requires crate feature `"serde"`
1257
impl<T: Serialize, const CAP: usize> Serialize for ArrayVec<T, CAP> {
1258
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1259
        where S: Serializer
1260
    {
1261
        serializer.collect_seq(self)
1262
    }
1263
}
1264
1265
#[cfg(feature="serde")]
1266
/// Requires crate feature `"serde"`
1267
impl<'de, T: Deserialize<'de>, const CAP: usize> Deserialize<'de> for ArrayVec<T, CAP> {
1268
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1269
        where D: Deserializer<'de>
1270
    {
1271
        use serde::de::{Visitor, SeqAccess, Error};
1272
        use std::marker::PhantomData;
1273
1274
        struct ArrayVecVisitor<'de, T: Deserialize<'de>, const CAP: usize>(PhantomData<(&'de (), [T; CAP])>);
1275
1276
        impl<'de, T: Deserialize<'de>, const CAP: usize> Visitor<'de> for ArrayVecVisitor<'de, T, CAP> {
1277
            type Value = ArrayVec<T, CAP>;
1278
1279
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1280
                write!(formatter, "an array with no more than {} items", CAP)
1281
            }
1282
1283
            fn visit_seq<SA>(self, mut seq: SA) -> Result<Self::Value, SA::Error>
1284
                where SA: SeqAccess<'de>,
1285
            {
1286
                let mut values = ArrayVec::<T, CAP>::new();
1287
1288
                while let Some(value) = seq.next_element()? {
1289
                    if let Err(_) = values.try_push(value) {
1290
                        return Err(SA::Error::invalid_length(CAP + 1, &self));
1291
                    }
1292
                }
1293
1294
                Ok(values)
1295
            }
1296
        }
1297
1298
        deserializer.deserialize_seq(ArrayVecVisitor::<T, CAP>(PhantomData))
1299
    }
1300
}
/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/arrayvec-0.7.4/src/arrayvec_impl.rs
Line
Count
Source (jump to first uncovered line)
1
use std::ptr;
2
use std::slice;
3
4
use crate::CapacityError;
5
6
/// Implements basic arrayvec methods - based on a few required methods
7
/// for length and element access.
8
pub(crate) trait ArrayVecImpl {
9
    type Item;
10
    const CAPACITY: usize;
11
12
    fn len(&self) -> usize;
13
14
    unsafe fn set_len(&mut self, new_len: usize);
15
16
    /// Return a slice containing all elements of the vector.
17
11.2k
    fn as_slice(&self) -> &[Self::Item] {
18
11.2k
        let len = self.len();
19
11.2k
        unsafe {
20
11.2k
            slice::from_raw_parts(self.as_ptr(), len)
21
11.2k
        }
22
11.2k
    }
_RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl8as_sliceCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
17
11.2k
    fn as_slice(&self) -> &[Self::Item] {
18
11.2k
        let len = self.len();
19
11.2k
        unsafe {
20
11.2k
            slice::from_raw_parts(self.as_ptr(), len)
21
11.2k
        }
22
11.2k
    }
Unexecuted instantiation: _RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl8as_sliceCslLTLXfmDngu_8flex_dns
23
24
    /// Return a mutable slice containing all elements of the vector.
25
    fn as_mut_slice(&mut self) -> &mut [Self::Item] {
26
        let len = self.len();
27
        unsafe {
28
            std::slice::from_raw_parts_mut(self.as_mut_ptr(), len)
29
        }
30
    }
31
32
    /// Return a raw pointer to the vector's buffer.
33
    fn as_ptr(&self) -> *const Self::Item;
34
35
    /// Return a raw mutable pointer to the vector's buffer.
36
    fn as_mut_ptr(&mut self) -> *mut Self::Item;
37
38
    #[track_caller]
39
0
    fn push(&mut self, element: Self::Item) {
40
0
        self.try_push(element).unwrap()
41
0
    }
42
43
0
    fn try_push(&mut self, element: Self::Item) -> Result<(), CapacityError<Self::Item>> {
44
0
        if self.len() < Self::CAPACITY {
45
0
            unsafe {
46
0
                self.push_unchecked(element);
47
0
            }
48
0
            Ok(())
49
        } else {
50
0
            Err(CapacityError::new(element))
51
        }
52
0
    }
53
54
0
    unsafe fn push_unchecked(&mut self, element: Self::Item) {
55
0
        let len = self.len();
56
0
        debug_assert!(len < Self::CAPACITY);
57
0
        ptr::write(self.as_mut_ptr().add(len), element);
58
0
        self.set_len(len + 1);
59
0
    }
60
61
    fn pop(&mut self) -> Option<Self::Item> {
62
        if self.len() == 0 {
63
            return None;
64
        }
65
        unsafe {
66
            let new_len = self.len() - 1;
67
            self.set_len(new_len);
68
            Some(ptr::read(self.as_ptr().add(new_len)))
69
        }
70
    }
71
72
2.25k
    fn clear(&mut self) {
73
2.25k
        self.truncate(0)
74
2.25k
    }
_RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl5clearCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
72
1.12k
    fn clear(&mut self) {
73
1.12k
        self.truncate(0)
74
1.12k
    }
_RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVecjKj10_ENtNtB7_13arrayvec_impl12ArrayVecImpl5clearCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
72
1.12k
    fn clear(&mut self) {
73
1.12k
        self.truncate(0)
74
1.12k
    }
Unexecuted instantiation: _RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl5clearCslLTLXfmDngu_8flex_dns
75
76
2.25k
    fn truncate(&mut self, new_len: usize) {
77
2.25k
        unsafe {
78
2.25k
            let len = self.len();
79
2.25k
            if new_len < len {
80
1.12k
                self.set_len(new_len);
81
1.12k
                let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len);
82
1.12k
                ptr::drop_in_place(tail);
83
1.12k
            }
84
        }
85
2.25k
    }
_RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtNtB7_13arrayvec_impl12ArrayVecImpl8truncateCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
76
1.12k
    fn truncate(&mut self, new_len: usize) {
77
1.12k
        unsafe {
78
1.12k
            let len = self.len();
79
1.12k
            if new_len < len {
80
1.12k
                self.set_len(new_len);
81
1.12k
                let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len);
82
1.12k
                ptr::drop_in_place(tail);
83
1.12k
            }
84
        }
85
1.12k
    }
_RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVecjKj10_ENtNtB7_13arrayvec_impl12ArrayVecImpl8truncateCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
76
1.12k
    fn truncate(&mut self, new_len: usize) {
77
1.12k
        unsafe {
78
1.12k
            let len = self.len();
79
1.12k
            if new_len < len {
80
0
                self.set_len(new_len);
81
0
                let tail = slice::from_raw_parts_mut(self.as_mut_ptr().add(new_len), len - new_len);
82
0
                ptr::drop_in_place(tail);
83
1.12k
            }
84
        }
85
1.12k
    }
Unexecuted instantiation: _RNvYINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVecjKj80_ENtNtB7_13arrayvec_impl12ArrayVecImpl8truncateCslLTLXfmDngu_8flex_dns
86
}
87
/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/arrayvec-0.7.4/src/errors.rs
Line
Count
Source (jump to first uncovered line)
1
use std::fmt;
2
#[cfg(feature="std")]
3
use std::any::Any;
4
#[cfg(feature="std")]
5
use std::error::Error;
6
7
/// Error value indicating insufficient capacity
8
#[derive(Clone, Copy, Eq, Ord, PartialEq, PartialOrd)]
9
pub struct CapacityError<T = ()> {
10
    element: T,
11
}
12
13
impl<T> CapacityError<T> {
14
    /// Create a new `CapacityError` from `element`.
15
0
    pub const fn new(element: T) -> CapacityError<T> {
16
0
        CapacityError {
17
0
            element: element,
18
0
        }
19
0
    }
Unexecuted instantiation: _RNvMNtCskQaAGJdWXwX_8arrayvec6errorsNtB2_13CapacityError3newCsgg978DXfVXR_13fuzz_target_1
Unexecuted instantiation: _RNvMNtCskQaAGJdWXwX_8arrayvec6errorsINtB2_13CapacityErrorjE3newCslLTLXfmDngu_8flex_dns
20
21
    /// Extract the overflowing element
22
    pub fn element(self) -> T {
23
        self.element
24
    }
25
26
    /// Convert into a `CapacityError` that does not carry an element.
27
    pub fn simplify(self) -> CapacityError {
28
        CapacityError { element: () }
29
    }
30
}
31
32
const CAPERROR: &'static str = "insufficient capacity";
33
34
#[cfg(feature="std")]
35
/// Requires `features="std"`.
36
impl<T: Any> Error for CapacityError<T> {}
37
38
impl<T> fmt::Display for CapacityError<T> {
39
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40
        write!(f, "{}", CAPERROR)
41
    }
42
}
43
44
impl<T> fmt::Debug for CapacityError<T> {
45
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46
0
        write!(f, "{}: {}", "CapacityError", CAPERROR)
47
0
    }
Unexecuted instantiation: _RNvXs1_NtCskQaAGJdWXwX_8arrayvec6errorsNtB5_13CapacityErrorNtNtCs6xNykbTfrCs_4core3fmt5Debug3fmtCsgg978DXfVXR_13fuzz_target_1
Unexecuted instantiation: _RNvXs1_NtCskQaAGJdWXwX_8arrayvec6errorsINtB5_13CapacityErrorjENtNtCs6xNykbTfrCs_4core3fmt5Debug3fmtCslLTLXfmDngu_8flex_dns
48
}
49
/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/libfuzzer-sys-0.4.7/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
//! Bindings to [libFuzzer](http://llvm.org/docs/LibFuzzer.html): a runtime for
2
//! coverage-guided fuzzing.
3
//!
4
//! See [the `cargo-fuzz`
5
//! guide](https://rust-fuzz.github.io/book/cargo-fuzz.html) for a usage
6
//! tutorial.
7
//!
8
//! The main export of this crate is [the `fuzz_target!`
9
//! macro](./macro.fuzz_target.html), which allows you to define targets for
10
//! libFuzzer to exercise.
11
12
#![deny(missing_docs, missing_debug_implementations)]
13
14
pub use arbitrary;
15
use once_cell::sync::OnceCell;
16
17
/// Indicates whether the input should be kept in the corpus or rejected. This
18
/// should be returned by your fuzz target. If your fuzz target does not return
19
/// a value (i.e., returns `()`), then the input will be kept in the corpus.
20
0
#[derive(Debug)]
21
pub enum Corpus {
22
    /// Keep the input in the corpus.
23
    Keep,
24
25
    /// Reject the input and do not keep it in the corpus.
26
    Reject,
27
}
28
29
impl From<()> for Corpus {
30
0
    fn from(_: ()) -> Self {
31
0
        Self::Keep
32
0
    }
33
}
34
35
impl Corpus {
36
    #[doc(hidden)]
37
    /// Convert this Corpus result into the [integer codes used by
38
    /// `libFuzzer`](https://llvm.org/docs/LibFuzzer.html#rejecting-unwanted-inputs).
39
    /// This is -1 for reject, 0 for keep.
40
0
    pub fn to_libfuzzer_code(self) -> i32 {
41
0
        match self {
42
0
            Corpus::Keep => 0,
43
0
            Corpus::Reject => -1,
44
        }
45
0
    }
46
}
47
48
extern "C" {
49
    // We do not actually cross the FFI bound here.
50
    #[allow(improper_ctypes)]
51
    fn rust_fuzzer_test_input(input: &[u8]) -> i32;
52
53
    fn LLVMFuzzerMutate(data: *mut u8, size: usize, max_size: usize) -> usize;
54
}
55
56
#[doc(hidden)]
57
#[export_name = "LLVMFuzzerTestOneInput"]
58
1.12k
pub fn test_input_wrap(data: *const u8, size: usize) -> i32 {
59
1.12k
    let test_input = ::std::panic::catch_unwind(|| unsafe {
60
1.12k
        let data_slice = ::std::slice::from_raw_parts(data, size);
61
1.12k
        rust_fuzzer_test_input(data_slice)
62
1.12k
    });
63
1.12k
64
1.12k
    match test_input {
65
1.12k
        Ok(i) => i,
66
        Err(_) => {
67
            // hopefully the custom panic hook will be called before and abort the
68
            // process before the stack frames are unwinded.
69
0
            ::std::process::abort();
70
        }
71
    }
72
1.12k
}
73
74
#[doc(hidden)]
75
pub static RUST_LIBFUZZER_DEBUG_PATH: OnceCell<String> = OnceCell::new();
76
77
#[doc(hidden)]
78
#[export_name = "LLVMFuzzerInitialize"]
79
1.12k
pub fn initialize(_argc: *const isize, _argv: *const *const *const u8) -> isize {
80
1.12k
    // Registers a panic hook that aborts the process before unwinding.
81
1.12k
    // It is useful to abort before unwinding so that the fuzzer will then be
82
1.12k
    // able to analyse the process stack frames to tell different bugs appart.
83
1.12k
    //
84
1.12k
    // HACK / FIXME: it would be better to use `-C panic=abort` but it's currently
85
1.12k
    // impossible to build code using compiler plugins with this flag.
86
1.12k
    // We will be able to remove this code when
87
1.12k
    // https://github.com/rust-lang/cargo/issues/5423 is fixed.
88
1.12k
    let default_hook = ::std::panic::take_hook();
89
1.12k
    ::std::panic::set_hook(Box::new(move |panic_info| {
90
0
        default_hook(panic_info);
91
0
        ::std::process::abort();
92
1.12k
    }));
93
94
    // Initialize the `RUST_LIBFUZZER_DEBUG_PATH` cell with the path so it can be
95
    // reused with little overhead.
96
1.12k
    if let Ok(path) = std::env::var("RUST_LIBFUZZER_DEBUG_PATH") {
97
0
        RUST_LIBFUZZER_DEBUG_PATH
98
0
            .set(path)
99
0
            .expect("Since this is initialize it is only called once so can never fail");
100
1.12k
    }
101
1.12k
    0
102
1.12k
}
103
104
/// Define a fuzz target.
105
///
106
/// ## Example
107
///
108
/// This example takes a `&[u8]` slice and attempts to parse it. The parsing
109
/// might fail and return an `Err`, but it shouldn't ever panic or segfault.
110
///
111
/// ```no_run
112
/// #![no_main]
113
///
114
/// use libfuzzer_sys::fuzz_target;
115
///
116
/// // Note: `|input|` is short for `|input: &[u8]|`.
117
/// fuzz_target!(|input| {
118
///     let _result: Result<_, _> = my_crate::parse(input);
119
/// });
120
/// # mod my_crate { pub fn parse(_: &[u8]) -> Result<(), ()> { unimplemented!() } }
121
/// ```
122
///
123
/// ## Rejecting Inputs
124
///
125
/// It may be desirable to reject some inputs, i.e. to not add them to the
126
/// corpus.
127
///
128
/// For example, when fuzzing an API consisting of parsing and other logic,
129
/// one may want to allow only those inputs into the corpus that parse
130
/// successfully. To indicate whether an input should be kept in or rejected
131
/// from the corpus, return either [Corpus::Keep] or [Corpus::Reject] from your
132
/// fuzz target. The default behavior (e.g. if `()` is returned) is to keep the
133
/// input in the corpus.
134
///
135
/// For example:
136
///
137
/// ```no_run
138
/// #![no_main]
139
///
140
/// use libfuzzer_sys::{Corpus, fuzz_target};
141
///
142
/// fuzz_target!(|input: String| -> Corpus {
143
///     let parts: Vec<&str> = input.splitn(2, '=').collect();
144
///     if parts.len() != 2 {
145
///         return Corpus::Reject;
146
///     }
147
///
148
///     let key = parts[0];
149
///     let value = parts[1];
150
///     let _result: Result<_, _> = my_crate::parse(key, value);
151
///     Corpus::Keep
152
/// });
153
/// # mod my_crate { pub fn parse(_key: &str, _value: &str) -> Result<(), ()> { unimplemented!() } }
154
/// ```
155
///
156
/// ## Arbitrary Input Types
157
///
158
/// The input is a `&[u8]` slice by default, but you can take arbitrary input
159
/// types, as long as the type implements [the `arbitrary` crate's `Arbitrary`
160
/// trait](https://docs.rs/arbitrary/*/arbitrary/trait.Arbitrary.html) (which is
161
/// also re-exported as `libfuzzer_sys::arbitrary::Arbitrary` for convenience).
162
///
163
/// For example, if you wanted to take an arbitrary RGB color, you could do the
164
/// following:
165
///
166
/// ```no_run
167
/// #![no_main]
168
/// # mod foo {
169
///
170
/// use libfuzzer_sys::{arbitrary::{Arbitrary, Error, Unstructured}, fuzz_target};
171
///
172
/// #[derive(Debug)]
173
/// pub struct Rgb {
174
///     r: u8,
175
///     g: u8,
176
///     b: u8,
177
/// }
178
///
179
/// impl<'a> Arbitrary<'a> for Rgb {
180
///     fn arbitrary(raw: &mut Unstructured<'a>) -> Result<Self, Error> {
181
///         let mut buf = [0; 3];
182
///         raw.fill_buffer(&mut buf)?;
183
///         let r = buf[0];
184
///         let g = buf[1];
185
///         let b = buf[2];
186
///         Ok(Rgb { r, g, b })
187
///     }
188
/// }
189
///
190
/// // Write a fuzz target that works with RGB colors instead of raw bytes.
191
/// fuzz_target!(|color: Rgb| {
192
///     my_crate::convert_color(color);
193
/// });
194
/// # mod my_crate {
195
/// #     use super::Rgb;
196
/// #     pub fn convert_color(_: Rgb) {}
197
/// # }
198
/// # }
199
/// ```
200
///
201
/// You can also enable the `arbitrary` crate's custom derive via this crate's
202
/// `"arbitrary-derive"` cargo feature.
203
#[macro_export]
204
macro_rules! fuzz_target {
205
    (|$bytes:ident| $body:expr) => {
206
        const _: () = {
207
            /// Auto-generated function
208
            #[no_mangle]
209
            pub extern "C" fn rust_fuzzer_test_input(bytes: &[u8]) -> i32 {
210
                // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
211
                // formatting of the input to that file. This is only intended for
212
                // `cargo fuzz`'s use!
213
214
                // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization.
215
1.12k
                if let Some(path) = $crate::RUST_LIBFUZZER_DEBUG_PATH.get() {
216
                    use std::io::Write;
217
0
                    let mut file = std::fs::File::create(path)
218
0
                        .expect("failed to create `RUST_LIBFUZZER_DEBUG_PATH` file");
219
0
                    writeln!(&mut file, "{:?}", bytes)
220
0
                        .expect("failed to write to `RUST_LIBFUZZER_DEBUG_PATH` file");
221
0
                    return 0;
222
1.12k
                }
223
1.12k
224
1.12k
                __libfuzzer_sys_run(bytes);
225
1.12k
                0
226
1.12k
            }
227
228
            // Split out the actual fuzzer into a separate function which is
229
            // tagged as never being inlined. This ensures that if the fuzzer
230
            // panics there's at least one stack frame which is named uniquely
231
            // according to this specific fuzzer that this is embedded within.
232
            //
233
            // Systems like oss-fuzz try to deduplicate crashes and without this
234
            // panics in separate fuzzers can accidentally appear the same
235
            // because each fuzzer will have a function called
236
            // `rust_fuzzer_test_input`. By using a normal Rust function here
237
            // it's named something like `the_fuzzer_name::_::__libfuzzer_sys_run` which should
238
            // ideally help prevent oss-fuzz from deduplicate fuzz bugs across
239
            // distinct targets accidentally.
240
            #[inline(never)]
241
1.12k
            fn __libfuzzer_sys_run($bytes: &[u8]) {
242
1.12k
                $body
243
1.12k
            }
244
        };
245
    };
246
247
    (|$data:ident: &[u8]| $body:expr) => {
248
        $crate::fuzz_target!(|$data| $body);
249
    };
250
251
    (|$data:ident: $dty:ty| $body:expr) => {
252
        $crate::fuzz_target!(|$data: $dty| -> () { $body });
253
    };
254
255
    (|$data:ident: $dty:ty| -> $rty:ty $body:block) => {
256
        const _: () = {
257
            /// Auto-generated function
258
            #[no_mangle]
259
            pub extern "C" fn rust_fuzzer_test_input(bytes: &[u8]) -> i32 {
260
                use $crate::arbitrary::{Arbitrary, Unstructured};
261
262
                // Early exit if we don't have enough bytes for the `Arbitrary`
263
                // implementation. This helps the fuzzer avoid exploring all the
264
                // different not-enough-input-bytes paths inside the `Arbitrary`
265
                // implementation. Additionally, it exits faster, letting the fuzzer
266
                // get to longer inputs that actually lead to interesting executions
267
                // quicker.
268
                if bytes.len() < <$dty as Arbitrary>::size_hint(0).0 {
269
                    return -1;
270
                }
271
272
                let mut u = Unstructured::new(bytes);
273
                let data = <$dty as Arbitrary>::arbitrary_take_rest(u);
274
275
                // When `RUST_LIBFUZZER_DEBUG_PATH` is set, write the debug
276
                // formatting of the input to that file. This is only intended for
277
                // `cargo fuzz`'s use!
278
279
                // `RUST_LIBFUZZER_DEBUG_PATH` is set in initialization.
280
                if let Some(path) = $crate::RUST_LIBFUZZER_DEBUG_PATH.get() {
281
                    use std::io::Write;
282
                    let mut file = std::fs::File::create(path)
283
                        .expect("failed to create `RUST_LIBFUZZER_DEBUG_PATH` file");
284
                    (match data {
285
                        Ok(data) => writeln!(&mut file, "{:#?}", data),
286
                        Err(err) => writeln!(&mut file, "Arbitrary Error: {}", err),
287
                    })
288
                    .expect("failed to write to `RUST_LIBFUZZER_DEBUG_PATH` file");
289
                    return -1;
290
                }
291
292
                let data = match data {
293
                    Ok(d) => d,
294
                    Err(_) => return -1,
295
                };
296
297
                let result = ::libfuzzer_sys::Corpus::from(__libfuzzer_sys_run(data));
298
                result.to_libfuzzer_code()
299
            }
300
301
            // See above for why this is split to a separate function.
302
            #[inline(never)]
303
            fn __libfuzzer_sys_run($data: $dty) -> $rty {
304
                $body
305
            }
306
        };
307
    };
308
}
309
310
/// Define a custom mutator.
311
///
312
/// This is optional, and libFuzzer will use its own, default mutation strategy
313
/// if this is not provided.
314
///
315
/// You might consider using a custom mutator when your fuzz target is very
316
/// particular about the shape of its input:
317
///
318
/// * You want to fuzz "deeper" than just the parser.
319
/// * The input contains checksums that have to match the hash of some subset of
320
///   the data or else the whole thing is invalid, and therefore mutating any of
321
///   that subset means you need to recompute the checksums.
322
/// * Small random changes to the input buffer make it invalid.
323
///
324
/// That is, a custom mutator is useful in similar situations where [a `T:
325
/// Arbitrary` input type](macro.fuzz_target.html#arbitrary-input-types) is
326
/// useful. Note that the two approaches are not mutually exclusive; you can use
327
/// whichever is easier for your problem domain or both!
328
///
329
/// ## Implementation Contract
330
///
331
/// The original, unmodified input is given in `data[..size]`.
332
///
333
/// You must modify the data in place and return the new size.
334
///
335
/// The new size should not be greater than `max_size`. If this is not the case,
336
/// then the `data` will be truncated to fit within `max_size`. Note that
337
/// `max_size < size` is possible when shrinking test cases.
338
///
339
/// You must produce the same mutation given the same `seed`. Generally, when
340
/// choosing what kind of mutation to make or where to mutate, you should start
341
/// by creating a random number generator (RNG) that is seeded with the given
342
/// `seed` and then consult the RNG whenever making a decision:
343
///
344
/// ```no_run
345
/// #![no_main]
346
///
347
/// use rand::{rngs::StdRng, Rng, SeedableRng};
348
///
349
/// libfuzzer_sys::fuzz_mutator!(|data: &mut [u8], size: usize, max_size: usize, seed: u32| {
350
///     let mut rng = StdRng::seed_from_u64(seed as u64);
351
///
352
/// #   let first_mutation = |_, _, _, _| todo!();
353
/// #   let second_mutation = |_, _, _, _| todo!();
354
/// #   let third_mutation = |_, _, _, _| todo!();
355
/// #   let fourth_mutation = |_, _, _, _| todo!();
356
///     // Choose which of our four supported kinds of mutations we want to make.
357
///     match rng.gen_range(0..4) {
358
///         0 => first_mutation(rng, data, size, max_size),
359
///         1 => second_mutation(rng, data, size, max_size),
360
///         2 => third_mutation(rng, data, size, max_size),
361
///         3 => fourth_mutation(rng, data, size, max_size),
362
///         _ => unreachable!()
363
///     }
364
/// });
365
/// ```
366
///
367
/// ## Example: Compression
368
///
369
/// Consider a simple fuzz target that takes compressed data as input,
370
/// decompresses it, and then asserts that the decompressed data doesn't begin
371
/// with "boom". It is difficult for `libFuzzer` (or any other fuzzer) to crash
372
/// this fuzz target because nearly all mutations it makes will invalidate the
373
/// compression format. Therefore, we use a custom mutator that decompresses the
374
/// raw input, mutates the decompressed data, and then recompresses it. This
375
/// allows `libFuzzer` to quickly discover crashing inputs.
376
///
377
/// ```no_run
378
/// #![no_main]
379
///
380
/// use flate2::{read::GzDecoder, write::GzEncoder, Compression};
381
/// use libfuzzer_sys::{fuzz_mutator, fuzz_target};
382
/// use std::io::{Read, Write};
383
///
384
/// fuzz_target!(|data: &[u8]| {
385
///     // Decompress the input data and crash if it starts with "boom".
386
///     if let Some(data) = decompress(data) {
387
///         if data.starts_with(b"boom") {
388
///             panic!();
389
///         }
390
///     }
391
/// });
392
///
393
/// fuzz_mutator!(
394
///     |data: &mut [u8], size: usize, max_size: usize, _seed: u32| {
395
///         // Decompress the input data. If that fails, use a dummy value.
396
///         let mut decompressed = decompress(&data[..size]).unwrap_or_else(|| b"hi".to_vec());
397
///
398
///         // Mutate the decompressed data with `libFuzzer`'s default mutator. Make
399
///         // the `decompressed` vec's extra capacity available for insertion
400
///         // mutations via `resize`.
401
///         let len = decompressed.len();
402
///         let cap = decompressed.capacity();
403
///         decompressed.resize(cap, 0);
404
///         let new_decompressed_size = libfuzzer_sys::fuzzer_mutate(&mut decompressed, len, cap);
405
///
406
///         // Recompress the mutated data.
407
///         let compressed = compress(&decompressed[..new_decompressed_size]);
408
///
409
///         // Copy the recompressed mutated data into `data` and return the new size.
410
///         let new_size = std::cmp::min(max_size, compressed.len());
411
///         data[..new_size].copy_from_slice(&compressed[..new_size]);
412
///         new_size
413
///     }
414
/// );
415
///
416
/// fn decompress(compressed_data: &[u8]) -> Option<Vec<u8>> {
417
///     let mut decoder = GzDecoder::new(compressed_data);
418
///     let mut decompressed = Vec::new();
419
///     if decoder.read_to_end(&mut decompressed).is_ok() {
420
///         Some(decompressed)
421
///     } else {
422
///         None
423
///     }
424
/// }
425
///
426
/// fn compress(data: &[u8]) -> Vec<u8> {
427
///     let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
428
///     encoder
429
///         .write_all(data)
430
///         .expect("writing into a vec is infallible");
431
///     encoder.finish().expect("writing into a vec is infallible")
432
/// }
433
/// ```
434
///
435
/// This example is inspired by [a similar example from the official `libFuzzer`
436
/// docs](https://github.com/google/fuzzing/blob/master/docs/structure-aware-fuzzing.md#example-compression).
437
///
438
/// ## More Example Ideas
439
///
440
/// * A PNG custom mutator that decodes a PNG, mutates the image, and then
441
/// re-encodes the mutated image as a new PNG.
442
///
443
/// * A [`serde`](https://serde.rs/) custom mutator that deserializes your
444
///   structure, mutates it, and then reserializes it.
445
///
446
/// * A Wasm binary custom mutator that inserts, replaces, and removes a
447
///   bytecode instruction in a function's body.
448
///
449
/// * An HTTP request custom mutator that inserts, replaces, and removes a
450
///   header from an HTTP request.
451
#[macro_export]
452
macro_rules! fuzz_mutator {
453
    (
454
        |
455
        $data:ident : &mut [u8] ,
456
        $size:ident : usize ,
457
        $max_size:ident : usize ,
458
        $seed:ident : u32 $(,)*
459
        |
460
        $body:block
461
    ) => {
462
        /// Auto-generated function.
463
        #[export_name = "LLVMFuzzerCustomMutator"]
464
        pub fn rust_fuzzer_custom_mutator(
465
            $data: *mut u8,
466
            $size: usize,
467
            $max_size: usize,
468
            $seed: std::os::raw::c_uint,
469
        ) -> usize {
470
            // Depending on if we are growing or shrinking the test case, `size`
471
            // might be larger or smaller than `max_size`. The `data`'s capacity
472
            // is the maximum of the two.
473
            let len = std::cmp::max($max_size, $size);
474
            let $data: &mut [u8] = unsafe { std::slice::from_raw_parts_mut($data, len) };
475
476
            // `unsigned int` is generally a `u32`, but not on all targets. Do
477
            // an infallible (and potentially lossy, but that's okay because it
478
            // preserves determinism) conversion.
479
            let $seed = $seed as u32;
480
481
            // Truncate the new size if it is larger than the max.
482
            let new_size = { $body };
483
            std::cmp::min(new_size, $max_size)
484
        }
485
    };
486
}
487
488
/// The default `libFuzzer` mutator.
489
///
490
/// You generally don't have to use this at all unless you're defining a
491
/// custom mutator with [the `fuzz_mutator!` macro][crate::fuzz_mutator].
492
///
493
/// Mutates `data[..size]` in place such that the mutated data is no larger than
494
/// `max_size` and returns the new size of the mutated data.
495
///
496
/// To only allow shrinking mutations, make `max_size < size`.
497
///
498
/// To additionally allow mutations that grow the size of the data, make
499
/// `max_size > size`.
500
///
501
/// Both `size` and `max_size` must be less than or equal to `data.len()`.
502
///
503
/// # Example
504
///
505
/// ```no_run
506
/// // Create some data in a buffer.
507
/// let mut data = vec![0; 128];
508
/// data[..b"hello".len()].copy_from_slice(b"hello");
509
///
510
/// // Ask `libFuzzer` to mutate the data. By setting `max_size` to our buffer's
511
/// // full length, we are allowing `libFuzzer` to perform mutations that grow
512
/// // the size of the data, such as insertions.
513
/// let size = b"hello".len();
514
/// let max_size = data.len();
515
/// let new_size = libfuzzer_sys::fuzzer_mutate(&mut data, size, max_size);
516
///
517
/// // Get the mutated data out of the buffer.
518
/// let mutated_data = &data[..new_size];
519
/// ```
520
0
pub fn fuzzer_mutate(data: &mut [u8], size: usize, max_size: usize) -> usize {
521
0
    assert!(size <= data.len());
522
0
    assert!(max_size <= data.len());
523
0
    let new_size = unsafe { LLVMFuzzerMutate(data.as_mut_ptr(), size, max_size) };
524
0
    assert!(new_size <= data.len());
525
0
    new_size
526
0
}
/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.18.0/src/imp_std.rs
Line
Count
Source (jump to first uncovered line)
1
// There's a lot of scary concurrent code in this module, but it is copied from
2
// `std::sync::Once` with two changes:
3
//   * no poisoning
4
//   * init function can fail
5
6
use std::{
7
    cell::{Cell, UnsafeCell},
8
    panic::{RefUnwindSafe, UnwindSafe},
9
    sync::atomic::{AtomicBool, AtomicPtr, Ordering},
10
    thread::{self, Thread},
11
};
12
13
0
#[derive(Debug)]
14
pub(crate) struct OnceCell<T> {
15
    // This `queue` field is the core of the implementation. It encodes two
16
    // pieces of information:
17
    //
18
    // * The current state of the cell (`INCOMPLETE`, `RUNNING`, `COMPLETE`)
19
    // * Linked list of threads waiting for the current cell.
20
    //
21
    // State is encoded in two low bits. Only `INCOMPLETE` and `RUNNING` states
22
    // allow waiters.
23
    queue: AtomicPtr<Waiter>,
24
    value: UnsafeCell<Option<T>>,
25
}
26
27
// Why do we need `T: Send`?
28
// Thread A creates a `OnceCell` and shares it with
29
// scoped thread B, which fills the cell, which is
30
// then destroyed by A. That is, destructor observes
31
// a sent value.
32
unsafe impl<T: Sync + Send> Sync for OnceCell<T> {}
33
unsafe impl<T: Send> Send for OnceCell<T> {}
34
35
impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {}
36
impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
37
38
impl<T> OnceCell<T> {
39
0
    pub(crate) const fn new() -> OnceCell<T> {
40
0
        OnceCell { queue: AtomicPtr::new(INCOMPLETE_PTR), value: UnsafeCell::new(None) }
41
0
    }
42
43
0
    pub(crate) const fn with_value(value: T) -> OnceCell<T> {
44
0
        OnceCell { queue: AtomicPtr::new(COMPLETE_PTR), value: UnsafeCell::new(Some(value)) }
45
0
    }
46
47
    /// Safety: synchronizes with store to value via Release/(Acquire|SeqCst).
48
    #[inline]
49
1.12k
    pub(crate) fn is_initialized(&self) -> bool {
50
1.12k
        // An `Acquire` load is enough because that makes all the initialization
51
1.12k
        // operations visible to us, and, this being a fast path, weaker
52
1.12k
        // ordering helps with performance. This `Acquire` synchronizes with
53
1.12k
        // `SeqCst` operations on the slow path.
54
1.12k
        self.queue.load(Ordering::Acquire) == COMPLETE_PTR
55
1.12k
    }
_RNvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE14is_initializedCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
49
1.12k
    pub(crate) fn is_initialized(&self) -> bool {
50
1.12k
        // An `Acquire` load is enough because that makes all the initialization
51
1.12k
        // operations visible to us, and, this being a fast path, weaker
52
1.12k
        // ordering helps with performance. This `Acquire` synchronizes with
53
1.12k
        // `SeqCst` operations on the slow path.
54
1.12k
        self.queue.load(Ordering::Acquire) == COMPLETE_PTR
55
1.12k
    }
Unexecuted instantiation: _RNvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE14is_initializedCsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB5_8OnceCellpE14is_initializedB7_
56
57
    /// Safety: synchronizes with store to value via SeqCst read from state,
58
    /// writes value only once because we never get to INCOMPLETE state after a
59
    /// successful write.
60
    #[cold]
61
0
    pub(crate) fn initialize<F, E>(&self, f: F) -> Result<(), E>
62
0
    where
63
0
        F: FnOnce() -> Result<T, E>,
64
0
    {
65
0
        let mut f = Some(f);
66
0
        let mut res: Result<(), E> = Ok(());
67
0
        let slot: *mut Option<T> = self.value.get();
68
0
        initialize_or_wait(
69
0
            &self.queue,
70
0
            Some(&mut || {
71
0
                let f = unsafe { f.take().unwrap_unchecked() };
72
0
                match f() {
73
0
                    Ok(value) => {
74
0
                        unsafe { *slot = Some(value) };
75
0
                        true
76
                    }
77
0
                    Err(err) => {
78
0
                        res = Err(err);
79
0
                        false
80
                    }
81
                }
82
0
            }),
Unexecuted instantiation: _RNCINvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB8_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE10initializeNCINvMs4_NtBa_4syncINtB1P_8OnceCellBR_E11get_or_initNCNvB1L_10try_insert0E0NtNvMs4_B1P_IB20_pE11get_or_init4VoidE0Csi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNCINvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB8_8OnceCellpE10initializeppE0Ba_
83
0
        );
84
0
        res
85
0
    }
Unexecuted instantiation: _RINvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB6_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE10initializeNCINvMs4_NtB8_4syncINtB1N_8OnceCellBP_E11get_or_initNCNvB1J_10try_insert0E0NtNvMs4_B1N_IB1Y_pE11get_or_init4VoidECsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RINvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB6_8OnceCellpE10initializeppEB8_
86
87
    #[cold]
88
0
    pub(crate) fn wait(&self) {
89
0
        initialize_or_wait(&self.queue, None);
90
0
    }
91
92
    /// Get the reference to the underlying value, without checking if the cell
93
    /// is initialized.
94
    ///
95
    /// # Safety
96
    ///
97
    /// Caller must ensure that the cell is in initialized state, and that
98
    /// the contents are acquired by (synchronized to) this thread.
99
0
    pub(crate) unsafe fn get_unchecked(&self) -> &T {
100
0
        debug_assert!(self.is_initialized());
101
0
        let slot = &*self.value.get();
102
0
        slot.as_ref().unwrap_unchecked()
103
0
    }
Unexecuted instantiation: _RNvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE13get_uncheckedCsgg978DXfVXR_13fuzz_target_1
Unexecuted instantiation: _RNvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE13get_uncheckedCsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNvMs2_NtCsaBdG7DIvBl9_9once_cell3impINtB5_8OnceCellpE13get_uncheckedB7_
104
105
    /// Gets the mutable reference to the underlying value.
106
    /// Returns `None` if the cell is empty.
107
0
    pub(crate) fn get_mut(&mut self) -> Option<&mut T> {
108
0
        // Safe b/c we have a unique access.
109
0
        unsafe { &mut *self.value.get() }.as_mut()
110
0
    }
111
112
    /// Consumes this `OnceCell`, returning the wrapped value.
113
    /// Returns `None` if the cell was empty.
114
    #[inline]
115
0
    pub(crate) fn into_inner(self) -> Option<T> {
116
0
        // Because `into_inner` takes `self` by value, the compiler statically
117
0
        // verifies that it is not currently borrowed.
118
0
        // So, it is safe to move out `Option<T>`.
119
0
        self.value.into_inner()
120
0
    }
121
}
122
123
// Three states that a OnceCell can be in, encoded into the lower bits of `queue` in
124
// the OnceCell structure.
125
const INCOMPLETE: usize = 0x0;
126
const RUNNING: usize = 0x1;
127
const COMPLETE: usize = 0x2;
128
const INCOMPLETE_PTR: *mut Waiter = INCOMPLETE as *mut Waiter;
129
const COMPLETE_PTR: *mut Waiter = COMPLETE as *mut Waiter;
130
131
// Mask to learn about the state. All other bits are the queue of waiters if
132
// this is in the RUNNING state.
133
const STATE_MASK: usize = 0x3;
134
135
/// Representation of a node in the linked list of waiters in the RUNNING state.
136
/// A waiters is stored on the stack of the waiting threads.
137
#[repr(align(4))] // Ensure the two lower bits are free to use as state bits.
138
struct Waiter {
139
    thread: Cell<Option<Thread>>,
140
    signaled: AtomicBool,
141
    next: *mut Waiter,
142
}
143
144
/// Drains and notifies the queue of waiters on drop.
145
struct Guard<'a> {
146
    queue: &'a AtomicPtr<Waiter>,
147
    new_queue: *mut Waiter,
148
}
149
150
impl Drop for Guard<'_> {
151
0
    fn drop(&mut self) {
152
0
        let queue = self.queue.swap(self.new_queue, Ordering::AcqRel);
153
0
154
0
        let state = strict::addr(queue) & STATE_MASK;
155
0
        assert_eq!(state, RUNNING);
156
157
        unsafe {
158
0
            let mut waiter = strict::map_addr(queue, |q| q & !STATE_MASK);
159
0
            while !waiter.is_null() {
160
0
                let next = (*waiter).next;
161
0
                let thread = (*waiter).thread.take().unwrap();
162
0
                (*waiter).signaled.store(true, Ordering::Release);
163
0
                waiter = next;
164
0
                thread.unpark();
165
0
            }
166
        }
167
0
    }
168
}
169
170
// Corresponds to `std::sync::Once::call_inner`.
171
//
172
// Originally copied from std, but since modified to remove poisoning and to
173
// support wait.
174
//
175
// Note: this is intentionally monomorphic
176
#[inline(never)]
177
0
fn initialize_or_wait(queue: &AtomicPtr<Waiter>, mut init: Option<&mut dyn FnMut() -> bool>) {
178
0
    let mut curr_queue = queue.load(Ordering::Acquire);
179
180
0
    loop {
181
0
        let curr_state = strict::addr(curr_queue) & STATE_MASK;
182
0
        match (curr_state, &mut init) {
183
0
            (COMPLETE, _) => return,
184
0
            (INCOMPLETE, Some(init)) => {
185
0
                let exchange = queue.compare_exchange(
186
0
                    curr_queue,
187
0
                    strict::map_addr(curr_queue, |q| (q & !STATE_MASK) | RUNNING),
188
0
                    Ordering::Acquire,
189
0
                    Ordering::Acquire,
190
0
                );
191
0
                if let Err(new_queue) = exchange {
192
0
                    curr_queue = new_queue;
193
0
                    continue;
194
0
                }
195
0
                let mut guard = Guard { queue, new_queue: INCOMPLETE_PTR };
196
0
                if init() {
197
0
                    guard.new_queue = COMPLETE_PTR;
198
0
                }
199
0
                return;
200
            }
201
0
            (INCOMPLETE, None) | (RUNNING, _) => {
202
0
                wait(queue, curr_queue);
203
0
                curr_queue = queue.load(Ordering::Acquire);
204
0
            }
205
0
            _ => debug_assert!(false),
206
        }
207
    }
208
0
}
209
210
0
fn wait(queue: &AtomicPtr<Waiter>, mut curr_queue: *mut Waiter) {
211
0
    let curr_state = strict::addr(curr_queue) & STATE_MASK;
212
0
    loop {
213
0
        let node = Waiter {
214
0
            thread: Cell::new(Some(thread::current())),
215
0
            signaled: AtomicBool::new(false),
216
0
            next: strict::map_addr(curr_queue, |q| q & !STATE_MASK),
217
0
        };
218
0
        let me = &node as *const Waiter as *mut Waiter;
219
0
220
0
        let exchange = queue.compare_exchange(
221
0
            curr_queue,
222
0
            strict::map_addr(me, |q| q | curr_state),
223
0
            Ordering::Release,
224
0
            Ordering::Relaxed,
225
0
        );
226
0
        if let Err(new_queue) = exchange {
227
0
            if strict::addr(new_queue) & STATE_MASK != curr_state {
228
0
                return;
229
0
            }
230
0
            curr_queue = new_queue;
231
0
            continue;
232
0
        }
233
234
0
        while !node.signaled.load(Ordering::Acquire) {
235
0
            thread::park();
236
0
        }
237
0
        break;
238
    }
239
0
}
240
241
// Polyfill of strict provenance from https://crates.io/crates/sptr.
242
//
243
// Use free-standing function rather than a trait to keep things simple and
244
// avoid any potential conflicts with future stabile std API.
245
mod strict {
246
    #[must_use]
247
    #[inline]
248
0
    pub(crate) fn addr<T>(ptr: *mut T) -> usize
249
0
    where
250
0
        T: Sized,
251
0
    {
252
0
        // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
253
0
        // SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
254
0
        // provenance).
255
0
        unsafe { core::mem::transmute(ptr) }
256
0
    }
257
258
    #[must_use]
259
    #[inline]
260
0
    pub(crate) fn with_addr<T>(ptr: *mut T, addr: usize) -> *mut T
261
0
    where
262
0
        T: Sized,
263
0
    {
264
0
        // FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
265
0
        //
266
0
        // In the mean-time, this operation is defined to be "as if" it was
267
0
        // a wrapping_offset, so we can emulate it as such. This should properly
268
0
        // restore pointer provenance even under today's compiler.
269
0
        let self_addr = self::addr(ptr) as isize;
270
0
        let dest_addr = addr as isize;
271
0
        let offset = dest_addr.wrapping_sub(self_addr);
272
0
273
0
        // This is the canonical desugarring of this operation,
274
0
        // but `pointer::cast` was only stabilized in 1.38.
275
0
        // self.cast::<u8>().wrapping_offset(offset).cast::<T>()
276
0
        (ptr as *mut u8).wrapping_offset(offset) as *mut T
277
0
    }
278
279
    #[must_use]
280
    #[inline]
281
0
    pub(crate) fn map_addr<T>(ptr: *mut T, f: impl FnOnce(usize) -> usize) -> *mut T
282
0
    where
283
0
        T: Sized,
284
0
    {
285
0
        self::with_addr(ptr, f(addr(ptr)))
286
0
    }
Unexecuted instantiation: _RINvNtNtCsaBdG7DIvBl9_9once_cell3imp6strict8map_addrNtB4_6WaiterNCNvB4_18initialize_or_wait0EB6_
Unexecuted instantiation: _RINvNtNtCsaBdG7DIvBl9_9once_cell3imp6strict8map_addrNtB4_6WaiterNCNvB4_4waits_0EB6_
Unexecuted instantiation: _RINvNtNtCsaBdG7DIvBl9_9once_cell3imp6strict8map_addrNtB4_6WaiterNCNvB4_4wait0EB6_
Unexecuted instantiation: _RINvNtNtCsaBdG7DIvBl9_9once_cell3imp6strict8map_addrNtB4_6WaiterNCNvXs3_B4_NtB4_5GuardNtNtNtCs6xNykbTfrCs_4core3ops4drop4Drop4drop0EB6_
287
}
288
289
// These test are snatched from std as well.
290
#[cfg(test)]
291
mod tests {
292
    use std::panic;
293
    use std::{sync::mpsc::channel, thread};
294
295
    use super::OnceCell;
296
297
    impl<T> OnceCell<T> {
298
        fn init(&self, f: impl FnOnce() -> T) {
299
            enum Void {}
300
            let _ = self.initialize(|| Ok::<T, Void>(f()));
301
        }
302
    }
303
304
    #[test]
305
    fn smoke_once() {
306
        static O: OnceCell<()> = OnceCell::new();
307
        let mut a = 0;
308
        O.init(|| a += 1);
309
        assert_eq!(a, 1);
310
        O.init(|| a += 1);
311
        assert_eq!(a, 1);
312
    }
313
314
    #[test]
315
    fn stampede_once() {
316
        static O: OnceCell<()> = OnceCell::new();
317
        static mut RUN: bool = false;
318
319
        let (tx, rx) = channel();
320
        for _ in 0..10 {
321
            let tx = tx.clone();
322
            thread::spawn(move || {
323
                for _ in 0..4 {
324
                    thread::yield_now()
325
                }
326
                unsafe {
327
                    O.init(|| {
328
                        assert!(!RUN);
329
                        RUN = true;
330
                    });
331
                    assert!(RUN);
332
                }
333
                tx.send(()).unwrap();
334
            });
335
        }
336
337
        unsafe {
338
            O.init(|| {
339
                assert!(!RUN);
340
                RUN = true;
341
            });
342
            assert!(RUN);
343
        }
344
345
        for _ in 0..10 {
346
            rx.recv().unwrap();
347
        }
348
    }
349
350
    #[test]
351
    fn poison_bad() {
352
        static O: OnceCell<()> = OnceCell::new();
353
354
        // poison the once
355
        let t = panic::catch_unwind(|| {
356
            O.init(|| panic!());
357
        });
358
        assert!(t.is_err());
359
360
        // we can subvert poisoning, however
361
        let mut called = false;
362
        O.init(|| {
363
            called = true;
364
        });
365
        assert!(called);
366
367
        // once any success happens, we stop propagating the poison
368
        O.init(|| {});
369
    }
370
371
    #[test]
372
    fn wait_for_force_to_finish() {
373
        static O: OnceCell<()> = OnceCell::new();
374
375
        // poison the once
376
        let t = panic::catch_unwind(|| {
377
            O.init(|| panic!());
378
        });
379
        assert!(t.is_err());
380
381
        // make sure someone's waiting inside the once via a force
382
        let (tx1, rx1) = channel();
383
        let (tx2, rx2) = channel();
384
        let t1 = thread::spawn(move || {
385
            O.init(|| {
386
                tx1.send(()).unwrap();
387
                rx2.recv().unwrap();
388
            });
389
        });
390
391
        rx1.recv().unwrap();
392
393
        // put another waiter on the once
394
        let t2 = thread::spawn(|| {
395
            let mut called = false;
396
            O.init(|| {
397
                called = true;
398
            });
399
            assert!(!called);
400
        });
401
402
        tx2.send(()).unwrap();
403
404
        assert!(t1.join().is_ok());
405
        assert!(t2.join().is_ok());
406
    }
407
408
    #[test]
409
    #[cfg(target_pointer_width = "64")]
410
    fn test_size() {
411
        use std::mem::size_of;
412
413
        assert_eq!(size_of::<OnceCell<u32>>(), 4 * size_of::<u32>());
414
    }
415
}
/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.18.0/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
//! # Overview
2
//!
3
//! `once_cell` provides two new cell-like types, [`unsync::OnceCell`] and
4
//! [`sync::OnceCell`]. A `OnceCell` might store arbitrary non-`Copy` types, can
5
//! be assigned to at most once and provides direct access to the stored
6
//! contents. The core API looks *roughly* like this (and there's much more
7
//! inside, read on!):
8
//!
9
//! ```rust,ignore
10
//! impl<T> OnceCell<T> {
11
//!     const fn new() -> OnceCell<T> { ... }
12
//!     fn set(&self, value: T) -> Result<(), T> { ... }
13
//!     fn get(&self) -> Option<&T> { ... }
14
//! }
15
//! ```
16
//!
17
//! Note that, like with [`RefCell`] and [`Mutex`], the `set` method requires
18
//! only a shared reference. Because of the single assignment restriction `get`
19
//! can return a `&T` instead of `Ref<T>` or `MutexGuard<T>`.
20
//!
21
//! The `sync` flavor is thread-safe (that is, implements the [`Sync`] trait),
22
//! while the `unsync` one is not.
23
//!
24
//! [`unsync::OnceCell`]: unsync/struct.OnceCell.html
25
//! [`sync::OnceCell`]: sync/struct.OnceCell.html
26
//! [`RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
27
//! [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
28
//! [`Sync`]: https://doc.rust-lang.org/std/marker/trait.Sync.html
29
//!
30
//! # Recipes
31
//!
32
//! `OnceCell` might be useful for a variety of patterns.
33
//!
34
//! ## Safe Initialization of Global Data
35
//!
36
//! ```rust
37
//! use std::{env, io};
38
//!
39
//! use once_cell::sync::OnceCell;
40
//!
41
//! #[derive(Debug)]
42
//! pub struct Logger {
43
//!     // ...
44
//! }
45
//! static INSTANCE: OnceCell<Logger> = OnceCell::new();
46
//!
47
//! impl Logger {
48
//!     pub fn global() -> &'static Logger {
49
//!         INSTANCE.get().expect("logger is not initialized")
50
//!     }
51
//!
52
//!     fn from_cli(args: env::Args) -> Result<Logger, std::io::Error> {
53
//!        // ...
54
//! #      Ok(Logger {})
55
//!     }
56
//! }
57
//!
58
//! fn main() {
59
//!     let logger = Logger::from_cli(env::args()).unwrap();
60
//!     INSTANCE.set(logger).unwrap();
61
//!     // use `Logger::global()` from now on
62
//! }
63
//! ```
64
//!
65
//! ## Lazy Initialized Global Data
66
//!
67
//! This is essentially the `lazy_static!` macro, but without a macro.
68
//!
69
//! ```rust
70
//! use std::{sync::Mutex, collections::HashMap};
71
//!
72
//! use once_cell::sync::OnceCell;
73
//!
74
//! fn global_data() -> &'static Mutex<HashMap<i32, String>> {
75
//!     static INSTANCE: OnceCell<Mutex<HashMap<i32, String>>> = OnceCell::new();
76
//!     INSTANCE.get_or_init(|| {
77
//!         let mut m = HashMap::new();
78
//!         m.insert(13, "Spica".to_string());
79
//!         m.insert(74, "Hoyten".to_string());
80
//!         Mutex::new(m)
81
//!     })
82
//! }
83
//! ```
84
//!
85
//! There are also the [`sync::Lazy`] and [`unsync::Lazy`] convenience types to
86
//! streamline this pattern:
87
//!
88
//! ```rust
89
//! use std::{sync::Mutex, collections::HashMap};
90
//! use once_cell::sync::Lazy;
91
//!
92
//! static GLOBAL_DATA: Lazy<Mutex<HashMap<i32, String>>> = Lazy::new(|| {
93
//!     let mut m = HashMap::new();
94
//!     m.insert(13, "Spica".to_string());
95
//!     m.insert(74, "Hoyten".to_string());
96
//!     Mutex::new(m)
97
//! });
98
//!
99
//! fn main() {
100
//!     println!("{:?}", GLOBAL_DATA.lock().unwrap());
101
//! }
102
//! ```
103
//!
104
//! Note that the variable that holds `Lazy` is declared as `static`, *not*
105
//! `const`. This is important: using `const` instead compiles, but works wrong.
106
//!
107
//! [`sync::Lazy`]: sync/struct.Lazy.html
108
//! [`unsync::Lazy`]: unsync/struct.Lazy.html
109
//!
110
//! ## General purpose lazy evaluation
111
//!
112
//! Unlike `lazy_static!`, `Lazy` works with local variables.
113
//!
114
//! ```rust
115
//! use once_cell::unsync::Lazy;
116
//!
117
//! fn main() {
118
//!     let ctx = vec![1, 2, 3];
119
//!     let thunk = Lazy::new(|| {
120
//!         ctx.iter().sum::<i32>()
121
//!     });
122
//!     assert_eq!(*thunk, 6);
123
//! }
124
//! ```
125
//!
126
//! If you need a lazy field in a struct, you probably should use `OnceCell`
127
//! directly, because that will allow you to access `self` during
128
//! initialization.
129
//!
130
//! ```rust
131
//! use std::{fs, path::PathBuf};
132
//!
133
//! use once_cell::unsync::OnceCell;
134
//!
135
//! struct Ctx {
136
//!     config_path: PathBuf,
137
//!     config: OnceCell<String>,
138
//! }
139
//!
140
//! impl Ctx {
141
//!     pub fn get_config(&self) -> Result<&str, std::io::Error> {
142
//!         let cfg = self.config.get_or_try_init(|| {
143
//!             fs::read_to_string(&self.config_path)
144
//!         })?;
145
//!         Ok(cfg.as_str())
146
//!     }
147
//! }
148
//! ```
149
//!
150
//! ## Lazily Compiled Regex
151
//!
152
//! This is a `regex!` macro which takes a string literal and returns an
153
//! *expression* that evaluates to a `&'static Regex`:
154
//!
155
//! ```
156
//! macro_rules! regex {
157
//!     ($re:literal $(,)?) => {{
158
//!         static RE: once_cell::sync::OnceCell<regex::Regex> = once_cell::sync::OnceCell::new();
159
//!         RE.get_or_init(|| regex::Regex::new($re).unwrap())
160
//!     }};
161
//! }
162
//! ```
163
//!
164
//! This macro can be useful to avoid the "compile regex on every loop
165
//! iteration" problem.
166
//!
167
//! ## Runtime `include_bytes!`
168
//!
169
//! The `include_bytes` macro is useful to include test resources, but it slows
170
//! down test compilation a lot. An alternative is to load the resources at
171
//! runtime:
172
//!
173
//! ```
174
//! use std::path::Path;
175
//!
176
//! use once_cell::sync::OnceCell;
177
//!
178
//! pub struct TestResource {
179
//!     path: &'static str,
180
//!     cell: OnceCell<Vec<u8>>,
181
//! }
182
//!
183
//! impl TestResource {
184
//!     pub const fn new(path: &'static str) -> TestResource {
185
//!         TestResource { path, cell: OnceCell::new() }
186
//!     }
187
//!     pub fn bytes(&self) -> &[u8] {
188
//!         self.cell.get_or_init(|| {
189
//!             let dir = std::env::var("CARGO_MANIFEST_DIR").unwrap();
190
//!             let path = Path::new(dir.as_str()).join(self.path);
191
//!             std::fs::read(&path).unwrap_or_else(|_err| {
192
//!                 panic!("failed to load test resource: {}", path.display())
193
//!             })
194
//!         }).as_slice()
195
//!     }
196
//! }
197
//!
198
//! static TEST_IMAGE: TestResource = TestResource::new("test_data/lena.png");
199
//!
200
//! #[test]
201
//! fn test_sobel_filter() {
202
//!     let rgb: &[u8] = TEST_IMAGE.bytes();
203
//!     // ...
204
//! # drop(rgb);
205
//! }
206
//! ```
207
//!
208
//! ## `lateinit`
209
//!
210
//! `LateInit` type for delayed initialization. It is reminiscent of Kotlin's
211
//! `lateinit` keyword and allows construction of cyclic data structures:
212
//!
213
//!
214
//! ```
215
//! use once_cell::sync::OnceCell;
216
//!
217
//! pub struct LateInit<T> { cell: OnceCell<T> }
218
//!
219
//! impl<T> LateInit<T> {
220
//!     pub fn init(&self, value: T) {
221
//!         assert!(self.cell.set(value).is_ok())
222
//!     }
223
//! }
224
//!
225
//! impl<T> Default for LateInit<T> {
226
//!     fn default() -> Self { LateInit { cell: OnceCell::default() } }
227
//! }
228
//!
229
//! impl<T> std::ops::Deref for LateInit<T> {
230
//!     type Target = T;
231
//!     fn deref(&self) -> &T {
232
//!         self.cell.get().unwrap()
233
//!     }
234
//! }
235
//!
236
//! #[derive(Default)]
237
//! struct A<'a> {
238
//!     b: LateInit<&'a B<'a>>,
239
//! }
240
//!
241
//! #[derive(Default)]
242
//! struct B<'a> {
243
//!     a: LateInit<&'a A<'a>>
244
//! }
245
//!
246
//!
247
//! fn build_cycle() {
248
//!     let a = A::default();
249
//!     let b = B::default();
250
//!     a.b.init(&b);
251
//!     b.a.init(&a);
252
//!
253
//!     let _a = &a.b.a.b.a;
254
//! }
255
//! ```
256
//!
257
//! # Comparison with std
258
//!
259
//! |`!Sync` types         | Access Mode            | Drawbacks                                     |
260
//! |----------------------|------------------------|-----------------------------------------------|
261
//! |`Cell<T>`             | `T`                    | requires `T: Copy` for `get`                  |
262
//! |`RefCell<T>`          | `RefMut<T>` / `Ref<T>` | may panic at runtime                          |
263
//! |`unsync::OnceCell<T>` | `&T`                   | assignable only once                          |
264
//!
265
//! |`Sync` types          | Access Mode            | Drawbacks                                     |
266
//! |----------------------|------------------------|-----------------------------------------------|
267
//! |`AtomicT`             | `T`                    | works only with certain `Copy` types          |
268
//! |`Mutex<T>`            | `MutexGuard<T>`        | may deadlock at runtime, may block the thread |
269
//! |`sync::OnceCell<T>`   | `&T`                   | assignable only once, may block the thread    |
270
//!
271
//! Technically, calling `get_or_init` will also cause a panic or a deadlock if
272
//! it recursively calls itself. However, because the assignment can happen only
273
//! once, such cases should be more rare than equivalents with `RefCell` and
274
//! `Mutex`.
275
//!
276
//! # Minimum Supported `rustc` Version
277
//!
278
//! This crate's minimum supported `rustc` version is `1.56.0`.
279
//!
280
//! If only the `std` feature is enabled, MSRV will be updated conservatively,
281
//! supporting at least latest 8 versions of the compiler. When using other
282
//! features, like `parking_lot`, MSRV might be updated more frequently, up to
283
//! the latest stable. In both cases, increasing MSRV is *not* considered a
284
//! semver-breaking change.
285
//!
286
//! # Implementation details
287
//!
288
//! The implementation is based on the
289
//! [`lazy_static`](https://github.com/rust-lang-nursery/lazy-static.rs/) and
290
//! [`lazy_cell`](https://github.com/indiv0/lazycell/) crates and
291
//! [`std::sync::Once`]. In some sense, `once_cell` just streamlines and unifies
292
//! those APIs.
293
//!
294
//! To implement a sync flavor of `OnceCell`, this crates uses either a custom
295
//! re-implementation of `std::sync::Once` or `parking_lot::Mutex`. This is
296
//! controlled by the `parking_lot` feature (disabled by default). Performance
297
//! is the same for both cases, but the `parking_lot` based `OnceCell<T>` is
298
//! smaller by up to 16 bytes.
299
//!
300
//! This crate uses `unsafe`.
301
//!
302
//! [`std::sync::Once`]: https://doc.rust-lang.org/std/sync/struct.Once.html
303
//!
304
//! # F.A.Q.
305
//!
306
//! **Should I use the sync or unsync flavor?**
307
//!
308
//! Because Rust compiler checks thread safety for you, it's impossible to
309
//! accidentally use `unsync` where `sync` is required. So, use `unsync` in
310
//! single-threaded code and `sync` in multi-threaded. It's easy to switch
311
//! between the two if code becomes multi-threaded later.
312
//!
313
//! At the moment, `unsync` has an additional benefit that reentrant
314
//! initialization causes a panic, which might be easier to debug than a
315
//! deadlock.
316
//!
317
//! **Does this crate support async?**
318
//!
319
//! No, but you can use
320
//! [`async_once_cell`](https://crates.io/crates/async_once_cell) instead.
321
//!
322
//! **Does this crate support `no_std`?**
323
//!
324
//! Yes, but with caveats. `OnceCell` is a synchronization primitive which
325
//! _semantically_ relies on blocking. `OnceCell` guarantees that at most one
326
//! `f` will be called to compute the value. If two threads of execution call
327
//! `get_or_init` concurrently, one of them has to wait.
328
//!
329
//! Waiting fundamentally requires OS support. Execution environment needs to
330
//! understand who waits on whom to prevent deadlocks due to priority inversion.
331
//! You _could_ make code to compile by blindly using pure spinlocks, but the
332
//! runtime behavior would be subtly wrong.
333
//!
334
//! Given these constraints, `once_cell` provides the following options:
335
//!
336
//! - The `race` module provides similar, but distinct synchronization primitive
337
//!   which is compatible with `no_std`. With `race`, the `f` function can be
338
//!   called multiple times by different threads, but only one thread will win
339
//!   to install the value.
340
//! - `critical-section` feature (with a `-`, not `_`) uses `critical_section`
341
//!   to implement blocking.
342
//!
343
//! **Can I bring my own mutex?**
344
//!
345
//! There is [generic_once_cell](https://crates.io/crates/generic_once_cell) to
346
//! allow just that.
347
//!
348
//! **Should I use `std::cell::OnceCell`, `once_cell`, or `lazy_static`?**
349
//!
350
//! If you can use `std` version (your MSRV is at least 1.70, and you don't need
351
//! extra features `once_cell` provides), use `std`. Otherwise, use `once_cell`.
352
//! Don't use `lazy_static`.
353
//!
354
//! # Related crates
355
//!
356
//! * Most of this crate's functionality is available in `std` starting with
357
//!   Rust 1.70. See `std::cell::OnceCell` and `std::sync::OnceLock`.
358
//! * [double-checked-cell](https://github.com/niklasf/double-checked-cell)
359
//! * [lazy-init](https://crates.io/crates/lazy-init)
360
//! * [lazycell](https://crates.io/crates/lazycell)
361
//! * [mitochondria](https://crates.io/crates/mitochondria)
362
//! * [lazy_static](https://crates.io/crates/lazy_static)
363
//! * [async_once_cell](https://crates.io/crates/async_once_cell)
364
//! * [generic_once_cell](https://crates.io/crates/generic_once_cell) (bring
365
//!   your own mutex)
366
367
#![cfg_attr(not(feature = "std"), no_std)]
368
369
#[cfg(feature = "alloc")]
370
extern crate alloc;
371
372
#[cfg(all(feature = "critical-section", not(feature = "std")))]
373
#[path = "imp_cs.rs"]
374
mod imp;
375
376
#[cfg(all(feature = "std", feature = "parking_lot"))]
377
#[path = "imp_pl.rs"]
378
mod imp;
379
380
#[cfg(all(feature = "std", not(feature = "parking_lot")))]
381
#[path = "imp_std.rs"]
382
mod imp;
383
384
/// Single-threaded version of `OnceCell`.
385
pub mod unsync {
386
    use core::{
387
        cell::{Cell, UnsafeCell},
388
        fmt, mem,
389
        ops::{Deref, DerefMut},
390
        panic::{RefUnwindSafe, UnwindSafe},
391
    };
392
393
    /// A cell which can be written to only once. It is not thread safe.
394
    ///
395
    /// Unlike [`std::cell::RefCell`], a `OnceCell` provides simple `&`
396
    /// references to the contents.
397
    ///
398
    /// [`std::cell::RefCell`]: https://doc.rust-lang.org/std/cell/struct.RefCell.html
399
    ///
400
    /// # Example
401
    /// ```
402
    /// use once_cell::unsync::OnceCell;
403
    ///
404
    /// let cell = OnceCell::new();
405
    /// assert!(cell.get().is_none());
406
    ///
407
    /// let value: &String = cell.get_or_init(|| {
408
    ///     "Hello, World!".to_string()
409
    /// });
410
    /// assert_eq!(value, "Hello, World!");
411
    /// assert!(cell.get().is_some());
412
    /// ```
413
    pub struct OnceCell<T> {
414
        // Invariant: written to at most once.
415
        inner: UnsafeCell<Option<T>>,
416
    }
417
418
    // Similarly to a `Sync` bound on `sync::OnceCell`, we can use
419
    // `&unsync::OnceCell` to sneak a `T` through `catch_unwind`,
420
    // by initializing the cell in closure and extracting the value in the
421
    // `Drop`.
422
    impl<T: RefUnwindSafe + UnwindSafe> RefUnwindSafe for OnceCell<T> {}
423
    impl<T: UnwindSafe> UnwindSafe for OnceCell<T> {}
424
425
    impl<T> Default for OnceCell<T> {
426
0
        fn default() -> Self {
427
0
            Self::new()
428
0
        }
429
    }
430
431
    impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
432
0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
433
0
            match self.get() {
434
0
                Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
435
0
                None => f.write_str("OnceCell(Uninit)"),
436
            }
437
0
        }
438
    }
439
440
    impl<T: Clone> Clone for OnceCell<T> {
441
0
        fn clone(&self) -> OnceCell<T> {
442
0
            match self.get() {
443
0
                Some(value) => OnceCell::with_value(value.clone()),
444
0
                None => OnceCell::new(),
445
            }
446
0
        }
447
448
        fn clone_from(&mut self, source: &Self) {
449
0
            match (self.get_mut(), source.get()) {
450
0
                (Some(this), Some(source)) => this.clone_from(source),
451
0
                _ => *self = source.clone(),
452
            }
453
0
        }
454
    }
455
456
    impl<T: PartialEq> PartialEq for OnceCell<T> {
457
0
        fn eq(&self, other: &Self) -> bool {
458
0
            self.get() == other.get()
459
0
        }
460
    }
461
462
    impl<T: Eq> Eq for OnceCell<T> {}
463
464
    impl<T> From<T> for OnceCell<T> {
465
0
        fn from(value: T) -> Self {
466
0
            OnceCell::with_value(value)
467
0
        }
468
    }
469
470
    impl<T> OnceCell<T> {
471
        /// Creates a new empty cell.
472
0
        pub const fn new() -> OnceCell<T> {
473
0
            OnceCell { inner: UnsafeCell::new(None) }
474
0
        }
475
476
        /// Creates a new initialized cell.
477
0
        pub const fn with_value(value: T) -> OnceCell<T> {
478
0
            OnceCell { inner: UnsafeCell::new(Some(value)) }
479
0
        }
480
481
        /// Gets a reference to the underlying value.
482
        ///
483
        /// Returns `None` if the cell is empty.
484
        #[inline]
485
0
        pub fn get(&self) -> Option<&T> {
486
0
            // Safe due to `inner`'s invariant of being written to at most once.
487
0
            // Had multiple writes to `inner` been allowed, a reference to the
488
0
            // value we return now would become dangling by a write of a
489
0
            // different value later.
490
0
            unsafe { &*self.inner.get() }.as_ref()
491
0
        }
492
493
        /// Gets a mutable reference to the underlying value.
494
        ///
495
        /// Returns `None` if the cell is empty.
496
        ///
497
        /// This method is allowed to violate the invariant of writing to a `OnceCell`
498
        /// at most once because it requires `&mut` access to `self`. As with all
499
        /// interior mutability, `&mut` access permits arbitrary modification:
500
        ///
501
        /// ```
502
        /// use once_cell::unsync::OnceCell;
503
        ///
504
        /// let mut cell: OnceCell<u32> = OnceCell::new();
505
        /// cell.set(92).unwrap();
506
        /// *cell.get_mut().unwrap() = 93;
507
        /// assert_eq!(cell.get(), Some(&93));
508
        /// ```
509
        #[inline]
510
0
        pub fn get_mut(&mut self) -> Option<&mut T> {
511
0
            // Safe because we have unique access
512
0
            unsafe { &mut *self.inner.get() }.as_mut()
513
0
        }
514
515
        /// Sets the contents of this cell to `value`.
516
        ///
517
        /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
518
        /// full.
519
        ///
520
        /// # Example
521
        /// ```
522
        /// use once_cell::unsync::OnceCell;
523
        ///
524
        /// let cell = OnceCell::new();
525
        /// assert!(cell.get().is_none());
526
        ///
527
        /// assert_eq!(cell.set(92), Ok(()));
528
        /// assert_eq!(cell.set(62), Err(62));
529
        ///
530
        /// assert!(cell.get().is_some());
531
        /// ```
532
0
        pub fn set(&self, value: T) -> Result<(), T> {
533
0
            match self.try_insert(value) {
534
0
                Ok(_) => Ok(()),
535
0
                Err((_, value)) => Err(value),
536
            }
537
0
        }
538
539
        /// Like [`set`](Self::set), but also returns a reference to the final cell value.
540
        ///
541
        /// # Example
542
        /// ```
543
        /// use once_cell::unsync::OnceCell;
544
        ///
545
        /// let cell = OnceCell::new();
546
        /// assert!(cell.get().is_none());
547
        ///
548
        /// assert_eq!(cell.try_insert(92), Ok(&92));
549
        /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
550
        ///
551
        /// assert!(cell.get().is_some());
552
        /// ```
553
        pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
554
0
            if let Some(old) = self.get() {
555
0
                return Err((old, value));
556
0
            }
557
0
558
0
            let slot = unsafe { &mut *self.inner.get() };
559
0
            // This is the only place where we set the slot, no races
560
0
            // due to reentrancy/concurrency are possible, and we've
561
0
            // checked that slot is currently `None`, so this write
562
0
            // maintains the `inner`'s invariant.
563
0
            *slot = Some(value);
564
0
            Ok(unsafe { slot.as_ref().unwrap_unchecked() })
565
0
        }
566
567
        /// Gets the contents of the cell, initializing it with `f`
568
        /// if the cell was empty.
569
        ///
570
        /// # Panics
571
        ///
572
        /// If `f` panics, the panic is propagated to the caller, and the cell
573
        /// remains uninitialized.
574
        ///
575
        /// It is an error to reentrantly initialize the cell from `f`. Doing
576
        /// so results in a panic.
577
        ///
578
        /// # Example
579
        /// ```
580
        /// use once_cell::unsync::OnceCell;
581
        ///
582
        /// let cell = OnceCell::new();
583
        /// let value = cell.get_or_init(|| 92);
584
        /// assert_eq!(value, &92);
585
        /// let value = cell.get_or_init(|| unreachable!());
586
        /// assert_eq!(value, &92);
587
        /// ```
588
0
        pub fn get_or_init<F>(&self, f: F) -> &T
589
0
        where
590
0
            F: FnOnce() -> T,
591
0
        {
592
0
            enum Void {}
593
0
            match self.get_or_try_init(|| Ok::<T, Void>(f())) {
594
0
                Ok(val) => val,
595
0
                Err(void) => match void {},
596
0
            }
597
0
        }
598
599
        /// Gets the contents of the cell, initializing it with `f` if
600
        /// the cell was empty. If the cell was empty and `f` failed, an
601
        /// error is returned.
602
        ///
603
        /// # Panics
604
        ///
605
        /// If `f` panics, the panic is propagated to the caller, and the cell
606
        /// remains uninitialized.
607
        ///
608
        /// It is an error to reentrantly initialize the cell from `f`. Doing
609
        /// so results in a panic.
610
        ///
611
        /// # Example
612
        /// ```
613
        /// use once_cell::unsync::OnceCell;
614
        ///
615
        /// let cell = OnceCell::new();
616
        /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
617
        /// assert!(cell.get().is_none());
618
        /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
619
        ///     Ok(92)
620
        /// });
621
        /// assert_eq!(value, Ok(&92));
622
        /// assert_eq!(cell.get(), Some(&92))
623
        /// ```
624
0
        pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
625
0
        where
626
0
            F: FnOnce() -> Result<T, E>,
627
0
        {
628
0
            if let Some(val) = self.get() {
629
0
                return Ok(val);
630
0
            }
631
0
            let val = f()?;
632
            // Note that *some* forms of reentrant initialization might lead to
633
            // UB (see `reentrant_init` test). I believe that just removing this
634
            // `assert`, while keeping `set/get` would be sound, but it seems
635
            // better to panic, rather than to silently use an old value.
636
0
            assert!(self.set(val).is_ok(), "reentrant init");
637
0
            Ok(unsafe { self.get().unwrap_unchecked() })
638
0
        }
639
640
        /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
641
        ///
642
        /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
643
        ///
644
        /// # Examples
645
        ///
646
        /// ```
647
        /// use once_cell::unsync::OnceCell;
648
        ///
649
        /// let mut cell: OnceCell<String> = OnceCell::new();
650
        /// assert_eq!(cell.take(), None);
651
        ///
652
        /// let mut cell = OnceCell::new();
653
        /// cell.set("hello".to_string()).unwrap();
654
        /// assert_eq!(cell.take(), Some("hello".to_string()));
655
        /// assert_eq!(cell.get(), None);
656
        /// ```
657
        ///
658
        /// This method is allowed to violate the invariant of writing to a `OnceCell`
659
        /// at most once because it requires `&mut` access to `self`. As with all
660
        /// interior mutability, `&mut` access permits arbitrary modification:
661
        ///
662
        /// ```
663
        /// use once_cell::unsync::OnceCell;
664
        ///
665
        /// let mut cell: OnceCell<u32> = OnceCell::new();
666
        /// cell.set(92).unwrap();
667
        /// cell = OnceCell::new();
668
        /// ```
669
0
        pub fn take(&mut self) -> Option<T> {
670
0
            mem::take(self).into_inner()
671
0
        }
672
673
        /// Consumes the `OnceCell`, returning the wrapped value.
674
        ///
675
        /// Returns `None` if the cell was empty.
676
        ///
677
        /// # Examples
678
        ///
679
        /// ```
680
        /// use once_cell::unsync::OnceCell;
681
        ///
682
        /// let cell: OnceCell<String> = OnceCell::new();
683
        /// assert_eq!(cell.into_inner(), None);
684
        ///
685
        /// let cell = OnceCell::new();
686
        /// cell.set("hello".to_string()).unwrap();
687
        /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
688
        /// ```
689
0
        pub fn into_inner(self) -> Option<T> {
690
0
            // Because `into_inner` takes `self` by value, the compiler statically verifies
691
0
            // that it is not currently borrowed. So it is safe to move out `Option<T>`.
692
0
            self.inner.into_inner()
693
0
        }
694
    }
695
696
    /// A value which is initialized on the first access.
697
    ///
698
    /// # Example
699
    /// ```
700
    /// use once_cell::unsync::Lazy;
701
    ///
702
    /// let lazy: Lazy<i32> = Lazy::new(|| {
703
    ///     println!("initializing");
704
    ///     92
705
    /// });
706
    /// println!("ready");
707
    /// println!("{}", *lazy);
708
    /// println!("{}", *lazy);
709
    ///
710
    /// // Prints:
711
    /// //   ready
712
    /// //   initializing
713
    /// //   92
714
    /// //   92
715
    /// ```
716
    pub struct Lazy<T, F = fn() -> T> {
717
        cell: OnceCell<T>,
718
        init: Cell<Option<F>>,
719
    }
720
721
    impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
722
723
    impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
724
0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
725
0
            f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
726
0
        }
727
    }
728
729
    impl<T, F> Lazy<T, F> {
730
        /// Creates a new lazy value with the given initializing function.
731
        ///
732
        /// # Example
733
        /// ```
734
        /// # fn main() {
735
        /// use once_cell::unsync::Lazy;
736
        ///
737
        /// let hello = "Hello, World!".to_string();
738
        ///
739
        /// let lazy = Lazy::new(|| hello.to_uppercase());
740
        ///
741
        /// assert_eq!(&*lazy, "HELLO, WORLD!");
742
        /// # }
743
        /// ```
744
0
        pub const fn new(init: F) -> Lazy<T, F> {
745
0
            Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) }
746
0
        }
747
748
        /// Consumes this `Lazy` returning the stored value.
749
        ///
750
        /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
751
0
        pub fn into_value(this: Lazy<T, F>) -> Result<T, F> {
752
0
            let cell = this.cell;
753
0
            let init = this.init;
754
0
            cell.into_inner().ok_or_else(|| {
755
0
                init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned"))
756
0
            })
757
0
        }
758
    }
759
760
    impl<T, F: FnOnce() -> T> Lazy<T, F> {
761
        /// Forces the evaluation of this lazy value and returns a reference to
762
        /// the result.
763
        ///
764
        /// This is equivalent to the `Deref` impl, but is explicit.
765
        ///
766
        /// # Example
767
        /// ```
768
        /// use once_cell::unsync::Lazy;
769
        ///
770
        /// let lazy = Lazy::new(|| 92);
771
        ///
772
        /// assert_eq!(Lazy::force(&lazy), &92);
773
        /// assert_eq!(&*lazy, &92);
774
        /// ```
775
0
        pub fn force(this: &Lazy<T, F>) -> &T {
776
0
            this.cell.get_or_init(|| match this.init.take() {
777
0
                Some(f) => f(),
778
0
                None => panic!("Lazy instance has previously been poisoned"),
779
0
            })
780
0
        }
781
782
        /// Forces the evaluation of this lazy value and returns a mutable reference to
783
        /// the result.
784
        ///
785
        /// This is equivalent to the `DerefMut` impl, but is explicit.
786
        ///
787
        /// # Example
788
        /// ```
789
        /// use once_cell::unsync::Lazy;
790
        ///
791
        /// let mut lazy = Lazy::new(|| 92);
792
        ///
793
        /// assert_eq!(Lazy::force_mut(&mut lazy), &92);
794
        /// assert_eq!(*lazy, 92);
795
        /// ```
796
0
        pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
797
0
            if this.cell.get_mut().is_none() {
798
0
                let value = match this.init.get_mut().take() {
799
0
                    Some(f) => f(),
800
0
                    None => panic!("Lazy instance has previously been poisoned"),
801
                };
802
0
                this.cell = OnceCell::with_value(value);
803
0
            }
804
0
            this.cell.get_mut().unwrap_or_else(|| unreachable!())
805
0
        }
806
807
        /// Gets the reference to the result of this lazy value if
808
        /// it was initialized, otherwise returns `None`.
809
        ///
810
        /// # Example
811
        /// ```
812
        /// use once_cell::unsync::Lazy;
813
        ///
814
        /// let lazy = Lazy::new(|| 92);
815
        ///
816
        /// assert_eq!(Lazy::get(&lazy), None);
817
        /// assert_eq!(&*lazy, &92);
818
        /// assert_eq!(Lazy::get(&lazy), Some(&92));
819
        /// ```
820
0
        pub fn get(this: &Lazy<T, F>) -> Option<&T> {
821
0
            this.cell.get()
822
0
        }
823
824
        /// Gets the mutable reference to the result of this lazy value if
825
        /// it was initialized, otherwise returns `None`.
826
        ///
827
        /// # Example
828
        /// ```
829
        /// use once_cell::unsync::Lazy;
830
        ///
831
        /// let mut lazy = Lazy::new(|| 92);
832
        ///
833
        /// assert_eq!(Lazy::get_mut(&mut lazy), None);
834
        /// assert_eq!(*lazy, 92);
835
        /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
836
        /// ```
837
0
        pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> {
838
0
            this.cell.get_mut()
839
0
        }
840
    }
841
842
    impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
843
        type Target = T;
844
0
        fn deref(&self) -> &T {
845
0
            Lazy::force(self)
846
0
        }
847
    }
848
849
    impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
850
0
        fn deref_mut(&mut self) -> &mut T {
851
0
            Lazy::force_mut(self)
852
0
        }
853
    }
854
855
    impl<T: Default> Default for Lazy<T> {
856
        /// Creates a new lazy value using `Default` as the initializing function.
857
0
        fn default() -> Lazy<T> {
858
0
            Lazy::new(T::default)
859
0
        }
860
    }
861
}
862
863
/// Thread-safe, blocking version of `OnceCell`.
864
#[cfg(any(feature = "std", feature = "critical-section"))]
865
pub mod sync {
866
    use core::{
867
        cell::Cell,
868
        fmt, mem,
869
        ops::{Deref, DerefMut},
870
        panic::RefUnwindSafe,
871
    };
872
873
    use super::imp::OnceCell as Imp;
874
875
    /// A thread-safe cell which can be written to only once.
876
    ///
877
    /// `OnceCell` provides `&` references to the contents without RAII guards.
878
    ///
879
    /// Reading a non-`None` value out of `OnceCell` establishes a
880
    /// happens-before relationship with a corresponding write. For example, if
881
    /// thread A initializes the cell with `get_or_init(f)`, and thread B
882
    /// subsequently reads the result of this call, B also observes all the side
883
    /// effects of `f`.
884
    ///
885
    /// # Example
886
    /// ```
887
    /// use once_cell::sync::OnceCell;
888
    ///
889
    /// static CELL: OnceCell<String> = OnceCell::new();
890
    /// assert!(CELL.get().is_none());
891
    ///
892
    /// std::thread::spawn(|| {
893
    ///     let value: &String = CELL.get_or_init(|| {
894
    ///         "Hello, World!".to_string()
895
    ///     });
896
    ///     assert_eq!(value, "Hello, World!");
897
    /// }).join().unwrap();
898
    ///
899
    /// let value: Option<&String> = CELL.get();
900
    /// assert!(value.is_some());
901
    /// assert_eq!(value.unwrap().as_str(), "Hello, World!");
902
    /// ```
903
    pub struct OnceCell<T>(Imp<T>);
904
905
    impl<T> Default for OnceCell<T> {
906
0
        fn default() -> OnceCell<T> {
907
0
            OnceCell::new()
908
0
        }
909
    }
910
911
    impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
912
0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
913
0
            match self.get() {
914
0
                Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
915
0
                None => f.write_str("OnceCell(Uninit)"),
916
            }
917
0
        }
918
    }
919
920
    impl<T: Clone> Clone for OnceCell<T> {
921
0
        fn clone(&self) -> OnceCell<T> {
922
0
            match self.get() {
923
0
                Some(value) => Self::with_value(value.clone()),
924
0
                None => Self::new(),
925
            }
926
0
        }
927
928
        fn clone_from(&mut self, source: &Self) {
929
0
            match (self.get_mut(), source.get()) {
930
0
                (Some(this), Some(source)) => this.clone_from(source),
931
0
                _ => *self = source.clone(),
932
            }
933
0
        }
934
    }
935
936
    impl<T> From<T> for OnceCell<T> {
937
0
        fn from(value: T) -> Self {
938
0
            Self::with_value(value)
939
0
        }
940
    }
941
942
    impl<T: PartialEq> PartialEq for OnceCell<T> {
943
0
        fn eq(&self, other: &OnceCell<T>) -> bool {
944
0
            self.get() == other.get()
945
0
        }
946
    }
947
948
    impl<T: Eq> Eq for OnceCell<T> {}
949
950
    impl<T> OnceCell<T> {
951
        /// Creates a new empty cell.
952
0
        pub const fn new() -> OnceCell<T> {
953
0
            OnceCell(Imp::new())
954
0
        }
955
956
        /// Creates a new initialized cell.
957
0
        pub const fn with_value(value: T) -> OnceCell<T> {
958
0
            OnceCell(Imp::with_value(value))
959
0
        }
960
961
        /// Gets the reference to the underlying value.
962
        ///
963
        /// Returns `None` if the cell is empty, or being initialized. This
964
        /// method never blocks.
965
1.12k
        pub fn get(&self) -> Option<&T> {
966
1.12k
            if self.0.is_initialized() {
967
                // Safe b/c value is initialized.
968
0
                Some(unsafe { self.get_unchecked() })
969
            } else {
970
1.12k
                None
971
            }
972
1.12k
        }
_RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE3getCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
965
1.12k
        pub fn get(&self) -> Option<&T> {
966
1.12k
            if self.0.is_initialized() {
967
                // Safe b/c value is initialized.
968
0
                Some(unsafe { self.get_unchecked() })
969
            } else {
970
1.12k
                None
971
            }
972
1.12k
        }
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE3getCsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellpE3getB7_
973
974
        /// Gets the reference to the underlying value, blocking the current
975
        /// thread until it is set.
976
        ///
977
        /// ```
978
        /// use once_cell::sync::OnceCell;
979
        ///
980
        /// let mut cell = std::sync::Arc::new(OnceCell::new());
981
        /// let t = std::thread::spawn({
982
        ///     let cell = std::sync::Arc::clone(&cell);
983
        ///     move || cell.set(92).unwrap()
984
        /// });
985
        ///
986
        /// // Returns immediately, but might return None.
987
        /// let _value_or_none = cell.get();
988
        ///
989
        /// // Will return 92, but might block until the other thread does `.set`.
990
        /// let value: &u32 = cell.wait();
991
        /// assert_eq!(*value, 92);
992
        /// t.join().unwrap();
993
        /// ```
994
        #[cfg(feature = "std")]
995
0
        pub fn wait(&self) -> &T {
996
0
            if !self.0.is_initialized() {
997
0
                self.0.wait()
998
0
            }
999
0
            debug_assert!(self.0.is_initialized());
1000
            // Safe b/c of the wait call above and the fact that we didn't
1001
            // relinquish our borrow.
1002
0
            unsafe { self.get_unchecked() }
1003
0
        }
1004
1005
        /// Gets the mutable reference to the underlying value.
1006
        ///
1007
        /// Returns `None` if the cell is empty.
1008
        ///
1009
        /// This method is allowed to violate the invariant of writing to a `OnceCell`
1010
        /// at most once because it requires `&mut` access to `self`. As with all
1011
        /// interior mutability, `&mut` access permits arbitrary modification:
1012
        ///
1013
        /// ```
1014
        /// use once_cell::sync::OnceCell;
1015
        ///
1016
        /// let mut cell: OnceCell<u32> = OnceCell::new();
1017
        /// cell.set(92).unwrap();
1018
        /// cell = OnceCell::new();
1019
        /// ```
1020
        #[inline]
1021
0
        pub fn get_mut(&mut self) -> Option<&mut T> {
1022
0
            self.0.get_mut()
1023
0
        }
1024
1025
        /// Get the reference to the underlying value, without checking if the
1026
        /// cell is initialized.
1027
        ///
1028
        /// # Safety
1029
        ///
1030
        /// Caller must ensure that the cell is in initialized state, and that
1031
        /// the contents are acquired by (synchronized to) this thread.
1032
        #[inline]
1033
0
        pub unsafe fn get_unchecked(&self) -> &T {
1034
0
            self.0.get_unchecked()
1035
0
        }
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE13get_uncheckedCsgg978DXfVXR_13fuzz_target_1
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE13get_uncheckedCsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellpE13get_uncheckedB7_
1036
1037
        /// Sets the contents of this cell to `value`.
1038
        ///
1039
        /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
1040
        /// full.
1041
        ///
1042
        /// # Example
1043
        ///
1044
        /// ```
1045
        /// use once_cell::sync::OnceCell;
1046
        ///
1047
        /// static CELL: OnceCell<i32> = OnceCell::new();
1048
        ///
1049
        /// fn main() {
1050
        ///     assert!(CELL.get().is_none());
1051
        ///
1052
        ///     std::thread::spawn(|| {
1053
        ///         assert_eq!(CELL.set(92), Ok(()));
1054
        ///     }).join().unwrap();
1055
        ///
1056
        ///     assert_eq!(CELL.set(62), Err(62));
1057
        ///     assert_eq!(CELL.get(), Some(&92));
1058
        /// }
1059
        /// ```
1060
0
        pub fn set(&self, value: T) -> Result<(), T> {
1061
0
            match self.try_insert(value) {
1062
0
                Ok(_) => Ok(()),
1063
0
                Err((_, value)) => Err(value),
1064
            }
1065
0
        }
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE3setCsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellpE3setB7_
1066
1067
        /// Like [`set`](Self::set), but also returns a reference to the final cell value.
1068
        ///
1069
        /// # Example
1070
        ///
1071
        /// ```
1072
        /// use once_cell::unsync::OnceCell;
1073
        ///
1074
        /// let cell = OnceCell::new();
1075
        /// assert!(cell.get().is_none());
1076
        ///
1077
        /// assert_eq!(cell.try_insert(92), Ok(&92));
1078
        /// assert_eq!(cell.try_insert(62), Err((&92, 62)));
1079
        ///
1080
        /// assert!(cell.get().is_some());
1081
        /// ```
1082
0
        pub fn try_insert(&self, value: T) -> Result<&T, (&T, T)> {
1083
0
            let mut value = Some(value);
1084
0
            let res = self.get_or_init(|| unsafe { value.take().unwrap_unchecked() });
Unexecuted instantiation: _RNCNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB7_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE10try_insert0Csi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNCNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB7_8OnceCellpE10try_insert0B9_
1085
0
            match value {
1086
0
                None => Ok(res),
1087
0
                Some(value) => Err((res, value)),
1088
            }
1089
0
        }
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE10try_insertCsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB5_8OnceCellpE10try_insertB7_
1090
1091
        /// Gets the contents of the cell, initializing it with `f` if the cell
1092
        /// was empty.
1093
        ///
1094
        /// Many threads may call `get_or_init` concurrently with different
1095
        /// initializing functions, but it is guaranteed that only one function
1096
        /// will be executed.
1097
        ///
1098
        /// # Panics
1099
        ///
1100
        /// If `f` panics, the panic is propagated to the caller, and the cell
1101
        /// remains uninitialized.
1102
        ///
1103
        /// It is an error to reentrantly initialize the cell from `f`. The
1104
        /// exact outcome is unspecified. Current implementation deadlocks, but
1105
        /// this may be changed to a panic in the future.
1106
        ///
1107
        /// # Example
1108
        /// ```
1109
        /// use once_cell::sync::OnceCell;
1110
        ///
1111
        /// let cell = OnceCell::new();
1112
        /// let value = cell.get_or_init(|| 92);
1113
        /// assert_eq!(value, &92);
1114
        /// let value = cell.get_or_init(|| unreachable!());
1115
        /// assert_eq!(value, &92);
1116
        /// ```
1117
0
        pub fn get_or_init<F>(&self, f: F) -> &T
1118
0
        where
1119
0
            F: FnOnce() -> T,
1120
0
        {
1121
0
            enum Void {}
1122
0
            match self.get_or_try_init(|| Ok::<T, Void>(f())) {
Unexecuted instantiation: _RNCINvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB8_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE11get_or_initNCNvB4_10try_insert0E0Csi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RNCINvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB8_8OnceCellpE11get_or_initpE0Ba_
1123
0
                Ok(val) => val,
1124
0
                Err(void) => match void {},
1125
0
            }
1126
0
        }
Unexecuted instantiation: _RINvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB6_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE11get_or_initNCNvB2_10try_insert0ECsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RINvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB6_8OnceCellpE11get_or_initpEB8_
1127
1128
        /// Gets the contents of the cell, initializing it with `f` if
1129
        /// the cell was empty. If the cell was empty and `f` failed, an
1130
        /// error is returned.
1131
        ///
1132
        /// # Panics
1133
        ///
1134
        /// If `f` panics, the panic is propagated to the caller, and
1135
        /// the cell remains uninitialized.
1136
        ///
1137
        /// It is an error to reentrantly initialize the cell from `f`.
1138
        /// The exact outcome is unspecified. Current implementation
1139
        /// deadlocks, but this may be changed to a panic in the future.
1140
        ///
1141
        /// # Example
1142
        /// ```
1143
        /// use once_cell::sync::OnceCell;
1144
        ///
1145
        /// let cell = OnceCell::new();
1146
        /// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
1147
        /// assert!(cell.get().is_none());
1148
        /// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
1149
        ///     Ok(92)
1150
        /// });
1151
        /// assert_eq!(value, Ok(&92));
1152
        /// assert_eq!(cell.get(), Some(&92))
1153
        /// ```
1154
0
        pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
1155
0
        where
1156
0
            F: FnOnce() -> Result<T, E>,
1157
0
        {
1158
            // Fast path check
1159
0
            if let Some(value) = self.get() {
1160
0
                return Ok(value);
1161
0
            }
1162
0
1163
0
            self.0.initialize(f)?;
1164
1165
            // Safe b/c value is initialized.
1166
0
            debug_assert!(self.0.is_initialized());
1167
0
            Ok(unsafe { self.get_unchecked() })
1168
0
        }
Unexecuted instantiation: _RINvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB6_8OnceCellNtNtCs5lS3ZDWxZLX_5alloc6string6StringE15get_or_try_initNCINvB2_11get_or_initNCNvB2_10try_insert0E0NtNvMs4_B6_IBC_pE11get_or_init4VoidECsi22ug6Xb94f_13libfuzzer_sys
Unexecuted instantiation: _RINvMs4_NtCsaBdG7DIvBl9_9once_cell4syncINtB6_8OnceCellpE15get_or_try_initppEB8_
1169
1170
        /// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
1171
        ///
1172
        /// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
1173
        ///
1174
        /// # Examples
1175
        ///
1176
        /// ```
1177
        /// use once_cell::sync::OnceCell;
1178
        ///
1179
        /// let mut cell: OnceCell<String> = OnceCell::new();
1180
        /// assert_eq!(cell.take(), None);
1181
        ///
1182
        /// let mut cell = OnceCell::new();
1183
        /// cell.set("hello".to_string()).unwrap();
1184
        /// assert_eq!(cell.take(), Some("hello".to_string()));
1185
        /// assert_eq!(cell.get(), None);
1186
        /// ```
1187
        ///
1188
        /// This method is allowed to violate the invariant of writing to a `OnceCell`
1189
        /// at most once because it requires `&mut` access to `self`. As with all
1190
        /// interior mutability, `&mut` access permits arbitrary modification:
1191
        ///
1192
        /// ```
1193
        /// use once_cell::sync::OnceCell;
1194
        ///
1195
        /// let mut cell: OnceCell<u32> = OnceCell::new();
1196
        /// cell.set(92).unwrap();
1197
        /// cell = OnceCell::new();
1198
        /// ```
1199
0
        pub fn take(&mut self) -> Option<T> {
1200
0
            mem::take(self).into_inner()
1201
0
        }
1202
1203
        /// Consumes the `OnceCell`, returning the wrapped value. Returns
1204
        /// `None` if the cell was empty.
1205
        ///
1206
        /// # Examples
1207
        ///
1208
        /// ```
1209
        /// use once_cell::sync::OnceCell;
1210
        ///
1211
        /// let cell: OnceCell<String> = OnceCell::new();
1212
        /// assert_eq!(cell.into_inner(), None);
1213
        ///
1214
        /// let cell = OnceCell::new();
1215
        /// cell.set("hello".to_string()).unwrap();
1216
        /// assert_eq!(cell.into_inner(), Some("hello".to_string()));
1217
        /// ```
1218
        #[inline]
1219
0
        pub fn into_inner(self) -> Option<T> {
1220
0
            self.0.into_inner()
1221
0
        }
1222
    }
1223
1224
    /// A value which is initialized on the first access.
1225
    ///
1226
    /// This type is thread-safe and can be used in statics.
1227
    ///
1228
    /// # Example
1229
    ///
1230
    /// ```
1231
    /// use std::collections::HashMap;
1232
    ///
1233
    /// use once_cell::sync::Lazy;
1234
    ///
1235
    /// static HASHMAP: Lazy<HashMap<i32, String>> = Lazy::new(|| {
1236
    ///     println!("initializing");
1237
    ///     let mut m = HashMap::new();
1238
    ///     m.insert(13, "Spica".to_string());
1239
    ///     m.insert(74, "Hoyten".to_string());
1240
    ///     m
1241
    /// });
1242
    ///
1243
    /// fn main() {
1244
    ///     println!("ready");
1245
    ///     std::thread::spawn(|| {
1246
    ///         println!("{:?}", HASHMAP.get(&13));
1247
    ///     }).join().unwrap();
1248
    ///     println!("{:?}", HASHMAP.get(&74));
1249
    ///
1250
    ///     // Prints:
1251
    ///     //   ready
1252
    ///     //   initializing
1253
    ///     //   Some("Spica")
1254
    ///     //   Some("Hoyten")
1255
    /// }
1256
    /// ```
1257
    pub struct Lazy<T, F = fn() -> T> {
1258
        cell: OnceCell<T>,
1259
        init: Cell<Option<F>>,
1260
    }
1261
1262
    impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
1263
0
        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1264
0
            f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
1265
0
        }
1266
    }
1267
1268
    // We never create a `&F` from a `&Lazy<T, F>` so it is fine to not impl
1269
    // `Sync` for `F`. We do create a `&mut Option<F>` in `force`, but this is
1270
    // properly synchronized, so it only happens once so it also does not
1271
    // contribute to this impl.
1272
    unsafe impl<T, F: Send> Sync for Lazy<T, F> where OnceCell<T>: Sync {}
1273
    // auto-derived `Send` impl is OK.
1274
1275
    impl<T, F: RefUnwindSafe> RefUnwindSafe for Lazy<T, F> where OnceCell<T>: RefUnwindSafe {}
1276
1277
    impl<T, F> Lazy<T, F> {
1278
        /// Creates a new lazy value with the given initializing
1279
        /// function.
1280
0
        pub const fn new(f: F) -> Lazy<T, F> {
1281
0
            Lazy { cell: OnceCell::new(), init: Cell::new(Some(f)) }
1282
0
        }
1283
1284
        /// Consumes this `Lazy` returning the stored value.
1285
        ///
1286
        /// Returns `Ok(value)` if `Lazy` is initialized and `Err(f)` otherwise.
1287
0
        pub fn into_value(this: Lazy<T, F>) -> Result<T, F> {
1288
0
            let cell = this.cell;
1289
0
            let init = this.init;
1290
0
            cell.into_inner().ok_or_else(|| {
1291
0
                init.take().unwrap_or_else(|| panic!("Lazy instance has previously been poisoned"))
1292
0
            })
1293
0
        }
1294
    }
1295
1296
    impl<T, F: FnOnce() -> T> Lazy<T, F> {
1297
        /// Forces the evaluation of this lazy value and
1298
        /// returns a reference to the result. This is equivalent
1299
        /// to the `Deref` impl, but is explicit.
1300
        ///
1301
        /// # Example
1302
        /// ```
1303
        /// use once_cell::sync::Lazy;
1304
        ///
1305
        /// let lazy = Lazy::new(|| 92);
1306
        ///
1307
        /// assert_eq!(Lazy::force(&lazy), &92);
1308
        /// assert_eq!(&*lazy, &92);
1309
        /// ```
1310
0
        pub fn force(this: &Lazy<T, F>) -> &T {
1311
0
            this.cell.get_or_init(|| match this.init.take() {
1312
0
                Some(f) => f(),
1313
0
                None => panic!("Lazy instance has previously been poisoned"),
1314
0
            })
1315
0
        }
1316
1317
        /// Forces the evaluation of this lazy value and
1318
        /// returns a mutable reference to the result. This is equivalent
1319
        /// to the `Deref` impl, but is explicit.
1320
        ///
1321
        /// # Example
1322
        /// ```
1323
        /// use once_cell::sync::Lazy;
1324
        ///
1325
        /// let mut lazy = Lazy::new(|| 92);
1326
        ///
1327
        /// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92);
1328
        /// ```
1329
0
        pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
1330
0
            if this.cell.get_mut().is_none() {
1331
0
                let value = match this.init.get_mut().take() {
1332
0
                    Some(f) => f(),
1333
0
                    None => panic!("Lazy instance has previously been poisoned"),
1334
                };
1335
0
                this.cell = OnceCell::with_value(value);
1336
0
            }
1337
0
            this.cell.get_mut().unwrap_or_else(|| unreachable!())
1338
0
        }
1339
1340
        /// Gets the reference to the result of this lazy value if
1341
        /// it was initialized, otherwise returns `None`.
1342
        ///
1343
        /// # Example
1344
        /// ```
1345
        /// use once_cell::sync::Lazy;
1346
        ///
1347
        /// let lazy = Lazy::new(|| 92);
1348
        ///
1349
        /// assert_eq!(Lazy::get(&lazy), None);
1350
        /// assert_eq!(&*lazy, &92);
1351
        /// assert_eq!(Lazy::get(&lazy), Some(&92));
1352
        /// ```
1353
0
        pub fn get(this: &Lazy<T, F>) -> Option<&T> {
1354
0
            this.cell.get()
1355
0
        }
1356
1357
        /// Gets the reference to the result of this lazy value if
1358
        /// it was initialized, otherwise returns `None`.
1359
        ///
1360
        /// # Example
1361
        /// ```
1362
        /// use once_cell::sync::Lazy;
1363
        ///
1364
        /// let mut lazy = Lazy::new(|| 92);
1365
        ///
1366
        /// assert_eq!(Lazy::get_mut(&mut lazy), None);
1367
        /// assert_eq!(&*lazy, &92);
1368
        /// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
1369
        /// ```
1370
0
        pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> {
1371
0
            this.cell.get_mut()
1372
0
        }
1373
    }
1374
1375
    impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1376
        type Target = T;
1377
0
        fn deref(&self) -> &T {
1378
0
            Lazy::force(self)
1379
0
        }
1380
    }
1381
1382
    impl<T, F: FnOnce() -> T> DerefMut for Lazy<T, F> {
1383
0
        fn deref_mut(&mut self) -> &mut T {
1384
0
            Lazy::force_mut(self)
1385
0
        }
1386
    }
1387
1388
    impl<T: Default> Default for Lazy<T> {
1389
        /// Creates a new lazy value using `Default` as the initializing function.
1390
0
        fn default() -> Lazy<T> {
1391
0
            Lazy::new(T::default)
1392
0
        }
1393
    }
1394
1395
    /// ```compile_fail
1396
    /// struct S(*mut ());
1397
    /// unsafe impl Sync for S {}
1398
    ///
1399
    /// fn share<T: Sync>(_: &T) {}
1400
    /// share(&once_cell::sync::OnceCell::<S>::new());
1401
    /// ```
1402
    ///
1403
    /// ```compile_fail
1404
    /// struct S(*mut ());
1405
    /// unsafe impl Sync for S {}
1406
    ///
1407
    /// fn share<T: Sync>(_: &T) {}
1408
    /// share(&once_cell::sync::Lazy::<S>::new(|| unimplemented!()));
1409
    /// ```
1410
0
    fn _dummy() {}
1411
}
1412
1413
#[cfg(feature = "race")]
1414
pub mod race;
/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/once_cell-1.18.0/src/race.rs
Line
Count
Source (jump to first uncovered line)
1
//! Thread-safe, non-blocking, "first one wins" flavor of `OnceCell`.
2
//!
3
//! If two threads race to initialize a type from the `race` module, they
4
//! don't block, execute initialization function together, but only one of
5
//! them stores the result.
6
//!
7
//! This module does not require `std` feature.
8
//!
9
//! # Atomic orderings
10
//!
11
//! All types in this module use `Acquire` and `Release`
12
//! [atomic orderings](Ordering) for all their operations. While this is not
13
//! strictly necessary for types other than `OnceBox`, it is useful for users as
14
//! it allows them to be certain that after `get` or `get_or_init` returns on
15
//! one thread, any side-effects caused by the setter thread prior to them
16
//! calling `set` or `get_or_init` will be made visible to that thread; without
17
//! it, it's possible for it to appear as if they haven't happened yet from the
18
//! getter thread's perspective. This is an acceptable tradeoff to make since
19
//! `Acquire` and `Release` have very little performance overhead on most
20
//! architectures versus `Relaxed`.
21
22
#[cfg(feature = "critical-section")]
23
use atomic_polyfill as atomic;
24
#[cfg(not(feature = "critical-section"))]
25
use core::sync::atomic;
26
27
use atomic::{AtomicPtr, AtomicUsize, Ordering};
28
use core::cell::UnsafeCell;
29
use core::marker::PhantomData;
30
use core::num::NonZeroUsize;
31
use core::ptr;
32
33
/// A thread-safe cell which can be written to only once.
34
0
#[derive(Default, Debug)]
35
pub struct OnceNonZeroUsize {
36
    inner: AtomicUsize,
37
}
38
39
impl OnceNonZeroUsize {
40
    /// Creates a new empty cell.
41
    #[inline]
42
0
    pub const fn new() -> OnceNonZeroUsize {
43
0
        OnceNonZeroUsize { inner: AtomicUsize::new(0) }
44
0
    }
45
46
    /// Gets the underlying value.
47
    #[inline]
48
0
    pub fn get(&self) -> Option<NonZeroUsize> {
49
0
        let val = self.inner.load(Ordering::Acquire);
50
0
        NonZeroUsize::new(val)
51
0
    }
52
53
    /// Sets the contents of this cell to `value`.
54
    ///
55
    /// Returns `Ok(())` if the cell was empty and `Err(())` if it was
56
    /// full.
57
    #[inline]
58
0
    pub fn set(&self, value: NonZeroUsize) -> Result<(), ()> {
59
0
        let exchange =
60
0
            self.inner.compare_exchange(0, value.get(), Ordering::AcqRel, Ordering::Acquire);
61
0
        match exchange {
62
0
            Ok(_) => Ok(()),
63
0
            Err(_) => Err(()),
64
        }
65
0
    }
66
67
    /// Gets the contents of the cell, initializing it with `f` if the cell was
68
    /// empty.
69
    ///
70
    /// If several threads concurrently run `get_or_init`, more than one `f` can
71
    /// be called. However, all threads will return the same value, produced by
72
    /// some `f`.
73
0
    pub fn get_or_init<F>(&self, f: F) -> NonZeroUsize
74
0
    where
75
0
        F: FnOnce() -> NonZeroUsize,
76
0
    {
77
0
        enum Void {}
78
0
        match self.get_or_try_init(|| Ok::<NonZeroUsize, Void>(f())) {
79
0
            Ok(val) => val,
80
0
            Err(void) => match void {},
81
0
        }
82
0
    }
83
84
    /// Gets the contents of the cell, initializing it with `f` if
85
    /// the cell was empty. If the cell was empty and `f` failed, an
86
    /// error is returned.
87
    ///
88
    /// If several threads concurrently run `get_or_init`, more than one `f` can
89
    /// be called. However, all threads will return the same value, produced by
90
    /// some `f`.
91
0
    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<NonZeroUsize, E>
92
0
    where
93
0
        F: FnOnce() -> Result<NonZeroUsize, E>,
94
0
    {
95
0
        let val = self.inner.load(Ordering::Acquire);
96
0
        let res = match NonZeroUsize::new(val) {
97
0
            Some(it) => it,
98
            None => {
99
0
                let mut val = f()?.get();
100
0
                let exchange =
101
0
                    self.inner.compare_exchange(0, val, Ordering::AcqRel, Ordering::Acquire);
102
0
                if let Err(old) = exchange {
103
0
                    val = old;
104
0
                }
105
0
                unsafe { NonZeroUsize::new_unchecked(val) }
106
            }
107
        };
108
0
        Ok(res)
109
0
    }
110
}
111
112
/// A thread-safe cell which can be written to only once.
113
0
#[derive(Default, Debug)]
114
pub struct OnceBool {
115
    inner: OnceNonZeroUsize,
116
}
117
118
impl OnceBool {
119
    /// Creates a new empty cell.
120
    #[inline]
121
0
    pub const fn new() -> OnceBool {
122
0
        OnceBool { inner: OnceNonZeroUsize::new() }
123
0
    }
124
125
    /// Gets the underlying value.
126
    #[inline]
127
0
    pub fn get(&self) -> Option<bool> {
128
0
        self.inner.get().map(OnceBool::from_usize)
129
0
    }
130
131
    /// Sets the contents of this cell to `value`.
132
    ///
133
    /// Returns `Ok(())` if the cell was empty and `Err(())` if it was
134
    /// full.
135
    #[inline]
136
0
    pub fn set(&self, value: bool) -> Result<(), ()> {
137
0
        self.inner.set(OnceBool::to_usize(value))
138
0
    }
139
140
    /// Gets the contents of the cell, initializing it with `f` if the cell was
141
    /// empty.
142
    ///
143
    /// If several threads concurrently run `get_or_init`, more than one `f` can
144
    /// be called. However, all threads will return the same value, produced by
145
    /// some `f`.
146
0
    pub fn get_or_init<F>(&self, f: F) -> bool
147
0
    where
148
0
        F: FnOnce() -> bool,
149
0
    {
150
0
        OnceBool::from_usize(self.inner.get_or_init(|| OnceBool::to_usize(f())))
151
0
    }
152
153
    /// Gets the contents of the cell, initializing it with `f` if
154
    /// the cell was empty. If the cell was empty and `f` failed, an
155
    /// error is returned.
156
    ///
157
    /// If several threads concurrently run `get_or_init`, more than one `f` can
158
    /// be called. However, all threads will return the same value, produced by
159
    /// some `f`.
160
0
    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<bool, E>
161
0
    where
162
0
        F: FnOnce() -> Result<bool, E>,
163
0
    {
164
0
        self.inner.get_or_try_init(|| f().map(OnceBool::to_usize)).map(OnceBool::from_usize)
165
0
    }
166
167
    #[inline]
168
0
    fn from_usize(value: NonZeroUsize) -> bool {
169
0
        value.get() == 1
170
0
    }
171
172
    #[inline]
173
0
    fn to_usize(value: bool) -> NonZeroUsize {
174
0
        unsafe { NonZeroUsize::new_unchecked(if value { 1 } else { 2 }) }
175
0
    }
176
}
177
178
/// A thread-safe cell which can be written to only once.
179
pub struct OnceRef<'a, T> {
180
    inner: AtomicPtr<T>,
181
    ghost: PhantomData<UnsafeCell<&'a T>>,
182
}
183
184
// TODO: Replace UnsafeCell with SyncUnsafeCell once stabilized
185
unsafe impl<'a, T: Sync> Sync for OnceRef<'a, T> {}
186
187
impl<'a, T> core::fmt::Debug for OnceRef<'a, T> {
188
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
189
0
        write!(f, "OnceRef({:?})", self.inner)
190
0
    }
191
}
192
193
impl<'a, T> Default for OnceRef<'a, T> {
194
0
    fn default() -> Self {
195
0
        Self::new()
196
0
    }
197
}
198
199
impl<'a, T> OnceRef<'a, T> {
200
    /// Creates a new empty cell.
201
0
    pub const fn new() -> OnceRef<'a, T> {
202
0
        OnceRef { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData }
203
0
    }
204
205
    /// Gets a reference to the underlying value.
206
0
    pub fn get(&self) -> Option<&'a T> {
207
0
        let ptr = self.inner.load(Ordering::Acquire);
208
0
        unsafe { ptr.as_ref() }
209
0
    }
210
211
    /// Sets the contents of this cell to `value`.
212
    ///
213
    /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
214
    /// full.
215
0
    pub fn set(&self, value: &'a T) -> Result<(), ()> {
216
0
        let ptr = value as *const T as *mut T;
217
0
        let exchange =
218
0
            self.inner.compare_exchange(ptr::null_mut(), ptr, Ordering::AcqRel, Ordering::Acquire);
219
0
        match exchange {
220
0
            Ok(_) => Ok(()),
221
0
            Err(_) => Err(()),
222
        }
223
0
    }
224
225
    /// Gets the contents of the cell, initializing it with `f` if the cell was
226
    /// empty.
227
    ///
228
    /// If several threads concurrently run `get_or_init`, more than one `f` can
229
    /// be called. However, all threads will return the same value, produced by
230
    /// some `f`.
231
0
    pub fn get_or_init<F>(&self, f: F) -> &'a T
232
0
    where
233
0
        F: FnOnce() -> &'a T,
234
0
    {
235
0
        enum Void {}
236
0
        match self.get_or_try_init(|| Ok::<&'a T, Void>(f())) {
237
0
            Ok(val) => val,
238
0
            Err(void) => match void {},
239
0
        }
240
0
    }
241
242
    /// Gets the contents of the cell, initializing it with `f` if
243
    /// the cell was empty. If the cell was empty and `f` failed, an
244
    /// error is returned.
245
    ///
246
    /// If several threads concurrently run `get_or_init`, more than one `f` can
247
    /// be called. However, all threads will return the same value, produced by
248
    /// some `f`.
249
0
    pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&'a T, E>
250
0
    where
251
0
        F: FnOnce() -> Result<&'a T, E>,
252
0
    {
253
0
        let mut ptr = self.inner.load(Ordering::Acquire);
254
0
255
0
        if ptr.is_null() {
256
            // TODO replace with `cast_mut` when MSRV reaches 1.65.0 (also in `set`)
257
0
            ptr = f()? as *const T as *mut T;
258
0
            let exchange = self.inner.compare_exchange(
259
0
                ptr::null_mut(),
260
0
                ptr,
261
0
                Ordering::AcqRel,
262
0
                Ordering::Acquire,
263
0
            );
264
0
            if let Err(old) = exchange {
265
0
                ptr = old;
266
0
            }
267
0
        }
268
269
0
        Ok(unsafe { &*ptr })
270
0
    }
271
272
    /// ```compile_fail
273
    /// use once_cell::race::OnceRef;
274
    ///
275
    /// let mut l = OnceRef::new();
276
    ///
277
    /// {
278
    ///     let y = 2;
279
    ///     let mut r = OnceRef::new();
280
    ///     r.set(&y).unwrap();
281
    ///     core::mem::swap(&mut l, &mut r);
282
    /// }
283
    ///
284
    /// // l now contains a dangling reference to y
285
    /// eprintln!("uaf: {}", l.get().unwrap());
286
    /// ```
287
0
    fn _dummy() {}
288
}
289
290
#[cfg(feature = "alloc")]
291
pub use self::once_box::OnceBox;
292
293
#[cfg(feature = "alloc")]
294
mod once_box {
295
    use super::atomic::{AtomicPtr, Ordering};
296
    use core::{marker::PhantomData, ptr};
297
298
    use alloc::boxed::Box;
299
300
    /// A thread-safe cell which can be written to only once.
301
    pub struct OnceBox<T> {
302
        inner: AtomicPtr<T>,
303
        ghost: PhantomData<Option<Box<T>>>,
304
    }
305
306
    impl<T> core::fmt::Debug for OnceBox<T> {
307
0
        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
308
0
            write!(f, "OnceBox({:?})", self.inner.load(Ordering::Relaxed))
309
0
        }
310
    }
311
312
    impl<T> Default for OnceBox<T> {
313
0
        fn default() -> Self {
314
0
            Self::new()
315
0
        }
316
    }
317
318
    impl<T> Drop for OnceBox<T> {
319
0
        fn drop(&mut self) {
320
0
            let ptr = *self.inner.get_mut();
321
0
            if !ptr.is_null() {
322
0
                drop(unsafe { Box::from_raw(ptr) })
323
0
            }
324
0
        }
325
    }
326
327
    impl<T> OnceBox<T> {
328
        /// Creates a new empty cell.
329
0
        pub const fn new() -> OnceBox<T> {
330
0
            OnceBox { inner: AtomicPtr::new(ptr::null_mut()), ghost: PhantomData }
331
0
        }
332
333
        /// Gets a reference to the underlying value.
334
0
        pub fn get(&self) -> Option<&T> {
335
0
            let ptr = self.inner.load(Ordering::Acquire);
336
0
            if ptr.is_null() {
337
0
                return None;
338
0
            }
339
0
            Some(unsafe { &*ptr })
340
0
        }
341
342
        /// Sets the contents of this cell to `value`.
343
        ///
344
        /// Returns `Ok(())` if the cell was empty and `Err(value)` if it was
345
        /// full.
346
0
        pub fn set(&self, value: Box<T>) -> Result<(), Box<T>> {
347
0
            let ptr = Box::into_raw(value);
348
0
            let exchange = self.inner.compare_exchange(
349
0
                ptr::null_mut(),
350
0
                ptr,
351
0
                Ordering::AcqRel,
352
0
                Ordering::Acquire,
353
0
            );
354
0
            if exchange.is_err() {
355
0
                let value = unsafe { Box::from_raw(ptr) };
356
0
                return Err(value);
357
0
            }
358
0
            Ok(())
359
0
        }
360
361
        /// Gets the contents of the cell, initializing it with `f` if the cell was
362
        /// empty.
363
        ///
364
        /// If several threads concurrently run `get_or_init`, more than one `f` can
365
        /// be called. However, all threads will return the same value, produced by
366
        /// some `f`.
367
0
        pub fn get_or_init<F>(&self, f: F) -> &T
368
0
        where
369
0
            F: FnOnce() -> Box<T>,
370
0
        {
371
0
            enum Void {}
372
0
            match self.get_or_try_init(|| Ok::<Box<T>, Void>(f())) {
373
0
                Ok(val) => val,
374
0
                Err(void) => match void {},
375
0
            }
376
0
        }
377
378
        /// Gets the contents of the cell, initializing it with `f` if
379
        /// the cell was empty. If the cell was empty and `f` failed, an
380
        /// error is returned.
381
        ///
382
        /// If several threads concurrently run `get_or_init`, more than one `f` can
383
        /// be called. However, all threads will return the same value, produced by
384
        /// some `f`.
385
0
        pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
386
0
        where
387
0
            F: FnOnce() -> Result<Box<T>, E>,
388
0
        {
389
0
            let mut ptr = self.inner.load(Ordering::Acquire);
390
0
391
0
            if ptr.is_null() {
392
0
                let val = f()?;
393
0
                ptr = Box::into_raw(val);
394
0
                let exchange = self.inner.compare_exchange(
395
0
                    ptr::null_mut(),
396
0
                    ptr,
397
0
                    Ordering::AcqRel,
398
0
                    Ordering::Acquire,
399
0
                );
400
0
                if let Err(old) = exchange {
401
0
                    drop(unsafe { Box::from_raw(ptr) });
402
0
                    ptr = old;
403
0
                }
404
0
            };
405
0
            Ok(unsafe { &*ptr })
406
0
        }
407
    }
408
409
    unsafe impl<T: Sync + Send> Sync for OnceBox<T> {}
410
411
    /// ```compile_fail
412
    /// struct S(*mut ());
413
    /// unsafe impl Sync for S {}
414
    ///
415
    /// fn share<T: Sync>(_: &T) {}
416
    /// share(&once_cell::race::OnceBox::<S>::new());
417
    /// ```
418
0
    fn _dummy() {}
419
}
/mnt/h/flex-dns/src/additional.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::answer::DnsAClass;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::question::DnsQType;
6
use crate::rdata::{DnsAType, RData};
7
use crate::write::WriteBytes;
8
9
pub struct DnsAdditionals<
10
    const PTR_STORAGE: usize,
11
    B: Buffer,
12
> {
13
    message: DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>,
14
    remaining: usize,
15
}
16
17
impl<
18
    const PTR_STORAGE: usize,
19
    B: Buffer,
20
> DnsAdditionals<PTR_STORAGE, B> {
21
    #[inline(always)]
22
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>) -> Self {
23
1.12k
        let remaining = message.header().unwrap().answer_count() as usize;
24
1.12k
        Self {
25
1.12k
            message,
26
1.12k
            remaining,
27
1.12k
        }
28
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns10additionalINtB2_14DnsAdditionalsKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
22
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>) -> Self {
23
1.12k
        let remaining = message.header().unwrap().answer_count() as usize;
24
1.12k
        Self {
25
1.12k
            message,
26
1.12k
            remaining,
27
1.12k
        }
28
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns10additionalINtB2_14DnsAdditionalsKppE3newB4_
29
30
0
    pub fn append(&mut self, answer: DnsAdditional<DnsAType>) -> Result<(), DnsMessageError> {
31
0
        let (buffer, position) = self.message.buffer_and_position();
32
0
        // Truncate the buffer to the current position.
33
0
        buffer.truncate(*position)?;
34
0
        answer.write(&mut self.message)?;
35
        // Set answer_count in the header to the current answer count + 1.
36
0
        let answer_count = self.message.header().unwrap().answer_count();
37
0
        let answer_count = answer_count + 1 - self.remaining as u16;
38
0
        self.message.header_mut()?.set_answer_count(answer_count);
39
0
        self.message.header_mut()?.set_name_server_count(0);
40
0
        self.message.header_mut()?.set_additional_records_count(0);
41
0
        self.remaining = 0;
42
0
43
0
        Ok(())
44
0
    }
45
46
    #[inline]
47
1.12k
    pub fn iter(&mut self) -> Result<DnsAdditionalsIterator, DnsMessageError> {
48
1.12k
        let (buffer, position) = self.message.buffer_and_position();
49
1.12k
        let buffer = buffer.bytes();
50
1.12k
51
1.12k
        Ok(DnsAdditionalsIterator {
52
1.12k
            buffer,
53
1.12k
            current_position: position,
54
1.12k
            remaining: &mut self.remaining,
55
1.12k
        })
56
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns10additionalINtB2_14DnsAdditionalsKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE4iterCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
47
1.12k
    pub fn iter(&mut self) -> Result<DnsAdditionalsIterator, DnsMessageError> {
48
1.12k
        let (buffer, position) = self.message.buffer_and_position();
49
1.12k
        let buffer = buffer.bytes();
50
1.12k
51
1.12k
        Ok(DnsAdditionalsIterator {
52
1.12k
            buffer,
53
1.12k
            current_position: position,
54
1.12k
            remaining: &mut self.remaining,
55
1.12k
        })
56
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns10additionalINtB2_14DnsAdditionalsKppE4iterB4_
57
58
    #[inline]
59
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>, DnsMessageError> {
60
1.12k
        if self.remaining != 0 {
61
0
            for x in self.iter()? { x?; }
62
1.12k
        }
63
64
1.12k
        Ok(DnsMessage {
65
1.12k
            buffer: self.message.buffer,
66
1.12k
            position: self.message.position,
67
1.12k
            ptr_storage: self.message.ptr_storage,
68
1.12k
        })
69
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns10additionalINtB2_14DnsAdditionalsKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE8completeCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
59
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>, DnsMessageError> {
60
1.12k
        if self.remaining != 0 {
61
0
            for x in self.iter()? { x?; }
62
1.12k
        }
63
64
1.12k
        Ok(DnsMessage {
65
1.12k
            buffer: self.message.buffer,
66
1.12k
            position: self.message.position,
67
1.12k
            ptr_storage: self.message.ptr_storage,
68
1.12k
        })
69
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns10additionalINtB2_14DnsAdditionalsKppE8completeB4_
70
}
71
72
pub struct DnsAdditionalsIterator<'a> {
73
    buffer: &'a [u8],
74
    current_position: &'a mut usize,
75
    remaining: &'a mut usize,
76
}
77
78
impl<'a> Iterator for DnsAdditionalsIterator<'a> {
79
    type Item = Result<DnsAdditional<'a, RData<'a>>, DnsMessageError>;
80
81
    #[inline]
82
22.6M
    fn next(&mut self) -> Option<Self::Item> {
83
22.6M
        if *self.remaining == 0 {
84
1.12k
            return None;
85
22.5M
        }
86
22.5M
87
22.5M
        let additional = DnsAdditional::parse(
88
22.5M
            self.buffer, self.current_position
89
22.5M
        );
90
22.5M
        *self.remaining -= 1;
91
22.5M
92
22.5M
        Some(additional)
93
22.6M
    }
_RNvXs_NtCslLTLXfmDngu_8flex_dns10additionalNtB4_22DnsAdditionalsIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
82
22.6M
    fn next(&mut self) -> Option<Self::Item> {
83
22.6M
        if *self.remaining == 0 {
84
1.12k
            return None;
85
22.5M
        }
86
22.5M
87
22.5M
        let additional = DnsAdditional::parse(
88
22.5M
            self.buffer, self.current_position
89
22.5M
        );
90
22.5M
        *self.remaining -= 1;
91
22.5M
92
22.5M
        Some(additional)
93
22.6M
    }
Unexecuted instantiation: _RNvXs_NtCslLTLXfmDngu_8flex_dns10additionalNtB4_22DnsAdditionalsIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextB6_
94
}
95
96
0
#[derive(Debug, PartialEq)]
97
pub struct DnsAdditional<'a, D> {
98
    pub name: DnsName<'a>,
99
    pub rdata: D,
100
    pub cache_flush: bool,
101
    pub aclass: DnsAClass,
102
    pub ttl: u32,
103
}
104
105
impl<'a> DnsAdditional<'a, RData<'a>> {
106
22.5M
    pub fn parse(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
107
22.5M
        let name = DnsName::parse(bytes, i)?;
108
86
        let atype_id = u16::parse(bytes, i)?;
109
81
        let atype = DnsQType::from_id(atype_id);
110
81
        let cache_flush = atype_id & 0b1000_0000_0000_0000 != 0;
111
81
        let aclass = DnsAClass::from_id(u16::parse(bytes, i)?);
112
71
        let ttl = u32::parse(bytes, i)?;
113
62
        let rdata = RData::parse(bytes, i, atype)?;
114
115
54
        Ok(Self {
116
54
            name,
117
54
            rdata,
118
54
            cache_flush,
119
54
            aclass,
120
54
            ttl,
121
54
        })
122
22.5M
    }
123
124
    fn write<
125
        const PTR_STORAGE: usize,
126
        const DNS_SECTION: DnsSection,
127
        B: Buffer,
128
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
129
        // Write the name to the buffer using the pointer storage for compression.
130
0
        message.write_name(self.name)?;
131
        // Write the atype and aclass to the buffer.
132
0
        self.rdata.id().write(message)?;
133
0
        let mut aclass = self.aclass.id();
134
0
        if self.cache_flush {
135
0
            aclass |= 0b1000_0000;
136
0
        }
137
0
        aclass.write(message)?;
138
        // Write the ttl to the buffer.
139
0
        self.ttl.write(message)?;
140
0
        (self.rdata.byte_len()? as u16).write(message)?;
141
        // Write the type specific data to the buffer.
142
0
        self.rdata.write(message)?;
143
144
0
        Ok(())
145
0
    }
146
147
54
    pub fn into_parsed(self) -> Result<DnsAdditional<'a, DnsAType<'a>>, DnsMessageError> {
148
54
        Ok(DnsAdditional {
149
54
            name: self.name,
150
54
            rdata: self.rdata.into_parsed()?,
151
12
            cache_flush: self.cache_flush,
152
12
            aclass: self.aclass,
153
12
            ttl: self.ttl,
154
        })
155
54
    }
156
}
157
158
impl<'a> DnsAdditional<'a, DnsAType<'a>> {
159
    fn write<
160
        const PTR_STORAGE: usize,
161
        const DNS_SECTION: DnsSection,
162
        B: Buffer,
163
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
164
        // Write the name to the buffer using the pointer storage for compression.
165
0
        self.name.write(message)?;
166
        // Write the atype and aclass to the buffer.
167
0
        self.rdata.id().write(message)?;
168
0
        let mut aclass = self.aclass.id();
169
0
        if self.cache_flush {
170
0
            aclass |= 0b1000_0000;
171
0
        }
172
0
        aclass.write(message)?;
173
        // Write the ttl to the buffer.
174
0
        self.ttl.write(message)?;
175
0
        let rdata_len = self.rdata.byte_len()? as u16;
176
0
        rdata_len.write(message)?;
177
        // Write the type specific data to the buffer.
178
0
        self.rdata.write(message)?;
179
180
0
        Ok(())
181
0
    }
182
}
/mnt/h/flex-dns/src/answer.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::question::DnsQType;
5
use crate::rdata::{DnsAType, RData};
6
use crate::write::WriteBytes;
7
8
pub struct DnsAnswers<
9
    const PTR_STORAGE: usize,
10
    B: Buffer,
11
> {
12
    message: DnsMessage<PTR_STORAGE, { DnsSection::Answers }, B>,
13
    remaining: usize,
14
}
15
16
impl<
17
    const PTR_STORAGE: usize,
18
    B: Buffer,
19
> DnsAnswers<PTR_STORAGE, B> {
20
    #[inline(always)]
21
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::Answers }, B>) -> Self {
22
1.12k
        let remaining = message.header().unwrap().answer_count() as usize;
23
1.12k
        Self {
24
1.12k
            message,
25
1.12k
            remaining,
26
1.12k
        }
27
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns6answerINtB2_10DnsAnswersKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
21
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::Answers }, B>) -> Self {
22
1.12k
        let remaining = message.header().unwrap().answer_count() as usize;
23
1.12k
        Self {
24
1.12k
            message,
25
1.12k
            remaining,
26
1.12k
        }
27
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns6answerINtB2_10DnsAnswersKppE3newB4_
28
29
0
    pub fn append(&mut self, answer: DnsAnswer<DnsAType>) -> Result<(), DnsMessageError> {
30
0
        let (buffer, position) = self.message.buffer_and_position();
31
0
        // Truncate the buffer to the current position.
32
0
        buffer.truncate(*position)?;
33
0
        answer.write(&mut self.message)?;
34
        // Set answer_count in the header to the current answer count + 1.
35
0
        let answer_count = self.message.header().unwrap().answer_count();
36
0
        let answer_count = answer_count + 1 - self.remaining as u16;
37
0
        self.message.header_mut()?.set_answer_count(answer_count);
38
0
        self.message.header_mut()?.set_name_server_count(0);
39
0
        self.message.header_mut()?.set_additional_records_count(0);
40
0
        self.remaining = 0;
41
0
42
0
        Ok(())
43
0
    }
44
45
    #[inline]
46
1.12k
    pub fn iter(&mut self) -> Result<DnsAnswerIterator, DnsMessageError> {
47
1.12k
        let (buffer, position) = self.message.buffer_and_position();
48
1.12k
        let buffer = buffer.bytes();
49
1.12k
50
1.12k
        Ok(DnsAnswerIterator {
51
1.12k
            buffer,
52
1.12k
            current_position: position,
53
1.12k
            remaining: &mut self.remaining,
54
1.12k
        })
55
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns6answerINtB2_10DnsAnswersKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE4iterCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
46
1.12k
    pub fn iter(&mut self) -> Result<DnsAnswerIterator, DnsMessageError> {
47
1.12k
        let (buffer, position) = self.message.buffer_and_position();
48
1.12k
        let buffer = buffer.bytes();
49
1.12k
50
1.12k
        Ok(DnsAnswerIterator {
51
1.12k
            buffer,
52
1.12k
            current_position: position,
53
1.12k
            remaining: &mut self.remaining,
54
1.12k
        })
55
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns6answerINtB2_10DnsAnswersKppE4iterB4_
56
57
    #[inline]
58
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::NameServers }, B>, DnsMessageError> {
59
1.12k
        if self.remaining != 0 {
60
0
            for x in self.iter()? { x?; }
61
1.12k
        }
62
63
1.12k
        Ok(DnsMessage {
64
1.12k
            buffer: self.message.buffer,
65
1.12k
            position: self.message.position,
66
1.12k
            ptr_storage: self.message.ptr_storage,
67
1.12k
        })
68
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns6answerINtB2_10DnsAnswersKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE8completeCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
58
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::NameServers }, B>, DnsMessageError> {
59
1.12k
        if self.remaining != 0 {
60
0
            for x in self.iter()? { x?; }
61
1.12k
        }
62
63
1.12k
        Ok(DnsMessage {
64
1.12k
            buffer: self.message.buffer,
65
1.12k
            position: self.message.position,
66
1.12k
            ptr_storage: self.message.ptr_storage,
67
1.12k
        })
68
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns6answerINtB2_10DnsAnswersKppE8completeB4_
69
}
70
71
pub struct DnsAnswerIterator<'a> {
72
    buffer: &'a [u8],
73
    current_position: &'a mut usize,
74
    remaining: &'a mut usize,
75
}
76
77
impl<'a> Iterator for DnsAnswerIterator<'a> {
78
    type Item = Result<DnsAnswer<'a, RData<'a>>, DnsMessageError>;
79
80
    #[inline]
81
22.6M
    fn next(&mut self) -> Option<Self::Item> {
82
22.6M
        if *self.remaining == 0 {
83
1.12k
            return None;
84
22.5M
        }
85
22.5M
86
22.5M
        let answer = DnsAnswer::parse(
87
22.5M
            self.buffer, self.current_position
88
22.5M
        );
89
22.5M
        *self.remaining -= 1;
90
22.5M
91
22.5M
        Some(answer)
92
22.6M
    }
_RNvXs_NtCslLTLXfmDngu_8flex_dns6answerNtB4_17DnsAnswerIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
81
22.6M
    fn next(&mut self) -> Option<Self::Item> {
82
22.6M
        if *self.remaining == 0 {
83
1.12k
            return None;
84
22.5M
        }
85
22.5M
86
22.5M
        let answer = DnsAnswer::parse(
87
22.5M
            self.buffer, self.current_position
88
22.5M
        );
89
22.5M
        *self.remaining -= 1;
90
22.5M
91
22.5M
        Some(answer)
92
22.6M
    }
Unexecuted instantiation: _RNvXs_NtCslLTLXfmDngu_8flex_dns6answerNtB4_17DnsAnswerIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextB6_
93
}
94
95
0
#[derive(Debug, PartialEq)]
96
pub struct DnsAnswer<'a, D> {
97
    pub name: DnsName<'a>,
98
    pub rdata: D,
99
    pub cache_flush: bool,
100
    pub aclass: DnsAClass,
101
    pub ttl: u32,
102
}
103
104
impl<'a> DnsAnswer<'a, RData<'a>> {
105
22.5M
    pub fn parse(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
106
22.5M
        let name = DnsName::parse(bytes, i)?;
107
2.81k
        let atype_id = u16::parse(bytes, i)?;
108
2.64k
        let atype = DnsQType::from_id(atype_id);
109
2.64k
        let cache_flush = atype_id & 0b1000_0000_0000_0000 != 0;
110
2.64k
        let aclass = DnsAClass::from_id(u16::parse(bytes, i)?);
111
2.51k
        let ttl = u32::parse(bytes, i)?;
112
2.38k
        let rdata = RData::parse(bytes, i, atype)?;
113
114
1.77k
        Ok(Self {
115
1.77k
            name,
116
1.77k
            rdata,
117
1.77k
            cache_flush,
118
1.77k
            aclass,
119
1.77k
            ttl,
120
1.77k
        })
121
22.5M
    }
122
123
    fn write<
124
        const PTR_STORAGE: usize,
125
        const DNS_SECTION: DnsSection,
126
        B: Buffer,
127
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
128
        // Write the name to the buffer using the pointer storage for compression.
129
0
        message.write_name(self.name)?;
130
        // Write the atype and aclass to the buffer.
131
0
        self.rdata.id().write(message)?;
132
0
        let mut aclass = self.aclass.id();
133
0
        if self.cache_flush {
134
0
            aclass |= 0b1000_0000;
135
0
        }
136
0
        aclass.write(message)?;
137
        // Write the ttl to the buffer.
138
0
        self.ttl.write(message)?;
139
0
        (self.rdata.byte_len()? as u16).write(message)?;
140
        // Write the type specific data to the buffer.
141
0
        self.rdata.write(message)?;
142
143
0
        Ok(())
144
0
    }
145
146
1.77k
    pub fn into_parsed(self) -> Result<DnsAnswer<'a, DnsAType<'a>>, DnsMessageError> {
147
1.77k
        Ok(DnsAnswer {
148
1.77k
            name: self.name,
149
1.77k
            rdata: self.rdata.into_parsed()?,
150
504
            cache_flush: self.cache_flush,
151
504
            aclass: self.aclass,
152
504
            ttl: self.ttl,
153
        })
154
1.77k
    }
155
}
156
157
impl<'a> DnsAnswer<'a, DnsAType<'a>> {
158
    fn write<
159
        const PTR_STORAGE: usize,
160
        const DNS_SECTION: DnsSection,
161
        B: Buffer,
162
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
163
        // Write the name to the buffer using the pointer storage for compression.
164
0
        self.name.write(message)?;
165
        // Write the atype and aclass to the buffer.
166
0
        self.rdata.id().write(message)?;
167
0
        let mut aclass = self.aclass.id();
168
0
        if self.cache_flush {
169
0
            aclass |= 0b1000_0000;
170
0
        }
171
0
        aclass.write(message)?;
172
        // Write the ttl to the buffer.
173
0
        self.ttl.write(message)?;
174
0
        let rdata_len = self.rdata.byte_len()? as u16;
175
0
        rdata_len.write(message)?;
176
        // Write the type specific data to the buffer.
177
0
        self.rdata.write(message)?;
178
179
0
        Ok(())
180
0
    }
181
}
182
183
0
#[derive(Copy, Clone, Debug, PartialEq)]
184
#[repr(u16)]
185
pub enum DnsAClass {
186
    IN = 1,
187
    CS = 2,
188
    CH = 3,
189
    HS = 4,
190
    Reserved,
191
}
192
193
impl DnsAClass {
194
    #[inline(always)]
195
2.75k
    pub fn from_id(id: u16) -> Self {
196
2.75k
        match id {
197
1.65k
            1..=4 => unsafe { core::mem::transmute(id) },
198
2.65k
            _ => DnsAClass::Reserved,
199
        }
200
2.75k
    }
201
202
    #[inline(always)]
203
    pub fn id(&self) -> u16 {
204
        match self {
205
            DnsAClass::Reserved => panic!("Reserved QClass"),
206
            _ => *self as u16,
207
        }
208
    }
209
}
210
211
impl From<DnsAClass> for u16 {
212
    #[inline(always)]
213
    fn from(q: DnsAClass) -> Self {
214
        DnsAClass::id(&q)
215
    }
216
}
217
218
impl From<u16> for DnsAClass {
219
    #[inline(always)]
220
    fn from(n: u16) -> Self {
221
        DnsAClass::from_id(n)
222
    }
223
}
/mnt/h/flex-dns/src/characters.rs
Line
Count
Source (jump to first uncovered line)
1
use core::fmt::Display;
2
use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, DnsSection};
3
use crate::parse::ParseBytes;
4
5
0
#[derive(Copy, Clone, Debug, PartialEq)]
6
pub struct Characters<'a> {
7
    bytes: &'a [u8],
8
}
9
10
const MAX_CHARACTER_STRING_LENGTH: usize = 255;
11
12
#[macro_export]
13
macro_rules! dns_characters {
14
    ($value:expr $(,)?) => {
15
        {
16
            const CHARACTERS: [u8; $value.len() + 1] = {
17
                let mut result = [0; $value.len() + 1];
18
                let mut index = 0;
19
                loop {
20
                    if index == $value.len() {
21
                        result[0] = index as u8;
22
23
                        break;
24
                    }
25
26
                    result[index + 1] = $value[index];
27
                    index += 1;
28
                }
29
30
                result
31
            };
32
            unsafe { flex_dns::characters::Characters::new_unchecked(&CHARACTERS) }
33
        }
34
    };
35
}
36
37
impl<'a> ParseBytes<'a> for Characters<'a> {
38
    #[inline]
39
770
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
40
770
        let length = u8::parse_bytes(bytes, i)? as usize;
41
42
726
        if length > MAX_CHARACTER_STRING_LENGTH {
43
0
            return Err(DnsMessageError::DnsError(DnsError::CharacterStringTooLong));
44
726
        }
45
726
46
726
        if *i + length > bytes.len() {
47
249
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
48
477
        }
49
477
50
477
        let bytes = &bytes[*i..*i + length];
51
477
        *i += length;
52
477
53
477
        Ok(Characters { bytes })
54
770
    }
55
}
56
57
impl<'a> Characters<'a> {
58
    #[inline]
59
8
    pub const fn new(bytes: &'a [u8]) -> Result<Self, DnsMessageError> {
60
8
        if bytes.len() > MAX_CHARACTER_STRING_LENGTH {
61
0
            return Err(DnsMessageError::DnsError(DnsError::CharacterStringTooLong));
62
8
        }
63
8
64
8
        Ok(Characters { bytes })
65
8
    }
66
67
    #[inline]
68
0
    pub const unsafe fn new_unchecked(bytes: &'a [u8]) -> Self {
69
0
        Characters { bytes }
70
0
    }
71
72
    #[inline]
73
    pub fn write<
74
        const PTR_STORAGE: usize,
75
        const DNS_SECTION: DnsSection,
76
        B: Buffer,
77
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
78
0
        message.write_bytes(&[self.bytes.len() as u8])?;
79
0
        message.write_bytes(self.bytes)?;
80
81
0
        Ok(())
82
0
    }
83
84
    #[inline(always)]
85
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
86
        Ok(1 + self.bytes.len())
87
    }
88
}
89
90
impl<'a> AsRef<[u8]> for Characters<'a> {
91
    #[inline]
92
0
    fn as_ref(&self) -> &[u8] {
93
0
        self.bytes
94
0
    }
95
}
96
97
impl<'a> From<&'a [u8]> for Characters<'a> {
98
    #[inline]
99
0
    fn from(bytes: &'a [u8]) -> Self {
100
0
        Characters { bytes }
101
0
    }
102
}
103
104
impl<'a> From<Characters<'a>> for &'a [u8] {
105
    #[inline]
106
0
    fn from(characters: Characters<'a>) -> Self {
107
0
        characters.bytes
108
0
    }
109
}
110
111
impl<'a> Display for Characters<'a> {
112
    #[inline]
113
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114
0
        for byte in self.bytes {
115
0
            write!(f, "\\x{:02x}", byte)?;
116
        }
117
118
0
        Ok(())
119
0
    }
120
}
/mnt/h/flex-dns/src/header.rs
Line
Count
Source (jump to first uncovered line)
1
/// A DNS header.
2
0
#[derive(Copy, Clone)]
3
#[repr(C)]
4
pub struct DnsHeader {
5
    id: [u8; 2],
6
    flags: [u8; 2],
7
    question_count: [u8; 2],
8
    answer_count: [u8; 2],
9
    name_server_count: [u8; 2],
10
    additional_records_count: [u8; 2],
11
}
12
13
impl DnsHeader {
14
    #[inline(always)]
15
    pub fn from_bytes_mut(bytes: &mut [u8]) -> &mut Self {
16
        unsafe { &mut *(bytes.as_mut_ptr() as *mut Self) }
17
    }
18
19
    #[inline(always)]
20
6.76k
    pub fn from_bytes(bytes: &[u8]) -> &Self {
21
6.76k
        unsafe { & *(bytes.as_ptr() as *const Self) }
22
6.76k
    }
23
24
    #[inline(always)]
25
1.12k
    pub fn id(&self) -> u16 {
26
1.12k
        u16::from_be_bytes(self.id)
27
1.12k
    }
28
29
    #[inline(always)]
30
1.12k
    pub fn kind(&self) -> DnsHeaderKind {
31
1.12k
        if (self.flags[0] & 0b10000000) == 0 {
32
883
            DnsHeaderKind::Query
33
        } else {
34
245
            DnsHeaderKind::Response
35
        }
36
1.12k
    }
37
38
    #[inline(always)]
39
1.12k
    pub fn opcode(&self) -> DnsHeaderOpcode {
40
1.12k
        (self.flags[0] & 0b01111000).into()
41
1.12k
    }
42
43
    #[inline(always)]
44
1.12k
    pub fn authoritative_answer(&self) -> bool {
45
1.12k
        (self.flags[0] & 0b00000100) != 0
46
1.12k
    }
47
48
    #[inline(always)]
49
1.12k
    pub fn truncated(&self) -> bool {
50
1.12k
        (self.flags[0] & 0b00000010) != 0
51
1.12k
    }
52
53
    #[inline(always)]
54
1.12k
    pub fn recursion_desired(&self) -> bool {
55
1.12k
        (self.flags[0] & 0b00000001) != 0
56
1.12k
    }
57
58
    #[inline(always)]
59
1.12k
    pub fn recursion_available(&self) -> bool {
60
1.12k
        (self.flags[1] & 0b10000000) != 0
61
1.12k
    }
62
63
    #[inline(always)]
64
1.12k
    pub fn response_code(&self) -> DnsHeaderResponseCode {
65
1.12k
        (self.flags[1] & 0b00001111).into()
66
1.12k
    }
67
68
    #[inline(always)]
69
1.12k
    pub fn question_count(&self) -> u16 {
70
1.12k
        u16::from_be_bytes(self.question_count)
71
1.12k
    }
72
73
    #[inline(always)]
74
3.38k
    pub fn answer_count(&self) -> u16 {
75
3.38k
        u16::from_be_bytes(self.answer_count)
76
3.38k
    }
77
78
    #[inline(always)]
79
0
    pub fn name_server_count(&self) -> u16 {
80
0
        u16::from_be_bytes(self.name_server_count)
81
0
    }
82
83
    #[inline(always)]
84
0
    pub fn additional_records_count(&self) -> u16 {
85
0
        u16::from_be_bytes(self.additional_records_count)
86
0
    }
87
88
    #[inline(always)]
89
    pub fn set_id(&mut self, id: u16) {
90
        self.id = id.to_be_bytes();
91
    }
92
93
    #[inline(always)]
94
    pub fn set_kind(&mut self, kind: DnsHeaderKind) {
95
        match kind {
96
            DnsHeaderKind::Query => self.flags[0] &= 0b01111111,
97
            DnsHeaderKind::Response => self.flags[0] |= 0b10000000,
98
        }
99
    }
100
101
    #[inline(always)]
102
    pub fn set_opcode(&mut self, opcode: DnsHeaderOpcode) {
103
        self.flags[0] &= 0b10000111;
104
        self.flags[0] |= (u8::from(opcode) & 0b0000_1111) << 3;
105
    }
106
107
    #[inline(always)]
108
    pub fn set_authoritative_answer(&mut self, authoritative_answer: bool) {
109
        if authoritative_answer {
110
            self.flags[0] |= 0b00000100;
111
        } else {
112
            self.flags[0] &= 0b11111011;
113
        }
114
    }
115
116
    #[inline(always)]
117
    pub fn set_truncated(&mut self, truncated: bool) {
118
        if truncated {
119
            self.flags[0] |= 0b00000010;
120
        } else {
121
            self.flags[0] &= 0b11111101;
122
        }
123
    }
124
125
    #[inline(always)]
126
    pub fn set_recursion_desired(&mut self, recursion_desired: bool) {
127
        if recursion_desired {
128
            self.flags[0] |= 0b00000001;
129
        } else {
130
            self.flags[0] &= 0b11111110;
131
        }
132
    }
133
134
    #[inline(always)]
135
    pub fn set_recursion_available(&mut self, recursion_available: bool) {
136
        if recursion_available {
137
            self.flags[1] |= 0b10000000;
138
        } else {
139
            self.flags[1] &= 0b01111111;
140
        }
141
    }
142
143
    #[inline(always)]
144
    pub fn set_response_code(&mut self, response_code: DnsHeaderResponseCode) {
145
        self.flags[1] &= 0b11110000;
146
        self.flags[1] |= u8::from(response_code) & 0b00001111;
147
    }
148
149
    #[inline(always)]
150
    pub(crate) fn set_question_count(&mut self, question_count: u16) {
151
        self.question_count = question_count.to_be_bytes();
152
    }
153
154
    #[inline(always)]
155
    pub(crate) fn set_answer_count(&mut self, answer_count: u16) {
156
        self.answer_count = answer_count.to_be_bytes();
157
    }
158
159
    #[inline(always)]
160
    pub(crate) fn set_name_server_count(&mut self, name_server_count: u16) {
161
        self.name_server_count = name_server_count.to_be_bytes();
162
    }
163
164
    #[inline(always)]
165
    pub(crate) fn set_additional_records_count(&mut self, additional_records_count: u16) {
166
        self.additional_records_count = additional_records_count.to_be_bytes();
167
    }
168
}
169
170
impl core::fmt::Debug for DnsHeader {
171
0
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
172
0
        f.debug_struct("Header")
173
0
            .field("id", &self.id())
174
0
            .field("kind", &self.kind())
175
0
            .field("opcode", &self.opcode())
176
0
            .field("authoritative_answer", &self.authoritative_answer())
177
0
            .field("truncated", &self.truncated())
178
0
            .field("recursion_desired", &self.recursion_desired())
179
0
            .field("recursion_available", &self.recursion_available())
180
0
            .field("response_code", &self.response_code())
181
0
            .field("question_count", &self.question_count())
182
0
            .field("answer_count", &self.answer_count())
183
0
            .field("name_server_count", &self.name_server_count())
184
0
            .field("additional_records_count", &self.additional_records_count())
185
0
            .finish()
186
0
    }
187
}
188
189
/// The kind of a DNS header.
190
0
#[derive(Copy, Clone, Debug, PartialEq)]
191
pub enum DnsHeaderKind {
192
    Query,
193
    Response,
194
}
195
196
/// A DNS opcode.
197
0
#[derive(Copy, Clone, Debug, PartialEq)]
198
pub enum DnsHeaderOpcode {
199
    Query,
200
    InverseQuery,
201
    Status,
202
    Notify,
203
    Update,
204
    Reserved(u8),
205
}
206
207
impl From<u8> for DnsHeaderOpcode {
208
1.12k
    fn from(value: u8) -> Self {
209
1.12k
        match value {
210
535
            0 => DnsHeaderOpcode::Query,
211
0
            1 => DnsHeaderOpcode::InverseQuery,
212
0
            2 => DnsHeaderOpcode::Status,
213
0
            4 => DnsHeaderOpcode::Notify,
214
0
            5 => DnsHeaderOpcode::Update,
215
593
            _ => DnsHeaderOpcode::Reserved(value),
216
        }
217
1.12k
    }
218
}
219
220
impl From<DnsHeaderOpcode> for u8 {
221
0
    fn from(value: DnsHeaderOpcode) -> Self {
222
0
        match value {
223
0
            DnsHeaderOpcode::Query => 0,
224
0
            DnsHeaderOpcode::InverseQuery => 1,
225
0
            DnsHeaderOpcode::Status => 2,
226
0
            DnsHeaderOpcode::Notify => 4,
227
0
            DnsHeaderOpcode::Update => 5,
228
0
            DnsHeaderOpcode::Reserved(value) => value,
229
        }
230
0
    }
231
}
232
233
/// A DNS response code.
234
0
#[derive(Copy, Clone, Debug, PartialEq)]
235
pub enum DnsHeaderResponseCode {
236
    NoError,
237
    FormatError,
238
    ServerFailure,
239
    NonExistentDomain,
240
    NotImplemented,
241
    Refused,
242
    ExistentDomain,
243
    ExistentRrSet,
244
    NonExistentRrSet,
245
    NotAuthoritative,
246
    NotZone,
247
    BadOptVersionOrBadSignature,
248
    BadKey,
249
    BadTime,
250
    BadMode,
251
    BadName,
252
    BadAlg,
253
    Reserved(u8),
254
}
255
256
impl From<DnsHeaderResponseCode> for u8 {
257
0
    fn from(r: DnsHeaderResponseCode) -> Self {
258
0
        match r {
259
0
            DnsHeaderResponseCode::NoError => 0,
260
0
            DnsHeaderResponseCode::FormatError => 1,
261
0
            DnsHeaderResponseCode::ServerFailure => 2,
262
0
            DnsHeaderResponseCode::NonExistentDomain => 3,
263
0
            DnsHeaderResponseCode::NotImplemented => 4,
264
0
            DnsHeaderResponseCode::Refused => 5,
265
0
            DnsHeaderResponseCode::ExistentDomain => 6,
266
0
            DnsHeaderResponseCode::ExistentRrSet => 7,
267
0
            DnsHeaderResponseCode::NonExistentRrSet => 8,
268
0
            DnsHeaderResponseCode::NotAuthoritative => 9,
269
0
            DnsHeaderResponseCode::NotZone => 10,
270
0
            DnsHeaderResponseCode::BadOptVersionOrBadSignature => 16,
271
0
            DnsHeaderResponseCode::BadKey => 17,
272
0
            DnsHeaderResponseCode::BadTime => 18,
273
0
            DnsHeaderResponseCode::BadMode => 19,
274
0
            DnsHeaderResponseCode::BadName => 20,
275
0
            DnsHeaderResponseCode::BadAlg => 21,
276
0
            DnsHeaderResponseCode::Reserved(n) => n,
277
        }
278
0
    }
279
}
280
281
impl From<u8> for DnsHeaderResponseCode {
282
1.12k
    fn from(n: u8) -> Self {
283
1.12k
        match n {
284
643
            0 => DnsHeaderResponseCode::NoError,
285
89
            1 => DnsHeaderResponseCode::FormatError,
286
16
            2 => DnsHeaderResponseCode::ServerFailure,
287
16
            3 => DnsHeaderResponseCode::NonExistentDomain,
288
20
            4 => DnsHeaderResponseCode::NotImplemented,
289
16
            5 => DnsHeaderResponseCode::Refused,
290
1
            6 => DnsHeaderResponseCode::ExistentDomain,
291
16
            7 => DnsHeaderResponseCode::ExistentRrSet,
292
5
            8 => DnsHeaderResponseCode::NonExistentRrSet,
293
8
            9 => DnsHeaderResponseCode::NotAuthoritative,
294
40
            10 => DnsHeaderResponseCode::NotZone,
295
0
            16 => DnsHeaderResponseCode::BadOptVersionOrBadSignature,
296
0
            17 => DnsHeaderResponseCode::BadKey,
297
0
            18 => DnsHeaderResponseCode::BadTime,
298
0
            19 => DnsHeaderResponseCode::BadMode,
299
0
            20 => DnsHeaderResponseCode::BadName,
300
0
            21 => DnsHeaderResponseCode::BadAlg,
301
258
            n => DnsHeaderResponseCode::Reserved(n),
302
        }
303
1.12k
    }
304
}
/mnt/h/flex-dns/src/lib.rs
Line
Count
Source (jump to first uncovered line)
1
#![feature(ip_in_core)]
2
#![feature(adt_const_params)]
3
#![feature(generic_const_exprs)]
4
#![no_std]
5
6
extern crate alloc;
7
8
use arrayvec::ArrayVec;
9
use core::marker::ConstParamTy;
10
use crate::additional::DnsAdditionals;
11
use crate::answer::DnsAnswers;
12
13
use crate::header::DnsHeader;
14
use crate::name::DnsName;
15
use crate::name_servers::DnsNameServers;
16
use crate::parse::Parse;
17
use crate::question::DnsQuestions;
18
19
pub mod header;
20
pub mod name;
21
pub mod characters;
22
pub mod question;
23
pub mod name_servers;
24
pub mod additional;
25
pub mod answer;
26
pub mod rdata;
27
mod parse;
28
mod write;
29
30
0
#[derive(Debug, PartialEq)]
31
pub enum DnsMessageError {
32
    DnsError(DnsError),
33
    BufferError(BufferError),
34
}
35
36
impl From<DnsError> for DnsMessageError {
37
0
    fn from(e: DnsError) -> Self {
38
0
        DnsMessageError::DnsError(e)
39
0
    }
40
}
41
42
impl From<BufferError> for DnsMessageError {
43
0
    fn from(e: BufferError) -> Self {
44
0
        DnsMessageError::BufferError(e)
45
0
    }
46
}
47
48
0
#[derive(Debug, PartialEq)]
49
pub enum DnsError {
50
    MessageTooShort,
51
    InvalidHeader,
52
    InvalidQuestion,
53
    InvalidAnswer,
54
    InvalidAuthority,
55
    InvalidAdditional,
56
    PointerIntoTheFuture,
57
    PointerCycle,
58
    NameTooLong,
59
    LabelTooLong,
60
    CharacterStringTooLong,
61
    RDataLongerThanMessage,
62
    UnexpectedEndOfBuffer,
63
    InvalidTxtRecord,
64
}
65
66
0
#[derive(Debug, PartialEq)]
67
pub enum BufferError {
68
    OutOfMemory,
69
    LengthOutOfBounds,
70
    InvalidLength,
71
    OffsetOutOfBounds,
72
}
73
74
pub trait Buffer {
75
    fn len(&self) -> usize;
76
    fn truncate(&mut self, new_len: usize) -> Result<(), BufferError>;
77
    fn write_bytes_at(&mut self, offset: usize, data: &[u8]) -> Result<(), BufferError>;
78
    fn write_array_at<const BYTES: usize>(&mut self, offset: usize, data: [u8; BYTES]) -> Result<(), BufferError>;
79
    fn write_at(&mut self, offset: usize, data: u8) -> Result<(), BufferError>;
80
    fn write_bytes(&mut self, data: &[u8]) -> Result<(), BufferError>;
81
    fn write_array<const BYTES: usize>(&mut self, data: [u8; BYTES]) -> Result<(), BufferError>;
82
    fn write(&mut self, data: u8) -> Result<(), BufferError>;
83
84
    fn read_bytes_at(&self, offset: usize, length: usize) -> Result<&[u8], BufferError>;
85
    fn read_bytes_at_mut(&mut self, offset: usize, length: usize) -> Result<&mut [u8], BufferError>;
86
    fn read_at(&self, offset: usize) -> Result<u8, BufferError>;
87
    fn bytes(&self) -> &[u8];
88
}
89
90
#[inline(always)]
91
37
fn check_length<const SIZE: usize>(offset: usize, length: usize) -> Result<(), BufferError> {
92
37
    if offset + length > SIZE {
93
0
        if offset > SIZE {
94
0
            return Err(BufferError::OffsetOutOfBounds);
95
0
        }
96
0
        return Err(BufferError::LengthOutOfBounds);
97
37
    }
98
37
99
37
    Ok(())
100
37
}
_RINvCslLTLXfmDngu_8flex_dns12check_lengthKj1000_ECsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
91
37
fn check_length<const SIZE: usize>(offset: usize, length: usize) -> Result<(), BufferError> {
92
37
    if offset + length > SIZE {
93
0
        if offset > SIZE {
94
0
            return Err(BufferError::OffsetOutOfBounds);
95
0
        }
96
0
        return Err(BufferError::LengthOutOfBounds);
97
37
    }
98
37
99
37
    Ok(())
100
37
}
Unexecuted instantiation: _RINvCslLTLXfmDngu_8flex_dns12check_lengthKpEB2_
101
102
impl<const SIZE: usize> Buffer for ArrayVec<u8, SIZE> {
103
    #[inline(always)]
104
7.89k
    fn len(&self) -> usize {
105
7.89k
        ArrayVec::len(self)
106
7.89k
    }
_RNvXs0_CslLTLXfmDngu_8flex_dnsINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtB5_6Buffer3lenCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
104
7.89k
    fn len(&self) -> usize {
105
7.89k
        ArrayVec::len(self)
106
7.89k
    }
Unexecuted instantiation: _RNvXINICslLTLXfmDngu_8flex_dnss0_0KpEINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKpENtB5_6Buffer3lenB5_
107
108
    #[inline(always)]
109
0
    fn truncate(&mut self, new_len: usize) -> Result<(), BufferError> {
110
0
        if new_len > self.len() {
111
0
            return Err(BufferError::InvalidLength);
112
0
        }
113
0
114
0
        ArrayVec::truncate(self, new_len);
115
0
        Ok(())
116
0
    }
117
118
    #[inline]
119
    fn write_bytes_at(&mut self, offset: usize, data: &[u8]) -> Result<(), BufferError> {
120
0
        check_length::<SIZE>(offset, data.len())?;
121
        // Grow the buffer to the required size
122
0
        unsafe { self.set_len(core::cmp::max(self.len(), offset + data.len())); };
123
0
        // Copy the data into the buffer
124
0
        self.as_mut_slice()[offset..offset + data.len()].copy_from_slice(data);
125
0
126
0
        Ok(())
127
0
    }
128
129
    #[inline]
130
    fn write_array_at<const BYTES: usize>(&mut self, offset: usize, data: [u8; BYTES]) -> Result<(), BufferError> {
131
0
        check_length::<SIZE>(offset, BYTES)?;
132
        // Grow the buffer to the required size
133
0
        unsafe { self.set_len(core::cmp::max(self.len(), offset + BYTES)); };
134
0
        self.as_mut_slice()[offset..offset + BYTES].copy_from_slice(&data);
135
0
136
0
        Ok(())
137
0
    }
138
139
    #[inline]
140
    fn write_at(&mut self, offset: usize, data: u8) -> Result<(), BufferError> {
141
0
        check_length::<SIZE>(offset, 1)?;
142
        // Grow the buffer to the required size
143
0
        unsafe { self.set_len(core::cmp::max(self.len(), offset + 1)); };
144
0
        self.as_mut_slice()[offset] = data;
145
0
146
0
        Ok(())
147
0
    }
148
149
    #[inline]
150
    fn write_bytes(&mut self, data: &[u8]) -> Result<(), BufferError> {
151
37
        check_length::<SIZE>(self.len(), data.len())?;
152
37
        self.try_extend_from_slice(data).map_err(|_| BufferError::OutOfMemory)?;
Unexecuted instantiation: _RNCNvXs0_CslLTLXfmDngu_8flex_dnsINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtB7_6Buffer11write_bytes0Csgg978DXfVXR_13fuzz_target_1
Unexecuted instantiation: _RNCNvXINICslLTLXfmDngu_8flex_dnss0_0KpEINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKpENtB7_6Buffer11write_bytes0B7_
153
154
37
        Ok(())
155
37
    }
_RNvXs0_CslLTLXfmDngu_8flex_dnsINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtB5_6Buffer11write_bytesCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
151
37
        check_length::<SIZE>(self.len(), data.len())?;
152
37
        self.try_extend_from_slice(data).map_err(|_| BufferError::OutOfMemory)?;
153
154
37
        Ok(())
155
37
    }
Unexecuted instantiation: _RNvXINICslLTLXfmDngu_8flex_dnss0_0KpEINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKpENtB5_6Buffer11write_bytesB5_
156
157
    #[inline]
158
    fn write_array<const BYTES: usize>(&mut self, data: [u8; BYTES]) -> Result<(), BufferError> {
159
0
        check_length::<SIZE>(self.len(), BYTES)?;
160
0
        self.try_extend_from_slice(&data).map_err(|_| BufferError::OutOfMemory)?;
161
162
0
        Ok(())
163
0
    }
164
165
    #[inline]
166
    fn write(&mut self, data: u8) -> Result<(), BufferError> {
167
0
        check_length::<SIZE>(self.len(), 1)?;
168
0
        self.push(data);
169
0
170
0
        Ok(())
171
0
    }
172
173
    #[inline]
174
6.76k
    fn read_bytes_at(&self, offset: usize, length: usize) -> Result<&[u8], BufferError> {
175
6.76k
        if offset + length > self.len() {
176
0
            if offset > self.len() {
177
0
                return Err(BufferError::OffsetOutOfBounds);
178
0
            }
179
0
            return Err(BufferError::LengthOutOfBounds);
180
6.76k
        }
181
6.76k
182
6.76k
        Ok(&self.as_slice()[offset..offset + length])
183
6.76k
    }
_RNvXs0_CslLTLXfmDngu_8flex_dnsINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtB5_6Buffer13read_bytes_atCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
174
6.76k
    fn read_bytes_at(&self, offset: usize, length: usize) -> Result<&[u8], BufferError> {
175
6.76k
        if offset + length > self.len() {
176
0
            if offset > self.len() {
177
0
                return Err(BufferError::OffsetOutOfBounds);
178
0
            }
179
0
            return Err(BufferError::LengthOutOfBounds);
180
6.76k
        }
181
6.76k
182
6.76k
        Ok(&self.as_slice()[offset..offset + length])
183
6.76k
    }
Unexecuted instantiation: _RNvXINICslLTLXfmDngu_8flex_dnss0_0KpEINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKpENtB5_6Buffer13read_bytes_atB5_
184
185
    #[inline]
186
    fn read_bytes_at_mut(&mut self, offset: usize, length: usize) -> Result<&mut [u8], BufferError> {
187
0
        check_length::<SIZE>(offset, length)?;
188
0
        unsafe { self.set_len(core::cmp::max(self.len(), offset + length)); };
189
0
        Ok(&mut self.as_mut_slice()[offset..offset + length])
190
0
    }
191
192
    #[inline]
193
0
    fn read_at(&self, offset: usize) -> Result<u8, BufferError> {
194
0
        if offset + 1 > self.len() {
195
0
            if offset > self.len() {
196
0
                return Err(BufferError::OffsetOutOfBounds);
197
0
            }
198
0
            return Err(BufferError::LengthOutOfBounds);
199
0
        }
200
0
201
0
        Ok(self.as_slice()[offset])
202
0
    }
203
204
    #[inline]
205
4.51k
    fn bytes(&self) -> &[u8] {
206
4.51k
        self.as_slice()
207
4.51k
    }
_RNvXs0_CslLTLXfmDngu_8flex_dnsINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_ENtB5_6Buffer5bytesCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
205
4.51k
    fn bytes(&self) -> &[u8] {
206
4.51k
        self.as_slice()
207
4.51k
    }
Unexecuted instantiation: _RNvXINICslLTLXfmDngu_8flex_dnss0_0KpEINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKpENtB5_6Buffer5bytesB5_
208
}
209
210
#[cfg(feature = "alloc")]
211
mod vec {
212
    extern crate alloc;
213
214
    use crate::{Buffer, BufferError};
215
216
    impl Buffer for alloc::vec::Vec<u8> {
217
        #[inline]
218
        fn len(&self) -> usize {
219
            <alloc::vec::Vec<u8>>::len(self)
220
        }
221
222
        #[inline]
223
        fn truncate(&mut self, new_len: usize) -> Result<(), BufferError> {
224
            if new_len > self.len() {
225
                return Err(BufferError::InvalidLength);
226
            }
227
228
            <alloc::vec::Vec<u8>>::truncate(self, new_len);
229
            Ok(())
230
        }
231
232
        #[inline]
233
        fn write_bytes_at(&mut self, offset: usize, data: &[u8]) -> Result<(), BufferError> {
234
            if offset + data.len() > self.len() {
235
                if offset > self.len() {
236
                    return Err(BufferError::OffsetOutOfBounds);
237
                }
238
                return Err(BufferError::LengthOutOfBounds);
239
            }
240
241
            self.as_mut_slice()[offset..offset + data.len()].copy_from_slice(data);
242
243
            Ok(())
244
        }
245
246
        #[inline]
247
        fn write_array_at<const BYTES: usize>(&mut self, offset: usize, data: [u8; BYTES]) -> Result<(), BufferError> {
248
            if offset + BYTES > self.len() {
249
                if offset > self.len() {
250
                    return Err(BufferError::OffsetOutOfBounds);
251
                }
252
                return Err(BufferError::LengthOutOfBounds);
253
            }
254
255
            self.as_mut_slice()[offset..offset + BYTES].copy_from_slice(&data);
256
257
            Ok(())
258
        }
259
260
        #[inline]
261
        fn write_at(&mut self, offset: usize, data: u8) -> Result<(), BufferError> {
262
            if offset + 1 > self.len() {
263
                if offset > self.len() {
264
                    return Err(BufferError::OffsetOutOfBounds);
265
                }
266
                return Err(BufferError::LengthOutOfBounds);
267
            }
268
269
            self.as_mut_slice()[offset] = data;
270
271
            Ok(())
272
        }
273
274
        #[inline]
275
        fn write_bytes(&mut self, data: &[u8]) -> Result<(), BufferError> {
276
            self.extend_from_slice(data);
277
            Ok(())
278
        }
279
280
        #[inline]
281
        fn write_array<const BYTES: usize>(&mut self, data: [u8; BYTES]) -> Result<(), BufferError> {
282
            self.extend_from_slice(&data);
283
            Ok(())
284
        }
285
286
        fn write(&mut self, data: u8) -> Result<(), BufferError> {
287
            self.push(data);
288
            Ok(())
289
        }
290
291
        #[inline]
292
        fn read_bytes_at(&self, offset: usize, length: usize) -> Result<&[u8], BufferError> {
293
            if offset + length > self.len() {
294
                if offset > self.len() {
295
                    return Err(BufferError::OffsetOutOfBounds);
296
                }
297
                return Err(BufferError::LengthOutOfBounds);
298
            }
299
300
            Ok(&self.as_slice()[offset..offset + length])
301
        }
302
303
        #[inline]
304
        fn read_bytes_at_mut(&mut self, offset: usize, length: usize) -> Result<&mut [u8], BufferError> {
305
            if offset + length > self.len() {
306
                if offset > self.len() {
307
                    return Err(BufferError::OffsetOutOfBounds);
308
                }
309
                return Err(BufferError::LengthOutOfBounds);
310
            }
311
312
            Ok(&mut self.as_mut_slice()[offset..offset + length])
313
        }
314
315
        #[inline]
316
        fn read_at(&self, offset: usize) -> Result<u8, BufferError> {
317
            if offset + 1 > self.len() {
318
                if offset > self.len() {
319
                    return Err(BufferError::OffsetOutOfBounds);
320
                }
321
                return Err(BufferError::LengthOutOfBounds);
322
            }
323
324
            Ok(self.as_slice()[offset])
325
        }
326
327
        #[inline]
328
        fn bytes(&self) -> &[u8] {
329
            self.as_slice()
330
        }
331
    }
332
}
333
334
335
const DNS_HEADER_SIZE: usize = 12;
336
337
0
#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, ConstParamTy)]
338
pub enum DnsSection {
339
    Questions,
340
    Answers,
341
    NameServers,
342
    Additionals,
343
}
344
345
pub struct DnsMessage<
346
    const PTR_STORAGE: usize,
347
    const DNS_SECTION: DnsSection,
348
    B: Buffer,
349
> {
350
    buffer: B,
351
    position: usize,
352
    // Pointers are stored as offsets from the start of the buffer
353
    // We dont need this for reading, but we need it for writing compressed pointers
354
    ptr_storage: ArrayVec<usize, PTR_STORAGE>,
355
}
356
357
macro_rules! to_section_impl {
358
    ($from:expr, $to:expr) => {
359
        impl<
360
            const PTR_STORAGE: usize,
361
            B: Buffer,
362
        > DnsMessage<PTR_STORAGE, { $from }, B> {
363
            #[inline]
364
0
            pub fn next_section(self) -> DnsMessage<PTR_STORAGE, { $to }, B> {
365
0
                DnsMessage {
366
0
                    buffer: self.buffer,
367
0
                    position: self.position,
368
0
                    ptr_storage: self.ptr_storage,
369
0
                }
370
0
            }
Unexecuted instantiation: _RNvMsn_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection9QuestionsUpE12next_sectionB5_
Unexecuted instantiation: _RNvMsp_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection11NameServersUpE12next_sectionB5_
Unexecuted instantiation: _RNvMso_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection7AnswersUpE12next_sectionB5_
371
        }
372
    };
373
}
374
375
to_section_impl!(DnsSection::Questions, DnsSection::Answers);
376
to_section_impl!(DnsSection::Answers, DnsSection::NameServers);
377
to_section_impl!(DnsSection::NameServers, DnsSection::Additionals);
378
379
impl<
380
    const PTR_STORAGE: usize,
381
    const SECTION: DnsSection,
382
    B: Buffer,
383
> DnsMessage<PTR_STORAGE, SECTION, B> {
384
    #[inline]
385
1.12k
    pub fn new(mut buffer: B) -> Result<Self, DnsMessageError> {
386
1.12k
        if buffer.len() < DNS_HEADER_SIZE {
387
37
            buffer.write_bytes(&[0; DNS_HEADER_SIZE])?;
388
1.09k
        }
389
390
1.12k
        Ok(Self {
391
1.12k
            buffer,
392
1.12k
            position: DNS_HEADER_SIZE,
393
1.12k
            ptr_storage: ArrayVec::new(),
394
1.12k
        })
395
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection9QuestionsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
385
1.12k
    pub fn new(mut buffer: B) -> Result<Self, DnsMessageError> {
386
1.12k
        if buffer.len() < DNS_HEADER_SIZE {
387
37
            buffer.write_bytes(&[0; DNS_HEADER_SIZE])?;
388
1.09k
        }
389
390
1.12k
        Ok(Self {
391
1.12k
            buffer,
392
1.12k
            position: DNS_HEADER_SIZE,
393
1.12k
            ptr_storage: ArrayVec::new(),
394
1.12k
        })
395
1.12k
    }
Unexecuted instantiation: _RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKppE3newB5_
396
397
    #[inline(always)]
398
4.51k
    pub(crate) fn buffer_and_position(&mut self) -> (&mut B, &mut usize) {
399
4.51k
        (&mut self.buffer, &mut self.position)
400
4.51k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection9QuestionsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE19buffer_and_positionCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
398
1.12k
    pub(crate) fn buffer_and_position(&mut self) -> (&mut B, &mut usize) {
399
1.12k
        (&mut self.buffer, &mut self.position)
400
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection11AdditionalsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE19buffer_and_positionCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
398
1.12k
    pub(crate) fn buffer_and_position(&mut self) -> (&mut B, &mut usize) {
399
1.12k
        (&mut self.buffer, &mut self.position)
400
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection7AnswersUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE19buffer_and_positionCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
398
1.12k
    pub(crate) fn buffer_and_position(&mut self) -> (&mut B, &mut usize) {
399
1.12k
        (&mut self.buffer, &mut self.position)
400
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection11NameServersUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE19buffer_and_positionCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
398
1.12k
    pub(crate) fn buffer_and_position(&mut self) -> (&mut B, &mut usize) {
399
1.12k
        (&mut self.buffer, &mut self.position)
400
1.12k
    }
Unexecuted instantiation: _RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKppE19buffer_and_positionB5_
401
402
    #[inline(always)]
403
0
    pub fn reset(self) -> DnsMessage<PTR_STORAGE, { DnsSection::Questions }, B> {
404
0
        DnsMessage {
405
0
            buffer: self.buffer,
406
0
            position: 0,
407
0
            ptr_storage: self.ptr_storage,
408
0
        }
409
0
    }
410
411
    #[inline(always)]
412
0
    pub fn complete(self) -> Result<B, DnsMessageError> {
413
0
        Ok(self.buffer)
414
0
    }
415
416
    #[inline]
417
0
    pub fn header_mut(&mut self) -> Result<&mut DnsHeader, DnsMessageError> {
418
0
        self.position = core::cmp::max(self.position, DNS_HEADER_SIZE);
419
0
        Ok(DnsHeader::from_bytes_mut(
420
0
            self.buffer.read_bytes_at_mut(0, DNS_HEADER_SIZE)?
421
        ))
422
0
    }
423
424
    #[inline]
425
6.76k
    pub fn header(&self) -> Result<&DnsHeader, DnsMessageError> {
426
6.76k
        if self.buffer.len() < DNS_HEADER_SIZE {
427
0
            return Err(DnsMessageError::DnsError(DnsError::MessageTooShort));
428
6.76k
        }
429
6.76k
430
6.76k
        Ok(DnsHeader::from_bytes(
431
6.76k
            self.buffer.read_bytes_at(0, DNS_HEADER_SIZE)?
432
        ))
433
6.76k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection11AdditionalsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE6headerCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
425
1.12k
    pub fn header(&self) -> Result<&DnsHeader, DnsMessageError> {
426
1.12k
        if self.buffer.len() < DNS_HEADER_SIZE {
427
0
            return Err(DnsMessageError::DnsError(DnsError::MessageTooShort));
428
1.12k
        }
429
1.12k
430
1.12k
        Ok(DnsHeader::from_bytes(
431
1.12k
            self.buffer.read_bytes_at(0, DNS_HEADER_SIZE)?
432
        ))
433
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection7AnswersUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE6headerCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
425
1.12k
    pub fn header(&self) -> Result<&DnsHeader, DnsMessageError> {
426
1.12k
        if self.buffer.len() < DNS_HEADER_SIZE {
427
0
            return Err(DnsMessageError::DnsError(DnsError::MessageTooShort));
428
1.12k
        }
429
1.12k
430
1.12k
        Ok(DnsHeader::from_bytes(
431
1.12k
            self.buffer.read_bytes_at(0, DNS_HEADER_SIZE)?
432
        ))
433
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection11NameServersUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE6headerCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
425
1.12k
    pub fn header(&self) -> Result<&DnsHeader, DnsMessageError> {
426
1.12k
        if self.buffer.len() < DNS_HEADER_SIZE {
427
0
            return Err(DnsMessageError::DnsError(DnsError::MessageTooShort));
428
1.12k
        }
429
1.12k
430
1.12k
        Ok(DnsHeader::from_bytes(
431
1.12k
            self.buffer.read_bytes_at(0, DNS_HEADER_SIZE)?
432
        ))
433
1.12k
    }
_RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection9QuestionsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE6headerCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
425
3.38k
    pub fn header(&self) -> Result<&DnsHeader, DnsMessageError> {
426
3.38k
        if self.buffer.len() < DNS_HEADER_SIZE {
427
0
            return Err(DnsMessageError::DnsError(DnsError::MessageTooShort));
428
3.38k
        }
429
3.38k
430
3.38k
        Ok(DnsHeader::from_bytes(
431
3.38k
            self.buffer.read_bytes_at(0, DNS_HEADER_SIZE)?
432
        ))
433
3.38k
    }
Unexecuted instantiation: _RNvMs1_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKppE6headerB5_
434
435
    #[inline(always)]
436
0
    pub(crate) fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), DnsMessageError> {
437
0
        self.position += bytes.len();
438
0
439
0
        Ok(self.buffer.write_bytes(bytes)?)
440
0
    }
441
442
0
    pub(crate) fn write_name(
443
0
        &mut self,
444
0
        name: DnsName,
445
0
    ) -> Result<(), DnsMessageError> {
446
        // Try to find match
447
0
        for idx in self.ptr_storage.iter().copied() {
448
0
            let mut i = idx;
449
0
            let name_at_idx = DnsName::parse(self.buffer.bytes(), &mut i)?;
450
0
            if name_at_idx == name {
451
0
                self.write_bytes(&(idx as u16 | 0b1100_0000_0000_0000).to_be_bytes())?;
452
0
                return Ok(());
453
0
            }
454
        }
455
456
        // No match found, write name
457
0
        let (first, rest) = name.split_first()?;
458
0
        let original_position = self.position;
459
0
        self.write_bytes(&[first.len() as u8])?;
460
0
        self.write_bytes(first)?;
461
462
0
        if let Some(rest) = rest {
463
0
            self.write_name(rest)?;
464
        } else {
465
0
            self.write_bytes(&[0])?; // Null terminator
466
        }
467
0
        if self.ptr_storage.len() < PTR_STORAGE {
468
0
            // Store pointer for later, if we have space
469
0
            // If we dont have space, we just write the name uncompressed
470
0
            // in the future
471
0
            self.ptr_storage.push(original_position);
472
0
        }
473
474
0
        Ok(())
475
0
    }
476
}
477
478
impl<
479
    const PTR_STORAGE: usize,
480
    B: Buffer,
481
> DnsMessage<PTR_STORAGE, { DnsSection::Questions }, B> {
482
    #[inline(always)]
483
1.12k
    pub fn questions(self) -> DnsQuestions<PTR_STORAGE, B> {
484
1.12k
        DnsQuestions::new(self)
485
1.12k
    }
_RNvMs2_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection9QuestionsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE9questionsCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
483
1.12k
    pub fn questions(self) -> DnsQuestions<PTR_STORAGE, B> {
484
1.12k
        DnsQuestions::new(self)
485
1.12k
    }
Unexecuted instantiation: _RNvMs2_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection9QuestionsUpE9questionsB5_
486
}
487
488
impl<
489
    const PTR_STORAGE: usize,
490
    B: Buffer,
491
> DnsMessage<PTR_STORAGE, { DnsSection::Answers }, B> {
492
1.12k
    pub fn answers(self) -> DnsAnswers<PTR_STORAGE, B> {
493
1.12k
        DnsAnswers::new(self)
494
1.12k
    }
_RNvMs3_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection7AnswersUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE7answersCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
492
1.12k
    pub fn answers(self) -> DnsAnswers<PTR_STORAGE, B> {
493
1.12k
        DnsAnswers::new(self)
494
1.12k
    }
Unexecuted instantiation: _RNvMs3_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection7AnswersUpE7answersB5_
495
}
496
497
impl<
498
    const PTR_STORAGE: usize,
499
    B: Buffer,
500
> DnsMessage<PTR_STORAGE, { DnsSection::NameServers }, B> {
501
1.12k
    pub fn name_servers(self) -> DnsNameServers<PTR_STORAGE, B> {
502
1.12k
        DnsNameServers::new(self)
503
1.12k
    }
_RNvMs4_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection11NameServersUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE12name_serversCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
501
1.12k
    pub fn name_servers(self) -> DnsNameServers<PTR_STORAGE, B> {
502
1.12k
        DnsNameServers::new(self)
503
1.12k
    }
Unexecuted instantiation: _RNvMs4_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection11NameServersUpE12name_serversB5_
504
}
505
506
impl<
507
    const PTR_STORAGE: usize,
508
    B: Buffer,
509
> DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B> {
510
1.12k
    pub fn additionals(self) -> DnsAdditionals<PTR_STORAGE, B> {
511
1.12k
        DnsAdditionals::new(self)
512
1.12k
    }
_RNvMs5_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKj10_KVNtNtB5_10DnsSection11AdditionalsUINtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE11additionalsCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
510
1.12k
    pub fn additionals(self) -> DnsAdditionals<PTR_STORAGE, B> {
511
1.12k
        DnsAdditionals::new(self)
512
1.12k
    }
Unexecuted instantiation: _RNvMs5_CslLTLXfmDngu_8flex_dnsINtB5_10DnsMessageKpKVNtNtB5_10DnsSection11AdditionalsUpE11additionalsB5_
513
}
514
515
#[cfg(test)]
516
mod test {
517
    use super::*;
518
519
    mod question {
520
        use crate::header::{DnsHeaderOpcode, DnsHeaderResponseCode};
521
        use crate::question::{DnsQClass, DnsQType, DnsQuestion};
522
        use super::*;
523
524
        #[test]
525
        fn test_question() {
526
            let buffer: ArrayVec<u8, 512> = ArrayVec::new();
527
            let mut message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
528
            message.header_mut().unwrap().set_id(0x1234);
529
            message.header_mut().unwrap().set_opcode(DnsHeaderOpcode::Query);
530
            message.header_mut().unwrap().set_authoritative_answer(false);
531
            message.header_mut().unwrap().set_truncated(false);
532
            message.header_mut().unwrap().set_recursion_desired(false);
533
            message.header_mut().unwrap().set_recursion_available(false);
534
            message.header_mut().unwrap().set_response_code(DnsHeaderResponseCode::NoError);
535
            let mut questions = message.questions();
536
            questions.append(DnsQuestion {
537
                name: DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap(),
538
                qtype: DnsQType::A,
539
                qclass: DnsQClass::IN,
540
            }).unwrap();
541
            let message = questions.complete().unwrap();
542
            let buffer = message.complete().unwrap();
543
544
            assert_eq!(buffer.as_slice(), [
545
                0x12, 0x34, // ID
546
                0b0000_0000, 0b0000_0000, // Flags
547
                0x00, 0x01, // Question count
548
                0x00, 0x00, // Answer count
549
                0x00, 0x00, // Authority count
550
                0x00, 0x00, // Additional count
551
                0x03, b'w', b'w', b'w', // Name
552
                0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e', // Name
553
                0x03, b'c', b'o', b'm', // Name
554
                0x00, // Name
555
                0x00, 0x01, // Type
556
                0x00, 0x01, // Class
557
            ].as_slice());
558
559
            // Decode
560
            let message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
561
            assert_eq!(message.header().unwrap().id(), 0x1234);
562
            assert_eq!(message.header().unwrap().opcode(), DnsHeaderOpcode::Query);
563
            assert_eq!(message.header().unwrap().authoritative_answer(), false);
564
            assert_eq!(message.header().unwrap().truncated(), false);
565
            assert_eq!(message.header().unwrap().recursion_desired(), false);
566
            assert_eq!(message.header().unwrap().recursion_available(), false);
567
            assert_eq!(message.header().unwrap().response_code(), DnsHeaderResponseCode::NoError);
568
            let mut questions = message.questions();
569
            let mut question_iter = questions.iter().unwrap();
570
            let question = question_iter.next().unwrap().unwrap();
571
            assert_eq!(question.name, DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap());
572
            assert_eq!(question.qtype, DnsQType::A);
573
            assert_eq!(question.qclass, DnsQClass::IN);
574
            assert!(question_iter.next().is_none());
575
        }
576
577
        #[test]
578
        fn query_google_com() {
579
            let buffer = ArrayVec::from([
580
                0x00, 0x03, // ID
581
                0x01, 0x00, // Flags
582
                0x00, 0x01, // Question count
583
                0x00, 0x00, // Answer count
584
                0x00, 0x00, // Authority count
585
                0x00, 0x00, // Additional count
586
                0x06, b'g', b'o', b'o', b'g', b'l', b'e', // Name
587
                0x03, b'c', b'o', b'm', // Name
588
                0x00, // Name
589
                0x00, 0x01, // Type
590
                0x00, 0x01, // Class
591
            ]);
592
            let message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
593
            assert_eq!(message.header().unwrap().id(), 0x0003);
594
            assert_eq!(message.header().unwrap().opcode(), DnsHeaderOpcode::Query);
595
            assert_eq!(message.header().unwrap().authoritative_answer(), false);
596
            assert_eq!(message.header().unwrap().truncated(), false);
597
            assert_eq!(message.header().unwrap().recursion_desired(), true);
598
            assert_eq!(message.header().unwrap().recursion_available(), false);
599
            assert_eq!(message.header().unwrap().response_code(), DnsHeaderResponseCode::NoError);
600
            let mut questions = message.questions();
601
            let mut question_iter = questions.iter().unwrap();
602
            let question = question_iter.next().unwrap().unwrap();
603
            assert_eq!(question.name, DnsName::from_bytes(b"\x06google\x03com\x00").unwrap());
604
            assert_eq!(question.qtype, DnsQType::A);
605
            assert_eq!(question.qclass, DnsQClass::IN);
606
            assert!(question_iter.next().is_none());
607
        }
608
609
        #[test]
610
        fn multiple_questions_compression() {
611
            let buffer: ArrayVec<u8, 512> = ArrayVec::new();
612
            let mut message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
613
            message.header_mut().unwrap().set_id(0x1234);
614
            message.header_mut().unwrap().set_opcode(DnsHeaderOpcode::Query);
615
            message.header_mut().unwrap().set_authoritative_answer(false);
616
            message.header_mut().unwrap().set_truncated(false);
617
            message.header_mut().unwrap().set_recursion_desired(false);
618
            message.header_mut().unwrap().set_recursion_available(false);
619
            message.header_mut().unwrap().set_response_code(DnsHeaderResponseCode::NoError);
620
            let mut questions = message.questions();
621
            questions.append(DnsQuestion {
622
                name: DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap(),
623
                qtype: DnsQType::A,
624
                qclass: DnsQClass::IN,
625
            }).unwrap();
626
            questions.append(DnsQuestion {
627
                name: DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap(),
628
                qtype: DnsQType::AAAA,
629
                qclass: DnsQClass::IN,
630
            }).unwrap();
631
            questions.append(DnsQuestion {
632
                name: DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap(),
633
                qtype: DnsQType::MX,
634
                qclass: DnsQClass::IN,
635
            }).unwrap();
636
            questions.append(DnsQuestion {
637
                name: DnsName::from_bytes(b"\x03www\x08examples\x03com\x00").unwrap(),
638
                qtype: DnsQType::TXT,
639
                qclass: DnsQClass::IN,
640
            }).unwrap();
641
            questions.append(DnsQuestion {
642
                name: DnsName::from_bytes(b"\x08examples\x03com\x00").unwrap(),
643
                qtype: DnsQType::CERT,
644
                qclass: DnsQClass::IN,
645
            }).unwrap();
646
            let message = questions.complete().unwrap();
647
            let buffer = message.complete().unwrap();
648
649
            assert_eq!(
650
                buffer.as_slice(),
651
                [
652
                    0x12, 0x34, // ID
653
                    0b0000_0000, 0b0000_0000, // Flags
654
                    0x00, 0x05, // Question count
655
                    0x00, 0x00, // Answer count
656
                    0x00, 0x00, // Authority count
657
                    0x00, 0x00, // Additional count
658
                    0x03, b'w', b'w', b'w', // Name
659
                    0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e', // Name
660
                    0x03, b'c', b'o', b'm', // Name
661
                    0x00, // Name
662
                    0x00, 0x01, // Type
663
                    0x00, 0x01, // Class
664
                    0xC0, 0x0C, // Name Pointer (0x0C = 12)
665
                    0x00, 0x1C, // Type
666
                    0x00, 0x01, // Class
667
                    0xC0, 0x0C, // Name Pointer (0x0C = 12)
668
                    0x00, 0x0F, // Type
669
                    0x00, 0x01, // Class
670
                    0x03, b'w', b'w', b'w', // Name
671
                    0x08, b'e', b'x', b'a', b'm', b'p', b'l', b'e', b's', // Name
672
                    0xC0, 0x18, // Name Pointer (0x18 = 24)
673
                    0x00, 0x10, // Type
674
                    0x00, 0x01, // Class
675
                    0xC0, 0x31, // Name Pointer (0x31 = 48)
676
                    0x00, 0x25, // Type
677
                    0x00, 0x01, // Class
678
                ].as_slice()
679
            );
680
681
            // Decode the message again and check that it is the same
682
            let message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
683
            assert_eq!(message.header().unwrap().id(), 0x1234);
684
            assert_eq!(message.header().unwrap().opcode(), DnsHeaderOpcode::Query);
685
            assert_eq!(message.header().unwrap().authoritative_answer(), false);
686
            assert_eq!(message.header().unwrap().truncated(), false);
687
            assert_eq!(message.header().unwrap().recursion_desired(), false);
688
            assert_eq!(message.header().unwrap().recursion_available(), false);
689
            assert_eq!(message.header().unwrap().response_code(), DnsHeaderResponseCode::NoError);
690
            let mut questions = message.questions();
691
            let mut question_iter = questions.iter().unwrap();
692
            let question = question_iter.next().unwrap().unwrap();
693
            assert_eq!(question.name, DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap());
694
            assert_eq!(question.qtype, DnsQType::A);
695
            assert_eq!(question.qclass, DnsQClass::IN);
696
            let question = question_iter.next().unwrap().unwrap();
697
            assert_eq!(question.name, DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap());
698
            assert_eq!(question.qtype, DnsQType::AAAA);
699
            assert_eq!(question.qclass, DnsQClass::IN);
700
            let question = question_iter.next().unwrap().unwrap();
701
            assert_eq!(question.name, DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap());
702
            assert_eq!(question.qtype, DnsQType::MX);
703
            assert_eq!(question.qclass, DnsQClass::IN);
704
            let question = question_iter.next().unwrap().unwrap();
705
            assert_eq!(question.name, DnsName::from_bytes(b"\x03www\x08examples\x03com\x00").unwrap());
706
            assert_eq!(question.qtype, DnsQType::TXT);
707
            assert_eq!(question.qclass, DnsQClass::IN);
708
            let question = question_iter.next().unwrap().unwrap();
709
            assert_eq!(question.name, DnsName::from_bytes(b"\x08examples\x03com\x00").unwrap());
710
            assert_eq!(question.qtype, DnsQType::CERT);
711
            assert_eq!(question.qclass, DnsQClass::IN);
712
            assert!(question_iter.next().is_none());
713
        }
714
    }
715
716
    mod answer {
717
        use core::net::Ipv4Addr;
718
        use crate::answer::{DnsAClass, DnsAnswer};
719
        use crate::header::{DnsHeaderOpcode, DnsHeaderResponseCode};
720
        use crate::rdata::{A, DnsAType};
721
        use super::*;
722
723
        #[test]
724
        fn single_answer() {
725
            let buffer: ArrayVec<u8, 512> = ArrayVec::new();
726
            let mut message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
727
            message.header_mut().unwrap().set_id(0x1234);
728
            message.header_mut().unwrap().set_opcode(DnsHeaderOpcode::Query);
729
            message.header_mut().unwrap().set_authoritative_answer(false);
730
            message.header_mut().unwrap().set_truncated(false);
731
            message.header_mut().unwrap().set_recursion_desired(false);
732
            message.header_mut().unwrap().set_recursion_available(false);
733
            message.header_mut().unwrap().set_response_code(DnsHeaderResponseCode::NoError);
734
            let message = message.questions().complete().unwrap();
735
            let message = {
736
                let mut answers = message.answers();
737
                answers.append(DnsAnswer {
738
                    name: DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap(),
739
                    aclass: DnsAClass::IN,
740
                    ttl: 0x12345678,
741
                    rdata: DnsAType::A(A { address: Ipv4Addr::new(127, 0, 0, 1) }),
742
                    cache_flush: false,
743
                }).unwrap();
744
                answers.complete().unwrap()
745
            };
746
            let buffer = message.complete().unwrap();
747
748
            assert_eq!(
749
                buffer.as_slice(),
750
                [
751
                    0x12, 0x34, // ID
752
                    0b0000_0000, 0b0000_0000, // Flags
753
                    0x00, 0x00, // Question count
754
                    0x00, 0x01, // Answer count
755
                    0x00, 0x00, // Authority count
756
                    0x00, 0x00, // Additional count
757
                    0x03, b'w', b'w', b'w', // Name
758
                    0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e', // Name
759
                    0x03, b'c', b'o', b'm', // Name
760
                    0x00, // Name
761
                    0x00, 0x01, // Type
762
                    0x00, 0x01, // Class
763
                    0x12, 0x34, 0x56, 0x78, // TTL
764
                    0x00, 0x04, // Data length
765
                    127, 0, 0, 1, // Data
766
                ].as_slice()
767
            );
768
769
            // Decode the message again and check that it is the same
770
            let message: DnsMessage<8, { DnsSection::Answers }, _> = DnsMessage::new(buffer).unwrap();
771
            assert_eq!(message.header().unwrap().id(), 0x1234);
772
            assert_eq!(message.header().unwrap().opcode(), DnsHeaderOpcode::Query);
773
            assert_eq!(message.header().unwrap().authoritative_answer(), false);
774
            assert_eq!(message.header().unwrap().truncated(), false);
775
            assert_eq!(message.header().unwrap().recursion_desired(), false);
776
            assert_eq!(message.header().unwrap().recursion_available(), false);
777
            assert_eq!(message.header().unwrap().response_code(), DnsHeaderResponseCode::NoError);
778
            let mut answers = message.answers();
779
            let mut answer_iter = answers.iter().unwrap();
780
            let answer = answer_iter.next().unwrap().unwrap();
781
            assert_eq!(answer.name, DnsName::from_bytes(b"\x03www\x07example\x03com\x00").unwrap());
782
            assert_eq!(answer.ttl, 0x12345678);
783
            assert_eq!(answer.into_parsed().unwrap().rdata, DnsAType::A(A { address: Ipv4Addr::new(127, 0, 0, 1) }));
784
            assert!(answer_iter.next().is_none());
785
        }
786
    }
787
788
    mod error {
789
        use crate::header::{DnsHeaderOpcode, DnsHeaderResponseCode};
790
        use super::*;
791
792
        #[test]
793
        fn truncated() {
794
            let buffer: ArrayVec<u8, 12> = ArrayVec::from([
795
                0x12, 0x34, // ID
796
                0b0000_0000, 0b0000_0000, // Flags
797
                0x00, 0x01, // Question count
798
                0x00, 0x00, // Answer count
799
                0x00, 0x00, // Authority count
800
                0x00, 0x00, // Additional count
801
                // Premature end of message
802
            ]);
803
            let message: DnsMessage<8, { DnsSection::Questions }, _> = DnsMessage::new(buffer).unwrap();
804
            assert_eq!(message.header().unwrap().id(), 0x1234);
805
            assert_eq!(message.header().unwrap().opcode(), DnsHeaderOpcode::Query);
806
            assert_eq!(message.header().unwrap().authoritative_answer(), false);
807
            assert_eq!(message.header().unwrap().truncated(), false);
808
            assert_eq!(message.header().unwrap().recursion_desired(), false);
809
            assert_eq!(message.header().unwrap().recursion_available(), false);
810
            assert_eq!(message.header().unwrap().response_code(), DnsHeaderResponseCode::NoError);
811
            let mut questions = message.questions();
812
            let mut question_iter = questions.iter().unwrap();
813
            assert_eq!(
814
                question_iter.next(),
815
                Some(Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer)))
816
            );
817
        }
818
    }
819
}
/mnt/h/flex-dns/src/name.rs
Line
Count
Source (jump to first uncovered line)
1
use core::fmt::{Debug, Display, Formatter};
2
use arrayvec::ArrayVec;
3
use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, DnsSection};
4
use crate::parse::ParseBytes;
5
6
const MAX_DOMAIN_NAME_LENGTH: usize = 255;
7
const MAX_DOMAIN_NAME_DEPTH: usize = 128;
8
const MAX_DOMAIN_NAME_LABEL_LENGTH: usize = 63;
9
10
/// A DNS name.
11
0
#[derive(Clone, Copy)]
12
pub struct DnsName<'a> {
13
    bytes: &'a [u8],
14
    offset: usize,
15
}
16
17
#[macro_export]
18
macro_rules! dns_name {
19
    ($value:expr $(,)?) => {
20
        {
21
            const NAME: [u8; $value.len() + 2] = {
22
                let mut result = [0; $value.len() + 2];
23
                let mut label_start = 0;
24
                let mut index = 0;
25
                loop {
26
                    if index == $value.len() {
27
                        result[label_start] = (index - label_start) as u8;
28
29
                        break;
30
                    }
31
32
                    let byte = $value[index];
33
                    if byte == b'.' {
34
                        result[label_start] = (index - label_start) as u8;
35
                        label_start = index + 1;
36
                    } else {
37
                        result[index + 1] = byte;
38
                    }
39
40
                    index += 1;
41
                }
42
43
                result
44
            };
45
            unsafe { DnsName::from_bytes_unchecked(&NAME) }
46
        }
47
    };
48
}
49
50
impl<'a> ParseBytes<'a> for DnsName<'a> {
51
    #[inline]
52
72.9M
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
53
72.9M
        const MAX_LENGTH: usize = 255;
54
72.9M
        let mut j = *i;
55
56
174M
        loop {
57
174M
            if j - *i >= MAX_LENGTH {
58
1.76M
                return Err(DnsMessageError::DnsError(DnsError::NameTooLong));
59
172M
            }
60
172M
61
172M
            match LabelType::from_bytes(bytes, &mut j)? {
62
                LabelType::Pointer(_) => {
63
49
                    break;
64
                }
65
101M
                LabelType::Part(len) => {
66
101M
                    j += len as usize;
67
101M
68
101M
                    if len == 0 {
69
4.62k
                        break;
70
101M
                    }
71
101M
72
101M
                    if len > MAX_DOMAIN_NAME_LABEL_LENGTH as u8 {
73
0
                        return Err(DnsMessageError::DnsError(DnsError::LabelTooLong));
74
101M
                    }
75
                }
76
            }
77
        }
78
79
4.67k
        let offset = *i;
80
4.67k
        *i = j;
81
4.67k
82
4.67k
        Ok(Self { bytes, offset })
83
72.9M
    }
84
}
85
86
impl<'a> DnsName<'a> {
87
    /// Create a new name from a string (Dot-separated labels).
88
0
    pub fn from_str(s: &'a mut str) -> Self {
89
0
        // Check that the name is ascii and that it is not too long.
90
0
        assert!(s.is_ascii());
91
0
        assert!(s.len() <= MAX_DOMAIN_NAME_LENGTH);
92
0
        let bytes = unsafe { s.as_bytes_mut() };
93
0
94
0
        let mut l = 0; // The length of the current label.
95
0
        let mut iter = bytes.iter_mut();
96
0
        let mut part_len_byte = iter.next().unwrap();
97
0
        let mut last_byte = *part_len_byte; // The last byte visited.
98
0
        while let Some(byte) = iter.next() {
99
0
            let b = *byte;
100
0
101
0
            if b == b'.' {
102
0
                // We've reached the end of a label.
103
0
                *part_len_byte = l as u8;
104
0
                l = 0;
105
0
                *byte = last_byte;
106
0
                part_len_byte = iter.next().unwrap();
107
0
                last_byte = *part_len_byte;
108
0
            } else {
109
0
                // We're still in the middle of a label.
110
0
                l += 1;
111
0
                *byte = last_byte;
112
0
                last_byte = b;
113
0
            }
114
        }
115
116
0
        Self { bytes, offset: 0 }
117
0
    }
118
119
    /// Read a name from a byte buffer (DNS wire format).
120
0
    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self, DnsMessageError> {
121
0
        for part in (NameIterator {
122
0
            bytes,
123
0
            offset: 0,
124
0
            depth: ArrayVec::new(),
125
        }) {
126
0
            part?;
127
        }
128
129
0
        Ok(Self { bytes, offset: 0 })
130
0
    }
131
132
    /// Read a name from a byte buffer (DNS wire format).
133
0
    pub const unsafe fn from_bytes_unchecked(bytes: &'a [u8]) -> Self {
134
0
        Self { bytes, offset: 0 }
135
0
    }
136
137
    #[inline(always)]
138
0
    pub fn write<
139
0
        const PTR_STORAGE: usize,
140
0
        const DNS_SECTION: DnsSection,
141
0
        B: Buffer,
142
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
143
0
        message.write_name(*self)
144
0
    }
145
146
0
    pub fn iter(&self) -> NameIterator<'a> {
147
0
        NameIterator {
148
0
            bytes: self.bytes,
149
0
            offset: self.offset,
150
0
            depth: ArrayVec::new(),
151
0
        }
152
0
    }
153
154
0
    pub fn split_first(&self) -> Result<(&'a [u8], Option<Self>), DnsMessageError> {
155
0
        let mut iter = self.iter();
156
0
        let first = iter.next().unwrap()?;
157
0
        if let Some(next) = iter.next() {
158
0
            let next = next?;
159
160
            // Calculate offset from address of the second pointer.
161
0
            let offset = next.as_ptr() as usize - self.bytes.as_ptr() as usize - 1;
162
0
163
0
            Ok((first, Some(Self {
164
0
                bytes: self.bytes,
165
0
                offset,
166
0
            })))
167
        } else {
168
0
            Ok((first, None))
169
        }
170
0
    }
171
172
0
    pub fn verify(&self) -> Result<(), DnsMessageError> {
173
0
        for part in self.iter() {
174
0
            part?;
175
        }
176
177
0
        Ok(())
178
0
    }
179
180
    #[inline(always)]
181
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
182
0
        self.iter().map(|part| part.map(|part| part.len() + 1)).sum()
183
    }
184
}
185
186
pub struct NameIterator<'a> {
187
    bytes: &'a [u8],
188
    offset: usize,
189
    depth: ArrayVec<usize, MAX_DOMAIN_NAME_DEPTH>,
190
}
191
192
impl<'a> Iterator for NameIterator<'a> {
193
    type Item = Result<&'a [u8], DnsMessageError>;
194
195
0
    fn next(&mut self) -> Option<Self::Item> {
196
0
        let mut i = self.offset;
197
0
        loop {
198
0
            self.depth.push(i);
199
0
            if self.depth.len() >= MAX_DOMAIN_NAME_DEPTH {
200
0
                return None;
201
0
            }
202
0
203
0
            match LabelType::from_bytes(self.bytes, &mut i).unwrap() {
204
0
                LabelType::Pointer(ptr) => {
205
0
                    if ptr < self.offset as u16 {
206
                        // The pointer points to an earlier part of the message.
207
0
                        i = ptr as usize;
208
0
209
0
                        if self.depth.contains(&i) {
210
                            // The pointer points to a part of the message that we've already visited.
211
0
                            return Some(Err(DnsMessageError::DnsError(DnsError::PointerCycle)));
212
0
                        }
213
0
214
0
                        continue;
215
                    } else {
216
                        // The pointer points into the future.
217
0
                        return Some(Err(DnsMessageError::DnsError(DnsError::PointerIntoTheFuture)));
218
                    }
219
                }
220
0
                LabelType::Part(len) => {
221
0
                    if len == 0 {
222
                        // We've reached the end of the name.
223
0
                        return None;
224
0
                    }
225
0
226
0
                    if len > MAX_DOMAIN_NAME_LABEL_LENGTH as u8 {
227
0
                        return Some(Err(DnsMessageError::DnsError(DnsError::LabelTooLong)));
228
0
                    }
229
0
230
0
                    if self.bytes.len() < i + len as usize {
231
                        // The name is longer than the buffer.
232
0
                        return Some(Err(DnsMessageError::DnsError(DnsError::MessageTooShort)));
233
0
                    }
234
0
235
0
                    let part = &self.bytes[i..i + len as usize];
236
0
                    self.offset = i + len as usize;
237
0
238
0
                    return Some(Ok(part))
239
                }
240
            }
241
        }
242
0
    }
243
}
244
245
impl PartialEq<DnsName<'_>> for DnsName<'_> {
246
0
    fn eq(&self, other: &DnsName<'_>) -> bool {
247
0
        for (a, b) in self.iter().zip(other.iter()) {
248
0
            match (a, b) {
249
0
                (Ok(a), Ok(b)) => {
250
0
                    if a != b {
251
0
                        return false;
252
0
                    }
253
                }
254
                _ => {
255
0
                    return false;
256
                }
257
            }
258
        }
259
260
0
        true
261
0
    }
262
}
263
264
impl Display for DnsName<'_> {
265
0
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
266
0
        let mut first = true;
267
0
        for part in self.iter() {
268
0
            if first {
269
0
                first = false;
270
0
            } else {
271
0
                f.write_str(".")?;
272
            }
273
274
0
            let part = part.map_err(|_| core::fmt::Error)?;
275
0
            f.write_str(core::str::from_utf8(part).unwrap())?;
276
        }
277
278
0
        Ok(())
279
0
    }
280
}
281
282
impl Debug for DnsName<'_> {
283
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
284
0
        f.write_str("DnsName(")?;
285
0
        Display::fmt(self, f)?;
286
0
        f.write_str(")")?;
287
288
0
        Ok(())
289
0
    }
290
}
291
292
0
#[derive(PartialEq)]
293
enum LabelType {
294
    Pointer(u16),
295
    Part(u8),
296
}
297
298
impl LabelType {
299
172M
    fn from_bytes(bytes: &[u8], i: &mut usize) -> Result<Self, DnsMessageError> {
300
        const PTR_MASK: u8 = 0b11000000;
301
        const LEN_MASK: u8 = !PTR_MASK;
302
303
172M
        let c = u8::parse_bytes(bytes, i)?;
304
305
116M
        if c & PTR_MASK == PTR_MASK {
306
15.4M
            let c = c & LEN_MASK;
307
15.4M
            let pointer = u16::from_be_bytes([c, u8::parse_bytes(bytes, i)?]);
308
11.5M
            if pointer >= *i as u16 {
309
                // Cannot point to the future.
310
11.5M
                return Err(DnsMessageError::DnsError(DnsError::PointerIntoTheFuture));
311
49
            }
312
49
313
49
            Ok(Self::Pointer(pointer))
314
        } else {
315
101M
            let len = c & LEN_MASK;
316
101M
317
101M
            Ok(Self::Part(len))
318
        }
319
172M
    }
320
}
/mnt/h/flex-dns/src/name_servers.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::answer::DnsAClass;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::question::DnsQType;
6
use crate::rdata::{DnsAType, RData};
7
use crate::write::WriteBytes;
8
9
pub struct DnsNameServers<
10
    const PTR_STORAGE: usize,
11
    B: Buffer,
12
> {
13
    message: DnsMessage<PTR_STORAGE, { DnsSection::NameServers }, B>,
14
    remaining: usize,
15
}
16
17
impl<
18
    const PTR_STORAGE: usize,
19
    B: Buffer,
20
> DnsNameServers<PTR_STORAGE, B> {
21
    #[inline(always)]
22
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::NameServers }, B>) -> Self {
23
1.12k
        let remaining = message.header().unwrap().answer_count() as usize;
24
1.12k
        Self {
25
1.12k
            message,
26
1.12k
            remaining,
27
1.12k
        }
28
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns12name_serversINtB2_14DnsNameServersKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
22
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::NameServers }, B>) -> Self {
23
1.12k
        let remaining = message.header().unwrap().answer_count() as usize;
24
1.12k
        Self {
25
1.12k
            message,
26
1.12k
            remaining,
27
1.12k
        }
28
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns12name_serversINtB2_14DnsNameServersKppE3newB4_
29
30
0
    pub fn append(&mut self, answer: NameServer<DnsAType>) -> Result<(), DnsMessageError> {
31
0
        let (buffer, position) = self.message.buffer_and_position();
32
0
        // Truncate the buffer to the current position.
33
0
        buffer.truncate(*position)?;
34
0
        answer.write(&mut self.message)?;
35
        // Set answer_count in the header to the current answer count + 1.
36
0
        let answer_count = self.message.header().unwrap().answer_count();
37
0
        let answer_count = answer_count + 1 - self.remaining as u16;
38
0
        self.message.header_mut()?.set_answer_count(answer_count);
39
0
        self.message.header_mut()?.set_name_server_count(0);
40
0
        self.message.header_mut()?.set_additional_records_count(0);
41
0
        self.remaining = 0;
42
0
43
0
        Ok(())
44
0
    }
45
46
    #[inline]
47
1.12k
    pub fn iter(&mut self) -> Result<DnsNameServersIterator, DnsMessageError> {
48
1.12k
        let (buffer, position) = self.message.buffer_and_position();
49
1.12k
        let buffer = buffer.bytes();
50
1.12k
51
1.12k
        Ok(DnsNameServersIterator {
52
1.12k
            buffer,
53
1.12k
            current_position: position,
54
1.12k
            remaining: &mut self.remaining,
55
1.12k
        })
56
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns12name_serversINtB2_14DnsNameServersKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE4iterCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
47
1.12k
    pub fn iter(&mut self) -> Result<DnsNameServersIterator, DnsMessageError> {
48
1.12k
        let (buffer, position) = self.message.buffer_and_position();
49
1.12k
        let buffer = buffer.bytes();
50
1.12k
51
1.12k
        Ok(DnsNameServersIterator {
52
1.12k
            buffer,
53
1.12k
            current_position: position,
54
1.12k
            remaining: &mut self.remaining,
55
1.12k
        })
56
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns12name_serversINtB2_14DnsNameServersKppE4iterB4_
57
58
    #[inline]
59
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>, DnsMessageError> {
60
1.12k
        if self.remaining != 0 {
61
0
            for x in self.iter()? { x?; }
62
1.12k
        }
63
64
1.12k
        Ok(DnsMessage {
65
1.12k
            buffer: self.message.buffer,
66
1.12k
            position: self.message.position,
67
1.12k
            ptr_storage: self.message.ptr_storage,
68
1.12k
        })
69
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns12name_serversINtB2_14DnsNameServersKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE8completeCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
59
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::Additionals }, B>, DnsMessageError> {
60
1.12k
        if self.remaining != 0 {
61
0
            for x in self.iter()? { x?; }
62
1.12k
        }
63
64
1.12k
        Ok(DnsMessage {
65
1.12k
            buffer: self.message.buffer,
66
1.12k
            position: self.message.position,
67
1.12k
            ptr_storage: self.message.ptr_storage,
68
1.12k
        })
69
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns12name_serversINtB2_14DnsNameServersKppE8completeB4_
70
}
71
72
pub struct DnsNameServersIterator<'a> {
73
    buffer: &'a [u8],
74
    current_position: &'a mut usize,
75
    remaining: &'a mut usize,
76
}
77
78
impl<'a> Iterator for DnsNameServersIterator<'a> {
79
    type Item = Result<NameServer<'a, RData<'a>>, DnsMessageError>;
80
81
    #[inline]
82
22.6M
    fn next(&mut self) -> Option<Self::Item> {
83
22.6M
        if *self.remaining == 0 {
84
1.12k
            return None;
85
22.5M
        }
86
22.5M
87
22.5M
        let name_server = NameServer::parse(
88
22.5M
            self.buffer, self.current_position
89
22.5M
        );
90
22.5M
        *self.remaining -= 1;
91
22.5M
92
22.5M
        Some(name_server)
93
22.6M
    }
_RNvXs_NtCslLTLXfmDngu_8flex_dns12name_serversNtB4_22DnsNameServersIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
82
22.6M
    fn next(&mut self) -> Option<Self::Item> {
83
22.6M
        if *self.remaining == 0 {
84
1.12k
            return None;
85
22.5M
        }
86
22.5M
87
22.5M
        let name_server = NameServer::parse(
88
22.5M
            self.buffer, self.current_position
89
22.5M
        );
90
22.5M
        *self.remaining -= 1;
91
22.5M
92
22.5M
        Some(name_server)
93
22.6M
    }
Unexecuted instantiation: _RNvXs_NtCslLTLXfmDngu_8flex_dns12name_serversNtB4_22DnsNameServersIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextB6_
94
}
95
96
0
#[derive(Debug, PartialEq)]
97
pub struct NameServer<'a, D> {
98
    pub name: DnsName<'a>,
99
    pub rdata: D,
100
    pub cache_flush: bool,
101
    pub aclass: DnsAClass,
102
    pub ttl: u32,
103
}
104
105
impl<'a> NameServer<'a, RData<'a>> {
106
22.5M
    pub fn parse(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
107
22.5M
        let name = DnsName::parse(bytes, i)?;
108
181
        let atype_id = u16::parse(bytes, i)?;
109
177
        let atype = DnsQType::from_id(atype_id);
110
177
        let cache_flush = atype_id & 0b1000_0000_0000_0000 != 0;
111
177
        let aclass = DnsAClass::from_id(u16::parse(bytes, i)?);
112
165
        let ttl = u32::parse(bytes, i)?;
113
150
        let rdata = RData::parse(bytes, i, atype)?;
114
115
103
        Ok(Self {
116
103
            name,
117
103
            rdata,
118
103
            cache_flush,
119
103
            aclass,
120
103
            ttl,
121
103
        })
122
22.5M
    }
123
124
    fn write<
125
        const PTR_STORAGE: usize,
126
        const DNS_SECTION: DnsSection,
127
        B: Buffer,
128
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
129
        // Write the name to the buffer using the pointer storage for compression.
130
0
        message.write_name(self.name)?;
131
        // Write the atype and aclass to the buffer.
132
0
        self.rdata.id().write(message)?;
133
0
        let mut aclass = self.aclass.id();
134
0
        if self.cache_flush {
135
0
            aclass |= 0b1000_0000;
136
0
        }
137
0
        aclass.write(message)?;
138
        // Write the ttl to the buffer.
139
0
        self.ttl.write(message)?;
140
0
        (self.rdata.byte_len()? as u16).write(message)?;
141
        // Write the type specific data to the buffer.
142
0
        self.rdata.write(message)?;
143
144
0
        Ok(())
145
0
    }
146
147
103
    pub fn into_parsed(self) -> Result<NameServer<'a, DnsAType<'a>>, DnsMessageError> {
148
103
        Ok(NameServer {
149
103
            name: self.name,
150
103
            rdata: self.rdata.into_parsed()?,
151
19
            cache_flush: self.cache_flush,
152
19
            aclass: self.aclass,
153
19
            ttl: self.ttl,
154
        })
155
103
    }
156
}
157
158
impl<'a> NameServer<'a, DnsAType<'a>> {
159
    fn write<
160
        const PTR_STORAGE: usize,
161
        const DNS_SECTION: DnsSection,
162
        B: Buffer,
163
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
164
        // Write the name to the buffer using the pointer storage for compression.
165
0
        self.name.write(message)?;
166
        // Write the atype and aclass to the buffer.
167
0
        self.rdata.id().write(message)?;
168
0
        let mut aclass = self.aclass.id();
169
0
        if self.cache_flush {
170
0
            aclass |= 0b1000_0000;
171
0
        }
172
0
        aclass.write(message)?;
173
        // Write the ttl to the buffer.
174
0
        self.ttl.write(message)?;
175
0
        let rdata_len = self.rdata.byte_len()? as u16;
176
0
        rdata_len.write(message)?;
177
        // Write the type specific data to the buffer.
178
0
        self.rdata.write(message)?;
179
180
0
        Ok(())
181
0
    }
182
}
/mnt/h/flex-dns/src/parse.rs
Line
Count
Source
1
use core::net::{Ipv4Addr, Ipv6Addr};
2
use crate::{DnsError, DnsMessageError};
3
4
pub(crate) trait ParseData<'a> {
5
    fn parse_data(&self) -> &'a [u8];
6
}
7
8
impl<'a> ParseData<'a> for &'a [u8] {
9
    #[inline(always)]
10
72.9M
    fn parse_data(&self) -> &'a [u8] {
11
72.9M
        *self
12
72.9M
    }
13
}
14
15
pub(crate) trait Parse<'a>: Sized {
16
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError>;
17
}
18
19
impl<'a, S: ParseBytes<'a>> Parse<'a> for S {
20
    #[inline(always)]
21
72.9M
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
72.9M
        Self::parse_bytes(bytes.parse_data(), i)
23
72.9M
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseAhj6_NtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
3
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
3
        Self::parse_bytes(bytes.parse_data(), i)
23
3
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseNtNtB7_10characters10CharactersNtB5_5Parse5parseRShEB7_
Line
Count
Source
21
252
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
252
        Self::parse_bytes(bytes.parse_data(), i)
23
252
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseNtNtNtCs6xNykbTfrCs_4core3net7ip_addr8Ipv4AddrNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
17
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
17
        Self::parse_bytes(bytes.parse_data(), i)
23
17
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parsehNtB5_5Parse5parseRShEB7_
Line
Count
Source
21
263
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
263
        Self::parse_bytes(bytes.parse_data(), i)
23
263
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseNtNtB7_4name7DnsNameNtB5_5Parse5parseRShEB7_
Line
Count
Source
21
72.9M
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
72.9M
        Self::parse_bytes(bytes.parse_data(), i)
23
72.9M
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseNtNtNtCs6xNykbTfrCs_4core3net7ip_addr8Ipv6AddrNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
27
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
27
        Self::parse_bytes(bytes.parse_data(), i)
23
27
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parsetNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
762
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
762
        Self::parse_bytes(bytes.parse_data(), i)
23
762
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseAhj8_NtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
3
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
3
        Self::parse_bytes(bytes.parse_data(), i)
23
3
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parsetNtB5_5Parse5parseRShEB7_
Line
Count
Source
21
11.2k
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
11.2k
        Self::parse_bytes(bytes.parse_data(), i)
23
11.2k
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parsemNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
179
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
179
        Self::parse_bytes(bytes.parse_data(), i)
23
179
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parsemNtB5_5Parse5parseRShEB7_
Line
Count
Source
21
3.20k
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
3.20k
        Self::parse_bytes(bytes.parse_data(), i)
23
3.20k
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parsehNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
565
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
565
        Self::parse_bytes(bytes.parse_data(), i)
23
565
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseyNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
27
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
27
        Self::parse_bytes(bytes.parse_data(), i)
23
27
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseNtNtB7_4name7DnsNameNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
234
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
234
        Self::parse_bytes(bytes.parse_data(), i)
23
234
    }
_RINvXs_NtCslLTLXfmDngu_8flex_dns5parseNtNtB7_10characters10CharactersNtB5_5Parse5parseRNtNtB7_5rdata5RDataEB7_
Line
Count
Source
21
518
    fn parse<T: ParseData<'a>>(bytes: T, i: &mut usize) -> Result<Self, DnsMessageError> {
22
518
        Self::parse_bytes(bytes.parse_data(), i)
23
518
    }
24
}
25
26
pub(crate) trait ParseBytes<'a>: Sized {
27
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError>;
28
}
29
30
impl<'a> ParseBytes<'a> for u8 {
31
    #[inline]
32
187M
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
33
187M
        if bytes.len() < *i + 1 {
34
59.5M
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
35
128M
        }
36
128M
37
128M
        let value = bytes[*i];
38
128M
        *i += 1;
39
128M
40
128M
        Ok(value)
41
187M
    }
42
}
43
44
impl<'a> ParseBytes<'a> for u16 {
45
    #[inline]
46
12.0k
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
47
12.0k
        if bytes.len() < *i + 2 {
48
557
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
49
11.4k
        }
50
11.4k
51
11.4k
        let value = u16::from_be_bytes([
52
11.4k
            bytes[*i],
53
11.4k
            bytes[*i + 1]
54
11.4k
        ]);
55
11.4k
        *i += 2;
56
11.4k
57
11.4k
        Ok(value)
58
12.0k
    }
59
}
60
61
impl<'a> ParseBytes<'a> for u32 {
62
    #[inline]
63
3.38k
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
64
3.38k
        if bytes.len() < *i + 4 {
65
206
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
66
3.17k
        }
67
3.17k
68
3.17k
        let value = u32::from_be_bytes([
69
3.17k
            bytes[*i],
70
3.17k
            bytes[*i + 1],
71
3.17k
            bytes[*i + 2],
72
3.17k
            bytes[*i + 3]
73
3.17k
        ]);
74
3.17k
        *i += 4;
75
3.17k
76
3.17k
        Ok(value)
77
3.38k
    }
78
}
79
80
impl<'a> ParseBytes<'a> for u64 {
81
    #[inline]
82
27
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
83
27
        if bytes.len() < *i + 8 {
84
2
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
85
25
        }
86
25
87
25
        let value = u64::from_be_bytes([
88
25
            bytes[*i],
89
25
            bytes[*i + 1],
90
25
            bytes[*i + 2],
91
25
            bytes[*i + 3],
92
25
            bytes[*i + 4],
93
25
            bytes[*i + 5],
94
25
            bytes[*i + 6],
95
25
            bytes[*i + 7]
96
25
        ]);
97
25
        *i += 8;
98
25
99
25
        Ok(value)
100
27
    }
101
}
102
103
impl<'a, const SIZE: usize> ParseBytes<'a> for [u8; SIZE] {
104
    #[inline]
105
6
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
106
6
        if bytes.len() < *i + SIZE {
107
3
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
108
3
        }
109
3
110
3
        let mut value = [0u8; SIZE];
111
3
        value.copy_from_slice(&bytes[*i..*i + SIZE]);
112
3
        *i += SIZE;
113
3
114
3
        Ok(value)
115
6
    }
_RNvXs4_NtCslLTLXfmDngu_8flex_dns5parseAhj6_NtB5_10ParseBytes11parse_bytesB7_
Line
Count
Source
105
3
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
106
3
        if bytes.len() < *i + SIZE {
107
2
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
108
1
        }
109
1
110
1
        let mut value = [0u8; SIZE];
111
1
        value.copy_from_slice(&bytes[*i..*i + SIZE]);
112
1
        *i += SIZE;
113
1
114
1
        Ok(value)
115
3
    }
_RNvXs4_NtCslLTLXfmDngu_8flex_dns5parseAhj8_NtB5_10ParseBytes11parse_bytesB7_
Line
Count
Source
105
3
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
106
3
        if bytes.len() < *i + SIZE {
107
1
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
108
2
        }
109
2
110
2
        let mut value = [0u8; SIZE];
111
2
        value.copy_from_slice(&bytes[*i..*i + SIZE]);
112
2
        *i += SIZE;
113
2
114
2
        Ok(value)
115
3
    }
116
}
117
118
impl<'a> ParseBytes<'a> for Ipv4Addr {
119
    #[inline]
120
17
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
121
17
        if bytes.len() < *i + 4 {
122
1
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
123
16
        }
124
16
125
16
        let address = Ipv4Addr::new(
126
16
            bytes[*i],
127
16
            bytes[*i + 1],
128
16
            bytes[*i + 2],
129
16
            bytes[*i + 3]
130
16
        );
131
16
        *i += 4;
132
16
133
16
        Ok(address)
134
17
    }
135
}
136
137
impl<'a> ParseBytes<'a> for Ipv6Addr {
138
    #[inline]
139
27
    fn parse_bytes(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
140
27
        if bytes.len() < *i + 16 {
141
7
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
142
20
        }
143
20
144
20
        let address = Ipv6Addr::new(
145
20
            ((bytes[*i] as u16) << 8) | (bytes[*i + 1] as u16),
146
20
            ((bytes[*i + 2] as u16) << 8) | (bytes[*i + 3] as u16),
147
20
            ((bytes[*i + 4] as u16) << 8) | (bytes[*i + 5] as u16),
148
20
            ((bytes[*i + 6] as u16) << 8) | (bytes[*i + 7] as u16),
149
20
            ((bytes[*i + 8] as u16) << 8) | (bytes[*i + 9] as u16),
150
20
            ((bytes[*i + 10] as u16) << 8) | (bytes[*i + 11] as u16),
151
20
            ((bytes[*i + 12] as u16) << 8) | (bytes[*i + 13] as u16),
152
20
            ((bytes[*i + 14] as u16) << 8) | (bytes[*i + 15] as u16),
153
20
        );
154
20
        *i += 16;
155
20
156
20
        Ok(address)
157
27
    }
158
}
/mnt/h/flex-dns/src/question.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::write::WriteBytes;
5
6
pub struct DnsQuestions<
7
    const PTR_STORAGE: usize,
8
    B: Buffer,
9
> {
10
    message: DnsMessage<PTR_STORAGE, { DnsSection::Questions }, B>,
11
    remaining: usize,
12
}
13
14
impl<
15
    const PTR_STORAGE: usize,
16
    B: Buffer,
17
> DnsQuestions<PTR_STORAGE, B> {
18
    #[inline(always)]
19
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::Questions }, B>) -> Self {
20
1.12k
        let remaining = message.header().unwrap().question_count() as usize;
21
1.12k
        Self {
22
1.12k
            message,
23
1.12k
            remaining,
24
1.12k
        }
25
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns8questionINtB2_12DnsQuestionsKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE3newCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
19
1.12k
    pub(crate) fn new(message: DnsMessage<PTR_STORAGE, { DnsSection::Questions }, B>) -> Self {
20
1.12k
        let remaining = message.header().unwrap().question_count() as usize;
21
1.12k
        Self {
22
1.12k
            message,
23
1.12k
            remaining,
24
1.12k
        }
25
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns8questionINtB2_12DnsQuestionsKppE3newB4_
26
27
0
    pub fn append(&mut self, question: DnsQuestion) -> Result<(), DnsMessageError> {
28
0
        let (buffer, position) = self.message.buffer_and_position();
29
0
        // Truncate the buffer to the current position.
30
0
        buffer.truncate(*position)?;
31
0
        question.write(&mut self.message)?;
32
        // Set question_count in the header to the current question count + 1.
33
0
        let question_count = self.message.header().unwrap().question_count();
34
0
        let question_count = question_count + 1 - self.remaining as u16;
35
0
        self.message.header_mut()?.set_question_count(question_count);
36
0
        self.message.header_mut()?.set_answer_count(0);
37
0
        self.message.header_mut()?.set_name_server_count(0);
38
0
        self.message.header_mut()?.set_additional_records_count(0);
39
0
        self.remaining = 0;
40
0
41
0
        Ok(())
42
0
    }
43
44
    #[inline]
45
1.12k
    pub fn iter(&mut self) -> Result<DnsQuestionIterator, DnsMessageError> {
46
1.12k
        let (buffer, position) = self.message.buffer_and_position();
47
1.12k
        let buffer = buffer.bytes();
48
1.12k
49
1.12k
        Ok(DnsQuestionIterator {
50
1.12k
            buffer,
51
1.12k
            current_position: position,
52
1.12k
            remaining: &mut self.remaining,
53
1.12k
        })
54
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns8questionINtB2_12DnsQuestionsKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE4iterCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
45
1.12k
    pub fn iter(&mut self) -> Result<DnsQuestionIterator, DnsMessageError> {
46
1.12k
        let (buffer, position) = self.message.buffer_and_position();
47
1.12k
        let buffer = buffer.bytes();
48
1.12k
49
1.12k
        Ok(DnsQuestionIterator {
50
1.12k
            buffer,
51
1.12k
            current_position: position,
52
1.12k
            remaining: &mut self.remaining,
53
1.12k
        })
54
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns8questionINtB2_12DnsQuestionsKppE4iterB4_
55
56
    #[inline]
57
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::Answers }, B>, DnsMessageError> {
58
1.12k
        if self.remaining != 0 {
59
0
            for x in self.iter()? { x?; }
60
1.12k
        }
61
62
1.12k
        Ok(DnsMessage {
63
1.12k
            buffer: self.message.buffer,
64
1.12k
            position: self.message.position,
65
1.12k
            ptr_storage: self.message.ptr_storage,
66
1.12k
        })
67
1.12k
    }
_RNvMNtCslLTLXfmDngu_8flex_dns8questionINtB2_12DnsQuestionsKj10_INtNtCskQaAGJdWXwX_8arrayvec8arrayvec8ArrayVechKj1000_EE8completeCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
57
1.12k
    pub fn complete(mut self) -> Result<DnsMessage<PTR_STORAGE, { DnsSection::Answers }, B>, DnsMessageError> {
58
1.12k
        if self.remaining != 0 {
59
0
            for x in self.iter()? { x?; }
60
1.12k
        }
61
62
1.12k
        Ok(DnsMessage {
63
1.12k
            buffer: self.message.buffer,
64
1.12k
            position: self.message.position,
65
1.12k
            ptr_storage: self.message.ptr_storage,
66
1.12k
        })
67
1.12k
    }
Unexecuted instantiation: _RNvMNtCslLTLXfmDngu_8flex_dns8questionINtB2_12DnsQuestionsKppE8completeB4_
68
}
69
70
pub struct DnsQuestionIterator<'a> {
71
    buffer: &'a [u8],
72
    current_position: &'a mut usize,
73
    remaining: &'a mut usize,
74
}
75
76
impl<'a> Iterator for DnsQuestionIterator<'a> {
77
    type Item = Result<DnsQuestion<'a>, DnsMessageError>;
78
79
    #[inline]
80
5.12M
    fn next(&mut self) -> Option<Self::Item> {
81
5.12M
        if *self.remaining == 0 {
82
1.12k
            return None;
83
5.12M
        }
84
5.12M
85
5.12M
        let question = DnsQuestion::parse(
86
5.12M
            self.buffer, self.current_position
87
5.12M
        );
88
5.12M
        *self.remaining -= 1;
89
5.12M
90
5.12M
        Some(question)
91
5.12M
    }
_RNvXs_NtCslLTLXfmDngu_8flex_dns8questionNtB4_19DnsQuestionIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextCsgg978DXfVXR_13fuzz_target_1
Line
Count
Source
80
5.12M
    fn next(&mut self) -> Option<Self::Item> {
81
5.12M
        if *self.remaining == 0 {
82
1.12k
            return None;
83
5.12M
        }
84
5.12M
85
5.12M
        let question = DnsQuestion::parse(
86
5.12M
            self.buffer, self.current_position
87
5.12M
        );
88
5.12M
        *self.remaining -= 1;
89
5.12M
90
5.12M
        Some(question)
91
5.12M
    }
Unexecuted instantiation: _RNvXs_NtCslLTLXfmDngu_8flex_dns8questionNtB4_19DnsQuestionIteratorNtNtNtNtCs6xNykbTfrCs_4core4iter6traits8iterator8Iterator4nextB6_
92
}
93
94
0
#[derive(Debug, PartialEq)]
95
pub struct DnsQuestion<'a> {
96
    pub name: DnsName<'a>,
97
    pub qtype: DnsQType,
98
    pub qclass: DnsQClass,
99
}
100
101
impl<'a> DnsQuestion<'a> {
102
5.12M
    pub fn parse(bytes: &'a [u8], i: &mut usize) -> Result<Self, DnsMessageError> {
103
5.12M
        let name = DnsName::parse(bytes, i)?;
104
1.08k
        let qtype = u16::parse(bytes, i)?.into();
105
1.03k
        let qclass = u16::parse(bytes, i)?.into();
106
958
107
958
        Ok(Self {
108
958
            name,
109
958
            qtype,
110
958
            qclass,
111
958
        })
112
5.12M
    }
113
114
    fn write<
115
        const PTR_STORAGE: usize,
116
        const DNS_SECTION: DnsSection,
117
        B: Buffer,
118
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
119
0
        self.name.write(message)?;
120
0
        self.qtype.id().write(message)?;
121
0
        self.qclass.id().write(message)?;
122
123
0
        Ok(())
124
0
    }
125
}
126
127
/// The kind of a DNS query.
128
///
129
/// According to [RFC 1035 Section 3.2.2](https://tools.ietf.org/rfc/rfc1035#section-3.2.2)
130
/// and [RFC 1035 Section 3.2.3](https://tools.ietf.org/rfc/rfc1035#section-3.2.3).
131
0
#[derive(Copy, Clone, Debug, PartialEq)]
132
#[repr(u16)]
133
pub enum DnsQType {
134
    A = 1,
135
    NS = 2,
136
    CNAME = 5,
137
    SOA = 6,
138
    PTR = 12,
139
    HINFO = 13,
140
    MX = 15,
141
    TXT = 16,
142
    RP = 17,
143
    AFSDB = 18,
144
    SIG = 24,
145
    KEY = 25,
146
    AAAA = 28,
147
    LOC = 29,
148
    SRV = 33,
149
    NAPTR = 35,
150
    KX = 36,
151
    CERT = 37,
152
    DNAME = 39,
153
    OPT = 41,
154
    APL = 42,
155
    DS = 43,
156
    SSHFP = 44,
157
    IPSECKEY = 45,
158
    RRSIG = 46,
159
    NSEC = 47,
160
    DNSKEY = 48,
161
    DHCID = 49,
162
    NSEC3 = 50,
163
    NSEC3PARAM = 51,
164
    TLSA = 52,
165
    SMIMEA = 53,
166
    HIP = 55,
167
    CDS = 59,
168
    CDNSKEY = 60,
169
    OPENPGPKEY = 61,
170
    CSYNC = 62,
171
    ZONEMD = 63,
172
    SVCB = 64,
173
    HTTPS = 65,
174
    EUI48 = 108,
175
    EUI64 = 109,
176
    TKEY = 249,
177
    TSIG = 250,
178
    IXFR = 251,
179
    AXFR = 252,
180
    ALL = 255,
181
    URI = 256,
182
    CAA = 257,
183
    TA = 32768,
184
    DLV = 32769,
185
    Reserved,
186
}
187
188
impl DnsQType {
189
    #[inline(always)]
190
3.93k
    pub fn from_id(id: u16) -> Self {
191
3.93k
        match id {
192
2.76k
            1..=2 | 5..=6 | 12..=13 | 15..=18 | 24..=25 | 28..=29
193
1.60k
            | 33 | 35..=37 | 39 | 41..=53 | 55 | 59..=65
194
918
            | 108..=109 | 249..=252 | 255 | 256 | 257
195
238
            | 32768..=32769 => unsafe {
196
1.96k
                core::mem::transmute(id)
197
            },
198
1.97k
            _ => DnsQType::Reserved,
199
        }
200
3.93k
    }
201
202
    #[inline(always)]
203
    pub fn id(&self) -> u16 {
204
        match self {
205
            DnsQType::Reserved => panic!("Reserved QType"),
206
            _ => *self as u16,
207
        }
208
    }
209
}
210
211
impl From<DnsQType> for u16 {
212
    #[inline(always)]
213
    fn from(q: DnsQType) -> Self {
214
        DnsQType::id(&q)
215
    }
216
}
217
218
impl From<u16> for DnsQType {
219
    #[inline(always)]
220
1.03k
    fn from(n: u16) -> Self {
221
1.03k
        DnsQType::from_id(n)
222
1.03k
    }
223
}
224
225
/// The class of a DNS query.
226
///
227
/// According to [RFC 1035 Section 3.2.4](https://tools.ietf.org/rfc/rfc1035#section-3.2.4).
228
0
#[derive(Copy, Clone, Debug, PartialEq)]
229
#[repr(u16)]
230
pub enum DnsQClass {
231
    /// Internet
232
    IN = 1,
233
    /// CSNET
234
    CS = 2,
235
    /// CHAOS
236
    CH = 3,
237
    /// Hesiod
238
    HS = 4,
239
    Reserved,
240
}
241
242
impl DnsQClass {
243
    #[inline(always)]
244
958
    pub fn from_id(id: u16) -> Self {
245
958
        match id {
246
595
            1..=4 => unsafe { core::mem::transmute(id) },
247
913
            _ => DnsQClass::Reserved,
248
        }
249
958
    }
250
251
    #[inline(always)]
252
    pub fn id(&self) -> u16 {
253
        match self {
254
            DnsQClass::Reserved => panic!("Reserved QClass"),
255
            _ => *self as u16,
256
        }
257
    }
258
}
259
260
impl From<DnsQClass> for u16 {
261
    #[inline(always)]
262
    fn from(q: DnsQClass) -> Self {
263
        DnsQClass::id(&q)
264
    }
265
}
266
267
impl From<u16> for DnsQClass {
268
    #[inline(always)]
269
958
    fn from(n: u16) -> Self {
270
958
        DnsQClass::from_id(n)
271
958
    }
272
}
/mnt/h/flex-dns/src/rdata.rs
Line
Count
Source (jump to first uncovered line)
1
mod a;
2
mod ns;
3
mod cname;
4
mod soa;
5
mod ptr;
6
mod hinfo;
7
mod mx;
8
mod txt;
9
mod rp;
10
mod afsdb;
11
mod sig;
12
mod key;
13
mod aaaa;
14
mod loc;
15
mod srv;
16
mod naptr;
17
mod kx;
18
mod cert;
19
mod dname;
20
mod opt;
21
mod apl;
22
mod ds;
23
mod sshfp;
24
mod ipseckey;
25
mod rrsig;
26
mod nsec;
27
mod dnskey;
28
mod dhcid;
29
mod nsec3;
30
mod nsec3param;
31
mod tlsa;
32
mod smimea;
33
mod hip;
34
mod cds;
35
mod cdnskey;
36
mod openpgpkey;
37
mod csync;
38
mod zonemd;
39
mod svcb;
40
mod https;
41
mod eui48;
42
mod eui64;
43
mod tkey;
44
mod tsig;
45
mod ixfr;
46
mod axfr;
47
mod uri;
48
mod caa;
49
mod ta;
50
mod dlv;
51
52
pub use a::A;
53
pub use ns::Ns;
54
pub use cname::CName;
55
pub use soa::Soa;
56
pub use ptr::Ptr;
57
pub use hinfo::HInfo;
58
pub use mx::Mx;
59
pub use txt::Txt;
60
pub use rp::Rp;
61
pub use afsdb::AfsDb;
62
pub use sig::Sig;
63
pub use key::Key;
64
pub use aaaa::Aaaa;
65
pub use loc::Loc;
66
pub use srv::Srv;
67
pub use naptr::Naptr;
68
pub use kx::Kx;
69
pub use cert::Cert;
70
pub use dname::DName;
71
pub use opt::Opt;
72
pub use apl::Apl;
73
pub use ds::Ds;
74
pub use sshfp::SshFp;
75
pub use ipseckey::IpSecKey;
76
pub use rrsig::RRSig;
77
pub use nsec::Nsec;
78
pub use dnskey::DnsKey;
79
pub use dhcid::DhcId;
80
pub use nsec3::Nsec3;
81
pub use nsec3param::Nsec3Param;
82
pub use tlsa::Tlsa;
83
pub use smimea::SmimeA;
84
pub use hip::Hip;
85
pub use cds::Cds;
86
pub use cdnskey::CdnsKey;
87
pub use openpgpkey::OpenPgpKey;
88
pub use csync::CSync;
89
pub use zonemd::ZoneMd;
90
pub use svcb::Svcb;
91
pub use https::Https;
92
pub use eui48::EUI48;
93
pub use eui64::EUI64;
94
pub use tkey::TKey;
95
pub use tsig::TSig;
96
pub use ixfr::IXfr;
97
pub use axfr::AXfr;
98
pub use uri::Uri;
99
pub use caa::Caa;
100
pub use ta::Ta;
101
pub use dlv::Dlv;
102
103
use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, DnsSection};
104
use crate::parse::{Parse, ParseData};
105
use crate::question::DnsQType;
106
use crate::write::WriteBytes;
107
108
0
#[derive(Debug, Clone, Copy, PartialEq)]
109
pub struct RData<'a> {
110
    buffer: &'a [u8],
111
    pos: usize,
112
    len: usize,
113
    type_: DnsQType,
114
}
115
116
impl<'a> ParseData<'a> for RData<'a> {
117
    #[inline(always)]
118
14
    fn parse_data(&self) -> &'a [u8] {
119
14
        self.buffer
120
14
    }
121
}
122
123
impl<'a> ParseData<'a> for &'_ RData<'a> {
124
    #[inline(always)]
125
2.33k
    fn parse_data(&self) -> &'a [u8] {
126
2.33k
        self.buffer
127
2.33k
    }
128
}
129
130
pub(crate) trait RDataParse<'a>: Sized {
131
    fn parse(bytes: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError>;
132
}
133
134
impl<'a> RData<'a> {
135
    #[inline(always)]
136
    pub fn id(&self) -> u16 {
137
        self.type_.id()
138
    }
139
140
2.60k
    pub fn parse(bytes: &'a [u8], i: &mut usize, type_: DnsQType) -> Result<Self, DnsMessageError> {
141
2.60k
        let len = u16::parse(bytes, i)? as usize;
142
2.53k
        let pos = *i;
143
2.53k
144
2.53k
        if pos + len > bytes.len() {
145
610
            return Err(DnsMessageError::DnsError(DnsError::RDataLongerThanMessage));
146
1.92k
        }
147
1.92k
148
1.92k
        *i += len;
149
1.92k
150
1.92k
        Ok(RData { buffer: bytes, pos, len, type_ })
151
2.60k
    }
152
153
    #[inline]
154
    pub fn write<
155
        const PTR_STORAGE: usize,
156
        const DNS_SECTION: DnsSection,
157
        B: Buffer,
158
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
159
0
        (self.len as u16).write(message)?;
160
0
        message.write_bytes(&self.buffer[self.pos..self.pos + self.len])
161
0
    }
162
163
    #[inline(always)]
164
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
165
        Ok(self.len)
166
    }
167
168
1.92k
    pub fn into_parsed(self) -> Result<DnsAType<'a>, DnsMessageError> {
169
1.92k
        let mut pos = self.pos;
170
1.92k
171
1.92k
        Ok(match self.type_ {
172
17
            DnsQType::A => DnsAType::A(A::parse(&self, &mut pos)?),
173
23
            DnsQType::NS => DnsAType::NS(Ns::parse(&self, &mut pos)?),
174
41
            DnsQType::CNAME => DnsAType::CName(CName::parse(&self, &mut pos)?),
175
63
            DnsQType::SOA => DnsAType::Soa(Soa::parse(&self, &mut pos)?),
176
5
            DnsQType::PTR => DnsAType::Ptr(Ptr::parse(&self, &mut pos)?),
177
10
            DnsQType::HINFO => DnsAType::HInfo(HInfo::parse(&self, &mut pos)?),
178
20
            DnsQType::MX => DnsAType::MX(Mx::parse(&self, &mut pos)?),
179
30
            DnsQType::TXT => DnsAType::Txt(Txt::parse(&self, &mut pos)?),
180
46
            DnsQType::RP => DnsAType::RP(Rp::parse(&self, &mut pos)?),
181
9
            DnsQType::AFSDB => DnsAType::AFSDB(AfsDb::parse(&self, &mut pos)?),
182
57
            DnsQType::SIG => DnsAType::SIG(Sig::parse(&self, &mut pos)?),
183
67
            DnsQType::KEY => DnsAType::KEY(Key::parse(&self, &mut pos)?),
184
27
            DnsQType::AAAA => DnsAType::AAAA(Aaaa::parse(&self, &mut pos)?),
185
15
            DnsQType::LOC => DnsAType::Loc(Loc::parse(&self, &mut pos)?),
186
62
            DnsQType::SRV => DnsAType::Srv(Srv::parse(&self, &mut pos)?),
187
34
            DnsQType::NAPTR => DnsAType::Naptr(Naptr::parse(&self, &mut pos)?),
188
3
            DnsQType::KX => DnsAType::KX(Kx::parse(&self, &mut pos)?),
189
27
            DnsQType::CERT => DnsAType::Cert(Cert::parse(&self, &mut pos)?),
190
6
            DnsQType::DNAME => DnsAType::DName(DName::parse(&self, &mut pos)?),
191
23
            DnsQType::OPT => DnsAType::OPT(Opt::parse(&self, &mut pos)?),
192
14
            DnsQType::APL => DnsAType::APL(Apl::parse(&self, &mut pos)?),
193
16
            DnsQType::DS => DnsAType::DS(Ds::parse(&self, &mut pos)?),
194
7
            DnsQType::SSHFP => DnsAType::SSHFP(SshFp::parse(&self, &mut pos)?),
195
35
            DnsQType::IPSECKEY => DnsAType::IPSECKEY(IpSecKey::parse(&self, &mut pos)?),
196
43
            DnsQType::RRSIG => DnsAType::RRSIG(RRSig::parse(&self, &mut pos)?),
197
36
            DnsQType::NSEC => DnsAType::NSEC(Nsec::parse(&self, &mut pos)?),
198
3
            DnsQType::DNSKEY => DnsAType::DNSKEY(DnsKey::parse(&self, &mut pos)?),
199
26
            DnsQType::DHCID => DnsAType::DHCID(DhcId::parse(&self, &mut pos)?),
200
27
            DnsQType::NSEC3 => DnsAType::NSEC3(Nsec3::parse(&self, &mut pos)?),
201
8
            DnsQType::NSEC3PARAM => DnsAType::NSEC3PARAM(Nsec3Param::parse(&self, &mut pos)?),
202
19
            DnsQType::TLSA => DnsAType::TLSA(Tlsa::parse(&self, &mut pos)?),
203
15
            DnsQType::SMIMEA => DnsAType::SMIMEA(SmimeA::parse(&self, &mut pos)?),
204
5
            DnsQType::HIP => DnsAType::HIP(Hip::parse(&self, &mut pos)?),
205
2
            DnsQType::CDS => DnsAType::CDS(Cds::parse(&self, &mut pos)?),
206
10
            DnsQType::CDNSKEY => DnsAType::CDNSKEY(CdnsKey::parse(&self, &mut pos)?),
207
14
            DnsQType::OPENPGPKEY => DnsAType::OPENPGPKEY(OpenPgpKey::parse(&self, &mut pos)?),
208
20
            DnsQType::CSYNC => DnsAType::CSYNC(CSync::parse(&self, &mut pos)?),
209
10
            DnsQType::ZONEMD => DnsAType::ZONEMD(ZoneMd::parse(&self, &mut pos)?),
210
108
            DnsQType::SVCB => DnsAType::SVCB(Svcb::parse(&self, &mut pos)?),
211
4
            DnsQType::HTTPS => DnsAType::HTTPS(Https::parse(&self, &mut pos)?),
212
3
            DnsQType::EUI48 => DnsAType::EUI48(EUI48::parse(&self, &mut pos)?),
213
3
            DnsQType::EUI64 => DnsAType::EUI64(EUI64::parse(&self, &mut pos)?),
214
47
            DnsQType::TKEY => DnsAType::TKEY(TKey::parse(&self, &mut pos)?),
215
42
            DnsQType::TSIG => DnsAType::TSIG(TSig::parse(&self, &mut pos)?),
216
8
            DnsQType::IXFR => DnsAType::IXFR(IXfr::parse(&self, &mut pos)?),
217
23
            DnsQType::AXFR => DnsAType::AXFR(AXfr::parse(&self, &mut pos)?),
218
12
            DnsQType::ALL => return Err(DnsMessageError::DnsError(DnsError::InvalidAnswer)),
219
63
            DnsQType::URI => DnsAType::URI(Uri::parse(&self, &mut pos)?),
220
27
            DnsQType::CAA => DnsAType::CAA(Caa::parse(&self, &mut pos)?),
221
3
            DnsQType::TA => DnsAType::TA(Ta::parse(&self, &mut pos)?),
222
4
            DnsQType::DLV => DnsAType::DLV(Dlv::parse(&self, &mut pos)?),
223
687
            DnsQType::Reserved => return Err(DnsMessageError::DnsError(DnsError::InvalidAnswer)),
224
        })
225
1.92k
    }
226
}
227
228
0
#[derive(Debug, Clone, Copy, PartialEq)]
229
pub enum DnsAType<'a> {
230
    A(A),
231
    NS(Ns<'a>),
232
    CName(CName<'a>),
233
    Soa(Soa<'a>),
234
    Ptr(Ptr<'a>),
235
    HInfo(HInfo<'a>),
236
    MX(Mx<'a>),
237
    Txt(Txt<'a>),
238
    RP(Rp<'a>),
239
    AFSDB(AfsDb<'a>),
240
    SIG(Sig<'a>),
241
    KEY(Key<'a>),
242
    AAAA(Aaaa),
243
    Loc(Loc),
244
    Srv(Srv<'a>),
245
    Naptr(Naptr<'a>),
246
    KX(Kx<'a>),
247
    Cert(Cert<'a>),
248
    DName(DName<'a>),
249
    OPT(Opt<'a>),
250
    APL(Apl<'a>),
251
    DS(Ds<'a>),
252
    SSHFP(SshFp<'a>),
253
    IPSECKEY(IpSecKey<'a>),
254
    RRSIG(RRSig<'a>),
255
    NSEC(Nsec<'a>),
256
    DNSKEY(DnsKey<'a>),
257
    DHCID(DhcId<'a>),
258
    NSEC3(Nsec3<'a>),
259
    NSEC3PARAM(Nsec3Param<'a>),
260
    TLSA(Tlsa<'a>),
261
    SMIMEA(SmimeA<'a>),
262
    HIP(Hip<'a>),
263
    CDS(Cds<'a>),
264
    CDNSKEY(CdnsKey<'a>),
265
    OPENPGPKEY(OpenPgpKey<'a>),
266
    CSYNC(CSync<'a>),
267
    ZONEMD(ZoneMd<'a>),
268
    SVCB(Svcb<'a>),
269
    HTTPS(Https<'a>),
270
    EUI48(EUI48),
271
    EUI64(EUI64),
272
    TKEY(TKey<'a>),
273
    TSIG(TSig<'a>),
274
    IXFR(IXfr<'a>),
275
    AXFR(AXfr<'a>),
276
    URI(Uri<'a>),
277
    CAA(Caa<'a>),
278
    TA(Ta<'a>),
279
    DLV(Dlv<'a>),
280
    /// Unknown
281
    Reserved,
282
}
283
284
impl<'a> Into<DnsQType> for DnsAType<'a> {
285
    #[inline(always)]
286
    fn into(self) -> DnsQType {
287
        match self {
288
            DnsAType::A(_) => DnsQType::A,
289
            DnsAType::NS(_) => DnsQType::NS,
290
            DnsAType::CName(_) => DnsQType::CNAME,
291
            DnsAType::Soa(_) => DnsQType::SOA,
292
            DnsAType::Ptr(_) => DnsQType::PTR,
293
            DnsAType::HInfo(_) => DnsQType::HINFO,
294
            DnsAType::MX(_) => DnsQType::MX,
295
            DnsAType::Txt(_) => DnsQType::TXT,
296
            DnsAType::RP(_) => DnsQType::RP,
297
            DnsAType::AFSDB(_) => DnsQType::AFSDB,
298
            DnsAType::SIG(_) => DnsQType::SIG,
299
            DnsAType::KEY(_) => DnsQType::KEY,
300
            DnsAType::AAAA(_) => DnsQType::AAAA,
301
            DnsAType::Loc(_) => DnsQType::LOC,
302
            DnsAType::Srv(_) => DnsQType::SRV,
303
            DnsAType::Naptr(_) => DnsQType::NAPTR,
304
            DnsAType::KX(_) => DnsQType::KX,
305
            DnsAType::Cert(_) => DnsQType::CERT,
306
            DnsAType::DName(_) => DnsQType::DNAME,
307
            DnsAType::OPT(_) => DnsQType::OPT,
308
            DnsAType::APL(_) => DnsQType::APL,
309
            DnsAType::DS(_) => DnsQType::DS,
310
            DnsAType::SSHFP(_) => DnsQType::SSHFP,
311
            DnsAType::IPSECKEY(_) => DnsQType::IPSECKEY,
312
            DnsAType::RRSIG(_) => DnsQType::RRSIG,
313
            DnsAType::NSEC(_) => DnsQType::NSEC,
314
            DnsAType::DNSKEY(_) => DnsQType::DNSKEY,
315
            DnsAType::DHCID(_) => DnsQType::DHCID,
316
            DnsAType::NSEC3(_) => DnsQType::NSEC3,
317
            DnsAType::NSEC3PARAM(_) => DnsQType::NSEC3PARAM,
318
            DnsAType::TLSA(_) => DnsQType::TLSA,
319
            DnsAType::SMIMEA(_) => DnsQType::SMIMEA,
320
            DnsAType::HIP(_) => DnsQType::HIP,
321
            DnsAType::CDS(_) => DnsQType::CDS,
322
            DnsAType::CDNSKEY(_) => DnsQType::CDNSKEY,
323
            DnsAType::OPENPGPKEY(_) => DnsQType::OPENPGPKEY,
324
            DnsAType::CSYNC(_) => DnsQType::CSYNC,
325
            DnsAType::ZONEMD(_) => DnsQType::ZONEMD,
326
            DnsAType::SVCB(_) => DnsQType::SVCB,
327
            DnsAType::HTTPS(_) => DnsQType::HTTPS,
328
            DnsAType::EUI48(_) => DnsQType::EUI48,
329
            DnsAType::EUI64(_) => DnsQType::EUI64,
330
            DnsAType::TKEY(_) => DnsQType::TKEY,
331
            DnsAType::TSIG(_) => DnsQType::TSIG,
332
            DnsAType::IXFR(_) => DnsQType::IXFR,
333
            DnsAType::AXFR(_) => DnsQType::AXFR,
334
            DnsAType::URI(_) => DnsQType::URI,
335
            DnsAType::CAA(_) => DnsQType::CAA,
336
            DnsAType::TA(_) => DnsQType::TA,
337
            DnsAType::DLV(_) => DnsQType::DLV,
338
            DnsAType::Reserved => DnsQType::Reserved,
339
        }
340
    }
341
}
342
343
impl<'a> DnsAType<'a> {
344
    #[inline]
345
0
    pub(crate) fn write<
346
0
        const PTR_STORAGE: usize,
347
0
        const DNS_SECTION: DnsSection,
348
0
        B: Buffer,
349
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
350
0
        match self {
351
0
            DnsAType::A(r) => r.write(message),
352
0
            DnsAType::NS(r) => r.write(message),
353
0
            DnsAType::CName(r) => r.write(message),
354
0
            DnsAType::Soa(r) => r.write(message),
355
0
            DnsAType::Ptr(r) => r.write(message),
356
0
            DnsAType::HInfo(r) => r.write(message),
357
0
            DnsAType::MX(r) => r.write(message),
358
0
            DnsAType::Txt(r) => r.write(message),
359
0
            DnsAType::RP(r) => r.write(message),
360
0
            DnsAType::AFSDB(r) => r.write(message),
361
0
            DnsAType::SIG(r) => r.write(message),
362
0
            DnsAType::KEY(r) => r.write(message),
363
0
            DnsAType::AAAA(r) => r.write(message),
364
0
            DnsAType::Loc(r) => r.write(message),
365
0
            DnsAType::Srv(r) => r.write(message),
366
0
            DnsAType::Naptr(r) => r.write(message),
367
0
            DnsAType::KX(r) => r.write(message),
368
0
            DnsAType::Cert(r) => r.write(message),
369
0
            DnsAType::DName(r) => r.write(message),
370
0
            DnsAType::OPT(r) => r.write(message),
371
0
            DnsAType::APL(r) => r.write(message),
372
0
            DnsAType::DS(r) => r.write(message),
373
0
            DnsAType::SSHFP(r) => r.write(message),
374
0
            DnsAType::IPSECKEY(r) => r.write(message),
375
0
            DnsAType::RRSIG(r) => r.write(message),
376
0
            DnsAType::NSEC(r) => r.write(message),
377
0
            DnsAType::DNSKEY(r) => r.write(message),
378
0
            DnsAType::DHCID(r) => r.write(message),
379
0
            DnsAType::NSEC3(r) => r.write(message),
380
0
            DnsAType::NSEC3PARAM(r) => r.write(message),
381
0
            DnsAType::TLSA(r) => r.write(message),
382
0
            DnsAType::SMIMEA(r) => r.write(message),
383
0
            DnsAType::HIP(r) => r.write(message),
384
0
            DnsAType::CDS(r) => r.write(message),
385
0
            DnsAType::CDNSKEY(r) => r.write(message),
386
0
            DnsAType::OPENPGPKEY(r) => r.write(message),
387
0
            DnsAType::CSYNC(r) => r.write(message),
388
0
            DnsAType::ZONEMD(r) => r.write(message),
389
0
            DnsAType::SVCB(r) => r.write(message),
390
0
            DnsAType::HTTPS(r) => r.write(message),
391
0
            DnsAType::EUI48(r) => r.write(message),
392
0
            DnsAType::EUI64(r) => r.write(message),
393
0
            DnsAType::TKEY(r) => r.write(message),
394
0
            DnsAType::TSIG(r) => r.write(message),
395
0
            DnsAType::IXFR(r) => r.write(message),
396
0
            DnsAType::AXFR(r) => r.write(message),
397
0
            DnsAType::URI(r) => r.write(message),
398
0
            DnsAType::CAA(r) => r.write(message),
399
0
            DnsAType::TA(r) => r.write(message),
400
0
            DnsAType::DLV(r) => r.write(message),
401
0
            DnsAType::Reserved => Err(DnsMessageError::DnsError(DnsError::InvalidAnswer)),
402
        }
403
0
    }
404
405
    #[inline(always)]
406
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
407
        match self {
408
            DnsAType::A(r) => r.byte_len(),
409
            DnsAType::NS(r) => r.byte_len(),
410
            DnsAType::CName(r) => r.byte_len(),
411
            DnsAType::Soa(r) => r.byte_len(),
412
            DnsAType::Ptr(r) => r.byte_len(),
413
            DnsAType::HInfo(r) => r.byte_len(),
414
            DnsAType::MX(r) => r.byte_len(),
415
            DnsAType::Txt(r) => r.byte_len(),
416
            DnsAType::RP(r) => r.byte_len(),
417
            DnsAType::AFSDB(r) => r.byte_len(),
418
            DnsAType::SIG(r) => r.byte_len(),
419
            DnsAType::KEY(r) => r.byte_len(),
420
            DnsAType::AAAA(r) => r.byte_len(),
421
            DnsAType::Loc(r) => r.byte_len(),
422
            DnsAType::Srv(r) => r.byte_len(),
423
            DnsAType::Naptr(r) => r.byte_len(),
424
            DnsAType::KX(r) => r.byte_len(),
425
            DnsAType::Cert(r) => r.byte_len(),
426
            DnsAType::DName(r) => r.byte_len(),
427
            DnsAType::OPT(r) => r.byte_len(),
428
            DnsAType::APL(r) => r.byte_len(),
429
            DnsAType::DS(r) => r.byte_len(),
430
            DnsAType::SSHFP(r) => r.byte_len(),
431
            DnsAType::IPSECKEY(r) => r.byte_len(),
432
            DnsAType::RRSIG(r) => r.byte_len(),
433
            DnsAType::NSEC(r) => r.byte_len(),
434
            DnsAType::DNSKEY(r) => r.byte_len(),
435
            DnsAType::DHCID(r) => r.byte_len(),
436
            DnsAType::NSEC3(r) => r.byte_len(),
437
            DnsAType::NSEC3PARAM(r) => r.byte_len(),
438
            DnsAType::TLSA(r) => r.byte_len(),
439
            DnsAType::SMIMEA(r) => r.byte_len(),
440
            DnsAType::HIP(r) => r.byte_len(),
441
            DnsAType::CDS(r) => r.byte_len(),
442
            DnsAType::CDNSKEY(r) => r.byte_len(),
443
            DnsAType::OPENPGPKEY(r) => r.byte_len(),
444
            DnsAType::CSYNC(r) => r.byte_len(),
445
            DnsAType::ZONEMD(r) => r.byte_len(),
446
            DnsAType::SVCB(r) => r.byte_len(),
447
            DnsAType::HTTPS(r) => r.byte_len(),
448
            DnsAType::EUI48(r) => r.byte_len(),
449
            DnsAType::EUI64(r) => r.byte_len(),
450
            DnsAType::TKEY(r) => r.byte_len(),
451
            DnsAType::TSIG(r) => r.byte_len(),
452
            DnsAType::IXFR(r) => r.byte_len(),
453
            DnsAType::AXFR(r) => r.byte_len(),
454
            DnsAType::URI(r) => r.byte_len(),
455
            DnsAType::CAA(r) => r.byte_len(),
456
            DnsAType::TA(r) => r.byte_len(),
457
            DnsAType::DLV(r) => r.byte_len(),
458
            DnsAType::Reserved => Ok(0),
459
        }
460
    }
461
462
    #[inline(always)]
463
    pub fn id(&self) -> u16 {
464
        let qtype: DnsQType = (*self).into();
465
        qtype.id()
466
    }
467
}
468
469
#[cfg(test)]
470
mod testutils {
471
    use core::fmt::Debug;
472
    use arrayvec::ArrayVec;
473
    use crate::DNS_HEADER_SIZE;
474
    use super::*;
475
476
    pub(crate) fn parse_and_compare<
477
        'a,
478
        A: RDataParse<'a> + PartialEq + Debug,
479
    >(bytes: &'a [u8], expected: A) {
480
        let mut i = 0;
481
        let rdata = RData {
482
            buffer: bytes,
483
            pos: 0,
484
            len: bytes.len(),
485
            type_: DnsQType::ALL,
486
        };
487
        let parsed = A::parse(&rdata, &mut i).unwrap();
488
        assert_eq!(parsed, expected);
489
    }
490
491
    pub(crate) fn write_and_compare<
492
        const N: usize,
493
        A: WriteBytes + PartialEq + Debug,
494
    >(a: A, expected: &[u8; N])
495
        where
496
            [(); DNS_HEADER_SIZE + N]: Sized,
497
    {
498
        let mut message: DnsMessage<
499
            0, { DnsSection::Questions }, ArrayVec<u8, { DNS_HEADER_SIZE + N }>
500
        > = DnsMessage::new(ArrayVec::new()).unwrap();
501
        a.write(&mut message).unwrap();
502
        let buffer = message.complete().unwrap();
503
        assert_eq!(&buffer[DNS_HEADER_SIZE..], expected.as_slice());
504
    }
505
506
    macro_rules! parse_write_test_macro {
507
        (
508
            $byte_count:literal,
509
            [ $( $bytes:literal ),* $(,)? ],
510
            $struct_name:ident { $( $content:ident: $content_builder:expr ),* $(,)? } $(,)?
511
        ) => {
512
            parse_write_test!(
513
                $byte_count,
514
                [ $( $bytes ),* ],
515
                $struct_name { $( $content: $content_builder ),* },
516
                parse,
517
                write,
518
            );
519
        };
520
        (
521
            $byte_count:literal,
522
            [ $( $bytes:literal ),* $(,)? ],
523
            $struct_name:ident { $( $content:ident: $content_builder:expr ),* $(,)? },
524
            $parse_name:ident,
525
            $write_name:ident $(,)?
526
        ) => {
527
            #[test]
528
            fn $parse_name() {
529
                const BYTES: [u8; $byte_count] = [ $( $bytes ),* ];
530
                const STRUCT: $struct_name = $struct_name {
531
                    $( $content: $content_builder ),*
532
                };
533
534
                crate::rdata::testutils::parse_and_compare(&BYTES, STRUCT);
535
            }
536
537
            #[test]
538
            fn $write_name() {
539
                const BYTES: [u8; $byte_count] = [ $( $bytes ),* ];
540
                const STRUCT: $struct_name = $struct_name {
541
                    $( $content: $content_builder ),*
542
                };
543
544
                crate::rdata::testutils::write_and_compare(STRUCT, &BYTES);
545
            }
546
        };
547
    }
548
549
    pub(crate) use parse_write_test_macro as parse_write_test;
550
}
/mnt/h/flex-dns/src/rdata/a.rs
Line
Count
Source (jump to first uncovered line)
1
use core::net::Ipv4Addr;
2
3
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # A host address
9
/// This record is used to return a ipv4 address for a host
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct A {
12
    /// The host ipv4 address
13
    pub address: Ipv4Addr,
14
}
15
16
impl<'a> RDataParse<'a> for A {
17
    #[inline]
18
17
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
19
17
        Ok(Self { address: Ipv4Addr::parse(rdata, i)? })
20
17
    }
21
}
22
23
impl WriteBytes for A {
24
    #[inline]
25
0
    fn write<
26
0
        const PTR_STORAGE: usize,
27
0
        const DNS_SECTION: DnsSection,
28
0
        B: Buffer,
29
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
30
0
        self.address.write(message)
31
0
    }
32
}
33
34
impl A {
35
    #[inline(always)]
36
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
37
        Ok(4)
38
    }
39
}
40
41
#[cfg(test)]
42
mod test {
43
    use crate::rdata::testutils::parse_write_test;
44
45
    use super::*;
46
47
    parse_write_test!(
48
        4,
49
        [0x01, 0x02, 0x03, 0x04],
50
        A {
51
            address: Ipv4Addr::new(1, 2, 3, 4),
52
        },
53
    );
54
}
/mnt/h/flex-dns/src/rdata/aaaa.rs
Line
Count
Source (jump to first uncovered line)
1
use core::net::Ipv6Addr;
2
3
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # IPv6 address record
9
/// This record is used to return a IPv6 address for a host.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Aaaa {
12
    /// IPv6 address
13
    pub address: Ipv6Addr,
14
}
15
16
impl<'a> RDataParse<'a> for Aaaa {
17
    #[inline]
18
27
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
19
27
        Ok(Self { address: Ipv6Addr::parse(rdata, i)? })
20
27
    }
21
}
22
23
impl WriteBytes for Aaaa {
24
    #[inline]
25
0
    fn write<
26
0
        const PTR_STORAGE: usize,
27
0
        const DNS_SECTION: DnsSection,
28
0
        B: Buffer,
29
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
30
0
        self.address.write(message)
31
0
    }
32
}
33
34
impl Aaaa {
35
    #[inline(always)]
36
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
37
        Ok(16)
38
    }
39
}
40
41
#[cfg(test)]
42
mod test {
43
    use crate::rdata::testutils::parse_write_test;
44
45
    use super::*;
46
47
    parse_write_test!(
48
        16,
49
        [
50
            0x01, 0x02, 0x03, 0x04,
51
            0x01, 0x02, 0x03, 0x04,
52
            0x01, 0x02, 0x03, 0x04,
53
            0x01, 0x02, 0x03, 0x04,
54
        ],
55
        Aaaa {
56
            address: Ipv6Addr::new(
57
                0x0102, 0x0304,
58
                0x0102, 0x0304,
59
                0x0102, 0x0304,
60
                0x0102, 0x0304,
61
            )
62
        },
63
    );
64
}
/mnt/h/flex-dns/src/rdata/afsdb.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # AFS data base location
8
/// This record is used to locate a server that has a copy of the named AFS cell's database.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct AfsDb<'a> {
11
    /// The subtype of the record
12
    subtype: u16,
13
    /// The hostname of the server
14
    hostname: DnsName<'a>,
15
}
16
17
impl<'a> RDataParse<'a> for AfsDb<'a> {
18
    #[inline]
19
9
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
20
9
        let subtype = u16::parse(rdata.buffer, i)?;
21
8
        let hostname = DnsName::parse(rdata.buffer, i)?;
22
23
3
        Ok(Self {
24
3
            subtype,
25
3
            hostname,
26
3
        })
27
9
    }
28
}
29
30
impl<'a> WriteBytes for AfsDb<'a> {
31
    #[inline]
32
    fn write<
33
        const PTR_STORAGE: usize,
34
        const DNS_SECTION: DnsSection,
35
        B: Buffer,
36
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
37
0
        self.subtype.write(message)?;
38
0
        self.hostname.write(message)
39
0
    }
40
}
41
42
impl<'a> AfsDb<'a> {
43
    #[inline(always)]
44
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
45
        Ok(2 + self.hostname.byte_len()?)
46
    }
47
}
48
49
#[cfg(test)]
50
mod test {
51
    use crate::rdata::testutils::parse_write_test;
52
53
    use super::*;
54
55
    parse_write_test!(
56
        9,
57
        [
58
            0x00, 0x01, // subtype
59
            0x03, b'f', b'o', b'o', 0x01, b'b', // hostname
60
            0x00, // null terminator
61
        ],
62
        AfsDb {
63
            subtype: 1,
64
            hostname: unsafe { DnsName::from_bytes_unchecked(b"\x03foo\x01b\x00") },
65
        },
66
    );
67
}
/mnt/h/flex-dns/src/rdata/apl.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::{Parse, ParseData};
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Address prefix list record
8
/// This record is used to store a list of address prefixes.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Apl<'a> {
11
    /// The address family for the prefix.
12
    pub address_family: u8,
13
    /// The prefix length.
14
    pub prefix: u8,
15
    /// The negation flag.
16
    pub negation: bool,
17
    /// The address family specific data.
18
    pub data: Characters<'a>,
19
}
20
21
impl<'a> RDataParse<'a> for Apl<'a> {
22
    #[inline]
23
14
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24
14
        let bytes = rdata.parse_data();
25
14
        let address_family = u8::parse(rdata.buffer, i)?;
26
13
        let prefix = u8::parse(rdata.buffer, i)?;
27
12
        let length = u8::parse(rdata.buffer, i)?;
28
11
        let negation = length & 0x80 != 0;
29
11
        let length = length & 0x7F;
30
11
31
11
        if bytes.len() < *i + length as usize {
32
3
            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
33
8
        }
34
35
8
        let data = Characters::new(&rdata.buffer[*i..*i + length as usize])?;
36
37
8
        Ok(Self {
38
8
            address_family,
39
8
            prefix,
40
8
            negation,
41
8
            data,
42
8
        })
43
14
    }
44
}
45
46
impl<'a> WriteBytes for Apl<'a> {
47
    #[inline]
48
    fn write<
49
        const PTR_STORAGE: usize,
50
        const DNS_SECTION: DnsSection,
51
        B: Buffer,
52
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
53
0
        self.address_family.write(message)?;
54
0
        self.prefix.write(message)?;
55
56
0
        let mut length = self.data.as_ref().len() as u8;
57
0
        if self.negation {
58
0
            length |= 0x80;
59
0
        }
60
61
0
        length.write(message)?;
62
0
        message.write_bytes(self.data.as_ref())
63
0
    }
64
}
65
66
impl<'a> Apl<'a> {
67
    #[inline(always)]
68
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
69
        Ok(3 + self.data.as_ref().len())
70
    }
71
}
72
73
#[cfg(test)]
74
mod test {
75
    use crate::rdata::testutils::parse_write_test;
76
77
    use super::*;
78
79
    parse_write_test!(
80
        6,
81
        [
82
            0x01, // address family
83
            0x02, // prefix
84
            0x03, // length
85
            0x01, 0x02, 0x03, // data
86
        ],
87
        Apl {
88
            address_family: 0x01,
89
            prefix: 0x02,
90
            negation: false,
91
            data: unsafe { Characters::new_unchecked(&[0x01, 0x02, 0x03]) },
92
        }
93
    );
94
    parse_write_test!(
95
        6,
96
        [
97
            0x01, // address family
98
            0x02, // prefix
99
            0x83, // length
100
            0x01, 0x02, 0x03, // data
101
        ],
102
        Apl {
103
            address_family: 0x01,
104
            prefix: 0x02,
105
            negation: true,
106
            data: unsafe { Characters::new_unchecked(&[0x01, 0x02, 0x03]) },
107
        },
108
        parse_negation,
109
        write_negation,
110
    );
111
}
/mnt/h/flex-dns/src/rdata/axfr.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Authoritative zone transfer record (AXFR)
8
/// This record is used to transfer an entire zone from a primary server to a
9
/// secondary server.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct AXfr<'a> {
12
    /// The domain name of the name server that was the
13
    /// original or primary source of data for this zone
14
    pub mname: DnsName<'a>,
15
    /// A domain name which specifies the mailbox of the
16
    /// person responsible for this zone
17
    pub rname: DnsName<'a>,
18
    /// The unsigned 32 bit version number of the original copy
19
    /// of the zone. Zone transfers preserve this value. This
20
    /// value wraps and should be compared using sequence space
21
    /// arithmetic
22
    pub serial: u32,
23
    /// A 32 bit time interval before the zone should be
24
    /// refreshed
25
    pub refresh: u32,
26
    /// A 32 bit time interval that should elapse before a
27
    /// failed refresh should be retried
28
    pub retry: u32,
29
    /// A 32 bit time value that specifies the upper limit on
30
    /// the time interval that can elapse before the zone is no
31
    /// longer authoritative
32
    pub expire: u32,
33
    /// The unsigned 32 bit minimum TTL field that should be
34
    /// exported with any RR from this zone
35
    pub minimum: u32,
36
}
37
38
impl<'a> RDataParse<'a> for AXfr<'a> {
39
    #[inline]
40
23
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
41
23
        let mname = DnsName::parse(rdata.buffer, i)?;
42
18
        let rname = DnsName::parse(rdata.buffer, i)?;
43
10
        let serial = u32::parse(rdata.buffer, i)?;
44
6
        let refresh = u32::parse(rdata.buffer, i)?;
45
5
        let retry = u32::parse(rdata.buffer, i)?;
46
5
        let expire = u32::parse(rdata.buffer, i)?;
47
5
        let minimum = u32::parse(rdata.buffer, i)?;
48
49
5
        Ok(Self {
50
5
            mname,
51
5
            rname,
52
5
            serial,
53
5
            refresh,
54
5
            retry,
55
5
            expire,
56
5
            minimum,
57
5
        })
58
23
    }
59
}
60
61
impl<'a> WriteBytes for AXfr<'a> {
62
    #[inline]
63
    fn write<
64
        const PTR_STORAGE: usize,
65
        const DNS_SECTION: DnsSection,
66
        B: Buffer,
67
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
68
0
        self.mname.write(message)?;
69
0
        self.rname.write(message)?;
70
0
        self.serial.write(message)?;
71
0
        self.refresh.write(message)?;
72
0
        self.retry.write(message)?;
73
0
        self.expire.write(message)?;
74
0
        self.minimum.write(message)
75
0
    }
76
}
77
78
impl<'a> AXfr<'a> {
79
    #[inline(always)]
80
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
81
        Ok(self.mname.byte_len()? + self.rname.byte_len()? + 20)
82
    }
83
}
84
85
#[cfg(test)]
86
mod test {
87
    use crate::rdata::testutils::parse_write_test;
88
89
    use super::*;
90
91
    parse_write_test!(
92
        45,
93
        [
94
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e', 0x03, b'c', b'o', b'm', 0x00, // example.com
95
            0x06, b'g', b'o', b'o', b'g', b'l', b'e', 0x03, b'c', b'o', b'm', 0x00, // google.com
96
            0x00, 0x00, 0x00, 0x01, // Serial
97
            0x00, 0x00, 0x00, 0x02, // Refresh
98
            0x00, 0x00, 0x00, 0x03, // Retry
99
            0x00, 0x00, 0x00, 0x04, // Expire
100
            0x00, 0x00, 0x00, 0x05, // Minimum
101
        ],
102
        AXfr {
103
            mname: unsafe { DnsName::from_bytes_unchecked(b"\x07example\x03com\x00") },
104
            rname: unsafe { DnsName::from_bytes_unchecked(b"\x06google\x03com\x00") },
105
            serial: 1,
106
            refresh: 2,
107
            retry: 3,
108
            expire: 4,
109
            minimum: 5,
110
        }
111
    );
112
}
/mnt/h/flex-dns/src/rdata/caa.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Certificate authority authorization record (CAA)
8
/// This record is used to specify which certificate authorities (CAs) are
9
/// allowed to issue certificates for a domain.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Caa<'a> {
12
    /// The flags field is used to specify critical CAA flags.
13
    pub flags: u8,
14
    /// The tag field is used to specify the property represented by the record.
15
    pub tag: Characters<'a>,
16
    /// The value field is used to specify the value of the property.
17
    pub value: Characters<'a>,
18
}
19
20
impl<'a> RDataParse<'a> for Caa<'a> {
21
    #[inline]
22
27
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
23
27
        let flags = u8::parse(rdata, i)?;
24
26
        let tag = Characters::parse(rdata, i)?;
25
16
        let value = Characters::parse(rdata, i)?;
26
27
11
        Ok(Self {
28
11
            flags,
29
11
            tag,
30
11
            value,
31
11
        })
32
27
    }
33
}
34
35
impl<'a> WriteBytes for Caa<'a> {
36
    #[inline]
37
    fn write<
38
        const PTR_STORAGE: usize,
39
        const DNS_SECTION: DnsSection,
40
        B: Buffer,
41
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
42
0
        self.flags.write(message)?;
43
0
        self.tag.write(message)?;
44
0
        self.value.write(message)
45
0
    }
46
}
47
48
impl<'a> Caa<'a> {
49
    #[inline(always)]
50
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
51
        Ok(1 + self.tag.byte_len()? + self.value.byte_len()?)
52
    }
53
}
54
55
#[cfg(test)]
56
mod test {
57
    use crate::rdata::testutils::parse_write_test;
58
59
    use super::*;
60
61
    parse_write_test!(
62
        23,
63
        [
64
            0x42, // flags
65
            0x05, // tag length
66
            b'i', b's', b's', b'u', b'e', // tag
67
            0x0f, // value length
68
            b'w', b'w', b'w', b'.', b'e', b'x', b'a', b'm', b'p', b'l', b'e', b't',
69
            b'e', b's', b't', // value
70
        ],
71
        Caa {
72
            flags: 0x42,
73
            tag: unsafe { Characters::new_unchecked(b"issue") },
74
            value: unsafe { Characters::new_unchecked(b"www.exampletest") },
75
        },
76
    );
77
}
/mnt/h/flex-dns/src/rdata/cdnskey.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Child DNS Key (CDNSKEY) Record
8
/// This record is
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct CdnsKey<'a> {
11
    /// The flags field specifies various flags that control the security
12
    /// related aspects of the key.
13
    pub flags: u16,
14
    /// The protocol field specifies the protocol for which the key is used.
15
    pub protocol: u8,
16
    /// The algorithm field specifies the public key's cryptographic algorithm
17
    pub algorithm: u8,
18
    /// The public key field holds the public key material.
19
    pub public_key: Characters<'a>
20
}
21
22
impl<'a> RDataParse<'a> for CdnsKey<'a> {
23
    #[inline]
24
10
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
25
10
        let flags = u16::parse(rdata, i)?;
26
10
        let protocol = u8::parse(rdata, i)?;
27
9
        let algorithm = u8::parse(rdata, i)?;
28
9
        let public_key = Characters::parse(rdata, i)?;
29
30
6
        Ok(Self {
31
6
            flags,
32
6
            protocol,
33
6
            algorithm,
34
6
            public_key
35
6
        })
36
10
    }
37
}
38
39
impl<'a> WriteBytes for CdnsKey<'a> {
40
    #[inline]
41
    fn write<
42
        const PTR_STORAGE: usize,
43
        const DNS_SECTION: DnsSection,
44
        B: Buffer,
45
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
46
0
        self.flags.write(message)?;
47
0
        self.protocol.write(message)?;
48
0
        self.algorithm.write(message)?;
49
0
        self.public_key.write(message)
50
0
    }
51
}
52
53
impl<'a> CdnsKey<'a> {
54
    #[inline(always)]
55
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
56
        Ok(4 + self.public_key.byte_len()?)
57
    }
58
}
59
60
#[cfg(test)]
61
mod test {
62
    use crate::rdata::testutils::parse_write_test;
63
64
    use super::*;
65
66
    parse_write_test!(
67
        5,
68
        [
69
            0x01, 0x02, // flags
70
            0x03, // protocol
71
            0x04, // algorithm
72
            0x00, // public key
73
        ],
74
        CdnsKey {
75
            flags: 0x0102,
76
            protocol: 0x03,
77
            algorithm: 0x04,
78
            public_key: unsafe { Characters::new_unchecked(&[]) },
79
        },
80
    );
81
}
/mnt/h/flex-dns/src/rdata/cds.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Child Delegation Signer (CDS) Record
8
/// This record is used to publish the key tag, algorithm, and digest type
9
/// used in the DS record of a child zone.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Cds<'a> {
12
    /// The key tag of the key that is being published.
13
    pub key_tag: u16,
14
    /// The algorithm of the key that is being published.
15
    pub algorithm: u8,
16
    /// The digest type of the key that is being published.
17
    pub digest_type: u8,
18
    /// The digest of the key that is being published.
19
    pub digest: Characters<'a>,
20
}
21
22
impl<'a> RDataParse<'a> for Cds<'a> {
23
    #[inline]
24
2
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
25
2
        let key_tag = u16::parse(rdata, i)?;
26
2
        let algorithm = u8::parse(rdata, i)?;
27
2
        let digest_type = u8::parse(rdata, i)?;
28
2
        let digest = Characters::parse(rdata, i)?;
29
30
1
        Ok(Self {
31
1
            key_tag,
32
1
            algorithm,
33
1
            digest_type,
34
1
            digest,
35
1
        })
36
2
    }
37
}
38
39
impl<'a> WriteBytes for Cds<'a> {
40
    #[inline]
41
    fn write<
42
        const PTR_STORAGE: usize,
43
        const DNS_SECTION: DnsSection,
44
        B: Buffer,
45
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
46
0
        self.key_tag.write(message)?;
47
0
        self.algorithm.write(message)?;
48
0
        self.digest_type.write(message)?;
49
0
        self.digest.write(message)
50
0
    }
51
}
52
53
impl<'a> Cds<'a> {
54
    #[inline(always)]
55
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
56
        Ok(4 + self.digest.byte_len()?)
57
    }
58
}
59
60
#[cfg(test)]
61
mod test {
62
    use crate::rdata::testutils::parse_write_test;
63
64
    use super::*;
65
66
    parse_write_test!(
67
        5,
68
        [ 0x00, 0x01, 0x08, 0x01, 0x00 ],
69
        Cds {
70
            key_tag: 1,
71
            algorithm: 8,
72
            digest_type: 1,
73
            digest: unsafe { Characters::new_unchecked(&[]) },
74
        },
75
    );
76
}
/mnt/h/flex-dns/src/rdata/cert.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Certificate record
8
/// This record lists the certificates used by the owner of the domain
9
/// name to sign other records in the zone.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Cert<'a> {
12
    /// The type of certificate.
13
    pub cert_type: u16,
14
    /// The key tag of the certificate.
15
    pub key_tag: u16,
16
    /// The algorithm used to sign the certificate.
17
    pub algorithm: u8,
18
    /// The certificate data.
19
    pub certificate: Characters<'a>,
20
}
21
22
impl<'a> RDataParse<'a> for Cert<'a> {
23
    #[inline]
24
27
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
25
27
        let cert_type = u16::parse(rdata.buffer, i)?;
26
25
        let key_tag = u16::parse(rdata.buffer, i)?;
27
22
        let algorithm = u8::parse(rdata.buffer, i)?;
28
21
        let certificate = Characters::parse(rdata.buffer, i)?;
29
30
12
        Ok(Self {
31
12
            cert_type,
32
12
            key_tag,
33
12
            algorithm,
34
12
            certificate,
35
12
        })
36
27
    }
37
}
38
39
impl<'a> WriteBytes for Cert<'a> {
40
    #[inline]
41
    fn write<
42
        const PTR_STORAGE: usize,
43
        const DNS_SECTION: DnsSection,
44
        B: Buffer,
45
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
46
0
        self.cert_type.write(message)?;
47
0
        self.key_tag.write(message)?;
48
0
        self.algorithm.write(message)?;
49
0
        self.certificate.write(message)
50
0
    }
51
}
52
53
impl<'a> Cert<'a> {
54
    #[inline(always)]
55
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
56
        Ok(5 + self.certificate.byte_len()?)
57
    }
58
}
59
60
#[cfg(test)]
61
mod test {
62
    use crate::rdata::testutils::parse_write_test;
63
64
    use super::*;
65
66
    parse_write_test!(
67
        6,
68
        [
69
            0x00, 0x01, // cert type
70
            0x02, 0x03, // key tag
71
            0x04, // algorithm
72
            0x00, // certificate length
73
        ],
74
        Cert {
75
            cert_type: 1,
76
            key_tag: 0x0203,
77
            algorithm: 4,
78
            certificate: unsafe { Characters::new_unchecked(&[]) },
79
        },
80
    );
81
}
/mnt/h/flex-dns/src/rdata/cname.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # The canonical name for an alias
8
/// This record is used to return a canonical name for an alias
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct CName<'a> {
11
    /// The canonical name for the alias
12
    name: DnsName<'a>,
13
}
14
15
impl<'a> RDataParse<'a> for CName<'a> {
16
    #[inline]
17
41
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
18
41
        Ok(Self {
19
41
            name: DnsName::parse(rdata.buffer, i)?,
20
        })
21
41
    }
22
}
23
24
impl<'a> WriteBytes for CName<'a> {
25
    #[inline]
26
0
    fn write<
27
0
        const PTR_STORAGE: usize,
28
0
        const DNS_SECTION: DnsSection,
29
0
        B: Buffer,
30
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
31
0
        self.name.write(message)
32
0
    }
33
}
34
35
impl<'a> CName<'a> {
36
    #[inline(always)]
37
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
38
        self.name.byte_len()
39
    }
40
}
41
42
#[cfg(test)]
43
mod test {
44
    use crate::rdata::testutils::parse_write_test;
45
46
    use super::*;
47
48
    parse_write_test!(
49
        14,
50
        [
51
            3, b'w', b'w', b'w',
52
            4, b't', b'e', b's', b't',
53
            3, b'c', b'o', b'm',
54
            0
55
        ],
56
        CName {
57
            name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x04test\x03com\x00") },
58
        },
59
    );
60
}
/mnt/h/flex-dns/src/rdata/csync.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Child-to-Parent Synchronization (CSYNC) Record
8
/// This record type is used to publish the synchronization state of a child zone to its parent zone.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct CSync<'a> {
11
    /// serial is the serial number of the zone
12
    pub serial: u32,
13
    /// flags is a bitmap of flags (see [RFC 7477](https://tools.ietf.org/html/rfc7477))
14
    pub flags: u16,
15
    /// type_bit_maps is the set of RRset types present at the next owner name in the zone
16
    pub type_bit_maps: Characters<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for CSync<'a> {
20
    #[inline]
21
20
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
20
        let serial = u32::parse(rdata, i)?;
23
17
        let flags = u16::parse(rdata, i)?;
24
16
        let type_bit_maps = Characters::parse(rdata, i)?;
25
26
13
        Ok(Self {
27
13
            serial,
28
13
            flags,
29
13
            type_bit_maps
30
13
        })
31
20
    }
32
}
33
34
impl<'a> WriteBytes for CSync<'a> {
35
    #[inline]
36
    fn write<
37
        const PTR_STORAGE: usize,
38
        const DNS_SECTION: DnsSection,
39
        B: Buffer,
40
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
41
0
        self.serial.write(message)?;
42
0
        self.flags.write(message)?;
43
0
        self.type_bit_maps.write(message)
44
0
    }
45
}
46
47
impl<'a> CSync<'a> {
48
    #[inline(always)]
49
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
50
        Ok(6 + self.type_bit_maps.byte_len()?)
51
    }
52
}
53
54
#[cfg(test)]
55
mod test {
56
    use crate::rdata::testutils::parse_write_test;
57
58
    use super::*;
59
60
    parse_write_test!(
61
        10,
62
        [
63
            0x00, 0x01, 0x02, 0x03, // serial
64
            0x10, 0x01, // flags
65
            3, b'w', b'w', b'w', // type_bit_maps
66
        ],
67
        CSync {
68
            serial: 0x00010203,
69
            flags: 0x1001,
70
            type_bit_maps: unsafe { Characters::new_unchecked(b"www") },
71
        },
72
    );
73
}
/mnt/h/flex-dns/src/rdata/dhcid.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Dynamic host configuration protocol record
8
/// This record is used to store DHCP information.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct DhcId<'a> {
11
    /// The identifier type.
12
    pub type_: u16,
13
    /// The digest type.
14
    pub digest_type: u8,
15
    /// The digest of the DHCP information.
16
    pub digest: Characters<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for DhcId<'a> {
20
    #[inline]
21
26
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
26
        let type_ = u16::parse(rdata, i)?;
23
25
        let digest_type = u8::parse(rdata, i)?;
24
24
        let digest = Characters::parse(rdata, i)?;
25
26
14
        Ok(Self {
27
14
            type_,
28
14
            digest_type,
29
14
            digest,
30
14
        })
31
26
    }
32
}
33
34
impl<'a> WriteBytes for DhcId<'a> {
35
    #[inline]
36
    fn write<
37
        const PTR_STORAGE: usize,
38
        const DNS_SECTION: DnsSection,
39
        B: Buffer,
40
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
41
0
        self.type_.write(message)?;
42
0
        self.digest_type.write(message)?;
43
0
        self.digest.write(message)
44
0
    }
45
}
46
47
impl<'a> DhcId<'a> {
48
    #[inline(always)]
49
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
50
        Ok(3 + self.digest.byte_len()?)
51
    }
52
}
53
54
#[cfg(test)]
55
mod test {
56
    use crate::rdata::testutils::parse_write_test;
57
58
    use super::*;
59
60
    parse_write_test!(
61
        7,
62
        [
63
            0x00, 0x0e, // type
64
            0x03, // digest type
65
            0x03, // digest len
66
            b'w', b'w', b'w', // digest
67
        ],
68
        DhcId {
69
            type_: 14,
70
            digest_type: 3,
71
            digest: unsafe { Characters::new_unchecked(b"www") },
72
        },
73
    );
74
}
/mnt/h/flex-dns/src/rdata/dlv.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # DNSSEC lookaside validation record (DLV)
8
/// This record is used to publish the public key of a DNSSEC lookaside validation
9
/// (DLV) trust anchor.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Dlv<'a> {
12
    /// key_tag is a mechanism for quickly identifying the signing key in a zone
13
    pub key_tag: u16,
14
    /// algorithm is the algorithm of the key
15
    pub algorithm: u8,
16
    /// digest_type is the algorithm used to construct the digest
17
    pub digest_type: u8,
18
    /// digest is the digest of the public key
19
    pub digest: Characters<'a>,
20
}
21
22
impl<'a> RDataParse<'a> for Dlv<'a> {
23
    #[inline]
24
4
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
25
4
        let key_tag = u16::parse(rdata, i)?;
26
4
        let algorithm = u8::parse(rdata, i)?;
27
3
        let digest_type = u8::parse(rdata, i)?;
28
3
        let digest = Characters::parse(rdata, i)?;
29
30
3
        Ok(Self {
31
3
            key_tag,
32
3
            algorithm,
33
3
            digest_type,
34
3
            digest,
35
3
        })
36
4
    }
37
}
38
39
impl<'a> WriteBytes for Dlv<'a> {
40
    #[inline]
41
    fn write<
42
        const PTR_STORAGE: usize,
43
        const DNS_SECTION: DnsSection,
44
        B: Buffer,
45
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
46
0
        self.key_tag.write(message)?;
47
0
        self.algorithm.write(message)?;
48
0
        self.digest_type.write(message)?;
49
0
        self.digest.write(message)
50
0
    }
51
}
52
53
impl<'a> Dlv<'a> {
54
    #[inline(always)]
55
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
56
        Ok(4 + self.digest.byte_len()?)
57
    }
58
}
59
60
#[cfg(test)]
61
mod test {
62
    use crate::rdata::testutils::parse_write_test;
63
64
    use super::*;
65
66
    parse_write_test!(
67
        8,
68
        [
69
            0x00, 0x0e, // key_tag
70
            0x03, // algorithm
71
            0x03, // digest_type
72
            0x03, // digest len
73
            b'w', b'w', b'w', // digest
74
        ],
75
        Dlv {
76
            key_tag: 14,
77
            algorithm: 3,
78
            digest_type: 3,
79
            digest: unsafe { Characters::new_unchecked(b"www") },
80
        },
81
    );
82
}
/mnt/h/flex-dns/src/rdata/dname.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Delegation name record
8
/// This record is used to delegate a DNS zone to use the given authoritative
9
/// name servers.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct DName<'a> {
12
    /// The name of the delegated domain.
13
    pub name: DnsName<'a>,
14
}
15
16
impl<'a> RDataParse<'a> for DName<'a> {
17
    #[inline]
18
6
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
19
6
        let name = DnsName::parse(rdata.buffer, i)?;
20
21
4
        Ok(Self {
22
4
            name,
23
4
        })
24
6
    }
25
}
26
27
impl<'a> WriteBytes for DName<'a> {
28
    #[inline]
29
0
    fn write<
30
0
        const PTR_STORAGE: usize,
31
0
        const DNS_SECTION: DnsSection,
32
0
        B: Buffer,
33
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
34
0
        self.name.write(message)
35
0
    }
36
}
37
38
impl<'a> DName<'a> {
39
    #[inline(always)]
40
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
41
        self.name.byte_len()
42
    }
43
}
44
45
#[cfg(test)]
46
mod test {
47
    use crate::rdata::testutils::parse_write_test;
48
49
    use super::*;
50
51
    parse_write_test!(
52
        17,
53
        [
54
            0x03, b'w', b'w', b'w',
55
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
56
            0x03, b'c', b'o', b'm',
57
            0x00,
58
        ],
59
        DName {
60
            name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
61
        },
62
    );
63
}
/mnt/h/flex-dns/src/rdata/dnskey.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # DNS key record
8
/// This record is used to store public keys that are associated with a zone.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct DnsKey<'a> {
11
    /// The flags field specifies various flags that control the security
12
    /// related aspects of the key.
13
    pub flags: u16,
14
    /// The protocol field specifies the protocol for which the key is used.
15
    pub protocol: u8,
16
    /// The algorithm field specifies the public key's cryptographic algorithm
17
    pub algorithm: u8,
18
    /// The public key field holds the public key material.
19
    pub public_key: Characters<'a>
20
}
21
22
impl<'a> RDataParse<'a> for DnsKey<'a> {
23
    #[inline]
24
3
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
25
3
        let flags = u16::parse(rdata, i)?;
26
3
        let protocol = u8::parse(rdata, i)?;
27
3
        let algorithm = u8::parse(rdata, i)?;
28
3
        let public_key = Characters::parse(rdata, i)?;
29
30
2
        Ok(DnsKey {
31
2
            flags,
32
2
            protocol,
33
2
            algorithm,
34
2
            public_key
35
2
        })
36
3
    }
37
}
38
39
impl<'a> WriteBytes for DnsKey<'a> {
40
    #[inline]
41
    fn write<
42
        const PTR_STORAGE: usize,
43
        const DNS_SECTION: DnsSection,
44
        B: Buffer,
45
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
46
0
        self.flags.write(message)?;
47
0
        self.protocol.write(message)?;
48
0
        self.algorithm.write(message)?;
49
0
        self.public_key.write(message)
50
0
    }
51
}
52
53
impl<'a> DnsKey<'a> {
54
    #[inline(always)]
55
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
56
        Ok(4 + self.public_key.byte_len()?)
57
    }
58
}
59
60
#[cfg(test)]
61
mod test {
62
    use crate::rdata::testutils::parse_write_test;
63
64
    use super::*;
65
66
    parse_write_test!(
67
        8,
68
        [
69
            0x0f, 0x0e, // flags
70
            0x5c, // protocol
71
            0x8a, // algorithm
72
            0x03, // public key length
73
            b'w', b'w', b'w', // public key
74
        ],
75
        DnsKey {
76
            flags: 0x0f0e,
77
            protocol: 0x5c,
78
            algorithm: 0x8a,
79
            public_key: unsafe { Characters::new_unchecked(b"www") },
80
        },
81
    );
82
}
/mnt/h/flex-dns/src/rdata/ds.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Delegation signer record
8
/// This record is used to store a cryptographic hash of a DNSKEY record.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Ds<'a> {
11
    /// The key tag of the DNSKEY record.
12
    pub key_tag: u16,
13
    /// The algorithm of the DNSKEY record.
14
    pub algorithm: u8,
15
    /// The digest type of the DNSKEY record.
16
    pub digest_type: u8,
17
    /// The digest of the DNSKEY record.
18
    pub digest: Characters<'a>,
19
}
20
21
impl<'a> RDataParse<'a> for Ds<'a> {
22
    #[inline]
23
16
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24
16
        let key_tag = u16::parse(rdata.buffer, i)?;
25
15
        let algorithm = u8::parse(rdata.buffer, i)?;
26
14
        let digest_type = u8::parse(rdata.buffer, i)?;
27
13
        let digest = Characters::parse(rdata.buffer, i)?;
28
29
5
        Ok(Ds {
30
5
            key_tag,
31
5
            algorithm,
32
5
            digest_type,
33
5
            digest,
34
5
        })
35
16
    }
36
}
37
38
impl<'a> WriteBytes for Ds<'a> {
39
    #[inline]
40
    fn write<
41
        const PTR_STORAGE: usize,
42
        const DNS_SECTION: DnsSection,
43
        B: Buffer,
44
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
45
0
        self.key_tag.write(message)?;
46
0
        self.algorithm.write(message)?;
47
0
        self.digest_type.write(message)?;
48
0
        self.digest.write(message)
49
0
    }
50
}
51
52
impl<'a> Ds<'a> {
53
    #[inline(always)]
54
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
55
        Ok(4 + self.digest.byte_len()?)
56
    }
57
}
58
59
#[cfg(test)]
60
mod test {
61
    use crate::rdata::testutils::parse_write_test;
62
63
    use super::*;
64
65
    parse_write_test!(
66
        8,
67
        [
68
            0x0c, 0x07, // key tag
69
            0x83, // algorithm
70
            0x73, // digest type
71
            0x03, // digest len
72
            b'w', b'w', b'w', // digest
73
        ],
74
        Ds {
75
            key_tag: 0x0c07,
76
            algorithm: 0x83,
77
            digest_type: 0x73,
78
            digest: unsafe { Characters::new_unchecked(b"www") },
79
        },
80
    );
81
}
/mnt/h/flex-dns/src/rdata/eui48.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::parse::Parse;
3
use crate::rdata::{RData, RDataParse};
4
use crate::write::WriteBytes;
5
6
/// # MAC address record (EUI-48)
7
/// This record is used to translate between a 48-bit MAC address used by the
8
/// IEEE 802 protocol family and a fully qualified domain name.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct EUI48 {
11
    /// mac_address is the MAC address
12
    pub mac_address: [u8; 6],
13
}
14
15
impl<'a> RDataParse<'a> for EUI48 {
16
    #[inline]
17
3
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
18
3
        let mac_address = <[u8; 6]>::parse(rdata, i)?;
19
20
1
        Ok(Self {
21
1
            mac_address,
22
1
        })
23
3
    }
24
}
25
26
impl<'a> WriteBytes for EUI48 {
27
    #[inline]
28
0
    fn write<
29
0
        const PTR_STORAGE: usize,
30
0
        const DNS_SECTION: DnsSection,
31
0
        B: Buffer,
32
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
33
0
        self.mac_address.write(message)
34
0
    }
35
}
36
37
impl EUI48 {
38
    #[inline(always)]
39
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
40
        Ok(6)
41
    }
42
}
43
44
#[cfg(test)]
45
mod test {
46
    use crate::rdata::testutils::parse_write_test;
47
48
    use super::*;
49
50
    parse_write_test!(
51
        6,
52
        [
53
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06
54
        ],
55
        EUI48 {
56
            mac_address: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06],
57
        },
58
    );
59
}
/mnt/h/flex-dns/src/rdata/eui64.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::parse::Parse;
3
use crate::rdata::{RData, RDataParse};
4
use crate::write::WriteBytes;
5
6
/// # MAC address record (EUI-64)
7
/// This record is used to translate between a 64-bit MAC address used by the
8
/// IEEE 802 protocol family and a fully qualified domain name.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct EUI64 {
11
    /// mac_address is the MAC address
12
    pub mac_address: [u8; 8],
13
}
14
15
impl<'a> RDataParse<'a> for EUI64 {
16
    #[inline]
17
3
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
18
3
        let mac_address = <[u8; 8]>::parse(rdata, i)?;
19
20
2
        Ok(Self {
21
2
            mac_address,
22
2
        })
23
3
    }
24
}
25
26
impl<'a> WriteBytes for EUI64 {
27
    #[inline]
28
0
    fn write<
29
0
        const PTR_STORAGE: usize,
30
0
        const DNS_SECTION: DnsSection,
31
0
        B: Buffer,
32
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
33
0
        self.mac_address.write(message)
34
0
    }
35
}
36
37
impl EUI64 {
38
    #[inline(always)]
39
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
40
        Ok(8)
41
    }
42
}
43
44
#[cfg(test)]
45
mod test {
46
    use crate::rdata::testutils::parse_write_test;
47
48
    use super::*;
49
50
    parse_write_test!(
51
        8,
52
        [
53
            0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
54
            0x07, 0x08,
55
        ],
56
        EUI64 {
57
            mac_address: [
58
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
59
            ],
60
        },
61
    );
62
}
/mnt/h/flex-dns/src/rdata/hinfo.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Host information
8
/// This record is used to return host information
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct HInfo<'a> {
11
    /// The CPU type
12
    cpu: Characters<'a>,
13
    /// The OS type
14
    os: Characters<'a>,
15
}
16
17
impl<'a> RDataParse<'a> for HInfo<'a> {
18
    #[inline]
19
10
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
20
10
        let cpu = Characters::parse(rdata, i)?;
21
8
        let os = Characters::parse(rdata, i)?;
22
23
2
        Ok(Self {
24
2
            cpu,
25
2
            os,
26
2
        })
27
10
    }
28
}
29
30
impl<'a> WriteBytes for HInfo<'a> {
31
    #[inline]
32
    fn write<
33
        const PTR_STORAGE: usize,
34
        const DNS_SECTION: DnsSection,
35
        B: Buffer,
36
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
37
0
        self.cpu.write(message)?;
38
0
        self.os.write(message)
39
0
    }
40
}
41
42
impl<'a> HInfo<'a> {
43
    #[inline(always)]
44
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
45
        Ok(self.cpu.byte_len()? + self.os.byte_len()?)
46
    }
47
}
48
49
#[cfg(test)]
50
mod test {
51
    use crate::rdata::testutils::parse_write_test;
52
53
    use super::*;
54
55
    parse_write_test!(
56
        8,
57
        [
58
            3, b'w', b'w', b'w',
59
            3, b'c', b'o', b'm',
60
        ],
61
        HInfo {
62
            cpu: unsafe { Characters::new_unchecked(b"www") },
63
            os: unsafe { Characters::new_unchecked(b"com") },
64
        },
65
    );
66
}
/mnt/h/flex-dns/src/rdata/hip.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Host identity protocol (HIP) Record
8
/// This record is used to associate a HIP public key with a domain name.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Hip<'a> {
11
    /// The usage field is an 8-bit value that defines the semantics of the
12
    /// certificate association data field.
13
    pub usage: u8,
14
    /// The selector field is an 8-bit value that defines the type of data in the
15
    /// certificate association data field.
16
    pub selector: u8,
17
    /// The matching type field is an 8-bit value that defines the semantics of
18
    /// the certificate association data field.
19
    pub matching_type: u8,
20
    /// The certificate association data field is a variable-length string of octets
21
    /// that contains the certificate association data.
22
    pub certificate_association_data: Characters<'a>,
23
}
24
25
impl<'a> RDataParse<'a> for Hip<'a> {
26
    #[inline]
27
5
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
28
5
        let usage = u8::parse(rdata, i)?;
29
4
        let selector = u8::parse(rdata, i)?;
30
4
        let matching_type = u8::parse(rdata, i)?;
31
4
        let certificate_association_data = Characters::parse(rdata, i)?;
32
33
4
        Ok(Self {
34
4
            usage,
35
4
            selector,
36
4
            matching_type,
37
4
            certificate_association_data,
38
4
        })
39
5
    }
40
}
41
42
impl<'a> WriteBytes for Hip<'a> {
43
    #[inline]
44
    fn write<
45
        const PTR_STORAGE: usize,
46
        const DNS_SECTION: DnsSection,
47
        B: Buffer,
48
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
49
0
        self.usage.write(message)?;
50
0
        self.selector.write(message)?;
51
0
        self.matching_type.write(message)?;
52
0
        self.certificate_association_data.write(message)
53
0
    }
54
}
55
56
impl<'a> Hip<'a> {
57
    #[inline(always)]
58
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
59
        Ok(3 + self.certificate_association_data.byte_len()?)
60
    }
61
}
62
63
#[cfg(test)]
64
mod test {
65
    use crate::rdata::testutils::parse_write_test;
66
67
    use super::*;
68
69
    parse_write_test!(
70
        7,
71
        [
72
            0x0e, // usage
73
            0x63, // selector
74
            0x43, // matching type
75
            0x03, // digest len
76
            b'w', b'w', b'w', // digest
77
        ],
78
        Hip {
79
            usage: 14,
80
            selector: 99,
81
            matching_type: 67,
82
            certificate_association_data: unsafe { Characters::new_unchecked(b"www") },
83
        },
84
    );
85
}
/mnt/h/flex-dns/src/rdata/https.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # HTTPs certificate record (HTTPS)
9
/// This record is used to describe the parameters of a service binding.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Https<'a> {
12
    /// The priority of this target host
13
    pub priority: u16,
14
    /// The relative weight for entries with the same priority
15
    pub weight: u16,
16
    /// The TCP or UDP port on which the service is to be found
17
    pub port: u16,
18
    /// The domain name of the target host
19
    pub target: DnsName<'a>,
20
    /// The parameters of the service binding
21
    pub parameters: Characters<'a>,
22
}
23
24
impl<'a> RDataParse<'a> for Https<'a> {
25
    #[inline]
26
4
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
27
4
        let priority = u16::parse(rdata, i)?;
28
4
        let weight = u16::parse(rdata, i)?;
29
4
        let port = u16::parse(rdata, i)?;
30
4
        let target = DnsName::parse(rdata, i)?;
31
4
        let parameters = Characters::parse(rdata, i)?;
32
33
3
        Ok(Self {
34
3
            priority,
35
3
            weight,
36
3
            port,
37
3
            target,
38
3
            parameters
39
3
        })
40
4
    }
41
}
42
43
impl<'a> WriteBytes for Https<'a> {
44
    #[inline]
45
    fn write<
46
        const PTR_STORAGE: usize,
47
        const DNS_SECTION: DnsSection,
48
        B: Buffer,
49
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
50
0
        self.priority.write(message)?;
51
0
        self.weight.write(message)?;
52
0
        self.port.write(message)?;
53
0
        self.target.write(message)?;
54
0
        self.parameters.write(message)
55
0
    }
56
}
57
58
impl<'a> Https<'a> {
59
    #[inline(always)]
60
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
61
        Ok(6 + self.target.byte_len()? + self.parameters.byte_len()?)
62
    }
63
}
64
65
#[cfg(test)]
66
mod test {
67
    use crate::rdata::testutils::parse_write_test;
68
69
    use super::*;
70
71
    parse_write_test!(
72
        15,
73
        [
74
            0x00, 0x0e, // priority
75
            0x00, 0x0e, // weight
76
            0x00, 0x0e, // port
77
            0x03, // length of "www"
78
            b'w', b'w', b'w', // "www"
79
            0x00, // end of name
80
            0x03, // length of "www"
81
            b'w', b'w', b'w', // "www"
82
        ],
83
        Https {
84
            priority: 14,
85
            weight: 14,
86
            port: 14,
87
            target: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
88
            parameters: unsafe { Characters::new_unchecked(b"www") },
89
        },
90
    );
91
}
/mnt/h/flex-dns/src/rdata/ipseckey.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # IPsec key record
8
/// This record is used to store a public key that is associated with a domain name.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct IpSecKey<'a> {
11
    /// The precedence of the key.
12
    pub precedence: u16,
13
    /// The gateway type.
14
    pub gateway_type: u8,
15
    /// The algorithm used for the key.
16
    pub algorithm: u8,
17
    /// The gateway data.
18
    pub gateway: Characters<'a>,
19
    /// The public key data.
20
    pub public_key: Characters<'a>,
21
}
22
23
impl<'a> RDataParse<'a> for IpSecKey<'a> {
24
    #[inline]
25
35
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
26
35
        let precedence = u16::parse(rdata.buffer, i)?;
27
33
        let gateway_type = u8::parse(rdata.buffer, i)?;
28
32
        let algorithm = u8::parse(rdata.buffer, i)?;
29
31
        let gateway = Characters::parse(rdata.buffer, i)?;
30
18
        let public_key = Characters::parse(rdata.buffer, i)?;
31
32
13
        Ok(Self {
33
13
            precedence,
34
13
            gateway_type,
35
13
            algorithm,
36
13
            gateway,
37
13
            public_key,
38
13
        })
39
35
    }
40
}
41
42
impl<'a> WriteBytes for IpSecKey<'a> {
43
    #[inline]
44
    fn write<
45
        const PTR_STORAGE: usize,
46
        const DNS_SECTION: DnsSection,
47
        B: Buffer,
48
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
49
0
        self.precedence.write(message)?;
50
0
        self.gateway_type.write(message)?;
51
0
        self.algorithm.write(message)?;
52
0
        self.gateway.write(message)?;
53
0
        self.public_key.write(message)
54
0
    }
55
}
56
57
impl<'a> IpSecKey<'a> {
58
    #[inline(always)]
59
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
60
        Ok(4 + self.gateway.byte_len()? + self.public_key.byte_len()?)
61
    }
62
}
63
64
#[cfg(test)]
65
mod test {
66
    use crate::rdata::testutils::parse_write_test;
67
68
    use super::*;
69
70
    parse_write_test!(
71
        12,
72
        [
73
            0x01, 0x02, // precedence
74
            0x03, // gateway type
75
            0x04, // algorithm
76
            0x03, b'w', b'w', b'w', // gateway
77
            0x03, b'w', b'w', b'w', // public key
78
        ],
79
        IpSecKey {
80
            precedence: 0x0102,
81
            gateway_type: 0x03,
82
            algorithm: 0x04,
83
            gateway: unsafe { Characters::new_unchecked(b"www") },
84
            public_key: unsafe { Characters::new_unchecked(b"www") },
85
        },
86
    );
87
}
/mnt/h/flex-dns/src/rdata/ixfr.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Incremental zone transfer record (IXFR)
8
/// This record is used to transfer a portion of a zone from a primary server to
9
/// a secondary server.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct IXfr<'a> {
12
    /// The domain name of the name server that was the
13
    /// original or primary source of data for this zone
14
    pub mname: DnsName<'a>,
15
    /// A domain name which specifies the mailbox of the
16
    /// person responsible for this zone
17
    pub rname: DnsName<'a>,
18
    /// The unsigned 32 bit version number of the original copy
19
    /// of the zone. Zone transfers preserve this value. This
20
    /// value wraps and should be compared using sequence space
21
    /// arithmetic
22
    pub serial: u32,
23
    /// A 32 bit time interval before the zone should be
24
    /// refreshed
25
    pub refresh: u32,
26
    /// A 32 bit time interval that should elapse before a
27
    /// failed refresh should be retried
28
    pub retry: u32,
29
    /// A 32 bit time value that specifies the upper limit on
30
    /// the time interval that can elapse before the zone is no
31
    /// longer authoritative
32
    pub expire: u32,
33
    /// The unsigned 32 bit minimum TTL field that should be
34
    /// exported with any RR from this zone
35
    pub minimum: u32,
36
}
37
38
impl<'a> RDataParse<'a> for IXfr<'a> {
39
    #[inline]
40
8
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
41
8
        let mname = DnsName::parse(rdata.buffer, i)?;
42
7
        let rname = DnsName::parse(rdata.buffer, i)?;
43
6
        let serial = u32::parse(rdata.buffer, i)?;
44
4
        let refresh = u32::parse(rdata.buffer, i)?;
45
4
        let retry = u32::parse(rdata.buffer, i)?;
46
4
        let expire = u32::parse(rdata.buffer, i)?;
47
4
        let minimum = u32::parse(rdata.buffer, i)?;
48
49
4
        Ok(Self {
50
4
            mname,
51
4
            rname,
52
4
            serial,
53
4
            refresh,
54
4
            retry,
55
4
            expire,
56
4
            minimum,
57
4
        })
58
8
    }
59
}
60
61
impl<'a> WriteBytes for IXfr<'a> {
62
    #[inline]
63
    fn write<
64
        const PTR_STORAGE: usize,
65
        const DNS_SECTION: DnsSection,
66
        B: Buffer,
67
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
68
0
        self.mname.write(message)?;
69
0
        self.rname.write(message)?;
70
0
        self.serial.write(message)?;
71
0
        self.refresh.write(message)?;
72
0
        self.retry.write(message)?;
73
0
        self.expire.write(message)?;
74
0
        self.minimum.write(message)
75
0
    }
76
}
77
78
impl<'a> IXfr<'a> {
79
    #[inline(always)]
80
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
81
        Ok(self.mname.byte_len()? + self.rname.byte_len()? + 20)
82
    }
83
}
84
85
#[cfg(test)]
86
mod test {
87
    use crate::rdata::testutils::parse_write_test;
88
89
    use super::*;
90
91
    parse_write_test!(
92
        53,
93
        [
94
            3, b'w', b'w', b'w',
95
            7, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
96
            3, b'c', b'o', b'm',
97
            0,
98
            3, b'w', b'w', b'w',
99
            6, b'g', b'o', b'o', b'g', b'l', b'e',
100
            3, b'c', b'o', b'm',
101
            0,
102
            0x00, 0x00, 0x00, 0x01,
103
            0x00, 0x00, 0x0E, 0x10,
104
            0x00, 0x00, 0x03, 0x84,
105
            0x00, 0x09, 0x3A, 0x80,
106
            0x00, 0x00, 0x03, 0x84,
107
        ],
108
        IXfr {
109
            mname: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
110
            rname: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x06google\x03com\x00") },
111
            serial: 1,
112
            refresh: 3600,
113
            retry: 900,
114
            expire: 604800,
115
            minimum: 900,
116
        },
117
    );
118
}
/mnt/h/flex-dns/src/rdata/key.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Key
8
/// This record is used to store a public key that can be used to verify DNSSEC signatures
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Key<'a> {
11
    /// The flags field is used to store flags specific to the algorithm
12
    pub flags: u16,
13
    /// The protocol field is used to store the protocol number for which this key is used
14
    pub protocol: u8,
15
    /// The algorithm field is used to store the algorithm number for this key
16
    pub algorithm: u8,
17
    /// The public key is stored as a character string
18
    pub public_key: Characters<'a>,
19
}
20
21
impl<'a> RDataParse<'a> for Key<'a> {
22
    #[inline]
23
67
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24
67
        let flags = u16::parse(rdata, i)?;
25
66
        let protocol = u8::parse(rdata, i)?;
26
65
        let algorithm = u8::parse(rdata, i)?;
27
63
        let public_key = Characters::parse(rdata, i)?;
28
29
36
        Ok(Self {
30
36
            flags,
31
36
            protocol,
32
36
            algorithm,
33
36
            public_key,
34
36
        })
35
67
    }
36
}
37
38
impl<'a> WriteBytes for Key<'a> {
39
    #[inline]
40
    fn write<
41
        const PTR_STORAGE: usize,
42
        const DNS_SECTION: DnsSection,
43
        B: Buffer,
44
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
45
0
        self.flags.write(message)?;
46
0
        self.protocol.write(message)?;
47
0
        self.algorithm.write(message)?;
48
0
        self.public_key.write(message)
49
0
    }
50
}
51
52
impl<'a> Key<'a> {
53
    #[inline(always)]
54
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
55
        Ok(4 + self.public_key.byte_len()?)
56
    }
57
}
58
59
#[cfg(test)]
60
mod test {
61
    use crate::rdata::testutils::parse_write_test;
62
63
    use super::*;
64
65
    parse_write_test!(
66
        8,
67
        [
68
            0x00, 0x0e, // flags
69
            0xc4, // protocol
70
            0x4c, // algorithm
71
            0x03, // length
72
            b'w', b'w', b'w', // "www"
73
        ],
74
        Key {
75
            flags: 14,
76
            protocol: 196,
77
            algorithm: 76,
78
            public_key: unsafe { Characters::new_unchecked(b"www") },
79
        },
80
    );
81
}
/mnt/h/flex-dns/src/rdata/kx.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Key exchange delegation record
8
/// This record describes a mechanism whereby authorization for one node
9
/// to act as a key exchange for another is delegated and made available
10
/// with the secure DNS protocol.
11
0
#[derive(Copy, Clone, Debug, PartialEq)]
12
pub struct Kx<'a> {
13
    /// The preference given to this record among others at the same owner.
14
    pub preference: u16,
15
    /// The key exchange host name.
16
    pub exchange: DnsName<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for Kx<'a> {
20
    #[inline]
21
3
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
3
        let preference = u16::parse(rdata.buffer, i)?;
23
3
        let exchange = DnsName::parse(rdata.buffer, i)?;
24
25
1
        Ok(Self {
26
1
            preference,
27
1
            exchange,
28
1
        })
29
3
    }
30
}
31
32
impl<'a> WriteBytes for Kx<'a> {
33
    #[inline]
34
    fn write<
35
        const PTR_STORAGE: usize,
36
        const DNS_SECTION: DnsSection,
37
        B: Buffer,
38
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
39
0
        self.preference.write(message)?;
40
0
        self.exchange.write(message)
41
0
    }
42
}
43
44
impl<'a> Kx<'a> {
45
    #[inline(always)]
46
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
47
        Ok(2 + self.exchange.byte_len()?)
48
    }
49
}
50
51
#[cfg(test)]
52
mod test {
53
    use crate::rdata::testutils::parse_write_test;
54
55
    use super::*;
56
57
    parse_write_test!(
58
        7,
59
        [
60
            0x00, 0x0e, // preference
61
            0x03, b'w', b'w', b'w', 0x00, // exchange
62
        ],
63
        Kx {
64
            preference: 14,
65
            exchange: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
66
        },
67
    );
68
}
/mnt/h/flex-dns/src/rdata/loc.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::parse::Parse;
3
use crate::rdata::{RData, RDataParse};
4
use crate::write::WriteBytes;
5
6
/// # Location information
7
/// This record is used to return a location for a host
8
0
#[derive(Copy, Clone, Debug, PartialEq)]
9
pub struct Loc {
10
    /// The version of the location record
11
    pub version: u8,
12
    /// The size of the location record
13
    pub size: u8,
14
    /// The horizontal precision of the location record
15
    pub horizontal_precision: u8,
16
    /// The vertical precision of the location record
17
    pub vertical_precision: u8,
18
    /// The latitude of the location record
19
    pub latitude: u32,
20
    /// The longitude of the location record
21
    pub longitude: u32,
22
    /// The altitude of the location record
23
    pub altitude: u32,
24
}
25
26
impl<'a> RDataParse<'a> for Loc {
27
    #[inline]
28
15
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
29
15
        let version = u8::parse(rdata.buffer, i)?;
30
14
        let size = u8::parse(rdata.buffer, i)?;
31
13
        let horizontal_precision = u8::parse(rdata.buffer, i)?;
32
11
        let vertical_precision = u8::parse(rdata.buffer, i)?;
33
10
        let latitude = u32::parse(rdata.buffer, i)?;
34
8
        let longitude = u32::parse(rdata.buffer, i)?;
35
7
        let altitude = u32::parse(rdata.buffer, i)?;
36
37
4
        Ok(Self {
38
4
            version,
39
4
            size,
40
4
            horizontal_precision,
41
4
            vertical_precision,
42
4
            latitude,
43
4
            longitude,
44
4
            altitude,
45
4
        })
46
15
    }
47
}
48
49
impl WriteBytes for Loc {
50
    #[inline]
51
    fn write<
52
        const PTR_STORAGE: usize,
53
        const DNS_SECTION: DnsSection,
54
        B: Buffer,
55
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
56
0
        self.version.write(message)?;
57
0
        self.size.write(message)?;
58
0
        self.horizontal_precision.write(message)?;
59
0
        self.vertical_precision.write(message)?;
60
0
        self.latitude.write(message)?;
61
0
        self.longitude.write(message)?;
62
0
        self.altitude.write(message)
63
0
    }
64
}
65
66
impl Loc {
67
    #[inline(always)]
68
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
69
        Ok(16)
70
    }
71
}
72
73
#[cfg(test)]
74
mod test {
75
    use crate::rdata::testutils::parse_write_test;
76
77
    use super::*;
78
79
    parse_write_test!(
80
        16,
81
        [
82
            0x0e, // version
83
            0x0d, // size
84
            0x0c, // horizontal precision
85
            0x0b, // vertical precision
86
            0x00, 0x00, 0x00, 0x0a, // latitude
87
            0x00, 0x00, 0x00, 0x0b, // longitude
88
            0x00, 0x00, 0x00, 0x0c, // altitude
89
        ],
90
        Loc {
91
            version: 0x0e,
92
            size: 0x0d,
93
            horizontal_precision: 0x0c,
94
            vertical_precision: 0x0b,
95
            latitude: 0x0a,
96
            longitude: 0x0b,
97
            altitude: 0x0c,
98
        },
99
    );
100
}
/mnt/h/flex-dns/src/rdata/mx.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Mail exchange
8
/// This record is used to specify the mail exchange for a domain name.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Mx<'a> {
11
    /// The preference of this mail exchange
12
    pub preference: u16,
13
    /// The domain name of the mail exchange
14
    pub exchange: DnsName<'a>,
15
}
16
17
impl<'a> RDataParse<'a> for Mx<'a> {
18
    #[inline]
19
20
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
20
20
        let preference = u16::parse(rdata.buffer, i)?;
21
20
        let exchange = DnsName::parse(rdata.buffer, i)?;
22
23
10
        Ok(Self {
24
10
            preference,
25
10
            exchange,
26
10
        })
27
20
    }
28
}
29
30
impl<'a> WriteBytes for Mx<'a> {
31
    #[inline]
32
    fn write<
33
        const PTR_STORAGE: usize,
34
        const DNS_SECTION: DnsSection,
35
        B: Buffer,
36
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
37
0
        self.preference.write(message)?;
38
0
        self.exchange.write(message)
39
0
    }
40
}
41
42
impl<'a> Mx<'a> {
43
    #[inline(always)]
44
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
45
        Ok(2 + self.exchange.byte_len()?)
46
    }
47
}
48
49
#[cfg(test)]
50
mod test {
51
    use crate::rdata::testutils::parse_write_test;
52
53
    use super::*;
54
55
    parse_write_test!(
56
        7,
57
        [
58
            0x00, 0x0e, // preference
59
            0x03, b'w', b'w', b'w', 0x00, // exchange
60
        ],
61
        Mx {
62
            preference: 14,
63
            exchange: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
64
        },
65
    );
66
}
/mnt/h/flex-dns/src/rdata/naptr.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # Naming authority pointer
9
/// This record is used to delegate a DNS zone to use the given authoritative name servers
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Naptr<'a> {
12
    /// The order in which the NAPTR records MUST be processed in order to accurately represent the ordered list of Rules.
13
    pub order: u16,
14
    /// The preference value of this NAPTR record.
15
    pub preference: u16,
16
    /// The flags field specifies various flags that control the processing of the NAPTR record.
17
    pub flags: Characters<'a>,
18
    /// The service field specifies the service(s) available down this rewrite path.
19
    pub service: Characters<'a>,
20
    /// The regexp field specifies a substitution expression that is applied to the original string held by the client in order to construct the next domain name to lookup.
21
    pub regexp: Characters<'a>,
22
    /// The replacement field specifies the next domain-name to query for NAPTR, SRV, or Address records depending on the value of the flags field.
23
    pub replacement: DnsName<'a>,
24
}
25
26
impl<'a> RDataParse<'a> for Naptr<'a> {
27
    #[inline]
28
34
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
29
34
        let order = u16::parse(rdata.buffer, i)?;
30
33
        let preference = u16::parse(rdata.buffer, i)?;
31
32
        let flags = Characters::parse(rdata.buffer, i)?;
32
26
        let service = Characters::parse(rdata.buffer, i)?;
33
23
        let regexp = Characters::parse(rdata.buffer, i)?;
34
20
        let replacement = DnsName::parse(rdata.buffer, i)?;
35
36
9
        Ok(Self {
37
9
            order,
38
9
            preference,
39
9
            flags,
40
9
            service,
41
9
            regexp,
42
9
            replacement,
43
9
        })
44
34
    }
45
}
46
47
impl<'a> WriteBytes for Naptr<'a> {
48
    #[inline]
49
    fn write<
50
        const PTR_STORAGE: usize,
51
        const DNS_SECTION: DnsSection,
52
        B: Buffer,
53
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
54
0
        self.order.write(message)?;
55
0
        self.preference.write(message)?;
56
0
        self.flags.write(message)?;
57
0
        self.service.write(message)?;
58
0
        self.regexp.write(message)?;
59
0
        self.replacement.write(message)
60
0
    }
61
}
62
63
impl<'a> Naptr<'a> {
64
    #[inline(always)]
65
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
66
        Ok(4 + self.flags.byte_len()? + self.service.byte_len()? + self.regexp.byte_len()? + self.replacement.byte_len()?)
67
    }
68
}
69
70
#[cfg(test)]
71
mod test {
72
    use crate::rdata::testutils::parse_write_test;
73
74
    use super::*;
75
76
    parse_write_test!(
77
        21,
78
        [
79
            0x00, 0x0e, // order
80
            0x00, 0x0f, // preference
81
            0x03, b'a', b'b', b'c', // flags
82
            0x03, b'd', b'e', b'f', // service
83
            0x03, b'g', b'h', b'i', // regexp
84
            0x03, b'j', b'k', b'l', 0x00, // replacement
85
        ],
86
        Naptr {
87
            order: 14,
88
            preference: 15,
89
            flags: unsafe { Characters::new_unchecked(b"abc") },
90
            service: unsafe { Characters::new_unchecked(b"def") },
91
            regexp: unsafe { Characters::new_unchecked(b"ghi") },
92
            replacement: unsafe { DnsName::from_bytes_unchecked(b"\x03jkl\x00") },
93
        },
94
    );
95
}
/mnt/h/flex-dns/src/rdata/ns.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # An authoritative name server
8
/// this record is used to return a nameserver for the given domain
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Ns<'a> {
11
    /// The name server for the domain
12
    name: DnsName<'a>,
13
}
14
15
impl<'a> RDataParse<'a> for Ns<'a> {
16
    #[inline]
17
23
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
18
23
        let name = DnsName::parse(rdata.buffer, i)?;
19
20
10
        Ok(Self {
21
10
            name,
22
10
        })
23
23
    }
24
}
25
26
impl<'a> WriteBytes for Ns<'a> {
27
    #[inline]
28
0
    fn write<
29
0
        const PTR_STORAGE: usize,
30
0
        const DNS_SECTION: DnsSection,
31
0
        B: Buffer,
32
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
33
0
        self.name.write(message)
34
0
    }
35
}
36
37
impl<'a> Ns<'a> {
38
    #[inline(always)]
39
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
40
        Ok(self.name.byte_len()?)
41
    }
42
}
43
44
#[cfg(test)]
45
mod test {
46
    use crate::rdata::testutils::parse_write_test;
47
48
    use super::*;
49
50
    parse_write_test!(
51
        17,
52
        [
53
            0x03, b'w', b'w', b'w',
54
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
55
            0x03, b'c', b'o', b'm',
56
            0x00,
57
        ],
58
        Ns {
59
            name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
60
        },
61
    );
62
}
/mnt/h/flex-dns/src/rdata/nsec.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # Next secure record
9
/// This record is used to prove that a name does not exist in a zone.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Nsec<'a> {
12
    /// The next owner name in the canonical ordering of the zone.
13
    pub next_domain_name: DnsName<'a>,
14
    /// The set of RR types present at the NSEC RR's owner name.
15
    pub type_bit_maps: Characters<'a>,
16
}
17
18
impl<'a> RDataParse<'a> for Nsec<'a> {
19
    #[inline]
20
36
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
21
36
        let next_domain_name = DnsName::parse(rdata, i)?;
22
18
        let type_bit_maps = Characters::parse(rdata, i)?;
23
24
11
        Ok(Self {
25
11
            next_domain_name,
26
11
            type_bit_maps,
27
11
        })
28
36
    }
29
}
30
31
impl<'a> WriteBytes for Nsec<'a> {
32
    #[inline]
33
    fn write<
34
        const PTR_STORAGE: usize,
35
        const DNS_SECTION: DnsSection,
36
        B: Buffer,
37
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
38
0
        self.next_domain_name.write(message)?;
39
0
        self.type_bit_maps.write(message)
40
0
    }
41
}
42
43
impl<'a> Nsec<'a> {
44
    #[inline(always)]
45
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
46
        Ok(self.next_domain_name.byte_len()? + self.type_bit_maps.byte_len()?)
47
    }
48
}
49
50
#[cfg(test)]
51
mod test {
52
    use crate::rdata::testutils::parse_write_test;
53
54
    use super::*;
55
56
    parse_write_test!(
57
        9,
58
        [
59
            0x03, // length of "www"
60
            b'w', b'w', b'w', // "www"
61
            0x00, // end of name
62
            0x03, // length of "www"
63
            b'w', b'w', b'w', // "www"
64
        ],
65
        Nsec {
66
            next_domain_name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
67
            type_bit_maps: unsafe { Characters::new_unchecked(b"www") },
68
        },
69
    );
70
}
/mnt/h/flex-dns/src/rdata/nsec3.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Next secure record version 3
8
/// This record is used to provide authenticated denial of existence for DNSSEC.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Nsec3<'a> {
11
    /// The hash algorithm used to hash the original owner name field.
12
    pub hash_algorithm: u8,
13
    /// The flags field.
14
    pub flags: u8,
15
    /// The number of iterations used to construct the hash.
16
    pub iterations: u16,
17
    /// The salt used to construct the hash.
18
    pub salt: Characters<'a>,
19
    /// The next hashed owner name in the canonical ordering of the zone.
20
    pub next_hashed_owner_name: Characters<'a>,
21
    /// The type bit maps field.
22
    pub type_bit_maps: Characters<'a>,
23
}
24
25
impl<'a> RDataParse<'a> for Nsec3<'a> {
26
    #[inline]
27
27
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
28
27
        let hash_algorithm = u8::parse(rdata, i)?;
29
26
        let flags = u8::parse(rdata, i)?;
30
24
        let iterations = u16::parse(rdata, i)?;
31
22
        let salt = Characters::parse(rdata, i)?;
32
16
        let next_hashed_owner_name = Characters::parse(rdata, i)?;
33
11
        let type_bit_maps = Characters::parse(rdata, i)?;
34
35
7
        Ok(Self {
36
7
            hash_algorithm,
37
7
            flags,
38
7
            iterations,
39
7
            salt,
40
7
            next_hashed_owner_name,
41
7
            type_bit_maps,
42
7
        })
43
27
    }
44
}
45
46
impl<'a> WriteBytes for Nsec3<'a> {
47
    #[inline]
48
    fn write<
49
        const PTR_STORAGE: usize,
50
        const DNS_SECTION: DnsSection,
51
        B: Buffer,
52
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
53
0
        self.hash_algorithm.write(message)?;
54
0
        self.flags.write(message)?;
55
0
        self.iterations.write(message)?;
56
0
        self.salt.write(message)?;
57
0
        self.next_hashed_owner_name.write(message)?;
58
0
        self.type_bit_maps.write(message)
59
0
    }
60
}
61
62
impl<'a> Nsec3<'a> {
63
    #[inline(always)]
64
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
65
        Ok(5 + self.salt.byte_len()? + self.next_hashed_owner_name.byte_len()? + self.type_bit_maps.byte_len()?)
66
    }
67
}
68
69
#[cfg(test)]
70
mod test {
71
    use crate::rdata::testutils::parse_write_test;
72
73
    use super::*;
74
75
    parse_write_test!(
76
        16,
77
        [
78
            0x0e, // hash algorithm
79
            0x0a, // flags
80
            0x00, 0x0e, // iterations
81
            0x03, // length of salt
82
            b'a', b'b', b'c',
83
            0x03, // length of next hashed owner name
84
            b'd', b'e', b'f',
85
            0x03, // length of type bit maps
86
            b'w', b'w', b'w',
87
        ],
88
        Nsec3 {
89
            hash_algorithm: 0x0e,
90
            flags: 0x0a,
91
            iterations: 0x000e,
92
            salt: unsafe { Characters::new_unchecked(b"abc") },
93
            next_hashed_owner_name: unsafe { Characters::new_unchecked(b"def") },
94
            type_bit_maps: unsafe { Characters::new_unchecked(b"www") },
95
        },
96
    );
97
}
/mnt/h/flex-dns/src/rdata/nsec3param.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Next secure record version 3 parameters
8
/// This record is used to provide parameters for the NSEC3 records.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Nsec3Param<'a> {
11
    /// Hash algorithm
12
    pub hash_algorithm: u8,
13
    /// Flags
14
    pub flags: u8,
15
    /// Iterations
16
    pub iterations: u16,
17
    /// Salt
18
    pub salt: Characters<'a>,
19
}
20
21
impl<'a> RDataParse<'a> for Nsec3Param<'a> {
22
    #[inline]
23
8
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24
8
        let hash_algorithm = u8::parse(rdata, i)?;
25
7
        let flags = u8::parse(rdata, i)?;
26
6
        let iterations = u16::parse(rdata, i)?;
27
5
        let salt = Characters::parse(rdata, i)?;
28
29
3
        Ok(Self {
30
3
            hash_algorithm,
31
3
            flags,
32
3
            iterations,
33
3
            salt,
34
3
        })
35
8
    }
36
}
37
38
impl<'a> WriteBytes for Nsec3Param<'a> {
39
    #[inline]
40
    fn write<
41
        const PTR_STORAGE: usize,
42
        const DNS_SECTION: DnsSection,
43
        B: Buffer,
44
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
45
0
        self.hash_algorithm.write(message)?;
46
0
        self.flags.write(message)?;
47
0
        self.iterations.write(message)?;
48
0
        self.salt.write(message)
49
0
    }
50
}
51
52
impl<'a> Nsec3Param<'a> {
53
    #[inline(always)]
54
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
55
        Ok(4 + self.salt.byte_len()?)
56
    }
57
}
58
59
#[cfg(test)]
60
mod test {
61
    use crate::rdata::testutils::parse_write_test;
62
63
    use super::*;
64
65
    parse_write_test!(
66
        8,
67
        [
68
            0x0e, // hash algorithm
69
            0xae, // flags
70
            0x0a, 0xfe, // iterations
71
            0x03, b'w', b'w', b'w', // salt
72
        ],
73
        Nsec3Param {
74
            hash_algorithm: 0x0e,
75
            flags: 0xae,
76
            iterations: 0x0afe,
77
            salt: unsafe { Characters::new_unchecked(b"www") },
78
        },
79
    );
80
}
/mnt/h/flex-dns/src/rdata/openpgpkey.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # OpenPGP Key Record (OPENPGPKEY)
8
/// This record is used as part of the DNS-Based Authentication of Named
9
/// Entities (DANE) protocol to associate a public key with a domain name.
10
/// The OPENPGPKEY record is intended to be used in conjunction with the
11
/// TLSA record [RFC6698].
12
0
#[derive(Copy, Clone, Debug, PartialEq)]
13
pub struct OpenPgpKey<'a> {
14
    /// flags is a bitmap of flags (see [RFC 4880](https://tools.ietf.org/html/rfc4880))
15
    pub flags: u16,
16
    /// algorithm is the algorithm of the public key
17
    pub algorithm: u8,
18
    /// public_key is the public key
19
    pub public_key: Characters<'a>,
20
    /// fingerprint is the fingerprint of the referenced public key
21
    pub fingerprint: Characters<'a>,
22
}
23
24
impl<'a> RDataParse<'a> for OpenPgpKey<'a> {
25
    #[inline]
26
14
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
27
14
        let flags = u16::parse(rdata, i)?;
28
13
        let algorithm = u8::parse(rdata, i)?;
29
11
        let public_key = Characters::parse(rdata, i)?;
30
6
        let fingerprint = Characters::parse(rdata, i)?;
31
32
4
        Ok(Self {
33
4
            flags,
34
4
            algorithm,
35
4
            public_key,
36
4
            fingerprint
37
4
        })
38
14
    }
39
}
40
41
impl<'a> WriteBytes for OpenPgpKey<'a> {
42
    #[inline]
43
    fn write<
44
        const PTR_STORAGE: usize,
45
        const DNS_SECTION: DnsSection,
46
        B: Buffer,
47
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
48
0
        self.flags.write(message)?;
49
0
        self.algorithm.write(message)?;
50
0
        self.public_key.write(message)?;
51
0
        self.fingerprint.write(message)
52
0
    }
53
}
54
55
impl<'a> OpenPgpKey<'a> {
56
    #[inline(always)]
57
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
58
        Ok(3 + self.public_key.byte_len()? + self.fingerprint.byte_len()?)
59
    }
60
}
61
62
#[cfg(test)]
63
mod test {
64
    use crate::rdata::testutils::parse_write_test;
65
66
    use super::*;
67
68
    parse_write_test!(
69
        11,
70
        [
71
            0x00, 0x0e, // flags
72
            0x0a, // algorithm
73
            0x03, b'w', b'w', b'w', // public key
74
            0x03, b'w', b'w', b'w', // fingerprint
75
        ],
76
        OpenPgpKey {
77
            flags: 0x000e,
78
            algorithm: 0x0a,
79
            public_key: unsafe { Characters::new_unchecked(b"www") },
80
            fingerprint: unsafe { Characters::new_unchecked(b"www") },
81
        },
82
    );
83
}
/mnt/h/flex-dns/src/rdata/opt.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Option record
8
/// This record is used to store options for the DNS protocol.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Opt<'a> {
11
    /// The code for the option.
12
    pub code: u16,
13
    /// The data for the option.
14
    pub data: Characters<'a>,
15
}
16
17
impl<'a> RDataParse<'a> for Opt<'a> {
18
    #[inline]
19
23
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
20
23
        let code = u16::parse(rdata.buffer, i)?;
21
22
        let data = Characters::parse(rdata.buffer, i)?;
22
23
9
        Ok(Self {
24
9
            code,
25
9
            data,
26
9
        })
27
23
    }
28
}
29
30
impl<'a> WriteBytes for Opt<'a> {
31
    #[inline]
32
    fn write<
33
        const PTR_STORAGE: usize,
34
        const DNS_SECTION: DnsSection,
35
        B: Buffer,
36
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
37
0
        self.code.write(message)?;
38
0
        self.data.write(message)
39
0
    }
40
}
41
42
impl<'a> Opt<'a> {
43
    #[inline(always)]
44
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
45
        Ok(2 + self.data.byte_len()?)
46
    }
47
}
48
49
#[cfg(test)]
50
mod test {
51
    use crate::rdata::testutils::parse_write_test;
52
53
    use super::*;
54
55
    parse_write_test!(
56
        6,
57
        [
58
            0x00, 0x0e, // code
59
            0x03, // length
60
            b'w', b'w', b'w', // data
61
        ],
62
        Opt {
63
            code: 14,
64
            data: unsafe { Characters::new_unchecked(b"www") },
65
        },
66
    );
67
}
/mnt/h/flex-dns/src/rdata/ptr.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # A domain name pointer
8
/// This record is used to return a canonical name for an alias
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Ptr<'a> {
11
    /// The canonical name for the alias
12
    name: DnsName<'a>,
13
}
14
15
impl<'a> RDataParse<'a> for Ptr<'a> {
16
    #[inline]
17
5
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
18
5
        let name = DnsName::parse(rdata.buffer, i)?;
19
20
2
        Ok(Self {
21
2
            name,
22
2
        })
23
5
    }
24
}
25
26
impl<'a> WriteBytes for Ptr<'a> {
27
    #[inline]
28
0
    fn write<
29
0
        const PTR_STORAGE: usize,
30
0
        const DNS_SECTION: DnsSection,
31
0
        B: Buffer,
32
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
33
0
        self.name.write(message)
34
0
    }
35
}
36
37
impl<'a> Ptr<'a> {
38
    #[inline(always)]
39
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
40
        Ok(self.name.byte_len()?)
41
    }
42
}
43
44
#[cfg(test)]
45
mod test {
46
    use crate::rdata::testutils::parse_write_test;
47
48
    use super::*;
49
50
    parse_write_test!(
51
        17,
52
        [
53
            0x03, b'w', b'w', b'w',
54
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
55
            0x03, b'c', b'o', b'm',
56
            0x00,
57
        ],
58
        Ptr {
59
            name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
60
        },
61
    );
62
}
/mnt/h/flex-dns/src/rdata/rp.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Responsible person
8
/// This record is used to identify the responsible person for a domain
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Rp<'a> {
11
    /// The mailbox name of the responsible person
12
    pub mbox: DnsName<'a>,
13
    /// The domain name of the responsible person
14
    pub txt: DnsName<'a>,
15
}
16
17
impl<'a> RDataParse<'a> for Rp<'a> {
18
    #[inline]
19
46
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
20
46
        let mbox = DnsName::parse(rdata.buffer, i)?;
21
37
        let txt = DnsName::parse(rdata.buffer, i)?;
22
23
28
        Ok(Self {
24
28
            mbox,
25
28
            txt,
26
28
        })
27
46
    }
28
}
29
30
impl<'a> WriteBytes for Rp<'a> {
31
    #[inline]
32
    fn write<
33
        const PTR_STORAGE: usize,
34
        const DNS_SECTION: DnsSection,
35
        B: Buffer,
36
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
37
0
        self.mbox.write(message)?;
38
0
        self.txt.write(message)
39
0
    }
40
}
41
42
impl<'a> Rp<'a> {
43
    #[inline(always)]
44
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
45
        Ok(self.mbox.byte_len()? + self.txt.byte_len()?)
46
    }
47
}
48
49
#[cfg(test)]
50
mod test {
51
    use crate::rdata::testutils::parse_write_test;
52
53
    use super::*;
54
55
    parse_write_test!(
56
        33,
57
        [
58
            0x03, b'w', b'w', b'w',
59
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
60
            0x03, b'c', b'o', b'm',
61
            0x00, // mbox
62
            0x03, b'w', b'w', b'w',
63
            0x06, b'g', b'o', b'o', b'g', b'l', b'e',
64
            0x03, b'c', b'o', b'm',
65
            0x00, // txt
66
        ],
67
        Rp {
68
            mbox: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
69
            txt: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x06google\x03com\x00") },
70
        },
71
    );
72
}
/mnt/h/flex-dns/src/rdata/rrsig.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # DNSSEC signature record
9
/// This record is used to sign other records. It is used in conjunction with the
10
/// DnsKey record to verify the authenticity of a record.
11
0
#[derive(Copy, Clone, Debug, PartialEq)]
12
pub struct RRSig<'a> {
13
    /// The type of record that is covered by this signature.
14
    pub type_covered: u16,
15
    /// The algorithm used to create the signature.
16
    pub algorithm: u8,
17
    /// The number of seconds the signature is valid for.
18
    pub original_ttl: u32,
19
    /// The time at which the signature was created.
20
    pub signature_expiration: u32,
21
    /// The time at which the signature was last refreshed.
22
    pub signature_inception: u32,
23
    /// The key tag of the key that was used to create the signature.
24
    pub key_tag: u16,
25
    /// The name of the zone that this signature was created for.
26
    pub signer_name: DnsName<'a>,
27
    /// The signature.
28
    pub signature: Characters<'a>,
29
}
30
31
impl<'a> RDataParse<'a> for RRSig<'a> {
32
    #[inline]
33
43
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
34
43
        let type_covered = u16::parse(rdata.buffer, i)?;
35
42
        let algorithm = u8::parse(rdata.buffer, i)?;
36
41
        let original_ttl = u32::parse(rdata.buffer, i)?;
37
39
        let signature_expiration = u32::parse(rdata.buffer, i)?;
38
37
        let signature_inception = u32::parse(rdata.buffer, i)?;
39
36
        let key_tag = u16::parse(rdata.buffer, i)?;
40
35
        let signer_name = DnsName::parse(rdata.buffer, i)?;
41
17
        let signature = Characters::parse(rdata.buffer, i)?;
42
43
12
        Ok(Self {
44
12
            type_covered,
45
12
            algorithm,
46
12
            original_ttl,
47
12
            signature_expiration,
48
12
            signature_inception,
49
12
            key_tag,
50
12
            signer_name,
51
12
            signature,
52
12
        })
53
43
    }
54
}
55
56
impl<'a> WriteBytes for RRSig<'a> {
57
    #[inline]
58
    fn write<
59
        const PTR_STORAGE: usize,
60
        const DNS_SECTION: DnsSection,
61
        B: Buffer,
62
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
63
0
        self.type_covered.write(message)?;
64
0
        self.algorithm.write(message)?;
65
0
        self.original_ttl.write(message)?;
66
0
        self.signature_expiration.write(message)?;
67
0
        self.signature_inception.write(message)?;
68
0
        self.key_tag.write(message)?;
69
0
        self.signer_name.write(message)?;
70
0
        self.signature.write(message)
71
0
    }
72
}
73
74
impl<'a> RRSig<'a> {
75
    #[inline(always)]
76
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
77
        Ok(18 + self.signer_name.byte_len()? + self.signature.byte_len()?)
78
    }
79
}
80
81
#[cfg(test)]
82
mod test {
83
    use crate::rdata::testutils::parse_write_test;
84
85
    use super::*;
86
87
    parse_write_test!(
88
        42,
89
        [
90
            0x00, 0x0e, // type covered
91
            0x05, // algorithm
92
            0x00, 0x00, 0x00, 0x0a, // original ttl
93
            0x00, 0x00, 0x00, 0x0b, // signature expiration
94
            0x00, 0x00, 0x00, 0x0c, // signature inception
95
            0x00, 0x0d, // key tag
96
            0x03, b'w', b'w', b'w',
97
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
98
            0x03, b'c', b'o', b'm',
99
            0x00, // signer name
100
            0x07, b'f', b'o', b'o', b'-', b'b', b'a', b'r', // signature
101
        ],
102
        RRSig {
103
            type_covered: 14,
104
            algorithm: 5,
105
            original_ttl: 10,
106
            signature_expiration: 11,
107
            signature_inception: 12,
108
            key_tag: 13,
109
            signer_name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
110
            signature: unsafe { Characters::new_unchecked(b"foo-bar") },
111
        },
112
    );
113
}
/mnt/h/flex-dns/src/rdata/sig.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # Signature
9
/// This record is used to authenticate the data in a message
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Sig<'a> {
12
    /// The type of the record covered by this signature
13
    type_covered: u16,
14
    /// The algorithm used
15
    algorithm: u8,
16
    /// The number of labels in the original RDATA
17
    labels: u8,
18
    /// The original TTL
19
    original_ttl: u32,
20
    /// The signature expiration
21
    signature_expiration: u32,
22
    /// The signature inception
23
    signature_inception: u32,
24
    /// The key tag
25
    key_tag: u16,
26
    /// The signer's name
27
    signer_name: DnsName<'a>,
28
    /// The signature
29
    signature: Characters<'a>,
30
}
31
32
impl<'a> RDataParse<'a> for Sig<'a> {
33
    #[inline]
34
57
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
35
57
        let type_covered = u16::parse(rdata, i)?;
36
56
        let algorithm = u8::parse(rdata, i)?;
37
55
        let labels = u8::parse(rdata, i)?;
38
54
        let original_ttl = u32::parse(rdata, i)?;
39
53
        let signature_expiration = u32::parse(rdata, i)?;
40
52
        let signature_inception = u32::parse(rdata, i)?;
41
49
        let key_tag = u16::parse(rdata, i)?;
42
48
        let signer_name = DnsName::parse(rdata, i)?;
43
30
        let signature = Characters::parse(rdata, i)?;
44
45
24
        Ok(Self {
46
24
            type_covered,
47
24
            algorithm,
48
24
            labels,
49
24
            original_ttl,
50
24
            signature_expiration,
51
24
            signature_inception,
52
24
            key_tag,
53
24
            signer_name,
54
24
            signature,
55
24
        })
56
57
    }
57
}
58
59
impl<'a> WriteBytes for Sig<'a> {
60
    #[inline]
61
    fn write<
62
        const PTR_STORAGE: usize,
63
        const DNS_SECTION: DnsSection,
64
        B: Buffer,
65
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
66
0
        self.type_covered.write(message)?;
67
0
        self.algorithm.write(message)?;
68
0
        self.labels.write(message)?;
69
0
        self.original_ttl.write(message)?;
70
0
        self.signature_expiration.write(message)?;
71
0
        self.signature_inception.write(message)?;
72
0
        self.key_tag.write(message)?;
73
0
        self.signer_name.write(message)?;
74
0
        self.signature.write(message)
75
0
    }
76
}
77
78
impl<'a> Sig<'a> {
79
    #[inline(always)]
80
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
81
        Ok(18 + self.signer_name.byte_len()? + self.signature.byte_len()?)
82
    }
83
}
84
85
#[cfg(test)]
86
mod test {
87
    use crate::rdata::testutils::parse_write_test;
88
89
    use super::*;
90
91
    parse_write_test!(
92
        43,
93
        [
94
            0x00, 0x0e, // type covered
95
            0x05, // algorithm
96
            0x06, // labels
97
            0x00, 0x00, 0x00, 0x0a, // original ttl
98
            0x00, 0x00, 0x00, 0x0b, // signature expiration
99
            0x00, 0x00, 0x00, 0x0c, // signature inception
100
            0x00, 0x0d, // key tag
101
            0x03, b'w', b'w', b'w',
102
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
103
            0x03, b'c', b'o', b'm',
104
            0x00, // signer name
105
            0x07, b'f', b'o', b'o', b'-', b'b', b'a', b'r', // signature
106
        ],
107
        Sig {
108
            type_covered: 14,
109
            algorithm: 5,
110
            labels: 6,
111
            original_ttl: 10,
112
            signature_expiration: 11,
113
            signature_inception: 12,
114
            key_tag: 13,
115
            signer_name: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
116
            signature: unsafe { Characters::new_unchecked(b"foo-bar") },
117
        },
118
    );
119
}
/mnt/h/flex-dns/src/rdata/smimea.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # S/MIME cert association record (SMIMEA)
8
/// This record is used to store S/MIME certificate association
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct SmimeA<'a> {
11
    /// The usage of the certificate
12
    pub usage: u8,
13
    /// The selector of the certificate
14
    pub selector: u8,
15
    /// The matching type of the certificate
16
    pub matching_type: u8,
17
    /// The certificate data
18
    pub certificate: Characters<'a>,
19
}
20
21
impl<'a> RDataParse<'a> for SmimeA<'a> {
22
    #[inline]
23
15
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24
15
        let usage = u8::parse(rdata, i)?;
25
14
        let selector = u8::parse(rdata, i)?;
26
13
        let matching_type = u8::parse(rdata, i)?;
27
13
        let certificate = Characters::parse(rdata, i)?;
28
29
5
        Ok(Self {
30
5
            usage,
31
5
            selector,
32
5
            matching_type,
33
5
            certificate,
34
5
        })
35
15
    }
36
}
37
38
impl<'a> WriteBytes for SmimeA<'a> {
39
    #[inline]
40
    fn write<
41
        const PTR_STORAGE: usize,
42
        const DNS_SECTION: DnsSection,
43
        B: Buffer,
44
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
45
0
        self.usage.write(message)?;
46
0
        self.selector.write(message)?;
47
0
        self.matching_type.write(message)?;
48
0
        self.certificate.write(message)
49
0
    }
50
}
51
52
impl<'a> SmimeA<'a> {
53
    #[inline(always)]
54
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
55
        Ok(3 + self.certificate.byte_len()?)
56
    }
57
}
58
59
#[cfg(test)]
60
mod test {
61
    use crate::rdata::testutils::parse_write_test;
62
63
    use super::*;
64
65
    parse_write_test!(
66
        19,
67
        [
68
            0x0e, // usage
69
            0x0f, // selector
70
            0x10, // matching type
71
            0x0f, // length of certificate
72
            0x01, 0x02, 0x03, 0x04, 0x05,
73
            0x06, 0x07, 0x08, 0x09, 0x0a,
74
            0x0b, 0x0c, 0x0d, 0x0e, 0x0f, // certificate
75
        ],
76
        SmimeA {
77
            usage: 0x0e,
78
            selector: 0x0f,
79
            matching_type: 0x10,
80
            certificate: unsafe { Characters::new_unchecked(&[
81
                0x01, 0x02, 0x03, 0x04, 0x05,
82
                0x06, 0x07, 0x08, 0x09, 0x0a,
83
                0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
84
            ]) },
85
        },
86
    );
87
}
/mnt/h/flex-dns/src/rdata/soa.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Marks the start of a zone of authority
8
/// This record is used to mark the start of a zone of authority
9
/// and contains the parameters of the zone
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Soa<'a> {
12
    /// The domain name of the name server that was the
13
    /// original or primary source of data for this zone
14
    pub mname: DnsName<'a>,
15
    /// A domain name which specifies the mailbox of the
16
    /// person responsible for this zone
17
    pub rname: DnsName<'a>,
18
    /// The unsigned 32 bit version number of the original copy
19
    /// of the zone. Zone transfers preserve this value. This
20
    /// value wraps and should be compared using sequence space
21
    /// arithmetic
22
    pub serial: u32,
23
    /// A 32 bit time interval before the zone should be
24
    /// refreshed
25
    pub refresh: u32,
26
    /// A 32 bit time interval that should elapse before a
27
    /// failed refresh should be retried
28
    pub retry: u32,
29
    /// A 32 bit time value that specifies the upper limit on
30
    /// the time interval that can elapse before the zone is no
31
    /// longer authoritative
32
    pub expire: u32,
33
    /// The unsigned 32 bit minimum TTL field that should be
34
    /// exported with any RR from this zone
35
    pub minimum: u32,
36
}
37
38
impl<'a> RDataParse<'a> for Soa<'a> {
39
    #[inline]
40
63
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
41
63
        let mname = DnsName::parse(rdata.buffer, i)?;
42
61
        let rname = DnsName::parse(rdata.buffer, i)?;
43
44
        let serial = u32::parse(rdata.buffer, i)?;
44
42
        let refresh = u32::parse(rdata.buffer, i)?;
45
38
        let retry = u32::parse(rdata.buffer, i)?;
46
34
        let expire = u32::parse(rdata.buffer, i)?;
47
28
        let minimum = u32::parse(rdata.buffer, i)?;
48
49
21
        Ok(Self {
50
21
            mname,
51
21
            rname,
52
21
            serial,
53
21
            refresh,
54
21
            retry,
55
21
            expire,
56
21
            minimum,
57
21
        })
58
63
    }
59
}
60
61
impl<'a> WriteBytes for Soa<'a> {
62
    #[inline]
63
    fn write<
64
        const PTR_STORAGE: usize,
65
        const DNS_SECTION: DnsSection,
66
        B: Buffer,
67
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
68
0
        self.mname.write(message)?;
69
0
        self.rname.write(message)?;
70
0
        self.serial.write(message)?;
71
0
        self.refresh.write(message)?;
72
0
        self.retry.write(message)?;
73
0
        self.expire.write(message)?;
74
0
        self.minimum.write(message)
75
0
    }
76
}
77
78
impl<'a> Soa<'a> {
79
    #[inline(always)]
80
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
81
        Ok(self.mname.byte_len()? + self.rname.byte_len()? + 20)
82
    }
83
}
84
85
#[cfg(test)]
86
mod test {
87
    use crate::rdata::testutils::parse_write_test;
88
89
    use super::*;
90
91
    parse_write_test!(
92
        53,
93
        [
94
            0x03, b'w', b'w', b'w',
95
            0x07, b'e', b'x', b'a', b'm', b'p', b'l', b'e',
96
            0x03, b'c', b'o', b'm',
97
            0x00, // mname
98
            0x03, b'w', b'w', b'w',
99
            0x06, b'g', b'o', b'o', b'g', b'l', b'e',
100
            0x03, b'c', b'o', b'm',
101
            0x00, // rname
102
            0x00, 0x00, 0x00, 0x0e, // serial
103
            0x00, 0x00, 0x00, 0x0f, // refresh
104
            0x00, 0x00, 0x00, 0x10, // retry
105
            0x00, 0x00, 0x00, 0x11, // expire
106
            0x00, 0x00, 0x00, 0x12, // minimum
107
        ],
108
        Soa {
109
            mname: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x07example\x03com\x00") },
110
            rname: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x06google\x03com\x00") },
111
            serial: 14,
112
            refresh: 15,
113
            retry: 16,
114
            expire: 17,
115
            minimum: 18,
116
        },
117
    );
118
}
/mnt/h/flex-dns/src/rdata/srv.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::name::DnsName;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Service locator
8
/// This record is used to return a service location
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Srv<'a> {
11
    /// The priority of the target host
12
    pub priority: u16,
13
    /// The weight of the target host
14
    pub weight: u16,
15
    /// The port on the target host
16
    pub port: u16,
17
    /// The target host
18
    pub target: DnsName<'a>,
19
}
20
21
impl<'a> RDataParse<'a> for Srv<'a> {
22
    #[inline]
23
62
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24
62
        let priority = u16::parse(rdata.buffer, i)?;
25
61
        let weight = u16::parse(rdata.buffer, i)?;
26
59
        let port = u16::parse(rdata.buffer, i)?;
27
56
        let target = DnsName::parse(rdata.buffer, i)?;
28
29
17
        Ok(Self {
30
17
            priority,
31
17
            weight,
32
17
            port,
33
17
            target,
34
17
        })
35
62
    }
36
}
37
38
impl<'a> WriteBytes for Srv<'a> {
39
    #[inline]
40
    fn write<
41
        const PTR_STORAGE: usize,
42
        const DNS_SECTION: DnsSection,
43
        B: Buffer,
44
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
45
0
        self.priority.write(message)?;
46
0
        self.weight.write(message)?;
47
0
        self.port.write(message)?;
48
0
        self.target.write(message)
49
0
    }
50
}
51
52
impl<'a> Srv<'a> {
53
    #[inline(always)]
54
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
55
        Ok(6 + self.target.byte_len()?)
56
    }
57
}
58
59
#[cfg(test)]
60
mod test {
61
    use crate::rdata::testutils::parse_write_test;
62
63
    use super::*;
64
65
    parse_write_test!(
66
        11,
67
        [
68
            0x00, 0x0e, // priority
69
            0x00, 0x0e, // weight
70
            0x00, 0x0e, // port
71
            0x03,
72
            b'w', b'w', b'w',
73
            0x00, // target
74
        ],
75
        Srv {
76
            priority: 14,
77
            weight: 14,
78
            port: 14,
79
            target: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
80
        },
81
    );
82
}
/mnt/h/flex-dns/src/rdata/sshfp.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # SSH public key fingerprint record
8
/// This record is used to store the fingerprint of an SSH public key.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct SshFp<'a> {
11
    /// The algorithm used to generate the fingerprint.
12
    pub algorithm: u8,
13
    /// The fingerprint type.
14
    pub fingerprint_type: u8,
15
    /// The fingerprint data.
16
    pub data: Characters<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for SshFp<'a> {
20
    #[inline]
21
7
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
7
        let algorithm = u8::parse(rdata.buffer, i)?;
23
6
        let fingerprint_type = u8::parse(rdata.buffer, i)?;
24
5
        let data = Characters::parse(rdata.buffer, i)?;
25
26
1
        Ok(Self {
27
1
            algorithm,
28
1
            fingerprint_type,
29
1
            data,
30
1
        })
31
7
    }
32
}
33
34
impl<'a> WriteBytes for SshFp<'a> {
35
    #[inline]
36
    fn write<
37
        const PTR_STORAGE: usize,
38
        const DNS_SECTION: DnsSection,
39
        B: Buffer,
40
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
41
0
        self.algorithm.write(message)?;
42
0
        self.fingerprint_type.write(message)?;
43
0
        self.data.write(message)
44
0
    }
45
}
46
47
impl<'a> SshFp<'a> {
48
    #[inline(always)]
49
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
50
        Ok(2 + self.data.byte_len()?)
51
    }
52
}
53
54
#[cfg(test)]
55
mod test {
56
    use crate::rdata::testutils::parse_write_test;
57
58
    use super::*;
59
60
    parse_write_test!(
61
        6,
62
        [
63
            0x01, // algorithm
64
            0x02, // fingerprint type
65
            0x03, // length of "www"
66
            b'w', b'w', b'w', // "www"
67
        ],
68
        SshFp {
69
            algorithm: 1,
70
            fingerprint_type: 2,
71
            data: unsafe { Characters::new_unchecked(b"www") },
72
        },
73
    );
74
}
/mnt/h/flex-dns/src/rdata/svcb.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # Service binding record (SVCB)
9
/// This record is used to describe the parameters of a service binding.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct Svcb<'a> {
12
    /// The priority of this target host
13
    pub priority: u16,
14
    /// The relative weight for entries with the same priority
15
    pub weight: u16,
16
    /// The TCP or UDP port on which the service is to be found
17
    pub port: u16,
18
    /// The domain name of the target host
19
    pub target: DnsName<'a>,
20
    /// The parameters of the service binding
21
    pub parameters: Characters<'a>,
22
}
23
24
impl<'a> RDataParse<'a> for Svcb<'a> {
25
    #[inline]
26
108
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
27
108
        let priority = u16::parse(rdata, i)?;
28
106
        let weight = u16::parse(rdata, i)?;
29
105
        let port = u16::parse(rdata, i)?;
30
104
        let target = DnsName::parse(rdata, i)?;
31
78
        let parameters = Characters::parse(rdata, i)?;
32
33
42
        Ok(Self {
34
42
            priority,
35
42
            weight,
36
42
            port,
37
42
            target,
38
42
            parameters
39
42
        })
40
108
    }
41
}
42
43
impl<'a> WriteBytes for Svcb<'a> {
44
    #[inline]
45
    fn write<
46
        const PTR_STORAGE: usize,
47
        const DNS_SECTION: DnsSection,
48
        B: Buffer,
49
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
50
0
        self.priority.write(message)?;
51
0
        self.weight.write(message)?;
52
0
        self.port.write(message)?;
53
0
        self.target.write(message)?;
54
0
        self.parameters.write(message)
55
0
    }
56
}
57
58
impl<'a> Svcb<'a> {
59
    #[inline(always)]
60
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
61
        Ok(6 + self.target.byte_len()? + self.parameters.byte_len()?)
62
    }
63
}
64
65
#[cfg(test)]
66
mod test {
67
    use crate::rdata::testutils::parse_write_test;
68
69
    use super::*;
70
71
    parse_write_test!(
72
        15,
73
        [
74
            0x00, 0x0e, // priority
75
            0x00, 0x0e, // weight
76
            0x00, 0x0e, // port
77
            0x03, // length of "www"
78
            b'w', b'w', b'w', // "www"
79
            0x00, // end of name
80
            0x03, // length of "www"
81
            b'w', b'w', b'w', // "www"
82
        ],
83
        Svcb {
84
            priority: 14,
85
            weight: 14,
86
            port: 14,
87
            target: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
88
            parameters: unsafe { Characters::new_unchecked(b"www") },
89
        },
90
    );
91
}
/mnt/h/flex-dns/src/rdata/ta.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # DNSSEC trust authorities record (TA)
8
/// This record is used to publish the public key of a DNSSEC trust anchor.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Ta<'a> {
11
    /// trust_anchor_link is the trust anchor link
12
    pub trust_anchor_link: Characters<'a>,
13
}
14
15
impl<'a> RDataParse<'a> for Ta<'a> {
16
    #[inline]
17
3
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
18
3
        let trust_anchor_link = Characters::parse(rdata, i)?;
19
20
2
        Ok(Self {
21
2
            trust_anchor_link,
22
2
        })
23
3
    }
24
}
25
26
impl<'a> WriteBytes for Ta<'a> {
27
    #[inline]
28
0
    fn write<
29
0
        const PTR_STORAGE: usize,
30
0
        const DNS_SECTION: DnsSection,
31
0
        B: Buffer,
32
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
33
0
        self.trust_anchor_link.write(message)
34
0
    }
35
}
36
37
impl<'a> Ta<'a> {
38
    #[inline(always)]
39
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
40
        Ok(self.trust_anchor_link.byte_len()?)
41
    }
42
}
43
44
#[cfg(test)]
45
mod test {
46
    use crate::rdata::testutils::parse_write_test;
47
48
    use super::*;
49
50
    parse_write_test!(
51
        4,
52
        [
53
            0x03,
54
            b'w', b'w', b'w', // trust_anchor_link
55
        ],
56
        Ta {
57
            trust_anchor_link: unsafe { Characters::new_unchecked(b"www") },
58
        },
59
    );
60
}
/mnt/h/flex-dns/src/rdata/tkey.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # Transaction key record (TKEY)
9
/// This record is used to establish a shared key between two hosts.
10
0
#[derive(Copy, Clone, Debug, PartialEq)]
11
pub struct TKey<'a> {
12
    /// The algorithm used to generate the key.
13
    pub algorithm: DnsName<'a>,
14
    /// The time the key was generated.
15
    pub inception: u32,
16
    /// The time the key will expire.
17
    pub expiration: u32,
18
    /// The mode of the key.
19
    pub mode: u16,
20
    /// The error that occurred.
21
    pub error: u16,
22
    /// The key data.
23
    pub key: Characters<'a>,
24
    /// The other data.
25
    pub other: Characters<'a>,
26
}
27
28
impl<'a> RDataParse<'a> for TKey<'a> {
29
    #[inline]
30
47
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
31
47
        let algorithm = DnsName::parse(rdata.buffer, i)?;
32
35
        let inception = u32::parse(rdata.buffer, i)?;
33
34
        let expiration = u32::parse(rdata.buffer, i)?;
34
33
        let mode = u16::parse(rdata.buffer, i)?;
35
32
        let error = u16::parse(rdata.buffer, i)?;
36
31
        let key = Characters::parse(rdata.buffer, i)?;
37
13
        let other = Characters::parse(rdata.buffer, i)?;
38
39
8
        Ok(Self {
40
8
            algorithm,
41
8
            inception,
42
8
            expiration,
43
8
            mode,
44
8
            error,
45
8
            key,
46
8
            other,
47
8
        })
48
47
    }
49
}
50
51
impl<'a> WriteBytes for TKey<'a> {
52
    #[inline]
53
    fn write<
54
        const PTR_STORAGE: usize,
55
        const DNS_SECTION: DnsSection,
56
        B: Buffer,
57
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
58
0
        self.algorithm.write(message)?;
59
0
        self.inception.write(message)?;
60
0
        self.expiration.write(message)?;
61
0
        self.mode.write(message)?;
62
0
        self.error.write(message)?;
63
0
        self.key.write(message)?;
64
0
        self.other.write(message)
65
0
    }
66
}
67
68
impl<'a> TKey<'a> {
69
    #[inline(always)]
70
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
71
        Ok(self.algorithm.byte_len()? + 4 + 4 + 2 + 2 + self.key.byte_len()? + self.other.byte_len()?)
72
    }
73
}
74
75
#[cfg(test)]
76
mod test {
77
    use crate::rdata::testutils::parse_write_test;
78
79
    use super::*;
80
81
    parse_write_test!(
82
        25,
83
        [
84
            0x03, b'w', b'w', b'w', 0x00, // algorithm
85
            0x00, 0x00, 0x00, 0x0a, // inception
86
            0x00, 0x00, 0x00, 0x0b, // expiration
87
            0x00, 0x0c, // mode
88
            0x00, 0x0d, // error
89
            0x03, b'w', b'w', b'w', // key
90
            0x03, b'w', b'w', b'w', // other
91
        ],
92
        TKey {
93
            algorithm: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
94
            inception: 10,
95
            expiration: 11,
96
            mode: 12,
97
            error: 13,
98
            key: unsafe { Characters::new_unchecked(b"www") },
99
            other: unsafe { Characters::new_unchecked(b"www") },
100
        },
101
    );
102
}
/mnt/h/flex-dns/src/rdata/tlsa.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Transport Layer Security Authentication (TLSA) Record
8
/// This record is used to associate a TLS server certificate or public key with
9
/// the domain name where the record is found, thus forming a "TLSA certificate association".
10
/// This record type is described in [RFC 6698](https://tools.ietf.org/html/rfc6698).
11
0
#[derive(Copy, Clone, Debug, PartialEq)]
12
pub struct Tlsa<'a> {
13
    usage: u8,
14
    selector: u8,
15
    matching_type: u8,
16
    certificate_association_data: Characters<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for Tlsa<'a> {
20
    #[inline]
21
19
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
19
        let usage = u8::parse(rdata, i)?;
23
18
        let selector = u8::parse(rdata, i)?;
24
18
        let matching_type = u8::parse(rdata, i)?;
25
17
        let certificate_association_data = Characters::parse(rdata, i)?;
26
27
5
        Ok(Self {
28
5
            usage,
29
5
            selector,
30
5
            matching_type,
31
5
            certificate_association_data,
32
5
        })
33
19
    }
34
}
35
36
impl<'a> WriteBytes for Tlsa<'a> {
37
    #[inline]
38
    fn write<
39
        const PTR_STORAGE: usize,
40
        const DNS_SECTION: DnsSection,
41
        B: Buffer,
42
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
43
0
        self.usage.write(message)?;
44
0
        self.selector.write(message)?;
45
0
        self.matching_type.write(message)?;
46
0
        self.certificate_association_data.write(message)
47
0
    }
48
}
49
50
impl<'a> Tlsa<'a> {
51
    #[inline(always)]
52
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
53
        Ok(3 + self.certificate_association_data.byte_len()?)
54
    }
55
}
56
57
#[cfg(test)]
58
mod test {
59
    use crate::rdata::testutils::parse_write_test;
60
61
    use super::*;
62
63
    parse_write_test!(
64
        7,
65
        [
66
            0x0a, // usage
67
            0x0b, // selector
68
            0x0c, // matching type
69
            0x03, // length of certificate association data
70
            0x77, 0x77, 0x77, // certificate association data
71
        ],
72
        Tlsa {
73
            usage: 10,
74
            selector: 11,
75
            matching_type: 12,
76
            certificate_association_data: unsafe { Characters::new_unchecked(b"www") },
77
        },
78
    );
79
}
/mnt/h/flex-dns/src/rdata/tsig.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::name::DnsName;
4
use crate::parse::Parse;
5
use crate::rdata::{RData, RDataParse};
6
use crate::write::WriteBytes;
7
8
/// # Transaction signature record (TSIG)
9
/// This record is used to authenticate dynamic updates as coming from an
10
/// approved client, and to authenticate responses as coming from an approved
11
/// recursive server.
12
0
#[derive(Copy, Clone, Debug, PartialEq)]
13
pub struct TSig<'a> {
14
    /// The name of the algorithm in domain name syntax.
15
    pub algorithm: DnsName<'a>,
16
    /// The time that the signature was generated.
17
    pub time_signed: u64,
18
    /// The Fudge value is an unsigned 8-bit field that specifies the allowed
19
    /// time difference in seconds.
20
    pub fudge: u8,
21
    /// The MAC is a variable length octet string containing the message
22
    /// authentication code.
23
    pub mac: Characters<'a>,
24
    /// The original ID of the message.
25
    pub original_id: u16,
26
    /// The error field is an unsigned 16-bit field that contains the extended
27
    /// RCODE covering TSIG processing.
28
    pub error: u16,
29
    /// The other field is a variable length octet string that contains
30
    /// information that may be used by the server to complete the transaction.
31
    pub other: Characters<'a>,
32
}
33
34
impl<'a> RDataParse<'a> for TSig<'a> {
35
    #[inline]
36
42
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
37
42
        let algorithm = DnsName::parse(rdata, i)?;
38
27
        let time_signed = u64::parse(rdata, i)?;
39
25
        let fudge = u8::parse(rdata, i)?;
40
24
        let mac = Characters::parse(rdata, i)?;
41
14
        let original_id = u16::parse(rdata, i)?;
42
13
        let error = u16::parse(rdata, i)?;
43
11
        let other = Characters::parse(rdata, i)?;
44
45
5
        Ok(Self {
46
5
            algorithm,
47
5
            time_signed,
48
5
            fudge,
49
5
            mac,
50
5
            original_id,
51
5
            error,
52
5
            other,
53
5
        })
54
42
    }
55
}
56
57
impl<'a> WriteBytes for TSig<'a> {
58
    #[inline]
59
    fn write<
60
        const PTR_STORAGE: usize,
61
        const DNS_SECTION: DnsSection,
62
        B: Buffer,
63
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
64
0
        self.algorithm.write(message)?;
65
0
        self.time_signed.write(message)?;
66
0
        self.fudge.write(message)?;
67
0
        self.mac.write(message)?;
68
0
        self.original_id.write(message)?;
69
0
        self.error.write(message)?;
70
0
        self.other.write(message)
71
0
    }
72
}
73
74
impl<'a> TSig<'a> {
75
    #[inline(always)]
76
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
77
        Ok(self.algorithm.byte_len()? + 10 + self.mac.byte_len()? + self.other.byte_len()?)
78
    }
79
}
80
81
#[cfg(test)]
82
mod test {
83
    use crate::rdata::testutils::parse_write_test;
84
85
    use super::*;
86
87
    parse_write_test!(
88
        26,
89
        [
90
            0x03, b'w', b'w', b'w', 0x00, // algorithm
91
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, // time_signed
92
            0x0b, // fudge
93
            0x03, 0x77, 0x77, 0x77, // mac
94
            0x00, 0x0c, // original_id
95
            0x00, 0x0d, // error
96
            0x03, 0x77, 0x77, 0x77, // other
97
        ],
98
        TSig {
99
            algorithm: unsafe { DnsName::from_bytes_unchecked(b"\x03www\x00") },
100
            time_signed: 10,
101
            fudge: 11,
102
            mac: unsafe { Characters::new_unchecked(b"www") },
103
            original_id: 12,
104
            error: 13,
105
            other: unsafe { Characters::new_unchecked(b"www") },
106
        },
107
    );
108
}
/mnt/h/flex-dns/src/rdata/txt.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, DnsSection};
2
use crate::rdata::{RData, RDataParse};
3
use crate::write::WriteBytes;
4
5
/// # The txt record
6
/// This record is used to hold arbitrary text data.
7
0
#[derive(Copy, Clone, Debug, PartialEq)]
8
pub struct Txt<'a> {
9
    /// The text data
10
    data: &'a [u8],
11
}
12
13
#[macro_export]
14
macro_rules! dns_txt {
15
    ($value:expr $(, $values:expr)* $(,)?) => {
16
        {
17
            const TXT: [u8; { $value.len() + 1 $(+ $values.len() + 1)* }] = {
18
                let mut result = [0; $value.len() + 1 $(+ $values.len() + 1)*];
19
                result[0] = $value.len() as u8;
20
21
                let mut index = 1;
22
                let mut r_index = 0;
23
                loop {
24
                    if r_index == $value.len() {
25
                        break;
26
                    }
27
28
                    result[index] = $value[r_index];
29
                    r_index += 1;
30
                    index += 1;
31
                }
32
33
                $(
34
                    result[index] = $values.len() as u8;
35
                    index += 1;
36
37
                    let mut r_index = 0;
38
                    loop {
39
                        if r_index == $values.len() {
40
                            break;
41
                        }
42
43
                        result[index] = $values[r_index];
44
                        r_index += 1;
45
                        index += 1;
46
                    }
47
                )*
48
49
                result
50
            };
51
52
            unsafe { Txt::new_unchecked(&TXT) }
53
        }
54
    };
55
}
56
57
impl<'a> RDataParse<'a> for Txt<'a> {
58
    #[inline]
59
30
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
60
30
        let data = &rdata.buffer[*i..*i + rdata.len];
61
30
        *i += rdata.len;
62
30
63
30
        Ok(Self {
64
30
            data,
65
30
        })
66
30
    }
67
}
68
69
impl<'a> WriteBytes for Txt<'a> {
70
    #[inline]
71
0
    fn write<
72
0
        const PTR_STORAGE: usize,
73
0
        const DNS_SECTION: DnsSection,
74
0
        B: Buffer,
75
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
76
0
        message.write_bytes(self.data)
77
0
    }
78
}
79
80
impl<'a> Txt<'a> {
81
    #[inline]
82
0
    pub fn new(data: &'a [u8]) -> Result<Self, DnsMessageError> {
83
0
        for r in (TxtIterator {
84
0
            data,
85
            pos: 0,
86
        }) {
87
0
            r?;
88
        }
89
90
0
        Ok(Self {
91
0
            data,
92
0
        })
93
0
    }
94
95
    #[inline]
96
0
    pub const unsafe fn new_unchecked(data: &'a [u8]) -> Self {
97
0
        Self {
98
0
            data,
99
0
        }
100
0
    }
101
102
    #[inline(always)]
103
    pub fn iter(&self) -> TxtIterator<'a> {
104
        TxtIterator {
105
            data: self.data,
106
            pos: 0,
107
        }
108
    }
109
110
    #[inline(always)]
111
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
112
        Ok(self.data.len())
113
    }
114
}
115
116
0
#[derive(Copy, Clone, Debug)]
117
pub struct TxtIterator<'a> {
118
    data: &'a [u8],
119
    pos: usize,
120
}
121
122
impl<'a> Iterator for TxtIterator<'a> {
123
    type Item = Result<&'a [u8], DnsMessageError>;
124
125
0
    fn next(&mut self) -> Option<Self::Item> {
126
0
        if self.pos >= self.data.len() {
127
0
            return None;
128
0
        }
129
0
130
0
        let len = self.data[self.pos] as usize;
131
0
132
0
        if len == 0 && self.pos + 1 == self.data.len() {
133
0
            return None;
134
0
        } else if len == 0 {
135
0
            return Some(Err(DnsMessageError::DnsError(DnsError::InvalidTxtRecord)));
136
0
        }
137
0
138
0
        self.pos += 1;
139
0
140
0
        let end = self.pos + len;
141
0
142
0
        if end > self.data.len() {
143
0
            return Some(Err(DnsMessageError::DnsError(DnsError::InvalidTxtRecord)));
144
0
        }
145
0
146
0
        let result = &self.data[self.pos..end];
147
0
        self.pos = end;
148
0
149
0
        Some(Ok(result))
150
0
    }
151
}
/mnt/h/flex-dns/src/rdata/uri.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Uniform resource identifier record (URI)
8
/// This record is used to publish mappings from hostnames to URIs.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct Uri<'a> {
11
    /// The priority of this URI record. Lower values are preferred.
12
    pub priority: u16,
13
    /// The weight of this URI record. Higher values are preferred.
14
    pub weight: u16,
15
    /// The target URI.
16
    pub target: Characters<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for Uri<'a> {
20
    #[inline]
21
63
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
63
        let priority = u16::parse(rdata, i)?;
23
62
        let weight = u16::parse(rdata, i)?;
24
57
        let target = Characters::parse(rdata, i)?;
25
26
39
        Ok(Self {
27
39
            priority,
28
39
            weight,
29
39
            target,
30
39
        })
31
63
    }
32
}
33
34
impl<'a> WriteBytes for Uri<'a> {
35
    #[inline]
36
    fn write<
37
        const PTR_STORAGE: usize,
38
        const DNS_SECTION: DnsSection,
39
        B: Buffer,
40
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
41
0
        self.priority.write(message)?;
42
0
        self.weight.write(message)?;
43
0
        self.target.write(message)
44
0
    }
45
}
46
47
impl<'a> Uri<'a> {
48
    #[inline(always)]
49
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
50
        Ok(4 + self.target.byte_len()?)
51
    }
52
}
53
54
#[cfg(test)]
55
mod test {
56
    use crate::rdata::testutils::parse_write_test;
57
58
    use super::*;
59
60
    parse_write_test!(
61
        8,
62
        [
63
            0x00, 0x0e, // priority
64
            0x00, 0x0e, // weight
65
            0x03, // length of "www"
66
            b'w', b'w', b'w', // "www"
67
        ],
68
        Uri {
69
            priority: 14,
70
            weight: 14,
71
            target: unsafe { Characters::new_unchecked(b"www") },
72
        },
73
    );
74
}
/mnt/h/flex-dns/src/rdata/zonemd.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
2
use crate::characters::Characters;
3
use crate::parse::Parse;
4
use crate::rdata::{RData, RDataParse};
5
use crate::write::WriteBytes;
6
7
/// # Message digest for DNS zone record (ZONEMD)
8
/// This record is used to publish a message digest for a DNS zone.
9
0
#[derive(Copy, Clone, Debug, PartialEq)]
10
pub struct ZoneMd<'a> {
11
    /// algorithm is the algorithm of the digest
12
    pub algorithm: u8,
13
    /// digest_type is the algorithm used to construct the digest
14
    pub digest_type: u8,
15
    /// digest is the digest of the zone
16
    pub digest: Characters<'a>,
17
}
18
19
impl<'a> RDataParse<'a> for ZoneMd<'a> {
20
    #[inline]
21
10
    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
22
10
        let algorithm = u8::parse(rdata, i)?;
23
9
        let digest_type = u8::parse(rdata, i)?;
24
8
        let digest = Characters::parse(rdata, i)?;
25
26
4
        Ok(Self {
27
4
            algorithm,
28
4
            digest_type,
29
4
            digest
30
4
        })
31
10
    }
32
}
33
34
impl<'a> WriteBytes for ZoneMd<'a> {
35
    #[inline]
36
    fn write<
37
        const PTR_STORAGE: usize,
38
        const DNS_SECTION: DnsSection,
39
        B: Buffer,
40
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
41
0
        self.algorithm.write(message)?;
42
0
        self.digest_type.write(message)?;
43
0
        self.digest.write(message)
44
0
    }
45
}
46
47
impl<'a> ZoneMd<'a> {
48
    #[inline(always)]
49
    pub(crate) fn byte_len(&self) -> Result<usize, DnsMessageError> {
50
        Ok(2 + self.digest.byte_len()?)
51
    }
52
}
53
54
#[cfg(test)]
55
mod test {
56
    use crate::rdata::testutils::parse_write_test;
57
58
    use super::*;
59
60
    parse_write_test!(
61
        6,
62
        [
63
            0x0e, // algorithm
64
            0x00, // digest_type
65
            0x03, // digest length
66
            b'w', b'w', b'w', // digest
67
        ],
68
        ZoneMd {
69
            algorithm: 14,
70
            digest_type: 0,
71
            digest: unsafe { Characters::new_unchecked(b"www") },
72
        },
73
    );
74
}
/mnt/h/flex-dns/src/write.rs
Line
Count
Source (jump to first uncovered line)
1
use core::net::{Ipv4Addr, Ipv6Addr};
2
use crate::{Buffer, DnsMessage, DnsMessageError, DnsSection};
3
4
pub(crate) trait WriteBytes {
5
    fn write<
6
        const PTR_STORAGE: usize,
7
        const DNS_SECTION: DnsSection,
8
        B: Buffer,
9
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError>;
10
}
11
12
impl WriteBytes for u8 {
13
    #[inline(always)]
14
0
    fn write<
15
0
        const PTR_STORAGE: usize,
16
0
        const DNS_SECTION: DnsSection,
17
0
        B: Buffer,
18
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
19
0
        message.write_bytes(&[*self])
20
0
    }
21
}
22
23
impl WriteBytes for u16 {
24
    #[inline(always)]
25
0
    fn write<
26
0
        const PTR_STORAGE: usize,
27
0
        const DNS_SECTION: DnsSection,
28
0
        B: Buffer,
29
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
30
0
        message.write_bytes(&self.to_be_bytes())
31
0
    }
32
}
33
34
impl WriteBytes for u32 {
35
    #[inline(always)]
36
0
    fn write<
37
0
        const PTR_STORAGE: usize,
38
0
        const DNS_SECTION: DnsSection,
39
0
        B: Buffer,
40
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
41
0
        message.write_bytes(&self.to_be_bytes())
42
0
    }
43
}
44
45
impl WriteBytes for u64 {
46
    #[inline(always)]
47
0
    fn write<
48
0
        const PTR_STORAGE: usize,
49
0
        const DNS_SECTION: DnsSection,
50
0
        B: Buffer,
51
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
52
0
        message.write_bytes(&self.to_be_bytes())
53
0
    }
54
}
55
56
impl<const SIZE: usize> WriteBytes for [u8; SIZE] {
57
    #[inline(always)]
58
0
    fn write<
59
0
        const PTR_STORAGE: usize,
60
0
        const DNS_SECTION: DnsSection,
61
0
        B: Buffer,
62
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
63
0
        message.write_bytes(self)
64
0
    }
65
}
66
67
impl WriteBytes for Ipv4Addr {
68
    #[inline(always)]
69
0
    fn write<
70
0
        const PTR_STORAGE: usize,
71
0
        const DNS_SECTION: DnsSection,
72
0
        B: Buffer,
73
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
74
0
        message.write_bytes(&self.octets())
75
0
    }
76
}
77
78
impl WriteBytes for Ipv6Addr {
79
    #[inline(always)]
80
0
    fn write<
81
0
        const PTR_STORAGE: usize,
82
0
        const DNS_SECTION: DnsSection,
83
0
        B: Buffer,
84
0
    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<(), DnsMessageError> {
85
0
        message.write_bytes(&self.octets())
86
0
    }
87
}