nell 0.3.0

Linux netlink interface
Documentation
// Copyright (C) 2018 - Will Glozer. All rights reserved.

use std::convert::TryFrom;
use std::iter;
use crate::err::Invalid;
use crate::ffi::*;
use crate::sys::{Cursor, Bytes, Message};
use super::{IFA, IFLA, NDA, RTA};

#[derive(Debug)]
pub enum Any<'a> {
    IFAddr(Message<'a, ifaddrmsg>),
    IFInfo(Message<'a, ifinfomsg>),
    Peer(Message<'a, ndmsg>),
    Route(Message<'a, rtmsg>),
    Unsupported(u16, Cursor<'a>),
}

impl<'a> Message<'a, ifaddrmsg> {
    pub fn attrs(&self) -> impl Iterator<Item = Result<IFA<'a>, Invalid>> {
        let mut tail = self.tail();
        iter::from_fn(move || tail.next().map(IFA::try_from))
    }
}

impl<'a> Message<'a, ifinfomsg> {
    pub fn attrs(&self) -> impl Iterator<Item = Result<IFLA<'a>, Invalid>> {
        let mut tail = self.tail();
        iter::from_fn(move || tail.next().map(IFLA::try_from))
    }
}

impl<'a> Message<'a, ndmsg> {
    pub fn attrs(&self) -> impl Iterator<Item = Result<NDA<'a>, Invalid>> {
        let mut tail = self.tail();
        iter::from_fn(move || tail.next().map(NDA::try_from))
    }
}

impl<'a> Message<'a, rtmsg> {
    pub fn attrs(&self) -> impl Iterator<Item = Result<RTA<'a>, Invalid>> {
        let mut tail = self.tail();
        iter::from_fn(move || tail.next().map(RTA::try_from))
    }
}

impl<'a> Message<'a, inet_diag_msg> {
    pub fn info<T: Bytes>(&self) -> Option<T> {
        let mut tail = self.tail();
        while let Some((attr, mut tail)) = tail.next::<rtattr>() {
            if attr.rta_type == INET_DIAG_INFO {
                return Some(tail.next()?.0);
            }
        }
        None
    }
}

impl<'a> Message<'a, ()> {
    pub fn any(&self) -> Any<'a> {
        match self.nlmsg_type() {
            RTM_NEWADDR  | RTM_DELADDR  => Any::IFAddr(self.msg()),
            RTM_NEWLINK  | RTM_DELLINK  => Any::IFInfo(self.msg()),
            RTM_NEWNEIGH | RTM_DELNEIGH => Any::Peer(self.msg()),
            RTM_NEWROUTE | RTM_DELROUTE => Any::Route(self.msg()),
            kind                        => Any::Unsupported(kind, self.tail()),
        }
    }

    fn msg<T: Bytes + Default>(&self) -> Message<'a, T> {
        let (head, _, mut tail) = self.parts();
        let (data, tail) = tail.next().unwrap_or_default();
        Message::with(head.clone(), data, tail)
    }
}