1use std::{
2 ffi::{c_int, c_uchar},
3 ptr,
4};
5
6#[cfg(unix)]
7#[path = "unix.rs"]
8mod imp;
9
10#[cfg(windows)]
11#[path = "windows.rs"]
12mod imp;
13
14pub(crate) use imp::Aligned;
15
16pub(crate) struct Encoder<'a, M: MsgHdr> {
22 hdr: &'a mut M,
23 cmsg: Option<&'a mut M::ControlMessage>,
24 len: usize,
25}
26
27impl<'a, M: MsgHdr> Encoder<'a, M> {
28 pub(crate) unsafe fn new(hdr: &'a mut M) -> Self {
33 Self {
34 cmsg: unsafe { hdr.cmsg_first_hdr().as_mut() },
35 hdr,
36 len: 0,
37 }
38 }
39
40 pub(crate) fn push<T: Copy>(&mut self, level: c_int, ty: c_int, value: T) {
46 assert!(align_of::<T>() <= align_of::<M::ControlMessage>());
47 let space = M::ControlMessage::cmsg_space(size_of_val(&value));
48 assert!(
49 self.hdr.control_len() >= self.len + space,
50 "control message buffer too small. Required: {}, Available: {}",
51 self.len + space,
52 self.hdr.control_len()
53 );
54 let cmsg = self.cmsg.take().expect("no control buffer space remaining");
55 cmsg.set(level, ty, M::ControlMessage::cmsg_len(size_of_val(&value)));
56 unsafe {
57 ptr::write(cmsg.cmsg_data() as *const T as *mut T, value);
58 }
59 self.len += space;
60 self.cmsg = unsafe { self.hdr.cmsg_nxt_hdr(cmsg).as_mut() };
61 }
62
63 pub(crate) fn finish(self) {
65 }
67}
68
69impl<M: MsgHdr> Drop for Encoder<'_, M> {
72 fn drop(&mut self) {
73 self.hdr.set_control_len(self.len as _);
74 }
75}
76
77pub(crate) unsafe fn decode<T: Copy, C: CMsgHdr>(cmsg: &impl CMsgHdr) -> T {
81 assert!(align_of::<T>() <= align_of::<C>());
82 debug_assert_eq!(cmsg.len(), C::cmsg_len(size_of::<T>()));
83 unsafe { ptr::read(cmsg.cmsg_data() as *const T) }
84}
85
86pub(crate) struct Iter<'a, M: MsgHdr> {
87 hdr: &'a M,
88 cmsg: Option<&'a M::ControlMessage>,
89}
90
91impl<'a, M: MsgHdr> Iter<'a, M> {
92 pub(crate) unsafe fn new(hdr: &'a M) -> Self {
98 Self {
99 hdr,
100 cmsg: unsafe { hdr.cmsg_first_hdr().as_ref() },
101 }
102 }
103}
104
105impl<'a, M: MsgHdr> Iterator for Iter<'a, M> {
106 type Item = &'a M::ControlMessage;
107
108 fn next(&mut self) -> Option<Self::Item> {
109 let current = self.cmsg.take()?;
110 self.cmsg = unsafe { self.hdr.cmsg_nxt_hdr(current).as_ref() };
111
112 #[cfg(apple_fast)]
113 {
114 if current.len() < size_of::<M::ControlMessage>() {
118 return None;
119 }
120 }
121
122 Some(current)
123 }
124}
125
126pub(crate) trait MsgHdr {
128 type ControlMessage: CMsgHdr;
129
130 fn cmsg_first_hdr(&self) -> *mut Self::ControlMessage;
131
132 fn cmsg_nxt_hdr(&self, cmsg: &Self::ControlMessage) -> *mut Self::ControlMessage;
133
134 fn set_control_len(&mut self, len: usize);
139
140 fn control_len(&self) -> usize;
141}
142
143pub(crate) trait CMsgHdr {
144 fn cmsg_len(length: usize) -> usize;
145
146 fn cmsg_space(length: usize) -> usize;
147
148 fn cmsg_data(&self) -> *mut c_uchar;
149
150 fn set(&mut self, level: c_int, ty: c_int, len: usize);
151
152 fn len(&self) -> usize;
153}
154
155#[cfg(unix)]
156pub(crate) const LEN: usize = 96;