proc_getter 0.0.3

make retriving infomations from /proc/* easier
Documentation
use crate::{Error, Result};
use std::convert::From;
use std::net::Ipv4Addr;
use std::str::FromStr;

#[derive(Debug, PartialEq, Eq)]
pub struct MacAddr([u8; 6]);

impl From<[u8; 6]> for MacAddr {
    fn from(s: [u8; 6]) -> Self {
        MacAddr(s)
    }
}

impl FromStr for MacAddr {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let columns: Vec<&str> = s.split(':').collect();
        if columns.len() != 6 {
            return Err(Error::BadFormat);
        }

        let mut et = [0; 6];
        for (e, v) in et.iter_mut().zip(columns.into_iter()) {
            *e = u8::from_str_radix(v, 16)?;
        }

        Ok(et.into())
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct Arp {
    ip_addr: Ipv4Addr,
    hw_type: u16,
    flags: i32,
    hw_addr: MacAddr,
    mask: String,
    device: String,
}

impl FromStr for Arp {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self> {
        let columns: Vec<&str> = s.split_ascii_whitespace().collect();
        if columns.len() != 6 {
            return Err(Error::BadFormat);
        }

        let ip_addr = columns[0].parse::<Ipv4Addr>()?;
        let hw_type = u16::from_str_radix(columns[1].trim_start_matches("0x"), 16)?;
        let flags = i32::from_str_radix(columns[2].trim_start_matches("0x"), 16)?;
        let hw_addr = columns[3].parse::<MacAddr>()?;
        let mask = columns[4].to_string();
        let device = columns[5].to_string();

        Ok(Arp {
            ip_addr,
            hw_type,
            flags,
            hw_addr,
            mask,
            device,
        })
    }
}

#[inline(always)]
fn to_arp(line: &str) -> Result<Arp> {
    Arp::from_str(line)
}

default_list! {
    arp, "/proc/net/arp", Arp, to_arp, '\n', 1
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn parse_arp() {
        let content = "192.168.0.50   0x1       0x2       00:50:BF:25:68:F3   *      eth0";
        let arp = content.parse::<Arp>().unwrap();
        assert_eq!(arp.ip_addr, Ipv4Addr::new(192, 168, 0, 50));
        assert_eq!(arp.hw_type, 1);
        assert_eq!(arp.flags, 2);
        assert_eq!(arp.hw_addr, MacAddr([0, 80, 191, 37, 104, 243]));
        assert_eq!(arp.mask, "*".to_string());
        assert_eq!(arp.device, "eth0".to_string());
    }
}