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 { let tbl : Vec = 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); }