compio_io/ancillary/
mod.rs1use std::{
16 marker::PhantomData,
17 mem::MaybeUninit,
18 ops::{Deref, DerefMut},
19};
20
21use compio_buf::{IoBuf, IoBufMut, SetLen};
22#[cfg(windows)]
23use windows_sys::Win32::Networking::WinSock;
24
25cfg_if::cfg_if! {
26 if #[cfg(windows)] {
27 #[path = "windows.rs"]
28 mod sys;
29 } else if #[cfg(unix)] {
30 #[path = "unix.rs"]
31 mod sys;
32 }
33}
34
35pub struct AncillaryRef<'a>(sys::CMsgRef<'a>);
37
38impl AncillaryRef<'_> {
39 pub fn level(&self) -> i32 {
41 self.0.level()
42 }
43
44 pub fn ty(&self) -> i32 {
46 self.0.ty()
47 }
48
49 #[allow(clippy::len_without_is_empty)]
51 pub fn len(&self) -> usize {
52 self.0.len() as _
53 }
54
55 pub unsafe fn data<T>(&self) -> &T {
62 unsafe { self.0.data() }
63 }
64}
65
66pub struct AncillaryIter<'a> {
68 inner: sys::CMsgIter,
69 _p: PhantomData<&'a ()>,
70}
71
72impl<'a> AncillaryIter<'a> {
73 pub unsafe fn new(buffer: &'a [u8]) -> Self {
84 Self {
85 inner: sys::CMsgIter::new(buffer.as_ptr(), buffer.len()),
86 _p: PhantomData,
87 }
88 }
89}
90
91impl<'a> Iterator for AncillaryIter<'a> {
92 type Item = AncillaryRef<'a>;
93
94 fn next(&mut self) -> Option<Self::Item> {
95 unsafe {
96 let cmsg = self.inner.current();
97 self.inner.next();
98 cmsg.map(AncillaryRef)
99 }
100 }
101}
102
103pub struct AncillaryBuilder<'a> {
105 inner: sys::CMsgIter,
106 len: usize,
107 _p: PhantomData<&'a mut ()>,
108}
109
110impl<'a> AncillaryBuilder<'a> {
111 pub fn new(buffer: &'a mut [MaybeUninit<u8>]) -> Self {
119 buffer.fill(MaybeUninit::new(0));
121 Self {
122 inner: sys::CMsgIter::new(buffer.as_ptr().cast(), buffer.len()),
123 len: 0,
124 _p: PhantomData,
125 }
126 }
127
128 pub fn finish(self) -> usize {
130 self.len
131 }
132
133 pub fn try_push<T>(&mut self, level: i32, ty: i32, value: T) -> Option<()> {
137 if !self.inner.is_aligned::<T>() || !self.inner.is_space_enough::<T>() {
138 return None;
139 }
140
141 unsafe {
143 let mut cmsg = self.inner.current_mut()?;
144 cmsg.set_level(level);
145 cmsg.set_ty(ty);
146 self.len += cmsg.set_data(value);
147
148 self.inner.next();
149 }
150
151 Some(())
152 }
153}
154
155pub struct AncillaryBuf<const N: usize> {
161 inner: [u8; N],
162 len: usize,
163 #[cfg(unix)]
164 _align: [libc::cmsghdr; 0],
165 #[cfg(windows)]
166 _align: [WinSock::CMSGHDR; 0],
167}
168
169impl<const N: usize> AncillaryBuf<N> {
170 pub fn new() -> Self {
172 Self {
173 inner: [0u8; N],
174 len: 0,
175 _align: [],
176 }
177 }
178}
179
180impl<const N: usize> Default for AncillaryBuf<N> {
181 fn default() -> Self {
182 Self::new()
183 }
184}
185
186impl<const N: usize> IoBuf for AncillaryBuf<N> {
187 fn as_init(&self) -> &[u8] {
188 &self.inner[..self.len]
189 }
190}
191
192impl<const N: usize> SetLen for AncillaryBuf<N> {
193 unsafe fn set_len(&mut self, len: usize) {
194 debug_assert!(len <= N);
195 self.len = len;
196 }
197}
198
199impl<const N: usize> IoBufMut for AncillaryBuf<N> {
200 fn as_uninit(&mut self) -> &mut [MaybeUninit<u8>] {
201 self.inner.as_uninit()
202 }
203}
204
205impl<const N: usize> Deref for AncillaryBuf<N> {
206 type Target = [u8];
207
208 fn deref(&self) -> &Self::Target {
209 &self.inner[0..self.len]
210 }
211}
212
213impl<const N: usize> DerefMut for AncillaryBuf<N> {
214 fn deref_mut(&mut self) -> &mut Self::Target {
215 &mut self.inner[0..self.len]
216 }
217}