// Copyright 2019 The ChromiumOS Authors1// Use of this source code is governed by a BSD-style license that can be2// found in the LICENSE file.34//! A wrapper for structures that contain flexible arrays.5//!6//! The following code provides generic helpers for creating and accessing flexible array structs.7//! A complete definition of flexible array structs is found in the ISO 9899 specification8//! <http://www.iso-9899.info/n1570.html>. A flexible array struct is of the form:9//!10//! ```ignore11//! #[repr(C)]12//! struct T {13//! some_data: u32,14//! nents: u32,15//! entries: __IncompleteArrayField<S>,16//! }17//! ```18//! where:19//!20//! - `T` is the flexible array struct type21//! - `S` is the flexible array type22//! - `nents` is the flexible array length23//! - `entries` is the flexible array member24//!25//! These structures are used by the kernel API.2627use std::marker::PhantomData;28use std::mem::size_of;2930// Returns a `Vec<T>` with a size in bytes at least as large as `size_in_bytes`.31fn vec_with_size_in_bytes<T: Default>(size_in_bytes: usize) -> Vec<T> {32let rounded_size = size_in_bytes.div_ceil(size_of::<T>());33let mut v = Vec::with_capacity(rounded_size);34v.resize_with(rounded_size, T::default);35v36}3738/// The kernel API has many structs that resemble the following `Foo` structure:39///40/// ```ignore41/// #[repr(C)]42/// struct Foo {43/// some_data: u32,44/// entries: __IncompleteArrayField<__u32>,45/// }46/// ```47///48/// In order to allocate such a structure, `size_of::<Foo>()` would be too small because it would49/// not include any space for `entries`. To make the allocation large enough while still being50/// aligned for `Foo`, a `Vec<Foo>` is created. Only the first element of `Vec<Foo>` would actually51/// be used as a `Foo`. The remaining memory in the `Vec<Foo>` is for `entries`, which must be52/// contiguous with `Foo`. This function is used to make the `Vec<Foo>` with enough space for53/// `count` entries.54pub fn vec_with_array_field<T: Default, F>(count: usize) -> Vec<T> {55let element_space = count * size_of::<F>();56let vec_size_bytes = size_of::<T>() + element_space;57vec_with_size_in_bytes(vec_size_bytes)58}5960/// A collection of methods that are required by the FlexibleArrayWrapper type.61///62/// When implemented for `T`, this trait allows the caller to set number of `S` entries and63/// retrieve a slice of `S` entries. Trait methods must only be called by the FlexibleArrayWrapper64/// type. Don't implement this trait directly, use the flexible_array! macro to avoid duplication.65pub trait FlexibleArray<S> {66/// Implementations must set flexible array length in the flexible array struct to the value67/// specified by `len`. Appropriate conversions (i.e, usize to u32) are allowed so long as68/// they don't overflow or underflow.69fn set_len(&mut self, len: usize);70/// Implementations must return the length of the flexible array member. Appropriate71/// conversions (i.e, usize to u32) are allowed so long as they don't overflow or underflow.72fn get_len(&self) -> usize;73/// Implementations must return a slice of flexible array member of length `len`.74/// # Safety75/// Do not use this function directly, as the FlexibleArrayWrapper will guarantee safety.76unsafe fn get_slice(&self, len: usize) -> &[S];77/// Implementations must return a mutable slice of flexible array member of length `len`.78/// # Safety79/// Do not use this function directly, as the FlexibleArrayWrapper will guarantee safety.80unsafe fn get_mut_slice(&mut self, len: usize) -> &mut [S];81}8283/// Always use this macro for implementing the FlexibleArray<`S`> trait for a given `T`. There84/// exists an 1:1 mapping of macro identifiers to the definitions in the FlexibleArray<`S`>85/// documentation, so refer to that for more information.86#[macro_export]87macro_rules! flexible_array_impl {88($T:ident, $S:ident, $nents:ident, $entries:ident) => {89impl $crate::FlexibleArray<$S> for $T {90fn set_len(&mut self, len: usize) {91self.$nents = ::std::convert::TryInto::try_into(len).unwrap();92}9394fn get_len(&self) -> usize {95self.$nents as usize96}9798unsafe fn get_slice(&self, len: usize) -> &[$S] {99self.$entries.as_slice(len)100}101102unsafe fn get_mut_slice(&mut self, len: usize) -> &mut [$S] {103self.$entries.as_mut_slice(len)104}105}106};107}108109pub struct FlexibleArrayWrapper<T, S> {110entries: Vec<T>,111phantom: PhantomData<S>,112allocated_len: usize,113}114115/// Convenience wrapper for flexible array structs.116///117/// The FlexibleArray trait must be implemented for the flexible array struct before using this118/// wrapper.119impl<T, S> FlexibleArrayWrapper<T, S>120where121T: FlexibleArray<S> + Default,122{123/// Creates a new FlexibleArrayWrapper for the given flexible array struct type and flexible124/// array type. The flexible array length is set to `array_len`. vec_with_array_field is used125/// to make sure the resultant wrapper is appropriately sized.126pub fn new(array_len: usize) -> FlexibleArrayWrapper<T, S> {127let mut entries = vec_with_array_field::<T, S>(array_len);128entries[0].set_len(array_len);129130FlexibleArrayWrapper {131entries,132phantom: PhantomData,133allocated_len: array_len,134}135}136137/// Mapping the unsized array to a slice is unsafe because the length isn't known. Using138/// the length we originally allocated with eliminates the possibility of overflow.139fn get_valid_len(&self) -> usize {140if self.entries[0].get_len() > self.allocated_len {141self.allocated_len142} else {143self.entries[0].get_len()144}145}146147/// Returns a slice of the flexible array member, for inspecting. To modify, use148/// mut_entries_slice instead.149pub fn entries_slice(&self) -> &[S] {150let valid_length = self.get_valid_len();151// SAFETY:152// Safe because the length has been validated.153unsafe { self.entries[0].get_slice(valid_length) }154}155156/// Returns a mutable slice of the flexible array member, for modifying.157pub fn mut_entries_slice(&mut self) -> &mut [S] {158let valid_length = self.get_valid_len();159self.entries[0].set_len(valid_length);160// SAFETY:161// Safe because the length has been validated.162unsafe { self.entries[0].get_mut_slice(valid_length) }163}164165/// Get a pointer so it can be passed to the kernel. Callers must not access the flexible166/// array member. Using this pointer is unsafe.167pub fn as_ptr(&self) -> *const T {168&self.entries[0]169}170171/// Get a mutable pointer so it can be passed to the kernel. Callers must not access the172/// flexible array member. Using this pointer is unsafe.173pub fn as_mut_ptr(&mut self) -> *mut T {174&mut self.entries[0]175}176}177178179