use std::str::FromStr; use super::NetworkingErr; #[derive(Debug, PartialEq, Eq)] pub struct InvalidIPErr; /// Ip address enum that includes associated type /// /// # Example /// ``` /// //Loopback Addresses: /// IpAddr::V4(127, 0, 0, 1) /// IpAddr::V6(String::from("::1")) /// ``` #[allow(unused)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum IpAddr { V4(u8, u8, u8, u8), V6(String) } impl ToString for IpAddr { /// Function that returns an IP address in string form fn to_string(&self) -> String { match self { IpAddr::V4(oct1, oct2, oct3, oct4) => format!("{}.{}.{}.{}", oct1, oct2, oct3, oct4), IpAddr::V6(addr) => format!("{}", addr) } } } impl FromStr for IpAddr { type Err = NetworkingErr; /// Function that generates a IpAddr / Err from a string /// /// # Limitation /// Currently only works for IPs of type IPv4 /// # Example /// ``` /// let ip: &str = "127.0.0.1"; /// /// let parsed_ip: IpAddr = IpAddr::from_str(ip); /// ///parsed_ip = IpAddr::V4(127,0,0,1) /// ``` fn from_str(s: &str) -> Result { let split_ip = s.split('.'); if split_ip.clone().count() != 4 { //Invalid IP address entered return Err(super::NetworkingErr::InvalidIPErr) } let mut ip: [u8; 4] = Default::default(); //Go through each octet and ensure it can be parsed; for (i, oct) in split_ip.into_iter().enumerate() { if i > ip.len() { //Ip string is out of the range of the 4 octets in an IPv4 Address return Err(NetworkingErr::InvalidIPErr) } match oct.parse::() { Ok(parsed_oct) => ip[i] = parsed_oct, Err(_) => return Err(NetworkingErr::InvalidIPErr) } } Ok(IpAddr::V4(ip[0],ip[1],ip[2],ip[3])) } } /// Function that takes in an IP address and then prints a formatted string to the CLI /// /// # Example /// ``` /// let ip = IpAddr::V4(127, 0, 0, 1); /// /// print_ip(ip); /// //Output: IP Address: 127.0.0.1 /// ``` #[allow(unused)] pub fn print_ip(ip_address: IpAddr) { println!("IP Address: {}", ip_address.to_string()) } mod tests { #[test] /// Tests if an IP is converted to a string /// correctly using the ToString trait fn ip_to_string() { use super::*; let ip = IpAddr::V4(192, 168, 0, 1); assert_eq!(ip.to_string(), "192.168.0.1") } #[test] /// Tests if an IP is converted from a string /// correctly using the FromString trait fn string_to_ip() { use super::*; let ip = "127.0.0.1"; assert_eq!(IpAddr::from_str(ip).unwrap(), IpAddr::V4(127, 0, 0, 1)) } #[test] #[should_panic] ///Tests if an invalid Ip will cause a panic when /// converting from a string to an IpAddr fn invalid_string_to_ip() { use super::*; let ip = "127.0.0.0.1"; IpAddr::from_str(ip).unwrap(); assert_eq!(IpAddr::from_str(ip), Err(NetworkingErr::InvalidIPErr)) } }