22 Commits

Author SHA1 Message Date
6d4e4ba47a Merge pull request #150 from achanda/autopublish
Auto publish to crates.io on new tag push
2022-04-13 22:59:50 -05:00
e842e0edc0 Auto publish to crates.io on new tag push 2022-04-13 22:56:43 -05:00
61550eda45 Merge pull request #149 from achanda/v0.19.0
Cut a new release for v0.19.0
2022-04-12 22:47:18 -05:00
3503e4c094 Cut a new release for v0.19.0
This one is still a manual release, I am hoping to get this automated
soon.
2022-04-12 22:44:10 -05:00
91528476a9 Merge pull request #148 from achanda/remove-html_root_url
Remove the redundant html_root_url attribute
2022-04-12 22:38:29 -05:00
501e5533d7 Remove the redundant html_root_url attribute 2022-04-12 22:35:37 -05:00
7120b93837 Merge pull request #144 from paolobarbolini/collect-str
Remove useless allocation when serializing
2021-12-29 10:24:38 -06:00
a57afd9e1a Remove useless allocation when serializing 2021-12-29 16:07:07 +01:00
8ad43541cd Merge pull request #143 from achanda/upgrade-edition
feat: Upgrade rust edition
2021-11-09 22:36:04 -06:00
9651b3b721 feat: Upgrade rust edition
cargo fix --edition did not result in any changes to src
2021-11-08 09:04:50 -06:00
5764406000 Merge pull request #142 from achanda/dependabot/add-v2-config-file 2021-04-29 15:43:16 -05:00
4cbd1f2424 Upgrade to GitHub-native Dependabot 2021-04-29 19:21:55 +00:00
772db6c569 Merge pull request #141 from achanda/v0.18.0
Cut a new release for v0.18.0
2021-04-13 18:32:45 -05:00
c9b2bc5519 Cut a new release for v0.18.0 2021-04-13 18:29:34 -05:00
fe9f1ba8d5 Merge pull request #140 from achanda/contains-inline
Always inline the contains function
2021-04-05 14:25:30 -05:00
9921661ebe Always inline the contains function
This function is commonly called in a loop (or iterator). Inlining it
makes it run faster, which is beneficial in this case.
2021-04-04 23:15:58 -05:00
14108098d6 Merge pull request #139 from achanda/iter-public
Reexport underlying iterators and do not implement Copy
2021-02-16 22:12:27 -06:00
1f3e10f73d Reexport underlying iterators and do not implement Copy
Closes #138
2021-02-15 11:12:15 -06:00
c26c836b39 Merge pull request #137 from achanda/const-fn
Convert Ipv{4,6}Network::new to const functions
2020-08-29 11:19:23 +01:00
8fcff82c7b Convert Ipv{4,6}Network::new to const functions
IpNetwork::new cannot be const since it is not supported with the ?
operator

Closes #111
2020-08-27 18:01:07 +01:00
46cc64d424 Merge pull request #136 from achanda/tryfrom
Implement TryFrom<&str> for all basic types
2020-08-09 22:32:03 +01:00
e15e8cb812 Implement TryFrom<&str> for all basic types
Also improve some docs and FromStr type signature
Closes #135
2020-08-09 22:27:49 +01:00
6 changed files with 79 additions and 20 deletions

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: cargo
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10

13
.github/workflows/publish.yml vendored Normal file
View File

@ -0,0 +1,13 @@
on:
push:
tags:
- 'v.*.*'
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
toolchain: stable
override: true
- uses: katyo/publish-crates@v1
with:
registry-token: ${{ secrets.CARGO_REGISTRY_TOKEN }}

View File

@ -1,6 +1,6 @@
[package]
name = "ipnetwork"
version = "0.17.0" # When updating version, also modify html_root_url in the lib.rs
version = "0.19.0"
authors = ["Abhishek Chanda <abhishek.becs@gmail.com>", "Linus Färnstrand <faern@faern.net>"]
description = "A library to work with IP CIDRs in Rust"
license = "MIT OR Apache-2.0"
@ -8,7 +8,7 @@ repository = "https://github.com/achanda/ipnetwork"
keywords = ["network", "ip", "address", "cidr"]
readme = "README.md"
categories = ["network-programming", "parser-implementations"]
edition = "2018"
edition = "2021"
[dependencies]
serde = { version = "1", optional = true }
@ -16,7 +16,7 @@ serde = { version = "1", optional = true }
[dev-dependencies]
serde_json = "1.0"
serde_derive = "1"
criterion = "0.3.0"
criterion = {version = "0.3.4", features= ["html_reports"]}
[badges]
travis-ci = { repository = "achanda/ipnetwork" }

