1#![crate_type = "lib"]
4#![deny(
5 missing_debug_implementations,
6 unsafe_code,
7 unused_extern_crates,
8 unused_import_braces
9)]
10
11use std::{convert::TryFrom, fmt, net::IpAddr, str::FromStr};
12
13mod error;
14mod ipv4;
15mod ipv6;
16mod parse;
17mod size;
18
19pub use crate::error::{NetworkSizeError, IpNetworkError};
20pub use crate::ipv4::Ipv4NetworkIterator;
21pub use crate::ipv4::{ipv4_mask_to_prefix, Ipv4Network};
22pub use crate::ipv6::Ipv6NetworkIterator;
23pub use crate::ipv6::{ipv6_mask_to_prefix, Ipv6Network};
24pub use crate::size::NetworkSize;
25
26)]
29pub enum IpNetwork {
30 V4(Ipv4Network),
31 V6(Ipv6Network),
32}
33
34#[cfg(feature = "serde")]
35impl<'de> serde::Deserialize<'de> for IpNetwork {
36 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
37 where
38 D: serde::Deserializer<'de>,
39 {
40 let s = <String>::deserialize(deserializer)?;
41 IpNetwork::from_str(&s).map_err(serde::de::Error::custom)
42 }
43}
44
45#[cfg(feature = "serde")]
46impl serde::Serialize for IpNetwork {
47 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
48 where
49 S: serde::Serializer,
50 {
51 serializer.collect_str(self)
52 }
53}
54
55#[cfg(feature = "schemars")]
56impl schemars::JsonSchema for IpNetwork {
57 fn schema_name() -> String {
58 "IpNetwork".to_string()
59 }
60
61 fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
62 schemars::schema::SchemaObject {
63 metadata: Some(
64 schemars::schema::Metadata {
65 ..Default::default()
66 }
67 .into(),
68 ),
69 subschemas: Some(
70 schemars::schema::SubschemaValidation {
71 one_of: Some(vec![
72 schemars::schema::SchemaObject {
73 metadata: Some(
74 schemars::schema::Metadata {
75 title: Some("v4".to_string()),
76 ..Default::default()
77 }
78 .into(),
79 ),
80 subschemas: Some(
81 schemars::schema::SubschemaValidation {
82 all_of: Some(vec![gen.subschema_for::<Ipv4Network>()]),
83 ..Default::default()
84 }
85 .into(),
86 ),
87 ..Default::default()
88 }
89 .into(),
90 schemars::schema::SchemaObject {
91 metadata: Some(
92 schemars::schema::Metadata {
93 title: Some("v6".to_string()),
94 ..Default::default()
95 }
96 .into(),
97 ),
98 subschemas: Some(
99 schemars::schema::SubschemaValidation {
100 all_of: Some(vec![gen.subschema_for::<Ipv6Network>()]),
101 ..Default::default()
102 }
103 .into(),
104 ),
105 ..Default::default()
106 }
107 .into(),
108 ]),
109 ..Default::default()
110 }
111 .into(),
112 ),
113 extensions: [("x-rust-type".to_string(), "ipnetwork::IpNetwork".into())]
114 .iter()
115 .cloned()
116 .collect(),
117 ..Default::default()
118 }
119 .into()
120 }
121}
122
123impl IpNetwork {
124 pub fn new(ip: IpAddr, prefix: u8) -> Result<IpNetwork, IpNetworkError> {
129 match ip {
130 IpAddr::V4(a) => Ok(IpNetwork::V4(Ipv4Network::new(a, prefix)?)),
131 IpAddr::V6(a) => Ok(IpNetwork::V6(Ipv6Network::new(a, prefix)?)),
132 }
133 }
134
135 pub fn with_netmask(netaddr: IpAddr, netmask: IpAddr) -> Result<Self, IpNetworkError> {
139 let prefix = ip_mask_to_prefix(netmask)?;
140 Self::new(netaddr, prefix)
141 }
142
143 pub fn ip(&self) -> IpAddr {
145 match *self {
146 IpNetwork::V4(ref a) => IpAddr::V4(a.ip()),
147 IpNetwork::V6(ref a) => IpAddr::V6(a.ip()),
148 }
149 }
150
151 pub fn prefix(&self) -> u8 {
164 match *self {
165 IpNetwork::V4(ref a) => a.prefix(),
166 IpNetwork::V6(ref a) => a.prefix(),
167 }
168 }
169
170 pub fn network(&self) -> IpAddr {
185 match *self {
186 IpNetwork::V4(ref a) => IpAddr::V4(a.network()),
187 IpNetwork::V6(ref a) => IpAddr::V6(a.network()),
188 }
189 }
190
191 pub fn broadcast(&self) -> IpAddr {
204 match *self {
205 IpNetwork::V4(ref a) => IpAddr::V4(a.broadcast()),
206 IpNetwork::V6(ref a) => IpAddr::V6(a.broadcast()),
207 }
208 }
209
210 pub fn mask(&self) -> IpAddr {
230 match *self {
231 IpNetwork::V4(ref a) => IpAddr::V4(a.mask()),
232 IpNetwork::V6(ref a) => IpAddr::V6(a.mask()),
233 }
234 }
235
236 pub fn is_ipv4(&self) -> bool {
249 match *self {
250 IpNetwork::V4(_) => true,
251 IpNetwork::V6(_) => false,
252 }
253 }
254
255 pub fn is_ipv6(&self) -> bool {
268 match *self {
269 IpNetwork::V4(_) => false,
270 IpNetwork::V6(_) => true,
271 }
272 }
273
274 #[inline]
295 pub fn contains(&self, ip: IpAddr) -> bool {
296 match (*self, ip) {
297 (IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
298 (IpNetwork::V6(net), IpAddr::V6(ip)) => net.contains(ip),
299 _ => false,
300 }
301 }
302
303 pub fn size(&self) -> NetworkSize {
315 match *self {
316 IpNetwork::V4(ref ip) => NetworkSize::V4(ip.size()),
317 IpNetwork::V6(ref ip) => NetworkSize::V6(ip.size()),
318 }
319 }
320
321 pub fn iter(&self) -> IpNetworkIterator {
325 let inner = match self {
326 IpNetwork::V4(ip) => IpNetworkIteratorInner::V4(ip.iter()),
327 IpNetwork::V6(ip) => IpNetworkIteratorInner::V6(ip.iter()),
328 };
329 IpNetworkIterator { inner }
330 }
331}
332
333impl FromStr for IpNetwork {
348 type Err = IpNetworkError;
349 fn from_str(s: &str) -> Result<Self, Self::Err> {
350 if let Ok(net) = Ipv4Network::from_str(s) {
351 Ok(IpNetwork::V4(net))
352 } else if let Ok(net) = Ipv6Network::from_str(s) {
353 Ok(IpNetwork::V6(net))
354 } else {
355 Err(IpNetworkError::InvalidAddr(s.to_string()))
356 }
357 }
358}
359
360impl TryFrom<&str> for IpNetwork {
361 type Error = IpNetworkError;
362
363 fn try_from(s: &str) -> Result<Self, Self::Error> {
364 IpNetwork::from_str(s)
365 }
366}
367
368impl From<Ipv4Network> for IpNetwork {
369 fn from(v4: Ipv4Network) -> IpNetwork {
370 IpNetwork::V4(v4)
371 }
372}
373
374impl From<Ipv6Network> for IpNetwork {
375 fn from(v6: Ipv6Network) -> IpNetwork {
376 IpNetwork::V6(v6)
377 }
378}
379
380impl From<IpAddr> for IpNetwork {
381 fn from(addr: IpAddr) -> IpNetwork {
382 match addr {
383 IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::from(a)),
384 IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::from(a)),
385 }
386 }
387}
388
389impl fmt::Display for IpNetwork {
390 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
391 match *self {
392 IpNetwork::V4(net) => net.fmt(f),
393 IpNetwork::V6(net) => net.fmt(f),
394 }
395 }
396}
397
398#[derive(#[automatically_derived]
impl ::core::clone::Clone for IpNetworkIteratorInner {
#[inline]
fn clone(&self) -> IpNetworkIteratorInner {
match self {
IpNetworkIteratorInner::V4(__self_0) =>
IpNetworkIteratorInner::V4(::core::clone::Clone::clone(__self_0)),
IpNetworkIteratorInner::V6(__self_0) =>
IpNetworkIteratorInner::V6(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IpNetworkIteratorInner {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
IpNetworkIteratorInner::V4(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "V4",
&__self_0),
IpNetworkIteratorInner::V6(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "V6",
&__self_0),
}
}
}Debug)]
399enum IpNetworkIteratorInner {
400 V4(Ipv4NetworkIterator),
401 V6(Ipv6NetworkIterator),
402}
403
404#[derive(#[automatically_derived]
impl ::core::clone::Clone for IpNetworkIterator {
#[inline]
fn clone(&self) -> IpNetworkIterator {
IpNetworkIterator { inner: ::core::clone::Clone::clone(&self.inner) }
}
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for IpNetworkIterator {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"IpNetworkIterator", "inner", &&self.inner)
}
}Debug)]
405pub struct IpNetworkIterator {
406 inner: IpNetworkIteratorInner,
407}
408
409impl Iterator for IpNetworkIterator {
410 type Item = IpAddr;
411 fn next(&mut self) -> Option<IpAddr> {
412 match &mut self.inner {
413 IpNetworkIteratorInner::V4(iter) => iter.next().map(IpAddr::V4),
414 IpNetworkIteratorInner::V6(iter) => iter.next().map(IpAddr::V6),
415 }
416 }
417}
418
419impl IntoIterator for &'_ IpNetwork {
420 type IntoIter = IpNetworkIterator;
421 type Item = IpAddr;
422 fn into_iter(self) -> IpNetworkIterator {
423 self.iter()
424 }
425}
426
427pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
430 match mask {
431 IpAddr::V4(mask) => ipv4_mask_to_prefix(mask),
432 IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
433 }
434}
435
436#[cfg(test)]
437mod test {
438 #[test]
439 #[cfg(feature = "serde")]
440 fn deserialize_from_serde_json_value() {
441 use super::*;
442 let network = IpNetwork::from_str("0.0.0.0/0").unwrap();
443 let val: serde_json::value::Value =
444 serde_json::from_str(&serde_json::to_string(&network).unwrap()).unwrap();
445 let _deser: IpNetwork = serde_json::from_value(val)
446 .expect("Fails to deserialize from json_value::value::Value");
447 }
448}