• 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

93.88
/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) {
69✔
22
        "[]".hash(hasher);
207✔
23
        hasher.write_usize(N);
138✔
24
        T::type_hash(hasher);
138✔
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) {
64✔
30
        if N == 0 {
64✔
31
            return;
×
32
        }
33
        T::align_hash(hasher, offset_of);
192✔
34
        *offset_of += (N - 1) * size_of::<T>();
64✔
35
    }
36
}
37

38
impl<T: AlignTo, const N: usize> AlignTo for [T; N] {
39
    fn align_to() -> usize {
44✔
40
        T::align_to()
44✔
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<()> {
23✔
51
        unsafe { SerHelper::_ser_inner(self, backend) }
69✔
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<()> {
15✔
58
        ser_zero(backend, self)
45✔
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<()> {
8✔
64
        for item in self.iter() {
32✔
65
            backend.write("item", item)?;
64✔
66
        }
67
        Ok(())
8✔
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>;
NEW
76
    fn __check_covariance<'__long: '__short, '__short>(
×
77
        p: deser::CovariantProof<Self::DeserType<'__long>>,
78
    ) -> deser::CovariantProof<Self::DeserType<'__short>> {
79
        // SAFETY: In the Zero case, DeserType<'a> = &'a [T; N], which is covariant.
80
        // In the Deep case, DeserType<'a> = [T::DeserType<'a>; N]; arrays are
81
        // covariant in their element type, and T::DeserType is covariant
82
        // (enforced by T's own __check_covariance).
NEW
83
        unsafe { core::mem::transmute(p) }
×
84
    }
85

86
    #[inline(always)]
87
    unsafe fn _deser_full_inner(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
24✔
88
        unsafe { <[T; N] as DeserHelper<<T as CopyType>::Copy>>::_deser_full_inner_impl(backend) }
48✔
89
    }
90

91
    #[inline(always)]
92
    unsafe fn _deser_eps_inner<'a>(
15✔
93
        backend: &mut SliceWithPos<'a>,
94
    ) -> deser::Result<<[T; N] as DeserHelper<<T as CopyType>::Copy>>::DeserType<'a>> {
95
        unsafe { <[T; N] as DeserHelper<<T as CopyType>::Copy>>::_deser_eps_inner_impl(backend) }
30✔
96
    }
97
}
98

99
impl<T: ZeroCopy + DeserInner, const N: usize> DeserHelper<Zero> for [T; N] {
100
    type FullType = Self;
101
    type DeserType<'a> = &'a [T; N];
102

103
    unsafe fn _deser_full_inner_impl(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
18✔
104
        let mut res = MaybeUninit::<[T; N]>::uninit();
36✔
105
        backend.align::<T>()?;
36✔
106
        // SAFETY: read_exact guarantees that the array will be filled with data.
107
        unsafe {
108
            backend.read_exact(res.assume_init_mut().align_to_mut::<u8>().1)?;
54✔
109
            Ok(res.assume_init())
18✔
110
        }
111
    }
112

113
    unsafe fn _deser_eps_inner_impl<'a>(
9✔
114
        backend: &mut SliceWithPos<'a>,
115
    ) -> deser::Result<DeserType<'a, Self>> {
116
        backend.align::<T>()?;
18✔
117
        let bytes = core::mem::size_of::<[T; N]>();
18✔
118
        let (pre, data, after) = unsafe { backend.data[..bytes].align_to::<[T; N]>() };
36✔
119
        debug_assert!(pre.is_empty());
27✔
120
        debug_assert!(after.is_empty());
27✔
121
        let res = &data[0];
18✔
122
        backend.skip(bytes);
27✔
123
        Ok(res)
9✔
124
    }
125
}
126

127
impl<T: DeepCopy + DeserInner, const N: usize> DeserHelper<Deep> for [T; N] {
128
    type FullType = Self;
129
    type DeserType<'a> = [DeserType<'a, T>; N];
130

131
    unsafe fn _deser_full_inner_impl(backend: &mut impl ReadWithPos) -> deser::Result<Self> {
8✔
132
        let mut res = MaybeUninit::<[T; N]>::uninit();
16✔
133
        for item in &mut unsafe { res.assume_init_mut().iter_mut() } {
24✔
134
            unsafe { core::ptr::write(item, T::_deser_full_inner(backend)?) };
64✔
135
        }
136
        Ok(unsafe { res.assume_init() })
8✔
137
    }
138

139
    unsafe fn _deser_eps_inner_impl<'a>(
8✔
140
        backend: &mut SliceWithPos<'a>,
141
    ) -> deser::Result<DeserType<'a, Self>> {
142
        let mut res = MaybeUninit::<DeserType<'a, Self>>::uninit();
16✔
143
        for item in &mut unsafe { res.assume_init_mut().iter_mut() } {
24✔
144
            unsafe { core::ptr::write(item, T::_deser_eps_inner(backend)?) };
64✔
145
        }
146
        Ok(unsafe { res.assume_init() })
8✔
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