netaddr2/
netv6addr.rs

1use crate::traits::Mask;
2use std::net::Ipv6Addr;
3
4/// A structure representing an IPv6 network.
5///
6/// Internally, this structure includes two values; an `Ipv6Addr`
7/// representing the network address (`addr`), and another
8/// representing the netmask (`mask`).
9#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
10pub struct Netv6Addr {
11	addr: Ipv6Addr,
12	mask: Ipv6Addr,
13}
14
15impl Netv6Addr {
16	pub const fn mask(&self) -> Ipv6Addr {
17		self.mask
18	}
19
20	pub const fn addr(&self) -> Ipv6Addr {
21		self.addr
22	}
23
24	pub fn is_cidr(&self) -> bool {
25		let mask: u128 = self.mask.into();
26		let ones: u32 = mask.count_ones();
27		let cidr_mask: u128 = u128::max_value().checked_shl(128 - ones).unwrap_or(0);
28		mask == cidr_mask
29	}
30
31	/// Create a new `Netv6Addr` from the given `addr` and `mask`.
32	///
33	/// Masks the given `addr` value with the given `mask` before
34	/// the structure containing both is returned.
35	///
36	/// # Examples
37	///
38	/// ```rust
39	/// # use netaddr2::Netv6Addr;
40	/// # use std::net::Ipv6Addr;
41	/// let network = Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0x42);
42	/// let netmask = Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0);
43	/// let netaddr = Netv6Addr::new(network, netmask);
44	/// ```
45	pub fn new(addr: Ipv6Addr, mask: Ipv6Addr) -> Self {
46		let addr = addr.mask(&mask);
47		Self { addr, mask }
48	}
49}
50
51mod contains;
52mod display;
53mod from;
54mod fromstr;
55mod hash;
56mod merge;
57mod ord;
58mod partialord;
59
60#[cfg(feature = "serde")]
61mod de;
62#[cfg(feature = "serde")]
63mod ser;
64
65#[cfg(test)]
66mod tests {
67	use super::*;
68
69	mod mask {
70		use super::*;
71
72		#[test]
73		fn returns_mask_field() {
74			let netaddr: Netv6Addr = Netv6Addr {
75				mask: "ffff:ffff:ffff:ffff::0".parse().unwrap(),
76				addr: "2001:db8:dead:beef::0".parse().unwrap(),
77			};
78
79			assert_eq!(
80				netaddr.mask(),
81				"ffff:ffff:ffff:ffff::0".parse::<Ipv6Addr>().unwrap()
82			);
83		}
84	}
85
86	mod addr {
87		use super::*;
88
89		#[test]
90		fn returns_addr_field() {
91			let netaddr: Netv6Addr = Netv6Addr {
92				mask: "ffff:ffff:ffff:ffff::0".parse().unwrap(),
93				addr: "2001:db8:dead:beef::0".parse().unwrap(),
94			};
95
96			assert_eq!(
97				netaddr.addr(),
98				"2001:db8:dead:beef::0".parse::<Ipv6Addr>().unwrap()
99			);
100		}
101	}
102
103	mod is_cidr {
104		use super::*;
105
106		#[test]
107		fn non_cidr_returns_false() {
108			let netaddr: Netv6Addr = Netv6Addr {
109				mask: "ffff:ffff:ffff:7f7f::0".parse().unwrap(),
110				addr: "::".parse().unwrap(),
111			};
112
113			assert!(!netaddr.is_cidr());
114		}
115
116		#[test]
117		fn cidr_returns_true() {
118			let netaddr: Netv6Addr = Netv6Addr {
119				mask: "ffff:ffff:ffff:fffc::0".parse().unwrap(),
120				addr: "::".parse().unwrap(),
121			};
122
123			assert!(netaddr.is_cidr());
124		}
125	}
126
127	mod new {
128		use super::*;
129
130		#[test]
131		fn masks_addr() {
132			let addr: Ipv6Addr = "2001:db8:dead:beef::0".parse().unwrap();
133			let mask: Ipv6Addr = "ffff:ffff:ffff:ff00::0".parse().unwrap();
134
135			let netaddr: Netv6Addr = Netv6Addr::new(addr, mask);
136
137			assert_eq!(netaddr.mask(), mask);
138			assert_eq!(
139				netaddr.addr(),
140				"2001:db8:dead:be00::0".parse::<Ipv6Addr>().unwrap()
141			);
142		}
143	}
144}