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
/*
* SPDX-FileCopyrightText: 2025 Inria
*
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
*/
//! Blanket implementations for references and smart pointers.
//!
//! This module provides blanket implementations of serialization traits for
//! (mutable) references. Moreover, it provides (de)serialization support for
//! [`Box`], [`Rc`] and [`Arc`] if the `std` or `alloc` feature is enabled.
//!
//! While references have the obvious semantics (we serialize the referred
//! value), smart pointers 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, which [have their own
//! treatment](crate::impls::boxed_slice)).
//!
//! 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.
//!
//! We also provide an implementation of [`TypeHash`] for `*const T`, which is
//! useful to write tuples in [`PhantomData`](core::marker::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(())
//! # }
//! ```
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!;