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