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);
835
836impl<A: MulticastAddress + UnicastAddress> From<UnicastAddr<A>> for NonMulticastAddr<A> {
837 #[inline]
838 fn from(addr: UnicastAddr<A>) -> Self {
839 unsafe { NonMulticastAddr::new_unchecked(addr.into_addr()) }
841 }
842}
843impl_nested_witness!(
846 MulticastAddress,
847 NonMulticastAddr,
848 MappedAddress,
849 NonMappedAddr,
850 SpecifiedAddress,
851 SpecifiedAddr
852);
853impl_into_specified_for_nested_witness!(
854 MulticastAddress,
855 NonMulticastAddr,
856 MappedAddress,
857 NonMappedAddr,
858 SpecifiedAddress,
859 SpecifiedAddr
860);
861
862impl_witness!(BroadcastAddr, "broadcast", BroadcastAddress, is_broadcast);
864impl_into_specified!(BroadcastAddr, BroadcastAddress, is_broadcast);
865impl_nested_witness!(BroadcastAddress, BroadcastAddr, LinkLocalAddress, LinkLocalAddr);
866impl_nested_witness!(BroadcastAddress, BroadcastAddr, MappedAddress, NonMappedAddr);
867impl_into_specified_for_nested_witness!(
868 BroadcastAddress,
869 BroadcastAddr,
870 LinkLocalAddress,
871 LinkLocalAddr
872);
873impl_into_specified_for_nested_witness!(
874 BroadcastAddress,
875 BroadcastAddr,
876 MappedAddress,
877 NonMappedAddr
878);
879impl_try_from_witness!(
880 [BroadcastAddr: BroadcastAddress],
881 [UnicastAddr: UnicastAddress],
882 [MulticastAddr: MulticastAddress],
883 [LinkLocalAddr: LinkLocalAddress],
884 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
885 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
886 [NonMappedAddr: MappedAddress]
887);
888
889impl_witness!(LinkLocalAddr, "link-local", LinkLocalAddress, is_link_local);
891impl_into_specified!(LinkLocalAddr, LinkLocalAddress, is_link_local);
892impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, UnicastAddress, UnicastAddr);
893impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, MulticastAddress, MulticastAddr);
894impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, BroadcastAddress, BroadcastAddr);
895impl_nested_witness!(LinkLocalAddress, LinkLocalAddr, MappedAddress, NonMappedAddr);
896impl_into_specified_for_nested_witness!(
897 LinkLocalAddress,
898 LinkLocalAddr,
899 UnicastAddress,
900 UnicastAddr
901);
902impl_into_specified_for_nested_witness!(
903 LinkLocalAddress,
904 LinkLocalAddr,
905 MulticastAddress,
906 MulticastAddr
907);
908impl_into_specified_for_nested_witness!(
909 LinkLocalAddress,
910 LinkLocalAddr,
911 BroadcastAddress,
912 BroadcastAddr
913);
914impl_into_specified_for_nested_witness!(
915 LinkLocalAddress,
916 LinkLocalAddr,
917 MappedAddress,
918 NonMappedAddr
919);
920impl_try_from_witness!(
921 [LinkLocalAddr: LinkLocalAddress],
922 [UnicastAddr: UnicastAddress],
923 [MulticastAddr: MulticastAddress],
924 [BroadcastAddr: BroadcastAddress],
925 [NonMappedAddr: MappedAddress]
926);
927
928impl_witness!(NonMappedAddr, "non_mapped", MappedAddress, is_non_mapped);
930impl_nested_witness!(MappedAddress, NonMappedAddr, SpecifiedAddress, SpecifiedAddr);
931impl_nested_witness!(MappedAddress, NonMappedAddr, UnicastAddress, UnicastAddr);
932impl_nested_witness!(MappedAddress, NonMappedAddr, MulticastAddress, MulticastAddr);
933impl_nested_witness!(MappedAddress, NonMappedAddr, BroadcastAddress, BroadcastAddr);
934impl_nested_witness!(MappedAddress, NonMappedAddr, LinkLocalAddress, LinkLocalAddr);
935impl_into_specified_for_nested_witness!(
936 MappedAddress,
937 NonMappedAddr,
938 SpecifiedAddress,
939 SpecifiedAddr
940);
941impl_into_specified_for_nested_witness!(MappedAddress, NonMappedAddr, UnicastAddress, UnicastAddr);
942impl_into_specified_for_nested_witness!(
943 MappedAddress,
944 NonMappedAddr,
945 MulticastAddress,
946 MulticastAddr
947);
948impl_into_specified_for_nested_witness!(
949 MappedAddress,
950 NonMappedAddr,
951 BroadcastAddress,
952 BroadcastAddr
953);
954impl_into_specified_for_nested_witness!(
955 MappedAddress,
956 NonMappedAddr,
957 LinkLocalAddress,
958 LinkLocalAddr
959);
960impl_try_from_witness!(
961 [NonMappedAddr: MappedAddress],
962 [SpecifiedAddr: SpecifiedAddress],
963 [UnicastAddr: UnicastAddress],
964 [MulticastAddr: MulticastAddress],
965 [BroadcastAddr: BroadcastAddress],
966 [LinkLocalAddr: LinkLocalAddress],
967 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
968 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
969 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
970);
971
972pub trait LinkLocalUnicastAddress: LinkLocalAddress + UnicastAddress {}
985impl<A: LinkLocalAddress + UnicastAddress> LinkLocalUnicastAddress for A {}
986
987pub trait LinkLocalMulticastAddress: LinkLocalAddress + MulticastAddress {}
992impl<A: LinkLocalAddress + MulticastAddress> LinkLocalMulticastAddress for A {}
993
994pub trait LinkLocalBroadcastAddress: LinkLocalAddress + BroadcastAddress {}
999impl<A: LinkLocalAddress + BroadcastAddress> LinkLocalBroadcastAddress for A {}
1000
1001pub type LinkLocalUnicastAddr<A> = LinkLocalAddr<UnicastAddr<A>>;
1003
1004pub type LinkLocalMulticastAddr<A> = LinkLocalAddr<MulticastAddr<A>>;
1006
1007pub type LinkLocalBroadcastAddr<A> = LinkLocalAddr<BroadcastAddr<A>>;
1009
1010impl_try_from_witness!(
1011 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1012 [UnicastAddr: UnicastAddress],
1013 [MulticastAddr: MulticastAddress],
1014 [LinkLocalAddr: LinkLocalAddress],
1015 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
1016 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
1017);
1018impl_try_from_witness!(
1019 [LinkLocalMulticastAddr: LinkLocalMulticastAddress],
1020 [UnicastAddr: UnicastAddress],
1021 [MulticastAddr: MulticastAddress],
1022 [LinkLocalAddr: LinkLocalAddress],
1023 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1024 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress]
1025);
1026impl_try_from_witness!(
1027 [LinkLocalBroadcastAddr: LinkLocalBroadcastAddress],
1028 [UnicastAddr: UnicastAddress],
1029 [MulticastAddr: MulticastAddress],
1030 [LinkLocalAddr: LinkLocalAddress],
1031 [LinkLocalUnicastAddr: LinkLocalUnicastAddress],
1032 [LinkLocalMulticastAddr: LinkLocalMulticastAddress]
1033);
1034
1035#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1045pub struct AddrAndZone<A, Z>(A, Z);
1046
1047impl<A: ScopeableAddress, Z> AddrAndZone<A, Z> {
1048 pub fn new(addr: A, zone: Z) -> Option<Self> {
1051 if addr.scope().can_have_zone() { Some(Self(addr, zone)) } else { None }
1052 }
1053}
1054
1055impl<A: ScopeableAddress + IpAddress, Z> AddrAndZone<A, Z> {
1056 pub fn new_not_loopback(addr: A, zone: Z) -> Option<Self> {
1060 if addr.scope().can_have_zone() && !addr.is_loopback() {
1061 Some(Self(addr, zone))
1062 } else {
1063 None
1064 }
1065 }
1066}
1067
1068impl<A, Z> AddrAndZone<A, Z> {
1069 #[inline]
1077 pub const unsafe fn new_unchecked(addr: A, zone: Z) -> Self {
1078 Self(addr, zone)
1079 }
1080
1081 pub fn into_addr_scope_id(self) -> (A, Z) {
1083 let AddrAndZone(addr, zone) = self;
1084 (addr, zone)
1085 }
1086
1087 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> AddrAndZone<A, Y> {
1089 let AddrAndZone(addr, zone) = self;
1090 AddrAndZone(addr, f(zone))
1091 }
1092
1093 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> AddrAndZone<B, Z> {
1095 let Self(addr, zone) = self;
1096 AddrAndZone(f(addr), zone)
1097 }
1098
1099 pub fn try_map_zone<Y, E>(
1101 self,
1102 f: impl FnOnce(Z) -> Result<Y, E>,
1103 ) -> Result<AddrAndZone<A, Y>, E> {
1104 let AddrAndZone(addr, zone) = self;
1105 f(zone).map(|zone| AddrAndZone(addr, zone))
1106 }
1107
1108 pub fn addr(&self) -> A
1110 where
1111 A: Copy,
1112 {
1113 let AddrAndZone(addr, _zone) = self;
1114 *addr
1115 }
1116
1117 pub fn as_ref(&self) -> AddrAndZone<&A, &Z> {
1119 let Self(addr, zone) = self;
1120 AddrAndZone(addr, zone)
1121 }
1122}
1123
1124impl<A: Display, Z: Display> Display for AddrAndZone<A, Z> {
1125 #[inline]
1126 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1127 write!(f, "{}%{}", self.0, self.1)
1128 }
1129}
1130
1131impl<A, Z> sealed::Sealed for AddrAndZone<A, Z> {}
1132
1133impl<A: SpecifiedAddress, Z> From<AddrAndZone<SpecifiedAddr<A>, Z>> for AddrAndZone<A, Z> {
1134 fn from(AddrAndZone(addr, zone): AddrAndZone<SpecifiedAddr<A>, Z>) -> Self {
1135 Self(addr.into_addr(), zone)
1136 }
1137}
1138
1139#[allow(missing_docs)]
1141#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1142pub enum ZonedAddr<A, Z> {
1143 Unzoned(A),
1144 Zoned(AddrAndZone<A, Z>),
1145}
1146
1147impl<A: Display, Z: Display> Display for ZonedAddr<A, Z> {
1148 #[inline]
1149 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1150 match self {
1151 Self::Unzoned(addr) => write!(f, "{addr}"),
1152 Self::Zoned(addr_and_zone) => write!(f, "{addr_and_zone}"),
1153 }
1154 }
1155}
1156
1157impl<A, Z> ZonedAddr<A, Z> {
1158 pub fn into_addr_zone(self) -> (A, Option<Z>) {
1160 match self {
1161 ZonedAddr::Unzoned(addr) => (addr, None),
1162 ZonedAddr::Zoned(scope_and_zone) => {
1163 let (addr, zone) = scope_and_zone.into_addr_scope_id();
1164 (addr, Some(zone))
1165 }
1166 }
1167 }
1168
1169 pub fn addr(&self) -> A
1171 where
1172 A: Copy,
1173 {
1174 match self {
1175 ZonedAddr::Unzoned(addr) => *addr,
1176 ZonedAddr::Zoned(addr_and_zone) => addr_and_zone.addr(),
1177 }
1178 }
1179
1180 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> ZonedAddr<A, Y> {
1182 match self {
1183 ZonedAddr::Unzoned(u) => ZonedAddr::Unzoned(u),
1184 ZonedAddr::Zoned(z) => ZonedAddr::Zoned(z.map_zone(f)),
1185 }
1186 }
1187
1188 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> ZonedAddr<B, Z> {
1190 match self {
1191 Self::Unzoned(u) => ZonedAddr::Unzoned(f(u)),
1192 Self::Zoned(z) => ZonedAddr::Zoned(z.map_addr(f)),
1193 }
1194 }
1195
1196 pub fn as_ref(&self) -> ZonedAddr<&A, &Z> {
1198 match self {
1199 Self::Unzoned(u) => ZonedAddr::Unzoned(u),
1200 Self::Zoned(z) => ZonedAddr::Zoned(z.as_ref()),
1201 }
1202 }
1203}
1204
1205impl<A: ScopeableAddress, Z> ZonedAddr<A, Z> {
1206 pub fn new(addr: A, zone: Option<Z>) -> Option<Self> {
1212 match zone {
1213 Some(zone) => AddrAndZone::new(addr, zone).map(ZonedAddr::Zoned),
1214 None => Some(ZonedAddr::Unzoned(addr)),
1215 }
1216 }
1217}
1218
1219impl<A: IpAddress + ScopeableAddress, Z: Clone> ZonedAddr<A, Z> {
1220 pub fn new_zoned_if_necessary(addr: A, get_zone: impl FnOnce() -> Z) -> Self {
1225 match AddrAndZone::new_not_loopback(addr, ()) {
1226 Some(addr_and_zone) => Self::Zoned(addr_and_zone.map_zone(move |()| get_zone())),
1227 None => Self::Unzoned(addr),
1228 }
1229 }
1230}
1231
1232impl<A: ScopeableAddress<Scope = ()>, Z> ZonedAddr<A, Z> {
1233 pub fn into_unzoned(self) -> A {
1238 match self {
1239 ZonedAddr::Unzoned(u) => u,
1240 ZonedAddr::Zoned(_z) => unreachable!(),
1241 }
1242 }
1243}
1244
1245impl<A, Z> From<AddrAndZone<A, Z>> for ZonedAddr<A, Z> {
1246 fn from(a: AddrAndZone<A, Z>) -> Self {
1247 Self::Zoned(a)
1248 }
1249}
1250
1251impl<A: SpecifiedAddress, Z> From<ZonedAddr<SpecifiedAddr<A>, Z>> for ZonedAddr<A, Z> {
1252 fn from(zoned_addr: ZonedAddr<SpecifiedAddr<A>, Z>) -> Self {
1253 match zoned_addr {
1254 ZonedAddr::Unzoned(a) => Self::Unzoned(a.into_addr()),
1255 ZonedAddr::Zoned(z) => Self::Zoned(z.into()),
1256 }
1257 }
1258}
1259
1260impl<A, I: Ip> GenericOverIp<I> for SpecifiedAddr<A> {
1261 type Type = SpecifiedAddr<I::Addr>;
1262}
1263
1264impl<A: IpAddress, I: Ip> GenericOverIp<I> for MulticastAddr<A> {
1265 type Type = MulticastAddr<I::Addr>;
1266}
1267
1268impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for ZonedAddr<A, Z> {
1269 type Type = ZonedAddr<A::Type, Z>;
1270}
1271
1272impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for AddrAndZone<A, Z> {
1273 type Type = AddrAndZone<A::Type, Z>;
1274}
1275
1276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1278pub struct AddrAndPortFormatter<A, P, I: Ip> {
1279 addr: A,
1280 port: P,
1281 _marker: IpVersionMarker<I>,
1282}
1283
1284impl<A, P, I: Ip> AddrAndPortFormatter<A, P, I> {
1285 pub fn new(addr: A, port: P) -> Self {
1287 Self { addr, port, _marker: IpVersionMarker::new() }
1288 }
1289}
1290
1291impl<A: Display, P: Display, I: Ip> Display for AddrAndPortFormatter<A, P, I> {
1292 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1293 let Self { addr, port, _marker } = self;
1294 let IpInvariant(result) = I::map_ip(
1295 IpInvariant((addr, port, f)),
1296 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "{}:{}", addr, port)),
1297 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "[{}]:{}", addr, port)),
1298 );
1299 result
1300 }
1301}
1302
1303#[cfg(test)]
1304mod tests {
1305 use super::*;
1306
1307 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1308 enum Address {
1309 Unspecified,
1310 GlobalUnicast,
1311 GlobalMulticast,
1312 GlobalBroadcast,
1313 LinkLocalUnicast,
1314 LinkLocalMulticast,
1315 LinkLocalBroadcast,
1316 MappedUnicast,
1317 MappedMulticast,
1318 MappedBroadcast,
1319 }
1320
1321 impl SpecifiedAddress for Address {
1322 fn is_specified(&self) -> bool {
1323 *self != Address::Unspecified
1324 }
1325 }
1326
1327 impl UnicastAddress for Address {
1328 fn is_unicast(&self) -> bool {
1329 use Address::*;
1330 match self {
1331 GlobalUnicast | LinkLocalUnicast | MappedUnicast => true,
1332 Unspecified | GlobalMulticast | GlobalBroadcast | LinkLocalMulticast
1333 | LinkLocalBroadcast | MappedMulticast | MappedBroadcast => false,
1334 }
1335 }
1336 }
1337
1338 impl MulticastAddress for Address {
1339 fn is_multicast(&self) -> bool {
1340 use Address::*;
1341 match self {
1342 GlobalMulticast | LinkLocalMulticast | MappedMulticast => true,
1343 Unspecified | GlobalUnicast | GlobalBroadcast | LinkLocalUnicast
1344 | MappedUnicast | MappedBroadcast | LinkLocalBroadcast => false,
1345 }
1346 }
1347 }
1348
1349 impl BroadcastAddress for Address {
1350 fn is_broadcast(&self) -> bool {
1351 use Address::*;
1352 match self {
1353 GlobalBroadcast | LinkLocalBroadcast | MappedBroadcast => true,
1354 Unspecified | GlobalUnicast | GlobalMulticast | LinkLocalUnicast
1355 | MappedUnicast | MappedMulticast | LinkLocalMulticast => false,
1356 }
1357 }
1358 }
1359
1360 impl LinkLocalAddress for Address {
1361 fn is_link_local(&self) -> bool {
1362 use Address::*;
1363 match self {
1364 LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1365 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast | MappedUnicast
1366 | MappedBroadcast | MappedMulticast => false,
1367 }
1368 }
1369 }
1370
1371 impl MappedAddress for Address {
1372 fn is_non_mapped(&self) -> bool {
1373 use Address::*;
1374 match self {
1375 MappedUnicast | MappedBroadcast | MappedMulticast => false,
1376 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast
1377 | LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1378 }
1379 }
1380 }
1381
1382 #[derive(Copy, Clone, Eq, PartialEq)]
1383 enum AddressScope {
1384 LinkLocal,
1385 Global,
1386 }
1387
1388 impl Scope for AddressScope {
1389 fn can_have_zone(&self) -> bool {
1390 matches!(self, AddressScope::LinkLocal)
1391 }
1392 }
1393
1394 impl ScopeableAddress for Address {
1395 type Scope = AddressScope;
1396
1397 fn scope(&self) -> AddressScope {
1398 if self.is_link_local() { AddressScope::LinkLocal } else { AddressScope::Global }
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}