taskstats 0.1.1

high-level encapsulation of Linux's per-task statistics interface
Documentation
use super::raw::{genlmsghdr, GENL_HDRLEN};
use crate::netlink::Serialize;
use thiserror::Error;
use zerocopy::LayoutVerified;

#[derive(Debug)]
pub struct GenericNetlinkMessage<P> {
    pub cmd: u8,
    pub version: u8,
    pub payload: P,
}

impl<P: Serialize> Serialize for GenericNetlinkMessage<P> {
    fn len(&self) -> u32 {
        GENL_HDRLEN + self.payload.len()
    }

    fn serialize(&self, buf: &mut [u8]) {
        let header_len = GENL_HDRLEN as usize;
        let (header, payload) = buf.split_at_mut(header_len);
        let mut header = LayoutVerified::<_, genlmsghdr>::new(header).expect("invalid buffer");
        header.cmd = self.cmd;
        header.version = self.version;
        header.reserved = 0;
        self.payload.serialize(payload);
    }
}

impl<'a> GenericNetlinkMessage<&'a [u8]> {
    pub fn deserialize(buf: &'a [u8]) -> Result<Self, InvalidBuffer> {
        let header_len = GENL_HDRLEN as usize;
        if buf.len() < header_len {
            return Err(InvalidBuffer::Header(buf.len()));
        }
        let (header, payload) = buf.split_at(header_len);
        let header = LayoutVerified::<_, genlmsghdr>::new(header).expect("invalid buffer");
        Ok(Self {
            cmd: header.cmd,
            version: header.version,
            payload,
        })
    }
}

#[derive(Debug, Error)]
pub enum InvalidBuffer {
    #[error("insufficient buffer for generic netlink header, got buffer size {0}")]
    Header(usize),
}