Added to_arr and from_arr methods to IpAddr
This commit is contained in:
		@@ -19,6 +19,45 @@ pub enum IpAddr {
 | 
			
		||||
    V6(String)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl IpAddr {
 | 
			
		||||
    /// Function that generates ar array of 4 octets / error 
 | 
			
		||||
    /// from an IpAddr
 | 
			
		||||
    /// 
 | 
			
		||||
    /// # Limitation
 | 
			
		||||
    /// Currently only works for IPs of type IPv4 
 | 
			
		||||
    /// # Example
 | 
			
		||||
    /// ```
 | 
			
		||||
    /// let ip: IpAddr = IpAddr::V4(127, 0, 0, 1);
 | 
			
		||||
    /// 
 | 
			
		||||
    /// let ip_add: [u8; 4] = ip.to_arr();
 | 
			
		||||
    /// /// 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)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Function that generates a IpAddr / Err from an array of 
 | 
			
		||||
    /// a octests
 | 
			
		||||
    /// 
 | 
			
		||||
    /// # Limitation
 | 
			
		||||
    /// Currently only works for IPs of type IPv4 
 | 
			
		||||
    /// # Example
 | 
			
		||||
    /// ```
 | 
			
		||||
    /// let ip_add: [u8; 4] = [127, 0, 0, 1];
 | 
			
		||||
    /// 
 | 
			
		||||
    /// let ip: IpAddr = IpAddr::V4(127, 0, 0, 1);
 | 
			
		||||
    /// /// ip_add = [127, 0, 0, 1]
 | 
			
		||||
    /// ```
 | 
			
		||||
    pub fn from_arr(arr: &[u8; 4]) -> Result<IpAddr, NetworkingErr> {
 | 
			
		||||
        Ok(IpAddr::V4(arr[0], arr[1], arr[2], arr[3]))
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl ToString for IpAddr {
 | 
			
		||||
    /// Function that returns an IP address in string form
 | 
			
		||||
    fn to_string(&self) -> String {
 | 
			
		||||
@@ -29,7 +68,6 @@ impl ToString for IpAddr {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
impl FromStr for IpAddr {
 | 
			
		||||
    type Err = NetworkingErr;
 | 
			
		||||
    /// Function that generates a IpAddr / Err from a string
 | 
			
		||||
@@ -85,7 +123,6 @@ mod tests {
 | 
			
		||||
    /// 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")
 | 
			
		||||
    }
 | 
			
		||||
@@ -109,4 +146,24 @@ mod tests {
 | 
			
		||||
        IpAddr::from_str(ip).unwrap();
 | 
			
		||||
        assert_eq!(IpAddr::from_str(ip), Err(NetworkingErr::InvalidIPErr))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    /// Tests the conversion of an IPv4 Address to
 | 
			
		||||
    /// an array
 | 
			
		||||
    fn ipaddr_to_arr() {
 | 
			
		||||
        use super::*;
 | 
			
		||||
        let mut ip_addr = IpAddr::V4(127, 0, 0, 1);
 | 
			
		||||
        assert_eq!(ip_addr.to_arr().unwrap(), [127, 0, 0, 1]);
 | 
			
		||||
        ip_addr = IpAddr::V6("::".to_string());
 | 
			
		||||
        assert_eq!(ip_addr.to_arr().unwrap_err(), NetworkingErr::InvalidIPErr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[test]
 | 
			
		||||
    /// Tests the conversion of an array to
 | 
			
		||||
    // an IPv4 Address
 | 
			
		||||
    fn arr_to_ipaddr() {
 | 
			
		||||
        use super::*;
 | 
			
		||||
        let mut ip_addr: [u8; 4] = [127, 0, 0, 1];
 | 
			
		||||
        assert_eq!(IpAddr::from_arr(&ip_addr).unwrap(), IpAddr::V4(127, 0, 0, 1));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
use std::{str::FromStr};
 | 
			
		||||
use std::str::FromStr;
 | 
			
		||||
use ip::IpAddr;
 | 
			
		||||
 | 
			
		||||
pub mod ip;
 | 
			
		||||
@@ -12,7 +12,6 @@ pub enum NetworkingErr {
 | 
			
		||||
    InvalidIPErr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#[allow(unused)]
 | 
			
		||||
pub struct Network {
 | 
			
		||||
    network_address: IpAddr,
 | 
			
		||||
@@ -45,28 +44,58 @@ impl Network {
 | 
			
		||||
    /// ```
 | 
			
		||||
    pub fn create_subnet(network_address: &IpAddr, cidr: u8) -> Result<Vec<Network>, NetworkingErr> {
 | 
			
		||||
        //Get number of host and network bits.
 | 
			
		||||
        let subnet_mask = match Network::gen_subnet_mask(cidr) {
 | 
			
		||||
            Ok(ip) => ip,
 | 
			
		||||
            Err(_) => return Err(NetworkingErr::InvalidCIDRErr)
 | 
			
		||||
        };
 | 
			
		||||
        let subnet_mask = Network::gen_subnet_mask(cidr)?.to_arr()?;
 | 
			
		||||
        let network_address = network_address.to_arr()?;
 | 
			
		||||
 | 
			
		||||
        let network_bits = match subnet_mask {
 | 
			
		||||
            IpAddr::V4(oct1, oct2, oct3, oct4) => {
 | 
			
		||||
                oct1.count_zeros() + oct2.count_zeros() + oct3.count_zeros() + oct4.count_zeros()
 | 
			
		||||
            },
 | 
			
		||||
            IpAddr::V6(_) => return Err(NetworkingErr::InvalidIPErr)
 | 
			
		||||
        };
 | 
			
		||||
        let mut network_bits: u8 = Default::default();
 | 
			
		||||
        let mut host_bits: u8 = Default::default();
 | 
			
		||||
 | 
			
		||||
        //Determine the number of networks needed for the subnet. 
 | 
			
		||||
        let num_networks = get_num_networks(network_bits);
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        //Get first address of each network
 | 
			
		||||
        //Need to get the most significant octet
 | 
			
		||||
        //Get number of bits available for host in specific octet
 | 
			
		||||
        //Determine Spacing 
 | 
			
		||||
        let mut most_sig_octet: usize = Default::default();
 | 
			
		||||
        for (i, oct) in subnet_mask.iter().enumerate(){
 | 
			
		||||
            if *oct < 255 {
 | 
			
		||||
                most_sig_octet = i;
 | 
			
		||||
                network_bits = oct.count_ones() as u8;
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            //There is no significant octet
 | 
			
		||||
            if i >= 4 {
 | 
			
		||||
                return Err(NetworkingErr::InvalidSubnetMask);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Determine the number of networks needed for the subnet.
 | 
			
		||||
        host_bits = subnet_mask.map(|o| o.count_zeros() as u8).iter().sum();
 | 
			
		||||
        host_bits -= network_bits;
 | 
			
		||||
 | 
			
		||||
        //Determine Spacing
 | 
			
		||||
        let network_spacing = 2 ^ subnet_mask[most_sig_octet].count_ones() as u8;
 | 
			
		||||
 | 
			
		||||
        //Determine number of networks in the subnet
 | 
			
		||||
        let mut num_networks: u8 = 0;
 | 
			
		||||
        for i in 1..network_bits {
 | 
			
		||||
            num_networks += 2^i;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Generate base address
 | 
			
		||||
        let mut base_address =  network_address;
 | 
			
		||||
        base_address[most_sig_octet] = 255 - num_networks;
 | 
			
		||||
        for i in most_sig_octet+1..=4 {
 | 
			
		||||
            base_address[i] = 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //Use Class constructor to generate each network.
 | 
			
		||||
        Ok(vec![Network::new(&IpAddr::V4(0, 0, 0, 0), &IpAddr::V4(0, 0, 0, 0))])
 | 
			
		||||
        let mut networks = vec![];
 | 
			
		||||
        for i in 0..num_networks {
 | 
			
		||||
            let mut new_ip = base_address;
 | 
			
		||||
            new_ip[most_sig_octet] += i * network_spacing;
 | 
			
		||||
            
 | 
			
		||||
            let new_network = Network::new(&IpAddr::from_arr(&new_ip)?, &IpAddr::from_arr(&subnet_mask)?);
 | 
			
		||||
            networks.push(new_network);
 | 
			
		||||
        }
 | 
			
		||||
        Ok(networks)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// Function that takes in a u8 CIDR and converts it to an IP address.
 | 
			
		||||
@@ -104,16 +133,6 @@ impl Network {
 | 
			
		||||
    //pub fn generate_subnets(self) -> Vec<Network> {}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_num_networks(mut network_bits: u8) -> u8 {
 | 
			
		||||
    for _ in 0..4 {
 | 
			
		||||
        if (network_bits / 8) > 1 {
 | 
			
		||||
            network_bits -= 8;
 | 
			
		||||
            continue;         
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    network_bits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// Function that takes in a string reference and returns the result of splitting a string into 
 | 
			
		||||
/// both its Address and CIDR
 | 
			
		||||
/// 
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user