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 = concat!("Constructs a new `", stringify!($type), "` without
535checking to see if `addr` is actually ", $adj, ".")]
536 #[doc = concat!("It is up to the caller to make sure that `addr`
540is ", $adj, " to avoid breaking the guarantees of `", stringify!($type), "`.
541See [`", stringify!($type), "`] for more details.")]
542 pub const unsafe fn new_unchecked(addr: A) -> $type<A> {
543 $type(addr)
544 }
545 }
546
547 impl<A> sealed::Sealed for $type<A> {}
548 impl<A: $trait> Witness<A> for $type<A> {
549 fn new(addr: A) -> Option<$type<A>> {
550 $type::new(addr)
551 }
552
553 unsafe fn new_unchecked(addr: A) -> $type<A> {
554 $type(addr)
555 }
556
557 #[inline]
558 fn into_addr(self) -> A {
559 self.0
560 }
561 }
562
563 impl<A: $trait> TransposableWitness<A> for $type<A> {
564 type Map<T> = $type<T>;
565 }
566
567 impl<A: $trait> AsRef<$type<A>> for $type<A> {
568 fn as_ref(&self) -> &$type<A> {
569 self
570 }
571 }
572
573 impl<A: $trait> AsRef<A> for $type<A> {
574 fn as_ref(&self) -> &A {
575 &self.0
576 }
577 }
578
579 impl<A: $trait> Deref for $type<A> {
580 type Target = A;
581
582 #[inline]
583 fn deref(&self) -> &A {
584 &self.0
585 }
586 }
587
588 impl<A: Display> Display for $type<A> {
589 #[inline]
590 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
591 self.0.fmt(f)
592 }
593 }
594
595 impl<A: Debug> Debug for $type<A> {
599 #[inline]
600 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
601 self.0.fmt(f)
602 }
603 }
604 };
605}
606
607macro_rules! impl_into_specified {
617 ($type:ident, $trait:ident, $method:ident) => {
618 impl<A: $trait + SpecifiedAddress> $type<A> {
619 doc_comment! {
620 concat!("Converts this `", stringify!($type), "` into a
621[`SpecifiedAddr`].
622
623[`", stringify!($trait), "::", stringify!($method), "`] implies
624[`SpecifiedAddress::is_specified`], so all `", stringify!($type), "`s are
625guaranteed to be specified, so this conversion is infallible."),
626 #[inline]
627 pub fn into_specified(self) -> SpecifiedAddr<A> {
628 SpecifiedAddr(self.0)
629 }
630 }
631 }
632
633 impl<A: $trait + SpecifiedAddress> From<$type<A>> for SpecifiedAddr<A> {
634 fn from(addr: $type<A>) -> SpecifiedAddr<A> {
635 addr.into_specified()
636 }
637 }
638 };
639}
640
641macro_rules! impl_nested_witness {
653 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident) => {
654 impl<A: $trait1 + $trait2> Witness<A> for $type1<$type2<A>> {
655 #[inline]
656 fn new(addr: A) -> Option<$type1<$type2<A>>> {
657 $type2::new(addr).and_then(Witness::<$type2<A>>::new)
658 }
659
660 unsafe fn new_unchecked(addr: A) -> $type1<$type2<A>> {
661 $type1($type2(addr))
662 }
663
664 #[inline]
665 fn into_addr(self) -> A {
666 self.0.into_addr()
667 }
668 }
669
670 impl<A: $trait1 + $trait2> AsRef<A> for $type1<$type2<A>> {
671 fn as_ref(&self) -> &A {
672 &self.0.0
673 }
674 }
675 };
676 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident, $trait3:ident, $type3:ident) => {
677 impl<A: $trait1 + $trait2 + $trait3> Witness<A> for $type1<$type2<$type3<A>>> {
678 #[inline]
679 fn new(addr: A) -> Option<$type1<$type2<$type3<A>>>> {
680 $type3::new(addr).and_then(Witness::<$type3<A>>::new)
681 }
682
683 unsafe fn new_unchecked(addr: A) -> $type1<$type2<$type3<A>>> {
684 $type1($type2($type3(addr)))
685 }
686
687 #[inline]
688 fn into_addr(self) -> A {
689 self.0.into_addr()
690 }
691 }
692
693 impl<A: $trait1 + $trait2 + $trait3> AsRef<A> for $type1<$type2<$type3<A>>> {
694 fn as_ref(&self) -> &A {
695 &self.0.0
696 }
697 }
698 };
699}
700
701macro_rules! impl_into_specified_for_nested_witness {
713 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident) => {
714 impl<A: $trait1 + $trait2 + SpecifiedAddress> From<$type1<$type2<A>>> for SpecifiedAddr<A> {
715 fn from(addr: $type1<$type2<A>>) -> SpecifiedAddr<A> {
716 SpecifiedAddr(addr.into_addr())
717 }
718 }
719 };
720 ($trait1:ident, $type1:ident, $trait2:ident, $type2:ident, $trait3:ident, $type3:ident) => {
721 impl<A: $trait1 + $trait2 + $trait3 + SpecifiedAddress> From<$type1<$type2<$type3<A>>>>
722 for SpecifiedAddr<A>
723 {
724 fn from(addr: $type1<$type2<$type3<A>>>) -> SpecifiedAddr<A> {
725 SpecifiedAddr(addr.into_addr())
726 }
727 }
728 };
729}
730
731macro_rules! impl_try_from_witness {
733 (@inner [$from_ty:ident: $from_trait:ident], [$into_ty:ident: $into_trait:ident]) => {
734 impl<A: $from_trait + $into_trait> TryFrom<$from_ty<A>> for $into_ty<A> {
735 type Error = ();
736 fn try_from(addr: $from_ty<A>) -> Result<$into_ty<A>, ()> {
737 Witness::<A>::from_witness(addr).ok_or(())
738 }
739 }
740 };
741 ([$from_ty:ident: $from_trait:ident], $([$into_ty:ident: $into_trait:ident]),*) => {
742 $(
743 impl_try_from_witness!(@inner [$from_ty: $from_trait], [$into_ty: $into_trait]);
744 )*
745 }
746}
747
748impl_witness!(SpecifiedAddr, "specified", SpecifiedAddress, is_specified);
750impl_try_from_witness!(
751 [SpecifiedAddr: SpecifiedAddress],
752 [UnicastAddr: UnicastAddress],
753 [MulticastAddr: MulticastAddress],
754 [BroadcastAddr: BroadcastAddress],
755 [LinkLocalAddr: LinkLocalAddress],
756 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
757 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
758 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
759 [NonMappedAddr: MappedAddress]
760);
761
762impl_witness!(UnicastAddr, "unicast", UnicastAddress, is_unicast);
764impl_into_specified!(UnicastAddr, UnicastAddress, is_unicast);
765impl_nested_witness!(UnicastAddress, UnicastAddr, LinkLocalAddress, LinkLocalAddr);
766impl_nested_witness!(UnicastAddress, UnicastAddr, MappedAddress, NonMappedAddr);
767impl_into_specified_for_nested_witness!(
768 UnicastAddress,
769 UnicastAddr,
770 LinkLocalAddress,
771 LinkLocalAddr
772);
773impl_into_specified_for_nested_witness!(UnicastAddress, UnicastAddr, MappedAddress, NonMappedAddr);
774impl_try_from_witness!(
775 [UnicastAddr: UnicastAddress],
776 [MulticastAddr: MulticastAddress],
777 [BroadcastAddr: BroadcastAddress],
778 [LinkLocalAddr: LinkLocalAddress],
779 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
780 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
781 [NonMappedAddr: MappedAddress]
782);
783
784impl_witness!(MulticastAddr, "multicast", MulticastAddress, is_multicast);
786impl_into_specified!(MulticastAddr, MulticastAddress, is_multicast);
787impl_nested_witness!(MulticastAddress, MulticastAddr, LinkLocalAddress, LinkLocalAddr);
788impl_nested_witness!(MulticastAddress, MulticastAddr, MappedAddress, NonMappedAddr);
789impl_into_specified_for_nested_witness!(
790 MulticastAddress,
791 MulticastAddr,
792 LinkLocalAddress,
793 LinkLocalAddr
794);
795impl_into_specified_for_nested_witness!(
796 MulticastAddress,
797 MulticastAddr,
798 MappedAddress,
799 NonMappedAddr
800);
801impl_try_from_witness!(
802 [MulticastAddr: MulticastAddress],
803 [UnicastAddr: UnicastAddress],
804 [BroadcastAddr: BroadcastAddress],
805 [LinkLocalAddr: LinkLocalAddress],
806 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
807 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
808 [NonMappedAddr: MappedAddress]
809);
810
811impl<A: MulticastAddress + MappedAddress> MulticastAddr<A> {
812 pub fn non_mapped(self) -> NonMappedAddr<MulticastAddr<A>> {
814 unsafe { NonMappedAddr::new_unchecked(self) }
819 }
820}
821
822impl_witness!(NonMulticastAddr, "non-multicast", MulticastAddress, is_non_multicast);
829impl_nested_witness!(MulticastAddress, NonMulticastAddr, SpecifiedAddress, SpecifiedAddr);
830impl_nested_witness!(MulticastAddress, NonMulticastAddr, UnicastAddress, UnicastAddr);
831impl_nested_witness!(MulticastAddress, NonMulticastAddr, BroadcastAddress, BroadcastAddr);
832impl_nested_witness!(MulticastAddress, NonMulticastAddr, MappedAddress, NonMappedAddr);
833
834impl<A: MulticastAddress + UnicastAddress> From<UnicastAddr<A>> for NonMulticastAddr<A> {
835 #[inline]
836 fn from(addr: UnicastAddr<A>) -> Self {
837 unsafe { NonMulticastAddr::new_unchecked(addr.into_addr()) }
839 }
840}
841impl_nested_witness!(
844 MulticastAddress,
845 NonMulticastAddr,
846 MappedAddress,
847 NonMappedAddr,
848 SpecifiedAddress,
849 SpecifiedAddr
850);
851impl_into_specified_for_nested_witness!(
852 MulticastAddress,
853 NonMulticastAddr,
854 MappedAddress,
855 NonMappedAddr,
856 SpecifiedAddress,
857 SpecifiedAddr
858);
859
860impl_witness!(BroadcastAddr, "broadcast", BroadcastAddress, is_broadcast);
862impl_into_specified!(BroadcastAddr, BroadcastAddress, is_broadcast);
863impl_nested_witness!(BroadcastAddress, BroadcastAddr, LinkLocalAddress, LinkLocalAddr);
864impl_nested_witness!(BroadcastAddress, BroadcastAddr, MappedAddress, NonMappedAddr);
865impl_into_specified_for_nested_witness!(
866 BroadcastAddress,
867 BroadcastAddr,
868 LinkLocalAddress,
869 LinkLocalAddr
870);
871impl_into_specified_for_nested_witness!(
872 BroadcastAddress,
873 BroadcastAddr,
874 MappedAddress,
875 NonMappedAddr
876);
877impl_try_from_witness!(
878 [BroadcastAddr: BroadcastAddress],
879 [UnicastAddr: UnicastAddress],
880 [MulticastAddr: MulticastAddress],
881 [LinkLocalAddr: LinkLocalAddress],
882 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
883 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
884 [NonMappedAddr: MappedAddress]
885);
886
887impl_witness!(LinkLocalAddr, "link-local", LinkLocalAddress, is_link_local);
889impl_into_specified!(LinkLocalAddr, LinkLocalAddress, is_link_local);
890impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, UnicastAddress, UnicastAddr);
891impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, MulticastAddress, MulticastAddr);
892impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, BroadcastAddress, BroadcastAddr);
893impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, MappedAddress, NonMappedAddr);
894impl_into_specified_for_nested_witness!(
895 LinkLocalAddress,
896 LinkLocalAddr,
897 UnicastAddress,
898 UnicastAddr
899);
900impl_into_specified_for_nested_witness!(
901 LinkLocalAddress,
902 LinkLocalAddr,
903 MulticastAddress,
904 MulticastAddr
905);
906impl_into_specified_for_nested_witness!(
907 LinkLocalAddress,
908 LinkLocalAddr,
909 BroadcastAddress,
910 BroadcastAddr
911);
912impl_into_specified_for_nested_witness!(
913 LinkLocalAddress,
914 LinkLocalAddr,
915 MappedAddress,
916 NonMappedAddr
917);
918impl_try_from_witness!(
919 [LinkLocalAddr: LinkLocalAddress],
920 [UnicastAddr: UnicastAddress],
921 [MulticastAddr: MulticastAddress],
922 [BroadcastAddr: BroadcastAddress],
923 [NonMappedAddr: MappedAddress]
924);
925
926impl_witness!(NonMappedAddr, "non_mapped", MappedAddress, is_non_mapped);
928impl_nested_witness!(MappedAddress, NonMappedAddr, SpecifiedAddress, SpecifiedAddr);
929impl_nested_witness!(MappedAddress, NonMappedAddr, UnicastAddress, UnicastAddr);
930impl_nested_witness!(MappedAddress, NonMappedAddr, MulticastAddress, MulticastAddr);
931impl_nested_witness!(MappedAddress, NonMappedAddr, BroadcastAddress, BroadcastAddr);
932impl_nested_witness!(MappedAddress, NonMappedAddr, LinkLocalAddress, LinkLocalAddr);
933impl_into_specified_for_nested_witness!(
934 MappedAddress,
935 NonMappedAddr,
936 SpecifiedAddress,
937 SpecifiedAddr
938);
939impl_into_specified_for_nested_witness!(MappedAddress, NonMappedAddr, UnicastAddress, UnicastAddr);
940impl_into_specified_for_nested_witness!(
941 MappedAddress,
942 NonMappedAddr,
943 MulticastAddress,
944 MulticastAddr
945);
946impl_into_specified_for_nested_witness!(
947 MappedAddress,
948 NonMappedAddr,
949 BroadcastAddress,
950 BroadcastAddr
951);
952impl_into_specified_for_nested_witness!(
953 MappedAddress,
954 NonMappedAddr,
955 LinkLocalAddress,
956 LinkLocalAddr
957);
958impl_try_from_witness!(
959 [NonMappedAddr: MappedAddress],
960 [SpecifiedAddr: SpecifiedAddress],
961 [UnicastAddr: UnicastAddress],
962 [MulticastAddr: MulticastAddress],
963 [BroadcastAddr: BroadcastAddress],
964 [LinkLocalAddr: LinkLocalAddress],
965 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
966 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
967 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
968);
969
970pub trait LinkLocalUnicastAddress: LinkLocalAddress + UnicastAddress {}
983impl<A: LinkLocalAddress + UnicastAddress> LinkLocalUnicastAddress for A {}
984
985pub trait LinkLocalMulticastAddress: LinkLocalAddress + MulticastAddress {}
990impl<A: LinkLocalAddress + MulticastAddress> LinkLocalMulticastAddress for A {}
991
992pub trait LinkLocalBroadcastAddress: LinkLocalAddress + BroadcastAddress {}
997impl<A: LinkLocalAddress + BroadcastAddress> LinkLocalBroadcastAddress for A {}
998
999pub type LinkLocalUnicastAddr<A> = LinkLocalAddr<UnicastAddr<A>>;
1001
1002pub type LinkLocalMulticastAddr<A> = LinkLocalAddr<MulticastAddr<A>>;
1004
1005pub type LinkLocalBroadcastAddr<A> = LinkLocalAddr<BroadcastAddr<A>>;
1007
1008impl_try_from_witness!(
1009 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1010 [UnicastAddr: UnicastAddress],
1011 [MulticastAddr: MulticastAddress],
1012 [LinkLocalAddr: LinkLocalAddress],
1013 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
1014 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
1015);
1016impl_try_from_witness!(
1017 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
1018 [UnicastAddr: UnicastAddress],
1019 [MulticastAddr: MulticastAddress],
1020 [LinkLocalAddr: LinkLocalAddress],
1021 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1022 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
1023);
1024impl_try_from_witness!(
1025 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
1026 [UnicastAddr: UnicastAddress],
1027 [MulticastAddr: MulticastAddress],
1028 [LinkLocalAddr: LinkLocalAddress],
1029 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1030 [LinkLocalMulticastAddr: LinkLocalMulticastAddress]
1031);
1032
1033#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1043pub struct AddrAndZone<A, Z>(A, Z);
1044
1045impl<A: ScopeableAddress, Z> AddrAndZone<A, Z> {
1046 pub fn new(addr: A, zone: Z) -> Option<Self> {
1049 if addr.scope().can_have_zone() { Some(Self(addr, zone)) } else { None }
1050 }
1051}
1052
1053impl<A: ScopeableAddress + IpAddress, Z> AddrAndZone<A, Z> {
1054 pub fn new_not_loopback(addr: A, zone: Z) -> Option<Self> {
1058 if addr.scope().can_have_zone() && !addr.is_loopback() {
1059 Some(Self(addr, zone))
1060 } else {
1061 None
1062 }
1063 }
1064}
1065
1066impl<A, Z> AddrAndZone<A, Z> {
1067 #[inline]
1075 pub const unsafe fn new_unchecked(addr: A, zone: Z) -> Self {
1076 Self(addr, zone)
1077 }
1078
1079 pub fn into_addr_scope_id(self) -> (A, Z) {
1081 let AddrAndZone(addr, zone) = self;
1082 (addr, zone)
1083 }
1084
1085 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> AddrAndZone<A, Y> {
1087 let AddrAndZone(addr, zone) = self;
1088 AddrAndZone(addr, f(zone))
1089 }
1090
1091 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> AddrAndZone<B, Z> {
1093 let Self(addr, zone) = self;
1094 AddrAndZone(f(addr), zone)
1095 }
1096
1097 pub fn try_map_zone<Y, E>(
1099 self,
1100 f: impl FnOnce(Z) -> Result<Y, E>,
1101 ) -> Result<AddrAndZone<A, Y>, E> {
1102 let AddrAndZone(addr, zone) = self;
1103 f(zone).map(|zone| AddrAndZone(addr, zone))
1104 }
1105
1106 pub fn addr(&self) -> A
1108 where
1109 A: Copy,
1110 {
1111 let AddrAndZone(addr, _zone) = self;
1112 *addr
1113 }
1114
1115 pub fn as_ref(&self) -> AddrAndZone<&A, &Z> {
1117 let Self(addr, zone) = self;
1118 AddrAndZone(addr, zone)
1119 }
1120}
1121
1122impl<A: Display, Z: Display> Display for AddrAndZone<A, Z> {
1123 #[inline]
1124 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1125 write!(f, "{}%{}", self.0, self.1)
1126 }
1127}
1128
1129impl<A, Z> sealed::Sealed for AddrAndZone<A, Z> {}
1130
1131impl<A: SpecifiedAddress, Z> From<AddrAndZone<SpecifiedAddr<A>, Z>> for AddrAndZone<A, Z> {
1132 fn from(AddrAndZone(addr, zone): AddrAndZone<SpecifiedAddr<A>, Z>) -> Self {
1133 Self(addr.into_addr(), zone)
1134 }
1135}
1136
1137#[allow(missing_docs)]
1139#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1140pub enum ZonedAddr<A, Z> {
1141 Unzoned(A),
1142 Zoned(AddrAndZone<A, Z>),
1143}
1144
1145impl<A: Display, Z: Display> Display for ZonedAddr<A, Z> {
1146 #[inline]
1147 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1148 match self {
1149 Self::Unzoned(addr) => write!(f, "{addr}"),
1150 Self::Zoned(addr_and_zone) => write!(f, "{addr_and_zone}"),
1151 }
1152 }
1153}
1154
1155impl<A, Z> ZonedAddr<A, Z> {
1156 pub fn into_addr_zone(self) -> (A, Option<Z>) {
1158 match self {
1159 ZonedAddr::Unzoned(addr) => (addr, None),
1160 ZonedAddr::Zoned(scope_and_zone) => {
1161 let (addr, zone) = scope_and_zone.into_addr_scope_id();
1162 (addr, Some(zone))
1163 }
1164 }
1165 }
1166
1167 pub fn addr(&self) -> A
1169 where
1170 A: Copy,
1171 {
1172 match self {
1173 ZonedAddr::Unzoned(addr) => *addr,
1174 ZonedAddr::Zoned(addr_and_zone) => addr_and_zone.addr(),
1175 }
1176 }
1177
1178 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> ZonedAddr<A, Y> {
1180 match self {
1181 ZonedAddr::Unzoned(u) => ZonedAddr::Unzoned(u),
1182 ZonedAddr::Zoned(z) => ZonedAddr::Zoned(z.map_zone(f)),
1183 }
1184 }
1185
1186 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> ZonedAddr<B, Z> {
1188 match self {
1189 Self::Unzoned(u) => ZonedAddr::Unzoned(f(u)),
1190 Self::Zoned(z) => ZonedAddr::Zoned(z.map_addr(f)),
1191 }
1192 }
1193
1194 pub fn as_ref(&self) -> ZonedAddr<&A, &Z> {
1196 match self {
1197 Self::Unzoned(u) => ZonedAddr::Unzoned(u),
1198 Self::Zoned(z) => ZonedAddr::Zoned(z.as_ref()),
1199 }
1200 }
1201}
1202
1203impl<A: ScopeableAddress, Z> ZonedAddr<A, Z> {
1204 pub fn new(addr: A, zone: Option<Z>) -> Option<Self> {
1210 match zone {
1211 Some(zone) => AddrAndZone::new(addr, zone).map(ZonedAddr::Zoned),
1212 None => Some(ZonedAddr::Unzoned(addr)),
1213 }
1214 }
1215}
1216
1217impl<A: IpAddress + ScopeableAddress, Z: Clone> ZonedAddr<A, Z> {
1218 pub fn new_zoned_if_necessary(addr: A, get_zone: impl FnOnce() -> Z) -> Self {
1223 match AddrAndZone::new_not_loopback(addr, ()) {
1224 Some(addr_and_zone) => Self::Zoned(addr_and_zone.map_zone(move |()| get_zone())),
1225 None => Self::Unzoned(addr),
1226 }
1227 }
1228}
1229
1230impl<A: ScopeableAddress<Scope = ()>, Z> ZonedAddr<A, Z> {
1231 pub fn into_unzoned(self) -> A {
1236 match self {
1237 ZonedAddr::Unzoned(u) => u,
1238 ZonedAddr::Zoned(_z) => unreachable!(),
1239 }
1240 }
1241}
1242
1243impl<A, Z> From<AddrAndZone<A, Z>> for ZonedAddr<A, Z> {
1244 fn from(a: AddrAndZone<A, Z>) -> Self {
1245 Self::Zoned(a)
1246 }
1247}
1248
1249impl<A: SpecifiedAddress, Z> From<ZonedAddr<SpecifiedAddr<A>, Z>> for ZonedAddr<A, Z> {
1250 fn from(zoned_addr: ZonedAddr<SpecifiedAddr<A>, Z>) -> Self {
1251 match zoned_addr {
1252 ZonedAddr::Unzoned(a) => Self::Unzoned(a.into_addr()),
1253 ZonedAddr::Zoned(z) => Self::Zoned(z.into()),
1254 }
1255 }
1256}
1257
1258impl<A, I: Ip> GenericOverIp<I> for SpecifiedAddr<A> {
1259 type Type = SpecifiedAddr<I::Addr>;
1260}
1261
1262impl<A: IpAddress, I: Ip> GenericOverIp<I> for MulticastAddr<A> {
1263 type Type = MulticastAddr<I::Addr>;
1264}
1265
1266impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for ZonedAddr<A, Z> {
1267 type Type = ZonedAddr<A::Type, Z>;
1268}
1269
1270impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for AddrAndZone<A, Z> {
1271 type Type = AddrAndZone<A::Type, Z>;
1272}
1273
1274#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1276pub struct AddrAndPortFormatter<A, P, I: Ip> {
1277 addr: A,
1278 port: P,
1279 _marker: IpVersionMarker<I>,
1280}
1281
1282impl<A, P, I: Ip> AddrAndPortFormatter<A, P, I> {
1283 pub fn new(addr: A, port: P) -> Self {
1285 Self { addr, port, _marker: IpVersionMarker::new() }
1286 }
1287}
1288
1289impl<A: Display, P: Display, I: Ip> Display for AddrAndPortFormatter<A, P, I> {
1290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1291 let Self { addr, port, _marker } = self;
1292 let IpInvariant(result) = I::map_ip(
1293 IpInvariant((addr, port, f)),
1294 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "{}:{}", addr, port)),
1295 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "[{}]:{}", addr, port)),
1296 );
1297 result
1298 }
1299}
1300
1301#[cfg(test)]
1302mod tests {
1303 use super::*;
1304
1305 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1306 enum Address {
1307 Unspecified,
1308 GlobalUnicast,
1309 GlobalMulticast,
1310 GlobalBroadcast,
1311 LinkLocalUnicast,
1312 LinkLocalMulticast,
1313 LinkLocalBroadcast,
1314 MappedUnicast,
1315 MappedMulticast,
1316 MappedBroadcast,
1317 }
1318
1319 impl SpecifiedAddress for Address {
1320 fn is_specified(&self) -> bool {
1321 *self != Address::Unspecified
1322 }
1323 }
1324
1325 impl UnicastAddress for Address {
1326 fn is_unicast(&self) -> bool {
1327 use Address::*;
1328 match self {
1329 GlobalUnicast | LinkLocalUnicast | MappedUnicast => true,
1330 Unspecified | GlobalMulticast | GlobalBroadcast | LinkLocalMulticast
1331 | LinkLocalBroadcast | MappedMulticast | MappedBroadcast => false,
1332 }
1333 }
1334 }
1335
1336 impl MulticastAddress for Address {
1337 fn is_multicast(&self) -> bool {
1338 use Address::*;
1339 match self {
1340 GlobalMulticast | LinkLocalMulticast | MappedMulticast => true,
1341 Unspecified | GlobalUnicast | GlobalBroadcast | LinkLocalUnicast
1342 | MappedUnicast | MappedBroadcast | LinkLocalBroadcast => false,
1343 }
1344 }
1345 }
1346
1347 impl BroadcastAddress for Address {
1348 fn is_broadcast(&self) -> bool {
1349 use Address::*;
1350 match self {
1351 GlobalBroadcast | LinkLocalBroadcast | MappedBroadcast => true,
1352 Unspecified | GlobalUnicast | GlobalMulticast | LinkLocalUnicast
1353 | MappedUnicast | MappedMulticast | LinkLocalMulticast => false,
1354 }
1355 }
1356 }
1357
1358 impl LinkLocalAddress for Address {
1359 fn is_link_local(&self) -> bool {
1360 use Address::*;
1361 match self {
1362 LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1363 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast | MappedUnicast
1364 | MappedBroadcast | MappedMulticast => false,
1365 }
1366 }
1367 }
1368
1369 impl MappedAddress for Address {
1370 fn is_non_mapped(&self) -> bool {
1371 use Address::*;
1372 match self {
1373 MappedUnicast | MappedBroadcast | MappedMulticast => false,
1374 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast
1375 | LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1376 }
1377 }
1378 }
1379
1380 #[derive(Copy, Clone, Eq, PartialEq)]
1381 enum AddressScope {
1382 LinkLocal,
1383 Global,
1384 }
1385
1386 impl Scope for AddressScope {
1387 fn can_have_zone(&self) -> bool {
1388 matches!(self, AddressScope::LinkLocal)
1389 }
1390 }
1391
1392 impl ScopeableAddress for Address {
1393 type Scope = AddressScope;
1394
1395 fn scope(&self) -> AddressScope {
1396 if self.is_link_local() { AddressScope::LinkLocal } else { AddressScope::Global }
1397 }
1398 }
1399
1400 #[test]
1401 fn specified_addr() {
1402 assert_eq!(
1403 SpecifiedAddr::new(Address::GlobalUnicast),
1404 Some(SpecifiedAddr(Address::GlobalUnicast))
1405 );
1406 assert_eq!(SpecifiedAddr::new(Address::Unspecified), None);
1407 }
1408
1409 #[test]
1410 fn unicast_addr() {
1411 assert_eq!(
1412 UnicastAddr::new(Address::GlobalUnicast),
1413 Some(UnicastAddr(Address::GlobalUnicast))
1414 );
1415 assert_eq!(UnicastAddr::new(Address::GlobalMulticast), None);
1416 assert_eq!(
1417 unsafe { UnicastAddr::new_unchecked(Address::GlobalUnicast) },
1418 UnicastAddr(Address::GlobalUnicast)
1419 );
1420 }
1421
1422 #[test]
1423 fn multicast_addr() {
1424 assert_eq!(
1425 MulticastAddr::new(Address::GlobalMulticast),
1426 Some(MulticastAddr(Address::GlobalMulticast))
1427 );
1428 assert_eq!(MulticastAddr::new(Address::GlobalUnicast), None);
1429 assert_eq!(
1430 unsafe { MulticastAddr::new_unchecked(Address::GlobalMulticast) },
1431 MulticastAddr(Address::GlobalMulticast)
1432 );
1433 }
1434
1435 #[test]
1436 fn broadcast_addr() {
1437 assert_eq!(
1438 BroadcastAddr::new(Address::GlobalBroadcast),
1439 Some(BroadcastAddr(Address::GlobalBroadcast))
1440 );
1441 assert_eq!(BroadcastAddr::new(Address::GlobalUnicast), None);
1442 assert_eq!(
1443 unsafe { BroadcastAddr::new_unchecked(Address::GlobalBroadcast) },
1444 BroadcastAddr(Address::GlobalBroadcast)
1445 );
1446 }
1447
1448 #[test]
1449 fn link_local_addr() {
1450 assert_eq!(
1451 LinkLocalAddr::new(Address::LinkLocalUnicast),
1452 Some(LinkLocalAddr(Address::LinkLocalUnicast))
1453 );
1454 assert_eq!(LinkLocalAddr::new(Address::GlobalMulticast), None);
1455 assert_eq!(
1456 unsafe { LinkLocalAddr::new_unchecked(Address::LinkLocalUnicast) },
1457 LinkLocalAddr(Address::LinkLocalUnicast)
1458 );
1459 }
1460
1461 #[test]
1462 fn non_mapped_addr() {
1463 assert_eq!(
1464 NonMappedAddr::new(Address::LinkLocalUnicast),
1465 Some(NonMappedAddr(Address::LinkLocalUnicast))
1466 );
1467 assert_eq!(NonMappedAddr::new(Address::MappedUnicast), None);
1468 assert_eq!(
1469 NonMappedAddr::new(Address::LinkLocalMulticast),
1470 Some(NonMappedAddr(Address::LinkLocalMulticast))
1471 );
1472 assert_eq!(NonMappedAddr::new(Address::MappedMulticast), None);
1473 assert_eq!(
1474 NonMappedAddr::new(Address::LinkLocalBroadcast),
1475 Some(NonMappedAddr(Address::LinkLocalBroadcast))
1476 );
1477 assert_eq!(NonMappedAddr::new(Address::MappedBroadcast), None);
1478 }
1479
1480 macro_rules! test_nested {
1481 ($outer:ident, $inner:ident, $($input:ident => $output:expr,)*) => {
1482 $(
1483 assert_eq!($inner::new(Address::$input).and_then($outer::new), $output);
1484 )*
1485 };
1486 }
1487
1488 #[test]
1489 fn nested_link_local() {
1490 test_nested!(
1496 UnicastAddr,
1497 LinkLocalAddr,
1498 Unspecified => None,
1499 GlobalUnicast => None,
1500 GlobalMulticast => None,
1501 LinkLocalUnicast => Some(UnicastAddr(LinkLocalAddr(Address::LinkLocalUnicast))),
1502 LinkLocalMulticast => None,
1503 LinkLocalBroadcast => None,
1504 );
1505
1506 test_nested!(
1508 MulticastAddr,
1509 LinkLocalAddr,
1510 Unspecified => None,
1511 GlobalUnicast => None,
1512 GlobalMulticast => None,
1513 LinkLocalUnicast => None,
1514 LinkLocalMulticast => Some(MulticastAddr(LinkLocalAddr(Address::LinkLocalMulticast))),
1515 LinkLocalBroadcast => None,
1516 );
1517
1518 test_nested!(
1520 BroadcastAddr,
1521 LinkLocalAddr,
1522 Unspecified => None,
1523 GlobalUnicast => None,
1524 GlobalMulticast => None,
1525 LinkLocalUnicast => None,
1526 LinkLocalMulticast => None,
1527 LinkLocalBroadcast => Some(BroadcastAddr(LinkLocalAddr(Address::LinkLocalBroadcast))),
1528 );
1529
1530 test_nested!(
1532 LinkLocalAddr,
1533 UnicastAddr,
1534 Unspecified => None,
1535 GlobalUnicast => None,
1536 GlobalMulticast => None,
1537 LinkLocalUnicast => Some(LinkLocalAddr(UnicastAddr(Address::LinkLocalUnicast))),
1538 LinkLocalMulticast => None,
1539 LinkLocalBroadcast => None,
1540 );
1541 test_nested!(
1542 LinkLocalAddr,
1543 MulticastAddr,
1544 Unspecified => None,
1545 GlobalUnicast => None,
1546 GlobalMulticast => None,
1547 LinkLocalUnicast => None,
1548 LinkLocalMulticast => Some(LinkLocalAddr(MulticastAddr(Address::LinkLocalMulticast))),
1549 LinkLocalBroadcast => None,
1550 );
1551 test_nested!(
1552 LinkLocalAddr,
1553 BroadcastAddr,
1554 Unspecified => None,
1555 GlobalUnicast => None,
1556 GlobalMulticast => None,
1557 LinkLocalUnicast => None,
1558 LinkLocalMulticast => None,
1559 LinkLocalBroadcast => Some(LinkLocalAddr(BroadcastAddr(Address::LinkLocalBroadcast))),
1560 );
1561 }
1562
1563 #[test]
1564 fn nested_non_mapped() {
1565 test_nested!(
1572 UnicastAddr,
1573 NonMappedAddr,
1574 Unspecified => None,
1575 LinkLocalUnicast => Some(UnicastAddr(NonMappedAddr(Address::LinkLocalUnicast))),
1576 LinkLocalMulticast => None,
1577 LinkLocalBroadcast => None,
1578 MappedUnicast => None,
1579 MappedMulticast => None,
1580 MappedBroadcast => None,
1581 );
1582
1583 test_nested!(
1585 MulticastAddr,
1586 NonMappedAddr,
1587 Unspecified => None,
1588 LinkLocalUnicast => None,
1589 LinkLocalMulticast => Some(MulticastAddr(NonMappedAddr(Address::LinkLocalMulticast))),
1590 LinkLocalBroadcast => None,
1591 MappedUnicast => None,
1592 MappedMulticast => None,
1593 MappedBroadcast => None,
1594 );
1595
1596 test_nested!(
1598 BroadcastAddr,
1599 NonMappedAddr,
1600 Unspecified => None,
1601 LinkLocalUnicast => None,
1602 LinkLocalMulticast => None,
1603 LinkLocalBroadcast => Some(BroadcastAddr(NonMappedAddr(Address::LinkLocalBroadcast))),
1604 MappedUnicast => None,
1605 MappedMulticast => None,
1606 MappedBroadcast => None,
1607 );
1608
1609 test_nested!(
1611 NonMappedAddr,
1612 UnicastAddr,
1613 Unspecified => None,
1614 LinkLocalUnicast => Some(NonMappedAddr(UnicastAddr(Address::LinkLocalUnicast))),
1615 LinkLocalMulticast => None,
1616 LinkLocalBroadcast => None,
1617 MappedUnicast => None,
1618 MappedMulticast => None,
1619 MappedBroadcast => None,
1620 );
1621 test_nested!(
1622 NonMappedAddr,
1623 MulticastAddr,
1624 Unspecified => None,
1625 LinkLocalUnicast => None,
1626 LinkLocalMulticast => Some(NonMappedAddr(MulticastAddr(Address::LinkLocalMulticast))),
1627 LinkLocalBroadcast => None,
1628 MappedUnicast => None,
1629 MappedMulticast => None,
1630 MappedBroadcast => None,
1631 );
1632 test_nested!(
1633 NonMappedAddr,
1634 BroadcastAddr,
1635 Unspecified => None,
1636 LinkLocalUnicast => None,
1637 LinkLocalMulticast => None,
1638 LinkLocalBroadcast => Some(NonMappedAddr(BroadcastAddr(Address::LinkLocalBroadcast))),
1639 MappedUnicast => None,
1640 MappedMulticast => None,
1641 MappedBroadcast => None,
1642 );
1643 }
1644
1645 #[test]
1646 fn addr_and_zone() {
1647 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, ());
1648 assert_eq!(addr_and_zone, Some(AddrAndZone(Address::LinkLocalUnicast, ())));
1649 assert_eq!(addr_and_zone.unwrap().into_addr_scope_id(), (Address::LinkLocalUnicast, ()));
1650 assert_eq!(AddrAndZone::new(Address::GlobalUnicast, ()), None);
1651 assert_eq!(
1652 unsafe { AddrAndZone::new_unchecked(Address::LinkLocalUnicast, ()) },
1653 AddrAndZone(Address::LinkLocalUnicast, ())
1654 );
1655 }
1656
1657 #[test]
1658 fn addr_and_zone_map_zone() {
1659 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 65).unwrap();
1660 assert_eq!(
1661 addr_and_zone.map_zone(|x| char::from_u32(x).unwrap()),
1662 AddrAndZone::new(Address::LinkLocalUnicast, 'A').unwrap()
1663 );
1664 }
1665
1666 #[test]
1667 fn addr_and_zone_try_map_zone() {
1668 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 32).unwrap();
1669 assert_eq!(
1670 addr_and_zone.try_map_zone(|x| Ok::<_, ()>(x + 1)),
1671 Ok(AddrAndZone::new(Address::LinkLocalUnicast, 33).unwrap())
1672 );
1673
1674 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 32).unwrap();
1675 assert_eq!(addr_and_zone.try_map_zone(|x| Err::<i32, _>(x - 1)), Err(31),);
1676 }
1677
1678 #[test]
1679 fn scoped_address() {
1680 type ZonedAddr = crate::ZonedAddr<Address, ()>;
1683 assert_eq!(
1684 ZonedAddr::new(Address::GlobalUnicast, None),
1685 Some(ZonedAddr::Unzoned(Address::GlobalUnicast))
1686 );
1687 assert_eq!(
1688 ZonedAddr::new(Address::Unspecified, None).unwrap().into_addr_zone(),
1689 (Address::Unspecified, None)
1690 );
1691 assert_eq!(
1692 ZonedAddr::new(Address::LinkLocalUnicast, None),
1693 Some(ZonedAddr::Unzoned(Address::LinkLocalUnicast))
1694 );
1695 assert_eq!(ZonedAddr::new(Address::GlobalUnicast, Some(())), None);
1696 assert_eq!(ZonedAddr::new(Address::Unspecified, Some(())), None);
1697 assert_eq!(
1698 ZonedAddr::new(Address::LinkLocalUnicast, Some(())),
1699 Some(ZonedAddr::Zoned(AddrAndZone(Address::LinkLocalUnicast, ())))
1700 );
1701
1702 assert_eq!(
1703 ZonedAddr::new(Address::GlobalUnicast, None).unwrap().into_addr_zone(),
1704 (Address::GlobalUnicast, None)
1705 );
1706 assert_eq!(
1707 ZonedAddr::new(Address::LinkLocalUnicast, Some(())).unwrap().into_addr_zone(),
1708 (Address::LinkLocalUnicast, Some(()))
1709 );
1710 }
1711
1712 #[test]
1713 fn transpose_with_fully_qualified_types() {
1714 let addr: SpecifiedAddr<NonMappedAddr<Address>> =
1715 <NonMappedAddr<SpecifiedAddr<Address>> as Witness<SpecifiedAddr<Address>>>::transpose::<
1716 Address,
1717 >(
1718 NonMappedAddr::new(
1719 SpecifiedAddr::new(Address::LinkLocalUnicast)
1720 .expect("should be specified addr"),
1721 )
1722 .expect("should be non-mapped addr"),
1723 );
1724 assert_eq!(
1725 addr,
1726 SpecifiedAddr::new(
1727 NonMappedAddr::new(Address::LinkLocalUnicast).expect("should be non-mapped addr")
1728 )
1729 .expect("should be specified addr")
1730 )
1731 }
1732
1733 #[test]
1734 fn transpose_with_inferred_types() {
1735 assert_eq!(
1736 NonMappedAddr::new(
1737 SpecifiedAddr::new(Address::LinkLocalUnicast).expect("should be specified addr")
1738 )
1739 .expect("should be non-mapped addr")
1740 .transpose(),
1741 SpecifiedAddr::new(
1742 NonMappedAddr::new(Address::LinkLocalUnicast).expect("should be non-mapped addr")
1743 )
1744 .expect("should be specified addr")
1745 )
1746 }
1747}