ip_network/
lib.rs

1//! IPv4 and IPv6 network structs.
2//!
3//! ## Optional features
4//!
5//! When using this crate, you can choose to compile with these features:
6//!
7//! * `serde` – for serialization and deserialization by [Serde framework](https://serde.rs).
8//! * `diesel` – support for [PostgreSQL CIDR type] with [Diesel ORM](https://diesel.rs).
9//! * `postgres` – support for [PostgreSQL CIDR type] with [postgres crate](https://github.com/sfackler/rust-postgres).
10//!
11//! ## Examples
12//!
13//! ```rust
14//! use std::net::Ipv4Addr;
15//! use ip_network::Ipv4Network;
16//!
17//! let ip_network = Ipv4Network::new(Ipv4Addr::new(192, 168, 1, 0), 24)?;
18//! assert_eq!(Ipv4Addr::new(192, 168, 1, 0), ip_network.network_address());
19//! assert_eq!(24, ip_network.netmask());
20//! assert_eq!(254, ip_network.hosts().len());
21//! assert_eq!("192.168.1.0/24", ip_network.to_string());
22//! # Ok::<(), ip_network::IpNetworkError>(())
23//! ```
24//!
25//! [PostgreSQL CIDR type]: https://www.postgresql.org/docs/current/datatype-net-types.html#DATATYPE-CIDR
26
27#[cfg(feature = "diesel")]
28#[macro_use]
29extern crate diesel;
30
31#[cfg(feature = "diesel")]
32/// Support for Diesel PostgreSQL CIDR type.
33pub mod diesel_support;
34mod helpers;
35mod ip_network;
36mod ipv4_network;
37mod ipv6_network;
38/// `Ipv4RangeIterator`, `Ipv4NetworkIterator`, and `Ipv6NetworkIterator`.
39pub mod iterator;
40#[cfg(any(feature = "diesel", feature = "postgres"))]
41mod postgres_common;
42#[cfg(feature = "postgres")]
43mod postgres_support;
44#[cfg(feature = "serde")]
45mod serde_support;
46
47use std::error::Error;
48use std::fmt;
49
50pub use self::ip_network::IpNetwork;
51pub use self::ipv4_network::Ipv4Network;
52pub use self::ipv6_network::{Ipv6MulticastScope, Ipv6Network};
53
54/// Errors when creating new IPv4 or IPv6 networks.
55#[derive(Debug, PartialEq)]
56pub enum IpNetworkError {
57    /// Network mask is bigger than possible for given IP version (32 for IPv4, 128 for IPv6).
58    NetmaskError(u8),
59    /// Host bits are set in given network IP address.
60    HostBitsSet,
61}
62
63impl Error for IpNetworkError {}
64
65impl fmt::Display for IpNetworkError {
66    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
67        let description = match *self {
68            IpNetworkError::NetmaskError(_) => "invalid netmask",
69            IpNetworkError::HostBitsSet => "IP network address has host bits set",
70        };
71        write!(fmt, "{}", description)
72    }
73}
74
75/// Errors from IPv4 or IPv6 network parsing.
76#[derive(Debug, PartialEq)]
77pub enum IpNetworkParseError {
78    /// Network mask is not valid integer between 0 and 255.
79    InvalidNetmaskFormat,
80    /// Network address has invalid format (not X/Y).
81    InvalidFormatError,
82    /// Invalid IP address syntax (IPv4 or IPv6).
83    AddrParseError,
84    /// Error when creating new IPv4 or IPv6 networks.
85    IpNetworkError(IpNetworkError),
86}
87
88impl Error for IpNetworkParseError {
89    fn source(&self) -> Option<&(dyn Error + 'static)> {
90        match *self {
91            IpNetworkParseError::IpNetworkError(ref ip_network_error) => Some(ip_network_error),
92            _ => None,
93        }
94    }
95}
96
97impl fmt::Display for IpNetworkParseError {
98    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
99        match *self {
100            IpNetworkParseError::InvalidNetmaskFormat => write!(fmt, "invalid netmask format"),
101            IpNetworkParseError::InvalidFormatError => write!(fmt, "invalid format"),
102            IpNetworkParseError::AddrParseError => write!(fmt, "invalid IP address syntax"),
103            IpNetworkParseError::IpNetworkError(ref ip_network_error) => {
104                write!(fmt, "{}", ip_network_error)
105            }
106        }
107    }
108}