1use std::fmt;
2use std::mem;
3use std::ops::{AddAssign, SubAssign};
4use std::cmp::Ordering;
5
6fn add_assign(bytes: &mut [u8], mut rhs: i64) {
7 if rhs < 0 {
8 sub_assign(bytes, -rhs)
9 } else {
10 for it in bytes.iter_mut().rev() {
11 let (val, car) = it.overflowing_add(rhs as u8);
12 *it = val;
13 rhs >>= 8;
14 if car {
15 rhs += 1;
16 }
17 }
18 if rhs > 0 {
19 panic!("overflow");
20 }
21 }
22}
23
24fn sub_assign(bytes: &mut [u8], mut rhs: i64) {
25 if rhs < 0 {
26 add_assign(bytes, -rhs)
27 } else {
28 for it in bytes.iter_mut().rev() {
29 let (val, car) = it.overflowing_sub(rhs as u8);
30 *it = val;
31 rhs >>= 8;
32 if car {
33 rhs += 1;
34 }
35 }
36 if rhs > 0 {
37 panic!("overflow");
38 }
39 }
40}
41
42fn fmt_v6(bytes: &[u8; 16], f: &mut fmt::Formatter) -> fmt::Result {
43 let ar: &[u16; 8] = unsafe { mem::transmute(bytes) };
44 let mut cnt = 0;
45 let mut max_idx = 0;
46 let mut max_cnt = 0;
47 for (i, e) in ar.iter().enumerate() {
48 if *e != 0 {
49 if max_cnt < cnt {
50 max_idx = i - cnt;
51 max_cnt = cnt;
52 }
53 cnt = 0;
54 } else {
55 cnt += 1;
56 }
57 }
58 if max_cnt < cnt {
59 max_idx = ar.len() - cnt;
60 max_cnt = cnt;
61 }
62
63 if max_idx == 0 && max_cnt == 0 {
64 return write!(f, "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
65 u16::from_be(ar[0]), u16::from_be(ar[1]), u16::from_be(ar[2]), u16::from_be(ar[3]),
66 u16::from_be(ar[4]), u16::from_be(ar[5]), u16::from_be(ar[6]), u16::from_be(ar[7]));
67 }
68
69 if max_idx == 0 {
70 try!(write!(f, ":"));
71 } else {
72 for i in 0..max_idx {
73 try!(write!(f, "{:x}:", u16::from_be(ar[i])));
74 }
75 }
76
77 if max_idx + max_cnt == 8 {
78 try!(write!(f, ":"));
79 } else {
80 for i in max_idx + max_cnt..ar.len() {
81 try!(write!(f, ":{:x}", u16::from_be(ar[i])));
82 }
83 }
84 Ok(())
85}
86
87fn netmask_len(addr: &[u8]) -> u8 {
88 if addr[0] == 0 {
89 return 0;
90 }
91
92 let mut mask = 0;
93 let mut it = addr.iter();
94 while let Some(&n) = it.next() {
95 match n {
96 0b00000000 => {
97 break;
98 },
99 0b10000000 => {
100 mask += 1;
101 break;
102 },
103 0b11000000 => {
104 mask += 2;
105 break;
106 },
107 0b11100000 => {
108 mask += 3;
109 break;
110 },
111 0b11110000 => {
112 mask += 4;
113 break;
114 },
115 0b11111000 => {
116 mask += 5;
117 break;
118 },
119 0b11111100 => {
120 mask += 6;
121 break;
122 },
123 0b11111110 => {
124 mask += 7;
125 break;
126 },
127 0b11111111 => {
128 mask += 8;
129 },
130 _ => return 0,
131 }
132 }
133 while let Some(&n) = it.next() {
134 if n != 0 {
135 return 0;
136 }
137 }
138 mask
139}
140
141#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
145pub struct LlAddr {
146 bytes: [u8; 6],
147}
148
149impl LlAddr {
150 pub fn new(a: u8, b: u8, c: u8, d: u8, e: u8, f: u8) -> LlAddr {
162 LlAddr { bytes: [a,b,c,d,e,f] }
163 }
164
165 pub fn as_bytes(&self) -> &[u8; 6] {
175 &self.bytes
176 }
177
178 pub fn oui(&self) -> i32 {
189 ((self.bytes[0] as i32 * 256 + self.bytes[1] as i32) * 256 + self.bytes[2] as i32)
190 }
191}
192
193impl AddAssign<i64> for LlAddr {
194 fn add_assign(&mut self, rhs: i64) {
195 add_assign(&mut self.bytes, rhs)
196 }
197}
198
199impl SubAssign<i64> for LlAddr {
200 fn sub_assign(&mut self, rhs: i64) {
201 sub_assign(&mut self.bytes, rhs)
202 }
203}
204
205impl fmt::Display for LlAddr {
206 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
207 write!(f, "{:02X}:{:02X}:{:02X}:{:02X}:{:02X}:{:02X}",
208 self.bytes[0], self.bytes[1], self.bytes[2],
209 self.bytes[3], self.bytes[4], self.bytes[5])
210 }
211}
212
213impl fmt::Debug for LlAddr {
214 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
215 write!(f, "{}", self)
216 }
217}
218
219impl From<[u8; 6]> for LlAddr {
220 fn from(bytes: [u8; 6]) -> Self {
221 LlAddr { bytes: bytes }
222 }
223}
224
225#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
227pub struct IpAddrV4 {
228 bytes: [u8; 4],
229}
230
231impl IpAddrV4 {
232 pub fn new(a: u8, b: u8, c: u8, d: u8) -> IpAddrV4 {
243 IpAddrV4 { bytes: [a,b,c,d] }
244 }
245
246 pub fn any() -> IpAddrV4 {
256 IpAddrV4 { bytes: [0; 4] }
257 }
258
259 pub fn loopback() -> IpAddrV4 {
269 IpAddrV4::new(127,0,0,1)
270 }
271
272 pub fn is_unspecified(&self) -> bool {
281 self.bytes.iter().all(|&x| x == 0)
282 }
283
284 pub fn is_loopback(&self) -> bool {
293 (self.bytes[0] & 0xFF) == 0x7F
294 }
295
296 pub fn is_class_a(&self) -> bool {
309 (self.bytes[0] & 0x80) == 0
310 }
311
312 pub fn is_class_b(&self) -> bool {
325 (self.bytes[0] & 0xC0) == 0x80
326 }
327
328 pub fn is_class_c(&self) -> bool {
341 (self.bytes[0] & 0xE0) == 0xC0
342 }
343
344 pub fn is_private(&self) -> bool {
359 self.is_class_a() || self.is_class_b() || self.is_class_c()
360 }
361
362 pub fn is_multicast(&self) -> bool {
375 (self.bytes[0] & 0xF0) == 0xE0
376 }
377
378 pub fn is_link_local(&self) -> bool {
391 self.bytes[0] == 0xA9 && self.bytes[1] == 0xFE
392 }
393
394 pub fn as_bytes(&self) -> &[u8; 4] {
403 &self.bytes
404 }
405
406 pub fn to_u32(&self) -> u32 {
415 ((((((self.bytes[0] as u32) << 8)
416 + self.bytes[1] as u32) << 8)
417 + self.bytes[2] as u32) << 8)
418 + self.bytes[3] as u32
419 }
420}
421
422impl AddAssign<i64> for IpAddrV4 {
423 fn add_assign(&mut self, rhs: i64) {
424 *self = Self::from(self.to_u32() + rhs as u32);
425 }
426}
427
428impl SubAssign<i64> for IpAddrV4 {
429 fn sub_assign(&mut self, rhs: i64) {
430 *self = Self::from(self.to_u32() - rhs as u32);
431 }
432}
433
434impl fmt::Display for IpAddrV4 {
435 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
436 write!(f, "{}.{}.{}.{}", self.bytes[0], self.bytes[1], self.bytes[2], self.bytes[3])
437 }
438}
439
440impl fmt::Debug for IpAddrV4 {
441 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
442 write!(f, "{}", self)
443 }
444}
445
446impl From<u32> for IpAddrV4 {
447 fn from(mut addr: u32) -> Self {
448 let d = (addr & 0xFF) as u8;
449 addr >>= 8;
450 let c = (addr & 0xFF) as u8;
451 addr >>= 8;
452 let b = (addr & 0xFF) as u8;
453 addr >>= 8;
454 IpAddrV4::new(addr as u8, b, c, d)
455 }
456}
457
458impl From<[u8; 4]> for IpAddrV4 {
459 fn from(bytes: [u8; 4]) -> Self {
460 IpAddrV4 { bytes: bytes }
461 }
462}
463
464#[derive(Default, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
466pub struct IpAddrV6 {
467 scope_id: u32,
468 bytes: [u8; 16],
469}
470
471impl IpAddrV6 {
472 pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> IpAddrV6 {
483 let ar = [ a.to_be(), b.to_be(), c.to_be(), d.to_be(), e.to_be(), f.to_be(), g.to_be(), h.to_be() ];
484 IpAddrV6::from(unsafe { mem::transmute(ar) }, 0)
485 }
486
487 pub fn with_scope_id(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16, scope_id: u32) -> IpAddrV6 {
498 let ar = [ a.to_be(), b.to_be(), c.to_be(), d.to_be(), e.to_be(), f.to_be(), g.to_be(), h.to_be() ];
499 IpAddrV6::from(unsafe { mem::transmute(ar) }, scope_id)
500 }
501
502 pub fn any() -> IpAddrV6 {
512 IpAddrV6 { scope_id: 0, bytes: [0; 16] }
513 }
514
515 pub fn loopback() -> IpAddrV6 {
525 IpAddrV6 { scope_id: 0, bytes: [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1] }
526 }
527
528 pub fn from(bytes: [u8; 16], scope_id: u32) -> IpAddrV6 {
538 IpAddrV6 { scope_id: scope_id, bytes: bytes }
539 }
540
541 pub fn get_scope_id(&self) -> u32 {
551 self.scope_id
552 }
553
554 pub fn set_scope_id(&mut self, scope_id: u32) {
567 self.scope_id = scope_id
568 }
569
570 pub fn is_unspecified(&self) -> bool {
572 self.bytes.iter().all(|&x| x == 0)
573 }
574
575 pub fn is_loopback(&self) -> bool {
577 (self.bytes[0] == 0 && self.bytes[1] == 0 && self.bytes[2] == 0 && self.bytes[3] == 0 &&
578 self.bytes[4] == 0 && self.bytes[5] == 0 && self.bytes[6] == 0 && self.bytes[7] == 0 &&
579 self.bytes[8] == 0 && self.bytes[9] == 0 && self.bytes[10] == 0 && self.bytes[11] == 0 &&
580 self.bytes[12] == 0 && self.bytes[13] == 0 && self.bytes[14] == 0 && self.bytes[15] == 1)
581 }
582
583 pub fn is_link_local(&self) -> bool {
585 self.bytes[0] == 0xFE && (self.bytes[1] & 0xC0) == 0x80
586 }
587
588 pub fn is_site_local(&self) -> bool {
590 self.bytes[0] == 0xFE && (self.bytes[1] & 0xC0) == 0xC0
591 }
592
593 pub fn is_multicast(&self) -> bool {
595 self.bytes[0] == 0xFF
596 }
597
598 pub fn is_multicast_global(&self) -> bool {
600 self.bytes[0] == 0xFF && (self.bytes[1] & 0x0F) == 0x0E
601 }
602
603 pub fn is_multicast_link_local(&self) -> bool {
605 self.bytes[0] == 0xFF && (self.bytes[1] & 0x0F) == 0x02
606 }
607
608 pub fn is_multicast_node_local(&self) -> bool {
610 self.bytes[0] == 0xFF && (self.bytes[1] & 0x0F) == 0x01
611 }
612
613 pub fn is_multicast_org_local(&self) -> bool {
615 self.bytes[0] == 0xFF && (self.bytes[1] & 0x0F) == 0x08
616 }
617
618 pub fn is_multicast_site_local(&self) -> bool {
620 self.bytes[0] == 0xFF && (self.bytes[1] & 0x0F) == 0x05
621 }
622
623 pub fn is_v4_mapped(&self) -> bool {
625 (self.bytes[0] == 0 && self.bytes[1] == 0 && self.bytes[2] == 0 && self.bytes[3] == 0 &&
626 self.bytes[4] == 0 && self.bytes[5] == 0 && self.bytes[6] == 0 && self.bytes[7] == 0 &&
627 self.bytes[8] == 0 && self.bytes[9] == 0 && self.bytes[10] == 0xFF && self.bytes[11] == 0xFF)
628 }
629
630 pub fn is_v4_compatible(&self) -> bool {
632 ((self.bytes[0] == 0 && self.bytes[1] == 0 && self.bytes[2] == 0 && self.bytes[3] == 0 &&
633 self.bytes[4] == 0 && self.bytes[5] == 0 && self.bytes[6] == 0 && self.bytes[7] == 0 &&
634 self.bytes[8] == 0 && self.bytes[9] == 0 && self.bytes[10] == 0 && self.bytes[11] == 0)
635 && !(self.bytes[12] == 0 && self.bytes[13] == 0 && self.bytes[14] == 0
636 && (self.bytes[15] == 0 || self.bytes[15] == 1)))
637 }
638
639 pub fn as_bytes(&self) -> &[u8; 16] {
641 &self.bytes
642 }
643
644 pub fn to_v4(&self) -> Option<IpAddrV4> {
646 if self.is_v4_mapped() || self.is_v4_compatible() {
647 Some(IpAddrV4 { bytes: [ self.bytes[12], self.bytes[13], self.bytes[14], self.bytes[15] ] })
648 } else {
649 None
650 }
651 }
652
653 pub fn v4_mapped(addr: &IpAddrV4) -> Self {
657 IpAddrV6 {
658 scope_id: 0,
659 bytes: [0,0,0,0,0,0,0,0,0,0,0xFF,0xFF,
660 addr.bytes[0], addr.bytes[1], addr.bytes[2], addr.bytes[3]]
661 }
662 }
663
664 pub fn v4_compatible(addr: &IpAddrV4) -> Option<Self> {
668 if addr.bytes[0] == 0 && addr.bytes[1] == 0 && addr.bytes[2] == 0
669 && (addr.bytes[3] == 0 || addr.bytes[3] == 1)
670 {
671 None
672 } else {
673 Some(IpAddrV6 {
674 scope_id: 0,
675 bytes: [0,0,0,0,0,0,0,0,0,0,0,0,
676 addr.bytes[0], addr.bytes[1], addr.bytes[2], addr.bytes[3]]
677 })
678 }
679 }
680}
681
682impl AddAssign<i64> for IpAddrV6 {
683 fn add_assign(&mut self, rhs: i64) {
684 add_assign(&mut self.bytes, rhs)
685 }
686}
687
688impl SubAssign<i64> for IpAddrV6 {
689 fn sub_assign(&mut self, rhs: i64) {
690 sub_assign(&mut self.bytes, rhs)
691 }
692}
693
694impl fmt::Display for IpAddrV6 {
695 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
696 fmt_v6(&self.bytes, f)
697 }
698}
699
700impl fmt::Debug for IpAddrV6 {
701 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
702 write!(f, "{}", self)
703 }
704}
705
706impl From<[u8; 16]> for IpAddrV6 {
707 fn from(bytes: [u8; 16]) -> Self {
708 IpAddrV6 { scope_id: 0, bytes: bytes }
709 }
710}
711
712#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
714pub enum IpAddr {
715 V4(IpAddrV4),
716 V6(IpAddrV6),
717}
718
719impl IpAddr {
720 pub fn is_unspecified(&self) -> bool {
722 match self {
723 &IpAddr::V4(ref addr) => addr.is_unspecified(),
724 &IpAddr::V6(ref addr) => addr.is_unspecified(),
725 }
726 }
727
728 pub fn is_loopback(&self) -> bool {
730 match self {
731 &IpAddr::V4(ref addr) => addr.is_loopback(),
732 &IpAddr::V6(ref addr) => addr.is_loopback(),
733 }
734 }
735
736 pub fn is_multicast(&self) -> bool {
738 match self {
739 &IpAddr::V4(ref addr) => addr.is_multicast(),
740 &IpAddr::V6(ref addr) => addr.is_multicast(),
741 }
742 }
743
744 pub fn as_bytes(&self) -> &[u8] {
746 match self {
747 &IpAddr::V4(ref addr) => addr.as_bytes(),
748 &IpAddr::V6(ref addr) => addr.as_bytes(),
749 }
750 }
751}
752
753impl AddAssign<i64> for IpAddr {
754 fn add_assign(&mut self, rhs: i64) {
755 match self {
756 &mut IpAddr::V4(ref mut addr) => addr.add_assign(rhs),
757 &mut IpAddr::V6(ref mut addr) => addr.add_assign(rhs),
758 }
759 }
760}
761
762impl SubAssign<i64> for IpAddr {
763 fn sub_assign(&mut self, rhs: i64) {
764 match self {
765 &mut IpAddr::V4(ref mut addr) => addr.sub_assign(rhs),
766 &mut IpAddr::V6(ref mut addr) => addr.sub_assign(rhs),
767 }
768 }
769}
770
771impl fmt::Display for IpAddr {
772 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
773 match self {
774 &IpAddr::V4(ref addr) => write!(f, "{}", addr),
775 &IpAddr::V6(ref addr) => write!(f, "{}", addr),
776 }
777 }
778}
779
780impl fmt::Debug for IpAddr {
781 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
782 write!(f, "{}", self)
783 }
784}
785
786pub struct PrefixIpAddrV4 {
788 bytes: [u8; 4],
789 len: u8,
790}
791
792impl PrefixIpAddrV4 {
793 fn masking(lhs: IpAddrV4, rhs: IpAddrV4) -> [u8; 4] {
794 unsafe {
795 let lhs: u32 = mem::transmute(lhs);
796 let rhs: u32 = mem::transmute(rhs);
797 mem::transmute(lhs & rhs)
798 }
799 }
800
801 pub fn new(addr: IpAddrV4, netmask: IpAddrV4) -> Option<PrefixIpAddrV4> {
815 let len = netmask_len(&netmask.bytes);
816 debug_assert!(len <= 32);
817 if len != 0 {
818 Some(PrefixIpAddrV4 {
819 bytes: Self::masking(addr, netmask),
820 len: len,
821 })
822 } else {
823 None
824 }
825 }
826
827 pub fn from(addr: IpAddrV4, len: u8) -> PrefixIpAddrV4 {
838 assert!(0 < len && len <= 32);
839 PrefixIpAddrV4 {
840 bytes: Self::masking(addr, (u32::max_value() << (32 - len)).into()),
841 len: len,
842 }
843 }
844
845 pub fn network(&self) -> IpAddrV4 {
856 self.bytes.into()
857 }
858
859 pub fn netmask(&self) -> IpAddrV4 {
870 (u32::max_value() << (32 - self.len)).into()
871 }
872
873 pub fn netmask_len(&self) -> u8 {
875 self.len
876 }
877}
878
879impl fmt::Display for PrefixIpAddrV4 {
880 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
881 write!(f, "{}.{}.{}.{}/{}", self.bytes[0], self.bytes[1], self.bytes[2], self.bytes[3], self.len)
882 }
883}
884
885impl fmt::Debug for PrefixIpAddrV4 {
886 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
887 write!(f, "{}", self)
888 }
889}
890
891pub struct PrefixIpAddrV6 {
893 bytes: [u8; 16],
894 len: u8,
895}
896
897impl PrefixIpAddrV6 {
898 fn masking(lhs: [u8; 16], rhs: [u8; 16]) -> [u8; 16] {
899 unsafe {
900 let lhs: [u64; 2] = mem::transmute(lhs);
901 let rhs: [u64; 2] = mem::transmute(rhs);
902 mem::transmute([lhs[0] & rhs[0], lhs[1] & rhs[1]])
903 }
904 }
905
906 fn make_netmask(len: u8) -> [u8; 16] {
907 let bytes = match len.cmp(&64) {
908 Ordering::Less => [(!((1u64 << (64 - len)) - 1)).to_be(), 0],
909 Ordering::Equal => [u64::max_value(), 0],
910 Ordering::Greater => [u64::max_value(), (!((1u64 << (128 - len)) - 1)).to_be()],
911 };
912 unsafe { mem::transmute(bytes) }
913 }
914
915 pub fn new(addr: IpAddrV6, netmask: IpAddrV6) -> Option<PrefixIpAddrV6> {
929 let len = netmask_len(&netmask.bytes);
930 debug_assert!(len <= 128);
931 if len != 0 {
932 Some(PrefixIpAddrV6 {
933 bytes: Self::masking(addr.bytes, netmask.bytes),
934 len: len,
935 })
936 } else {
937 None
938 }
939 }
940
941 pub fn from(addr: IpAddrV6, len: u8) -> PrefixIpAddrV6 {
953 assert!(0 < len && len <= 128);
954 PrefixIpAddrV6 {
955 bytes: Self::masking(addr.bytes, Self::make_netmask(len)),
956 len: len,
957 }
958 }
959
960 pub fn prefix(&self) -> IpAddrV6 {
971 self.bytes.into()
972 }
973
974 pub fn netmask(&self) -> IpAddrV6 {
985 Self::make_netmask(self.len).into()
986 }
987
988 pub fn netmask_len(&self) -> u8 {
990 self.len
991 }
992}
993
994impl fmt::Display for PrefixIpAddrV6 {
995 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
996 try!(fmt_v6(&self.bytes, f));
997 write!(f, "/{}", self.len)
998 }
999}
1000
1001impl fmt::Debug for PrefixIpAddrV6 {
1002 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1003 write!(f, "{}", self)
1004 }
1005}
1006
1007#[test]
1008fn test_lladdr() {
1009 assert_eq!(LlAddr::default().bytes, [0,0,0,0,0,0]);
1010 assert_eq!(LlAddr::new(1,2,3,4,5,6).bytes, [1,2,3,4,5,6]);
1011 assert!(LlAddr::new(1,2,3,4,5,6) == LlAddr::from([1,2,3,4,5,6]));
1012 assert!(LlAddr::new(1,2,3,4,5,6) < LlAddr::new(1,2,3,4,5,7));
1013 assert!(LlAddr::new(1,2,3,4,5,6) < LlAddr::new(1,2,3,4,6,0));
1014 assert!(LlAddr::new(1,2,3,4,5,6) < LlAddr::new(1,2,3,5,0,0));
1015 assert!(LlAddr::new(1,2,3,4,5,6) < LlAddr::new(1,2,4,0,0,0));
1016 assert!(LlAddr::new(1,2,3,4,5,6) < LlAddr::new(1,3,0,0,0,0));
1017 assert!(LlAddr::new(1,2,3,4,5,6) < LlAddr::new(2,0,0,0,0,0));
1018}
1019
1020#[test]
1021fn test_lladdr_format() {
1022 assert_eq!(format!("{}", LlAddr::new(1,2,3,4,5,6)), "01:02:03:04:05:06");
1023 assert_eq!(format!("{}", LlAddr::new(0xAA,0xBB,0xCC,0xDD,0xEE,0xFF)), "AA:BB:CC:DD:EE:FF");
1024}
1025
1026#[test]
1027fn test_ipaddr_v4() {
1028 assert_eq!(IpAddrV4::default().bytes, [0,0,0,0]);
1029 assert_eq!(IpAddrV4::new(1,2,3,4).bytes, [1,2,3,4]);
1030 assert_eq!(IpAddrV4::new(1,2,3,4), IpAddrV4::from([1,2,3,4]));
1031 assert!(IpAddrV4::new(1,2,3,4) < IpAddrV4::new(1,2,3,5));
1032 assert!(IpAddrV4::new(1,2,3,4) < IpAddrV4::new(1,2,4,0));
1033 assert!(IpAddrV4::new(1,2,3,4) < IpAddrV4::new(1,3,0,0));
1034 assert!(IpAddrV4::new(1,2,3,4) < IpAddrV4::new(2,0,0,0));
1035}
1036
1037#[test]
1038fn test_ipaddr_v4_format() {
1039 assert_eq!(format!("{}", IpAddrV4::any()), "0.0.0.0");
1040 assert_eq!(format!("{}", IpAddrV4::loopback()), "127.0.0.1");
1041}
1042
1043#[test]
1044fn test_ipaddr_v4_add() {
1045 let mut a = IpAddrV4::new(192,168,0,1);
1046 a += 1;
1047 assert_eq!(a, IpAddrV4::new(192,168,0,2));
1048 a += 100;
1049 assert_eq!(a, IpAddrV4::new(192,168,0,102));
1050 a += 256*10;
1051 assert_eq!(a, IpAddrV4::new(192,168,10,102));
1052}
1053
1054#[test]
1055fn test_ipaddr_v4_sub() {
1056 let mut a = IpAddrV4::new(192,168,0,1);
1057 a -= 1;
1058 assert_eq!(a, IpAddrV4::new(192,168,0,0));
1059 a -= 100;
1060 assert_eq!(a, IpAddrV4::new(192,167,255,156));
1061 a -= 256*10;
1062 assert_eq!(a, IpAddrV4::new(192,167,245,156));
1063}
1064
1065#[test]
1066fn test_ipaddr_v6() {
1067 assert_eq!(IpAddrV6::default().bytes, [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]);
1068 assert_eq!(IpAddrV6::new(0x0102,0x0304,0x0506,0x0708,0x090a,0x0b0c,0x0d0e,0x0f10).bytes,
1069 [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]);
1070 assert_eq!(IpAddrV6::new(0x0102,0x0304,0x0506,0x0708,0x090a,0x0b0c,0x0d0e,0x0f10),
1071 IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 0));
1072 assert_eq!(IpAddrV6::with_scope_id(0,0,0,0,0,0,0,0,100).get_scope_id(), 100);
1073 assert!(IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 0) <
1074 IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,17], 0));
1075 assert!(IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 0) <
1076 IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,14,16,00], 0));
1077 assert!(IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16], 0) <
1078 IpAddrV6::from([1,2,3,4,5,6,7,8,9,10,11,12,13,15,00,00], 0));
1079}
1080
1081#[test]
1082fn test_ipaddr_v6_format() {
1083 assert_eq!(format!("{}", IpAddrV6::any()), "::");
1084 assert_eq!(format!("{}", IpAddrV6::loopback()), "::1");
1085 assert_eq!(format!("{}", IpAddrV6::new(1,2,3,4,5,6,7,8)), "1:2:3:4:5:6:7:8");
1086 assert_eq!(format!("{}", IpAddrV6::new(0,2,3,4,5,6,7,8)), "::2:3:4:5:6:7:8");
1087 assert_eq!(format!("{}", IpAddrV6::new(1,2,3,4,5,6,7,0)), "1:2:3:4:5:6:7::");
1088 assert_eq!(format!("{}", IpAddrV6::new(1,2,3,4,0,6,7,8)), "1:2:3:4::6:7:8");
1089 assert_eq!(format!("{}", IpAddrV6::new(1,0,0,0,0,0,0,8)), "1::8");
1090}
1091
1092#[test]
1093fn test_add_assign() {
1094 let mut a = [0,0];
1095 add_assign(&mut a, 0xFF);
1096 assert_eq!(&a, &[0, 0xFF]);
1097 add_assign(&mut a, 0x01);
1098 assert_eq!(&a, &[1, 0]);
1099 add_assign(&mut a, 0x101);
1100 assert_eq!(&a, &[2, 1]);
1101}
1102
1103#[test]
1104#[should_panic]
1105fn test_add_assign_overflow() {
1106 let mut a = [0xFF, 0xFF];
1107 add_assign(&mut a, 1);
1108}
1109
1110#[test]
1111fn test_sub_assign() {
1112 let mut a = [0xFF, 0xFF];
1113 sub_assign(&mut a, 0xFF);
1114 assert_eq!(&a, &[0xFF, 0]);
1115 sub_assign(&mut a, 0x01);
1116 assert_eq!(&a, &[0xFE, 0xFF]);
1117 sub_assign(&mut a, 0x101);
1118 assert_eq!(&a, &[0xFD, 0xFE]);
1119}
1120
1121#[test]
1122#[should_panic]
1123fn test_sub_assign_underflow() {
1124 let mut a = [0, 0];
1125 sub_assign(&mut a, 1);
1126}
1127
1128#[test]
1129fn test_ipaddr_as_bytes() {
1130 let bytes = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
1131 let v4 = IpAddr::V4(IpAddrV4::new(1,2,3,4));
1132 assert!(v4.as_bytes() == &bytes[..4]);
1133 assert!(v4.as_bytes() != &bytes[..5]);
1134 assert!(v4.as_bytes() != &bytes[1..5]);
1135
1136 let v6 = IpAddr::V6(IpAddrV6::from(bytes.clone(), 0));
1137 assert!(v6.as_bytes() == &bytes[..]);
1138 assert!(v6.as_bytes() != v4.as_bytes());
1139}
1140
1141#[test]
1142fn test_netmask_len() {
1143 assert_eq!(netmask_len(&[255,255,255,0]), 24);
1144 assert_eq!(netmask_len(&[255,255,255,255]), 32);
1145 assert_eq!(netmask_len(&[255,255,254,0]), 23);
1146 assert_eq!(netmask_len(&[255,255,255,254]), 31);
1147 assert_eq!(netmask_len(&[128,0,0,0]), 1);
1148
1149 assert_eq!(netmask_len(&[0,0,0,0]), 0);
1150 assert_eq!(netmask_len(&[1,1,1,1]), 0);
1151 assert_eq!(netmask_len(&[128,1,1,1]), 0);
1152}
1153
1154#[test]
1155fn test_prefix_ipaddr_v4() {
1156 let ip = PrefixIpAddrV4::new(IpAddrV4::new(192,168,0,1), IpAddrV4::new(255,255,255,0)).unwrap();
1157 assert_eq!(ip.network(), IpAddrV4::new(192,168,0,0));
1158 assert_eq!(ip.netmask(), IpAddrV4::new(255,255,255,0));
1159 assert_eq!(ip.netmask_len(), 24);
1160
1161 let ip = PrefixIpAddrV4::new(IpAddrV4::new(192,168,255,1), IpAddrV4::new(255,255,240,0)).unwrap();
1162 assert_eq!(ip.network(), IpAddrV4::new(192,168,240,0));
1163 assert_eq!(ip.netmask(), IpAddrV4::new(255,255,240,0));
1164 assert_eq!(ip.netmask_len(), 20);
1165}
1166
1167#[test]
1168#[should_panic]
1169fn test_prefix_ipaddr_v4_from_panic() {
1170 PrefixIpAddrV4::from(IpAddrV4::loopback(), 0);
1171}
1172
1173#[test]
1174fn test_prefix_ipaddr_v4_format() {
1175 let ip = PrefixIpAddrV4::new(IpAddrV4::new(192,168,0,1), IpAddrV4::new(255,255,255,0)).unwrap();
1176 assert_eq!(format!("{}", ip), "192.168.0.0/24");
1177}
1178
1179#[test]
1180fn test_prefix_ipaddr_v6_half() {
1181 let netmask = IpAddrV6::new(0xffff,0xffff,0xffff,0xffff,0,0,0,0);
1182 let ip = PrefixIpAddrV6::new(IpAddrV6::new(0x2001,0,0,0,0,0,0xdead,0xbeaf), netmask.clone()).unwrap();
1183 assert_eq!(ip.prefix(), IpAddrV6::new(0x2001,0,0,0,0,0,0,0));
1184 assert_eq!(ip.netmask(), netmask);
1185 assert_eq!(ip.netmask_len(), 64);
1186}
1187
1188#[test]
1189fn test_prefix_ipaddr_v6_long() {
1190 let netmask = IpAddrV6::new(0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xffff,0xfff0);
1191 let ip = PrefixIpAddrV6::new(IpAddrV6::new(0x2001,0,0,0,0,0,0xdead, 0xbeaf), netmask.clone()).unwrap();
1192 assert_eq!(ip.prefix(), IpAddrV6::new(0x2001,0,0,0,0,0,0xdead,0xbea0));
1193 assert_eq!(ip.netmask(), netmask);
1194 assert_eq!(ip.netmask_len(), 124);
1195}
1196
1197#[test]
1198fn test_prefix_ipaddr_v6_short() {
1199 let netmask = IpAddrV6::new(0xfe00, 0,0,0,0,0,0,0);
1200 let ip = PrefixIpAddrV6::new(IpAddrV6::new(0x2001,0,0,0,0,0,0xdead, 0xbeaf), netmask.clone()).unwrap();
1201 assert_eq!(ip.prefix(), IpAddrV6::new(0x2000,0,0,0,0,0,0,0));
1202 assert_eq!(ip.netmask(), netmask);
1203 assert_eq!(ip.netmask_len(), 7);
1204}
1205
1206#[test]
1207#[should_panic]
1208fn test_prefix_ipaddr_v6_from_panic() {
1209 PrefixIpAddrV6::from(IpAddrV6::loopback(), 0);
1210}
1211
1212#[test]
1213fn test_prefix_ipaddr_v6_format() {
1214 let ip = PrefixIpAddrV6::from(IpAddrV6::loopback(), 64);
1215 assert_eq!(format!("{}", ip), "::/64");
1216
1217 let ip = PrefixIpAddrV6::from(IpAddrV6::new(0xdead,0xbeaf,0,0,0,0,0,0), 32);
1218 assert_eq!(format!("{}", ip), "dead:beaf::/32");
1219}