1mod cmp;
8mod inherent;
9mod iter;
10
11pub use self::iter::{CharacterStrings, Labels, Questions, Records};
12
13use core::{
14 fmt::{Debug, Display},
15 ops::{Bound, Range, RangeBounds},
16};
17
18use byteorder::{ByteOrder, NetworkEndian};
19
20use crate::{core::Type, seen::Seen};
21
22pub type Result<V, E> = core::result::Result<(V, Range<usize>), E>;
25
26pub trait View<'s>: 's {
28 type Error: Debug + Display;
29
30 fn view(source: &'s [u8], range: impl RangeBounds<usize>) -> Result<Self, Self::Error>
31 where
32 Self: Sized,
33 {
34 let start = match range.start_bound() {
35 Bound::Included(&x) => x,
36 Bound::Excluded(&x) => x + 1,
37 Bound::Unbounded => 0,
38 };
39 let stop = match range.end_bound() {
40 Bound::Included(&x) => x + 1,
41 Bound::Excluded(&x) => x,
42 Bound::Unbounded => source.len(),
43 };
44
45 Self::view_range(source, start..stop)
46 }
47
48 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error>
49 where
50 Self: Sized;
51}
52
53pub trait BorrowedView<'s> {
54 fn source(&self) -> &'s [u8];
55 fn offset(&self) -> usize;
56 fn len(&self) -> usize;
57 fn as_bytes(&self) -> &'s [u8] {
58 &self.source()[self.offset()..][..self.len()]
59 }
60}
61
62pub trait ViewToOwned<Owned> {
63 fn to_owned(&self) -> Owned;
64}
65
66#[derive(Debug, Clone)]
77pub struct Message<'s> {
78 source: &'s [u8],
79 offset: usize,
80 qd_len: usize,
81 an_len: usize,
82 ns_len: usize,
83 ar_len: usize,
84 opt: Option<Extension<'s>>,
85}
86
87#[derive(Debug, Clone)]
98pub struct Header<'s> {
99 source: &'s [u8],
100 offset: usize,
101}
102
103#[derive(Debug, Clone)]
114pub struct Question<'s> {
115 source: &'s [u8],
116 offset: usize,
117 len: usize,
118}
119
120#[derive(Debug, Clone)]
131pub struct Record<'s> {
132 source: &'s [u8],
133 offset: usize,
134 name_len: usize,
135 rdata_len: usize,
136}
137
138#[derive(Debug, Clone)]
149pub struct Name<'s> {
150 source: &'s [u8],
151 offset: usize,
152 len: usize,
153}
154
155#[derive(Debug, Clone)]
166pub struct Label<'s> {
167 source: &'s [u8],
168 offset: usize,
169 len: usize,
170}
171
172#[derive(Debug, Clone)]
186pub struct Extension<'s> {
187 pub inner: Record<'s>,
188}
189
190pub struct CharacterString<'s> {
201 source: &'s [u8],
202 offset: usize,
203 len: usize,
204}
205
206error!(BoundsError);
207#[derive(Debug, displaydoc::Display)]
208#[prefix_enum_doc_attributes]
209pub enum BoundsError {
211 BackwardsRange(usize, usize),
213
214 RangeOverflow(usize, usize),
216
217 ReadOverflow(usize, usize, usize),
219}
220
221error!(MessageError(_edns_version, [inner: inner]));
222#[derive(Debug, displaydoc::Display)]
224pub struct MessageError(pub Option<u8>, pub MessageErrorKind);
225
226error!(MessageErrorKind, Header, Question, Record, Extension);
227#[derive(Debug, displaydoc::Display)]
228pub enum MessageErrorKind {
229 Header(BoundsError),
231
232 Question(QuestionError),
234
235 Record(RecordError),
237
238 Extension(ExtensionError),
240
241 MisplacedOptRecord,
243
244 MultipleOptRecords,
246}
247
248error!(QuestionError, Bounds, Name);
249#[derive(Debug, displaydoc::Display)]
251#[prefix_enum_doc_attributes]
252pub enum QuestionError {
253 Bounds(BoundsError),
255
256 Name(NameError),
258}
259
260error!(RecordError, Bounds, Name);
261#[derive(Debug, displaydoc::Display)]
263#[prefix_enum_doc_attributes]
264pub enum RecordError {
265 Bounds(BoundsError),
267
268 Name(NameError),
270}
271
272error!(NameError, Label);
273#[derive(Debug, displaydoc::Display)]
275#[prefix_enum_doc_attributes]
276pub enum NameError {
277 Label(LabelError),
279
280 PointerCycle,
282
283 TooLong,
285}
286
287error!(LabelError, Bounds);
288#[derive(Debug, displaydoc::Display)]
290#[prefix_enum_doc_attributes]
291pub enum LabelError {
292 Bounds(BoundsError),
294
295 ReservedLength,
297}
298
299error!(ExtensionError);
300#[derive(Debug, displaydoc::Display)]
302#[prefix_enum_doc_attributes]
303pub enum ExtensionError {
304 BadName,
306
307 UnimplementedVersion,
309}
310
311impl<'s> View<'s> for Message<'s> {
312 type Error = MessageError;
313
314 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
315 use self::MessageErrorKind as Kind;
316
317 let (header, rest) =
318 Header::view(source, range.clone()).map_err(|e| MessageError(None, Kind::Header(e)))?;
319
320 let qdcount = header.qdcount();
321 let ancount = header.ancount();
322 let nscount = header.nscount();
323 let arcount = header.arcount();
324
325 let mut next = rest;
326 let section = next.clone();
327
328 for _ in 0..qdcount {
329 let (_, rest) =
330 Question::view(source, next).map_err(|e| MessageError(None, Kind::Question(e)))?;
331 next = rest;
332 }
333
334 let qd_len = next.start - section.start;
335 let section = next.clone();
336
337 for _ in 0..ancount {
338 let (record, rest) =
339 Record::view(source, next).map_err(|e| MessageError(None, Kind::Record(e)))?;
340 next = rest;
341
342 if record.r#type() == Type::OPT {
343 let version = record.ttl().edns_version();
344 return Err(MessageError(Some(version), Kind::MisplacedOptRecord));
345 }
346 }
347
348 let an_len = next.start - section.start;
349 let section = next.clone();
350
351 for _ in 0..nscount {
352 let (record, rest) =
353 Record::view(source, next).map_err(|e| MessageError(None, Kind::Record(e)))?;
354 next = rest;
355
356 if record.r#type() == Type::OPT {
357 let version = record.ttl().edns_version();
358 return Err(MessageError(Some(version), Kind::MisplacedOptRecord));
359 }
360 }
361
362 let ns_len = next.start - section.start;
363 let section = next.clone();
364 let mut opt = None;
365 let mut edns_version = None;
366
367 for _ in 0..arcount {
368 let (record, rest) = Record::view(source, next)
369 .map_err(|e| MessageError(edns_version, Kind::Record(e)))?;
370 next = rest;
371
372 if record.r#type() == Type::OPT {
373 if opt.is_some() {
374 return Err(MessageError(edns_version, Kind::MultipleOptRecords));
375 }
376 edns_version = Some(record.ttl().edns_version());
377 opt = Some(
378 Extension::wrap(record)
379 .map_err(|e| MessageError(edns_version, Kind::Extension(e)))?,
380 );
381 }
382 }
383
384 let ar_len = next.start - section.start;
385 let rest = next;
386
387 Ok((
388 Message {
389 source,
390 opt,
391 offset: range.start,
392 qd_len,
393 an_len,
394 ns_len,
395 ar_len,
396 },
397 rest,
398 ))
399 }
400}
401impl<'s> BorrowedView<'s> for Message<'s> {
402 fn source(&self) -> &'s [u8] {
403 self.source
404 }
405 fn offset(&self) -> usize {
406 self.offset
407 }
408 fn len(&self) -> usize {
409 self.header().len() + self.qd_len + self.an_len + self.ns_len + self.ar_len
410 }
411}
412
413impl<'s> View<'s> for Header<'s> {
414 type Error = BoundsError;
415
416 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
417 let mut rest = range.clone();
418
419 assert(source, &rest, 12)?;
420 rest.start += 12;
421
422 Ok((
423 Header {
424 source,
425 offset: range.start,
426 },
427 rest,
428 ))
429 }
430}
431impl<'s> BorrowedView<'s> for Header<'s> {
432 fn source(&self) -> &'s [u8] {
433 self.source
434 }
435 fn offset(&self) -> usize {
436 self.offset
437 }
438 fn len(&self) -> usize {
439 12
440 }
441}
442
443impl<'s> View<'s> for Question<'s> {
444 type Error = QuestionError;
445
446 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
447 let (_, mut rest) = Name::view(source, range.clone()).map_err(Self::Error::Name)?;
448
449 assert(source, &rest, 4).map_err(Self::Error::Bounds)?;
450 rest.start += 4;
451
452 Ok((
453 Question {
454 source,
455 offset: range.start,
456 len: rest.start - range.start,
457 },
458 rest,
459 ))
460 }
461}
462impl<'s> BorrowedView<'s> for Question<'s> {
463 fn source(&self) -> &'s [u8] {
464 self.source
465 }
466 fn offset(&self) -> usize {
467 self.offset
468 }
469 fn len(&self) -> usize {
470 self.len
471 }
472}
473
474impl<'s> View<'s> for Record<'s> {
475 type Error = RecordError;
476
477 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
478 let (_, mut rest) = Name::view(source, range.clone()).map_err(Self::Error::Name)?;
479 let name_len = rest.start - range.start;
480
481 assert(source, &rest, 8).map_err(Self::Error::Bounds)?;
482 rest.start += 8;
483
484 let (rdlength, mut rest) = u16::view(source, rest).map_err(Self::Error::Bounds)?;
485 let rdata_len = usize::from(rdlength);
486
487 assert(source, &rest, rdata_len).map_err(Self::Error::Bounds)?;
488 rest.start += rdata_len;
489
490 Ok((
491 Record {
492 source,
493 offset: range.start,
494 name_len,
495 rdata_len,
496 },
497 rest,
498 ))
499 }
500}
501impl<'s> BorrowedView<'s> for Record<'s> {
502 fn source(&self) -> &'s [u8] {
503 self.source
504 }
505 fn offset(&self) -> usize {
506 self.offset
507 }
508 fn len(&self) -> usize {
509 self.name_len + 10 + self.rdata_len
510 }
511}
512
513impl<'s> View<'s> for Name<'s> {
514 type Error = NameError;
515
516 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
517 let mut result = None;
518 let mut next = range.clone();
519 let mut seen = Seen::default();
520 let mut len = 0;
521
522 let rest = loop {
523 let (label, rest) = Label::view(source, next.clone()).map_err(Self::Error::Label)?;
524
525 if label.is_null() {
526 break result.unwrap_or(rest);
527 } else if let Some(offset) = label.pointer() {
528 if seen.see(offset) {
529 return Err(Self::Error::PointerCycle);
530 }
531
532 next = offset.into()..source.len();
533 result.get_or_insert_with(|| rest.clone());
534 } else {
535 len += label.len();
536
537 if len > 255 {
538 return Err(Self::Error::TooLong);
539 }
540
541 next = rest;
542 }
543 };
544
545 let offset = range.start;
546 let len = rest.start - offset;
547
548 Ok((
549 Name {
550 source,
551 offset,
552 len,
553 },
554 rest,
555 ))
556 }
557}
558impl<'s> BorrowedView<'s> for Name<'s> {
559 fn source(&self) -> &'s [u8] {
560 self.source
561 }
562 fn offset(&self) -> usize {
563 self.offset
564 }
565 fn len(&self) -> usize {
566 self.len
567 }
568}
569
570impl<'s> View<'s> for Label<'s> {
571 type Error = LabelError;
572
573 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
574 let (length, mut rest) = u8::view(source, range.clone()).map_err(Self::Error::Bounds)?;
575
576 let len = if length < 64 {
577 usize::from(length)
578 } else if length < 192 {
579 return Err(Self::Error::ReservedLength);
580 } else {
581 1
582 };
583
584 assert(source, &rest, len).map_err(Self::Error::Bounds)?;
585 rest.start += len;
586
587 Ok((
588 Label {
589 source,
590 offset: range.start,
591 len: rest.start - range.start,
592 },
593 rest,
594 ))
595 }
596}
597impl<'s> BorrowedView<'s> for Label<'s> {
598 fn source(&self) -> &'s [u8] {
599 self.source
600 }
601 fn offset(&self) -> usize {
602 self.offset
603 }
604 fn len(&self) -> usize {
605 self.len
606 }
607}
608
609impl<'s> BorrowedView<'s> for Extension<'s> {
610 fn source(&self) -> &'s [u8] {
611 self.inner.source()
612 }
613 fn offset(&self) -> usize {
614 self.inner.offset()
615 }
616 fn len(&self) -> usize {
617 self.inner.len()
618 }
619}
620
621impl<'s> View<'s> for CharacterString<'s> {
622 type Error = BoundsError;
623
624 fn view_range(source: &'s [u8], range: Range<usize>) -> Result<Self, Self::Error> {
625 let (length, mut rest) = u8::view(source, range.clone())?;
626
627 assert(source, &rest, length.into())?;
628 rest.start += usize::from(length);
629
630 Ok((
631 CharacterString {
632 source,
633 offset: range.start,
634 len: rest.start - range.start,
635 },
636 rest,
637 ))
638 }
639}
640impl<'s> BorrowedView<'s> for CharacterString<'s> {
641 fn source(&self) -> &'s [u8] {
642 self.source
643 }
644 fn offset(&self) -> usize {
645 self.offset
646 }
647 fn len(&self) -> usize {
648 self.len
649 }
650}
651
652impl View<'_> for u32 {
653 type Error = BoundsError;
654
655 fn view_range(source: &[u8], mut range: Range<usize>) -> Result<Self, Self::Error> {
656 assert(source, &range, 4)?;
657
658 let result = NetworkEndian::read_u32(&source[range.start..]);
659
660 range.start += 4;
661
662 Ok((result, range))
663 }
664}
665
666impl View<'_> for u16 {
667 type Error = BoundsError;
668
669 fn view_range(source: &[u8], mut range: Range<usize>) -> Result<Self, Self::Error> {
670 assert(source, &range, 2)?;
671
672 let result = NetworkEndian::read_u16(&source[range.start..]);
673
674 range.start += 2;
675
676 Ok((result, range))
677 }
678}
679
680impl View<'_> for u8 {
681 type Error = BoundsError;
682
683 fn view_range(source: &[u8], mut range: Range<usize>) -> Result<Self, Self::Error> {
684 assert(source, &range, 1)?;
685
686 let result = source[range.start];
687
688 range.start += 1;
689
690 Ok((result, range))
691 }
692}
693
694pub(crate) fn assert(
695 source: &[u8],
696 range: &Range<usize>,
697 len: usize,
698) -> core::result::Result<(), BoundsError> {
699 if range.end < range.start {
700 return Err(BoundsError::BackwardsRange(range.start, range.end));
701 }
702
703 if source.len() < range.end {
704 return Err(BoundsError::RangeOverflow(range.end, source.len()));
705 }
706
707 if range.end - range.start < len {
708 return Err(BoundsError::ReadOverflow(len, range.start, range.end));
709 }
710
711 Ok(())
712}
713
714#[cfg(test)]
715mod test {
716 use core::iter::once;
717
718 use arrayvec::ArrayVec;
719 use assert_matches::assert_matches;
720
721 use super::{Extension, Label, Message, Name, Question, Record, View};
722
723 type A12 = ArrayVec<u8, 4096>;
724
725 #[test]
726 fn message() {
727 use super::MessageError;
728 use super::MessageErrorKind as Kind;
729
730 let source = include_bytes!("../samples/daria.daz.cat.a.dns");
731 let len = source.len();
732
733 assert_matches!(
734 Message::view(source, 0..len),
735 Ok((
736 Message {
737 source: _,
738 opt: Some(Extension {
739 inner: Record {
740 source: _,
741 offset: 141,
742 name_len: 1,
743 rdata_len: 0
744 }
745 }),
746 offset: 0,
747 qd_len: 19,
748 an_len: 16,
749 ns_len: 66,
750 ar_len: 39
751 },
752 ref x
753 )) if *x == (len..len)
754 );
755
756 let header = b"\x13\x13\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00";
757 let question = b"\0\x00\x02\x00\x01";
758 let v0 = b"\0\x00\x29\x10\x00\x00\x00\x00\x00\x00\x00";
759 let v13 = b"\0\x00\x29\x10\x00\x00\x0D\x00\x00\x00\x00";
760
761 let source: A12 = header
762 .iter()
763 .copied()
764 .chain(question.iter().copied())
765 .chain(v13.iter().copied())
766 .collect();
767
768 assert_matches!(
769 Message::view(&source, ..),
770 Err(MessageError(Some(13), Kind::MisplacedOptRecord))
771 );
772
773 let header = b"\x13\x13\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00";
774
775 let source: A12 = header
776 .iter()
777 .copied()
778 .chain(question.iter().copied())
779 .chain(v13.iter().copied())
780 .collect();
781
782 assert_matches!(
783 Message::view(&source, ..),
784 Err(MessageError(Some(13), Kind::MisplacedOptRecord))
785 );
786
787 let header = b"\x13\x13\x00\x00\x00\x01\x00\x00\x00\x00\x00\x02";
788
789 let source: A12 = header
790 .iter()
791 .copied()
792 .chain(question.iter().copied())
793 .chain(v0.iter().copied())
794 .chain(v13.iter().copied())
795 .collect();
796
797 assert_matches!(
798 Message::view(&source, ..),
799 Err(MessageError(Some(0), Kind::MultipleOptRecords))
800 );
801 }
802
803 #[test]
804 fn question() {
805 assert_matches!(
806 Question::view(b"\0\xFF\xFE\xFF\xFE", 0..5),
807 Ok((Question { source: _, offset: 0, len: 5 }, ref x)) if *x == (5..5)
808 );
809 }
810
811 #[test]
812 fn record() {
813 assert_matches!(
814 Record::view(
815 b"\0\xFF\xFE\xFF\xFE\x00\x00\x0E\x10\x00\x00\x00",
816 0..12,
817 ),
818 Ok((
819 Record {
820 source: _,
821 offset: 0,
822 name_len: 1,
823 rdata_len: 0
824 },
825 ref x
826 )) if *x == (11..12)
827 );
828
829 assert_matches!(
830 Record::view(
831 b"\0\xFF\xFE\xFF\xFE\x00\x00\x0E\x10\x00\x01\x00",
832 0..12,
833 ),
834 Ok((
835 Record {
836 source: _,
837 offset: 0,
838 name_len: 1,
839 rdata_len: 1
840 },
841 ref x
842 )) if *x == (12..12)
843 );
844 }
845
846 #[test]
847 fn name() {
848 use super::{BoundsError, LabelError::Bounds, NameError::*};
849
850 assert_matches!(
851 Name::view(b"\x05daria\x03daz\x03cat\0", 0..15),
852 Ok((Name { source: _, offset: 0, len: 15 }, ref x)) if *x == (15..15)
853 );
854
855 assert_matches!(
856 Name::view(
857 b"\x05daria\x03daz\x03cat\0\x08charming\xC0\x06",
858 15..26,
859 ),
860 Ok((
861 Name {
862 source: _,
863 offset: 15,
864 len: 11
865 },
866 ref x
867 )) if *x == (26..26)
868 );
869
870 assert_matches!(
871 Name::view(
872 b"\x05daria\x03daz\x03cat\0\x08charming\xC0\x06\xC0\x0F",
873 26..28,
874 ),
875 Ok((
876 Name {
877 source: _,
878 offset: 26,
879 len: 2
880 },
881 ref x
882 )) if *x == (28..28)
883 );
884
885 assert_matches!(
886 Name::view(b"\xC0\x03", 0..2),
887 Err(Label(Bounds(BoundsError::BackwardsRange(3, 2))))
888 );
889 assert_matches!(
890 Name::view(b"\xC0\x02", 0..2),
891 Err(Label(Bounds(BoundsError::ReadOverflow(1, 2, 2))))
892 );
893 assert_matches!(
894 Name::view(b"\xC0\x01", 0..2),
895 Err(Label(Bounds(BoundsError::ReadOverflow(1, 2, 2))))
896 );
897
898 assert_matches!(
900 Name::view(b"\xC0\x02\0", 0..2),
901 Ok((Name { source: _, offset: 0, len: 2 }, ref x)) if *x == (2..2)
902 );
903
904 assert_matches!(Name::view(b"\xC0\x02\xC0\x00", 0..2), Err(PointerCycle));
906 assert_matches!(Name::view(b"\xC0\x00", 0..2), Err(PointerCycle));
907
908 let source = [2; 255].iter().copied().chain(once(0)).collect::<A12>();
910 assert_matches!(Name::view(&source, 0..256), Ok((Name { source: _, offset: 0, len: 256 }, ref x)) if *x == (256..256));
911
912 let source = [3; 256].iter().copied().chain(once(0)).collect::<A12>();
914 assert_matches!(Name::view(&source, 0..257), Err(TooLong));
915
916 let source = [3; 128]
918 .iter()
919 .copied()
920 .chain(once(0))
921 .chain([3; 128].iter().copied())
922 .chain([0xC0, 0x00].iter().copied())
923 .collect::<A12>();
924 assert_matches!(Name::view(&source, 129..259), Err(TooLong));
925 }
926
927 #[test]
928 #[rustfmt::skip]
929 fn label() {
930 use super::{BoundsError, LabelError::*};
931
932 assert_matches!(
933 Label::view(b"\0", 0..1),
934 Ok((Label { source: _, offset: 0, len: 1 }, ref x)) if *x == (1..1)
935 );
936
937 assert_matches!(
938 Label::view(b"\x01\0", 0..2),
939 Ok((Label { source: _, offset: 0, len: 2 }, ref x)) if *x == (2..2)
940 );
941
942 assert_matches!(
943 Label::view(b"\0\0", 0..2),
944 Ok((Label { source: _, offset: 0, len: 1 }, ref x)) if *x == (1..2)
945 );
946
947 assert_matches!(
948 Label::view(&[63; 64], 0..64),
949 Ok((Label { source: _, offset: 0, len: 64 }, ref x)) if *x == (64..64)
950 );
951
952 assert_matches!(Label::view(&[64; 65], 0..65), Err(ReservedLength));
953 assert_matches!(Label::view(&[191; 192], 191..192), Err(ReservedLength));
954
955 assert_matches!(
956 Label::view(&[192, 0], 0..2),
957 Ok((Label { source: _, offset: 0, len: 2 }, ref x)) if *x == (2..2)
958 );
959
960 assert_matches!(Label::view(b"\x01\0", 0..1), Err(Bounds(BoundsError::ReadOverflow(1, 1, 1))));
961 assert_matches!(Label::view(b"\x01", 0..1), Err(Bounds(BoundsError::ReadOverflow(1, 1, 1))));
962 assert_matches!(Label::view(b"", 0..0), Err(Bounds(BoundsError::ReadOverflow(1, 0, 0))));
963 }
964
965 #[test]
966 #[rustfmt::skip]
967 fn assert() {
968 use super::{assert, BoundsError};
969
970 assert_matches!(assert(b"", &(0..0), 0), Ok(()));
971 assert_matches!(assert(b"", &(0..0), 1), Err(BoundsError::ReadOverflow(1, 0, 0)));
972
973 assert_matches!(assert(b"", &(0..1), 0), Err(BoundsError::RangeOverflow(1, 0)));
974 assert_matches!(assert(b"", &(0..1), 1), Err(BoundsError::RangeOverflow(1, 0)));
975
976 assert_matches!(assert(b"~", &(0..0), 0), Ok(()));
977 assert_matches!(assert(b"~", &(0..0), 1), Err(BoundsError::ReadOverflow(1, 0, 0)));
978
979 assert_matches!(assert(b"~", &(0..1), 0), Ok(()));
980 assert_matches!(assert(b"~", &(0..1), 1), Ok(()));
981 assert_matches!(assert(b"~", &(0..1), 2), Err(BoundsError::ReadOverflow(2, 0, 1)));
982
983 assert_matches!(assert(b"~", &(1..1), 0), Ok(()));
984 assert_matches!(assert(b"~", &(1..1), 1), Err(BoundsError::ReadOverflow(1, 1, 1)));
985
986 assert_matches!(assert(b"~", &(1..0), 0), Err(BoundsError::BackwardsRange(1, 0)));
987
988 assert_matches!(assert(b"<>", &(0..2), 2), Ok(()));
989 assert_matches!(assert(b"<>", &(0..1), 2), Err(BoundsError::ReadOverflow(2, 0, 1)));
990 }
991}
992
993#[cfg(all(test, feature = "bench"))]
994mod bench {
995 extern crate test;
996
997 use test::Bencher;
998
999 use super::{Message, Name, Question, Record, View};
1000
1001 #[bench]
1002 fn message(bencher: &mut Bencher) {
1003 let source = include_bytes!("../samples/daria.daz.cat.a.dns");
1004 let len = source.len();
1005
1006 bencher.iter(|| Message::view(source, 0..len));
1007 }
1008
1009 #[bench]
1010 fn question(bencher: &mut Bencher) {
1011 bencher.iter(|| Question::view(b"\0\xFF\xFE\xFF\xFE", 0..5));
1012 }
1013
1014 #[bench]
1015 fn record(bencher: &mut Bencher) {
1016 bencher.iter(|| Record::view(b"\0\xFF\xFE\xFF\xFE\x00\x00\x0E\x10\x00\x00", 0..11));
1017 }
1018
1019 #[bench]
1020 fn name0(bencher: &mut Bencher) {
1021 bencher.iter(|| Name::view(b"\0", 0..1));
1022 }
1023
1024 #[bench]
1025 fn name1(bencher: &mut Bencher) {
1026 bencher.iter(|| Name::view(b"\x05daria\x03daz\x03cat\0", 0..15));
1027 }
1028
1029 #[bench]
1030 fn name2(bencher: &mut Bencher) {
1031 bencher.iter(|| Name::view(b"\x05daria\x03daz\x03cat\0\x08charming\xC0\x00", 15..26));
1032 }
1033
1034 #[bench]
1035 fn name3(bencher: &mut Bencher) {
1036 let mut source = alloc::vec![];
1037
1038 source.extend(b"\x08charming\xFF\xFF");
1039 source.resize(16383, b'\0');
1040 source.extend(b"\x03daz\x03cat\0");
1041
1042 bencher.iter(|| Name::view(&source, 0..11));
1043 }
1044}