diff --git a/Cargo.toml b/Cargo.toml index f614a1d..a2f5405 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,8 @@ documentation = "https://docs.rs/ipnet" edition = "2018" [features] -default = [] +default = ["std"] +std = [] # Implements "schemars::JsonSchema". Also implies "serde". json = ["serde", "schemars"] diff --git a/src/ipext.rs b/src/ipext.rs index aff7930..15e0fea 100644 --- a/src/ipext.rs +++ b/src/ipext.rs @@ -4,9 +4,12 @@ //! the `Ipv4Addr` and `Ipv6Addr` types with methods to perform these //! operations. -use std::cmp::Ordering::{Less, Equal}; -use std::iter::{FusedIterator, DoubleEndedIterator}; -use std::mem; +use core::cmp::Ordering::{Less, Equal}; +use core::iter::{FusedIterator, DoubleEndedIterator}; +use core::mem; +#[cfg(not(feature = "std"))] +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +#[cfg(feature = "std")] use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// Provides a `saturating_add()` method for `Ipv4Addr` and `Ipv6Addr`. @@ -18,6 +21,10 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// # Examples /// /// ``` +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(not(feature = "std"))] +/// # use core::net::{Ipv4Addr, Ipv6Addr}; +/// # #[cfg(feature = "std")] /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpAdd; /// @@ -58,6 +65,10 @@ pub trait IpAdd { /// # Examples /// /// ``` +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(not(feature = "std"))] +/// # use core::net::{Ipv4Addr, Ipv6Addr}; +/// # #[cfg(feature = "std")] /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpSub; /// @@ -89,6 +100,10 @@ pub trait IpSub { /// # Examples /// /// ``` +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(not(feature = "std"))] +/// # use core::net::{Ipv4Addr, Ipv6Addr}; +/// # #[cfg(feature = "std")] /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpBitAnd; /// @@ -116,6 +131,10 @@ pub trait IpBitAnd { /// # Examples /// /// ``` +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(not(feature = "std"))] +/// # use core::net::{Ipv4Addr, Ipv6Addr}; +/// # #[cfg(feature = "std")] /// use std::net::{Ipv4Addr, Ipv6Addr}; /// use ipnet::IpBitOr; /// @@ -290,6 +309,10 @@ pub enum IpAddrRange { /// # Examples /// /// ``` +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(not(feature = "std"))] +/// # use core::net::Ipv4Addr; +/// # #[cfg(feature = "std")] /// use std::net::Ipv4Addr; /// use ipnet::Ipv4AddrRange; /// @@ -315,7 +338,11 @@ pub struct Ipv4AddrRange { /// /// # Examples /// -/// ``` +/// ``` +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(not(feature = "std"))] +/// # use core::net::Ipv6Addr; +/// # #[cfg(feature = "std")] /// use std::net::Ipv6Addr; /// use ipnet::Ipv6AddrRange; /// @@ -481,12 +508,12 @@ impl Iterator for Ipv4AddrRange { // so need to explicitly check for overflow. // 'usize::MAX as u32' is okay here - if usize is 64 bits, // value truncates to u32::MAX - if count <= std::usize::MAX as u32 { + if count <= core::usize::MAX as u32 { count as usize + 1 // count overflows usize } else { // emulate standard overflow/panic behavior - std::usize::MAX + 2 + count as usize + core::usize::MAX + 2 + count as usize } }, Some(Equal) => 1, @@ -531,8 +558,8 @@ impl Iterator for Ipv4AddrRange { fn size_hint(&self) -> (usize, Option) { let count = self.count_u64(); - if count > std::usize::MAX as u64 { - (std::usize::MAX, None) + if count > core::usize::MAX as u64 { + (core::usize::MAX, None) } else { let count = count as usize; (count, Some(count)) @@ -561,12 +588,12 @@ impl Iterator for Ipv6AddrRange { fn count(self) -> usize { let count = self.count_u128(); // count fits in usize - if count <= std::usize::MAX as u128 { + if count <= core::usize::MAX as u128 { count as usize // count does not fit in usize } else { // emulate standard overflow/panic behavior - std::usize::MAX + 1 + count as usize + core::usize::MAX + 1 + count as usize } } @@ -616,14 +643,14 @@ impl Iterator for Ipv6AddrRange { fn size_hint(&self) -> (usize, Option) { if self.can_count_u128() { let count = self.count_u128(); - if count > std::usize::MAX as u128 { - (std::usize::MAX, None) + if count > core::usize::MAX as u128 { + (core::usize::MAX, None) } else { let count = count as usize; (count, Some(count)) } } else { - (std::usize::MAX, None) + (core::usize::MAX, None) } } } @@ -722,8 +749,12 @@ impl FusedIterator for Ipv6AddrRange {} #[cfg(test)] mod tests { + use alloc::vec::Vec; + use core::str::FromStr; + #[cfg(not(feature = "std"))] + use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; + #[cfg(feature = "std")] use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; - use std::str::FromStr; use super::*; #[test] @@ -876,7 +907,7 @@ mod tests { Ipv6Addr::from_str("::").unwrap(), Ipv6Addr::from_str("8000::").unwrap(), ); - assert_eq!(i.size_hint(), (std::usize::MAX, None)); + assert_eq!(i.size_hint(), (core::usize::MAX, None)); // Min, Max, Last let i = Ipv4AddrRange::new( diff --git a/src/ipnet.rs b/src/ipnet.rs index e190f06..3875d2c 100644 --- a/src/ipnet.rs +++ b/src/ipnet.rs @@ -1,11 +1,18 @@ -use std::cmp::{min, max}; -use std::cmp::Ordering::{Less, Equal}; -use std::convert::From; +use alloc::vec::Vec; +use core::cmp::{min, max}; +use core::cmp::Ordering::{Less, Equal}; +use core::convert::From; +use core::fmt; +use core::iter::FusedIterator; +use core::option::Option::{Some, None}; +#[cfg(not(feature = "std"))] +use core::error::Error; +#[cfg(feature = "std")] use std::error::Error; -use std::fmt; -use std::iter::FusedIterator; +#[cfg(not(feature = "std"))] +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +#[cfg(feature = "std")] use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; -use std::option::Option::{Some, None}; use crate::ipext::{IpAdd, IpSub, IpStep, IpAddrRange, Ipv4AddrRange, Ipv6AddrRange}; use crate::mask::{ip_mask_to_prefix, ipv4_mask_to_prefix, ipv6_mask_to_prefix}; @@ -64,7 +71,11 @@ pub enum IpNet { /// # Examples /// /// ``` -/// use std::net::Ipv4Addr; +/// # #![cfg_attr(not(feature = "std"), feature(ip_in_core))] +/// # #[cfg(feature = "std")] +/// # use std::net::Ipv6Addr; +/// # #[cfg(not(feature = "std"))] +/// # use core::net::Ipv6Addr; /// use ipnet::Ipv4Net; /// /// let net: Ipv4Net = "10.1.1.0/24".parse().unwrap(); @@ -882,7 +893,7 @@ impl Ipv4Net { let mut res: Vec = Vec::new(); for (start, mut end) in intervals { - if end != std::u32::MAX { + if end != core::u32::MAX { end = end.saturating_sub(1) } let iter = Ipv4Subnets::new(start.into(), end.into(), 0); @@ -1227,7 +1238,7 @@ impl Ipv6Net { let mut res: Vec = Vec::new(); for (start, mut end) in intervals { - if end != std::u128::MAX { + if end != core::u128::MAX { end = end.saturating_sub(1) } let iter = Ipv6Subnets::new(start.into(), end.into(), 0); @@ -1507,7 +1518,7 @@ impl Iterator for IpSubnets { fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4Net { let range = end.saturating_sub(start).saturating_add(1); - if range == std::u32::MAX && min_prefix_len == 0 { + if range == core::u32::MAX && min_prefix_len == 0 { Ipv4Net::new(start, min_prefix_len).unwrap() } else { @@ -1521,7 +1532,7 @@ fn next_ipv4_subnet(start: Ipv4Addr, end: Ipv4Addr, min_prefix_len: u8) -> Ipv4N fn next_ipv6_subnet(start: Ipv6Addr, end: Ipv6Addr, min_prefix_len: u8) -> Ipv6Net { let range = end.saturating_sub(start).saturating_add(1); - if range == std::u128::MAX && min_prefix_len == 0 { + if range == core::u128::MAX && min_prefix_len == 0 { Ipv6Net::new(start, min_prefix_len).unwrap() } else { diff --git a/src/ipnet_serde.rs b/src/ipnet_serde.rs index bbf15ac..e42df68 100644 --- a/src/ipnet_serde.rs +++ b/src/ipnet_serde.rs @@ -1,5 +1,5 @@ use crate::{IpNet, Ipv4Net, Ipv6Net}; -use std::fmt; +use core::fmt; use std::net::{Ipv4Addr, Ipv6Addr}; use serde::{self, Serialize, Deserialize, Serializer, Deserializer}; use serde::ser::SerializeTuple; diff --git a/src/lib.rs b/src/lib.rs index 4f8fb16..8eae5e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,16 @@ //! //! [feature]: https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section +#![no_std] +#![cfg_attr(not(feature = "std"), feature(error_in_core))] +#![cfg_attr(not(feature = "std"), feature(ip_in_core))] + +#[cfg(feature = "std")] +extern crate std; + +#[cfg_attr(test, macro_use)] +extern crate alloc; + #[cfg(feature = "serde")] extern crate serde; #[cfg(feature = "schemars")] diff --git a/src/mask.rs b/src/mask.rs index 1047bf9..761c031 100644 --- a/src/mask.rs +++ b/src/mask.rs @@ -1,4 +1,7 @@ use crate::PrefixLenError; +#[cfg(not(feature = "std"))] +use core::net::{IpAddr, Ipv4Addr, Ipv6Addr}; +#[cfg(feature = "std")] use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; /// Converts a `IpAddr` network mask into a prefix. diff --git a/src/parser.rs b/src/parser.rs index 7ec9991..d21fe60 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -4,10 +4,16 @@ //! is private. It is copied and extended here with methods for parsing //! IP network addresses. +use alloc::{str::FromStr, boxed::Box}; +use core::fmt; +#[cfg(not(feature = "std"))] +use core::error::Error; +#[cfg(feature = "std")] use std::error::Error; -use std::fmt; +#[cfg(not(feature = "std"))] +use core::net::{Ipv4Addr, Ipv6Addr}; +#[cfg(feature = "std")] use std::net::{Ipv4Addr, Ipv6Addr}; -use std::str::FromStr; use crate::ipnet::{IpNet, Ipv4Net, Ipv6Net};