-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added needed traits to
NetworkSize
(#175)
* Add conversion and better equality traits to NetworkSize * Add tests for NetworkSize conversion/equality * impl Display for NetworkSize
- Loading branch information
1 parent
19aafee
commit d19ac33
Showing
6 changed files
with
221 additions
and
42 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
use std::{error::Error, fmt}; | ||
|
||
use crate::error::IpNetworkError::*; | ||
|
||
/// Represents a bunch of errors that can occur while working with a `IpNetwork` | ||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
#[non_exhaustive] | ||
pub enum IpNetworkError { | ||
InvalidAddr(String), | ||
InvalidPrefix, | ||
InvalidCidrFormat(String), | ||
NetworkSizeError(NetworkSizeError) | ||
} | ||
|
||
impl fmt::Display for IpNetworkError { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
match *self { | ||
InvalidAddr(ref s) => write!(f, "invalid address: {s}"), | ||
InvalidPrefix => write!(f, "invalid prefix"), | ||
InvalidCidrFormat(ref s) => write!(f, "invalid cidr format: {s}"), | ||
NetworkSizeError(ref e) => write!(f, "network size error: {e}") | ||
} | ||
} | ||
} | ||
|
||
impl Error for IpNetworkError { | ||
fn description(&self) -> &str { | ||
match *self { | ||
InvalidAddr(_) => "address is invalid", | ||
InvalidPrefix => "prefix is invalid", | ||
InvalidCidrFormat(_) => "cidr is invalid", | ||
NetworkSizeError(_) => "network size error" | ||
} | ||
} | ||
} | ||
|
||
/// Cannot convert an IPv6 network size to a u32 as it is a 128-bit value. | ||
#[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
#[non_exhaustive] | ||
pub enum NetworkSizeError { | ||
NetworkIsTooLarge | ||
} | ||
|
||
impl fmt::Display for NetworkSizeError { | ||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result { | ||
f.write_str("Network is too large to fit into an unsigned 32-bit integer!") | ||
} | ||
} | ||
|
||
impl Error for NetworkSizeError {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
use std::{cmp::Ordering, fmt::Display}; | ||
|
||
use crate::error::NetworkSizeError; | ||
|
||
/// 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)] | ||
pub enum NetworkSize { | ||
V4(u32), | ||
V6(u128), | ||
} | ||
use NetworkSize::*; | ||
|
||
// Conversions | ||
|
||
impl From<u128> for NetworkSize { | ||
fn from(value: u128) -> Self { | ||
V6(value) | ||
} | ||
} | ||
|
||
impl From<u32> for NetworkSize { | ||
fn from(value: u32) -> Self { | ||
V4(value) | ||
} | ||
} | ||
|
||
impl TryInto<u32> for NetworkSize { | ||
type Error = NetworkSizeError; | ||
fn try_into(self) -> Result<u32, Self::Error> { | ||
match self { | ||
V4(a) => Ok(a), | ||
V6(_) => Err(NetworkSizeError::NetworkIsTooLarge), | ||
} | ||
} | ||
} | ||
|
||
impl Into<u128> for NetworkSize { | ||
fn into(self) -> u128 { | ||
match self { | ||
V4(a) => a as u128, | ||
V6(a) => a, | ||
} | ||
} | ||
} | ||
|
||
// Equality/comparisons | ||
|
||
impl PartialEq for NetworkSize { | ||
fn eq(&self, other: &Self) -> bool { | ||
let a: u128 = (*self).into(); | ||
let b: u128 = (*other).into(); | ||
a == b | ||
} | ||
} | ||
|
||
impl Ord for NetworkSize { | ||
fn cmp(&self, other: &Self) -> Ordering { | ||
let a: u128 = (*self).into(); | ||
let b: u128 = (*other).into(); | ||
return a.cmp(&b); | ||
} | ||
} | ||
|
||
impl PartialOrd for NetworkSize { | ||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | ||
Some(self.cmp(other)) | ||
} | ||
} | ||
|
||
impl Eq for NetworkSize {} | ||
|
||
// Display | ||
|
||
impl Display for NetworkSize { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", Into::<u128>::into(*self)) | ||
} | ||
} | ||
|
||
// Tests | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_from_u128() { | ||
let value: u128 = 100; | ||
let ns = NetworkSize::from(value); | ||
assert_eq!(ns, V6(100)); | ||
} | ||
|
||
#[test] | ||
fn test_from_u32() { | ||
let value: u32 = 100; | ||
let ns = NetworkSize::from(value); | ||
assert_eq!(ns, V4(100)); | ||
} | ||
|
||
#[test] | ||
fn test_try_into_u32() { | ||
let value: u32 = 100; | ||
let ns = V4(value); | ||
let result: Result<u32, _> = ns.try_into(); | ||
assert!(result.is_ok()); | ||
assert_eq!(result.unwrap(), value); | ||
} | ||
|
||
#[test] | ||
fn test_try_into_u32_error() { | ||
let value: u128 = u32::MAX as u128 + 1; | ||
let ns = V6(value); | ||
let result: Result<u32, _> = ns.try_into(); | ||
assert!(result.is_err()); | ||
} | ||
|
||
#[test] | ||
fn test_into_u128() { | ||
let value: u32 = 100; | ||
let ns = V4(value); | ||
let result: u128 = ns.into(); | ||
assert_eq!(result, value as u128); | ||
} | ||
|
||
#[test] | ||
fn test_eq() { | ||
let ns1 = V4(100); | ||
let ns2 = V4(100); | ||
assert_eq!(ns1, ns2); | ||
|
||
let ns1 = V6(100); | ||
let ns2 = V6(100); | ||
assert_eq!(ns1, ns2); | ||
|
||
let ns1 = V4(100); | ||
let ns2 = V6(100); | ||
assert_eq!(ns1, ns2); | ||
} | ||
|
||
#[test] | ||
fn test_cmp() { | ||
let ns1 = V4(100); | ||
let ns2 = V4(200); | ||
assert!(ns1 < ns2); | ||
|
||
let ns1 = V6(200); | ||
let ns2 = V6(100); | ||
assert!(ns1 > ns2); | ||
|
||
let ns1 = V4(100); | ||
let ns2 = V6(200); | ||
assert!(ns1 < ns2); | ||
} | ||
|
||
#[test] | ||
fn test_display() { | ||
let ns1 = V4(u32::MAX); | ||
let ns2 = V6(ns1.into()); | ||
assert_eq!(ns1.to_string(), ns2.to_string()); | ||
} | ||
} |