1use super::super::cmp::CanonicalOrd;
7use super::super::wire::{FormError, ParseError};
8use super::dname::Dname;
9use super::label::{Label, LabelTypeError};
10use super::relative::RelativeDname;
11use super::traits::{FlattenInto, ToDname, ToLabelIter};
12use core::{cmp, fmt, hash};
13use octseq::builder::{
14 BuilderAppendError, EmptyBuilder, FreezeBuilder, FromBuilder,
15 OctetsBuilder,
16};
17use octseq::octets::Octets;
18use octseq::parse::Parser;
19
20#[derive(Clone, Copy)]
55pub struct ParsedDname<Octs> {
56 octets: Octs,
61
62 pos: usize,
64
65 name_len: u16,
69
70 compressed: bool,
74}
75
76impl<Octs> ParsedDname<Octs> {
77 pub fn is_compressed(&self) -> bool {
79 self.compressed
80 }
81
82 pub fn is_root(&self) -> bool {
84 self.name_len == 1
85 }
86
87 fn parser(&self) -> Parser<Octs>
89 where
90 Octs: AsRef<[u8]>,
91 {
92 let mut res = Parser::from_ref(&self.octets);
93 res.advance(self.pos).expect("illegal pos in ParsedDname");
94 res
95 }
96
97 pub fn ref_octets(&self) -> ParsedDname<&Octs> {
99 ParsedDname {
100 octets: &self.octets,
101 pos: self.pos,
102 name_len: self.name_len,
103 compressed: self.compressed,
104 }
105 }
106}
107
108impl<'a, Octs: Octets + ?Sized> ParsedDname<&'a Octs> {
109 #[must_use]
110 pub fn deref_octets(&self) -> ParsedDname<Octs::Range<'a>> {
111 ParsedDname {
112 octets: self.octets.range(..),
113 pos: self.pos,
114 name_len: self.name_len,
115 compressed: self.compressed,
116 }
117 }
118}
119
120impl<Octs: AsRef<[u8]>> ParsedDname<Octs> {
123 pub fn iter(&self) -> ParsedDnameIter {
125 ParsedDnameIter::new(self.octets.as_ref(), self.pos, self.name_len)
126 }
127
128 pub fn iter_suffixes(&self) -> ParsedSuffixIter<Octs> {
134 ParsedSuffixIter::new(self)
135 }
136
137 pub fn label_count(&self) -> usize {
139 self.iter().count()
140 }
141
142 pub fn first(&self) -> &Label {
144 self.iter().next().unwrap()
145 }
146
147 pub fn last(&self) -> &'static Label {
153 Label::root()
154 }
155
156 pub fn starts_with<N: ToLabelIter>(&self, base: &N) -> bool {
158 <Self as ToLabelIter>::starts_with(self, base)
159 }
160
161 pub fn ends_with<N: ToLabelIter>(&self, base: &N) -> bool {
163 <Self as ToLabelIter>::ends_with(self, base)
164 }
165
166 pub fn split_first(&mut self) -> Option<RelativeDname<Octs::Range<'_>>>
172 where
173 Octs: Octets,
174 {
175 if self.name_len == 1 {
176 return None;
177 }
178 let mut name_len = self.name_len;
179 let range = {
180 let mut parser = self.parser();
181 let len = loop {
182 match LabelType::peek(&parser).unwrap() {
183 LabelType::Normal(0) => {
184 unreachable!()
185 }
186 LabelType::Normal(label_len) => break label_len + 1,
187 LabelType::Compressed(pos) => {
188 parser.seek(pos).unwrap();
189 }
190 }
191 };
192 name_len -= len;
193 parser.pos()..parser.pos() + usize::from(len)
194 };
195 self.pos = range.end;
196 self.name_len = name_len;
197 Some(unsafe {
198 RelativeDname::from_octets_unchecked(self.octets.range(range))
199 })
200 }
201
202 pub fn parent(&mut self) -> bool {
207 if self.name_len == 1 {
208 return false;
209 }
210 let (pos, len) = {
211 let mut parser = self.parser();
212 let len = loop {
213 match LabelType::peek(&parser).unwrap() {
214 LabelType::Normal(0) => {
215 unreachable!()
216 }
217 LabelType::Normal(label_len) => break label_len + 1,
218 LabelType::Compressed(pos) => {
219 parser.seek(pos).unwrap();
220 }
221 }
222 };
223 (parser.pos() + usize::from(len), len)
224 };
225 self.name_len -= len;
226 self.pos = pos;
227 true
228 }
229}
230
231impl<Octs> ParsedDname<Octs> {
232 pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
233 parser: &mut Parser<'a, Src>,
234 ) -> Result<Self, ParseError> {
235 ParsedDname::parse_ref(parser).map(|res| res.deref_octets())
236 }
237}
238
239impl<'a, Octs: AsRef<[u8]> + ?Sized> ParsedDname<&'a Octs> {
240 pub fn parse_ref(
241 parser: &mut Parser<'a, Octs>,
242 ) -> Result<Self, ParseError> {
243 let mut name_len = 0;
244 let mut pos = parser.pos();
245
246 let mut ptr = loop {
251 match LabelType::parse(parser)? {
252 LabelType::Normal(0) => {
253 name_len += 1;
255 return Ok(ParsedDname {
256 octets: parser.octets_ref(),
257 pos,
258 name_len,
259 compressed: false,
260 });
261 }
262 LabelType::Normal(label_len) => {
263 parser.advance(usize::from(label_len))?;
264 name_len += label_len + 1;
265 if name_len >= 255 {
266 return Err(ParsedDnameError::LongName.into());
267 }
268 }
269 LabelType::Compressed(ptr) => {
270 break ptr;
271 }
272 }
273 };
274
275 let mut parser = *parser;
285 let mut compressed = true;
286 loop {
287 if ptr >= parser.pos() - 2 {
292 return Err(ParsedDnameError::ExcessiveCompression.into());
293 }
294
295 if name_len == 0 {
298 pos = ptr;
299 compressed = false;
300 }
301
302 parser.seek(ptr)?;
304
305 loop {
306 match LabelType::parse(&mut parser)? {
307 LabelType::Normal(0) => {
308 name_len += 1;
310 return Ok(ParsedDname {
311 octets: parser.octets_ref(),
312 pos,
313 name_len,
314 compressed,
315 });
316 }
317 LabelType::Normal(label_len) => {
318 parser.advance(usize::from(label_len))?;
319 name_len += label_len + 1;
320 if name_len >= 255 {
321 return Err(ParsedDnameError::LongName.into());
322 }
323 }
324 LabelType::Compressed(new_ptr) => {
325 ptr = new_ptr;
326 compressed = true;
327 break;
328 }
329 }
330 }
331 }
332 }
333}
334
335impl ParsedDname<()> {
336 pub fn skip<Src: AsRef<[u8]> + ?Sized>(
345 parser: &mut Parser<Src>,
346 ) -> Result<(), ParseError> {
347 let mut len = 0;
348 loop {
349 match LabelType::parse(parser) {
350 Ok(LabelType::Normal(0)) => {
351 len += 1;
352 if len > 255 {
353 return Err(ParsedDnameError::LongName.into());
354 }
355 return Ok(());
356 }
357 Ok(LabelType::Normal(label_len)) => {
358 parser.advance(label_len.into())?;
359 len += label_len + 1;
360 if len > 255 {
361 return Err(ParsedDnameError::LongName.into());
362 }
363 }
364 Ok(LabelType::Compressed(_)) => return Ok(()),
365 Err(err) => return Err(err),
366 }
367 }
368 }
369}
370
371impl<Octs: AsRef<[u8]>> From<Dname<Octs>> for ParsedDname<Octs> {
374 fn from(name: Dname<Octs>) -> ParsedDname<Octs> {
375 let name_len = name.compose_len();
376 ParsedDname {
377 octets: name.into_octets(),
378 pos: 0,
379 name_len,
380 compressed: false,
381 }
382 }
383}
384
385impl<Octs, Target> FlattenInto<Dname<Target>> for ParsedDname<Octs>
388where
389 Octs: Octets,
390 Target: FromBuilder,
391 <Target as FromBuilder>::Builder: EmptyBuilder,
392{
393 type AppendError = BuilderAppendError<Target>;
394
395 fn try_flatten_into(self) -> Result<Dname<Target>, Self::AppendError> {
396 let mut builder =
397 Target::Builder::with_capacity(self.compose_len().into());
398 if let Some(slice) = self.as_flat_slice() {
399 builder.append_slice(slice)?;
400 } else {
401 self.iter_labels()
402 .try_for_each(|label| label.compose(&mut builder))?;
403 }
404 Ok(unsafe { Dname::from_octets_unchecked(builder.freeze()) })
405 }
406}
407
408impl<Octs, N> PartialEq<N> for ParsedDname<Octs>
411where
412 Octs: AsRef<[u8]>,
413 N: ToDname + ?Sized,
414{
415 fn eq(&self, other: &N) -> bool {
416 self.name_eq(other)
417 }
418}
419
420impl<Octs: AsRef<[u8]>> Eq for ParsedDname<Octs> {}
421
422impl<Octs, N> PartialOrd<N> for ParsedDname<Octs>
425where
426 Octs: AsRef<[u8]>,
427 N: ToDname + ?Sized,
428{
429 fn partial_cmp(&self, other: &N) -> Option<cmp::Ordering> {
430 Some(self.name_cmp(other))
431 }
432}
433
434impl<Octs: AsRef<[u8]>> Ord for ParsedDname<Octs> {
435 fn cmp(&self, other: &Self) -> cmp::Ordering {
436 self.name_cmp(other)
437 }
438}
439
440impl<Octs, N> CanonicalOrd<N> for ParsedDname<Octs>
441where
442 Octs: AsRef<[u8]>,
443 N: ToDname + ?Sized,
444{
445 fn canonical_cmp(&self, other: &N) -> cmp::Ordering {
446 self.name_cmp(other)
447 }
448}
449
450impl<Octs: AsRef<[u8]>> hash::Hash for ParsedDname<Octs> {
453 fn hash<H: hash::Hasher>(&self, state: &mut H) {
454 for item in self.iter() {
455 item.hash(state)
456 }
457 }
458}
459
460impl<Octs: AsRef<[u8]>> ToLabelIter for ParsedDname<Octs> {
463 type LabelIter<'s> = ParsedDnameIter<'s> where Octs: 's;
464
465 fn iter_labels(&self) -> Self::LabelIter<'_> {
466 self.iter()
467 }
468
469 fn compose_len(&self) -> u16 {
470 self.name_len
471 }
472}
473
474impl<Octs: AsRef<[u8]>> ToDname for ParsedDname<Octs> {
475 fn as_flat_slice(&self) -> Option<&[u8]> {
476 if self.compressed {
477 None
478 } else {
479 Some(
480 &self.octets.as_ref()
481 [self.pos..self.pos + usize::from(self.name_len)],
482 )
483 }
484 }
485}
486
487impl<'a, Octs> IntoIterator for &'a ParsedDname<Octs>
490where
491 Octs: AsRef<[u8]>,
492{
493 type Item = &'a Label;
494 type IntoIter = ParsedDnameIter<'a>;
495
496 fn into_iter(self) -> Self::IntoIter {
497 self.iter()
498 }
499}
500
501impl<Octs: AsRef<[u8]>> fmt::Display for ParsedDname<Octs> {
504 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
509 let mut iter = self.iter();
510 write!(f, "{}", iter.next().unwrap())?;
511 for label in iter {
512 if !label.is_root() {
513 write!(f, ".{}", label)?
514 }
515 }
516 Ok(())
517 }
518}
519
520impl<Octs: AsRef<[u8]>> fmt::Debug for ParsedDname<Octs> {
521 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
522 write!(f, "ParsedDname({}.)", self)
523 }
524}
525
526#[derive(Clone)]
530pub struct ParsedDnameIter<'a> {
531 slice: &'a [u8],
532 pos: usize,
533 len: u16,
534}
535
536impl<'a> ParsedDnameIter<'a> {
537 pub(crate) fn new(slice: &'a [u8], pos: usize, len: u16) -> Self {
541 ParsedDnameIter { slice, pos, len }
542 }
543
544 fn get_label(&mut self) -> &'a Label {
551 let end = loop {
552 let ltype = self.slice[self.pos];
553 self.pos += 1;
554 match ltype {
555 0..=0x3F => break self.pos + (ltype as usize),
556 0xC0..=0xFF => {
557 self.pos = (self.slice[self.pos] as usize)
558 | (((ltype as usize) & 0x3F) << 8);
559 }
560 _ => panic!("bad label"),
561 }
562 };
563 let res = unsafe {
564 Label::from_slice_unchecked(&self.slice[self.pos..end])
565 };
566 self.pos = end;
567 self.len -= res.compose_len();
568 res
569 }
570}
571
572impl<'a> Iterator for ParsedDnameIter<'a> {
573 type Item = &'a Label;
574
575 fn next(&mut self) -> Option<&'a Label> {
576 if self.len == 0 {
577 return None;
578 }
579 Some(self.get_label())
580 }
581}
582
583impl<'a> DoubleEndedIterator for ParsedDnameIter<'a> {
584 fn next_back(&mut self) -> Option<&'a Label> {
585 if self.len == 0 {
586 return None;
587 }
588 let mut tmp = self.clone();
589 let label = loop {
590 let label = tmp.get_label();
591 if tmp.len == 0 {
592 break label;
593 }
594 };
595 self.len -= label.compose_len();
596 Some(label)
597 }
598}
599
600#[derive(Clone)]
604pub struct ParsedSuffixIter<'a, Octs: ?Sized> {
605 name: Option<ParsedDname<&'a Octs>>,
606}
607
608impl<'a, Octs> ParsedSuffixIter<'a, Octs> {
609 fn new(name: &'a ParsedDname<Octs>) -> Self {
611 ParsedSuffixIter {
612 name: Some(name.ref_octets()),
613 }
614 }
615}
616
617impl<'a, Octs: Octets + ?Sized> Iterator for ParsedSuffixIter<'a, Octs> {
618 type Item = ParsedDname<Octs::Range<'a>>;
619
620 fn next(&mut self) -> Option<Self::Item> {
621 let name = match self.name {
622 Some(ref mut name) => name,
623 None => return None,
624 };
625 let res = name.deref_octets();
626 if !name.parent() {
627 self.name = None
628 }
629 Some(res)
630 }
631}
632
633#[derive(Clone, Copy, Debug, Eq, PartialEq)]
637enum LabelType {
638 Normal(u16),
640
641 Compressed(usize),
643}
644
645impl LabelType {
646 pub fn parse<Octs: AsRef<[u8]> + ?Sized>(
648 parser: &mut Parser<Octs>,
649 ) -> Result<Self, ParseError> {
650 let ltype = parser.parse_u8()?;
651 match ltype {
652 0..=0x3F => Ok(LabelType::Normal(ltype.into())),
653 0xC0..=0xFF => {
654 let res = usize::from(parser.parse_u8()?);
655 let res = res | ((usize::from(ltype) & 0x3F) << 8);
656 Ok(LabelType::Compressed(res))
657 }
658 _ => Err(ParseError::Form(FormError::new("invalid label type"))),
659 }
660 }
661
662 pub fn peek<Ref: AsRef<[u8]> + ?Sized>(
664 parser: &Parser<Ref>,
665 ) -> Result<Self, ParseError> {
666 let ltype = parser.peek(1)?[0];
667 match ltype {
668 0..=0x3F => Ok(LabelType::Normal(ltype.into())),
669 0xC0..=0xFF => {
670 let res = usize::from(parser.peek(2)?[1]);
671 let res = res | ((usize::from(ltype) & 0x3F) << 8);
672 Ok(LabelType::Compressed(res))
673 }
674 _ => Err(ParseError::Form(FormError::new("invalid label type"))),
675 }
676 }
677}
678
679#[derive(Clone, Copy, Debug, Eq, PartialEq)]
683pub enum ParsedDnameError {
684 BadLabel(LabelTypeError),
686
687 LongName,
689
690 ExcessiveCompression,
692}
693
694impl fmt::Display for ParsedDnameError {
695 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
696 FormError::from(*self).fmt(f)
697 }
698}
699
700#[cfg(feature = "std")]
701impl std::error::Error for ParsedDnameError {}
702
703impl From<LabelTypeError> for ParsedDnameError {
704 fn from(err: LabelTypeError) -> Self {
705 ParsedDnameError::BadLabel(err)
706 }
707}
708
709impl From<ParsedDnameError> for FormError {
710 fn from(err: ParsedDnameError) -> FormError {
711 match err {
712 ParsedDnameError::BadLabel(_) => {
713 FormError::new("invalid label type")
714 }
715 ParsedDnameError::LongName => FormError::new("long domain name"),
716 ParsedDnameError::ExcessiveCompression => {
717 FormError::new("too many compression pointers")
718 }
719 }
720 }
721}
722
723impl From<ParsedDnameError> for ParseError {
724 fn from(err: ParsedDnameError) -> ParseError {
725 ParseError::Form(err.into())
726 }
727}
728
729#[cfg(test)]
732mod test {
733 use super::*;
734 use crate::base::name::{Dname, RelativeDname};
735
736 macro_rules! name {
737 (root) => {
738 name!(b"123\0", 3, 1, false)
739 };
740 (flat) => {
741 name!(b"\x03www\x07example\x03com\0\xc0\0", 0, 17, false)
742 };
743 (copy) => {
744 name!(b"\x03www\x07example\x03com\0\xc0\0", 17, 17, false)
745 };
746 (once) => {
747 name!(b"\x03com\0\x03www\x07example\xC0\0", 5, 17, true)
748 };
749 (twice) => {
750 name!(b"\x03com\0\x07example\xc0\0\x03www\xc0\x05", 15, 17, true)
751 };
752
753 ($bytes:expr, $start:expr, $len:expr, $compressed:expr) => {{
754 let mut parser = Parser::from_ref($bytes.as_ref());
755 parser.advance($start).unwrap();
756 ParsedDname {
757 octets: $bytes.as_ref(),
758 pos: $start,
759 name_len: $len,
760 compressed: $compressed,
761 }
762 }};
763 }
764
765 static WECR: &[u8] = b"\x03www\x07example\x03com\0";
766
767 #[test]
768 fn len() {
769 assert_eq!(name!(root).compose_len(), 1);
770 assert_eq!(name!(flat).compose_len(), 17);
771 assert_eq!(name!(once).compose_len(), 17);
772 assert_eq!(name!(twice).compose_len(), 17);
773 }
774
775 #[test]
776 fn is_compressed() {
777 assert!(!name!(root).is_compressed());
778 assert!(!name!(flat).is_compressed());
779 assert!(name!(once).is_compressed());
780 assert!(name!(twice).is_compressed());
781 }
782
783 #[test]
784 fn is_root() {
785 assert!(name!(root).is_root());
786 assert!(!name!(flat).is_root());
787 assert!(!name!(once).is_root());
788 assert!(!name!(twice).is_root());
789 }
790
791 #[test]
792 fn iter() {
793 use crate::base::name::dname::test::cmp_iter;
794
795 let labels: &[&[u8]] = &[b"www", b"example", b"com", b""];
796 cmp_iter(name!(root).iter(), &[b""]);
797 cmp_iter(name!(flat).iter(), labels);
798 cmp_iter(name!(once).iter(), labels);
799 cmp_iter(name!(twice).iter(), labels);
800 }
801
802 #[test]
803 fn iter_back() {
804 use crate::base::name::dname::test::cmp_iter_back;
805
806 let labels: &[&[u8]] = &[b"", b"com", b"example", b"www"];
807 cmp_iter_back(name!(root).iter(), &[b""]);
808 cmp_iter_back(name!(flat).iter(), labels);
809 cmp_iter_back(name!(once).iter(), labels);
810 cmp_iter_back(name!(twice).iter(), labels);
811 }
812
813 fn cmp_iter_suffixes<'a, I>(iter: I, labels: &[&[u8]])
814 where
815 I: Iterator<Item = ParsedDname<&'a [u8]>>,
816 {
817 for (name, labels) in iter.zip(labels) {
818 let mut iter = name.iter();
819 let labels = Dname::from_slice(labels).unwrap();
820 let mut labels_iter = labels.iter();
821 loop {
822 match (iter.next(), labels_iter.next()) {
823 (Some(left), Some(right)) => assert_eq!(left, right),
824 (None, None) => break,
825 (_, None) => panic!("extra items in iterator"),
826 (None, _) => panic!("missing items in iterator"),
827 }
828 }
829 }
830 }
831
832 #[test]
833 fn iter_suffixes() {
834 let suffixes: &[&[u8]] = &[
835 b"\x03www\x07example\x03com\0",
836 b"\x07example\x03com\0",
837 b"\x03com\0",
838 b"\0",
839 ];
840 cmp_iter_suffixes(name!(root).iter_suffixes(), &[b"\0"]);
841 cmp_iter_suffixes(name!(flat).iter_suffixes(), suffixes);
842 cmp_iter_suffixes(name!(once).iter_suffixes(), suffixes);
843 cmp_iter_suffixes(name!(twice).iter_suffixes(), suffixes);
844 }
845
846 #[test]
847 fn label_count() {
848 assert_eq!(name!(root).label_count(), 1);
849 assert_eq!(name!(flat).label_count(), 4);
850 assert_eq!(name!(once).label_count(), 4);
851 assert_eq!(name!(twice).label_count(), 4);
852 }
853
854 #[test]
855 fn first() {
856 assert_eq!(name!(root).first().as_slice(), b"");
857 assert_eq!(name!(flat).first().as_slice(), b"www");
858 assert_eq!(name!(once).first().as_slice(), b"www");
859 assert_eq!(name!(twice).first().as_slice(), b"www");
860 }
861
862 #[test]
863 fn starts_with() {
864 let root = name!(root);
865 let flat_wec = name!(flat);
866 let once_wec = name!(once);
867 let twice_wec = name!(twice);
868
869 let test = Dname::root_ref();
870 assert!(root.starts_with(&test));
871 assert!(!flat_wec.starts_with(&test));
872 assert!(!once_wec.starts_with(&test));
873 assert!(!twice_wec.starts_with(&test));
874
875 let test = RelativeDname::empty_ref();
876 assert!(root.starts_with(&test));
877 assert!(flat_wec.starts_with(&test));
878 assert!(once_wec.starts_with(&test));
879 assert!(twice_wec.starts_with(&test));
880
881 let test = RelativeDname::from_slice(b"\x03www").unwrap();
882 assert!(!root.starts_with(&test));
883 assert!(flat_wec.starts_with(&test));
884 assert!(once_wec.starts_with(&test));
885 assert!(twice_wec.starts_with(&test));
886
887 let test = RelativeDname::from_slice(b"\x03www\x07example").unwrap();
888 assert!(!root.starts_with(&test));
889 assert!(flat_wec.starts_with(&test));
890 assert!(once_wec.starts_with(&test));
891 assert!(twice_wec.starts_with(&test));
892
893 let test =
894 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap();
895 assert!(!root.starts_with(&test));
896 assert!(flat_wec.starts_with(&test));
897 assert!(once_wec.starts_with(&test));
898 assert!(twice_wec.starts_with(&test));
899
900 let test = Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap();
901 assert!(!root.starts_with(&test));
902 assert!(flat_wec.starts_with(&test));
903 assert!(once_wec.starts_with(&test));
904 assert!(twice_wec.starts_with(&test));
905
906 let test = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
907 assert!(!root.starts_with(&test));
908 assert!(!flat_wec.starts_with(&test));
909 assert!(!once_wec.starts_with(&test));
910 assert!(!twice_wec.starts_with(&test));
911
912 let test = RelativeDname::from_octets(b"\x03www".as_ref())
913 .unwrap()
914 .chain(
915 RelativeDname::from_octets(b"\x07example".as_ref()).unwrap(),
916 )
917 .unwrap();
918 assert!(!root.starts_with(&test));
919 assert!(flat_wec.starts_with(&test));
920 assert!(once_wec.starts_with(&test));
921 assert!(twice_wec.starts_with(&test));
922
923 let test = test
924 .chain(RelativeDname::from_octets(b"\x03com".as_ref()).unwrap())
925 .unwrap();
926 assert!(!root.starts_with(&test));
927 assert!(flat_wec.starts_with(&test));
928 assert!(once_wec.starts_with(&test));
929 assert!(twice_wec.starts_with(&test));
930 }
931
932 #[test]
933 fn ends_with() {
934 let root = name!(root);
935 let flat_wec = name!(flat);
936 let once_wec = name!(once);
937 let twice_wec = name!(twice);
938 let wecr =
939 Dname::from_octets(b"\x03www\x07example\x03com\0".as_ref())
940 .unwrap();
941
942 for name in wecr.iter_suffixes() {
943 if name.is_root() {
944 assert!(root.ends_with(&name))
945 } else {
946 assert!(!root.ends_with(&name))
947 }
948 assert!(flat_wec.ends_with(&name));
949 assert!(once_wec.ends_with(&name));
950 assert!(twice_wec.ends_with(&name));
951 }
952 }
953
954 #[test]
955 #[cfg(feature = "std")]
956 fn split_first() {
957 fn split_first_wec(mut name: ParsedDname<&[u8]>) {
958 assert_eq!(
959 name.to_vec().as_slice(),
960 b"\x03www\x07example\x03com\0"
961 );
962 assert_eq!(
963 name.split_first().unwrap().as_slice(),
964 b"\x03www".as_ref()
965 );
966 assert_eq!(name.to_vec().as_slice(), b"\x07example\x03com\0");
967 assert_eq!(
968 name.split_first().unwrap().as_slice(),
969 b"\x07example".as_ref()
970 );
971 assert_eq!(name.to_vec().as_slice(), b"\x03com\0");
972 assert_eq!(
973 name.split_first().unwrap().as_slice(),
974 b"\x03com".as_ref()
975 );
976 assert_eq!(name.to_vec().as_slice(), b"\0");
977 assert_eq!(name.split_first(), None);
978 assert_eq!(name.split_first(), None);
979 }
980
981 split_first_wec(name!(flat));
982 split_first_wec(name!(once));
983 split_first_wec(name!(twice));
984 }
985
986 #[test]
987 #[cfg(feature = "std")]
988 fn parent() {
989 fn parent_wec(mut name: ParsedDname<&[u8]>) {
990 assert_eq!(
991 name.to_vec().as_slice(),
992 b"\x03www\x07example\x03com\0"
993 );
994 assert!(name.parent());
995 assert_eq!(name.to_vec().as_slice(), b"\x07example\x03com\0");
996 assert!(name.parent());
997 assert_eq!(name.to_vec().as_slice(), b"\x03com\0");
998 assert!(name.parent());
999 assert_eq!(name.to_vec().as_slice(), b"\0");
1000 assert!(!name.parent());
1001 assert!(!name.parent());
1002 }
1003
1004 parent_wec(name!(flat));
1005 parent_wec(name!(once));
1006 parent_wec(name!(twice));
1007 }
1008
1009 #[test]
1010 #[cfg(feature = "std")]
1011 fn parse_and_skip() {
1012 use std::vec::Vec;
1013
1014 fn name_eq(parsed: ParsedDname<&[u8]>, name: ParsedDname<&[u8]>) {
1015 assert_eq!(parsed.octets, name.octets);
1016 assert_eq!(parsed.pos, name.pos);
1017 assert_eq!(parsed.name_len, name.name_len);
1018 assert_eq!(parsed.compressed, name.compressed);
1019 }
1020
1021 fn parse(
1022 mut parser: Parser<&[u8]>,
1023 equals: ParsedDname<&[u8]>,
1024 compose_len: usize,
1025 ) {
1026 let end = parser.pos() + compose_len;
1027 name_eq(ParsedDname::parse(&mut parser).unwrap(), equals);
1028 assert_eq!(parser.pos(), end);
1029 }
1030
1031 fn skip(name: ParsedDname<&[u8]>, len: usize) {
1032 let mut parser = name.parser();
1033 let pos = parser.pos();
1034 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1035 assert_eq!(parser.pos(), pos + len);
1036 }
1037
1038 fn p(slice: &[u8], pos: usize) -> Parser<[u8]> {
1039 let mut res = Parser::from_ref(slice);
1040 res.advance(pos).unwrap();
1041 res
1042 }
1043
1044 parse(name!(root).parser(), name!(root), 1);
1046 parse(name!(flat).parser(), name!(flat), 17);
1047 parse(name!(copy).parser(), name!(flat), 2);
1048 parse(name!(once).parser(), name!(once), 14);
1049 parse(name!(twice).parser(), name!(twice), 6);
1050 skip(name!(root), 1);
1051 skip(name!(flat), 17);
1052 skip(name!(copy), 2);
1053 skip(name!(once), 14);
1054 skip(name!(twice), 6);
1055
1056 let mut parser = p(b"\x03www\x07exam", 0);
1058 assert_eq!(
1059 ParsedDname::parse(&mut parser.clone()),
1060 Err(ParseError::ShortInput)
1061 );
1062 assert_eq!(
1063 ParsedDname::skip(&mut parser),
1064 Err(ParseError::ShortInput)
1065 );
1066
1067 let mut parser = p(b"\x03www\x07example", 0);
1069 assert_eq!(
1070 ParsedDname::parse(&mut parser.clone()),
1071 Err(ParseError::ShortInput)
1072 );
1073 assert_eq!(
1074 ParsedDname::skip(&mut parser),
1075 Err(ParseError::ShortInput)
1076 );
1077
1078 let mut parser = p(b"\x03www\xc0\xee12", 0);
1080 assert!(ParsedDname::parse(&mut parser.clone()).is_err());
1081 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1082 assert_eq!(parser.remaining(), 2);
1083
1084 assert!(ParsedDname::parse(&mut p(b"\x03www\xc0\x0412", 4)).is_err());
1086
1087 assert!(ParsedDname::parse(&mut p(b"\x03www\xc0\x0612", 4)).is_err());
1089
1090 let mut parser = p(b"\x03www\x07example\xbffoo", 0);
1092 assert!(ParsedDname::parse(&mut parser.clone()).is_err());
1093 assert!(ParsedDname::skip(&mut parser).is_err());
1094
1095 let mut buf = Vec::from(&b"\x03123\0"[..]);
1097 for _ in 0..25 {
1098 buf.extend_from_slice(b"\x09123456789");
1099 }
1100 buf.extend_from_slice(b"\xc0\x0012");
1101 let mut parser = Parser::from_ref(buf.as_slice());
1102 parser.advance(5).unwrap();
1103 let name = ParsedDname::parse(&mut parser.clone()).unwrap();
1104 assert_eq!(name.compose_len(), 255);
1105 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1106 assert_eq!(parser.remaining(), 2);
1107
1108 let mut buf = Vec::from(&b"\x041234\x00"[..]);
1110 for _ in 0..25 {
1111 buf.extend_from_slice(b"\x09123456789");
1112 }
1113 buf.extend_from_slice(b"\xc0\x0012");
1114 let mut parser = Parser::from_ref(buf.as_slice());
1115 parser.advance(6).unwrap();
1116 assert!(ParsedDname::parse(&mut parser.clone()).is_err());
1117 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1118 assert_eq!(parser.remaining(), 2);
1119
1120 let mut parser = p(b"\x03www\xc0\x0012", 0);
1122 assert!(ParsedDname::parse(&mut parser.clone()).is_err());
1123 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1124 assert_eq!(parser.remaining(), 2);
1125
1126 let mut parser = p(b"\xc0\x0012", 0);
1128 assert!(ParsedDname::parse(&mut parser.clone()).is_err());
1129 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1130 assert_eq!(parser.remaining(), 2);
1131
1132 let mut parser = p(b"\xc0\x02\xc0\x0012", 2);
1134 assert!(ParsedDname::parse(&mut parser.clone()).is_err());
1135 assert_eq!(ParsedDname::skip(&mut parser), Ok(()));
1136 assert_eq!(parser.remaining(), 2);
1137 }
1138
1139 #[test]
1140 #[cfg(feature = "std")]
1141 fn compose() {
1142 use octseq::builder::infallible;
1143 use std::vec::Vec;
1144
1145 fn step(name: ParsedDname<&[u8]>, result: &[u8]) {
1146 let mut buf = Vec::new();
1147 infallible(name.compose(&mut buf));
1148 assert_eq!(buf.as_slice(), result);
1149 }
1150
1151 step(name!(root), b"\x00");
1152 step(name!(flat), WECR);
1153 step(name!(once), WECR);
1154 step(name!(twice), WECR);
1155 }
1156
1157 #[test]
1160 fn as_flat_slice() {
1161 assert_eq!(name!(root).as_flat_slice(), Some(b"\x00".as_ref()));
1162 assert_eq!(name!(flat).as_flat_slice(), Some(WECR));
1163 assert_eq!(name!(once).as_flat_slice(), None);
1164 assert_eq!(name!(twice).as_flat_slice(), None);
1165 }
1166
1167 #[test]
1168 fn eq() {
1169 fn step<N: ToDname + fmt::Debug>(name: N) {
1170 assert_eq!(name!(flat), &name);
1171 assert_eq!(name!(once), &name);
1172 assert_eq!(name!(twice), &name);
1173 }
1174
1175 fn ne_step<N: ToDname + fmt::Debug>(name: N) {
1176 assert_ne!(name!(flat), &name);
1177 assert_ne!(name!(once), &name);
1178 assert_ne!(name!(twice), &name);
1179 }
1180
1181 step(name!(flat));
1182 step(name!(once));
1183 step(name!(twice));
1184
1185 step(Dname::from_slice(b"\x03www\x07example\x03com\x00").unwrap());
1186 step(Dname::from_slice(b"\x03wWw\x07EXAMPLE\x03com\x00").unwrap());
1187 step(
1188 RelativeDname::from_octets(b"\x03www\x07example\x03com")
1189 .unwrap()
1190 .chain_root(),
1191 );
1192 step(
1193 RelativeDname::from_octets(b"\x03www\x07example")
1194 .unwrap()
1195 .chain(Dname::from_octets(b"\x03com\x00").unwrap())
1196 .unwrap(),
1197 );
1198
1199 ne_step(Dname::from_slice(b"\x03ww4\x07EXAMPLE\x03com\x00").unwrap());
1200 }
1201
1202 }