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

vigna / epserde-rs / 29101819327

10 Jul 2026 02:57PM UTC coverage: 47.056% (+1.0%) from 46.037%
29101819327

push

github

vigna
Restructured and deduplicated derive code

0 of 965 new or added lines in 13 files covered. (0.0%)

30 existing lines in 5 files now uncovered.

999 of 2123 relevant lines covered (47.06%)

583.44 hits per line

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

92.86
/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
//! The string types `String`, `Box<str>`, and `&str` have the same
11
//! serialization type, `Box<str>`; the deserializable owners `String` and
12
//! `Box<str>` have deserialization type `&str`. Thus, you can serialize a
13
//! `String` and fully deserialize it as `Box<str>`.
14
//!
15
//! Similarly to the case of [slices], the [`SerInner`] implementation for
16
//! `&str` is a serialization-only convenience.
17
//!
18
//! We implement [`TypeHash`] for `str` so that it can be used in
19
//! [`PhantomData`].
20
//!
21
//! [slices]: crate::impls::slice
22
//! [`PhantomData`]: core::marker::PhantomData
23

24
use crate::{check_covariance, prelude::*};
25
use core::hash::Hash;
26
use deser::*;
27
use ser::*;
28

29
#[cfg(not(feature = "std"))]
30
use alloc::boxed::Box;
31

32
unsafe impl CopyType for String {
33
    type Copy = Deep;
34
}
35

36
#[cfg(not(feature = "std"))]
37
use alloc::string::String;
38

39
impl TypeHash for String {
40
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
1✔
41
        "String".hash(hasher);
3✔
42
    }
43
}
44

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

49
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
25✔
50
        unsafe { ser_slice_zero(backend, self.as_bytes()) }
75✔
51
    }
52
}
53

54
impl DeserInner for String {
55
    check_covariance!();
56
    unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
32✔
57
        let slice = unsafe { deser_full_vec_zero(backend) }?;
96✔
58
        // SAFETY: the bytes are valid UTF-8 because the data comes from a
59
        // correct serialization (see the Deserialize contract).
60
        Ok(unsafe { String::from_utf8_unchecked(slice) })
32✔
61
    }
62

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

65
    unsafe fn _deser_eps_inner<'a>(
35✔
66
        backend: &mut SliceWithPos<'a>,
67
    ) -> deser::Result<Self::DeserType<'a>> {
68
        let slice = unsafe { deser_eps_slice_zero(backend) }?;
105✔
69
        // SAFETY: the bytes are valid UTF-8 because the data comes from a
70
        // correct serialization (see the Deserialize contract).
71
        Ok({
35✔
72
            unsafe {
35✔
73
                #[allow(clippy::transmute_bytes_to_str)]
35✔
74
                core::mem::transmute::<&'_ [u8], &'_ str>(slice)
35✔
75
            }
76
        })
77
    }
78
}
79

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

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

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

94
impl SerInner for Box<str> {
95
    type SerType = Self;
96
    // The bytes of a Box<str> are written as a zero-copy slice, but
97
    // Box<str> itself is not zero-copy.
98
    const IS_ZERO_COPY: bool = false;
99

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

105
impl DeserInner for Box<str> {
106
    check_covariance!();
107
    #[inline(always)]
108
    unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
4✔
109
        Ok(unsafe { String::_deser_full_inner(backend) }?.into_boxed_str())
12✔
110
    }
111

112
    type DeserType<'a> = &'a str;
113

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

122
// For use with PhantomData
123
impl TypeHash for str {
124
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
4✔
125
        "str".hash(hasher);
12✔
126
    }
127
}
128

129
impl TypeHash for &str {
UNCOV
130
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
×
131
        "&str".hash(hasher);
×
132
    }
133
}
134
unsafe impl CopyType for &str {
135
    type Copy = Deep;
136
}
137

138
impl SerInner for &str {
139
    type SerType = Box<str>;
140
    const IS_ZERO_COPY: bool = false;
141

142
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
467✔
143
        unsafe { ser_slice_zero(backend, self.as_bytes()) }
1,401✔
144
    }
145
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc