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() { Some(Self(addr, zone)) } else { None }
1044 }
1045}
1046
1047impl<A: ScopeableAddress + IpAddress, Z> AddrAndZone<A, Z> {
1048 pub fn new_not_loopback(addr: A, zone: Z) -> Option<Self> {
1052 if addr.scope().can_have_zone() && !addr.is_loopback() {
1053 Some(Self(addr, zone))
1054 } else {
1055 None
1056 }
1057 }
1058}
1059
1060impl<A, Z> AddrAndZone<A, Z> {
1061 #[inline]
1069 pub const unsafe fn new_unchecked(addr: A, zone: Z) -> Self {
1070 Self(addr, zone)
1071 }
1072
1073 pub fn into_addr_scope_id(self) -> (A, Z) {
1075 let AddrAndZone(addr, zone) = self;
1076 (addr, zone)
1077 }
1078
1079 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> AddrAndZone<A, Y> {
1081 let AddrAndZone(addr, zone) = self;
1082 AddrAndZone(addr, f(zone))
1083 }
1084
1085 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> AddrAndZone<B, Z> {
1087 let Self(addr, zone) = self;
1088 AddrAndZone(f(addr), zone)
1089 }
1090
1091 pub fn try_map_zone<Y, E>(
1093 self,
1094 f: impl FnOnce(Z) -> Result<Y, E>,
1095 ) -> Result<AddrAndZone<A, Y>, E> {
1096 let AddrAndZone(addr, zone) = self;
1097 f(zone).map(|zone| AddrAndZone(addr, zone))
1098 }
1099
1100 pub fn addr(&self) -> A
1102 where
1103 A: Copy,
1104 {
1105 let AddrAndZone(addr, _zone) = self;
1106 *addr
1107 }
1108
1109 pub fn as_ref(&self) -> AddrAndZone<&A, &Z> {
1111 let Self(addr, zone) = self;
1112 AddrAndZone(addr, zone)
1113 }
1114}
1115
1116impl<A: Display, Z: Display> Display for AddrAndZone<A, Z> {
1117 #[inline]
1118 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1119 write!(f, "{}%{}", self.0, self.1)
1120 }
1121}
1122
1123impl<A, Z> sealed::Sealed for AddrAndZone<A, Z> {}
1124
1125impl<A: SpecifiedAddress, Z> From<AddrAndZone<SpecifiedAddr<A>, Z>> for AddrAndZone<A, Z> {
1126 fn from(AddrAndZone(addr, zone): AddrAndZone<SpecifiedAddr<A>, Z>) -> Self {
1127 Self(addr.into_addr(), zone)
1128 }
1129}
1130
1131#[allow(missing_docs)]
1133#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
1134pub enum ZonedAddr<A, Z> {
1135 Unzoned(A),
1136 Zoned(AddrAndZone<A, Z>),
1137}
1138
1139impl<A: Display, Z: Display> Display for ZonedAddr<A, Z> {
1140 #[inline]
1141 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1142 match self {
1143 Self::Unzoned(addr) => write!(f, "{addr}"),
1144 Self::Zoned(addr_and_zone) => write!(f, "{addr_and_zone}"),
1145 }
1146 }
1147}
1148
1149impl<A, Z> ZonedAddr<A, Z> {
1150 pub fn into_addr_zone(self) -> (A, Option<Z>) {
1152 match self {
1153 ZonedAddr::Unzoned(addr) => (addr, None),
1154 ZonedAddr::Zoned(scope_and_zone) => {
1155 let (addr, zone) = scope_and_zone.into_addr_scope_id();
1156 (addr, Some(zone))
1157 }
1158 }
1159 }
1160
1161 pub fn addr(&self) -> A
1163 where
1164 A: Copy,
1165 {
1166 match self {
1167 ZonedAddr::Unzoned(addr) => *addr,
1168 ZonedAddr::Zoned(addr_and_zone) => addr_and_zone.addr(),
1169 }
1170 }
1171
1172 pub fn map_zone<Y>(self, f: impl FnOnce(Z) -> Y) -> ZonedAddr<A, Y> {
1174 match self {
1175 ZonedAddr::Unzoned(u) => ZonedAddr::Unzoned(u),
1176 ZonedAddr::Zoned(z) => ZonedAddr::Zoned(z.map_zone(f)),
1177 }
1178 }
1179
1180 pub fn map_addr<B>(self, f: impl FnOnce(A) -> B) -> ZonedAddr<B, Z> {
1182 match self {
1183 Self::Unzoned(u) => ZonedAddr::Unzoned(f(u)),
1184 Self::Zoned(z) => ZonedAddr::Zoned(z.map_addr(f)),
1185 }
1186 }
1187
1188 pub fn as_ref(&self) -> ZonedAddr<&A, &Z> {
1190 match self {
1191 Self::Unzoned(u) => ZonedAddr::Unzoned(u),
1192 Self::Zoned(z) => ZonedAddr::Zoned(z.as_ref()),
1193 }
1194 }
1195}
1196
1197impl<A: ScopeableAddress, Z> ZonedAddr<A, Z> {
1198 pub fn new(addr: A, zone: Option<Z>) -> Option<Self> {
1204 match zone {
1205 Some(zone) => AddrAndZone::new(addr, zone).map(ZonedAddr::Zoned),
1206 None => Some(ZonedAddr::Unzoned(addr)),
1207 }
1208 }
1209}
1210
1211impl<A: IpAddress + ScopeableAddress, Z: Clone> ZonedAddr<A, Z> {
1212 pub fn new_zoned_if_necessary(addr: A, get_zone: impl FnOnce() -> Z) -> Self {
1217 match AddrAndZone::new_not_loopback(addr, ()) {
1218 Some(addr_and_zone) => Self::Zoned(addr_and_zone.map_zone(move |()| get_zone())),
1219 None => Self::Unzoned(addr),
1220 }
1221 }
1222}
1223
1224impl<A: ScopeableAddress<Scope = ()>, Z> ZonedAddr<A, Z> {
1225 pub fn into_unzoned(self) -> A {
1230 match self {
1231 ZonedAddr::Unzoned(u) => u,
1232 ZonedAddr::Zoned(_z) => unreachable!(),
1233 }
1234 }
1235}
1236
1237impl<A, Z> From<AddrAndZone<A, Z>> for ZonedAddr<A, Z> {
1238 fn from(a: AddrAndZone<A, Z>) -> Self {
1239 Self::Zoned(a)
1240 }
1241}
1242
1243impl<A: SpecifiedAddress, Z> From<ZonedAddr<SpecifiedAddr<A>, Z>> for ZonedAddr<A, Z> {
1244 fn from(zoned_addr: ZonedAddr<SpecifiedAddr<A>, Z>) -> Self {
1245 match zoned_addr {
1246 ZonedAddr::Unzoned(a) => Self::Unzoned(a.into_addr()),
1247 ZonedAddr::Zoned(z) => Self::Zoned(z.into()),
1248 }
1249 }
1250}
1251
1252impl<A, I: Ip> GenericOverIp<I> for SpecifiedAddr<A> {
1253 type Type = SpecifiedAddr<I::Addr>;
1254}
1255
1256impl<A: IpAddress, I: Ip> GenericOverIp<I> for MulticastAddr<A> {
1257 type Type = MulticastAddr<I::Addr>;
1258}
1259
1260impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for ZonedAddr<A, Z> {
1261 type Type = ZonedAddr<A::Type, Z>;
1262}
1263
1264impl<A: GenericOverIp<I>, I: Ip, Z> GenericOverIp<I> for AddrAndZone<A, Z> {
1265 type Type = AddrAndZone<A::Type, Z>;
1266}
1267
1268#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1270pub struct AddrAndPortFormatter<A, P, I: Ip> {
1271 addr: A,
1272 port: P,
1273 _marker: IpVersionMarker<I>,
1274}
1275
1276impl<A, P, I: Ip> AddrAndPortFormatter<A, P, I> {
1277 pub fn new(addr: A, port: P) -> Self {
1279 Self { addr, port, _marker: IpVersionMarker::new() }
1280 }
1281}
1282
1283impl<A: Display, P: Display, I: Ip> Display for AddrAndPortFormatter<A, P, I> {
1284 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
1285 let Self { addr, port, _marker } = self;
1286 let IpInvariant(result) = I::map_ip(
1287 IpInvariant((addr, port, f)),
1288 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "{}:{}", addr, port)),
1289 |IpInvariant((addr, port, f))| IpInvariant(write!(f, "[{}]:{}", addr, port)),
1290 );
1291 result
1292 }
1293}
1294
1295#[cfg(test)]
1296mod tests {
1297 use super::*;
1298
1299 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
1300 enum Address {
1301 Unspecified,
1302 GlobalUnicast,
1303 GlobalMulticast,
1304 GlobalBroadcast,
1305 LinkLocalUnicast,
1306 LinkLocalMulticast,
1307 LinkLocalBroadcast,
1308 MappedUnicast,
1309 MappedMulticast,
1310 MappedBroadcast,
1311 }
1312
1313 impl SpecifiedAddress for Address {
1314 fn is_specified(&self) -> bool {
1315 *self != Address::Unspecified
1316 }
1317 }
1318
1319 impl UnicastAddress for Address {
1320 fn is_unicast(&self) -> bool {
1321 use Address::*;
1322 match self {
1323 GlobalUnicast | LinkLocalUnicast | MappedUnicast => true,
1324 Unspecified | GlobalMulticast | GlobalBroadcast | LinkLocalMulticast
1325 | LinkLocalBroadcast | MappedMulticast | MappedBroadcast => false,
1326 }
1327 }
1328 }
1329
1330 impl MulticastAddress for Address {
1331 fn is_multicast(&self) -> bool {
1332 use Address::*;
1333 match self {
1334 GlobalMulticast | LinkLocalMulticast | MappedMulticast => true,
1335 Unspecified | GlobalUnicast | GlobalBroadcast | LinkLocalUnicast
1336 | MappedUnicast | MappedBroadcast | LinkLocalBroadcast => false,
1337 }
1338 }
1339 }
1340
1341 impl BroadcastAddress for Address {
1342 fn is_broadcast(&self) -> bool {
1343 use Address::*;
1344 match self {
1345 GlobalBroadcast | LinkLocalBroadcast | MappedBroadcast => true,
1346 Unspecified | GlobalUnicast | GlobalMulticast | LinkLocalUnicast
1347 | MappedUnicast | MappedMulticast | LinkLocalMulticast => false,
1348 }
1349 }
1350 }
1351
1352 impl LinkLocalAddress for Address {
1353 fn is_link_local(&self) -> bool {
1354 use Address::*;
1355 match self {
1356 LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1357 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast | MappedUnicast
1358 | MappedBroadcast | MappedMulticast => false,
1359 }
1360 }
1361 }
1362
1363 impl MappedAddress for Address {
1364 fn is_non_mapped(&self) -> bool {
1365 use Address::*;
1366 match self {
1367 MappedUnicast | MappedBroadcast | MappedMulticast => false,
1368 Unspecified | GlobalUnicast | GlobalMulticast | GlobalBroadcast
1369 | LinkLocalUnicast | LinkLocalMulticast | LinkLocalBroadcast => true,
1370 }
1371 }
1372 }
1373
1374 #[derive(Copy, Clone, Eq, PartialEq)]
1375 enum AddressScope {
1376 LinkLocal,
1377 Global,
1378 }
1379
1380 impl Scope for AddressScope {
1381 fn can_have_zone(&self) -> bool {
1382 matches!(self, AddressScope::LinkLocal)
1383 }
1384 }
1385
1386 impl ScopeableAddress for Address {
1387 type Scope = AddressScope;
1388
1389 fn scope(&self) -> AddressScope {
1390 if self.is_link_local() { AddressScope::LinkLocal } else { AddressScope::Global }
1391 }
1392 }
1393
1394 #[test]
1395 fn specified_addr() {
1396 assert_eq!(
1397 SpecifiedAddr::new(Address::GlobalUnicast),
1398 Some(SpecifiedAddr(Address::GlobalUnicast))
1399 );
1400 assert_eq!(SpecifiedAddr::new(Address::Unspecified), None);
1401 }
1402
1403 #[test]
1404 fn unicast_addr() {
1405 assert_eq!(
1406 UnicastAddr::new(Address::GlobalUnicast),
1407 Some(UnicastAddr(Address::GlobalUnicast))
1408 );
1409 assert_eq!(UnicastAddr::new(Address::GlobalMulticast), None);
1410 assert_eq!(
1411 unsafe { UnicastAddr::new_unchecked(Address::GlobalUnicast) },
1412 UnicastAddr(Address::GlobalUnicast)
1413 );
1414 }
1415
1416 #[test]
1417 fn multicast_addr() {
1418 assert_eq!(
1419 MulticastAddr::new(Address::GlobalMulticast),
1420 Some(MulticastAddr(Address::GlobalMulticast))
1421 );
1422 assert_eq!(MulticastAddr::new(Address::GlobalUnicast), None);
1423 assert_eq!(
1424 unsafe { MulticastAddr::new_unchecked(Address::GlobalMulticast) },
1425 MulticastAddr(Address::GlobalMulticast)
1426 );
1427 }
1428
1429 #[test]
1430 fn broadcast_addr() {
1431 assert_eq!(
1432 BroadcastAddr::new(Address::GlobalBroadcast),
1433 Some(BroadcastAddr(Address::GlobalBroadcast))
1434 );
1435 assert_eq!(BroadcastAddr::new(Address::GlobalUnicast), None);
1436 assert_eq!(
1437 unsafe { BroadcastAddr::new_unchecked(Address::GlobalBroadcast) },
1438 BroadcastAddr(Address::GlobalBroadcast)
1439 );
1440 }
1441
1442 #[test]
1443 fn link_local_addr() {
1444 assert_eq!(
1445 LinkLocalAddr::new(Address::LinkLocalUnicast),
1446 Some(LinkLocalAddr(Address::LinkLocalUnicast))
1447 );
1448 assert_eq!(LinkLocalAddr::new(Address::GlobalMulticast), None);
1449 assert_eq!(
1450 unsafe { LinkLocalAddr::new_unchecked(Address::LinkLocalUnicast) },
1451 LinkLocalAddr(Address::LinkLocalUnicast)
1452 );
1453 }
1454
1455 #[test]
1456 fn non_mapped_addr() {
1457 assert_eq!(
1458 NonMappedAddr::new(Address::LinkLocalUnicast),
1459 Some(NonMappedAddr(Address::LinkLocalUnicast))
1460 );
1461 assert_eq!(NonMappedAddr::new(Address::MappedUnicast), None);
1462 assert_eq!(
1463 NonMappedAddr::new(Address::LinkLocalMulticast),
1464 Some(NonMappedAddr(Address::LinkLocalMulticast))
1465 );
1466 assert_eq!(NonMappedAddr::new(Address::MappedMulticast), None);
1467 assert_eq!(
1468 NonMappedAddr::new(Address::LinkLocalBroadcast),
1469 Some(NonMappedAddr(Address::LinkLocalBroadcast))
1470 );
1471 assert_eq!(NonMappedAddr::new(Address::MappedBroadcast), None);
1472 }
1473
1474 macro_rules! test_nested {
1475 ($outer:ident, $inner:ident, $($input:ident => $output:expr,)*) => {
1476 $(
1477 assert_eq!($inner::new(Address::$input).and_then($outer::new), $output);
1478 )*
1479 };
1480 }
1481
1482 #[test]
1483 fn nested_link_local() {
1484 test_nested!(
1490 UnicastAddr,
1491 LinkLocalAddr,
1492 Unspecified => None,
1493 GlobalUnicast => None,
1494 GlobalMulticast => None,
1495 LinkLocalUnicast => Some(UnicastAddr(LinkLocalAddr(Address::LinkLocalUnicast))),
1496 LinkLocalMulticast => None,
1497 LinkLocalBroadcast => None,
1498 );
1499
1500 test_nested!(
1502 MulticastAddr,
1503 LinkLocalAddr,
1504 Unspecified => None,
1505 GlobalUnicast => None,
1506 GlobalMulticast => None,
1507 LinkLocalUnicast => None,
1508 LinkLocalMulticast => Some(MulticastAddr(LinkLocalAddr(Address::LinkLocalMulticast))),
1509 LinkLocalBroadcast => None,
1510 );
1511
1512 test_nested!(
1514 BroadcastAddr,
1515 LinkLocalAddr,
1516 Unspecified => None,
1517 GlobalUnicast => None,
1518 GlobalMulticast => None,
1519 LinkLocalUnicast => None,
1520 LinkLocalMulticast => None,
1521 LinkLocalBroadcast => Some(BroadcastAddr(LinkLocalAddr(Address::LinkLocalBroadcast))),
1522 );
1523
1524 test_nested!(
1526 LinkLocalAddr,
1527 UnicastAddr,
1528 Unspecified => None,
1529 GlobalUnicast => None,
1530 GlobalMulticast => None,
1531 LinkLocalUnicast => Some(LinkLocalAddr(UnicastAddr(Address::LinkLocalUnicast))),
1532 LinkLocalMulticast => None,
1533 LinkLocalBroadcast => None,
1534 );
1535 test_nested!(
1536 LinkLocalAddr,
1537 MulticastAddr,
1538 Unspecified => None,
1539 GlobalUnicast => None,
1540 GlobalMulticast => None,
1541 LinkLocalUnicast => None,
1542 LinkLocalMulticast => Some(LinkLocalAddr(MulticastAddr(Address::LinkLocalMulticast))),
1543 LinkLocalBroadcast => None,
1544 );
1545 test_nested!(
1546 LinkLocalAddr,
1547 BroadcastAddr,
1548 Unspecified => None,
1549 GlobalUnicast => None,
1550 GlobalMulticast => None,
1551 LinkLocalUnicast => None,
1552 LinkLocalMulticast => None,
1553 LinkLocalBroadcast => Some(LinkLocalAddr(BroadcastAddr(Address::LinkLocalBroadcast))),
1554 );
1555 }
1556
1557 #[test]
1558 fn nested_non_mapped() {
1559 test_nested!(
1566 UnicastAddr,
1567 NonMappedAddr,
1568 Unspecified => None,
1569 LinkLocalUnicast => Some(UnicastAddr(NonMappedAddr(Address::LinkLocalUnicast))),
1570 LinkLocalMulticast => None,
1571 LinkLocalBroadcast => None,
1572 MappedUnicast => None,
1573 MappedMulticast => None,
1574 MappedBroadcast => None,
1575 );
1576
1577 test_nested!(
1579 MulticastAddr,
1580 NonMappedAddr,
1581 Unspecified => None,
1582 LinkLocalUnicast => None,
1583 LinkLocalMulticast => Some(MulticastAddr(NonMappedAddr(Address::LinkLocalMulticast))),
1584 LinkLocalBroadcast => None,
1585 MappedUnicast => None,
1586 MappedMulticast => None,
1587 MappedBroadcast => None,
1588 );
1589
1590 test_nested!(
1592 BroadcastAddr,
1593 NonMappedAddr,
1594 Unspecified => None,
1595 LinkLocalUnicast => None,
1596 LinkLocalMulticast => None,
1597 LinkLocalBroadcast => Some(BroadcastAddr(NonMappedAddr(Address::LinkLocalBroadcast))),
1598 MappedUnicast => None,
1599 MappedMulticast => None,
1600 MappedBroadcast => None,
1601 );
1602
1603 test_nested!(
1605 NonMappedAddr,
1606 UnicastAddr,
1607 Unspecified => None,
1608 LinkLocalUnicast => Some(NonMappedAddr(UnicastAddr(Address::LinkLocalUnicast))),
1609 LinkLocalMulticast => None,
1610 LinkLocalBroadcast => None,
1611 MappedUnicast => None,
1612 MappedMulticast => None,
1613 MappedBroadcast => None,
1614 );
1615 test_nested!(
1616 NonMappedAddr,
1617 MulticastAddr,
1618 Unspecified => None,
1619 LinkLocalUnicast => None,
1620 LinkLocalMulticast => Some(NonMappedAddr(MulticastAddr(Address::LinkLocalMulticast))),
1621 LinkLocalBroadcast => None,
1622 MappedUnicast => None,
1623 MappedMulticast => None,
1624 MappedBroadcast => None,
1625 );
1626 test_nested!(
1627 NonMappedAddr,
1628 BroadcastAddr,
1629 Unspecified => None,
1630 LinkLocalUnicast => None,
1631 LinkLocalMulticast => None,
1632 LinkLocalBroadcast => Some(NonMappedAddr(BroadcastAddr(Address::LinkLocalBroadcast))),
1633 MappedUnicast => None,
1634 MappedMulticast => None,
1635 MappedBroadcast => None,
1636 );
1637 }
1638
1639 #[test]
1640 fn addr_and_zone() {
1641 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, ());
1642 assert_eq!(addr_and_zone, Some(AddrAndZone(Address::LinkLocalUnicast, ())));
1643 assert_eq!(addr_and_zone.unwrap().into_addr_scope_id(), (Address::LinkLocalUnicast, ()));
1644 assert_eq!(AddrAndZone::new(Address::GlobalUnicast, ()), None);
1645 assert_eq!(
1646 unsafe { AddrAndZone::new_unchecked(Address::LinkLocalUnicast, ()) },
1647 AddrAndZone(Address::LinkLocalUnicast, ())
1648 );
1649 }
1650
1651 #[test]
1652 fn addr_and_zone_map_zone() {
1653 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 65).unwrap();
1654 assert_eq!(
1655 addr_and_zone.map_zone(|x| char::from_u32(x).unwrap()),
1656 AddrAndZone::new(Address::LinkLocalUnicast, 'A').unwrap()
1657 );
1658 }
1659
1660 #[test]
1661 fn addr_and_zone_try_map_zone() {
1662 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 32).unwrap();
1663 assert_eq!(
1664 addr_and_zone.try_map_zone(|x| Ok::<_, ()>(x + 1)),
1665 Ok(AddrAndZone::new(Address::LinkLocalUnicast, 33).unwrap())
1666 );
1667
1668 let addr_and_zone = AddrAndZone::new(Address::LinkLocalUnicast, 32).unwrap();
1669 assert_eq!(addr_and_zone.try_map_zone(|x| Err::<i32, _>(x - 1)), Err(31),);
1670 }
1671
1672 #[test]
1673 fn scoped_address() {
1674 type ZonedAddr = crate::ZonedAddr<Address, ()>;
1677 assert_eq!(
1678 ZonedAddr::new(Address::GlobalUnicast, None),
1679 Some(ZonedAddr::Unzoned(Address::GlobalUnicast))
1680 );
1681 assert_eq!(
1682 ZonedAddr::new(Address::Unspecified, None).unwrap().into_addr_zone(),
1683 (Address::Unspecified, None)
1684 );
1685 assert_eq!(
1686 ZonedAddr::new(Address::LinkLocalUnicast, None),
1687 Some(ZonedAddr::Unzoned(Address::LinkLocalUnicast))
1688 );
1689 assert_eq!(ZonedAddr::new(Address::GlobalUnicast, Some(())), None);
1690 assert_eq!(ZonedAddr::new(Address::Unspecified, Some(())), None);
1691 assert_eq!(
1692 ZonedAddr::new(Address::LinkLocalUnicast, Some(())),
1693 Some(ZonedAddr::Zoned(AddrAndZone(Address::LinkLocalUnicast, ())))
1694 );
1695
1696 assert_eq!(
1697 ZonedAddr::new(Address::GlobalUnicast, None).unwrap().into_addr_zone(),
1698 (Address::GlobalUnicast, None)
1699 );
1700 assert_eq!(
1701 ZonedAddr::new(Address::LinkLocalUnicast, Some(())).unwrap().into_addr_zone(),
1702 (Address::LinkLocalUnicast, Some(()))
1703 );
1704 }
1705
1706 #[test]
1707 fn transpose_with_fully_qualified_types() {
1708 let addr: SpecifiedAddr<NonMappedAddr<Address>> =
1709 <NonMappedAddr<SpecifiedAddr<Address>> as Witness<SpecifiedAddr<Address>>>::transpose::<
1710 Address,
1711 >(
1712 NonMappedAddr::new(
1713 SpecifiedAddr::new(Address::LinkLocalUnicast)
1714 .expect("should be specified addr"),
1715 )
1716 .expect("should be non-mapped addr"),
1717 );
1718 assert_eq!(
1719 addr,
1720 SpecifiedAddr::new(
1721 NonMappedAddr::new(Address::LinkLocalUnicast).expect("should be non-mapped addr")
1722 )
1723 .expect("should be specified addr")
1724 )
1725 }
1726
1727 #[test]
1728 fn transpose_with_inferred_types() {
1729 assert_eq!(
1730 NonMappedAddr::new(
1731 SpecifiedAddr::new(Address::LinkLocalUnicast).expect("should be specified addr")
1732 )
1733 .expect("should be non-mapped addr")
1734 .transpose(),
1735 SpecifiedAddr::new(
1736 NonMappedAddr::new(Address::LinkLocalUnicast).expect("should be non-mapped addr")
1737 )
1738 .expect("should be specified addr")
1739 )
1740 }
1741}