1use std::{cmp, fmt, hash, ops};
6use bytes::{BufMut, Bytes};
7use ::bits::compose::Compose;
8use super::builder::DnameBuilder;
9use super::chain::{Chain, LongChainError};
10use super::dname::Dname;
11use super::label::{Label, LabelTypeError, SplitLabelError};
12use super::traits::{ToLabelIter, ToRelativeDname};
13
14
15#[derive(Clone)]
33pub struct RelativeDname {
34 bytes: Bytes,
35}
36
37impl RelativeDname {
40 pub(super) unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self {
45 RelativeDname { bytes }
46 }
47
48 pub fn empty() -> Self {
53 unsafe {
54 RelativeDname::from_bytes_unchecked(Bytes::from_static(b""))
55 }
56 }
57
58 pub fn wildcard() -> Self {
65 unsafe {
66 RelativeDname::from_bytes_unchecked(Bytes::from_static(b"\x01*"))
67 }
68 }
69
70 pub fn from_bytes(bytes: Bytes) -> Result<Self, RelativeDnameError> {
75 if bytes.len() > 254 {
76 return Err(RelativeDnameError::LongName)
77 }
78 {
79 let mut tmp = bytes.as_ref();
80 while !tmp.is_empty() {
81 let (label, tail) = Label::split_from(tmp)?;
82 if label.is_root() {
83 return Err(RelativeDnameError::AbsoluteName);
84 }
85 tmp = tail;
86 }
87 }
88 Ok(unsafe { RelativeDname::from_bytes_unchecked(bytes) })
89 }
90
91 pub fn from_slice(slice: &[u8]) -> Result<Self, RelativeDnameError> {
97 Self::from_bytes(slice.into())
98 }
99
100 pub fn as_bytes(&self) -> &Bytes {
102 &self.bytes
103 }
104
105 pub fn as_slice(&self) -> &[u8] {
107 self.bytes.as_ref()
108 }
109
110 pub fn into_bytes(self) -> Bytes {
112 self.bytes
113 }
114
115 pub fn into_builder(self) -> DnameBuilder {
125 let bytes = match self.bytes.try_mut() {
126 Ok(bytes) => bytes,
127 Err(bytes) => bytes.as_ref().into()
128 };
129 unsafe { DnameBuilder::from_bytes(bytes) }
130 }
131
132 pub fn into_absolute(self) -> Dname {
140 self.into_builder().into_dname().unwrap()
141 }
142
143 pub fn chain<N: Compose>(self, other: N)
153 -> Result<Chain<Self, N>, LongChainError> {
154 Chain::new(self, other)
155 }
156
157 pub fn chain_root(self) -> Chain<Self, Dname> {
159 self.chain(Dname::root()).unwrap()
160 }
161}
162
163impl RelativeDname {
166 pub fn iter(&self) -> DnameIter {
168 DnameIter::new(self.bytes.as_ref())
169 }
170
171 pub fn label_count(&self) -> usize {
173 self.iter().count()
174 }
175
176 pub fn first(&self) -> Option<&Label> {
178 self.iter().next()
179 }
180
181 pub fn last(&self) -> Option<&Label> {
183 self.iter().next_back()
184 }
185
186 pub fn ndots(&self) -> usize {
191 if self.is_empty() { 0 }
192 else {
193 self.label_count() - 1
194 }
195 }
196
197 pub fn starts_with<'a, N: ToLabelIter<'a>>(&'a self, base: &'a N) -> bool {
199 <Self as ToLabelIter>::starts_with(self, base)
200 }
201
202 pub fn ends_with<'a, N: ToLabelIter<'a>>(&'a self, base: &'a N) -> bool {
204 <Self as ToLabelIter>::ends_with(self, base)
205 }
206
207 pub fn is_label_start(&self, mut index: usize) -> bool {
209 if index == 0 {
210 return true
211 }
212 let mut tmp = self.as_slice();
213 while !tmp.is_empty() {
214 let (label, tail) = Label::split_from(tmp).unwrap();
215 let len = label.len() + 1;
216 if index < len {
217 return false
218 }
219 else if index == len {
220 return true
221 }
222 index -= len;
223 tmp = tail;
224 }
225 false
226 }
227
228 fn check_index(&self, index: usize) {
230 if !self.is_label_start(index) {
231 panic!("index not at start of a label");
232 }
233 }
234
235 pub fn slice(&self, begin: usize, end: usize) -> Self {
245 self.check_index(begin);
246 self.check_index(end);
247 unsafe { Self::from_bytes_unchecked(self.bytes.slice(begin, end)) }
248 }
249
250 pub fn slice_from(&self, begin: usize) -> Self {
257 self.check_index(begin);
258 unsafe { Self::from_bytes_unchecked(self.bytes.slice_from(begin)) }
259 }
260
261 pub fn slice_to(&self, end: usize) -> Self {
268 self.check_index(end);
269 unsafe { Self::from_bytes_unchecked(self.bytes.slice_to(end)) }
270 }
271
272 pub fn split_off(&mut self, mid: usize) -> Self {
282 self.check_index(mid);
283 unsafe { Self::from_bytes_unchecked(self.bytes.split_off(mid)) }
284 }
285
286 pub fn split_to(&mut self, mid: usize) -> Self {
296 self.check_index(mid);
297 unsafe { Self::from_bytes_unchecked(self.bytes.split_to(mid)) }
298 }
299
300 pub fn truncate(&mut self, len: usize) {
307 self.check_index(len);
308 self.bytes.truncate(len);
309 }
310
311 pub fn split_first(&mut self) -> Option<Self> {
318 if self.is_empty() {
319 return None
320 }
321 let first_end = match self.iter().next() {
322 Some(label) => label.len() + 1,
323 None => return None
324 };
325 Some(unsafe {
326 Self::from_bytes_unchecked(self.bytes.split_to(first_end))
327 })
328 }
329
330 pub fn parent(&mut self) -> bool {
335 self.split_first().is_some()
336 }
337
338 pub fn strip_suffix<N: ToRelativeDname>(&mut self, base: &N)
345 -> Result<(), StripSuffixError> {
346 if self.ends_with(base) {
347 let idx = self.bytes.len() - base.compose_len();
348 self.bytes.split_off(idx);
349 Ok(())
350 }
351 else {
352 Err(StripSuffixError)
353 }
354 }
355}
356
357
358impl Compose for RelativeDname {
361 fn compose_len(&self) -> usize {
362 self.bytes.len()
363 }
364
365 fn compose<B: BufMut>(&self, buf: &mut B) {
366 buf.put_slice(self.as_ref())
367 }
368}
369
370
371impl<'a> ToLabelIter<'a> for RelativeDname {
374 type LabelIter = DnameIter<'a>;
375
376 fn iter_labels(&'a self) -> Self::LabelIter {
377 self.iter()
378 }
379}
380
381impl ToRelativeDname for RelativeDname {
382 fn to_name(&self) -> RelativeDname {
383 self.clone()
384 }
385
386 fn as_flat_slice(&self) -> Option<&[u8]> {
387 Some(self.as_slice())
388 }
389}
390
391
392impl ops::Deref for RelativeDname {
395 type Target = Bytes;
396
397 fn deref(&self) -> &Bytes {
398 self.as_ref()
399 }
400}
401
402impl AsRef<Bytes> for RelativeDname {
403 fn as_ref(&self) -> &Bytes {
404 &self.bytes
405 }
406}
407
408impl AsRef<[u8]> for RelativeDname {
409 fn as_ref(&self) -> &[u8] {
410 self.bytes.as_ref()
411 }
412}
413
414
415impl<'a> IntoIterator for &'a RelativeDname {
418 type Item = &'a Label;
419 type IntoIter = DnameIter<'a>;
420
421 fn into_iter(self) -> Self::IntoIter {
422 self.iter()
423 }
424}
425
426
427impl<N: ToRelativeDname> PartialEq<N> for RelativeDname {
430 fn eq(&self, other: &N) -> bool {
431 self.name_eq(other)
432 }
433}
434
435impl Eq for RelativeDname { }
436
437
438impl PartialOrd for RelativeDname {
441 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
442 Some(self.name_cmp(other))
443 }
444}
445
446impl Ord for RelativeDname {
447 fn cmp(&self, other: &Self) -> cmp::Ordering {
448 self.name_cmp(other)
449 }
450}
451
452
453impl hash::Hash for RelativeDname {
456 fn hash<H: hash::Hasher>(&self, state: &mut H) {
457 for item in self.iter() {
458 item.hash(state)
459 }
460 }
461}
462
463
464impl fmt::Display for RelativeDname {
467 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
468 let mut iter = self.iter();
469 match iter.next() {
470 Some(label) => label.fmt(f)?,
471 None => return Ok(())
472 }
473 for label in iter {
474 f.write_str(".")?;
475 label.fmt(f)?;
476 }
477 Ok(())
478 }
479}
480
481impl fmt::Debug for RelativeDname {
482 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483 write!(f, "RelativeDname({})", self)
484 }
485}
486
487
488#[derive(Clone, Debug)]
492pub struct DnameIter<'a> {
493 slice: &'a [u8],
494}
495
496impl<'a> DnameIter<'a> {
497 pub(super) fn new(slice: &'a [u8]) -> Self {
498 DnameIter { slice }
499 }
500}
501
502impl<'a> Iterator for DnameIter<'a> {
503 type Item = &'a Label;
504
505 fn next(&mut self) -> Option<Self::Item> {
506 let (label, tail) = match Label::split_from(self.slice) {
507 Ok(res) => res,
508 Err(_) => return None,
509 };
510 self.slice = tail;
511 Some(label)
512 }
513}
514
515impl<'a> DoubleEndedIterator for DnameIter<'a> {
516 fn next_back(&mut self) -> Option<Self::Item> {
517 if self.slice.is_empty() {
518 return None
519 }
520 let mut tmp = self.slice;
521 loop {
522 let (label, tail) = Label::split_from(tmp).unwrap();
523 if tail.is_empty() {
524 let end = self.slice.len() - (label.len() + 1);
525 self.slice = &self.slice[..end];
526 return Some(label)
527 }
528 else {
529 tmp = tail
530 }
531 }
532 }
533}
534
535
536#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
540pub enum RelativeDnameError {
541 #[fail(display="{}", _0)]
543 BadLabel(LabelTypeError),
544
545 #[fail(display="compressed domain name")]
547 CompressedName,
548
549 #[fail(display="unexpected end of input")]
551 ShortData,
552
553 #[fail(display="long domain name")]
555 LongName,
556
557 #[fail(display="absolute domain name")]
559 AbsoluteName,
560}
561
562impl From<LabelTypeError> for RelativeDnameError {
563 fn from(err: LabelTypeError) -> Self {
564 RelativeDnameError::BadLabel(err)
565 }
566}
567
568impl From<SplitLabelError> for RelativeDnameError {
569 fn from(err: SplitLabelError) -> Self {
570 match err {
571 SplitLabelError::Pointer(_) => RelativeDnameError::CompressedName,
572 SplitLabelError::BadType(t) => RelativeDnameError::BadLabel(t),
573 SplitLabelError::ShortBuf => RelativeDnameError::ShortData,
574 }
575 }
576}
577
578
579#[derive(Clone, Copy, Debug, Eq, Fail, PartialEq)]
583#[fail(display="suffix not found")]
584pub struct StripSuffixError;
585
586
587#[cfg(test)]
590mod test {
591 use super::*;
592 use ::bits::parse::ShortBuf;
593
594 macro_rules! assert_panic {
595 ( $cond:expr ) => {
596 {
597 let result = ::std::panic::catch_unwind(|| $cond);
598 assert!(result.is_err());
599 }
600 }
601 }
602
603 #[test]
604 fn empty() {
605 assert_eq!(RelativeDname::empty().as_slice(), b"");
606 }
607
608 #[test]
609 fn wildcard() {
610 assert_eq!(RelativeDname::wildcard().as_slice(), b"\x01*");
611 }
612
613 #[test]
614 fn from_slice() {
615 assert_eq!(RelativeDname::from_slice(b"").unwrap().as_slice(), b"");
617 assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap().as_slice(),
618 b"\x03www");
619 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example")
620 .unwrap().as_slice(),
621 b"\x03www\x07example");
622
623 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example\x03com\0"),
625 Err(RelativeDnameError::AbsoluteName));
626 assert_eq!(RelativeDname::from_slice(b"\0"),
627 Err(RelativeDnameError::AbsoluteName));
628
629 assert_eq!(Dname::from_slice(b"\x03www\x07exa"),
631 Err(ShortBuf.into()));
632
633 let mut slice = [0u8; 64];
635 slice[0] = 63;
636 assert!(RelativeDname::from_slice(&slice[..]).is_ok());
637 let mut slice = [0u8; 65];
638 slice[0] = 64;
639 assert!(RelativeDname::from_slice(&slice[..]).is_err());
640
641 let mut buf = Vec::new();
643 for _ in 0..25 {
644 buf.extend_from_slice(b"\x09123456789");
645 }
646 assert_eq!(buf.len(), 250);
647 let mut tmp = buf.clone();
648 tmp.extend_from_slice(b"\x03123");
649 assert_eq!(RelativeDname::from_slice(&tmp).map(|_| ()), Ok(()));
650 buf.extend_from_slice(b"\x041234");
651 assert!(RelativeDname::from_slice(&buf).is_err());
652
653 assert_eq!(RelativeDname::from_slice(b"\xa2asdasds"),
655 Err(LabelTypeError::Undefined.into()));
656 assert_eq!(RelativeDname::from_slice(b"\x62asdasds"),
657 Err(LabelTypeError::Extended(0x62).into()));
658 assert_eq!(RelativeDname::from_slice(b"\xccasdasds"),
659 Err(RelativeDnameError::CompressedName.into()));
660 }
661
662 #[test]
663 fn into_absolute() {
664 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example\x03com")
665 .unwrap().into_absolute().as_slice(),
666 b"\x03www\x07example\x03com\0");
667 }
668
669 #[test]
672 fn chain_root() {
673 assert_eq!(Dname::from_slice(b"\x03www\x07example\x03com\0").unwrap(),
674 RelativeDname::from_slice(b"\x03www\x07example\x03com")
675 .unwrap().chain_root());
676 }
677
678 #[test]
679 fn iter() {
680 use ::bits::name::dname::test::cmp_iter;
681
682 cmp_iter(RelativeDname::empty().iter(), &[]);
683 cmp_iter(RelativeDname::wildcard().iter(), &[b"*"]);
684 cmp_iter(RelativeDname::from_slice(b"\x03www\x07example\x03com")
685 .unwrap().iter(),
686 &[b"www", b"example", b"com"]);
687 }
688
689 #[test]
690 fn iter_back() {
691 use ::bits::name::dname::test::cmp_iter_back;
692
693 cmp_iter_back(RelativeDname::empty().iter(), &[]);
694 cmp_iter_back(RelativeDname::wildcard().iter(), &[b"*"]);
695 cmp_iter_back(RelativeDname::from_slice(b"\x03www\x07example\x03com")
696 .unwrap().iter(),
697 &[b"com", b"example", b"www"]);
698 }
699
700 #[test]
701 fn label_count() {
702 assert_eq!(RelativeDname::empty().label_count(), 0);
703 assert_eq!(RelativeDname::wildcard().label_count(), 1);
704 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example\x03com")
705 .unwrap().label_count(),
706 3);
707 }
708
709 #[test]
710 fn first() {
711 assert_eq!(RelativeDname::empty().first(), None);
712 assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap()
713 .first().unwrap().as_slice(),
714 b"www");
715 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example").unwrap()
716 .first().unwrap().as_slice(),
717 b"www");
718 }
719
720 #[test]
721 fn last() {
722 assert_eq!(RelativeDname::empty().last(), None);
723 assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap()
724 .last().unwrap().as_slice(),
725 b"www");
726 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example").unwrap()
727 .last().unwrap().as_slice(),
728 b"example");
729 }
730
731 #[test]
732 fn ndots() {
733 assert_eq!(RelativeDname::empty().ndots(), 0);
734 assert_eq!(RelativeDname::from_slice(b"\x03www").unwrap().ndots(),
735 0);
736 assert_eq!(RelativeDname::from_slice(b"\x03www\x07example").unwrap()
737 .ndots(),
738 1);
739 }
740
741 #[test]
742 fn starts_with() {
743 let matrix = [
744 ( RelativeDname::empty(),
745 [ true, false, false, false, false, false ]),
746 ( RelativeDname::from_slice(b"\x03www").unwrap(),
747 [ true, true, false, false, false, false ]),
748 ( RelativeDname::from_slice(b"\x03www\x07example").unwrap(),
749 [ true, true, true, false, false, false ]),
750 ( RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
751 [ true, true, true, true, false, false ]),
752 ( RelativeDname::from_slice(b"\x07example\x03com").unwrap(),
753 [ true, false, false, false, true, false ]),
754 ( RelativeDname::from_slice(b"\x03com").unwrap(),
755 [ true, false, false, false, false, true ])
756 ];
757 for i in 0..6 {
758 for j in 0..6 {
759 assert_eq!(matrix[i].0.starts_with(&matrix[j].0),
760 matrix[i].1[j],
761 "i={}, j={}", i, j)
762 }
763 }
764 }
765
766 #[test]
767 fn ends_with() {
768 let matrix = [
769 ( RelativeDname::empty(),
770 [ true, false, false, false, false, false ]),
771 ( RelativeDname::from_slice(b"\x03www").unwrap(),
772 [ true, true, false, false, false, false ]),
773 ( RelativeDname::from_slice(b"\x03www\x07example").unwrap(),
774 [ true, false, true, false, false, false ]),
775 ( RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
776 [ true, false, false, true, true, true]),
777 ( RelativeDname::from_slice(b"\x07example\x03com").unwrap(),
778 [ true, false, false, false, true, true]),
779 ( RelativeDname::from_slice(b"\x03com").unwrap(),
780 [ true, false, false, false, false, true ]),
781 ];
782 for i in 0..matrix.len() {
783 for j in 0..matrix.len() {
784 assert_eq!(matrix[i].0.ends_with(&matrix[j].0),
785 matrix[i].1[j],
786 "i={}, j={}", i, j)
787 }
788 }
789 }
790
791 #[test]
792 fn is_label_start() {
793 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
794 .unwrap();
795
796 assert!( wec.is_label_start(0)); assert!(!wec.is_label_start(1)); assert!(!wec.is_label_start(2)); assert!(!wec.is_label_start(3)); assert!( wec.is_label_start(4)); assert!(!wec.is_label_start(5)); assert!(!wec.is_label_start(6)); assert!(!wec.is_label_start(7)); assert!(!wec.is_label_start(8)); assert!(!wec.is_label_start(9)); assert!(!wec.is_label_start(10)); assert!(!wec.is_label_start(11)); assert!( wec.is_label_start(12)); assert!(!wec.is_label_start(13)); assert!(!wec.is_label_start(14)); assert!(!wec.is_label_start(15)); assert!( wec.is_label_start(16)); assert!(!wec.is_label_start(17)); }
815
816 #[test]
817 fn slice() {
818 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
819 .unwrap();
820 assert_eq!(wec.slice(0, 4).as_slice(), b"\x03www");
821 assert_eq!(wec.slice(0, 12).as_slice(), b"\x03www\x07example");
822 assert_eq!(wec.slice(4, 12).as_slice(), b"\x07example");
823 assert_eq!(wec.slice(4, 16).as_slice(), b"\x07example\x03com");
824
825 assert_panic!(wec.slice(0,3));
826 assert_panic!(wec.slice(1,4));
827 assert_panic!(wec.slice(0,11));
828 assert_panic!(wec.slice(1,12));
829 assert_panic!(wec.slice(0,17));
830 assert_panic!(wec.slice(4,17));
831 assert_panic!(wec.slice(0,18));
832 }
833
834 #[test]
835 fn slice_from() {
836 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
837 .unwrap();
838
839 assert_eq!(wec.slice_from(0).as_slice(),
840 b"\x03www\x07example\x03com");
841 assert_eq!(wec.slice_from(4).as_slice(), b"\x07example\x03com");
842 assert_eq!(wec.slice_from(12).as_slice(), b"\x03com");
843 assert_eq!(wec.slice_from(16).as_slice(), b"");
844
845 assert_panic!(wec.slice_from(17));
846 assert_panic!(wec.slice_from(18));
847 }
848
849 #[test]
850 fn slice_to() {
851 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
852 .unwrap();
853
854 assert_eq!(wec.slice_to(0).as_slice(), b"");
855 assert_eq!(wec.slice_to(4).as_slice(), b"\x03www");
856 assert_eq!(wec.slice_to(12).as_slice(), b"\x03www\x07example");
857 assert_eq!(wec.slice_to(16).as_slice(), b"\x03www\x07example\x03com");
858
859 assert_panic!(wec.slice_to(17));
860 assert_panic!(wec.slice_to(18));
861 }
862
863 #[test]
864 fn split_off() {
865 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
866 .unwrap();
867
868 let mut tmp = wec.clone();
869 assert_eq!(tmp.split_off(0).as_slice(), b"\x03www\x07example\x03com");
870 assert_eq!(tmp.as_slice(), b"");
871
872 let mut tmp = wec.clone();
873 assert_eq!(tmp.split_off(4).as_slice(), b"\x07example\x03com");
874 assert_eq!(tmp.as_slice(), b"\x03www");
875
876 let mut tmp = wec.clone();
877 assert_eq!(tmp.split_off(12).as_slice(), b"\x03com");
878 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
879
880 let mut tmp = wec.clone();
881 assert_eq!(tmp.split_off(16).as_slice(), b"");
882 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
883
884 assert_panic!(wec.clone().split_off(1));
885 assert_panic!(wec.clone().split_off(14));
886 assert_panic!(wec.clone().split_off(17));
887 assert_panic!(wec.clone().split_off(18));
888 }
889
890 #[test]
891 fn split_to() {
892 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
893 .unwrap();
894
895 let mut tmp = wec.clone();
896 assert_eq!(tmp.split_to(0).as_slice(), b"");
897 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
898
899 let mut tmp = wec.clone();
900 assert_eq!(tmp.split_to(4).as_slice(), b"\x03www");
901 assert_eq!(tmp.as_slice(), b"\x07example\x03com");
902
903 let mut tmp = wec.clone();
904 assert_eq!(tmp.split_to(12).as_slice(), b"\x03www\x07example");
905 assert_eq!(tmp.as_slice(), b"\x03com");
906
907 let mut tmp = wec.clone();
908 assert_eq!(tmp.split_to(16).as_slice(), b"\x03www\x07example\x03com");
909 assert_eq!(tmp.as_slice(), b"");
910
911 assert_panic!(wec.clone().split_to(1));
912 assert_panic!(wec.clone().split_to(14));
913 assert_panic!(wec.clone().split_to(17));
914 assert_panic!(wec.clone().split_to(18));
915 }
916
917 #[test]
918 fn truncate() {
919 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
920 .unwrap();
921
922 let mut tmp = wec.clone();
923 tmp.truncate(0);
924 assert_eq!(tmp.as_slice(), b"");
925
926 let mut tmp = wec.clone();
927 tmp.truncate(4);
928 assert_eq!(tmp.as_slice(), b"\x03www");
929
930 let mut tmp = wec.clone();
931 tmp.truncate(12);
932 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
933
934 let mut tmp = wec.clone();
935 tmp.truncate(16);
936 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
937
938 assert_panic!(wec.clone().truncate(1));
939 assert_panic!(wec.clone().truncate(14));
940 assert_panic!(wec.clone().truncate(17));
941 assert_panic!(wec.clone().truncate(18));
942 }
943
944 #[test]
945 fn split_first() {
946 let mut wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
947 .unwrap();
948
949 assert_eq!(wec.split_first().unwrap().as_slice(), b"\x03www");
950 assert_eq!(wec.as_slice(), b"\x07example\x03com");
951 assert_eq!(wec.split_first().unwrap().as_slice(), b"\x07example");
952 assert_eq!(wec.as_slice(), b"\x03com");
953 assert_eq!(wec.split_first().unwrap().as_slice(), b"\x03com");
954 assert_eq!(wec.as_slice(), b"");
955 assert!(wec.split_first().is_none());
956 assert_eq!(wec.as_slice(), b"");
957 assert!(wec.split_first().is_none());
958 assert_eq!(wec.as_slice(), b"");
959 }
960
961 #[test]
962 fn parent() {
963 let mut wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
964 .unwrap();
965
966 assert!(wec.parent());
967 assert_eq!(wec.as_slice(), b"\x07example\x03com");
968 assert!(wec.parent());
969 assert_eq!(wec.as_slice(), b"\x03com");
970 assert!(wec.parent());
971 assert_eq!(wec.as_slice(), b"");
972 assert!(!wec.parent());
973 assert_eq!(wec.as_slice(), b"");
974 assert!(!wec.parent());
975 assert_eq!(wec.as_slice(), b"");
976 }
977
978 #[test]
979 fn strip_suffix() {
980 let wec = RelativeDname::from_slice(b"\x03www\x07example\x03com")
981 .unwrap();
982 let ec = RelativeDname::from_slice(b"\x07example\x03com").unwrap();
983 let c = RelativeDname::from_slice(b"\x03com").unwrap();
984 let wen = RelativeDname::from_slice(b"\x03www\x07example\x03net")
985 .unwrap();
986 let en = RelativeDname::from_slice(b"\x07example\x03net").unwrap();
987 let n = RelativeDname::from_slice(b"\x03net").unwrap();
988
989 let mut tmp = wec.clone();
990 assert_eq!(tmp.strip_suffix(&wec), Ok(()));
991 assert_eq!(tmp.as_slice(), b"");
992
993 let mut tmp = wec.clone();
994 assert_eq!(tmp.strip_suffix(&ec), Ok(()));
995 assert_eq!(tmp.as_slice(), b"\x03www");
996
997 let mut tmp = wec.clone();
998 assert_eq!(tmp.strip_suffix(&c), Ok(()));
999 assert_eq!(tmp.as_slice(), b"\x03www\x07example");
1000
1001 let mut tmp = wec.clone();
1002 assert_eq!(tmp.strip_suffix(&RelativeDname::empty()), Ok(()));
1003 assert_eq!(tmp.as_slice(), b"\x03www\x07example\x03com");
1004
1005 assert_eq!(wec.clone().strip_suffix(&wen), Err(StripSuffixError));
1006 assert_eq!(wec.clone().strip_suffix(&en), Err(StripSuffixError));
1007 assert_eq!(wec.clone().strip_suffix(&n), Err(StripSuffixError));
1008 }
1009
1010 #[test]
1013 fn eq() {
1014 assert_eq!(
1015 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1016 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap()
1017 );
1018 assert_eq!(
1019 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1020 RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap()
1021 );
1022 assert_eq!(
1023 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1024 RelativeDname::from_slice(b"\x03www").unwrap()
1025 .chain(RelativeDname::from_slice(b"\x07example\x03com")
1026 .unwrap())
1027 .unwrap()
1028 );
1029 assert_eq!(
1030 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1031 RelativeDname::from_slice(b"\x03wWw").unwrap()
1032 .chain(RelativeDname::from_slice(b"\x07eXAMple\x03coM")
1033 .unwrap())
1034 .unwrap()
1035 );
1036
1037 assert_ne!(
1038 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1039 RelativeDname::from_slice(b"\x03ww4\x07example\x03com").unwrap()
1040 );
1041 assert_ne!(
1042 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap(),
1043 RelativeDname::from_slice(b"\x03www").unwrap()
1044 .chain(RelativeDname::from_slice(b"\x073xample\x03com")
1045 .unwrap())
1046 .unwrap()
1047 );
1048 }
1049
1050 #[test]
1051 fn cmp() {
1052 use std::cmp::Ordering;
1053
1054 let names = [
1056 RelativeDname::from_slice(b"\x07example").unwrap(),
1057 RelativeDname::from_slice(b"\x01a\x07example").unwrap(),
1058 RelativeDname::from_slice(b"\x08yljkjljk\x01a\x07example").unwrap(),
1059 RelativeDname::from_slice(b"\x01Z\x01a\x07example").unwrap(),
1060 RelativeDname::from_slice(b"\x04zABC\x01a\x07example").unwrap(),
1061 RelativeDname::from_slice(b"\x01z\x07example").unwrap(),
1062 RelativeDname::from_slice(b"\x01\x01\x01z\x07example").unwrap(),
1063 RelativeDname::from_slice(b"\x01*\x01z\x07example").unwrap(),
1064 RelativeDname::from_slice(b"\x01\xc8\x01z\x07example").unwrap(),
1065 ];
1066 for i in 0..names.len() {
1067 for j in 0..names.len() {
1068 let ord = if i < j { Ordering::Less }
1069 else if i == j { Ordering::Equal }
1070 else { Ordering::Greater };
1071 assert_eq!(names[i].partial_cmp(&names[j]), Some(ord));
1072 assert_eq!(names[i].cmp(&names[j]), ord);
1073 }
1074 }
1075
1076 let n1 = RelativeDname::from_slice(b"\x03www\x07example\x03com")
1077 .unwrap();
1078 let n2 = RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com")
1079 .unwrap();
1080 assert_eq!(n1.partial_cmp(&n2), Some(Ordering::Equal));
1081 assert_eq!(n1.cmp(&n2), Ordering::Equal);
1082 }
1083
1084 #[test]
1085 fn hash() {
1086 use std::collections::hash_map::DefaultHasher;
1087 use std::hash::{Hash, Hasher};
1088
1089 let mut s1 = DefaultHasher::new();
1090 let mut s2 = DefaultHasher::new();
1091 RelativeDname::from_slice(b"\x03www\x07example\x03com").unwrap()
1092 .hash(&mut s1);
1093 RelativeDname::from_slice(b"\x03wWw\x07eXAMple\x03Com").unwrap()
1094 .hash(&mut s2);
1095 assert_eq!(s1.finish(), s2.finish());
1096 }
1097
1098 }
1100