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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*
* SPDX-FileCopyrightText: 2023 Inria
* SPDX-FileCopyrightText: 2023 Sebastiano Vigna
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
//! Traits computing information about a type.
use cratepad_align_to;
use Hash;
use ;
use ZeroCopy;
/// A [`core::hash::Hasher`] that accumulates the bytes fed to it into a
/// [SHA-256](Sha256) digest.
///
/// This is the hasher used to compute the type and alignment [hashes stored in
/// the header]. [`TypeHash`] and [`AlignHash`] only ever feed data into a
/// [`core::hash::Hasher`]; they never call [`finish`]. This wrapper exploits
/// that: [`write`] forwards the bytes to the SHA-256 state, while [`finish`] is
/// unreachable, since its 64-bit return value cannot represent the 256-bit
/// digest. Call [`CryptoHasher::finalize`] to obtain the digest instead.
///
/// [`finish`]: core::hash::Hasher::finish
/// [`write`]: core::hash::Hasher::write
/// [hashes stored in the header]: crate::ser::write_header
;
/// Recursively compute a type hash for a type.
///
/// [`type_hash`] is a recursive function that computes information about a
/// type. It is used to check that the serialization type of the data being
/// deserialized matches the serialization 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.
///
/// When serializing an instance of type `T`, [`SerType<T>`] must implement this
/// trait.
///
/// Additionally, it is recommended that commonly used types implement this
/// trait, even if their serialization type is different, because it makes it
/// possible to use correctly [`PhantomData`], which implements its type hash using
/// its argument type hash, and not the type hash of the serialization type of
/// its argument, so the type hash of `PhantomData<Vec<usize>>` is different
/// from that of `PhantomData<Box<[usize]>>` even if the type hash of the
/// serialization type of `Vec<usize>` and `Box<[usize]>` is the same.
///
/// [`type_hash`]: TypeHash::type_hash
/// [`SerType<T>`]: crate::ser::SerInner::SerType
/// [`PhantomData`]: core::marker::PhantomData
/// Recursively compute an alignment hash for a zero-copy type.
///
/// [`align_hash`] is a recursive function that computes alignment information
/// about zero-copy types. It is used to check that the alignment (and thus
/// padding) of data that is zero-copied matches the alignment at serialization
/// time.
///
/// More precisely, at each call a zero-copy type looks 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.
///
/// Deep-copy containers whose serialized form embeds zero-copy data (e.g.,
/// boxed slices, options, results) must forward [`align_hash`] to each such
/// component with a fresh `offset_of` equal to zero, since the component is
/// realigned in the stream. A no-op implementation is acceptable only when
/// the embedded zero-copy data is byte-like, that is, when its layout cannot
/// differ across architectures: for example, `Box<str>` implements
/// [`AlignHash`] as a no-op because its serialized form contains only bytes.
///
/// When serializing an instance of type `T`, [`SerType<T>`] must implement this
/// trait. Thus, if `T` different from its serialization type it is not
/// necessary to implement this trait for `T`. For example, [`String`] does not
/// need to implement this trait, because its serialization type is `Box<str>`,
/// which indeed implements this trait.
///
/// [`align_hash`]: AlignHash::align_hash
/// [`SerType<T>`]: crate::ser::SerInner::SerType
/// [`String`]: https://doc.rust-lang.org/alloc/string/struct.String.html
/// A function providing a reasonable default
/// implementation of [`AlignHash::align_hash`] for basic sized types.
pub
/// A trait providing the desired alignment of zero-copy types in serialized
/// data.
///
/// We use the value returned by [`PadTo::pad_to`] 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`].
///
/// The alignment returned by this function is computed by maximizing the
/// alignment required by the type itself (i.e., [`core::mem::align_of`]) and
/// the [`PadTo::pad_to`] of its fields; moreover, [`PadTo::pad_to`] of
/// primitive types is defined using the size, rather than the value returned 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.
///
/// Deep-copy types do not need to implement [`PadTo`].