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
/*
* SPDX-FileCopyrightText: 2023 Inria
* SPDX-FileCopyrightText: 2023 Sebastiano Vigna
*
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
*/
//! Traits to mark types as zero-copy or deep-copy.
use crate::;
use sealed;
/// Internal trait used to select whether a type is zero-copy
/// or deep-copy.
///
/// It has only two implementations, [`Zero`] and [`Deep`].
///
/// In the first case, the type can be serialized from memory and deserialized
/// to memory as a sequence of bytes; in the second case, one has to
/// (de)serialize the type field by field.
/// An implementation of a [`CopySelector`] specifying that a type is zero-copy.
/// An implementation of a [`CopySelector`] specifying that a type is deep-copy.
/// Marker trait for data specifying whether it is zero-copy or deep-copy.
///
/// The trait comes in two flavors: `CopySelector<Type=Zero>` and
/// `CopySelector<Type=Deep>`. To each of these flavors corresponds two
/// dependent traits, [`ZeroCopy`] (which requires implementing [`Copy`],
/// [`AlignTo`], and be `'static`) and [`DeepCopy`], which are automatically
/// implemented.
///
/// You should not implement this trait manually, but rather use
/// the provided [derive macro](epserde_derive::Epserde).
///
/// We use this trait to implement a different behavior for [`ZeroCopy`] and
/// [`DeepCopy`] types, in particular on arrays, vectors, and boxed slices,
/// [working around the bug that prevents the compiler from understanding that
/// implementations for the two flavors of `CopySelector` are mutually
/// exclusive](https://github.com/rust-lang/rfcs/pull/1672#issuecomment-1405377983).
///
/// For an array of elements of type `T` to be zero-copy serializable and
/// deserializable, `T` must implement `CopySelector<Type=Zero>`. The conditions
/// for this marker trait are that `T` is a [copy type](Copy), that it has a
/// fixed memory layout, and that it does not contain any reference (in
/// particular, that it has `'static` lifetime). If this happen vectors of `T`
/// or boxed slices of `T` can be ε-copy deserialized using a reference to a
/// slice of `T`.
///
/// You can make zero-copy your own types, but you must ensure that they do not
/// contain references and that they have a fixed memory layout; for structures,
/// this requires `repr(C)`. ε-serde will track these conditions at compile time
/// and check them at runtime: in case of failure, serialization will panic.
///
/// Since we cannot use negative trait bounds, every type that is used as a
/// parameter of an array, vector or boxed slice must implement either
/// `CopySelector<Type=Zero>` or `CopySelector<Type=Deep>`. In the latter case,
/// slices will be deserialized element by element, and the result will be a
/// fully deserialized vector or boxed slice. If you do not implement either of
/// these traits, the type will not be serializable inside vectors or boxed
/// slices but error messages will be very unhelpful due to the contrived way we
/// have to implement mutually exclusive types.
///
/// If you use the provided derive macros all this logic will be hidden from
/// you. You'll just have to add `#[epserde(zero_copy)]` to your structures (if you want
/// them to be zero-copy) and ε-serde will do the rest.
///
/// # Safety
///
/// The trait is unsafe because the user must guarantee that zero-copy types do
/// not contain references, and this cannot be checked by the compiler.
pub unsafe
/// Marker trait for zero-copy types. You cannot implement this trait directly:
/// you rather implement the traits on which it depends, and then it is
/// automatically implemented by a blanket implementation.
///
/// Note that we require `SerInner<SerType = Self>` but just `DeserInner` and
/// not, say, `DeserInner<DeserType<'_> = &Self>`, which would be natural for
/// user-defined zero-copy types, because most primitive types have have
/// deserialization type `Self`.
/// Marker trait for deep-copy types. You cannot implement this trait directly:
/// you rather implement the traits on which it depends, and then it is automatically
/// implemented by a blanket implementation.
///
/// Note that we require `SerInner` but not `DeserInner` to make the
/// serialization of undeserializable types possible (for example, iterators).