pod/
pod.rs

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
6/// A marker trait indicating that a type is Plain Old Data.
7///
8/// It is unsafe to `impl` this manually, use `#[derive(Pod)]` instead.
9pub unsafe trait Pod: Sized {
10    /// Generates a new uninitialized instance of a POD type.
11    #[inline]
12    unsafe fn uninitialized() -> Self {
13        uninitialized()
14    }
15
16    /// Creates a new zeroed instance of a POD type.
17    #[inline]
18    fn zeroed() -> Self {
19        unsafe { zeroed() }
20    }
21
22    /// Creates a copy of this POD instance
23    #[inline]
24    fn copy(&self) -> Self {
25        unsafe {
26            read(self)
27        }
28    }
29
30    /// Converts a POD reference from one to another type of the same size.
31    ///
32    /// Returns `None` if the two types are misaligned or not the same size.
33    #[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    /// Converts a mutable POD reference from one to another type of the same size.
43    ///
44    /// Returns `None` if the two types are misaligned or not the same size.
45    #[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    /// Converts a POD type from one to another of the same size.
55    ///
56    /// Returns `None` if the two types are not the same size.
57    #[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    /// Converts a POD reference from one to another type of the same or lesser size.
69    ///
70    /// Returns `None` if the two types are misaligned or `T` is larger.
71    #[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    /// Converts a mutable POD reference from one to another type of the same or lesser size.
81    ///
82    /// Returns `None` if the two types are misaligned or `T` is larger.
83    #[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    /// Converts a POD type from one to another of the same or lesser size.
93    ///
94    /// Returns `None` if `T` is larger.
95    #[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    /// Converts a boxed POD type from one to another of the same size.
107    ///
108    /// Fails if the two types are misaligned or not the same size.
109    #[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    /// Converts a POD reference into a slice of another type.
119    ///
120    /// Returns `None` if the types are misaligned or do not fit perfectly.
121    #[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    /// Converts a mutable POD reference into a slice of another type.
133    ///
134    /// Returns `None` if the types are misaligned or do not fit perfectly.
135    #[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    /// Converts a POD reference into a slice of another type.
147    ///
148    /// Returns an empty slice if the types are misaligned.
149    #[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    /// Converts a mutable POD reference into a slice of another type.
161    ///
162    /// Returns an empty slice if the types are misaligned.
163    #[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    /// Converts a boxed POD object into a boxed slice of another type.
175    ///
176    /// Fails if the types are misaligned or do not fit perfectly.
177    #[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    /// Converts a boxed POD object into a vector of another type.
192    ///
193    /// Fails if the types are misaligned or do not fit perfectly.
194    #[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    /// Maps a POD slice from one type to another.
200    ///
201    /// Returns `None` if the slice is misaligned or the output type does not perfectly fit.
202    #[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    /// Maps a mutable POD slice from one type to another.
215    ///
216    /// Returns `None` if the slice is misaligned or the output type does not perfectly fit.
217    #[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    /// Maps a POD slice from one type to another.
230    ///
231    /// Returns `None` if the slice is misaligned.
232    #[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    /// Maps a mutable POD slice from one type to another.
245    ///
246    /// Returns `None` if the slice is misaligned.
247    #[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    /// Maps a boxed POD slice from one type to another.
260    ///
261    /// Fails if the slice is misaligned or does not perfectly fit.
262    #[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    /// Maps a POD vector from one type to another.
278    ///
279    /// Fails if the slice is misaligned or does not perfectly fit.
280    #[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    /// Converts a POD slice into another type.
286    ///
287    /// Returns `None` if the types are misaligned or not the same size.
288    #[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    /// Converts a mutable POD slice into another type.
298    ///
299    /// Returns `None` if the types are misaligned or not the same size.
300    #[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    /// Converts a POD slice into another type.
310    ///
311    /// Returns `None` if the types are not the same size.
312    #[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    /// Converts a POD slice into another type.
324    ///
325    /// Returns `None` if the types are misaligned or `T` is larger.
326    #[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    /// Converts a mutable POD slice into another type.
336    ///
337    /// Returns `None` if the types are misaligned or `T` is larger.
338    #[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    /// Converts a POD slice into another type.
348    ///
349    /// Returns `None` if `T` is larger.
350    #[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    /// Converts a boxed POD slice into another boxed type.
362    ///
363    /// Fails if the types are misaligned or not the same size.
364    #[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    /// Converts a POD vector into another boxed type.
377    ///
378    /// Fails if the types are misaligned or not the same size.
379    #[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    /// Creates a new POD instance from an unaligned pointer.
385    ///
386    /// This is an unsafe operation because the pointer is not validated in any way.
387    #[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    /// Creates a new POD instance with the inverse of `map_copy()`
395    #[inline]
396    fn from_ref<T: Pod>(p: &T) -> Option<Self> {
397        Pod::map_copy(p)
398    }
399
400    /// Creates a new POD instance with the inverse of `merge_copy()`
401    #[inline]
402    fn from_slice<T: Pod>(p: &[T]) -> Option<Self> {
403        Pod::merge_copy(p)
404    }
405
406    /// Creates a new POD instance with the inverse of `merge_box()`
407    #[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    /// Creates a new POD instance with the inverse of `merge_vec()`
415    #[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    /// Creates a new POD instance with the inverse of `map_slice_box()`
421    #[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    /// Creates a POD reference with the inverse of `map()`
427    #[inline]
428    fn ref_from<T: Pod>(p: &T) -> Option<&Self> {
429        Pod::map(p)
430    }
431
432    /// Creates a mutable POD reference with the inverse of `map_mut()`
433    #[inline]
434    fn ref_from_mut<T: Pod>(p: &mut T) -> Option<&mut Self> {
435        Pod::map_mut(p)
436    }
437
438    /// Creates a POD reference with the inverse of `merge()`
439    #[inline]
440    fn ref_from_slice<T: Pod>(p: &[T]) -> Option<&Self> {
441        Pod::merge(p)
442    }
443
444    /// Creates a mutable POD reference with the inverse of `merge_mut()`
445    #[inline]
446    fn ref_from_slice_mut<T: Pod>(p: &mut [T]) -> Option<&mut Self> {
447        Pod::merge_mut(p)
448    }
449
450    /// Borrows the POD as a byte slice
451    #[inline]
452    fn as_bytes(&self) -> &[u8] {
453        self.try_split()
454    }
455
456    /// Borrows the POD as a mutable byte slice
457    #[inline]
458    fn as_bytes_mut(&mut self) -> &mut [u8] {
459        self.try_split_mut()
460    }
461
462    /// Safely creates a POD value from a potentially unaligned slice
463    ///
464    /// Returns `None` if `slice.len()` is not the same as the type's size
465    #[inline]
466    fn from_bytes(p: &[u8]) -> Option<Self> {
467        Self::from_slice(&p)
468    }
469
470    /// Borrows a new instance of the POD from a byte slice
471    ///
472    /// Returns `None` if `slice.len()` is not the same as the type's size
473    #[inline]
474    fn ref_from_bytes(p: &[u8]) -> Option<&Self> {
475        Self::ref_from_slice(p)
476    }
477
478    /// Borrows a mutable instance of the POD from a mutable byte slice
479    ///
480    /// Returns `None` if `slice.len()` is not the same as the type's size
481    #[inline]
482    fn ref_from_bytes_mut(p: &mut [u8]) -> Option<&mut Self> {
483        Self::ref_from_slice_mut(p)
484    }
485
486    /// Converts a boxed slice to a boxed instance of the POD type
487    ///
488    /// Fails if `slice.len()` is not the same as the type's size
489    #[inline]
490    fn from_byte_slice(p: Box<[u8]>) -> Result<Box<Self>, Box<[u8]>> {
491        Self::from_boxed_slice(p)
492    }
493
494    /// Converts a byte vector to a boxed instance of the POD type
495    ///
496    /// Fails if `vec.len()` is not the same as the type's size
497    #[inline]
498    fn from_byte_vec(p: Vec<u8>) -> Result<Box<Self>, Vec<u8>> {
499        Self::from_vec(p)
500    }
501
502    /// Converts a boxed POD to a boxed slice
503    #[inline]
504    fn into_byte_slice(self: Box<Self>) -> Box<[u8]> {
505        Self::split_box(self).ok().unwrap()
506    }
507
508    /// Converts a boxed POD to a byte vector
509    #[inline]
510    fn into_byte_vec(self: Box<Self>) -> Vec<u8> {
511        Self::split_vec(self).ok().unwrap()
512    }
513
514    /// Safely borrows the aligned value mutably
515    ///
516    /// See also: `Aligned::from_unaligned_mut`
517    #[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    /// Safely borrows the unaligned value mutably
523    ///
524    /// See also: `Aligned::from_unaligned_mut`
525    #[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    /// Safely converts an unaligned value to its aligned equivalent
531    ///
532    /// See also: `Aligned::from_unaligned`
533    #[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}