1 // Copyright 2017 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 use std::mem::size_of; 6 use std::slice::{from_raw_parts, from_raw_parts_mut}; 7 8 /// Types for which it is safe to initialize from raw data. 9 /// 10 /// A type `T` is `DataInit` if and only if it can be initialized by reading its contents from a 11 /// byte array. This is generally true for all plain-old-data structs. It is notably not true for 12 /// any type that includes a reference. 13 /// 14 /// Implementing this trait guarantees that it is safe to instantiate the struct with random data. 15 pub unsafe trait DataInit: Copy + Send + Sync { 16 /// Converts a slice of raw data into a reference of `Self`. 17 /// 18 /// The value of `data` is not copied. Instead a reference is made from the given slice. The 19 /// value of `Self` will depend on the representation of the type in memory, and may change in 20 /// an unstable fashion. 21 /// 22 /// This will return `None` if the length of data does not match the size of `Self`, or if the 23 /// data is not aligned for the type of `Self`. from_slice(data: &[u8]) -> Option<&Self>24 fn from_slice(data: &[u8]) -> Option<&Self> { 25 // Early out to avoid an unneeded `align_to` call. 26 if data.len() != size_of::<Self>() { 27 return None; 28 } 29 30 // Safe because the DataInit trait asserts any data is valid for this type, and we ensured 31 // the size of the pointer's buffer is the correct size. The `align_to` method ensures that 32 // we don't have any unaligned references. This aliases a pointer, but because the pointer 33 // is from a const slice reference, there are no mutable aliases. Finally, the reference 34 // returned can not outlive data because they have equal implicit lifetime constraints. 35 match unsafe { data.align_to::<Self>() } { 36 ([], [mid], []) => Some(mid), 37 _ => None, 38 } 39 } 40 41 /// Converts a mutable slice of raw data into a mutable reference of `Self`. 42 /// 43 /// Because `Self` is made from a reference to the mutable slice`, mutations to the returned 44 /// reference are immediately reflected in `data`. The value of the returned `Self` will depend 45 /// on the representation of the type in memory, and may change in an unstable fashion. 46 /// 47 /// This will return `None` if the length of data does not match the size of `Self`, or if the 48 /// data is not aligned for the type of `Self`. from_mut_slice(data: &mut [u8]) -> Option<&mut Self>49 fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> { 50 // Early out to avoid an unneeded `align_to_mut` call. 51 if data.len() != size_of::<Self>() { 52 return None; 53 } 54 55 // Safe because the DataInit trait asserts any data is valid for this type, and we ensured 56 // the size of the pointer's buffer is the correct size. The `align_to` method ensures that 57 // we don't have any unaligned references. This aliases a pointer, but because the pointer 58 // is from a mut slice reference, we borrow the passed in mutable reference. Finally, the 59 // reference returned can not outlive data because they have equal implicit lifetime 60 // constraints. 61 match unsafe { data.align_to_mut::<Self>() } { 62 ([], [mid], []) => Some(mid), 63 _ => None, 64 } 65 } 66 67 /// Converts a reference to `self` into a slice of bytes. 68 /// 69 /// The value of `self` is not copied. Instead, the slice is made from a reference to `self`. 70 /// The value of bytes in the returned slice will depend on the representation of the type in 71 /// memory, and may change in an unstable fashion. as_slice(&self) -> &[u8]72 fn as_slice(&self) -> &[u8] { 73 // Safe because the entire size of self is accessible as bytes because the trait guarantees 74 // it. The lifetime of the returned slice is the same as the passed reference, so that no 75 // dangling pointers will result from this pointer alias. 76 unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) } 77 } 78 79 /// Converts a mutable reference to `self` into a mutable slice of bytes. 80 /// 81 /// Because the slice is made from a reference to `self`, mutations to the returned slice are 82 /// immediately reflected in `self`. The value of bytes in the returned slice will depend on 83 /// the representation of the type in memory, and may change in an unstable fashion. as_mut_slice(&mut self) -> &mut [u8]84 fn as_mut_slice(&mut self) -> &mut [u8] { 85 // Safe because the entire size of self is accessible as bytes because the trait guarantees 86 // it. The trait also guarantees that any combination of bytes is valid for this type, so 87 // modifying them in the form of a byte slice is valid. The lifetime of the returned slice 88 // is the same as the passed reference, so that no dangling pointers will result from this 89 // pointer alias. Although this does alias a mutable pointer, we do so by exclusively 90 // borrowing the given mutable reference. 91 unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) } 92 } 93 } 94 95 // All intrinsic types and arays of intrinsic types are DataInit. They are just numbers. 96 macro_rules! array_data_init { 97 ($T:ty, $($N:expr)+) => { 98 $( 99 unsafe impl DataInit for [$T; $N] {} 100 )+ 101 } 102 } 103 macro_rules! data_init_type { 104 ($($T:ident),*) => { 105 $( 106 unsafe impl DataInit for $T {} 107 array_data_init! { 108 $T, 109 0 1 2 3 4 5 6 7 8 9 110 10 11 12 13 14 15 16 17 18 19 111 20 21 22 23 24 25 26 27 28 29 112 30 31 32 113 } 114 )* 115 #[cfg(test)] 116 mod data_init_tests { 117 use std::mem::{size_of, align_of}; 118 use crate::DataInit; 119 120 #[test] 121 fn from_slice_alignment() { 122 let mut v = [0u8; 32]; 123 $( 124 let (pre, _, _) = unsafe { v.align_to::<$T>() }; 125 let pre_len = pre.len(); 126 127 let aligned_v = &mut v[pre_len..pre_len + size_of::<$T>()]; 128 129 let from_aligned = $T::from_slice(aligned_v); 130 assert_eq!(from_aligned, Some(&0)); 131 132 let from_aligned_mut = $T::from_mut_slice(aligned_v); 133 assert_eq!(from_aligned_mut, Some(&mut 0)); 134 135 for i in 1..size_of::<$T>() { 136 let begin = pre_len + i; 137 let end = begin + size_of::<$T>(); 138 let unaligned_v = &mut v[begin..end]; 139 140 let from_unaligned = $T::from_slice(unaligned_v); 141 if align_of::<$T>() != 1 { 142 assert_eq!(from_unaligned, None); 143 } 144 145 let from_unaligned_mut = $T::from_mut_slice(unaligned_v); 146 if align_of::<$T>() != 1 { 147 assert_eq!(from_unaligned_mut, None); 148 } 149 } 150 )* 151 152 } 153 } 154 }; 155 } 156 data_init_type!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize); 157 158 pub mod endian; 159 pub use crate::endian::*; 160 161 pub mod volatile_memory; 162 pub use crate::volatile_memory::*; 163