1use std::marker::PhantomData;
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 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 [u8]) -> Self {
97 buffer.fill(0);
98 Self {
99 inner: sys::CMsgIter::new(buffer.as_ptr(), buffer.len()),
100 len: 0,
101 _p: PhantomData,
102 }
103 }
104
105 pub fn finish(self) -> usize {
107 self.len
108 }
109
110 pub fn try_push<T>(&mut self, level: i32, ty: i32, value: T) -> Option<()> {
114 if !self.inner.is_aligned::<T>() || !self.inner.is_space_enough::<T>() {
115 return None;
116 }
117
118 unsafe {
120 let mut cmsg = self.inner.current_mut()?;
121 cmsg.set_level(level);
122 cmsg.set_ty(ty);
123 self.len += cmsg.set_data(value);
124
125 self.inner.next();
126 }
127
128 Some(())
129 }
130}