1use crate::*;
2use std::{
3 marker::PhantomData,
4 mem,
5 mem::{ManuallyDrop, MaybeUninit},
6 ops::Deref,
7 slice,
8};
9
10pub unsafe trait Pod {}
25
26pub fn pod_zeroed<T: Pod>() -> T {
28 unsafe { mem::zeroed() }
29}
30
31pub fn pod_read<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<T> {
35 let mut t = pod_zeroed();
36 pod_write(u, &mut t)?;
37 Ok(t)
38}
39
40pub fn pod_iter<'a, T: Pod + 'a, U: Packed + ?Sized>(
44 u: &'a U,
45) -> Result<impl Iterator<Item = T> + 'a> {
46 if mem::size_of::<T>() != 0 && mem::size_of_val(u) % mem::size_of::<T>() != 0 {
47 einval()
48 } else {
49 Ok(Iter {
50 buf: as_bytes(u),
51 _pd: PhantomData,
52 })
53 }
54}
55
56struct Iter<'a, T> {
57 buf: &'a [u8],
58 _pd: PhantomData<fn() -> T>,
59}
60
61impl<'a, T: Pod> Iterator for Iter<'a, T> {
62 type Item = T;
63
64 fn next(&mut self) -> Option<Self::Item> {
65 if self.buf.is_empty() {
66 None
67 } else {
68 let t = pod_read_init(self.buf).unwrap();
69 self.buf = &self.buf[mem::size_of::<T>()..];
70 Some(t)
71 }
72 }
73}
74
75pub fn pod_read_init<T: Pod, U: Packed + ?Sized>(u: &U) -> Result<T> {
79 let mut t = pod_zeroed();
80 pod_write_common_prefix(u, &mut t)?;
81 Ok(t)
82}
83
84pub fn pod_write<T: Pod + ?Sized, U: Packed + ?Sized>(u: &U, t: &mut T) -> Result<()> {
88 if mem::size_of_val(t) != mem::size_of_val(u) {
89 einval()
90 } else {
91 pod_write_common_prefix(u, t)
92 }
93}
94
95fn pod_write_common_prefix<T: Pod + ?Sized, U: Packed + ?Sized>(
99 u: &U,
100 t: &mut T,
101) -> Result<()> {
102 if mem::size_of_val(t) > mem::size_of_val(u) {
103 einval()
104 } else {
105 unsafe {
106 let dst = t as *mut _ as *mut u8;
107 let src = u as *const _ as *const u8;
108 std::ptr::copy_nonoverlapping(src, dst, mem::size_of_val(t));
109 }
110 Ok(())
111 }
112}
113
114unsafe impl<T: Pod> Pod for [T] {
115}
116
117unsafe impl<T: Pod, const N: usize> Pod for [T; N] {
118}
119
120unsafe impl<T> Pod for *const T {
125}
126
127unsafe impl<T> Pod for *mut T {
128}
129
130unsafe impl<T> Pod for MaybeUninit<T> {
131}
132
133macro_rules! imp_pod {
134 ($($path:path)*) => {
135 $(unsafe impl Pod for $path {})*
136 }
137}
138
139imp_pod! {
140 u8
141 u16
142 u32
143 u64
144 u128
145 usize
146 i8
147 i16
148 i32
149 i64
150 i128
151 isize
152
153 f32
154 f64
155
156 c::sockaddr
157 c::sockaddr_storage
158 c::sockaddr_un
159 c::sockaddr_in
160 c::sockaddr_in6
161
162 c::msghdr
163 c::cmsghdr
164
165 c::in6_pktinfo
166
167 c::siginfo_t
168 c::flock
169 c::timespec
170 c::timeval
171 c::linger
172
173 OwnedFd
174 Fd
175}
176
177#[cfg(not(any(target_os = "macos", target_os = "openbsd")))]
178imp_pod! {
179 c::sigset_t
180}
181
182#[cfg(target_os = "linux")]
183imp_pod! {
184 c::sockaddr_alg
185 c::sockaddr_nl
186 c::sockaddr_ll
187 c::sockaddr_vm
188 c::signalfd_siginfo
189 c::nlmsghdr
190 c::nlattr
191 c::ifinfomsg
192 c::input_event
193 c::open_how
194 c::sched_attr
195 c::sched_param
196 c::genlmsghdr
197 c::nlmsgerr
198 c::itimerspec
199 c::itimerval
200 c::epoll_event
201}
202
203#[cfg(not(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd")))]
204imp_pod! {
205 c::ucred
206 c::in_pktinfo
207 c::ip_mreq
208 c::ip_mreqn
209}
210
211pub unsafe trait Packed {}
217
218unsafe impl<T: Packed> Packed for [T] {
219}
220
221unsafe impl<T: Packed, const N: usize> Packed for [T; N] {
222}
223
224unsafe impl<T> Packed for *const T {
229}
230
231unsafe impl<T> Packed for *mut T {
232}
233
234macro_rules! imp_packed {
235 ($($path:path)*) => {
236 $(unsafe impl Packed for $path {})*
237 }
238}
239
240imp_packed! {
241 u8
242 u16
243 u32
244 u64
245 u128
246 usize
247 i8
248 i16
249 i32
250 i64
251 i128
252 isize
253
254 f32
255 f64
256
257 OwnedFd
258 Fd
259}
260
261pub fn as_bytes<T: Packed + ?Sized>(t: &T) -> &[u8] {
263 unsafe {
264 let ptr = t as *const _ as *const u8;
265 slice::from_raw_parts(ptr, mem::size_of_val(t))
266 }
267}
268
269pub fn as_bytes_mut<T: Pod + Packed + ?Sized>(t: &mut T) -> &mut [u8] {
271 unsafe {
272 let ptr = t as *mut _ as *mut u8;
273 slice::from_raw_parts_mut(ptr, mem::size_of_val(t))
274 }
275}
276
277#[repr(transparent)]
279#[derive(Copy)]
280pub struct AssertPod<T: ?Sized>(ManuallyDrop<T>);
281
282impl<T: ?Sized> AssertPod<T> {
283 pub unsafe fn new(t: &mut T) -> &mut Self {
289 &mut *(t as *mut T as *mut AssertPod<T>)
290 }
291}
292
293impl<T: Copy> Clone for AssertPod<T> {
294 fn clone(&self) -> Self {
295 *self
296 }
297}
298
299impl<T> AssertPod<T> {
300 pub unsafe fn unwrap(self) -> T {
306 ManuallyDrop::into_inner(self.0)
307 }
308}
309
310unsafe impl<T: ?Sized> Pod for AssertPod<T> {
311}
312
313#[repr(transparent)]
315#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
316pub struct AssertPacked<T: ?Sized>(T);
317
318impl<T: ?Sized> AssertPacked<T> {
319 pub unsafe fn new(t: &T) -> &Self {
325 &*(t as *const T as *const AssertPacked<T>)
326 }
327}
328
329unsafe impl<T: ?Sized> Packed for AssertPacked<T> {
330}
331
332impl<T: ?Sized> Deref for AssertPacked<T> {
333 type Target = T;
334
335 fn deref(&self) -> &Self::Target {
336 &self.0
337 }
338}
339
340pub unsafe fn assert_pod<T: ?Sized>(t: &mut T) -> &mut AssertPod<T> {
346 AssertPod::new(t)
347}
348
349pub unsafe fn assert_packed<T: ?Sized>(t: &T) -> &AssertPacked<T> {
355 AssertPacked::new(t)
356}