nell 0.3.0

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

use std::cmp::min;
use std::marker::PhantomData;
use std::mem::size_of;
use std::ptr::read_unaligned;
use std::slice;
use std::str::{self, Utf8Error};
use super::{align, Bytes};

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Cursor<'a> {
    ptr: *const u8,
    len: usize,
    pha: PhantomData<&'a ()>,
}

impl<'a> Cursor<'a> {
    fn new(ptr: *const u8, len: usize) -> Self {
        Self { ptr, len, pha: PhantomData }
    }

    pub fn next<T: Bytes>(&mut self) -> Option<(T, Self)> {
        unsafe {
            let size = align(size_of::<T>());
            self.len = self.len.checked_sub(size)?;
            let item = read_unaligned(self.ptr as *const T);
            self.ptr = self.ptr.add(size);

            let max  = self.len;
            let size = min(item.tail(max), max);
            let tail = Self::new(self.ptr, size);

            let size = min(align(size), max);
            self.len = self.len.checked_sub(size)?;
            self.ptr = self.ptr.add(size);

            Some((item, tail))
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub fn asciiz(self) -> Result<&'a str, Utf8Error> {
        let len = self.len.saturating_sub(1);
        str::from_utf8(self.slice(len))
    }

    pub fn bytes(self) -> &'a [u8] {
        self.slice(self.len)
    }

    pub fn copy<T: Bytes>(self) -> T {
        self.read()
    }

    fn slice(&self, len: usize) -> &'a [u8] {
        assert!(len <= self.len);
        unsafe {
            slice::from_raw_parts(self.ptr, len)
        }
    }

    fn read<T: Bytes>(&self) -> T {
        assert!(size_of::<T>() <= self.len);
        unsafe {
            read_unaligned(self.ptr as *const T)
        }
    }
}

impl Default for Cursor<'_> {
    fn default() -> Self {
        static EMPTY: &[u8] = &[];
        Self {
            ptr: EMPTY.as_ptr(),
            len: 0,
            pha: PhantomData,
        }
    }
}

impl<'a> From<&'a [u8]> for Cursor<'a> {
    fn from(slice: &'a [u8]) -> Self {
        Self::new(slice.as_ptr(), slice.len())
    }
}