• 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

81.25
/epserde/src/impls/string.rs
1
/*
2
 * SPDX-FileCopyrightText: 2023 Inria
3
 * SPDX-FileCopyrightText: 2023 Sebastiano Vigna
4
 *
5
 * SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
6
 */
7

8
//! Implementations for strings.
9
//!
10
//! All string types have the same serialization type, `Box<str>`, and the same
11
//! deserialization type, `&str`. Thus, you can serialize a `String` and fully
12
//! deserialize it as `Box<str>`.
13
//!
14
//! Similarly to the case of [slices](crate::impls::slice), there is
15
//! a convenience [`SerInner`] implementation for `&str` that
16
//! serializes it as `Box<str>`.
17
//!
18
//! We provide type hashes for `String` and `str` so that they can be used
19
//! in [`PhantomData`](core::marker::PhantomData).
20

21
use crate::prelude::*;
22
use core::hash::Hash;
23
use deser::*;
24
use ser::*;
25

26
#[cfg(not(feature = "std"))]
27
use alloc::boxed::Box;
28

29
unsafe impl CopyType for String {
30
    type Copy = Deep;
31
}
32

33
#[cfg(not(feature = "std"))]
34
use alloc::string::String;
35

36
// For use with PhantomData
37
impl TypeHash for String {
38
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
1✔
39
        "String".hash(hasher);
3✔
40
    }
41
}
42

43
impl SerInner for String {
44
    type SerType = Box<str>;
45
    const IS_ZERO_COPY: bool = false;
46

47
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
22✔
48
        ser_slice_zero(backend, self.as_bytes())
66✔
49
    }
50
}
51

52
impl DeserInner for String {
NEW
53
    fn __check_covariance<'__long: '__short, '__short>(
×
54
        p: deser::CovariantProof<Self::DeserType<'__long>>,
55
    ) -> deser::CovariantProof<Self::DeserType<'__short>> {
NEW
56
        p
×
57
    }
58
    unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
695✔
59
        let slice = unsafe { deser_full_vec_zero(backend) }?;
2,085✔
60
        Ok(String::from_utf8(slice).unwrap())
1,390✔
61
    }
62

63
    type DeserType<'a> = &'a str;
64

65
    unsafe fn _deser_eps_inner<'a>(
32✔
66
        backend: &mut SliceWithPos<'a>,
67
    ) -> deser::Result<Self::DeserType<'a>> {
68
        let slice = unsafe { deser_eps_slice_zero(backend) }?;
96✔
69
        // SAFETY: Actually this is unsafe if the data we read is not valid UTF-8
70
        Ok({
32✔
71
            unsafe {
32✔
72
                #[allow(clippy::transmute_bytes_to_str)]
32✔
73
                core::mem::transmute::<&'_ [u8], &'_ str>(slice)
32✔
74
            }
75
        })
76
    }
77
}
78

79
unsafe impl CopyType for Box<str> {
80
    type Copy = Deep;
81
}
82

83
impl TypeHash for Box<str> {
84
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
41✔
85
        "Box<str>".hash(hasher);
123✔
86
    }
87
}
88

89
impl AlignHash for Box<str> {
90
    fn align_hash(_hasher: &mut impl core::hash::Hasher, _offset_of: &mut usize) {}
88✔
91
}
92

93
impl SerInner for Box<str> {
94
    type SerType = Self;
95
    // Box<[$ty]> can, but Vec<Box<[$ty]>> cannot!
96
    const IS_ZERO_COPY: bool = false;
97

98
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
2✔
99
        ser_slice_zero(backend, self.as_bytes())
6✔
100
    }
101
}
102

103
impl DeserInner for Box<str> {
NEW
104
    fn __check_covariance<'__long: '__short, '__short>(
×
105
        p: deser::CovariantProof<Self::DeserType<'__long>>,
106
    ) -> deser::CovariantProof<Self::DeserType<'__short>> {
NEW
107
        p
×
108
    }
109
    #[inline(always)]
110
    unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
4✔
111
        Ok(unsafe { String::_deser_full_inner(backend) }?.into_boxed_str())
12✔
112
    }
113

114
    type DeserType<'a> = &'a str;
115

116
    #[inline(always)]
117
    unsafe fn _deser_eps_inner<'a>(
6✔
118
        backend: &mut SliceWithPos<'a>,
119
    ) -> deser::Result<Self::DeserType<'a>> {
120
        unsafe { String::_deser_eps_inner(backend) }
12✔
121
    }
122
}
123

124
// For use with PhantomData
125
impl TypeHash for str {
126
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
1✔
127
        "str".hash(hasher);
3✔
128
    }
129
}
130

131
// For use with PhantomData
132
impl TypeHash for &str {
133
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
×
134
        "&str".hash(hasher);
×
135
    }
136
}
137
unsafe impl CopyType for &str {
138
    type Copy = Deep;
139
}
140

141
impl SerInner for &str {
142
    type SerType = Box<str>;
143
    const IS_ZERO_COPY: bool = false;
144

145
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
336✔
146
        ser_slice_zero(backend, self.as_bytes())
1,008✔
147
    }
148
}
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