2017-06-20 20:44:40 +00:00
|
|
|
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
2018-01-17 01:12:07 +00:00
|
|
|
use std::mem::size_of;
|
|
|
|
use std::slice::{from_raw_parts, from_raw_parts_mut};
|
|
|
|
|
2017-06-20 20:44:40 +00:00
|
|
|
/// Types for which it is safe to initialize from raw data.
|
|
|
|
///
|
|
|
|
/// A type `T` is `DataInit` if and only if it can be initialized by reading its contents from a
|
|
|
|
/// byte array. This is generally true for all plain-old-data structs. It is notably not true for
|
|
|
|
/// any type that includes a reference.
|
|
|
|
///
|
|
|
|
/// Implementing this trait guarantees that it is safe to instantiate the struct with random data.
|
2018-01-17 01:12:07 +00:00
|
|
|
pub unsafe trait DataInit: Copy + Send + Sync {
|
|
|
|
/// Converts a slice of raw data into a reference of `Self`.
|
|
|
|
///
|
|
|
|
/// The value of `data` is not copied. Instead a reference is made from the given slice. The
|
|
|
|
/// value of `Self` will depend on the representation of the type in memory, and may change in
|
|
|
|
/// an unstable fashion.
|
|
|
|
///
|
2018-11-20 13:40:05 +00:00
|
|
|
/// This will return `None` if the length of data does not match the size of `Self`, or if the
|
|
|
|
/// data is not aligned for the type of `Self`.
|
2018-01-17 01:12:07 +00:00
|
|
|
fn from_slice(data: &[u8]) -> Option<&Self> {
|
2018-11-20 13:40:05 +00:00
|
|
|
// Early out to avoid an unneeded `align_to` call.
|
|
|
|
if data.len() != size_of::<Self>() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Safe because the DataInit trait asserts any data is valid for this type, and we ensured
|
|
|
|
// the size of the pointer's buffer is the correct size. The `align_to` method ensures that
|
|
|
|
// we don't have any unaligned references. This aliases a pointer, but because the pointer
|
|
|
|
// is from a const slice reference, there are no mutable aliases. Finally, the reference
|
|
|
|
// returned can not outlive data because they have equal implicit lifetime constraints.
|
|
|
|
match unsafe { data.align_to::<Self>() } {
|
|
|
|
([], [mid], []) => Some(mid),
|
|
|
|
_ => None,
|
2018-01-17 01:12:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts a mutable slice of raw data into a mutable reference of `Self`.
|
|
|
|
///
|
|
|
|
/// Because `Self` is made from a reference to the mutable slice`, mutations to the returned
|
|
|
|
/// reference are immediately reflected in `data`. The value of the returned `Self` will depend
|
|
|
|
/// on the representation of the type in memory, and may change in an unstable fashion.
|
|
|
|
///
|
2018-11-20 13:40:05 +00:00
|
|
|
/// This will return `None` if the length of data does not match the size of `Self`, or if the
|
|
|
|
/// data is not aligned for the type of `Self`.
|
2018-01-17 01:12:07 +00:00
|
|
|
fn from_mut_slice(data: &mut [u8]) -> Option<&mut Self> {
|
2018-11-20 13:40:05 +00:00
|
|
|
// Early out to avoid an unneeded `align_to_mut` call.
|
|
|
|
if data.len() != size_of::<Self>() {
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Safe because the DataInit trait asserts any data is valid for this type, and we ensured
|
|
|
|
// the size of the pointer's buffer is the correct size. The `align_to` method ensures that
|
|
|
|
// we don't have any unaligned references. This aliases a pointer, but because the pointer
|
|
|
|
// is from a mut slice reference, we borrow the passed in mutable reference. Finally, the
|
|
|
|
// reference returned can not outlive data because they have equal implicit lifetime
|
|
|
|
// constraints.
|
|
|
|
match unsafe { data.align_to_mut::<Self>() } {
|
|
|
|
([], [mid], []) => Some(mid),
|
|
|
|
_ => None,
|
2018-01-17 01:12:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts a reference to `self` into a slice of bytes.
|
|
|
|
///
|
|
|
|
/// The value of `self` is not copied. Instead, the slice is made from a reference to `self`.
|
|
|
|
/// The value of bytes in the returned slice will depend on the representation of the type in
|
|
|
|
/// memory, and may change in an unstable fashion.
|
|
|
|
fn as_slice(&self) -> &[u8] {
|
|
|
|
// Safe because the entire size of self is accessible as bytes because the trait guarantees
|
|
|
|
// it. The lifetime of the returned slice is the same as the passed reference, so that no
|
|
|
|
// dangling pointers will result from this pointer alias.
|
|
|
|
unsafe { from_raw_parts(self as *const Self as *const u8, size_of::<Self>()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Converts a mutable reference to `self` into a mutable slice of bytes.
|
|
|
|
///
|
|
|
|
/// Because the slice is made from a reference to `self`, mutations to the returned slice are
|
|
|
|
/// immediately reflected in `self`. The value of bytes in the returned slice will depend on
|
|
|
|
/// the representation of the type in memory, and may change in an unstable fashion.
|
|
|
|
fn as_mut_slice(&mut self) -> &mut [u8] {
|
|
|
|
// Safe because the entire size of self is accessible as bytes because the trait guarantees
|
|
|
|
// it. The trait also guarantees that any combination of bytes is valid for this type, so
|
|
|
|
// modifying them in the form of a byte slice is valid. The lifetime of the returned slice
|
|
|
|
// is the same as the passed reference, so that no dangling pointers will result from this
|
|
|
|
// pointer alias. Although this does alias a mutable pointer, we do so by exclusively
|
|
|
|
// borrowing the given mutable reference.
|
|
|
|
unsafe { from_raw_parts_mut(self as *mut Self as *mut u8, size_of::<Self>()) }
|
|
|
|
}
|
|
|
|
}
|
2017-06-20 20:44:40 +00:00
|
|
|
|
|
|
|
// All intrinsic types and arays of intrinsic types are DataInit. They are just numbers.
|
|
|
|
macro_rules! array_data_init {
|
|
|
|
($T:ty, $($N:expr)+) => {
|
|
|
|
$(
|
|
|
|
unsafe impl DataInit for [$T; $N] {}
|
|
|
|
)+
|
|
|
|
}
|
|
|
|
}
|
|
|
|
macro_rules! data_init_type {
|
2018-11-20 13:40:05 +00:00
|
|
|
($($T:ident),*) => {
|
|
|
|
$(
|
|
|
|
unsafe impl DataInit for $T {}
|
|
|
|
array_data_init! {
|
|
|
|
$T,
|
|
|
|
0 1 2 3 4 5 6 7 8 9
|
|
|
|
10 11 12 13 14 15 16 17 18 19
|
|
|
|
20 21 22 23 24 25 26 27 28 29
|
|
|
|
30 31 32
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
#[cfg(test)]
|
|
|
|
mod data_init_tests {
|
|
|
|
use std::mem::{size_of, align_of};
|
2019-03-08 23:57:49 +00:00
|
|
|
use crate::DataInit;
|
2018-11-20 13:40:05 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn from_slice_alignment() {
|
|
|
|
let mut v = [0u8; 32];
|
|
|
|
$(
|
2019-04-15 22:30:21 +00:00
|
|
|
let (pre, _, _) = unsafe { v.align_to::<$T>() };
|
|
|
|
let pre_len = pre.len();
|
|
|
|
|
|
|
|
let aligned_v = &mut v[pre_len..pre_len + size_of::<$T>()];
|
|
|
|
|
|
|
|
let from_aligned = $T::from_slice(aligned_v);
|
|
|
|
assert_eq!(from_aligned, Some(&0));
|
|
|
|
|
|
|
|
let from_aligned_mut = $T::from_mut_slice(aligned_v);
|
|
|
|
assert_eq!(from_aligned_mut, Some(&mut 0));
|
|
|
|
|
2018-11-20 13:40:05 +00:00
|
|
|
for i in 1..size_of::<$T>() {
|
|
|
|
let begin = pre_len + i;
|
|
|
|
let end = begin + size_of::<$T>();
|
|
|
|
let unaligned_v = &mut v[begin..end];
|
2019-04-15 22:30:21 +00:00
|
|
|
|
|
|
|
let from_unaligned = $T::from_slice(unaligned_v);
|
|
|
|
if align_of::<$T>() != 1 {
|
|
|
|
assert_eq!(from_unaligned, None);
|
2018-11-20 13:40:05 +00:00
|
|
|
}
|
2019-04-15 22:30:21 +00:00
|
|
|
|
|
|
|
let from_unaligned_mut = $T::from_mut_slice(unaligned_v);
|
|
|
|
if align_of::<$T>() != 1 {
|
|
|
|
assert_eq!(from_unaligned_mut, None);
|
2018-11-20 13:40:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)*
|
|
|
|
|
|
|
|
}
|
2017-06-20 20:44:40 +00:00
|
|
|
}
|
2018-10-03 17:22:32 +00:00
|
|
|
};
|
2017-06-20 20:44:40 +00:00
|
|
|
}
|
2018-11-20 13:40:05 +00:00
|
|
|
data_init_type!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
|
2017-06-22 21:04:43 +00:00
|
|
|
|
|
|
|
pub mod endian;
|
2019-03-08 23:57:49 +00:00
|
|
|
pub use crate::endian::*;
|
2017-06-24 00:24:13 +00:00
|
|
|
|
|
|
|
pub mod volatile_memory;
|
2019-03-08 23:57:49 +00:00
|
|
|
pub use crate::volatile_memory::*;
|