xand-api-proto 49.0.0

Protobuf definitions for the Xand API
Documentation
use core::{
    fmt::{Debug, Display, Formatter},
    str::FromStr,
};

/// IPv4 CIDR Block, with first four indices the ip address and last being the suffix
#[derive(
    derive_more::From,
    derive_more::Into,
    derive_more::Deref,
    Copy,
    Clone,
    Debug,
    Hash,
    Eq,
    PartialEq,
    serde::Serialize,
    serde::Deserialize,
)]
pub struct CidrBlock(pub [u8; 5]);

#[derive(Debug, Clone)]
pub struct CidrBlockParseErr;
impl FromStr for CidrBlock {
    type Err = CidrBlockParseErr;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let ip_and_suffix: Vec<&str> = s.split('/').collect();
        if ip_and_suffix.len() != 2 {
            return Err(CidrBlockParseErr);
        }
        let mut cidr_block_strings: Vec<&str> = ip_and_suffix[0].split('.').collect();
        if cidr_block_strings.len() != 4 {
            return Err(CidrBlockParseErr);
        }
        cidr_block_strings.push(ip_and_suffix[1]);
        let mut array = [0_u8; 5];
        for i in 0..array.len() {
            array[i] = match cidr_block_strings[i].parse().ok() {
                Some(x) => x,
                None => return Err(CidrBlockParseErr),
            }
        }
        Ok(array.into())
    }
}

impl Display for CidrBlock {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
        write!(
            f,
            "{}.{}.{}.{}/{}",
            self[0], self[1], self[2], self[3], self[4]
        )
    }
}

#[test]
fn test_convert_cidr_block_to_string() {
    let block: CidrBlock = [1, 2, 3, 4, 5].into();
    let converted = block.to_string();
    assert_eq!(converted, "1.2.3.4/5");
}