1use std::ptr::{copy_nonoverlapping, read};
2use std::mem::{size_of, transmute, uninitialized, zeroed};
3use std::slice::{from_raw_parts, from_raw_parts_mut};
4use packed::{Unaligned, Aligned, is_aligned_for, is_aligned_for_slice, size_of_slice};
5
6pub unsafe trait Pod: Sized {
10 #[inline]
12 unsafe fn uninitialized() -> Self {
13 uninitialized()
14 }
15
16 #[inline]
18 fn zeroed() -> Self {
19 unsafe { zeroed() }
20 }
21
22 #[inline]
24 fn copy(&self) -> Self {
25 unsafe {
26 read(self)
27 }
28 }
29
30 #[inline]
34 fn map<T: Pod>(&self) -> Option<&T> {
35 if size_of::<T>() == size_of::<Self>() && is_aligned_for::<T, _>(self) {
36 Some(unsafe { transmute(self) })
37 } else {
38 None
39 }
40 }
41
42 #[inline]
46 fn map_mut<T: Pod>(&mut self) -> Option<&mut T> {
47 if size_of::<T>() == size_of::<Self>() && is_aligned_for::<T, _>(self) {
48 Some(unsafe { transmute(self) })
49 } else {
50 None
51 }
52 }
53
54 #[inline]
58 fn map_copy<T: Pod>(&self) -> Option<T> {
59 if size_of::<T>() == size_of::<Self>() {
60 Some(unsafe {
61 Pod::from_ptr(self)
62 })
63 } else {
64 None
65 }
66 }
67
68 #[inline]
72 fn try_map<T: Pod>(&self) -> Option<&T> {
73 if size_of::<T>() <= size_of::<Self>() && is_aligned_for::<T, _>(self) {
74 Some(unsafe { transmute(self) })
75 } else {
76 None
77 }
78 }
79
80 #[inline]
84 fn try_map_mut<T: Pod>(&mut self) -> Option<&mut T> {
85 if size_of::<T>() <= size_of::<Self>() && is_aligned_for::<T, _>(self) {
86 Some(unsafe { transmute(self) })
87 } else {
88 None
89 }
90 }
91
92 #[inline]
96 fn try_map_copy<T: Pod>(&self) -> Option<T> {
97 if size_of::<T>() <= size_of::<Self>() {
98 Some(unsafe {
99 Pod::from_ptr(self)
100 })
101 } else {
102 None
103 }
104 }
105
106 #[inline]
110 fn map_box<T: Pod>(self: Box<Self>) -> Result<Box<T>, Box<Self>> {
111 if size_of::<T>() == size_of::<Self>() && is_aligned_for::<T, _>(&*self) {
112 Ok(unsafe { Box::from_raw(Box::into_raw(self) as *mut _) })
113 } else {
114 Err(self)
115 }
116 }
117
118 #[inline]
122 fn split<T: Pod>(&self) -> Option<&[T]> {
123 if size_of::<Self>() % size_of::<T>() == 0 && is_aligned_for::<T, _>(self) {
124 Some(unsafe {
125 from_raw_parts(self as *const _ as *const T, size_of::<Self>() / size_of::<T>())
126 })
127 } else {
128 None
129 }
130 }
131
132 #[inline]
136 fn split_mut<T: Pod>(&mut self) -> Option<&mut [T]> {
137 if size_of::<Self>() % size_of::<T>() == 0 && is_aligned_for::<T, _>(self) {
138 Some(unsafe {
139 from_raw_parts_mut(self as *mut _ as *mut T, size_of::<Self>() / size_of::<T>())
140 })
141 } else {
142 None
143 }
144 }
145
146 #[inline]
150 fn try_split<T: Pod>(&self) -> &[T] {
151 if is_aligned_for::<T, _>(self) {
152 unsafe {
153 from_raw_parts(self as *const _ as *const T, size_of::<Self>() / size_of::<T>())
154 }
155 } else {
156 &[]
157 }
158 }
159
160 #[inline]
164 fn try_split_mut<T: Pod>(&mut self) -> &mut [T] {
165 if is_aligned_for::<T, _>(self) {
166 unsafe {
167 from_raw_parts_mut(self as *mut _ as _, size_of::<Self>() / size_of::<T>())
168 }
169 } else {
170 &mut []
171 }
172 }
173
174 #[inline]
178 fn split_box<T: Pod>(self: Box<Self>) -> Result<Box<[T]>, Box<Self>> {
179 if size_of::<Self>() % size_of::<T>() == 0 && is_aligned_for::<T, _>(&*self) {
180 Ok(unsafe {
181 let ptr = Box::into_raw(self);
182 Box::from_raw(
183 from_raw_parts_mut(ptr as _, size_of::<Self>() / size_of::<T>())
184 )
185 })
186 } else {
187 Err(self)
188 }
189 }
190
191 #[inline]
195 fn split_vec<T: Pod>(self: Box<Self>) -> Result<Vec<T>, Box<Self>> {
196 Self::split_box(self).map(|s| s.into_vec())
197 }
198
199 #[inline]
203 fn map_slice<T: Pod>(s: &[Self]) -> Option<&[T]> {
204 let len = size_of_slice(s);
205 if is_aligned_for_slice::<T, _>(s) && len % size_of::<T>() == 0 {
206 Some(unsafe {
207 from_raw_parts(s.as_ptr() as _, len / size_of::<T>())
208 })
209 } else {
210 None
211 }
212 }
213
214 #[inline]
218 fn map_slice_mut<T: Pod>(s: &mut [Self]) -> Option<&mut [T]> {
219 let len = size_of_slice(s);
220 if is_aligned_for_slice::<T, _>(s) && len % size_of::<T>() == 0 {
221 Some(unsafe {
222 from_raw_parts_mut(s.as_mut_ptr() as _, len / size_of::<T>())
223 })
224 } else {
225 None
226 }
227 }
228
229 #[inline]
233 fn try_map_slice<T: Pod>(s: &[Self]) -> &[T] {
234 let len = size_of_slice(s);
235 if is_aligned_for_slice::<T, _>(s) {
236 unsafe {
237 from_raw_parts(s.as_ptr() as _, len / size_of::<T>())
238 }
239 } else {
240 &[]
241 }
242 }
243
244 #[inline]
248 fn try_map_slice_mut<T: Pod>(s: &mut [Self]) -> &mut [T] {
249 let len = size_of_slice(s);
250 if is_aligned_for_slice::<T, _>(s) {
251 unsafe {
252 from_raw_parts_mut(s.as_mut_ptr() as _, len / size_of::<T>())
253 }
254 } else {
255 &mut []
256 }
257 }
258
259 #[inline]
263 fn map_slice_box<T: Pod>(s: Box<[Self]>) -> Result<Box<[T]>, Box<[Self]>> {
264 let len = size_of_slice(&s);
265 if is_aligned_for_slice::<T, _>(&s) && len % size_of::<T>() == 0 {
266 Ok(unsafe {
267 let ptr = Box::into_raw(s);
268 Box::from_raw(
269 from_raw_parts_mut(ptr as _, len / size_of::<T>())
270 )
271 })
272 } else {
273 Err(s)
274 }
275 }
276
277 #[inline]
281 fn map_slice_vec<T: Pod>(s: Vec<Self>) -> Result<Vec<T>, Vec<Self>> {
282 Self::map_slice_box(s.into_boxed_slice()).map_err(|s| s.into_vec()).map(|s| s.into_vec())
283 }
284
285 #[inline]
289 fn merge<T: Pod>(s: &[Self]) -> Option<&T> {
290 if is_aligned_for_slice::<T, _>(s) && size_of_slice(s) == size_of::<T>() {
291 Some(unsafe { transmute(s.as_ptr()) })
292 } else {
293 None
294 }
295 }
296
297 #[inline]
301 fn merge_mut<T: Pod>(s: &mut [Self]) -> Option<&mut T> {
302 if is_aligned_for_slice::<T, _>(s) && size_of_slice(s) == size_of::<T>() {
303 Some(unsafe { transmute(s.as_mut_ptr()) })
304 } else {
305 None
306 }
307 }
308
309 #[inline]
313 fn merge_copy<T: Pod>(s: &[Self]) -> Option<T> {
314 if size_of_slice(s) == size_of::<T>() {
315 Some(unsafe {
316 Pod::from_ptr(s.as_ptr())
317 })
318 } else {
319 None
320 }
321 }
322
323 #[inline]
327 fn try_merge<T: Pod>(s: &[Self]) -> Option<&T> {
328 if is_aligned_for_slice::<T, _>(s) && size_of_slice(s) >= size_of::<T>() {
329 Some(unsafe { transmute(s.as_ptr()) })
330 } else {
331 None
332 }
333 }
334
335 #[inline]
339 fn try_merge_mut<T: Pod>(s: &mut [Self]) -> Option<&mut T> {
340 if is_aligned_for_slice::<T, _>(s) && size_of_slice(s) >= size_of::<T>() {
341 Some(unsafe { transmute(s.as_mut_ptr()) })
342 } else {
343 None
344 }
345 }
346
347 #[inline]
351 fn try_merge_copy<T: Pod>(s: &[Self]) -> Option<T> {
352 if size_of_slice(s) <= size_of::<T>() {
353 Some(unsafe {
354 Pod::from_ptr(s.as_ptr())
355 })
356 } else {
357 None
358 }
359 }
360
361 #[inline]
365 fn merge_box<T: Pod>(s: Box<[Self]>) -> Result<Box<T>, Box<[Self]>> {
366 if is_aligned_for_slice::<T, _>(&s) && size_of_slice(&s) == size_of::<T>() {
367 Ok(unsafe {
368 let ptr = (*Box::into_raw(s)).as_mut_ptr();
369 Box::from_raw(ptr as _)
370 })
371 } else {
372 Err(s)
373 }
374 }
375
376 #[inline]
380 fn merge_vec<T: Pod>(s: Vec<Self>) -> Result<Box<T>, Vec<Self>> {
381 Self::merge_box(s.into_boxed_slice()).map_err(|s| s.into_vec())
382 }
383
384 #[inline]
388 unsafe fn from_ptr<T>(source: *const T) -> Self {
389 let mut s = Self::uninitialized();
390 copy_nonoverlapping(source as *const u8, &mut s as *mut _ as _, size_of::<Self>());
391 s
392 }
393
394 #[inline]
396 fn from_ref<T: Pod>(p: &T) -> Option<Self> {
397 Pod::map_copy(p)
398 }
399
400 #[inline]
402 fn from_slice<T: Pod>(p: &[T]) -> Option<Self> {
403 Pod::merge_copy(p)
404 }
405
406 #[inline]
408 fn from_boxed_slice<T: Pod>(p: Box<[T]>) -> Result<Box<Self>, Box<[T]>> {
409 Pod::merge_box(p).or_else(|p|
410 Pod::merge_copy(&p).map(Box::new).ok_or(p)
411 )
412 }
413
414 #[inline]
416 fn from_vec<T: Pod>(p: Vec<T>) -> Result<Box<Self>, Vec<T>> {
417 Pod::from_boxed_slice(p.into_boxed_slice()).map_err(|p| p.into_vec())
418 }
419
420 #[inline]
422 fn slice_from_boxed_slice<T: Pod>(p: Box<[T]>) -> Result<Box<[Self]>, Box<[T]>> {
423 Pod::map_slice_box(p)
424 }
425
426 #[inline]
428 fn ref_from<T: Pod>(p: &T) -> Option<&Self> {
429 Pod::map(p)
430 }
431
432 #[inline]
434 fn ref_from_mut<T: Pod>(p: &mut T) -> Option<&mut Self> {
435 Pod::map_mut(p)
436 }
437
438 #[inline]
440 fn ref_from_slice<T: Pod>(p: &[T]) -> Option<&Self> {
441 Pod::merge(p)
442 }
443
444 #[inline]
446 fn ref_from_slice_mut<T: Pod>(p: &mut [T]) -> Option<&mut Self> {
447 Pod::merge_mut(p)
448 }
449
450 #[inline]
452 fn as_bytes(&self) -> &[u8] {
453 self.try_split()
454 }
455
456 #[inline]
458 fn as_bytes_mut(&mut self) -> &mut [u8] {
459 self.try_split_mut()
460 }
461
462 #[inline]
466 fn from_bytes(p: &[u8]) -> Option<Self> {
467 Self::from_slice(&p)
468 }
469
470 #[inline]
474 fn ref_from_bytes(p: &[u8]) -> Option<&Self> {
475 Self::ref_from_slice(p)
476 }
477
478 #[inline]
482 fn ref_from_bytes_mut(p: &mut [u8]) -> Option<&mut Self> {
483 Self::ref_from_slice_mut(p)
484 }
485
486 #[inline]
490 fn from_byte_slice(p: Box<[u8]>) -> Result<Box<Self>, Box<[u8]>> {
491 Self::from_boxed_slice(p)
492 }
493
494 #[inline]
498 fn from_byte_vec(p: Vec<u8>) -> Result<Box<Self>, Vec<u8>> {
499 Self::from_vec(p)
500 }
501
502 #[inline]
504 fn into_byte_slice(self: Box<Self>) -> Box<[u8]> {
505 Self::split_box(self).ok().unwrap()
506 }
507
508 #[inline]
510 fn into_byte_vec(self: Box<Self>) -> Vec<u8> {
511 Self::split_vec(self).ok().unwrap()
512 }
513
514 #[inline]
518 fn as_aligned_mut<T: Pod + Aligned<Unaligned=Self>>(&mut self) -> Option<&mut T> where Self: Copy + Unaligned {
519 unsafe { Aligned::from_unaligned_mut(self) }
520 }
521
522 #[inline]
526 fn from_unaligned_mut<T: Copy + Unaligned>(s: &mut T) -> Option<&mut Self> where Self: Aligned<Unaligned=T> {
527 unsafe { Aligned::from_unaligned_mut(s) }
528 }
529
530 #[inline]
534 fn from_unaligned<T: Copy + Unaligned>(s: T) -> Self where Self: Aligned<Unaligned=T> {
535 unsafe { Aligned::from_unaligned(s) }
536 }
537
538 #[doc(hidden)]
539 fn __assert_pod() { }
540}
541
542unsafe impl Pod for () { }
543unsafe impl Pod for f32 { }
544unsafe impl Pod for f64 { }
545unsafe impl Pod for i8 { }
546unsafe impl Pod for u8 { }
547unsafe impl Pod for i16 { }
548unsafe impl Pod for u16 { }
549unsafe impl Pod for i32 { }
550unsafe impl Pod for u32 { }
551unsafe impl Pod for i64 { }
552unsafe impl Pod for u64 { }
553unsafe impl Pod for isize { }
554unsafe impl Pod for usize { }
555unsafe impl<T> Pod for *const T { }
556unsafe impl<T> Pod for *mut T { }
557
558macro_rules! pod_def {
559 ($($x:expr),*) => {
560 $(
561 unsafe impl<T: Pod> Pod for [T; $x] { }
562 )*
563 };
564}
565
566unsafe impl<T: Pod> Pod for (T,) { }
567pod_def! {
568 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
569 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
570 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
571 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
572 0x40,
573 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800, 0x900, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00, 0xf00,
574 0x1000
575}