1use super::super::scan::Scanner;
6use super::super::wire::ParseError;
7use super::builder::{DnameBuilder, FromStrError, PushError};
8use super::chain::{Chain, LongChainError};
9use super::dname::Dname;
10use super::label::{Label, LabelTypeError, SplitLabelError};
11use super::relative::{DnameIter, RelativeDname};
12use super::traits::ToLabelIter;
13#[cfg(feature = "bytes")]
14use bytes::Bytes;
15use core::{fmt, hash, str};
16use octseq::builder::{
17 EmptyBuilder, FreezeBuilder, FromBuilder, IntoBuilder,
18};
19#[cfg(feature = "serde")]
20use octseq::serde::{DeserializeOctets, SerializeOctets};
21#[cfg(feature = "std")]
22use std::vec::Vec;
23
24#[derive(Clone)]
31pub enum UncertainDname<Octets> {
32 Absolute(Dname<Octets>),
33 Relative(RelativeDname<Octets>),
34}
35
36impl<Octets> UncertainDname<Octets> {
37 pub fn absolute(name: Dname<Octets>) -> Self {
39 UncertainDname::Absolute(name)
40 }
41
42 pub fn relative(name: RelativeDname<Octets>) -> Self {
44 UncertainDname::Relative(name)
45 }
46
47 #[must_use]
49 pub fn root() -> Self
50 where
51 Octets: From<&'static [u8]>,
52 {
53 UncertainDname::Absolute(Dname::root())
54 }
55
56 #[must_use]
58 pub fn empty() -> Self
59 where
60 Octets: From<&'static [u8]>,
61 {
62 UncertainDname::Relative(RelativeDname::empty())
63 }
64
65 pub fn from_octets(octets: Octets) -> Result<Self, UncertainDnameError>
70 where
71 Octets: AsRef<[u8]>,
72 {
73 if Self::is_slice_absolute(octets.as_ref())? {
74 Ok(UncertainDname::Absolute(unsafe {
75 Dname::from_octets_unchecked(octets)
76 }))
77 } else {
78 Ok(UncertainDname::Relative(unsafe {
79 RelativeDname::from_octets_unchecked(octets)
80 }))
81 }
82 }
83
84 fn is_slice_absolute(
86 mut slice: &[u8],
87 ) -> Result<bool, UncertainDnameError> {
88 if slice.len() > Dname::MAX_LEN {
89 return Err(UncertainDnameError::LongName);
90 }
91 loop {
92 let (label, tail) = Label::split_from(slice)?;
93 if label.is_root() {
94 if tail.is_empty() {
95 return Ok(true);
96 } else {
97 return Err(UncertainDnameError::TrailingData);
98 }
99 }
100 if tail.is_empty() {
101 return Ok(false);
102 }
103 slice = tail;
104 }
105 }
106
107 pub fn from_chars<C>(chars: C) -> Result<Self, FromStrError>
125 where
126 Octets: FromBuilder,
127 <Octets as FromBuilder>::Builder: FreezeBuilder<Octets = Octets>
128 + EmptyBuilder
129 + AsRef<[u8]>
130 + AsMut<[u8]>,
131 C: IntoIterator<Item = char>,
132 {
133 let mut builder =
134 DnameBuilder::<<Octets as FromBuilder>::Builder>::new();
135 builder.append_chars(chars)?;
136 if builder.in_label() || builder.is_empty() {
137 Ok(builder.finish().into())
138 } else {
139 Ok(builder.into_dname()?.into())
140 }
141 }
142
143 pub fn scan<S: Scanner<Dname = Dname<Octets>>>(
144 scanner: &mut S,
145 ) -> Result<Self, S::Error> {
146 scanner.scan_dname().map(UncertainDname::Absolute)
147 }
148}
149
150impl UncertainDname<&'static [u8]> {
151 #[must_use]
153 pub fn empty_ref() -> Self {
154 Self::empty()
155 }
156
157 #[must_use]
159 pub fn root_ref() -> Self {
160 Self::root()
161 }
162}
163
164#[cfg(feature = "std")]
165impl UncertainDname<Vec<u8>> {
166 #[must_use]
168 pub fn empty_vec() -> Self {
169 Self::empty()
170 }
171
172 #[must_use]
174 pub fn root_vec() -> Self {
175 Self::root()
176 }
177}
178
179#[cfg(feature = "bytes")]
180impl UncertainDname<Bytes> {
181 pub fn empty_bytes() -> Self {
183 Self::empty()
184 }
185
186 pub fn root_bytes() -> Self {
188 Self::root()
189 }
190}
191
192impl<Octets> UncertainDname<Octets> {
193 pub fn is_absolute(&self) -> bool {
195 match *self {
196 UncertainDname::Absolute(_) => true,
197 UncertainDname::Relative(_) => false,
198 }
199 }
200
201 pub fn is_relative(&self) -> bool {
203 !self.is_absolute()
204 }
205
206 pub fn as_absolute(&self) -> Option<&Dname<Octets>> {
208 match *self {
209 UncertainDname::Absolute(ref name) => Some(name),
210 _ => None,
211 }
212 }
213
214 pub fn as_relative(&self) -> Option<&RelativeDname<Octets>> {
216 match *self {
217 UncertainDname::Relative(ref name) => Some(name),
218 _ => None,
219 }
220 }
221
222 pub fn into_absolute(self) -> Result<Dname<Octets>, PushError>
230 where
231 Octets: AsRef<[u8]> + IntoBuilder,
232 <Octets as IntoBuilder>::Builder:
233 FreezeBuilder<Octets = Octets> + AsRef<[u8]> + AsMut<[u8]>,
234 {
235 match self {
236 UncertainDname::Absolute(name) => Ok(name),
237 UncertainDname::Relative(name) => name.into_absolute(),
238 }
239 }
240
241 pub fn try_into_absolute(self) -> Result<Dname<Octets>, Self> {
245 if let UncertainDname::Absolute(name) = self {
246 Ok(name)
247 } else {
248 Err(self)
249 }
250 }
251
252 pub fn try_into_relative(self) -> Result<RelativeDname<Octets>, Self> {
256 if let UncertainDname::Relative(name) = self {
257 Ok(name)
258 } else {
259 Err(self)
260 }
261 }
262
263 pub fn as_octets(&self) -> &Octets {
265 match *self {
266 UncertainDname::Absolute(ref name) => name.as_octets(),
267 UncertainDname::Relative(ref name) => name.as_octets(),
268 }
269 }
270
271 pub fn as_slice(&self) -> &[u8]
273 where
274 Octets: AsRef<[u8]>,
275 {
276 match *self {
277 UncertainDname::Absolute(ref name) => name.as_slice(),
278 UncertainDname::Relative(ref name) => name.as_slice(),
279 }
280 }
281
282 pub fn chain<S: ToLabelIter>(
289 self,
290 suffix: S,
291 ) -> Result<Chain<Self, S>, LongChainError>
292 where
293 Octets: AsRef<[u8]>,
294 {
295 Chain::new_uncertain(self, suffix)
296 }
297}
298
299impl<Octets> From<Dname<Octets>> for UncertainDname<Octets> {
302 fn from(src: Dname<Octets>) -> Self {
303 UncertainDname::Absolute(src)
304 }
305}
306
307impl<Octets> From<RelativeDname<Octets>> for UncertainDname<Octets> {
308 fn from(src: RelativeDname<Octets>) -> Self {
309 UncertainDname::Relative(src)
310 }
311}
312
313impl<Octets> str::FromStr for UncertainDname<Octets>
316where
317 Octets: FromBuilder,
318 <Octets as FromBuilder>::Builder: EmptyBuilder
319 + FreezeBuilder<Octets = Octets>
320 + AsRef<[u8]>
321 + AsMut<[u8]>,
322{
323 type Err = FromStrError;
324
325 fn from_str(s: &str) -> Result<Self, Self::Err> {
326 Self::from_chars(s.chars())
327 }
328}
329
330impl<Octs> AsRef<Octs> for UncertainDname<Octs> {
333 fn as_ref(&self) -> &Octs {
334 match *self {
335 UncertainDname::Absolute(ref name) => name.as_ref(),
336 UncertainDname::Relative(ref name) => name.as_ref(),
337 }
338 }
339}
340
341impl<Octs: AsRef<[u8]>> AsRef<[u8]> for UncertainDname<Octs> {
342 fn as_ref(&self) -> &[u8] {
343 match *self {
344 UncertainDname::Absolute(ref name) => name.as_ref(),
345 UncertainDname::Relative(ref name) => name.as_ref(),
346 }
347 }
348}
349
350impl<Octets, Other> PartialEq<UncertainDname<Other>>
353 for UncertainDname<Octets>
354where
355 Octets: AsRef<[u8]>,
356 Other: AsRef<[u8]>,
357{
358 fn eq(&self, other: &UncertainDname<Other>) -> bool {
359 use UncertainDname::*;
360
361 match (self, other) {
362 (Absolute(l), Absolute(r)) => l.eq(r),
363 (Relative(l), Relative(r)) => l.eq(r),
364 _ => false,
365 }
366 }
367}
368
369impl<Octets: AsRef<[u8]>> Eq for UncertainDname<Octets> {}
370
371impl<Octets: AsRef<[u8]>> hash::Hash for UncertainDname<Octets> {
374 fn hash<H: hash::Hasher>(&self, state: &mut H) {
375 for item in self.iter_labels() {
376 item.hash(state)
377 }
378 }
379}
380
381impl<Octs: AsRef<[u8]>> ToLabelIter for UncertainDname<Octs> {
384 type LabelIter<'a> = DnameIter<'a> where Octs: 'a;
385
386 fn iter_labels(&self) -> Self::LabelIter<'_> {
387 match *self {
388 UncertainDname::Absolute(ref name) => name.iter_labels(),
389 UncertainDname::Relative(ref name) => name.iter_labels(),
390 }
391 }
392
393 fn compose_len(&self) -> u16 {
394 match *self {
395 UncertainDname::Absolute(ref name) => name.compose_len(),
396 UncertainDname::Relative(ref name) => name.compose_len(),
397 }
398 }
399}
400
401impl<'a, Octets: AsRef<[u8]>> IntoIterator for &'a UncertainDname<Octets> {
404 type Item = &'a Label;
405 type IntoIter = DnameIter<'a>;
406
407 fn into_iter(self) -> Self::IntoIter {
408 self.iter_labels()
409 }
410}
411
412impl<Octets: AsRef<[u8]>> fmt::Display for UncertainDname<Octets> {
415 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416 match *self {
417 UncertainDname::Absolute(ref name) => {
418 write!(f, "{}.", name)
419 }
420 UncertainDname::Relative(ref name) => name.fmt(f),
421 }
422 }
423}
424
425impl<Octets: AsRef<[u8]>> fmt::Debug for UncertainDname<Octets> {
426 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
427 match *self {
428 UncertainDname::Absolute(ref name) => {
429 write!(f, "UncertainDname::Absolute({})", name)
430 }
431 UncertainDname::Relative(ref name) => {
432 write!(f, "UncertainDname::Relative({})", name)
433 }
434 }
435 }
436}
437
438#[cfg(feature = "serde")]
441impl<Octets> serde::Serialize for UncertainDname<Octets>
442where
443 Octets: AsRef<[u8]> + SerializeOctets,
444{
445 fn serialize<S: serde::Serializer>(
446 &self,
447 serializer: S,
448 ) -> Result<S::Ok, S::Error> {
449 if serializer.is_human_readable() {
450 serializer.serialize_newtype_struct(
451 "UncertainDname",
452 &format_args!("{}", self),
453 )
454 } else {
455 serializer.serialize_newtype_struct(
456 "UncertainDname",
457 &self.as_octets().as_serialized_octets(),
458 )
459 }
460 }
461}
462
463#[cfg(feature = "serde")]
464impl<'de, Octets> serde::Deserialize<'de> for UncertainDname<Octets>
465where
466 Octets: FromBuilder + DeserializeOctets<'de>,
467 <Octets as FromBuilder>::Builder: EmptyBuilder
468 + FreezeBuilder<Octets = Octets>
469 + AsRef<[u8]>
470 + AsMut<[u8]>,
471{
472 fn deserialize<D: serde::Deserializer<'de>>(
473 deserializer: D,
474 ) -> Result<Self, D::Error> {
475 use core::marker::PhantomData;
476
477 struct InnerVisitor<'de, T: DeserializeOctets<'de>>(T::Visitor);
478
479 impl<'de, Octets> serde::de::Visitor<'de> for InnerVisitor<'de, Octets>
480 where
481 Octets: FromBuilder + DeserializeOctets<'de>,
482 <Octets as FromBuilder>::Builder: EmptyBuilder
483 + FreezeBuilder<Octets = Octets>
484 + AsRef<[u8]>
485 + AsMut<[u8]>,
486 {
487 type Value = UncertainDname<Octets>;
488
489 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
490 f.write_str("a domain name")
491 }
492
493 fn visit_str<E: serde::de::Error>(
494 self,
495 v: &str,
496 ) -> Result<Self::Value, E> {
497 use core::str::FromStr;
498
499 UncertainDname::from_str(v).map_err(E::custom)
500 }
501
502 fn visit_borrowed_bytes<E: serde::de::Error>(
503 self,
504 value: &'de [u8],
505 ) -> Result<Self::Value, E> {
506 self.0.visit_borrowed_bytes(value).and_then(|octets| {
507 UncertainDname::from_octets(octets).map_err(E::custom)
508 })
509 }
510
511 #[cfg(feature = "std")]
512 fn visit_byte_buf<E: serde::de::Error>(
513 self,
514 value: std::vec::Vec<u8>,
515 ) -> Result<Self::Value, E> {
516 self.0.visit_byte_buf(value).and_then(|octets| {
517 UncertainDname::from_octets(octets).map_err(E::custom)
518 })
519 }
520 }
521
522 struct NewtypeVisitor<T>(PhantomData<T>);
523
524 impl<'de, Octets> serde::de::Visitor<'de> for NewtypeVisitor<Octets>
525 where
526 Octets: FromBuilder + DeserializeOctets<'de>,
527 <Octets as FromBuilder>::Builder: EmptyBuilder
528 + FreezeBuilder<Octets = Octets>
529 + AsRef<[u8]>
530 + AsMut<[u8]>,
531 {
532 type Value = UncertainDname<Octets>;
533
534 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
535 f.write_str("a domain name")
536 }
537
538 fn visit_newtype_struct<D: serde::Deserializer<'de>>(
539 self,
540 deserializer: D,
541 ) -> Result<Self::Value, D::Error> {
542 if deserializer.is_human_readable() {
543 deserializer
544 .deserialize_str(InnerVisitor(Octets::visitor()))
545 } else {
546 Octets::deserialize_with_visitor(
547 deserializer,
548 InnerVisitor(Octets::visitor()),
549 )
550 }
551 }
552 }
553
554 deserializer.deserialize_newtype_struct(
555 "UncertainDname",
556 NewtypeVisitor(PhantomData),
557 )
558 }
559}
560
561#[derive(Clone, Copy, Debug, Eq, PartialEq)]
567pub enum UncertainDnameError {
568 BadLabel(LabelTypeError),
570
571 CompressedName,
573
574 LongName,
576
577 TrailingData,
579
580 ShortInput,
582}
583
584impl From<LabelTypeError> for UncertainDnameError {
587 fn from(err: LabelTypeError) -> UncertainDnameError {
588 UncertainDnameError::BadLabel(err)
589 }
590}
591
592impl From<SplitLabelError> for UncertainDnameError {
593 fn from(err: SplitLabelError) -> UncertainDnameError {
594 match err {
595 SplitLabelError::Pointer(_) => {
596 UncertainDnameError::CompressedName
597 }
598 SplitLabelError::BadType(t) => UncertainDnameError::BadLabel(t),
599 SplitLabelError::ShortInput => UncertainDnameError::ShortInput,
600 }
601 }
602}
603
604impl fmt::Display for UncertainDnameError {
607 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
608 match *self {
609 UncertainDnameError::BadLabel(ref err) => err.fmt(f),
610 UncertainDnameError::CompressedName => {
611 f.write_str("compressed domain name")
612 }
613 UncertainDnameError::LongName => f.write_str("long domain name"),
614 UncertainDnameError::TrailingData => f.write_str("trailing data"),
615 UncertainDnameError::ShortInput => ParseError::ShortInput.fmt(f),
616 }
617 }
618}
619
620#[cfg(feature = "std")]
621impl std::error::Error for UncertainDnameError {}
622
623#[cfg(test)]
626#[cfg(feature = "std")]
627mod test {
628 use super::*;
629 use std::str::FromStr;
630 use std::string::String;
631
632 #[test]
633 fn from_str() {
634 type U = UncertainDname<Vec<u8>>;
635
636 fn name(s: &str) -> U {
637 U::from_str(s).unwrap()
638 }
639
640 assert_eq!(
641 name("www.example.com").as_relative().unwrap().as_slice(),
642 b"\x03www\x07example\x03com"
643 );
644 assert_eq!(
645 name("www.example.com.").as_absolute().unwrap().as_slice(),
646 b"\x03www\x07example\x03com\0"
647 );
648
649 assert_eq!(
650 name(r"www\.example.com").as_slice(),
651 b"\x0bwww.example\x03com"
652 );
653 assert_eq!(
654 name(r"w\119w.example.com").as_slice(),
655 b"\x03www\x07example\x03com"
656 );
657 assert_eq!(
658 name(r"w\000w.example.com").as_slice(),
659 b"\x03w\0w\x07example\x03com"
660 );
661
662 assert_eq!(U::from_str(r"w\01"), Err(FromStrError::UnexpectedEnd));
663 assert_eq!(U::from_str(r"w\"), Err(FromStrError::UnexpectedEnd));
664 assert_eq!(
665 U::from_str(r"www..example.com"),
666 Err(FromStrError::EmptyLabel)
667 );
668 assert_eq!(
669 U::from_str(r"www.example.com.."),
670 Err(FromStrError::EmptyLabel)
671 );
672 assert_eq!(
673 U::from_str(r".www.example.com"),
674 Err(FromStrError::EmptyLabel)
675 );
676 assert_eq!(
677 U::from_str(r"www.\[322].example.com"),
678 Err(FromStrError::BinaryLabel)
679 );
680 assert_eq!(
681 U::from_str(r"www.\2example.com"),
682 Err(FromStrError::IllegalEscape)
683 );
684 assert_eq!(
685 U::from_str(r"www.\29example.com"),
686 Err(FromStrError::IllegalEscape)
687 );
688 assert_eq!(
689 U::from_str(r"www.\299example.com"),
690 Err(FromStrError::IllegalEscape)
691 );
692 assert_eq!(
693 U::from_str(r"www.\892example.com"),
694 Err(FromStrError::IllegalEscape)
695 );
696 assert_eq!(
697 U::from_str("www.e\0ample.com"),
698 Err(FromStrError::IllegalCharacter('\0'))
699 );
700 assert_eq!(
701 U::from_str("www.eüample.com"),
702 Err(FromStrError::IllegalCharacter('ü'))
703 );
704
705 let mut s = String::from("www.");
707 for _ in 0..Label::MAX_LEN {
708 s.push('x');
709 }
710 s.push_str(".com");
711 assert!(U::from_str(&s).is_ok());
712 let mut s = String::from("www.");
713 for _ in 0..64 {
714 s.push('x');
715 }
716 s.push_str(".com");
717 assert_eq!(U::from_str(&s), Err(FromStrError::LongLabel));
718
719 let mut s = String::new();
721 for _ in 0..50 {
722 s.push_str("four.");
723 }
724 let mut s1 = s.clone();
725 s1.push_str("com.");
726 assert_eq!(name(&s1).as_slice().len(), 255);
727 let mut s1 = s.clone();
728 s1.push_str("com");
729 assert_eq!(name(&s1).as_slice().len(), 254);
730 let mut s1 = s.clone();
731 s1.push_str("coma.");
732 assert_eq!(U::from_str(&s1), Err(FromStrError::LongName));
733 let mut s1 = s.clone();
734 s1.push_str("coma");
735 assert_eq!(U::from_str(&s1), Err(FromStrError::LongName));
736 }
737
738 #[cfg(feature = "serde")]
739 #[test]
740 fn ser_de() {
741 use serde_test::{assert_tokens, Configure, Token};
742
743 let abs_name =
744 UncertainDname::<Vec<u8>>::from_str("www.example.com.").unwrap();
745 assert!(abs_name.is_absolute());
746
747 assert_tokens(
748 &abs_name.clone().compact(),
749 &[
750 Token::NewtypeStruct {
751 name: "UncertainDname",
752 },
753 Token::ByteBuf(b"\x03www\x07example\x03com\0"),
754 ],
755 );
756 assert_tokens(
757 &abs_name.readable(),
758 &[
759 Token::NewtypeStruct {
760 name: "UncertainDname",
761 },
762 Token::Str("www.example.com."),
763 ],
764 );
765
766 let rel_name =
767 UncertainDname::<Vec<u8>>::from_str("www.example.com").unwrap();
768 assert!(rel_name.is_relative());
769
770 assert_tokens(
771 &rel_name.clone().compact(),
772 &[
773 Token::NewtypeStruct {
774 name: "UncertainDname",
775 },
776 Token::ByteBuf(b"\x03www\x07example\x03com"),
777 ],
778 );
779 assert_tokens(
780 &rel_name.readable(),
781 &[
782 Token::NewtypeStruct {
783 name: "UncertainDname",
784 },
785 Token::Str("www.example.com"),
786 ],
787 );
788 }
789}