1#![deny(missing_docs)]
72#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
73
74pub mod ethernet;
75pub mod ip;
76
77use core::fmt::{self, Debug, Display, Formatter};
78use core::ops::Deref;
79
80use crate::ip::{GenericOverIp, Ip, IpAddress, IpInvariant, IpVersionMarker};
81
82mod sealed {
83 pub trait Sealed {}
86}
87
88pub trait Witness<A>: AsRef<A> + Sized + sealed::Sealed {
95 fn new(addr: A) -> Option<Self>;
100
101 unsafe fn new_unchecked(addr: A) -> Self;
109
110 fn from_witness<W: Witness<A>>(addr: W) -> Option<Self> {
114 Self::new(addr.into_addr())
115 }
116
117 #[inline]
125 fn get(&self) -> A
126 where
127 A: Copy,
128 {
129 *self.as_ref()
130 }
131
132 fn into_addr(self) -> A;
145
146 fn transpose<T>(self) -> A::Map<Self::Map<T>>
150 where
151 Self: TransposableWitness<A>,
152 A: TransposableWitness<T>,
153 Self::Map<T>: Witness<T>,
154 A::Map<Self::Map<T>>: Witness<Self::Map<T>>,
155 {
156 let middle = self.into_addr();
157 let innermost = middle.into_addr();
158 unsafe {
159 let new_middle = Self::Map::<T>::new_unchecked(innermost);
162 A::Map::<Self::Map<T>>::new_unchecked(new_middle)
163 }
164 }
165}
166
167pub trait TransposableWitness<A>: Witness<A> {
178 type Map<T>;
180}
181
182macro_rules! impl_trait_for_witness {
202 ($trait:ident, $method:ident, $witness:ident) => {
203 impl<A: $trait> $trait for $witness<A> {
204 fn $method(&self) -> bool {
205 self.0.$method()
206 }
207 }
208 };
209}
210
211macro_rules! impl_trait_with_associated_type_for_witness {
216 ($trait:ident, $method:ident, $type:ident, $witness:ident) => {
217 impl<A: $trait> $trait for $witness<A> {
218 type $type = A::$type;
219 fn $method(&self) -> Self::$type {
220 self.0.$method()
221 }
222 }
223 };
224}
225
226pub trait SpecifiedAddress {
239 fn is_specified(&self) -> bool;
249}
250
251impl_trait_for_witness!(SpecifiedAddress, is_specified, UnicastAddr);
252impl_trait_for_witness!(SpecifiedAddress, is_specified, MulticastAddr);
253impl_trait_for_witness!(SpecifiedAddress, is_specified, BroadcastAddr);
254impl_trait_for_witness!(SpecifiedAddress, is_specified, LinkLocalAddr);
255impl_trait_for_witness!(SpecifiedAddress, is_specified, NonMappedAddr);
256
257pub trait UnicastAddress {
271 fn is_unicast(&self) -> bool;
284}
285
286impl_trait_for_witness!(UnicastAddress, is_unicast, SpecifiedAddr);
287impl_trait_for_witness!(UnicastAddress, is_unicast, MulticastAddr);
288impl_trait_for_witness!(UnicastAddress, is_unicast, BroadcastAddr);
289impl_trait_for_witness!(UnicastAddress, is_unicast, LinkLocalAddr);
290impl_trait_for_witness!(UnicastAddress, is_unicast, NonMappedAddr);
291
292pub trait MulticastAddress {
302 fn is_multicast(&self) -> bool;
315
316 fn is_non_multicast(&self) -> bool {
318 !self.is_multicast()
319 }
320}
321
322impl_trait_for_witness!(MulticastAddress, is_multicast, SpecifiedAddr);
323impl_trait_for_witness!(MulticastAddress, is_multicast, UnicastAddr);
324impl_trait_for_witness!(MulticastAddress, is_multicast, BroadcastAddr);
325impl_trait_for_witness!(MulticastAddress, is_multicast, LinkLocalAddr);
326impl_trait_for_witness!(MulticastAddress, is_multicast, NonMappedAddr);
327
328pub trait BroadcastAddress {
338 fn is_broadcast(&self) -> bool;
343}
344
345impl_trait_for_witness!(BroadcastAddress, is_broadcast, SpecifiedAddr);
346impl_trait_for_witness!(BroadcastAddress, is_broadcast, UnicastAddr);
347impl_trait_for_witness!(BroadcastAddress, is_broadcast, MulticastAddr);
348impl_trait_for_witness!(BroadcastAddress, is_broadcast, LinkLocalAddr);
349impl_trait_for_witness!(BroadcastAddress, is_broadcast, NonMappedAddr);
350
351pub trait LinkLocalAddress {
363 fn is_link_local(&self) -> bool;
376}
377
378impl_trait_for_witness!(LinkLocalAddress, is_link_local, SpecifiedAddr);
379impl_trait_for_witness!(LinkLocalAddress, is_link_local, UnicastAddr);
380impl_trait_for_witness!(LinkLocalAddress, is_link_local, MulticastAddr);
381impl_trait_for_witness!(LinkLocalAddress, is_link_local, BroadcastAddr);
382impl_trait_for_witness!(LinkLocalAddress, is_link_local, NonMappedAddr);
383
384pub trait Scope {
391 fn can_have_zone(&self) -> bool;
393}
394
395impl Scope for () {
396 fn can_have_zone(&self) -> bool {
397 false
398 }
399}
400
401pub trait ScopeableAddress {
415 type Scope: Scope;
417
418 fn scope(&self) -> Self::Scope;
433}
434
435impl_trait_with_associated_type_for_witness!(ScopeableAddress, scope, Scope, SpecifiedAddr);
436impl_trait_with_associated_type_for_witness!(ScopeableAddress, scope, Scope, UnicastAddr);
437impl_trait_with_associated_type_for_witness!(ScopeableAddress, scope, Scope, MulticastAddr);
438impl_trait_with_associated_type_for_witness!(ScopeableAddress, scope, Scope, BroadcastAddr);
439impl_trait_with_associated_type_for_witness!(ScopeableAddress, scope, Scope, LinkLocalAddr);
440impl_trait_with_associated_type_for_witness!(ScopeableAddress, scope, Scope, NonMappedAddr);
441
442pub trait MappedAddress {
452 fn is_non_mapped(&self) -> bool;
454}
455
456impl_trait_for_witness!(MappedAddress, is_non_mapped, SpecifiedAddr);
457impl_trait_for_witness!(MappedAddress, is_non_mapped, UnicastAddr);
458impl_trait_for_witness!(MappedAddress, is_non_mapped, MulticastAddr);
459impl_trait_for_witness!(MappedAddress, is_non_mapped, BroadcastAddr);
460impl_trait_for_witness!(MappedAddress, is_non_mapped, LinkLocalAddr);
461
462macro_rules! doc_comment {
463 ($x:expr, $($tt:tt)*) => {
464 #[doc = $x]
465 $($tt)*
466 };
467}
468
469macro_rules! impl_witness {
480 ($type:ident, $adj:literal, $trait:ident, $method:ident) => {
481 doc_comment! {
482 concat!("An address which is guaranteed to be ", $adj, ".
483
484`", stringify!($type), "` wraps an address of type `A` and guarantees that it is
485a ", $adj, " address. Note that this guarantee is contingent on a correct
486implementation of the [`", stringify!($trait), "`] trait. Since that trait is
487not `unsafe`, `unsafe` code may NOT rely on this guarantee for its soundness."),
488 #[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
489 pub struct $type<A>(A);
490 }
491
492 impl<A: $trait> $type<A> {
493 doc_comment! {
507 concat!("Constructs a new `", stringify!($type), "`.
508
509`new` returns `None` if `!addr.", stringify!($method), "()`."),
510 #[inline]
511 pub fn new(addr: A) -> Option<$type<A>> {
512 if !addr.$method() {
513 return None;
514 }
515 Some($type(addr))
516 }
517 }
518
519 doc_comment! {
520 concat!("Constructs a new `", stringify!($type), "` from a
521witness type.
522
523`from_witness(witness)` is equivalent to `new(witness.into_addr())`."),
524 pub fn from_witness<W: Witness<A>>(addr: W) -> Option<$type<A>> {
525 $type::new(addr.into_addr())
526 }
527 }
528 }
529
530 impl<A> $type<A> {
534 doc_comment! {
535 concat!("Constructs a new `", stringify!($type), "` without
536checking to see if `addr` is actually ", $adj, ".
537
538# Safety
539
540It is up to the caller to make sure that `addr` is ", $adj, " to avoid breaking
541the guarantees of `", stringify!($type), "`. See [`", stringify!($type), "`] for
542more details."),
543 pub const unsafe fn new_unchecked(addr: A) -> $type<A> {
544 $type(addr)
545 }
546 }
547 }
548
549 impl<A> sealed::Sealed for $type<A> {}
550 impl<A: $trait> Witness<A> for $type<A> {
551 fn new(addr: A) -> Option<$type<A>> {
552 $type::new(addr)
553 }
554
555 unsafe fn new_unchecked(addr: A) -> $type<A> {
556 $type(addr)
557 }
558
559 #[inline]
560 fn into_addr(self) -> A {
561 self.0
562 }
563 }
564
565 impl<A: $trait> TransposableWitness<A> for $type<A> {
566 type Map<T> = $type<T>;
567 }
568
569 impl<A: $trait> AsRef<$type<A>> for $type<A> {
570 fn as_ref(&self) -> &$type<A> {
571 self
572 }
573 }
574
575 impl<A: $trait> AsRef<A> for $type<A> {
576 fn as_ref(&self) -> &A {
577 &self.0
578 }
579 }
580
581 impl<A: $trait> Deref for $type<A> {
582 type Target = A;
583
584 #[inline]
585 fn deref(&self) -> &A {
586 &self.0
587 }
588 }
589
590 impl<A: Display> Display for $type<A> {
591 #[inline]
592 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
593 self.0.fmt(f)
594 }
595 }
596
597 impl<A: Debug> Debug for $type<A> {
601 #[inline]
602 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
603 self.0.fmt(f)
604 }
605 }
606 };
607}
608
609macro_rules! impl_into_specified {
619 ($type:ident, $trait:ident, $method:ident) => {
620 impl<A: $trait + SpecifiedAddress> $type<A> {
621 doc_comment! {
622 concat!("Converts this `", stringify!($type), "` into a
623[`SpecifiedAddr`].
624
625[`", stringify!($trait), "::", stringify!($method), "`] implies
626[`SpecifiedAddress::is_specified`], so all `", stringify!($type), "`s are
627guaranteed to be specified, so this conversion is infallible."),
628 #[inline]
629 pub fn into_specified(self) -> SpecifiedAddr<A> {
630 SpecifiedAddr(self.0)
631 }
632 }
633 }
634
635 impl<A: $trait + SpecifiedAddress> From<$type<A>> for SpecifiedAddr<A> {
636 fn from(addr: $type<A>) -> SpecifiedAddr<A> {
637 addr.into_specified()
638 }
639 }
640 };
641}
642
643macro_rules! impl_nested_witness {
655 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident) => {
656 impl<A: $trait1 + $trait2> Witness<A> for $type1<$type2<A>> {
657 #[inline]
658 fn new(addr: A) -> Option<$type1<$type2<A>>> {
659 $type2::new(addr).and_then(Witness::<$type2<A>>::new)
660 }
661
662 unsafe fn new_unchecked(addr: A) -> $type1<$type2<A>> {
663 $type1($type2(addr))
664 }
665
666 #[inline]
667 fn into_addr(self) -> A {
668 self.0.into_addr()
669 }
670 }
671
672 impl<A: $trait1 + $trait2> AsRef<A> for $type1<$type2<A>> {
673 fn as_ref(&self) -> &A {
674 &self.0 .0
675 }
676 }
677 };
678 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident, $trait3:ident, $type3:ident) => {
679 impl<A: $trait1 + $trait2 + $trait3> Witness<A> for $type1<$type2<$type3<A>>> {
680 #[inline]
681 fn new(addr: A) -> Option<$type1<$type2<$type3<A>>>> {
682 $type3::new(addr).and_then(Witness::<$type3<A>>::new)
683 }
684
685 unsafe fn new_unchecked(addr: A) -> $type1<$type2<$type3<A>>> {
686 $type1($type2($type3(addr)))
687 }
688
689 #[inline]
690 fn into_addr(self) -> A {
691 self.0.into_addr()
692 }
693 }
694
695 impl<A: $trait1 + $trait2 + $trait3> AsRef<A> for $type1<$type2<$type3<A>>> {
696 fn as_ref(&self) -> &A {
697 &self.0 .0
698 }
699 }
700 };
701}
702
703macro_rules! impl_into_specified_for_nested_witness {
715 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident) => {
716 impl<A: $trait1 + $trait2 + SpecifiedAddress> From<$type1<$type2<A>>> for SpecifiedAddr<A> {
717 fn from(addr: $type1<$type2<A>>) -> SpecifiedAddr<A> {
718 SpecifiedAddr(addr.into_addr())
719 }
720 }
721 };
722 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident, $trait3:ident, $type3:ident) => {
723 impl<A: $trait1 + $trait2 + $trait3 + SpecifiedAddress> From<$type1<$type2<$type3<A>>>>
724 for SpecifiedAddr<A>
725 {
726 fn from(addr: $type1<$type2<$type3<A>>>) -> SpecifiedAddr<A> {
727 SpecifiedAddr(addr.into_addr())
728 }
729 }
730 };
731}
732
733macro_rules! impl_try_from_witness {
735 (@inner [$from_ty:ident: $from_trait:ident], [$into_ty:ident: $into_trait:ident]) => {
736 impl<A: $from_trait + $into_trait> TryFrom<$from_ty<A>> for $into_ty<A> {
737 type Error = ();
738 fn try_from(addr: $from_ty<A>) -> Result<$into_ty<A>, ()> {
739 Witness::<A>::from_witness(addr).ok_or(())
740 }
741 }
742 };
743 ([$from_ty:ident: $from_trait:ident], $([$into_ty:ident: $into_trait:ident]),*) => {
744 $(
745 impl_try_from_witness!(@inner [$from_ty: $from_trait], [$into_ty: $into_trait]);
746 )*
747 }
748}
749
750impl_witness!(SpecifiedAddr, "specified", SpecifiedAddress, is_specified);
752impl_try_from_witness!(
753 [SpecifiedAddr: SpecifiedAddress],
754 [UnicastAddr: UnicastAddress],
755 [MulticastAddr: MulticastAddress],
756 [BroadcastAddr: BroadcastAddress],
757 [LinkLocalAddr: LinkLocalAddress],
758 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
759 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
760 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
761 [NonMappedAddr: MappedAddress]
762);
763
764impl_witness!(UnicastAddr, "unicast", UnicastAddress, is_unicast);
766impl_into_specified!(UnicastAddr, UnicastAddress, is_unicast);
767impl_nested_witness!(UnicastAddress, UnicastAddr, LinkLocalAddress, LinkLocalAddr);
768impl_nested_witness!(UnicastAddress, UnicastAddr, MappedAddress, NonMappedAddr);
769impl_into_specified_for_nested_witness!(
770 UnicastAddress,
771 UnicastAddr,
772 LinkLocalAddress,
773 LinkLocalAddr
774);
775impl_into_specified_for_nested_witness!(UnicastAddress, UnicastAddr, MappedAddress, NonMappedAddr);
776impl_try_from_witness!(
777 [UnicastAddr: UnicastAddress],
778 [MulticastAddr: MulticastAddress],
779 [BroadcastAddr: BroadcastAddress],
780 [LinkLocalAddr: LinkLocalAddress],
781 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
782 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
783 [NonMappedAddr: MappedAddress]
784);
785
786impl_witness!(MulticastAddr, "multicast", MulticastAddress, is_multicast);
788impl_into_specified!(MulticastAddr, MulticastAddress, is_multicast);
789impl_nested_witness!(MulticastAddress, MulticastAddr, LinkLocalAddress, LinkLocalAddr);
790impl_nested_witness!(MulticastAddress, MulticastAddr, MappedAddress, NonMappedAddr);
791impl_into_specified_for_nested_witness!(
792 MulticastAddress,
793 MulticastAddr,
794 LinkLocalAddress,
795 LinkLocalAddr
796);
797impl_into_specified_for_nested_witness!(
798 MulticastAddress,
799 MulticastAddr,
800 MappedAddress,
801 NonMappedAddr
802);
803impl_try_from_witness!(
804 [MulticastAddr: MulticastAddress],
805 [UnicastAddr: UnicastAddress],
806 [BroadcastAddr: BroadcastAddress],
807 [LinkLocalAddr: LinkLocalAddress],
808 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
809 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
810 [NonMappedAddr: MappedAddress]
811);
812
813impl<A: MulticastAddress + MappedAddress> MulticastAddr<A> {
814 pub fn non_mapped(self) -> NonMappedAddr<MulticastAddr<A>> {
816 unsafe { NonMappedAddr::new_unchecked(self) }
821 }
822}
823
824impl_witness!(NonMulticastAddr, "non-multicast", MulticastAddress, is_non_multicast);
831impl_nested_witness!(MulticastAddress, NonMulticastAddr, SpecifiedAddress, SpecifiedAddr);
832impl_nested_witness!(MulticastAddress, NonMulticastAddr, UnicastAddress, UnicastAddr);
833impl_nested_witness!(MulticastAddress, NonMulticastAddr, BroadcastAddress, BroadcastAddr);
834impl_nested_witness!(MulticastAddress, NonMulticastAddr, MappedAddress, NonMappedAddr);
835impl_nested_witness!(
838 MulticastAddress,
839 NonMulticastAddr,
840 MappedAddress,
841 NonMappedAddr,
842 SpecifiedAddress,
843 SpecifiedAddr
844);
845impl_into_specified_for_nested_witness!(
846 MulticastAddress,
847 NonMulticastAddr,
848 MappedAddress,
849 NonMappedAddr,
850 SpecifiedAddress,
851 SpecifiedAddr
852);
853
854impl_witness!(BroadcastAddr, "broadcast", BroadcastAddress, is_broadcast);
856impl_into_specified!(BroadcastAddr, BroadcastAddress, is_broadcast);
857impl_nested_witness!(BroadcastAddress, BroadcastAddr, LinkLocalAddress, LinkLocalAddr);
858impl_nested_witness!(BroadcastAddress, BroadcastAddr, MappedAddress, NonMappedAddr);
859impl_into_specified_for_nested_witness!(
860 BroadcastAddress,
861 BroadcastAddr,
862 LinkLocalAddress,
863 LinkLocalAddr
864);
865impl_into_specified_for_nested_witness!(
866 BroadcastAddress,
867 BroadcastAddr,
868 MappedAddress,
869 NonMappedAddr
870);
871impl_try_from_witness!(
872 [BroadcastAddr: BroadcastAddress],
873 [UnicastAddr: UnicastAddress],
874 [MulticastAddr: MulticastAddress],
875 [LinkLocalAddr: LinkLocalAddress],
876 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
877 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
878 [NonMappedAddr: MappedAddress]
879);
880
881impl_witness!(LinkLocalAddr, "link-local", LinkLocalAddress, is_link_local);
883impl_into_specified!(LinkLocalAddr, LinkLocalAddress, is_link_local);
884impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, UnicastAddress, UnicastAddr);
885impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, MulticastAddress, MulticastAddr);
886impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, BroadcastAddress, BroadcastAddr);
887impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, MappedAddress, NonMappedAddr);
888impl_into_specified_for_nested_witness!(
889 LinkLocalAddress,
890 LinkLocalAddr,
891 UnicastAddress,
892 UnicastAddr
893);
894impl_into_specified_for_nested_witness!(
895 LinkLocalAddress,
896 LinkLocalAddr,
897 MulticastAddress,
898 MulticastAddr
899);
900impl_into_specified_for_nested_witness!(
901 LinkLocalAddress,
902 LinkLocalAddr,
903 BroadcastAddress,
904 BroadcastAddr
905);
906impl_into_specified_for_nested_witness!(
907 LinkLocalAddress,
908 LinkLocalAddr,
909 MappedAddress,
910 NonMappedAddr
911);
912impl_try_from_witness!(
913 [LinkLocalAddr: LinkLocalAddress],
914 [UnicastAddr: UnicastAddress],
915 [MulticastAddr: MulticastAddress],
916 [BroadcastAddr: BroadcastAddress],
917 [NonMappedAddr: MappedAddress]
918);
919
920impl_witness!(NonMappedAddr, "non_mapped", MappedAddress, is_non_mapped);
922impl_nested_witness!(MappedAddress, NonMappedAddr, SpecifiedAddress, SpecifiedAddr);
923impl_nested_witness!(MappedAddress, NonMappedAddr, UnicastAddress, UnicastAddr);
924impl_nested_witness!(MappedAddress, NonMappedAddr, MulticastAddress, MulticastAddr);
925impl_nested_witness!(MappedAddress, NonMappedAddr, BroadcastAddress, BroadcastAddr);
926impl_nested_witness!(MappedAddress, NonMappedAddr, LinkLocalAddress, LinkLocalAddr);
927impl_into_specified_for_nested_witness!(
928 MappedAddress,
929 NonMappedAddr,
930 SpecifiedAddress,
931 SpecifiedAddr
932);
933impl_into_specified_for_nested_witness!(MappedAddress, NonMappedAddr, UnicastAddress, UnicastAddr);
934impl_into_specified_for_nested_witness!(
935 MappedAddress,
936 NonMappedAddr,
937 MulticastAddress,
938 MulticastAddr
939);
940impl_into_specified_for_nested_witness!(
941 MappedAddress,
942 NonMappedAddr,
943 BroadcastAddress,
944 BroadcastAddr
945);
946impl_into_specified_for_nested_witness!(
947 MappedAddress,
948 NonMappedAddr,
949 LinkLocalAddress,
950 LinkLocalAddr
951);
952impl_try_from_witness!(
953 [NonMappedAddr: MappedAddress],
954 [SpecifiedAddr: SpecifiedAddress],
955 [UnicastAddr: UnicastAddress],
956 [MulticastAddr: MulticastAddress],
957 [BroadcastAddr: BroadcastAddress],
958 [LinkLocalAddr: LinkLocalAddress],
959 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
960 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
961 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
962);
963
964pub trait LinkLocalUnicastAddress: LinkLocalAddress + UnicastAddress {}
977impl<A: LinkLocalAddress + UnicastAddress> LinkLocalUnicastAddress for A {}
978
979pub trait LinkLocalMulticastAddress: LinkLocalAddress + MulticastAddress {}
984impl<A: LinkLocalAddress + MulticastAddress> LinkLocalMulticastAddress for A {}
985
986pub trait LinkLocalBroadcastAddress: LinkLocalAddress + BroadcastAddress {}
991impl<A: LinkLocalAddress + BroadcastAddress> LinkLocalBroadcastAddress for A {}
992
993pub type LinkLocalUnicastAddr<A> = LinkLocalAddr<UnicastAddr<A>>;
995
996pub type LinkLocalMulticastAddr<A> = LinkLocalAddr<MulticastAddr<A>>;
998
999pub type LinkLocalBroadcastAddr<A> = LinkLocalAddr<BroadcastAddr<A>>;
1001
1002impl_try_from_witness!(
1003 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1004 [UnicastAddr: UnicastAddress],
1005 [MulticastAddr: MulticastAddress],
1006 [LinkLocalAddr: LinkLocalAddress],
1007 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
1008 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
1009);
1010impl_try_from_witness!(
1011 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
1012 [UnicastAddr: UnicastAddress],
1013 [MulticastAddr: MulticastAddress],
1014 [LinkLocalAddr: LinkLocalAddress],
1015 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1016 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
1017);
1018impl_try_from_witness!(
1019 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
1020 [UnicastAddr: UnicastAddress],
1021 [MulticastAddr: MulticastAddress],
1022 [LinkLocalAddr: LinkLocalAddress],
1023 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1024 [LinkLocalMulticastAddr: LinkLocalMulticastAddress]
1025);
1026
1027#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1037pub struct AddrAndZone<A, Z>(A, Z);
1038
1039impl<A: ScopeableAddress, Z> AddrAndZone<A, Z> {
1040 pub fn new(addr: A, zone: Z) -> Option<Self> {
1043 if addr.scope().can_have_zone() {
1044 Some(Self(addr, zone))
1045 } else {
1046 None
1047 }
1048 }
1049}
1050
1051impl<A: ScopeableAddress + IpAddress, Z> AddrAndZone<A, Z> {
1052 pub fn new_not_loopback(addr: A, zone: Z) -> Option<Self> {
1056 if addr.scope().can_have_zone() && !addr.is_loopback() {
1057 Some(Self(addr, zone))
1058 } else {
1059 None
1060 }
1061 }
1062}
1063
1064impl<A, Z> AddrAndZone<A, Z> {
1065 #[inline]
1073 pub const unsafe fn new_unchecked(addr: A, zone: Z) -> Self {
1074 Self(addr, zone)
1075 }
1076
1077 pub fn into_addr_scope_id(self) -> (A, Z) {
1079 let AddrAndZone(addr, zone) = self;
1080 (addr, zone)
1081 }
1082
1083 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> AddrAndZone<A, Y> {
1085 let AddrAndZone(addr, zone) = self;
1086 AddrAndZone(addr, f(zone))
1087 }
1088
1089 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> AddrAndZone<B, Z> {
1091 let Self(addr, zone) = self;
1092 AddrAndZone(f(addr), zone)
1093 }
1094
1095 pub fn try_map_zone<Y, E>(
1097 self,
1098 f: impl FnOnce(Z) -> Result<Y, E>,
1099 ) -> Result<AddrAndZone<A, Y>, E> {
1100 let AddrAndZone(addr, zone) = self;
1101 f(zone).map(|zone| AddrAndZone(addr, zone))
1102 }
1103
1104 pub fn addr(&self) -> A
1106 where
1107 A: Copy,
1108 {
1109 let AddrAndZone(addr, _zone) = self;
1110 *addr
1111 }
1112
1113 pub fn as_ref(&self) -> AddrAndZone<&A, &Z> {
1115 let Self(addr, zone) = self;
1116 AddrAndZone(addr, zone)
1117 }
1118}
1119
1120impl<A: Display, Z: Display> Display for AddrAndZone<A, Z> {
1121 #[inline]
1122 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1123 write!(f, "{}%{}", self.0, self.1)
1124 }
1125}
1126
1127impl<A, Z> sealed::Sealed for AddrAndZone<A, Z> {}
1128
1129impl<A: SpecifiedAddress, Z> From<AddrAndZone<SpecifiedAddr<A>, Z>> for AddrAndZone<A, Z> {
1130 fn from(AddrAndZone(addr, zone): AddrAndZone<SpecifiedAddr<A>, Z>) -> Self {
1131 Self(addr.into_addr(), zone)
1132 }
1133}
1134
1135#[allow(missing_docs)]
1137#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1138pub enum ZonedAddr<A, Z> {
1139 Unzoned(A),
1140 Zoned(AddrAndZone<A, Z>),
1141}
1142
1143impl<A: Display, Z: Display> Display for ZonedAddr<A, Z> {
1144 #[inline]
1145 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1146 match self {
1147 Self::Unzoned(addr) => write!(f, "{addr}"),
1148 Self::Zoned(addr_and_zone) => write!(f, "{addr_and_zone}"),
1149 }
1150 }
1151}
1152
1153impl<A, Z> ZonedAddr<A, Z> {
1154 pub fn into_addr_zone(self) -> (A, Option<Z>) {
1156 match self {
1157 ZonedAddr::Unzoned(addr) => (addr, None),
1158 ZonedAddr::Zoned(scope_and_zone) => {
1159 let (addr, zone) = scope_and_zone.into_addr_scope_id();
1160 (addr, Some(zone))
1161 }
1162 }
1163 }
1164
1165 pub fn addr(&self) -> A
1167 where
1168 A: Copy,
1169 {
1170 match self {
1171 ZonedAddr::Unzoned(addr) => *addr,
1172 ZonedAddr::Zoned(addr_and_zone) => addr_and_zone.addr(),
1173 }
1174 }
1175
1176 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> ZonedAddr<A, Y> {
1178 match self {
1179 ZonedAddr::Unzoned(u) => ZonedAddr::Unzoned(u),
1180 ZonedAddr::Zoned(z) => ZonedAddr::Zoned(z.map_zone(f)),
1181 }
1182 }
1183
1184 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> ZonedAddr<B, Z> {
1186 match self {
1187 Self::Unzoned(u) => ZonedAddr::Unzoned(f(u)),
1188 Self::Zoned(z) => ZonedAddr::Zoned(z.map_addr(f)),
1189 }
1190 }
1191
1192 pub fn as_ref(&self) -> ZonedAddr<&A, &Z> {
1194 match self {
1195 Self::Unzoned(u) => ZonedAddr::Unzoned(u),
1196 Self::Zoned(z) => ZonedAddr::Zoned(z.as_ref()),
1197 }
1198 }
1199}
1200
1201impl<A: ScopeableAddress, Z> ZonedAddr<A, Z> {
1202 pub fn new(addr: A, zone: Option<Z>) -> Option<Self> {
1208 match zone {
1209 Some(zone) => AddrAndZone::new(addr, zone).map(ZonedAddr::Zoned),
1210 None => Some(ZonedAddr::Unzoned(addr)),
1211 }
1212 }
1213}
1214
1215impl<A: IpAddress + ScopeableAddress, Z: Clone> ZonedAddr<A, Z> {
1216 pub fn new_zoned_if_necessary(addr: A, get_zone: impl FnOnce() -> Z) -> Self {
1221 match AddrAndZone::new_not_loopback(addr, ()) {
1222 Some(addr_and_zone) => Self::Zoned(addr_and_zone.map_zone(move |()| get_zone())),
1223 None => Self::Unzoned(addr),
1224 }
1225 }
1226}
1227
1228impl<A: ScopeableAddress<Scope = ()>, Z> ZonedAddr<A, Z> {
1229 pub fn into_unzoned(self) -> A {
1234 match self {
1235 ZonedAddr::Unzoned(u) => u,
1236 ZonedAddr::Zoned(_z) => unreachable!(),
1237 }
1238 }
1239}
1240
1241impl<A, Z> From<AddrAndZone<A, Z>> for ZonedAddr<A, Z> {
1242 fn from(a: AddrAndZone<A, Z>) -> Self {
1243 Self::Zoned(a)
1244 }
1245}
1246
1247impl<A: SpecifiedAddress, Z> From<ZonedAddr<SpecifiedAddr<A>, Z>> for ZonedAddr<A, Z> {
1248 fn from(zoned_addr: ZonedAddr<SpecifiedAddr<A>, Z>) -> Self {
1249 match zoned_addr {
1250 ZonedAddr::Unzoned(a) => Self::Unzoned(a.into_addr()),
1251 ZonedAddr::Zoned(z) => Self::Zoned(z.into()),
1252 }
1253 }
1254}
1255
1256impl<A, I: Ip> GenericOverIp<I> for SpecifiedAddr<A> {
1257 type Type = SpecifiedAddr<I::Addr>;
1258}
1259
1260impl<A: IpAddress, I: Ip> GenericOverIp<I> for MulticastAddr<A> {
1261 type Type = MulticastAddr<I::Addr>;
1262}
1263
1264impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for ZonedAddr<A, Z> {
1265 type Type = ZonedAddr<A::Type, Z>;
1266}
1267
1268impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for AddrAndZone<A, Z> {
1269 type Type = AddrAndZone<A::Type, Z>;
1270}
1271
1272#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1274pub struct AddrAndPortFormatter<A, P, I: Ip> {
1275 addr: A,
1276 port: P,
1277 _marker: IpVersionMarker<I>,
1278}
1279
1280impl<A, P, I: Ip> AddrAndPortFormatter<A, P, I> {
1281 pub fn new(addr: A, port: P) -> Self {
1283 Self { addr, port, _marker: IpVersionMarker::new() }
1284 }
1285}
1286
1287impl<A: Display, P: Display, I: Ip> Display for AddrAndPortFormatter<A, P, I> {
1288 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1289 let Self { addr, port, _marker } = self;
1290 let IpInvariant(result) = I::map_ip(
1291 IpInvariant((addr, port, f)),
1292 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "{}:{}", addr, port)),
1293 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "[{}]:{}", addr, port)),
1294 );
1295 result
1296 }
1297}
1298
1299#[cfg(test)]
1300mod tests {
1301 use super::*;
1302
1303 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1304 enum Address {
1305 Unspecified,
1306 GlobalUnicast,
1307 GlobalMulticast,
1308 GlobalBroadcast,
1309 LinkLocalUnicast,
1310 LinkLocalMulticast,
1311 LinkLocalBroadcast,
1312 MappedUnicast,
1313 MappedMulticast,
1314 MappedBroadcast,
1315 }
1316
1317 impl SpecifiedAddress for Address {
1318 fn is_specified(&self) -> bool {
1319 *self != Address::Unspecified
1320 }
1321 }
1322
1323 impl UnicastAddress for Address {
1324 fn is_unicast(&self) -> bool {
1325 use Address::*;
1326 match self {
1327 GlobalUnicast | LinkLocalUnicast | MappedUnicast => true,
1328 Unspecified | GlobalMulticast | GlobalBroadcast | LinkLocalMulticast
1329 | LinkLocalBroadcast | MappedMulticast | MappedBroadcast => false,
1330 }
1331 }
1332 }
1333
1334 impl MulticastAddress for Address {
1335 fn is_multicast(&self) -> bool {
1336 use Address::*;
1337 match self {
1338 GlobalMulticast | LinkLocalMulticast | MappedMulticast => true,
1339 Unspecified | GlobalUnicast | GlobalBroadcast | LinkLocalUnicast
1340 | MappedUnicast | MappedBroadcast | LinkLocalBroadcast => false,
1341 }
1342 }
1343 }
1344
1345 impl BroadcastAddress for Address {
1346 fn is_broadcast(&self) -> bool {
1347 use Address::*;
1348 match self {
1349 GlobalBroadcast | LinkLocalBroadcast | MappedBroadcast => true,
1350 Unspecified | GlobalUnicast | GlobalMulticast | LinkLocalUnicast
1351 | MappedUnicast | MappedMulticast | LinkLocalMulticast => false,
1352 }
1353 }
1354 }
1355
1356 impl LinkLocalAddress for Address {
1357 fn is_link_local(&self) -> bool {
1358 use Address::*;
1359 match self {
1360 LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1361 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast | MappedUnicast
1362 | MappedBroadcast | MappedMulticast => false,
1363 }
1364 }
1365 }
1366
1367 impl MappedAddress for Address {
1368 fn is_non_mapped(&self) -> bool {
1369 use Address::*;
1370 match self {
1371 MappedUnicast | MappedBroadcast | MappedMulticast => false,
1372 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast
1373 | LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1374 }
1375 }
1376 }
1377
1378 #[derive(Copy, Clone, Eq, PartialEq)]
1379 enum AddressScope {
1380 LinkLocal,
1381 Global,
1382 }
1383
1384 impl Scope for AddressScope {
1385 fn can_have_zone(&self) -> bool {
1386 matches!(self, AddressScope::LinkLocal)
1387 }
1388 }
1389
1390 impl ScopeableAddress for Address {
1391 type Scope = AddressScope;
1392
1393 fn scope(&self) -> AddressScope {
1394 if self.is_link_local() {
1395 AddressScope::LinkLocal
1396 } else {
1397 AddressScope::Global
1398 }
1399 }
1400 }
1401
1402 #[test]
1403 fn specified_addr() {
1404 assert_eq!(
1405 SpecifiedAddr::new(Address::GlobalUnicast),
1406 Some(SpecifiedAddr(Address::GlobalUnicast))
1407 );
1408 assert_eq!(SpecifiedAddr::new(Address::Unspecified), None);
1409 }
1410
1411 #[test]
1412 fn unicast_addr() {
1413 assert_eq!(
1414 UnicastAddr::new(Address::GlobalUnicast),
1415 Some(UnicastAddr(Address::GlobalUnicast))
1416 );
1417 assert_eq!(UnicastAddr::new(Address::GlobalMulticast), None);
1418 assert_eq!(
1419 unsafe { UnicastAddr::new_unchecked(Address::GlobalUnicast) },
1420 UnicastAddr(Address::GlobalUnicast)
1421 );
1422 }
1423
1424 #[test]
1425 fn multicast_addr() {
1426 assert_eq!(
1427 MulticastAddr::new(Address::GlobalMulticast),
1428 Some(MulticastAddr(Address::GlobalMulticast))
1429 );
1430 assert_eq!(MulticastAddr::new(Address::GlobalUnicast), None);
1431 assert_eq!(
1432 unsafe { MulticastAddr::new_unchecked(Address::GlobalMulticast) },
1433 MulticastAddr(Address::GlobalMulticast)
1434 );
1435 }
1436
1437 #[test]
1438 fn broadcast_addr() {
1439 assert_eq!(
1440 BroadcastAddr::new(Address::GlobalBroadcast),
1441 Some(BroadcastAddr(Address::GlobalBroadcast))
1442 );
1443 assert_eq!(BroadcastAddr::new(Address::GlobalUnicast), None);
1444 assert_eq!(
1445 unsafe { BroadcastAddr::new_unchecked(Address::GlobalBroadcast) },
1446 BroadcastAddr(Address::GlobalBroadcast)
1447 );
1448 }
1449
1450 #[test]
1451 fn link_local_addr() {
1452 assert_eq!(
1453 LinkLocalAddr::new(Address::LinkLocalUnicast),
1454 Some(LinkLocalAddr(Address::LinkLocalUnicast))
1455 );
1456 assert_eq!(LinkLocalAddr::new(Address::GlobalMulticast), None);
1457 assert_eq!(
1458 unsafe { LinkLocalAddr::new_unchecked(Address::LinkLocalUnicast) },
1459 LinkLocalAddr(Address::LinkLocalUnicast)
1460 );
1461 }
1462
1463 #[test]
1464 fn non_mapped_addr() {
1465 assert_eq!(
1466 NonMappedAddr::new(Address::LinkLocalUnicast),
1467 Some(NonMappedAddr(Address::LinkLocalUnicast))
1468 );
1469 assert_eq!(NonMappedAddr::new(Address::MappedUnicast), None);
1470 assert_eq!(
1471 NonMappedAddr::new(Address::LinkLocalMulticast),
1472 Some(NonMappedAddr(Address::LinkLocalMulticast))
1473 );
1474 assert_eq!(NonMappedAddr::new(Address::MappedMulticast), None);
1475 assert_eq!(
1476 NonMappedAddr::new(Address::LinkLocalBroadcast),
1477 Some(NonMappedAddr(Address::LinkLocalBroadcast))
1478 );
1479 assert_eq!(NonMappedAddr::new(Address::MappedBroadcast), None);
1480 }
1481
1482 macro_rules! test_nested {
1483 ($outer:ident, $inner:ident, $($input:ident => $output:expr,)*) => {
1484 $(
1485 assert_eq!($inner::new(Address::$input).and_then($outer::new), $output);
1486 )*
1487 };
1488 }
1489
1490 #[test]
1491 fn nested_link_local() {
1492 test_nested!(
1498 UnicastAddr,
1499 LinkLocalAddr,
1500 Unspecified => None,
1501 GlobalUnicast => None,
1502 GlobalMulticast => None,
1503 LinkLocalUnicast => Some(UnicastAddr(LinkLocalAddr(Address::LinkLocalUnicast))),
1504 LinkLocalMulticast => None,
1505 LinkLocalBroadcast => None,
1506 );
1507
1508 test_nested!(
1510 MulticastAddr,
1511 LinkLocalAddr,
1512 Unspecified => None,
1513 GlobalUnicast => None,
1514 GlobalMulticast => None,
1515 LinkLocalUnicast => None,
1516 LinkLocalMulticast => Some(MulticastAddr(LinkLocalAddr(Address::LinkLocalMulticast))),
1517 LinkLocalBroadcast => None,
1518 );
1519
1520 test_nested!(
1522 BroadcastAddr,
1523 LinkLocalAddr,
1524 Unspecified => None,
1525 GlobalUnicast => None,
1526 GlobalMulticast => None,
1527 LinkLocalUnicast => None,
1528 LinkLocalMulticast => None,
1529 LinkLocalBroadcast => Some(BroadcastAddr(LinkLocalAddr(Address::LinkLocalBroadcast))),
1530 );
1531
1532 test_nested!(
1534 LinkLocalAddr,
1535 UnicastAddr,
1536 Unspecified => None,
1537 GlobalUnicast => None,
1538 GlobalMulticast => None,
1539 LinkLocalUnicast => Some(LinkLocalAddr(UnicastAddr(Address::LinkLocalUnicast))),
1540 LinkLocalMulticast => None,
1541 LinkLocalBroadcast => None,
1542 );
1543 test_nested!(
1544 LinkLocalAddr,
1545 MulticastAddr,
1546 Unspecified => None,
1547 GlobalUnicast => None,
1548 GlobalMulticast => None,
1549 LinkLocalUnicast => None,
1550 LinkLocalMulticast => Some(LinkLocalAddr(MulticastAddr(Address::LinkLocalMulticast))),
1551 LinkLocalBroadcast => None,
1552 );
1553 test_nested!(
1554 LinkLocalAddr,
1555 BroadcastAddr,
1556 Unspecified => None,
1557 GlobalUnicast => None,
1558 GlobalMulticast => None,
1559 LinkLocalUnicast => None,
1560 LinkLocalMulticast => None,
1561 LinkLocalBroadcast => Some(LinkLocalAddr(BroadcastAddr(Address::LinkLocalBroadcast))),
1562 );
1563 }
1564
1565 #[test]
1566 fn nested_non_mapped() {
1567 test_nested!(
1574 UnicastAddr,
1575 NonMappedAddr,
1576 Unspecified => None,
1577 LinkLocalUnicast => Some(UnicastAddr(NonMappedAddr(Address::LinkLocalUnicast))),
1578 LinkLocalMulticast => None,
1579 LinkLocalBroadcast => None,
1580 MappedUnicast => None,
1581 MappedMulticast => None,
1582 MappedBroadcast => None,
1583 );
1584
1585 test_nested!(
1587 MulticastAddr,
1588 NonMappedAddr,
1589 Unspecified => None,
1590 LinkLocalUnicast => None,
1591 LinkLocalMulticast => Some(MulticastAddr(NonMappedAddr(Address::LinkLocalMulticast))),
1592 LinkLocalBroadcast => None,
1593 MappedUnicast => None,
1594 MappedMulticast => None,
1595 MappedBroadcast => None,
1596 );
1597
1598 test_nested!(
1600 BroadcastAddr,
1601 NonMappedAddr,
1602 Unspecified => None,
1603 LinkLocalUnicast => None,
1604 LinkLocalMulticast => None,
1605 LinkLocalBroadcast => Some(BroadcastAddr(NonMappedAddr(Address::LinkLocalBroadcast))),
1606 MappedUnicast => None,
1607 MappedMulticast => None,
1608 MappedBroadcast => None,
1609 );
1610
1611 test_nested!(
1613 NonMappedAddr,
1614 UnicastAddr,
1615 Unspecified => None,
1616 LinkLocalUnicast => Some(NonMappedAddr(UnicastAddr(Address::LinkLocalUnicast))),
1617 LinkLocalMulticast => None,
1618 LinkLocalBroadcast => None,
1619 MappedUnicast => None,
1620 MappedMulticast => None,
1621 MappedBroadcast => None,
1622 );
1623 test_nested!(
1624 NonMappedAddr,
1625 MulticastAddr,
1626 Unspecified => None,
1627 LinkLocalUnicast => None,
1628 LinkLocalMulticast => Some(NonMappedAddr(MulticastAddr(Address::LinkLocalMulticast))),
1629 LinkLocalBroadcast => None,
1630 MappedUnicast => None,
1631 MappedMulticast => None,
1632 MappedBroadcast => None,
1633 );
1634 test_nested!(
1635 NonMappedAddr,
1636 BroadcastAddr,
1637 Unspecified => None,
1638 LinkLocalUnicast => None,
1639 LinkLocalMulticast => None,
1640 LinkLocalBroadcast => Some(NonMappedAddr(BroadcastAddr(Address::LinkLocalBroadcast))),
1641 MappedUnicast => None,
1642 MappedMulticast => None,
1643 MappedBroadcast => None,
1644 );
1645 }
1646
1647 #[test]
1648 fn addr_and_zone() {
1649 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, ());
1650 assert_eq!(addr_and_zone, Some(AddrAndZone(Address::LinkLocalUnicast, ())));
1651 assert_eq!(addr_and_zone.unwrap().into_addr_scope_id(), (Address::LinkLocalUnicast, ()));
1652 assert_eq!(AddrAndZone::new(Address::GlobalUnicast, ()), None);
1653 assert_eq!(
1654 unsafe { AddrAndZone::new_unchecked(Address::LinkLocalUnicast, ()) },
1655 AddrAndZone(Address::LinkLocalUnicast, ())
1656 );
1657 }
1658
1659 #[test]
1660 fn addr_and_zone_map_zone() {
1661 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 65).unwrap();
1662 assert_eq!(
1663 addr_and_zone.map_zone(|x| char::from_u32(x).unwrap()),
1664 AddrAndZone::new(Address::LinkLocalUnicast, 'A').unwrap()
1665 );
1666 }
1667
1668 #[test]
1669 fn addr_and_zone_try_map_zone() {
1670 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 32).unwrap();
1671 assert_eq!(
1672 addr_and_zone.try_map_zone(|x| Ok::<_, ()>(x + 1)),
1673 Ok(AddrAndZone::new(Address::LinkLocalUnicast, 33).unwrap())
1674 );
1675
1676 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 32).unwrap();
1677 assert_eq!(addr_and_zone.try_map_zone(|x| Err::<i32, _>(x - 1)), Err(31),);
1678 }
1679
1680 #[test]
1681 fn scoped_address() {
1682 type ZonedAddr = crate::ZonedAddr<Address, ()>;
1685 assert_eq!(
1686 ZonedAddr::new(Address::GlobalUnicast, None),
1687 Some(ZonedAddr::Unzoned(Address::GlobalUnicast))
1688 );
1689 assert_eq!(
1690 ZonedAddr::new(Address::Unspecified, None).unwrap().into_addr_zone(),
1691 (Address::Unspecified, None)
1692 );
1693 assert_eq!(
1694 ZonedAddr::new(Address::LinkLocalUnicast, None),
1695 Some(ZonedAddr::Unzoned(Address::LinkLocalUnicast))
1696 );
1697 assert_eq!(ZonedAddr::new(Address::GlobalUnicast, Some(())), None);
1698 assert_eq!(ZonedAddr::new(Address::Unspecified, Some(())), None);
1699 assert_eq!(
1700 ZonedAddr::new(Address::LinkLocalUnicast, Some(())),
1701 Some(ZonedAddr::Zoned(AddrAndZone(Address::LinkLocalUnicast, ())))
1702 );
1703
1704 assert_eq!(
1705 ZonedAddr::new(Address::GlobalUnicast, None).unwrap().into_addr_zone(),
1706 (Address::GlobalUnicast, None)
1707 );
1708 assert_eq!(
1709 ZonedAddr::new(Address::LinkLocalUnicast, Some(())).unwrap().into_addr_zone(),
1710 (Address::LinkLocalUnicast, Some(()))
1711 );
1712 }
1713
1714 #[test]
1715 fn transpose_with_fully_qualified_types() {
1716 let addr: SpecifiedAddr<NonMappedAddr<Address>> =
1717 <NonMappedAddr<SpecifiedAddr<Address>> as Witness<SpecifiedAddr<Address>>>::transpose::<
1718 Address,
1719 >(
1720 NonMappedAddr::new(
1721 SpecifiedAddr::new(Address::LinkLocalUnicast)
1722 .expect("should be specified addr"),
1723 )
1724 .expect("should be non-mapped addr"),
1725 );
1726 assert_eq!(
1727 addr,
1728 SpecifiedAddr::new(
1729 NonMappedAddr::new(Address::LinkLocalUnicast).expect("should be non-mapped addr")
1730 )
1731 .expect("should be specified addr")
1732 )
1733 }
1734
1735 #[test]
1736 fn transpose_with_inferred_types() {
1737 assert_eq!(
1738 NonMappedAddr::new(
1739 SpecifiedAddr::new(Address::LinkLocalUnicast).expect("should be specified addr")
1740 )
1741 .expect("should be non-mapped addr")
1742 .transpose(),
1743 SpecifiedAddr::new(
1744 NonMappedAddr::new(Address::LinkLocalUnicast).expect("should be non-mapped addr")
1745 )
1746 .expect("should be specified addr")
1747 )
1748 }
1749}