1use std::{marker::PhantomData, mem::MaybeUninit};
2
3cfg_if::cfg_if! {
4 if #[cfg(windows)] {
5 #[path = "windows.rs"]
6 mod sys;
7 } else if #[cfg(unix)] {
8 #[path = "unix.rs"]
9 mod sys;
10 }
11}
12
13pub struct CMsgRef<'a>(sys::CMsgRef<'a>);
15
16impl CMsgRef<'_> {
17 pub fn level(&self) -> i32 {
19 self.0.level()
20 }
21
22 pub fn ty(&self) -> i32 {
24 self.0.ty()
25 }
26
27 #[allow(clippy::len_without_is_empty)]
29 pub fn len(&self) -> usize {
30 self.0.len() as _
31 }
32
33 pub unsafe fn data<T>(&self) -> &T {
40 unsafe { self.0.data() }
41 }
42}
43
44pub struct CMsgIter<'a> {
46 inner: sys::CMsgIter,
47 _p: PhantomData<&'a ()>,
48}
49
50impl<'a> CMsgIter<'a> {
51 pub unsafe fn new(buffer: &'a [u8]) -> Self {
62 Self {
63 inner: sys::CMsgIter::new(buffer.as_ptr(), buffer.len()),
64 _p: PhantomData,
65 }
66 }
67}
68
69impl<'a> Iterator for CMsgIter<'a> {
70 type Item = CMsgRef<'a>;
71
72 fn next(&mut self) -> Option<Self::Item> {
73 unsafe {
74 let cmsg = self.inner.current();
75 self.inner.next();
76 cmsg.map(CMsgRef)
77 }
78 }
79}
80
81pub struct CMsgBuilder<'a> {
83 inner: sys::CMsgIter,
84 len: usize,
85 _p: PhantomData<&'a mut ()>,
86}
87
88impl<'a> CMsgBuilder<'a> {
89 pub fn new(buffer: &'a mut [MaybeUninit<u8>]) -> Self {
97 buffer.fill(MaybeUninit::new(0));
99 Self {
100 inner: sys::CMsgIter::new(buffer.as_ptr().cast(), buffer.len()),
101 len: 0,
102 _p: PhantomData,
103 }
104 }
105
106 pub fn finish(self) -> usize {
108 self.len
109 }
110
111 pub fn try_push<T>(&mut self, level: i32, ty: i32, value: T) -> Option<()> {
115 if !self.inner.is_aligned::<T>() || !self.inner.is_space_enough::<T>() {
116 return None;
117 }
118
119 unsafe {
121 let mut cmsg = self.inner.current_mut()?;
122 cmsg.set_level(level);
123 cmsg.set_ty(ty);
124 self.len += cmsg.set_data(value);
125
126 self.inner.next();
127 }
128
129 Some(())
130 }
131}