View File

@ -1,5 +1,5 @@
use crate::common::{cidr_parts, parse_prefix, IpNetworkError};
use std::{fmt, net::Ipv4Addr, str::FromStr};
use std::{fmt, net::Ipv4Addr, str::FromStr, convert::TryFrom};
const IPV4_BITS: u8 = 32;
@ -27,7 +27,7 @@ impl serde::Serialize for Ipv4Network {
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
serializer.collect_str(self)
}
}
@ -35,7 +35,7 @@ impl Ipv4Network {
/// Constructs a new `Ipv4Network` from any `Ipv4Addr` and a prefix denoting the network size.
///
/// If the prefix is larger than 32 this will return an `IpNetworkError::InvalidPrefix`.
pub fn new(addr: Ipv4Addr, prefix: u8) -> Result<Ipv4Network, IpNetworkError> {
pub const fn new(addr: Ipv4Addr, prefix: u8) -> Result<Ipv4Network, IpNetworkError> {
if prefix > IPV4_BITS {
Err(IpNetworkError::InvalidPrefix)
} else {
@ -163,6 +163,7 @@ impl Ipv4Network {
/// assert!(net.contains(Ipv4Addr::new(127, 0, 0, 70)));
/// assert!(!net.contains(Ipv4Addr::new(127, 0, 1, 70)));
/// ```
#[inline]
pub fn contains(self, ip: Ipv4Addr) -> bool {
let mask = !(0xffff_ffff as u64 >> self.prefix) as u32;
let net = u32::from(self.addr) & mask;
@ -236,7 +237,7 @@ impl fmt::Display for Ipv4Network {
/// ```
impl FromStr for Ipv4Network {
type Err = IpNetworkError;
fn from_str(s: &str) -> Result<Ipv4Network, IpNetworkError> {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (addr_str, prefix_str) = cidr_parts(s)?;
let addr = Ipv4Addr::from_str(addr_str)
.map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?;
@ -254,6 +255,14 @@ impl FromStr for Ipv4Network {
}
}
impl TryFrom<&str> for Ipv4Network {
type Error = IpNetworkError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Ipv4Network::from_str(s)
}
}
impl From<Ipv4Addr> for Ipv4Network {
fn from(a: Ipv4Addr) -> Ipv4Network {
Ipv4Network {
@ -263,7 +272,7 @@ impl From<Ipv4Addr> for Ipv4Network {
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Clone, Debug)]
pub struct Ipv4NetworkIterator {
next: Option<u32>,
end: u32,

View File

@ -1,5 +1,5 @@
use crate::common::{cidr_parts, parse_prefix, IpNetworkError};
use std::{cmp, fmt, net::Ipv6Addr, str::FromStr};
use std::{cmp, fmt, net::Ipv6Addr, str::FromStr, convert::TryFrom};
const IPV6_BITS: u8 = 128;
const IPV6_SEGMENT_BITS: u8 = 16;
@ -28,7 +28,7 @@ impl serde::Serialize for Ipv6Network {
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
serializer.collect_str(self)
}
}
@ -36,7 +36,7 @@ impl Ipv6Network {
/// Constructs a new `Ipv6Network` from any `Ipv6Addr` and a prefix denoting the network size.
///
/// If the prefix is larger than 128 this will return an `IpNetworkError::InvalidPrefix`.
pub fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Network, IpNetworkError> {
pub const fn new(addr: Ipv6Addr, prefix: u8) -> Result<Ipv6Network, IpNetworkError> {
if prefix > IPV6_BITS {
Err(IpNetworkError::InvalidPrefix)
} else {
@ -174,6 +174,7 @@ impl Ipv6Network {
/// assert!(net.contains(Ipv6Addr::new(0xff01, 0, 0, 0, 0, 0, 0, 0x1)));
/// assert!(!net.contains(Ipv6Addr::new(0xffff, 0, 0, 0, 0, 0, 0, 0x1)));
/// ```
#[inline]
pub fn contains(&self, ip: Ipv6Addr) -> bool {
let a = self.addr.segments();
let b = ip.segments();
@ -205,9 +206,22 @@ impl Ipv6Network {
}
}
/// Creates an `Ipv6Network` from parsing a string in CIDR notation.
///
/// # Examples
///
/// ```
/// use std::net::Ipv6Addr;
/// use ipnetwork::Ipv6Network;
///
/// let new = Ipv6Network::new(Ipv6Addr::new(0xff01, 0, 0, 0x17, 0, 0, 0, 0x2), 65).unwrap();
/// let from_cidr: Ipv6Network = "FF01:0:0:17:0:0:0:2/65".parse().unwrap();
/// assert_eq!(new.ip(), from_cidr.ip());
/// assert_eq!(new.prefix(), from_cidr.prefix());
/// ```
impl FromStr for Ipv6Network {
type Err = IpNetworkError;
fn from_str(s: &str) -> Result<Ipv6Network, IpNetworkError> {
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (addr_str, prefix_str) = cidr_parts(s)?;
let addr = Ipv6Addr::from_str(addr_str)
.map_err(|_| IpNetworkError::InvalidAddr(addr_str.to_string()))?;
@ -219,6 +233,14 @@ impl FromStr for Ipv6Network {
}
}
impl TryFrom<&str> for Ipv6Network {
type Error = IpNetworkError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
Ipv6Network::from_str(s)
}
}
impl From<Ipv6Addr> for Ipv6Network {
fn from(a: Ipv6Addr) -> Ipv6Network {
Ipv6Network {
@ -228,7 +250,7 @@ impl From<Ipv6Addr> for Ipv6Network {
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Clone, Debug)]
pub struct Ipv6NetworkIterator {
next: Option<u128>,
end: u128,

View File

@ -1,24 +1,23 @@
//! The `ipnetwork` crate provides a set of APIs to work with IP CIDRs in
//! Rust.
#![crate_type = "lib"]
#![doc(html_root_url = "https://docs.rs/ipnetwork/0.17.0")]
#![deny(missing_copy_implementations,
#![deny(
missing_debug_implementations,
unsafe_code,
unused_extern_crates,
unused_import_braces)]
use std::{fmt, net::IpAddr, str::FromStr};
use std::{fmt, net::IpAddr, str::FromStr, convert::TryFrom};
mod common;
mod ipv4;
mod ipv6;
pub use crate::common::IpNetworkError;
use crate::ipv4::Ipv4NetworkIterator;
pub use crate::ipv4::Ipv4NetworkIterator;
pub use crate::ipv4::{ipv4_mask_to_prefix, Ipv4Network};
use crate::ipv6::Ipv6NetworkIterator;
pub use crate::ipv6::Ipv6NetworkIterator;
pub use crate::ipv6::{ipv6_mask_to_prefix, Ipv6Network};
/// Represents a generic network range. This type can have two variants:
@ -46,7 +45,7 @@ impl serde::Serialize for IpNetwork {
where
S: serde::Serializer,
{
serializer.serialize_str(&self.to_string())
serializer.collect_str(self)
}
}
@ -228,6 +227,7 @@ impl IpNetwork {
/// assert!(!net.contains(ip2));
/// assert!(!net.contains(ip4));
/// ```
#[inline]
pub fn contains(&self, ip: IpAddr) -> bool {
match (*self, ip) {
(IpNetwork::V4(net), IpAddr::V4(ip)) => net.contains(ip),
@ -282,7 +282,7 @@ impl IpNetwork {
/// ```
impl FromStr for IpNetwork {
type Err = IpNetworkError;
fn from_str(s: &str) -> Result<IpNetwork, IpNetworkError> {
fn from_str(s: &str) -> Result<Self, Self::Err> {
if let Ok(net) = Ipv4Network::from_str(s) {
Ok(IpNetwork::V4(net))
} else if let Ok(net) = Ipv6Network::from_str(s) {
@ -293,6 +293,14 @@ impl FromStr for IpNetwork {
}
}
impl TryFrom<&str> for IpNetwork {
type Error = IpNetworkError;
fn try_from(s: &str) -> Result<Self, Self::Error> {
IpNetwork::from_str(s)
}
}
impl From<Ipv4Network> for IpNetwork {
fn from(v4: Ipv4Network) -> IpNetwork {
IpNetwork::V4(v4)