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

vigna / epserde-rs / 28525681214

01 Jul 2026 02:39PM UTC coverage: 44.084% (+0.1%) from 43.952%
28525681214

push

github

vigna
Removed MIGHT_BE_ZERO_COPY, as IS_ZERO_COPY subsumes it (final part)

883 of 2003 relevant lines covered (44.08%)

449.05 hits per line

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

96.49
/epserde/src/impls/array.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 arrays.
9

10
use crate::prelude::*;
11
use core::hash::Hash;
12
use core::mem::MaybeUninit;
13
use deser::*;
14
use ser::*;
15

16
unsafe impl<T: CopyType, const N: usize> CopyType for [T; N] {
17
    type Copy = T::Copy;
18
}
19

20
impl<T: TypeHash, const N: usize> TypeHash for [T; N] {
21
    fn type_hash(hasher: &mut impl core::hash::Hasher) {
276✔
22
        "[]".hash(hasher);
828✔
23
        hasher.write_usize(N);
552✔
24
        T::type_hash(hasher);
552✔
25
    }
26
}
27

28
impl<T: AlignHash, const N: usize> AlignHash for [T; N] {
29
    fn align_hash(hasher: &mut impl core::hash::Hasher, offset_of: &mut usize) {
271✔
30
        if N == 0 {
271✔
31
            return;
×
32
        }
33
        T::align_hash(hasher, offset_of);
813✔
34
        *offset_of += (N - 1) * size_of::<T>();
271✔
35
    }
36
}
37

38
impl<T: AlignTo, const N: usize> AlignTo for [T; N] {
39
    fn align_to() -> usize {
42✔
40
        T::align_to()
42✔
41
    }
42
}
43

44
impl<T: CopyType + SerInner, const N: usize> SerInner for [T; N]
45
where
46
    [T; N]: SerHelper<<T as CopyType>::Copy>,
47
{
48
    type SerType = [T::SerType; N];
49
    const IS_ZERO_COPY: bool = T::IS_ZERO_COPY;
50
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
27✔
51
        unsafe { SerHelper::_ser_inner(self, backend) }
81✔
52
    }
53
}
54

55
impl<T: ZeroCopy, const N: usize> SerHelper<Zero> for [T; N] {
56
    #[inline(always)]
57
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
18✔
58
        ser_zero(backend, self)
54✔
59
    }
60
}
61

62
impl<T: DeepCopy, const N: usize> SerHelper<Deep> for [T; N] {
63
    unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
9✔
64
        for item in self.iter() {
36✔
65
            backend.write("item", item)?;
72✔
66
        }
67
        Ok(())
9✔
68
    }
69
}
70

71
impl<T: CopyType + DeserInner, const N: usize> DeserInner for [T; N]
72
where
73
    [T; N]: DeserHelper<<T as CopyType>::Copy, FullType = [T; N]>,
74
{
75
    type DeserType<'a> = <[T; N] as DeserHelper<<T as CopyType>::Copy>>::DeserType<'a>;
76
    // SAFETY: In the Zero case, DeserType<'a> = &'a [T; N], which is covariant.
77
    // In the Deep case, DeserType<'a> = [T::DeserType<'a>; N]; arrays are
78
    // covariant in their element type, and T::DeserType is covariant
79
    // (enforced by T's own __check_covariance).
80
    crate::unsafe_assume_covariance!(T);
81

82
    #[inline(always)]
83
    unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
59✔
84
        unsafe { <[T; N] as DeserHelper<<T as CopyType>::Copy>>::_deser_full_inner_impl(backend) }
118✔
85
    }
86

87
    #[inline(always)]
88
    unsafe fn _deser_eps_inner<'a>(
47✔
89
        backend: &mut SliceWithPos<'a>,
90
    ) -> deser::Result<<[T; N] as DeserHelper<<T as CopyType>::Copy>>::DeserType<'a>> {
