mirror of
https://github.com/achanda/ipnetwork.git
synced 2025-06-17 09:18:51 +00:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
aff0419a75 | |||
1f96439a87 | |||
25d7dc19d1 | |||
d8ce2e4dbc | |||
16c4af9823 | |||
72677fbe8f | |||
35331cf7ea | |||
1d57287c77 | |||
ddec283819 | |||
2b21f38171 | |||
2bd3db84a8 | |||
a8edccafa1 | |||
9ab988715e | |||
1f3d42d89f |
@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "ipnetwork"
|
||||
version = "0.13.0" # When updating version, also modify html_root_url in the lib.rs
|
||||
version = "0.14.0" # When updating version, also modify html_root_url in the lib.rs
|
||||
authors = ["Abhishek Chanda <abhishek.becs@gmail.com>", "Linus Färnstrand <faern@faern.net>"]
|
||||
description = "A library to work with IP CIDRs in Rust, heavily WIP"
|
||||
license = "Apache-2.0"
|
||||
@ -11,12 +11,12 @@ documentation = "https://docs.rs/ipnetwork/"
|
||||
categories = ["network-programming", "os"]
|
||||
|
||||
[dependencies]
|
||||
clippy = {version = "0.0.104", optional = true}
|
||||
clippy = {version = "0.0.302", optional = true}
|
||||
serde = ">=0.8.0, <2.0"
|
||||
serde_derive = ">=0.8.0, <2.0"
|
||||
|
||||
[dev-dependencies]
|
||||
serde_json = "1.0"
|
||||
serde_derive = ">=0.8.0, <2.0"
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "achanda/ipnetwork" }
|
||||
|
@ -1,6 +1,5 @@
|
||||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
/// Represents a bunch of errors that can occur while working with a `IpNetwork`
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
|
12
src/ipv4.rs
12
src/ipv4.rs
@ -49,7 +49,7 @@ impl Ipv4Network {
|
||||
/// `Ipv4Addr` in the given network. `None` will be returned when there are no more
|
||||
/// addresses.
|
||||
pub fn iter(&self) -> Ipv4NetworkIterator {
|
||||
let start = u64::from(u32::from(self.network()));
|
||||
let start = u32::from(self.network());
|
||||
let end = start + self.size();
|
||||
Ipv4NetworkIterator { next: start, end }
|
||||
}
|
||||
@ -150,9 +150,9 @@ impl Ipv4Network {
|
||||
/// let tinynet: Ipv4Network = "0.0.0.0/32".parse().unwrap();
|
||||
/// assert_eq!(tinynet.size(), 1);
|
||||
/// ```
|
||||
pub fn size(&self) -> u64 {
|
||||
pub fn size(&self) -> u32 {
|
||||
let host_bits = u32::from(IPV4_BITS - self.prefix);
|
||||
(2 as u64).pow(host_bits)
|
||||
(2 as u32).pow(host_bits)
|
||||
}
|
||||
|
||||
/// Returns the `n`:th address within this network.
|
||||
@ -173,7 +173,7 @@ impl Ipv4Network {
|
||||
/// assert_eq!(net2.nth(256).unwrap(), Ipv4Addr::new(10, 0, 1, 0));
|
||||
/// ```
|
||||
pub fn nth(&self, n: u32) -> Option<Ipv4Addr> {
|
||||
if u64::from(n) < self.size() {
|
||||
if n < self.size() {
|
||||
let net = u32::from(self.network());
|
||||
Some(Ipv4Addr::from(net + n))
|
||||
} else {
|
||||
@ -225,8 +225,8 @@ impl From<Ipv4Addr> for Ipv4Network {
|
||||
}
|
||||
|
||||
pub struct Ipv4NetworkIterator {
|
||||
next: u64,
|
||||
end: u64,
|
||||
next: u32,
|
||||
end: u32,
|
||||
}
|
||||
|
||||
impl Iterator for Ipv4NetworkIterator {
|
||||
|
@ -55,10 +55,10 @@ impl Ipv6Network {
|
||||
let max = u128::max_value();
|
||||
let prefix = self.prefix;
|
||||
|
||||
let mask = max.checked_shl((IPV6_BITS - prefix) as u32).unwrap_or(0);
|
||||
let mask = max.checked_shl(u32::from(IPV6_BITS - prefix)).unwrap_or(0);
|
||||
let start: u128 = dec & mask;
|
||||
|
||||
let mask = max.checked_shr(prefix as u32).unwrap_or(0);
|
||||
let mask = max.checked_shr(u32::from(prefix)).unwrap_or(0);
|
||||
let end: u128 = dec | mask;
|
||||
|
||||
Ipv6NetworkIterator {
|
||||
@ -174,7 +174,7 @@ impl Ipv6Network {
|
||||
/// assert_eq!(tinynet.size(), 1);
|
||||
/// ```
|
||||
pub fn size(&self) -> u128 {
|
||||
let host_bits = (IPV6_BITS - self.prefix) as u32;
|
||||
let host_bits = u32::from(IPV6_BITS - self.prefix);
|
||||
(2 as u128).pow(host_bits)
|
||||
}
|
||||
}
|
||||
|
109
src/lib.rs
109
src/lib.rs
@ -4,11 +4,9 @@
|
||||
#![cfg_attr(feature = "dev", feature(plugin))]
|
||||
#![cfg_attr(feature = "dev", plugin(clippy))]
|
||||
#![crate_type = "lib"]
|
||||
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.13")]
|
||||
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.14.0")]
|
||||
|
||||
extern crate serde;
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use std::fmt;
|
||||
use std::net::IpAddr;
|
||||
@ -19,19 +17,46 @@ mod ipv6;
|
||||
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
pub use common::IpNetworkError;
|
||||
pub use ipv4::{Ipv4Network, ipv4_mask_to_prefix};
|
||||
pub use ipv6::{Ipv6Network, ipv6_mask_to_prefix};
|
||||
pub use ipv4::{ipv4_mask_to_prefix, Ipv4Network};
|
||||
pub use ipv6::{ipv6_mask_to_prefix, Ipv6Network};
|
||||
|
||||
/// Represents a generic network range. This type can have two variants:
|
||||
/// the v4 and the v6 case.
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
|
||||
#[serde(untagged)]
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum IpNetwork {
|
||||
V4(Ipv4Network),
|
||||
V6(Ipv6Network),
|
||||
}
|
||||
|
||||
impl<'de> Deserialize<'de> for IpNetwork {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = <String>::deserialize(deserializer)?;
|
||||
IpNetwork::from_str(&s).map_err(de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
impl Serialize for IpNetwork {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a generic network size. For IPv4, the max size is a u32 and for IPv6, it is a u128
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum NetworkSize {
|
||||
V4(u32),
|
||||
V6(u128),
|
||||
}
|
||||
|
||||
impl IpNetwork {
|
||||
/// Constructs a new `IpNetwork` from a given `IpAddr` and a prefix denoting the
|
||||
/// network size. If the prefix is larger than 32 (for IPv4) or 128 (for IPv6), this
|
||||
@ -71,6 +96,46 @@ impl IpNetwork {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the address of the network denoted by this `IpNetwork`.
|
||||
/// This means the lowest possible IP address inside of the network.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
/// use ipnetwork::IpNetwork;
|
||||
///
|
||||
/// let net: IpNetwork = "10.1.9.32/16".parse().unwrap();
|
||||
/// assert_eq!(net.network(), Ipv4Addr::new(10, 1, 0, 0));
|
||||
/// let net: IpNetwork = "2001:db8::/96".parse().unwrap();
|
||||
/// assert_eq!(net.network(), Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 0));
|
||||
/// ```
|
||||
pub fn network(&self) -> IpAddr {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => IpAddr::V4(a.network()),
|
||||
IpNetwork::V6(ref a) => IpAddr::V6(a.network()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the broadcasting address of this `IpNetwork`.
|
||||
/// This means the highest possible IP address inside of the network.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::net::Ipv4Addr;
|
||||
/// use ipnetwork::{IpNetwork, Ipv4Network};
|
||||
///
|
||||
/// let net: Ipv4Network = "10.9.0.32/16".parse().unwrap();
|
||||
/// assert_eq!(net.broadcast(), Ipv4Addr::new(10, 9, 255, 255));
|
||||
/// ```
|
||||
pub fn broadcast(&self) -> IpAddr {
|
||||
match *self {
|
||||
IpNetwork::V4(ref a) => IpAddr::V4(a.broadcast()),
|
||||
IpNetwork::V6(ref a) => IpAddr::V6(a.broadcast()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the mask for this `IpNetwork`.
|
||||
/// That means the `prefix` most significant bits will be 1 and the rest 0
|
||||
///
|
||||
@ -158,6 +223,24 @@ impl IpNetwork {
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of possible host addresses in this `IpAddr`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ipnetwork::{IpNetwork, NetworkSize};
|
||||
///
|
||||
///
|
||||
/// let net: IpNetwork = "127.0.0.0/24".parse().unwrap();
|
||||
/// assert_eq!(net.size(), NetworkSize::V4(256))
|
||||
/// ```
|
||||
pub fn size(&self) -> NetworkSize {
|
||||
match *self {
|
||||
IpNetwork::V4(ref ip) => NetworkSize::V4(ip.size()),
|
||||
IpNetwork::V6(ref ip) => NetworkSize::V6(ip.size()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to parse the given string into a `IpNetwork`. Will first try to parse
|
||||
@ -225,3 +308,15 @@ pub fn ip_mask_to_prefix(mask: IpAddr) -> Result<u8, IpNetworkError> {
|
||||
IpAddr::V6(mask) => ipv6_mask_to_prefix(mask),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#[test]
|
||||
fn deserialize_from_serde_json_value() {
|
||||
use super::*;
|
||||
let network = IpNetwork::from_str("0.0.0.0/0").unwrap();
|
||||
let val: serde_json::value::Value = serde_json::from_str(&serde_json::to_string(&network).unwrap()).unwrap();
|
||||
let _deser: IpNetwork =
|
||||
serde_json::from_value(val).expect("Fails to deserialize from json_value::value::Value");
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user