use std::{mem, ptr};
#[derive(Copy, Clone)]
#[repr(align(8))] pub struct Aligned<T>(pub T);
pub struct Encoder<'a> {
hdr: &'a mut libc::msghdr,
cmsg: Option<&'a mut libc::cmsghdr>,
len: usize,
}
impl<'a> Encoder<'a> {
pub unsafe fn new(hdr: &'a mut libc::msghdr) -> Self {
Self {
cmsg: libc::CMSG_FIRSTHDR(hdr).as_mut(),
hdr,
len: 0,
}
}
pub fn push<T: Copy + ?Sized>(&mut self, level: libc::c_int, ty: libc::c_int, value: T) {
assert!(mem::align_of::<T>() <= mem::align_of::<libc::cmsghdr>());
let space = unsafe { libc::CMSG_SPACE(mem::size_of_val(&value) as _) as usize };
assert!(
self.hdr.msg_controllen as usize >= self.len + space,
"control message buffer too small"
);
let cmsg = self.cmsg.take().expect("no control buffer space remaining");
cmsg.cmsg_level = level;
cmsg.cmsg_type = ty;
cmsg.cmsg_len = unsafe { libc::CMSG_LEN(mem::size_of_val(&value) as _) } as _;
unsafe {
ptr::write(libc::CMSG_DATA(cmsg) as *const T as *mut T, value);
}
self.len += space;
self.cmsg = unsafe { libc::CMSG_NXTHDR(self.hdr, cmsg).as_mut() };
}
pub fn finish(self) {
}
}
impl<'a> Drop for Encoder<'a> {
fn drop(&mut self) {
self.hdr.msg_controllen = self.len as _;
}
}
pub unsafe fn decode<T: Copy>(cmsg: &libc::cmsghdr) -> T {
assert!(mem::align_of::<T>() <= mem::align_of::<libc::cmsghdr>());
debug_assert_eq!(
cmsg.cmsg_len as usize,
libc::CMSG_LEN(mem::size_of::<T>() as _) as usize
);
ptr::read(libc::CMSG_DATA(cmsg) as *const T)
}
pub struct Iter<'a> {
hdr: &'a libc::msghdr,
cmsg: Option<&'a libc::cmsghdr>,
}
impl<'a> Iter<'a> {
pub unsafe fn new(hdr: &'a libc::msghdr) -> Self {
Self {
hdr,
cmsg: libc::CMSG_FIRSTHDR(hdr).as_ref(),
}
}
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a libc::cmsghdr;
fn next(&mut self) -> Option<&'a libc::cmsghdr> {
let current = self.cmsg.take()?;
self.cmsg = unsafe { libc::CMSG_NXTHDR(self.hdr, current).as_ref() };
Some(current)
}
}