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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
/*
* SPDX-FileCopyrightText: 2023 Inria
* SPDX-FileCopyrightText: 2023 Sebastiano Vigna
*
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
*/
/*!
Traits computing information about a type.
*/
use crate::pad_align_to;
use core::hash::Hash;
/// Recursively compute a type hash for a type.
///
/// [`TypeHash::type_hash`] is a recursive function that computes information
/// about a type. It is used to
/// check that the type of the data being deserialized matches
/// syntactically the type of the data that was written.
///
/// The type hasher should store information about the name and the type
/// of the fields of a type, and the name of the type itself.
pub trait TypeHash {
/// Accumulate type information in `hasher`.
fn type_hash(hasher: &mut impl core::hash::Hasher);
/// Call [`TypeHash::type_hash`] on a value.
fn type_hash_val(&self, hasher: &mut impl core::hash::Hasher) {
Self::type_hash(hasher);
}
}
/// Recursively compute a representational hash for a type.
///
/// [`ReprHash::repr_hash`] is a recursive function that computes
/// representation information about a zero-copy type. It is used to
/// check that the the alignment and the representation data
/// of the data being deserialized.
///
/// More precisely, at each call a zero-copy type look at `offset_of`,
/// assuming that the type is stored at that offset in the structure,
/// hashes in the padding necessary to make `offset_of` a multiple of
/// [`core::mem::align_of`] the type, hashes in the type size, and
/// finally increases `offset_of` by [`core::mem::size_of`] the type.
pub trait ReprHash {
/// Accumulate representional information in `hasher` assuming to
/// be positioned at `offset_of`.
fn repr_hash(_hasher: &mut impl core::hash::Hasher, _offset_of: &mut usize);
/// Call [`ReprHash::repr_hash`] on a value.
fn repr_hash_val(&self, hasher: &mut impl core::hash::Hasher, offset_of: &mut usize) {
Self::repr_hash(hasher, offset_of);
}
}
/// A function providing a reasonable default
/// implementation of [`ReprHash::repr_hash`] for basic sized types.
pub(crate) fn std_repr_hash<T>(hasher: &mut impl core::hash::Hasher, offset_of: &mut usize) {
let padding = pad_align_to(*offset_of, core::mem::align_of::<T>());
padding.hash(hasher);
core::mem::size_of::<T>().hash(hasher);
*offset_of += padding;
*offset_of += core::mem::size_of::<T>();
}
/// A trait providing the maximum size of a primitive field in a type
/// maximized with [`core::mem::align_of`].
///
/// We use the value returned by [`MaxSizeOf::max_size_of`]
/// to generate padding before storing a zero-copy type. Note that this
/// is different from the padding used to align the same type inside
/// a struct, which is not under our control and is
/// given by [`core::mem::align_of`].
///
/// In this way we increase interoperability between architectures
/// with different alignment requirements for the same types (e.g.,
/// 4 or 8 bytes for `u64`).
///
/// By maximizing with [`core::mem::align_of`] we ensure that
/// we provide sufficient alignment in case the attribute `repr(align(N))`
/// was specified.
pub trait MaxSizeOf: Sized {
fn max_size_of() -> usize;
}