1use log::trace;
2use zerocopy::{NetworkEndian, U128, U32};
3
4use crate::types::BitSpan;
5
6pub trait AddressFamily:
15 std::fmt::Binary
16 + std::fmt::Debug
17 + std::hash::Hash
18 + std::fmt::Display
19 + Eq
20 + std::ops::BitAnd<Output = Self>
21 + std::ops::BitOr<Output = Self>
22 + std::ops::Shr<Self, Output = Self>
23 + std::ops::Shl<Output = Self>
24 + std::ops::Shl<Self, Output = Self>
25 + std::ops::Sub<Output = Self>
26 + Copy
27 + Ord
28 + zerocopy::FromBytes
29 + zerocopy::IntoBytes
30 + zerocopy::KnownLayout
31 + zerocopy::Immutable
32 + zerocopy::Unaligned
33{
34 const BITS: u8;
36
37 type Inner: Into<Self> + From<u32> + From<u8>;
39
40 type InnerIpAddr;
44
45 fn new(value: Self::Inner) -> Self {
46 value.into()
47 }
48
49 fn from_ipaddr(ip_addr: Self::InnerIpAddr) -> Self;
50
51 fn from_u32(value: u32) -> Self;
52 fn from_u8(value: u8) -> Self;
53
54 fn zero() -> Self;
55
56 fn into_bit_span(net: Self, start_bit: u8, len: u8) -> BitSpan;
59
60 fn add_bit_span(self, len: u8, bs: BitSpan) -> (Self, u8);
62
63 fn truncate_to_len(self, len: u8) -> Self;
66
67 fn into_ipaddr(self) -> std::net::IpAddr;
69
70 fn dangerously_truncate_to_u32(self) -> u32;
73
74 fn checked_shr_or_zero(self, rhs: u32) -> Self;
79 fn checked_shl_or_zero(self, rhs: u32) -> Self;
80
81 fn checked_shr(self, rhs: u32) -> Option<Self::Inner>;
83 fn checked_shl(self, rhs: u32) -> Option<Self::Inner>;
84}
85
86pub type IPv4 = zerocopy::U32<NetworkEndian>;
90
91impl AddressFamily for IPv4 {
92 const BITS: u8 = 32;
93 type Inner = u32;
94 type InnerIpAddr = std::net::Ipv4Addr;
95
96 fn zero() -> Self {
97 0.into()
98 }
99
100 fn from_u8(value: u8) -> Self {
101 IPv4::from([0, 0, 0, value])
102 }
103
104 fn from_u32(value: u32) -> Self {
105 IPv4::from(value)
106 }
107
108 fn from_ipaddr(ip_addr: Self::InnerIpAddr) -> Self {
109 IPv4::from(ip_addr.octets())
110 }
111
112 fn into_bit_span(net: Self, start_bit: u8, len: u8) -> BitSpan {
113 BitSpan {
114 bits: ((net << <U32<NetworkEndian>>::from(start_bit as u32))
115 >> <U32<NetworkEndian>>::from(((32 - len) % 32) as u32))
116 .into(),
117 len,
118 }
119 }
120
121 fn add_bit_span(self, len: u8, bs: BitSpan) -> (U32<NetworkEndian>, u8) {
122 let res = self | (bs.bits << (32 - len - bs.len) as usize);
123 (res, len + bs.len)
124 }
125
126 fn into_ipaddr(self) -> std::net::IpAddr {
127 std::net::IpAddr::V4(std::net::Ipv4Addr::from(u32::from(self)))
128 }
129
130 fn dangerously_truncate_to_u32(self) -> u32 {
131 self.into()
133 }
134
135 fn truncate_to_len(self, len: u8) -> Self {
136 self & ((1_u32.rotate_right(len as u32)
137 ^ 1_u32.saturating_sub(len as u32))
138 .wrapping_sub(1)
139 ^ u32::MAX)
140 }
141
142 fn checked_shr_or_zero(self, rhs: u32) -> Self {
143 trace!("CHECKED_SHR_OR_ZERO {} >> {}", u32::from(self), rhs);
144 if rhs == 0 || rhs == 32 {
145 return 0.into();
146 }
147 self >> U32::<NetworkEndian>::from(rhs)
148 }
149
150 fn checked_shl_or_zero(self, rhs: u32) -> Self {
151 trace!("CHECKED_SHL_OR_ZERO {} >> {}", u32::from(self), rhs);
152 if rhs == 0 || rhs >= 32 {
153 return 0.into();
154 }
155 self << U32::<NetworkEndian>::from(rhs)
156 }
157
158 fn checked_shr(self, rhs: u32) -> Option<u32> {
159 u32::from(self).checked_shr(rhs)
160 }
161
162 fn checked_shl(self, rhs: u32) -> Option<u32> {
163 u32::from(self).checked_shl(rhs)
164 }
165}
166
167pub type IPv6 = U128<NetworkEndian>;
171
172impl AddressFamily for IPv6 {
173 const BITS: u8 = 128;
175 type Inner = u128;
176 type InnerIpAddr = std::net::Ipv6Addr;
177
178 fn zero() -> Self {
179 0.into()
180 }
181
182 fn from_ipaddr(ip_addr: Self::InnerIpAddr) -> Self {
183 IPv6::from(ip_addr.octets())
184 }
185
186 fn into_bit_span(net: Self, start_bit: u8, len: u8) -> BitSpan {
187 BitSpan {
188 bits: u128::from(
189 (net << <U128<NetworkEndian>>::from(start_bit as u128))
190 >> (<U128<NetworkEndian>>::from(128 - len as u128) % 128),
191 ) as u32,
192 len,
193 }
194 }
195
196 fn add_bit_span(self, len: u8, bs: BitSpan) -> (Self, u8) {
197 let res = self | ((bs.bits as u128) << (128 - len - bs.len) as usize);
198 (res, len + bs.len)
199 }
200
201 fn truncate_to_len(self, len: u8) -> Self {
202 self & ((1_u128.rotate_right(len as u32)
203 ^ 1_u128.saturating_sub(len as u128))
204 .wrapping_sub(1)
205 ^ u128::MAX)
206 }
207
208 fn into_ipaddr(self) -> std::net::IpAddr {
209 std::net::IpAddr::V6(std::net::Ipv6Addr::from(u128::from(self)))
210 }
211
212 fn dangerously_truncate_to_u32(self) -> u32 {
213 u128::from(self) as u32
215 }
216
217 fn checked_shr_or_zero(self, rhs: u32) -> Self {
218 if rhs == 0 || rhs == 128 {
219 return U128::from(0);
220 };
221
222 self >> U128::from(rhs as u128)
223 }
224
225 fn checked_shl_or_zero(self, rhs: u32) -> Self {
226 if rhs >= 128 {
227 return U128::from(0);
228 };
229
230 self << U128::from(rhs as u128)
231 }
232
233 fn checked_shr(self, rhs: u32) -> Option<u128> {
234 u128::from(self).checked_shr(rhs)
235 }
236
237 fn checked_shl(self, rhs: u32) -> Option<u128> {
238 u128::from(self).checked_shl(rhs)
239 }
240
241 fn from_u8(value: u8) -> Self {
242 IPv6::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, value])
243 }
244
245 fn from_u32(value: u32) -> Self {
246 (value as u128).into()
247 }
248}
249
250pub trait IntoIpAddr {
251 fn into_ipaddr(self) -> std::net::IpAddr;
252}
253
254impl IntoIpAddr for u32 {
255 fn into_ipaddr(self) -> std::net::IpAddr {
256 std::net::IpAddr::V4(std::net::Ipv4Addr::from(self))
257 }
258}
259
260impl IntoIpAddr for u128 {
261 fn into_ipaddr(self) -> std::net::IpAddr {
262 std::net::IpAddr::V6(std::net::Ipv6Addr::from(self))
263 }
264}