94 lines
2.5 KiB
Rust
94 lines
2.5 KiB
Rust
use std::fmt::{self,Display}; // needed to implement Display for Ip
|
|
use std::convert::From; // needed to implement u32::from(&ip)
|
|
|
|
// Debug needed for {:?} format
|
|
// PartialEq and Eq allows comparisons (usefull for unit tests)
|
|
#[derive(Debug,PartialEq,Eq)]
|
|
pub enum Ip {
|
|
V4([u8 ; 4]),
|
|
// V6([u16 ; 8]) // not implemented yet...
|
|
}
|
|
|
|
// implement methods on the Ip type
|
|
// 'new' and 'from_str' are arbitrary and could be named differently
|
|
impl Ip {
|
|
pub fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
|
|
Ip::V4([a, b, c, d])
|
|
}
|
|
|
|
pub fn from_str(s: &str) -> Option<Self> {
|
|
let tbl : Vec<u8> = s.split('.')
|
|
.filter_map(|s| s.parse().ok())
|
|
.collect();
|
|
Some(Ip::V4(tbl.try_into().ok()?))
|
|
}
|
|
|
|
// totaly useless but an example of an object method :)
|
|
pub fn is_even(&self) -> bool {
|
|
let Ip::V4([_,_,_,n]) = self;
|
|
n % 2 == 0
|
|
}
|
|
}
|
|
|
|
// allows conversion from ip to u32 with this syntax:
|
|
// `let nbr = u32::from(&ip);`
|
|
// use the std::convert::From trait
|
|
impl From<&Ip> for u32 {
|
|
fn from(src: &Ip) -> u32 {
|
|
let mut ip : u32 = 0;
|
|
let Ip::V4(array) = src;
|
|
for (idx, n) in array.iter().enumerate() {
|
|
ip += (*n as u32) << (8 * (3 - idx));
|
|
}
|
|
ip
|
|
}
|
|
}
|
|
|
|
// Display is a standard trait used by format! and println! and others
|
|
// to display objects...
|
|
impl Display for Ip {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
match self {
|
|
Ip::V4(arr) => write!(f, "{}.{}.{}.{}",
|
|
arr[0], arr[1], arr[2], arr[3]),
|
|
/*
|
|
Ip::V6(arr) => write!(f,
|
|
"{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
|
|
arr[0], arr[1], arr[2], arr[3],
|
|
arr[4], arr[5], arr[6], arr[7])
|
|
*/
|
|
}
|
|
}
|
|
}
|
|
|
|
// Some unit tests, run with:
|
|
// `$ cargo test`
|
|
#[test]
|
|
fn test_ip_new() {
|
|
let ip = Ip::new(127, 0, 0, 1);
|
|
assert_eq!(ip, Ip::V4([127, 0, 0, 1]));
|
|
}
|
|
|
|
#[test]
|
|
fn test_ip_from_str() {
|
|
let ip1 = Ip::from_str("127.0.0.1");
|
|
assert_eq!(ip1, Some(Ip::V4([127, 0, 0, 1])));
|
|
|
|
let ip2 = Ip::from_str("512.0.0.1");
|
|
assert_eq!(ip2, None);
|
|
|
|
}
|
|
|
|
#[test]
|
|
fn test_ip_is_even() {
|
|
assert_eq!(Ip::new(127, 0, 0, 1).is_even(), false);
|
|
assert_eq!(Ip::new(192, 168, 0, 2).is_even(), true);
|
|
}
|
|
|
|
#[test]
|
|
fn test_u32_from_ip() {
|
|
let ip = Ip::new(127, 0, 0, 1);
|
|
let nbr = u32::from(&ip);
|
|
assert_eq!(nbr, 0x7f000001);
|
|
}
|