• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vigna / epserde-rs / 22098498149

17 Feb 2026 12:28PM UTC coverage: 52.283% (-1.7%) from 54.0%
22098498149

push

github

vigna
New covariance-checking infrastructure

7 of 61 new or added lines in 11 files covered. (11.48%)

1 existing line in 1 file now uncovered.

790 of 1511 relevant lines covered (52.28%)

482.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.67
/epserde/src/impls/pointer.rs
1
/*
2
 * SPDX-FileCopyrightText: 2025 Inria
3
 *
4
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5
 */
6

7
//! Blanket implementations for references and smart pointers.
8
//!
9
//! This module provides blanket implementations of serialization traits for
10
//! (mutable) references. Moreover, it provides (de)serialization support for
11
//! [`Box`], [`Rc`] and [`Arc`] if the `std` or `alloc` feature is enabled.
12
//!
13
//! While references have the obvious semantics (we serialize the referred
14
//! value), smart pointers are supported by erasure: if a type parameter has
15
//! value `Box<T>`, `Rc<T>`, or `Arc<T>`, we serialize `T` in its place (with
16
//! the exception of boxed slices, which [have their own
17
//! treatment](crate::impls::boxed_slice)).
18
//!
19
//! Upon deserialization, if the type parameter is `T` we deserialize `T`, but
20
//! if it is `Box<T>`, `Rc<T>`, or `Arc<T>` we deserialize `T` and then wrap
21
//! it in the appropriate smart pointer.
22
//!
23
//! In particular, this means that it is always possible to wrap in a smart pointer
24
//! type parameters, even if the serialized data did not come from a smart pointer.
25
//!
26
//! # Examples
27
//!
28
//! In this example we serialize a vector wrapped in an [`Rc`], but then we
29
//! deserialize it as a plain vector, or even wrapped with an [`Arc`]:
30
//!
31
//! ```
32
//! # use epserde::prelude::*;
33
//! # use std::rc::Rc;
34
//! # use std::sync::Arc;
35
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
36
//! let v = vec![1, 2, 3, 4, 5];
37
//! let mut cursor = <AlignedCursor<Aligned16>>::new();
38
//! unsafe { Rc::new(v).serialize(&mut cursor)?; }
39
//! // Rc is erased
40
//! cursor.set_position(0);
41
//! let _no_rc: Vec<i32> = unsafe { <Vec<i32>>::deserialize_full(&mut cursor)? };
42
//!
43
//! // In fact, we can deserialize wrapping in any smart pointer
44
//! cursor.set_position(0);
45
//! let _no_rc_but_arc: Arc<Vec<i32>> =
46
//!     unsafe { <Arc<Vec<i32>>>::deserialize_full(&mut cursor)? };
47
//! # Ok(())
48
//! # }
49
//! ```
50
//!
51
//! The same is true of fields, provided that their type is a type parameter:
52
//! ```
53
//! # use epserde::prelude::*;
54
//! # use std::rc::Rc;
55
//! # use std::sync::Arc;
56
//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
57
//! #[derive(Epserde)]
58
//! struct Data<A>(A);
59
//! let data = Data(Rc::new(vec![1, 2, 3, 4, 5]));
60
//! let mut cursor = <AlignedCursor<Aligned16>>::new();
61
//! unsafe { data.serialize(&mut cursor)?; }
62
//! // Rc is erased
63
//! cursor.set_position(0);
64
//! let _no_rc: Data<Vec<i32>> = unsafe { <Data<Vec<i32>>>::deserialize_full(&mut cursor)? };
65
//!
66
//! // In fact, we can deserialize wrapping in any smart pointer
67
//! cursor.set_position(0);
68
//! let _no_rc_but_arc: Data<Arc<Vec<i32>>> =
69
//!     unsafe { <Data<Arc<Vec<i32>>>>::deserialize_full(&mut cursor)? };
70
//! # Ok(())
71
//! # }
72
//! ```
73
use crate::prelude::*;
74
use ser::*;
75

76
macro_rules! impl_ser {
77
    ($type:ty) => {
78
        impl<T: SerInner> SerInner for $type {
79
            type SerType = T::SerType;
80
            const IS_ZERO_COPY: bool = <T as SerInner>::IS_ZERO_COPY;
81

82
            #[inline(always)]
83
            unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
18✔
84
                unsafe { <T as SerInner>::_ser_inner(self, backend) }
54✔
85
            }
86
        }
87
    };
88
}
89

90
impl_ser!(&T);
91
impl_ser!(&mut T);
92

93
#[cfg(not(feature = "std"))]
94
mod imports {
95
    pub use alloc::boxed::Box;
96
    pub use alloc::rc::Rc;
97
    pub use alloc::sync::Arc;
98
}
99
#[cfg(feature = "std")]
100
mod imports {
101
    pub use std::rc::Rc;
102
    pub use std::sync::Arc;
103
}
104
use imports::*;
105

106
macro_rules! impl_all {
107
    ($type:ident) => {
108
        impl_ser!($type<T>);
109

110
        impl<T: DeserInner> DeserInner for $type<T> {
111
            type DeserType<'a> = $type<DeserType<'a, T>>;
NEW
112
            fn __check_covariance<'__long: '__short, '__short>(
×
NEW
113
                p: deser::CovariantProof<Self::DeserType<'__long>>,
×
NEW
114
            ) -> deser::CovariantProof<Self::DeserType<'__short>> {
×
115
                // SAFETY: Box/Rc/Arc are covariant in T, and T::DeserType is
116
                // covariant (enforced by T's own __check_covariance).
NEW
117
                unsafe { core::mem::transmute(p) }
×
118
            }
119

120
            #[inline(always)]
121
            unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
9✔
122
                unsafe { <T as DeserInner>::_deser_full_inner(backend).map($type::new) }
27✔
123
            }
124
            #[inline(always)]
125
            unsafe fn _deser_eps_inner<'a>(
11✔
126
                backend: &mut SliceWithPos<'a>,
11✔
127
            ) -> deser::Result<Self::DeserType<'a>> {
11✔
128
                unsafe { <T as DeserInner>::_deser_eps_inner(backend).map($type::new) }
33✔
129
            }
130
        }
131
    };
132
}
133

134
impl_all!(Box);
135
impl_all!(Arc);
136
impl_all!(Rc);
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc