diff --git a/src/ip.rs b/src/ip.rs index 52e5c0c..65f2785 100644 --- a/src/ip.rs +++ b/src/ip.rs @@ -1,17 +1,17 @@ -use std::str::FromStr; use super::NetworkingErr; +use std::str::FromStr; #[derive(Debug, PartialEq, Eq)] pub struct InvalidIPErr; /// Ip address enum that includes associated type -/// +/// /// # Example /// ``` /// //Loopback Addresses: /// use subnet_calculator::ip::IpAddr; /// use std::str::FromStr; -/// +/// /// IpAddr::V4(127, 0, 0, 1); /// IpAddr::V6(String::from("::1")); /// ``` @@ -19,44 +19,42 @@ pub struct InvalidIPErr; #[derive(Debug, PartialEq, Eq, Clone)] pub enum IpAddr { V4(u8, u8, u8, u8), - V6(String) + V6(String), } impl IpAddr { - /// Function that generates ar array of 4 octets / error + /// Function that generates ar array of 4 octets / error /// from an IpAddr - /// + /// /// # Limitation - /// Currently only works for IPs of type IPv4 + /// Currently only works for IPs of type IPv4 /// # Example /// ``` /// use subnet_calculator::ip::IpAddr; - /// + /// /// let ip: IpAddr = IpAddr::V4(127, 0, 0, 1); - /// + /// /// let ip_add: [u8; 4] = ip.to_arr().unwrap(); /// assert_eq!(ip_add, [127, 0, 0, 1]); /// ``` pub fn to_arr(&self) -> Result<[u8; 4], NetworkingErr> { match self { - IpAddr::V4(o1, o2, o3, o4) => { - Ok([*o1, *o2, *o3, *o4]) - } - _ => Err(NetworkingErr::InvalidIPErr) + IpAddr::V4(o1, o2, o3, o4) => Ok([*o1, *o2, *o3, *o4]), + _ => Err(NetworkingErr::InvalidIPErr), } } - /// Function that generates a IpAddr / Err from an array of + /// Function that generates a IpAddr / Err from an array of /// a octests - /// + /// /// # Limitation - /// Currently only works for IPs of type IPv4 + /// Currently only works for IPs of type IPv4 /// # Example /// ``` /// use subnet_calculator::ip::IpAddr; - /// + /// /// let ip_add: [u8; 4] = [127, 0, 0, 1]; - /// + /// /// let ip: IpAddr = IpAddr::from_arr(&ip_add).unwrap(); /// assert_eq!(ip, IpAddr::V4(127, 0, 0, 1)); /// ``` @@ -68,15 +66,15 @@ impl IpAddr { impl From for u32 { /// Function that converts an Ip address /// into an Unsigned 32 bit integer. - /// + /// /// # Limitation /// Currently only works for IPs of type IPv4 /// # Example /// ``` /// use subnet_calculator::ip::IpAddr; - /// + /// /// let ip: IpAddr = IpAddr::V4(127, 0, 0, 1); - /// + /// /// let ip_u32: u32 = u32::from(ip); /// assert_eq!(ip_u32, 2130706433); /// ``` @@ -88,15 +86,15 @@ impl From for u32 { impl From for IpAddr { /// Function that converts an Unsigned 32-bit Ip address /// into an IpAddr - /// + /// /// # Limitation - /// Currently only works for IPs of type IPv4 + /// Currently only works for IPs of type IPv4 /// # Example /// ``` /// use subnet_calculator::ip::IpAddr; - /// + /// /// let ip: u32 = 2_130_706_433; - /// + /// /// let ip_addr: IpAddr = IpAddr::from(ip); /// assert_eq!(ip_addr, IpAddr::V4(127, 0, 0, 1)); /// ``` @@ -110,7 +108,7 @@ impl ToString for IpAddr { fn to_string(&self) -> String { match self { IpAddr::V4(oct1, oct2, oct3, oct4) => format!("{}.{}.{}.{}", oct1, oct2, oct3, oct4), - IpAddr::V6(addr) => format!("{}", addr) + IpAddr::V6(addr) => format!("{}", addr), } } } @@ -118,16 +116,16 @@ impl ToString for IpAddr { 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 + /// Currently only works for IPs of type IPv4 /// # Example /// ``` /// use subnet_calculator::ip::IpAddr; /// use std::str::FromStr; - /// + /// /// let ip: &str = "127.0.0.1"; - /// + /// /// let parsed_ip: IpAddr = IpAddr::from_str(ip).unwrap(); /// assert_eq!(parsed_ip, IpAddr::V4(127,0,0,1)); /// ``` @@ -135,18 +133,18 @@ impl FromStr for IpAddr { let split_ip = s.split('.'); if split_ip.clone().count() != 4 { //Invalid IP address entered - return Err(super::NetworkingErr::InvalidIPErr) + 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) + return Err(NetworkingErr::InvalidIPErr); } match oct.parse::() { Ok(parsed_oct) => ip[i] = parsed_oct, - Err(_) => return Err(NetworkingErr::InvalidIPErr) + Err(_) => return Err(NetworkingErr::InvalidIPErr), } } Ok(IpAddr::from_arr(&ip)?) @@ -154,13 +152,13 @@ impl FromStr for IpAddr { } /// Function that takes in an IP address and then prints a formatted string to the CLI -/// +/// /// # Example /// ``` /// use subnet_calculator::ip::{IpAddr, print_ip}; -/// +/// /// let ip = IpAddr::V4(127, 0, 0, 1); -/// +/// /// print_ip(ip); /// //Output: IP Address: 127.0.0.1 /// ``` @@ -171,7 +169,7 @@ pub fn print_ip(ip_address: IpAddr) { mod tests { #[test] - /// Tests if an IP is converted to a string + /// Tests if an IP is converted to a string /// correctly using the ToString trait fn ip_to_string() { use super::*; @@ -216,7 +214,10 @@ mod tests { fn arr_to_ipaddr() { use super::*; let ip_addr: [u8; 4] = [127, 0, 0, 1]; - assert_eq!(IpAddr::from_arr(&ip_addr).unwrap(), IpAddr::V4(127, 0, 0, 1)); + assert_eq!( + IpAddr::from_arr(&ip_addr).unwrap(), + IpAddr::V4(127, 0, 0, 1) + ); } #[test] @@ -226,7 +227,7 @@ mod tests { use super::*; let ip = IpAddr::V4(0, 0, 0, 0); assert_eq!(0, u32::from(ip)); - + let ip = IpAddr::V4(127, 0, 0, 1); assert_eq!(2_130_706_433, u32::from(ip)); @@ -240,12 +241,11 @@ mod tests { #[test] /// Tests the conversion of an u32 IPv4 Address to /// an IpAddr - fn u32_to_ipaddr() - { + fn u32_to_ipaddr() { use super::*; let ip = u32::from(IpAddr::V4(0, 0, 0, 0)); assert_eq!(IpAddr::V4(0, 0, 0, 0), IpAddr::from(ip)); - + let ip = u32::from(IpAddr::V4(127, 0, 0, 1)); assert_eq!(IpAddr::V4(127, 0, 0, 1), IpAddr::from(ip)); @@ -255,4 +255,4 @@ mod tests { let ip = u32::from(IpAddr::V4(255, 255, 255, 255)); assert_eq!(IpAddr::V4(255, 255, 255, 255), IpAddr::from(ip)); } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index e8b2df1..38433f5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,7 @@ pub enum NetworkingErr { InvalidCIDRErr, InvalidSubnetMask, InvalidNetwork, - InvalidIPErr + InvalidIPErr, } /// enum to allow the identification of the class of the network @@ -17,7 +17,7 @@ pub enum NetworkingErr { enum NetworkClass { A = 8, B = 16, - C = 24 + C = 24, } #[allow(unused)] @@ -36,30 +36,29 @@ pub struct Subnet { } impl Network { - #[allow(unused)] /// Function that constucts a network struct. - /// + /// /// ``` - /// //Awaiting implementation before creating doctest + /// //Awaiting implementation before creating doctest /// //let network = Network::new(&IpAddr::V4(127, 0, 0, 1), 32); /// ``` fn new(given_address: &IpAddr, broadcast_address: &IpAddr, num_hosts: u32) -> Network { - Network { - network_address: given_address.clone(), - broadcast_addr: broadcast_address.clone(), - num_hosts, + Network { + network_address: given_address.clone(), + broadcast_addr: broadcast_address.clone(), + num_hosts, } } /// Function that constucts a subnet, returning a vector of all subnets included - /// + /// /// ``` /// use subnet_calculator::ip::IpAddr; /// use subnet_calculator::Network; - /// + /// /// let subnets = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 16).unwrap(); - /// + /// /// assert_eq!(subnets.networks.len(), 256); /// ``` pub fn create_subnet(network_address: &IpAddr, cidr: u8) -> Result { @@ -69,17 +68,17 @@ impl Network { // If the CIDR < class network enum associated value, then there is an invalid subnet. if cidr < network_class as u8 { - return Err(NetworkingErr::InvalidCIDRErr) - } + return Err(NetworkingErr::InvalidCIDRErr); + } // Determine the starting network let mut base_network = network_address.clone(); let most_sig_octet: u8 = match network_class { NetworkClass::A => 1, NetworkClass::B => 2, - NetworkClass::C => 3 - }; - + NetworkClass::C => 3, + }; + for i in most_sig_octet..4 { base_network[i as usize] = 0; } @@ -99,24 +98,32 @@ impl Network { // Determine how many networks are available // We know that this value is >0 at this point let num_networks = u32::pow(2, num_borrowed_bits as u32); - + // The broadcast address will always be 1 less than the next subnet network address let mut broadcast_addr = (base_addr + addr_increment) - 1; - + //Create the subnets - let mut subnet = Subnet::new(&IpAddr::from(base_addr), &IpAddr::from(broadcast_addr), num_hosts, cidr)?; + let mut subnet = Subnet::new( + &IpAddr::from(base_addr), + &IpAddr::from(broadcast_addr), + num_hosts, + cidr, + )?; // Determine the networking gaps //If there is only 1 network, returning the base network will be sufficient if num_networks > 1 { - - for _ in 0..num_networks-1 { + for _ in 0..num_networks - 1 { //Increment address and append to list base_addr += addr_increment; // We can start adding the full subnet range now instead of 1 less - broadcast_addr += addr_increment; - - subnet.networks.push(Network::new(&IpAddr::from(base_addr), &IpAddr::from(broadcast_addr), num_hosts)); + broadcast_addr += addr_increment; + + subnet.networks.push(Network::new( + &IpAddr::from(base_addr), + &IpAddr::from(broadcast_addr), + num_hosts, + )); } } @@ -124,39 +131,39 @@ impl Network { } /// Function that is used to determine the class of network that an IP is in. - /// + /// /// ```ignore /// use subnet_calculator::Network; - /// + /// /// let network_class = Network::get_network_class(&[127, 0, 0, 1]).unwrap(); /// assert_eq!(network_class, NetworkClass::A); /// ``` fn get_network_class(network_address: &IpAddr) -> Result { let network_address = network_address.to_arr()?; if network_address[0] > 224 { - return Err(NetworkingErr::InvalidIPErr) - }else if network_address[0] >= 192 { - return Ok(NetworkClass::C) - }else if network_address[0] >= 128 { - return Ok(NetworkClass::B) - }else if network_address[0] >= 1 { + return Err(NetworkingErr::InvalidIPErr); + } else if network_address[0] >= 192 { + return Ok(NetworkClass::C); + } else if network_address[0] >= 128 { + return Ok(NetworkClass::B); + } else if network_address[0] >= 1 { return Ok(NetworkClass::A); } - return Err(NetworkingErr::InvalidIPErr) + return Err(NetworkingErr::InvalidIPErr); } #[allow(unused)] /// Function that takes in a u8 CIDR and converts it to an IP address. - /// - /// ```ignore + /// + /// ```ignore /// let cidr: u8 = 22; /// let subnet_mask: [u8; 4] = gen_subnet_mask(cidr).unwrap(); - /// + /// /// assert_eq!(subnet_mask, IpAddr::V4(255, 255, 252, 0)); /// ``` fn gen_subnet_mask(mut cidr: u8) -> Result { if cidr > 32 { - return Err(NetworkingErr::InvalidCIDRErr) + return Err(NetworkingErr::InvalidCIDRErr); } let mut oct: [u8; 4] = [0; 4]; @@ -165,10 +172,10 @@ impl Network { *octet = if usize::from(cidr) >= 8 { cidr -= 8; u8::MAX - }else{ + } else { // Count the number of remaining 1s and convert to binary let mut count: u8 = 0; - for i in ((8-cidr)..8).rev() { + for i in ((8 - cidr)..8).rev() { count += u8::pow(2, u32::from(i)); } cidr = 0; @@ -181,22 +188,22 @@ impl Network { //pub fn generate_subnets(self) -> Vec {} } -/// Function that takes in a string reference and returns the result of splitting a string into +/// Function that takes in a string reference and returns the result of splitting a string into /// both its Address and CIDR -/// +/// /// ``` /// use subnet_calculator::ip_and_cidr_from_string; /// use subnet_calculator::ip::IpAddr; -/// +/// /// let ip_string = String::from("192.168.0.1/24"); /// let result = match ip_and_cidr_from_string(&ip_string) { /// Err(_) => panic!(), /// Ok(ip_and_cidr) => ip_and_cidr /// }; -/// +/// /// assert_eq!(result, (IpAddr::V4(192, 168, 0, 1), 24)); /// ``` -pub fn ip_and_cidr_from_string(ip_and_cidr: &String) -> Result<(IpAddr, u8), ip::InvalidIPErr>{ +pub fn ip_and_cidr_from_string(ip_and_cidr: &String) -> Result<(IpAddr, u8), ip::InvalidIPErr> { let mut cidr: u8 = Default::default(); let mut ip: String = Default::default(); @@ -205,34 +212,42 @@ pub fn ip_and_cidr_from_string(ip_and_cidr: &String) -> Result<(IpAddr, u8), ip: if split_ip_cidr.clone().count() > 2 { return Err(ip::InvalidIPErr); } - ip = split_ip_cidr.clone().into_iter().next().unwrap_or("0.0.0.0").to_owned(); + ip = split_ip_cidr + .clone() + .into_iter() + .next() + .unwrap_or("0.0.0.0") + .to_owned(); cidr = match split_ip_cidr.into_iter().last() { None => return Err(ip::InvalidIPErr), Some(cidr) => match cidr.trim().parse::() { Err(_) => return Err(ip::InvalidIPErr), - Ok(cidr) => cidr - } + Ok(cidr) => cidr, + }, }; } - + let ip_address: IpAddr = match IpAddr::from_str(&ip.trim()) { Err(_) => return Err(ip::InvalidIPErr), Ok(ip) => ip, }; - return Ok((ip_address, cidr)) + return Ok((ip_address, cidr)); } impl Subnet { /// Function to return a new subbet struct /// - fn new(base_address: &IpAddr, broadcast_addr: &IpAddr, num_hosts: u32, cidr: u8) -> Result { - Ok( - Subnet { - networks: vec![Network::new(base_address, broadcast_addr, num_hosts)], - subnet_mask: Network::gen_subnet_mask(cidr)?, - } - ) + fn new( + base_address: &IpAddr, + broadcast_addr: &IpAddr, + num_hosts: u32, + cidr: u8, + ) -> Result { + Ok(Subnet { + networks: vec![Network::new(base_address, broadcast_addr, num_hosts)], + subnet_mask: Network::gen_subnet_mask(cidr)?, + }) } } @@ -245,7 +260,7 @@ mod tests { let ip_string = String::from("127.0.0.1/8"); let result = match ip_and_cidr_from_string(&ip_string) { Err(_) => panic!(), - Ok(ip_and_cidr) => ip_and_cidr + Ok(ip_and_cidr) => ip_and_cidr, }; assert_eq!(result.0, IpAddr::V4(127, 0, 0, 1)); assert_eq!(result.1, 8); @@ -255,61 +270,137 @@ mod tests { fn cidr_to_ip_test() { use super::*; - assert_eq!(Network::gen_subnet_mask(22).unwrap(), IpAddr::V4(255, 255, 252, 0)); - assert_eq!(Network::gen_subnet_mask(24).unwrap(), IpAddr::V4(255, 255, 255, 0)); + assert_eq!( + Network::gen_subnet_mask(22).unwrap(), + IpAddr::V4(255, 255, 252, 0) + ); + assert_eq!( + Network::gen_subnet_mask(24).unwrap(), + IpAddr::V4(255, 255, 255, 0) + ); assert_eq!(Network::gen_subnet_mask(0).unwrap(), IpAddr::V4(0, 0, 0, 0)); - assert_eq!(Network::gen_subnet_mask(4).unwrap(), IpAddr::V4(240, 0, 0, 0)); - assert_eq!(Network::gen_subnet_mask(35).unwrap_err(), NetworkingErr::InvalidCIDRErr); + assert_eq!( + Network::gen_subnet_mask(4).unwrap(), + IpAddr::V4(240, 0, 0, 0) + ); + assert_eq!( + Network::gen_subnet_mask(35).unwrap_err(), + NetworkingErr::InvalidCIDRErr + ); } #[test] fn network_class_test() { use super::*; - assert_eq!(Network::get_network_class(&IpAddr::V4(127, 0, 0, 1)).unwrap(), NetworkClass::A); - assert_eq!(Network::get_network_class(&IpAddr::V4(172, 6, 8, 10)).unwrap(), NetworkClass::B); - assert_eq!(Network::get_network_class(&IpAddr::V4(192, 168, 0, 1)).unwrap(), NetworkClass::C); - assert_eq!(Network::get_network_class(&IpAddr::V4(10, 6, 8, 10)).unwrap(), NetworkClass::A); - assert_eq!(Network::get_network_class(&IpAddr::V4(225, 255, 255, 255)).unwrap_err(), NetworkingErr::InvalidIPErr); - assert_eq!(Network::get_network_class(&IpAddr::V4(225, 0, 0, 0)).unwrap_err(), NetworkingErr::InvalidIPErr); - assert_eq!(Network::get_network_class(&IpAddr::V4(0, 0, 0, 0)).unwrap_err(), NetworkingErr::InvalidIPErr); - assert_eq!(Network::get_network_class(&IpAddr::V4(0, 0, 0, 1)).unwrap_err(), NetworkingErr::InvalidIPErr); + assert_eq!( + Network::get_network_class(&IpAddr::V4(127, 0, 0, 1)).unwrap(), + NetworkClass::A + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(172, 6, 8, 10)).unwrap(), + NetworkClass::B + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(192, 168, 0, 1)).unwrap(), + NetworkClass::C + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(10, 6, 8, 10)).unwrap(), + NetworkClass::A + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(225, 255, 255, 255)).unwrap_err(), + NetworkingErr::InvalidIPErr + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(225, 0, 0, 0)).unwrap_err(), + NetworkingErr::InvalidIPErr + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(0, 0, 0, 0)).unwrap_err(), + NetworkingErr::InvalidIPErr + ); + assert_eq!( + Network::get_network_class(&IpAddr::V4(0, 0, 0, 1)).unwrap_err(), + NetworkingErr::InvalidIPErr + ); } #[test] fn subnet_creation_test() { use super::*; - assert_eq!(Network::create_subnet(&IpAddr::V4(192, 168, 0, 1), 23).unwrap_err(), NetworkingErr::InvalidCIDRErr); + assert_eq!( + Network::create_subnet(&IpAddr::V4(192, 168, 0, 1), 23).unwrap_err(), + NetworkingErr::InvalidCIDRErr + ); let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 1), 10).unwrap(); assert_eq!(networks.networks.len(), 4); - let networks = Network::create_subnet(&IpAddr::V4(192, 168, 200, 1), 31).unwrap().networks; + let networks = Network::create_subnet(&IpAddr::V4(192, 168, 200, 1), 31) + .unwrap() + .networks; assert_eq!(networks.len(), 128); - assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(192, 168, 200, 254)); - assert_eq!(networks.last().unwrap().broadcast_addr, IpAddr::V4(192, 168, 200, 255)); + assert_eq!( + networks.last().unwrap().network_address, + IpAddr::V4(192, 168, 200, 254) + ); + assert_eq!( + networks.last().unwrap().broadcast_addr, + IpAddr::V4(192, 168, 200, 255) + ); assert_eq!(networks.last().unwrap().num_hosts, 2); - - let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 8).unwrap().networks; + + let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 8) + .unwrap() + .networks; assert_eq!(networks.len(), 1); - assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(127, 0, 0, 0)); - assert_eq!(networks.last().unwrap().broadcast_addr, IpAddr::V4(127, 255, 255, 255)); + assert_eq!( + networks.last().unwrap().network_address, + IpAddr::V4(127, 0, 0, 0) + ); + assert_eq!( + networks.last().unwrap().broadcast_addr, + IpAddr::V4(127, 255, 255, 255) + ); assert_eq!(networks.last().unwrap().num_hosts, 16_777_216); - let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 9).unwrap().networks; + let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 9) + .unwrap() + .networks; assert_eq!(networks.len(), 2); - assert_eq!(networks.first().unwrap().network_address, IpAddr::V4(127, 0, 0, 0)); - assert_eq!(networks.first().unwrap().broadcast_addr, IpAddr::V4(127, 127, 255, 255)); + assert_eq!( + networks.first().unwrap().network_address, + IpAddr::V4(127, 0, 0, 0) + ); + assert_eq!( + networks.first().unwrap().broadcast_addr, + IpAddr::V4(127, 127, 255, 255) + ); - let networks = Network::create_subnet(&IpAddr::V4(168, 20, 0, 0), 17).unwrap().networks; + let networks = Network::create_subnet(&IpAddr::V4(168, 20, 0, 0), 17) + .unwrap() + .networks; assert_eq!(networks.len(), 2); - assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(168, 20, 128, 0)); - assert_eq!(networks.last().unwrap().broadcast_addr, IpAddr::V4(168, 20, 255, 255)); + assert_eq!( + networks.last().unwrap().network_address, + IpAddr::V4(168, 20, 128, 0) + ); + assert_eq!( + networks.last().unwrap().broadcast_addr, + IpAddr::V4(168, 20, 255, 255) + ); assert_eq!(networks.last().unwrap().num_hosts, 32_768); - let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 17).unwrap().networks; + let networks = Network::create_subnet(&IpAddr::V4(127, 0, 0, 0), 17) + .unwrap() + .networks; assert_eq!(networks.len(), 512); - assert_eq!(networks.last().unwrap().network_address, IpAddr::V4(127, 255, 128, 0)); + assert_eq!( + networks.last().unwrap().network_address, + IpAddr::V4(127, 255, 128, 0) + ); } }