91
        unsafe { <[T; N] as DeserHelper<<T as CopyType>::Copy>>::_deser_eps_inner_impl(backend) }
94✔
92
    }
93
}
94

95
impl<T: ZeroCopy + DeserInner, const N: usize> DeserHelper<Zero> for [T; N] {
96
    type FullType = Self;
97
    type DeserType<'a> = &'a [T; N];
98

99
    unsafe fn _deser_full_inner_impl(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
21✔
100
        let mut res = MaybeUninit::<[T; N]>::uninit();
42✔
101
        backend.align::<T>()?;
42✔
102
        // SAFETY: we read exactly size_of::<[T; N]>() bytes into res, and
103
        // read_exact guarantees that the array will be filled with data.
104
        unsafe {
105
            let slice = core::slice::from_raw_parts_mut(
106
                res.as_mut_ptr() as *mut u8,
21✔
107
                core::mem::size_of::<[T; N]>(),
21✔
108
            );
109
            backend.read_exact(slice)?;
63✔
110
            Ok(res.assume_init())
21✔
111
        }
112
    }
113

114
    unsafe fn _deser_eps_inner_impl<'a>(
9✔
115
        backend: &mut SliceWithPos<'a>,
116
    ) -> deser::Result<DeserType<'a, Self>> {
117
        let bytes = core::mem::size_of::<[T; N]>();
18✔
118
        if bytes == 0 {
9✔
119
            // SAFETY: [T; N] is zero-sized (see the NonNull::dangling docs)
120
            return Ok(unsafe { core::ptr::NonNull::<[T; N]>::dangling().as_ref() });
×
121
        }
122
        backend.align::<T>()?;
18✔
123
        let block = backend.data.get(..bytes).ok_or(deser::Error::ReadError)?;
54✔
124
        let (pre, data, after) = unsafe { block.align_to::<[T; N]>() };
36✔
125
        debug_assert!(pre.is_empty());
27✔
126
        debug_assert!(after.is_empty());
27✔
127
        let res = &data[0];
18✔
128
        backend.skip(bytes)?;
27✔
129
        Ok(res)
9✔
130
    }
131
}
132

133
/// Initializes an array element by element, dropping the already-initialized
134
/// prefix and returning the error if the initialization of an element fails.
135
fn try_init_array<T, const N: usize>(
84✔
136
    mut init: impl FnMut() -> deser::Result<T>,
137
) -> deser::Result<[T; N]> {
138
    let mut res = MaybeUninit::<[T; N]>::uninit();
168✔
139
    let first = res.as_mut_ptr() as *mut T;
252✔
140
    for i in 0..N {
216✔
141
        match init() {
132✔
142
            // SAFETY: the i-th slot of the array is in bounds
143
            Ok(v) => unsafe { first.add(i).write(v) },
384✔
144
            Err(e) => {
68✔
145
                // SAFETY: the first i slots of the array have been initialized
146
                for j in 0..i {
132✔
147
                    unsafe { first.add(j).drop_in_place() };
96✔
148
                }
149
                return Err(e);
68✔
150
            }
151
        }
152
    }
153
    // SAFETY: all N slots of the array have been initialized
154
    Ok(unsafe { res.assume_init() })
16✔
155
}
156

157
impl<T: DeepCopy + DeserInner, const N: usize> DeserHelper<Deep> for [T; N] {
158
    type FullType = Self;
159
    type DeserType<'a> = [DeserType<'a, T>; N];
160

161
    unsafe fn _deser_full_inner_impl(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
42✔
162
        try_init_array(|| unsafe { T::_deser_full_inner(backend) })
240✔
163
    }
164

165
    unsafe fn _deser_eps_inner_impl<'a>(
42✔
166
        backend: &mut SliceWithPos<'a>,
167
    ) -> deser::Result<DeserType<'a, Self>> {
168
        try_init_array(|| unsafe { T::_deser_eps_inner(backend) })
240✔
169
    }
170
}
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