@@ -59,6 +59,48 @@ pub enum Ipv6MulticastScope {
5959 Global
6060}
6161
62+ impl IpAddr {
63+ /// Returns true for the special 'unspecified' address (0.0.0.0 in IPv4, :: in IPv6).
64+ pub fn is_unspecified ( & self ) -> bool {
65+ match * self {
66+ IpAddr :: V4 ( ref a) => a. is_unspecified ( ) ,
67+ IpAddr :: V6 ( ref a) => a. is_unspecified ( ) ,
68+ }
69+ }
70+
71+ /// Returns true if this is a loopback address (127.0.0.0/8 in IPv4, ::1 in IPv6).
72+ pub fn is_loopback ( & self ) -> bool {
73+ match * self {
74+ IpAddr :: V4 ( ref a) => a. is_loopback ( ) ,
75+ IpAddr :: V6 ( ref a) => a. is_loopback ( ) ,
76+ }
77+ }
78+
79+ /// Returns true if the address appears to be globally routable.
80+ pub fn is_global ( & self ) -> bool {
81+ match * self {
82+ IpAddr :: V4 ( ref a) => a. is_global ( ) ,
83+ IpAddr :: V6 ( ref a) => a. is_global ( ) ,
84+ }
85+ }
86+
87+ /// Returns true if this is a multicast address (224.0.0.0/4 in IPv4, ff00::/8 in IPv6)
88+ pub fn is_multicast ( & self ) -> bool {
89+ match * self {
90+ IpAddr :: V4 ( ref a) => a. is_multicast ( ) ,
91+ IpAddr :: V6 ( ref a) => a. is_multicast ( ) ,
92+ }
93+ }
94+
95+ /// Returns true if this address is in a range designated for documentation.
96+ pub fn is_documentation ( & self ) -> bool {
97+ match * self {
98+ IpAddr :: V4 ( ref a) => a. is_documentation ( ) ,
99+ IpAddr :: V6 ( ref a) => a. is_documentation ( ) ,
100+ }
101+ }
102+ }
103+
62104impl Ipv4Addr {
63105 /// Creates a new IPv4 address from four eight-bit octets.
64106 ///
@@ -756,6 +798,67 @@ mod tests {
756798 None ) ;
757799 }
758800
801+ #[ test]
802+ fn ip_properties ( ) {
803+ fn check4 ( octets : & [ u8 ; 4 ] , unspec : bool , loopback : bool ,
804+ global : bool , multicast : bool , documentation : bool ) {
805+ let ip = IpAddr :: V4 ( Ipv4Addr :: new ( octets[ 0 ] , octets[ 1 ] , octets[ 2 ] , octets[ 3 ] ) ) ;
806+ assert_eq ! ( ip. is_unspecified( ) , unspec) ;
807+ assert_eq ! ( ip. is_loopback( ) , loopback) ;
808+ assert_eq ! ( ip. is_global( ) , global) ;
809+ assert_eq ! ( ip. is_multicast( ) , multicast) ;
810+ assert_eq ! ( ip. is_documentation( ) , documentation) ;
811+ }
812+
813+ fn check6 ( str_addr : & str , unspec : bool , loopback : bool ,
814+ global : bool , u_doc : bool , mcast : bool ) {
815+ let ip = IpAddr :: V6 ( str_addr. parse ( ) . unwrap ( ) ) ;
816+ assert_eq ! ( ip. is_unspecified( ) , unspec) ;
817+ assert_eq ! ( ip. is_loopback( ) , loopback) ;
818+ assert_eq ! ( ip. is_global( ) , global) ;
819+ assert_eq ! ( ip. is_documentation( ) , u_doc) ;
820+ assert_eq ! ( ip. is_multicast( ) , mcast) ;
821+ }
822+
823+ // address unspec loopbk global multicast doc
824+ check4 ( & [ 0 , 0 , 0 , 0 ] , true , false , false , false , false ) ;
825+ check4 ( & [ 0 , 0 , 0 , 1 ] , false , false , true , false , false ) ;
826+ check4 ( & [ 0 , 1 , 0 , 0 ] , false , false , true , false , false ) ;
827+ check4 ( & [ 10 , 9 , 8 , 7 ] , false , false , false , false , false ) ;
828+ check4 ( & [ 127 , 1 , 2 , 3 ] , false , true , false , false , false ) ;
829+ check4 ( & [ 172 , 31 , 254 , 253 ] , false , false , false , false , false ) ;
830+ check4 ( & [ 169 , 254 , 253 , 242 ] , false , false , false , false , false ) ;
831+ check4 ( & [ 192 , 0 , 2 , 183 ] , false , false , false , false , true ) ;
832+ check4 ( & [ 192 , 1 , 2 , 183 ] , false , false , true , false , false ) ;
833+ check4 ( & [ 192 , 168 , 254 , 253 ] , false , false , false , false , false ) ;
834+ check4 ( & [ 198 , 51 , 100 , 0 ] , false , false , false , false , true ) ;
835+ check4 ( & [ 203 , 0 , 113 , 0 ] , false , false , false , false , true ) ;
836+ check4 ( & [ 203 , 2 , 113 , 0 ] , false , false , true , false , false ) ;
837+ check4 ( & [ 224 , 0 , 0 , 0 ] , false , false , true , true , false ) ;
838+ check4 ( & [ 239 , 255 , 255 , 255 ] , false , false , true , true , false ) ;
839+ check4 ( & [ 255 , 255 , 255 , 255 ] , false , false , false , false , false ) ;
840+
841+ // address unspec loopbk global doc mcast
842+ check6 ( "::" , true , false , false , false , false ) ;
843+ check6 ( "::1" , false , true , false , false , false ) ;
844+ check6 ( "::0.0.0.2" , false , false , true , false , false ) ;
845+ check6 ( "1::" , false , false , true , false , false ) ;
846+ check6 ( "fc00::" , false , false , false , false , false ) ;
847+ check6 ( "fdff:ffff::" , false , false , false , false , false ) ;
848+ check6 ( "fe80:ffff::" , false , false , false , false , false ) ;
849+ check6 ( "febf:ffff::" , false , false , false , false , false ) ;
850+ check6 ( "fec0::" , false , false , false , false , false ) ;
851+ check6 ( "ff01::" , false , false , false , false , true ) ;
852+ check6 ( "ff02::" , false , false , false , false , true ) ;
853+ check6 ( "ff03::" , false , false , false , false , true ) ;
854+ check6 ( "ff04::" , false , false , false , false , true ) ;
855+ check6 ( "ff05::" , false , false , false , false , true ) ;
856+ check6 ( "ff08::" , false , false , false , false , true ) ;
857+ check6 ( "ff0e::" , false , false , true , false , true ) ;
858+ check6 ( "2001:db8:85a3::8a2e:370:7334" , false , false , false , true , false ) ;
859+ check6 ( "102:304:506:708:90a:b0c:d0e:f10" , false , false , true , false , false ) ;
860+ }
861+
759862 #[ test]
760863 fn ipv4_properties ( ) {
761864 fn check ( octets : & [ u8 ; 4 ] , unspec : bool , loopback : bool ,
0 commit comments