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
/*
* SPDX-FileCopyrightText: 2025 Inria
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
//! Implementations for references and wrappers.
//!
//! This module provides implementations of serialization traits for (mutable)
//! references. Moreover, it provides (de)serialization support for [`Box`],
//! [`Rc`] and [`Arc`] (with the `std` feature, or through the `alloc` crate in
//! `no_std` builds).
//!
//! While references have the obvious semantics (we serialize the referred
//! value), wrappers are supported by erasure: if a type parameter has value
//! `Box<T>`, `Rc<T>`, or `Arc<T>`, we serialize `T` in its place (with the
//! exception of boxed slices and `Box<str>`, which have their own treatment
//! in [`boxed_slice`] and [`string`]).
//!
//! Upon deserialization, if the type parameter is `T` we deserialize `T`, but
//! if it is `Box<T>`, `Rc<T>`, or `Arc<T>` we deserialize `T` and then wrap
//! it in the appropriate smart pointer.
//!
//! In particular, this means that it is always possible to wrap in a smart
//! pointer type parameters, even if the serialized data did not come from a
//! smart pointer.
//!
//! `Box<T>`, `Rc<T>`, and `Arc<T>` implement only the (de)serialization traits,
//! and not [`CopyType`] or [`TypeHash`], so they cannot appear as sequence
//! elements (e.g., `Vec<Box<T>>`) or as [`PhantomData`] parameters. Boxed
//! slices and `Box<str>` are again the exception, having their own complete
//! implementations.
//!
//! We also provide an implementation of [`TypeHash`] for `*const T`, which is
//! useful to write tuples in [`PhantomData`] with unsized type parameters, such
//! as `PhantomData<(*const T, U)>` when `T` is unsized.
//!
//! # Examples
//!
//! In this example we serialize a vector wrapped in an [`Rc`], but then we
//! deserialize it as a plain vector, or even wrapped with an [`Arc`]:
//!
//! ```
//! # use epserde::prelude::*;
//! # use std::rc::Rc;
//! # use std::sync::Arc;
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let v = vec![1, 2, 3, 4, 5];
//! let mut cursor = <AlignedCursor<Aligned16>>::new();
//! unsafe { Rc::new(v).serialize(&mut cursor)?; }
//! // Rc is erased
//! cursor.set_position(0);
//! let _no_rc: Vec<i32> = unsafe { <Vec<i32>>::deserialize_full(&mut cursor)? };
//!
//! // In fact, we can deserialize wrapping in any smart pointer
//! cursor.set_position(0);
//! let _no_rc_but_arc: Arc<Vec<i32>> =
//! unsafe { <Arc<Vec<i32>>>::deserialize_full(&mut cursor)? };
//! # Ok(())
//! # }
//! ```
//!
//! The same is true of fields, provided that their type is a type parameter:
//! ```
//! # use epserde::prelude::*;
//! # use std::rc::Rc;
//! # use std::sync::Arc;
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
//! #[derive(Epserde)]
//! struct Data<A>(A);
//! let data = Data(Rc::new(vec![1, 2, 3, 4, 5]));
//! let mut cursor = <AlignedCursor<Aligned16>>::new();
//! unsafe { data.serialize(&mut cursor)?; }
//! // Rc is erased
//! cursor.set_position(0);
//! let _no_rc: Data<Vec<i32>> = unsafe { <Data<Vec<i32>>>::deserialize_full(&mut cursor)? };
//!
//! // In fact, we can deserialize wrapping in any smart pointer
//! cursor.set_position(0);
//! let _no_rc_but_arc: Data<Arc<Vec<i32>>> =
//! unsafe { <Data<Arc<Vec<i32>>>>::deserialize_full(&mut cursor)? };
//! # Ok(())
//! # }
//! ```
//!
//! [`boxed_slice`]: crate::impls::boxed_slice
//! [`string`]: crate::impls::string
//! [`PhantomData`]: core::marker::PhantomData
use crate*;
use Hash;
use *;
// For use with PhantomData<(*const T, ...)>, with T unsized
impl_ser!;
impl_ser!;
use *;
impl_all!;
impl_all!;
impl_all!;