Coverage Report

Created: 2026-09-14 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerovec-0.11.8/src/ule/multi.rs
Line
Count
Source
1
// This file is part of ICU4X. For terms of use, please see the file
2
// called LICENSE at the top level of the ICU4X source tree
3
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5
use super::*;
6
use crate::varzerovec::lengthless::VarZeroLengthlessSlice;
7
use crate::vecs::VarZeroVecFormat;
8
#[cfg(doc)]
9
use crate::VarZeroSlice;
10
use core::fmt;
11
12
/// This type is used by the custom derive to represent multiple [`VarULE`]
13
/// fields packed into a single end-of-struct field. It is not recommended
14
/// to use this type directly, use [`Tuple2VarULE`](crate::ule::tuplevar::Tuple2VarULE) etc instead.
15
///
16
/// Logically, consider it to be `(, , , ..)`
17
/// where ` ` etc are potentially different [`VarULE`] types.
18
///
19
/// Internally, it is represented by a [`VarZeroSlice`] without the length part.
20
#[derive(PartialEq, Eq)]
21
#[repr(transparent)]
22
pub struct MultiFieldsULE<const LEN: usize, Format: VarZeroVecFormat>(
23
    VarZeroLengthlessSlice<[u8], Format>,
24
);
25
26
impl<const LEN: usize, Format: VarZeroVecFormat> MultiFieldsULE<LEN, Format> {
27
    /// Compute the amount of bytes needed to support elements with lengths `lengths`
28
    #[inline]
29
    #[expect(clippy::expect_used)] // See #1410
30
0
    pub fn compute_encoded_len_for(lengths: [usize; LEN]) -> usize {
31
0
        let lengths = lengths.map(BlankSliceEncoder);
32
0
        crate::varzerovec::components::compute_serializable_len_without_length::<_, _, Format>(
33
0
            &lengths,
34
0
        )
35
0
        .expect("Too many bytes to encode") as usize
36
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<2, zerovec::varzerovec::components::Index16>>::compute_encoded_len_for
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<_, _>>::compute_encoded_len_for
37
38
    /// Construct a partially initialized `MultiFieldsULE` backed by a mutable byte buffer
39
0
    pub fn new_from_lengths_partially_initialized<'a>(
40
0
        lengths: [usize; LEN],
41
0
        output: &'a mut [u8],
42
0
    ) -> &'a mut Self {
43
0
        let lengths = lengths.map(BlankSliceEncoder);
44
0
        crate::varzerovec::components::write_serializable_bytes_without_length::<_, _, Format>(
45
0
            &lengths, output,
46
        );
47
0
        debug_assert!(
48
0
            <VarZeroLengthlessSlice<[u8], Format>>::parse_bytes(LEN as u32, output).is_ok(),
49
0
            "Encoded slice must be valid VarZeroSlice"
50
        );
51
0
        unsafe {
52
0
            // Safe since write_serializable_bytes produces a valid VarZeroLengthlessSlice buffer with the right format
53
0
            let slice = VarZeroLengthlessSlice::<[u8], Format>::from_bytes_unchecked_mut(output);
54
0
            // safe since `Self` is transparent over VarZeroLengthlessSlice<[u8], Format>
55
0
            &mut *(slice as *mut VarZeroLengthlessSlice<[u8], Format>
56
0
                as *mut MultiFieldsULE<LEN, Format>)
57
0
        }
58
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<2, zerovec::varzerovec::components::Index16>>::new_from_lengths_partially_initialized
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<_, _>>::new_from_lengths_partially_initialized
59
60
    /// Given a buffer of size obtained by [`Self::compute_encoded_len_for()`], write element A to index idx
61
    ///
62
    /// # Safety
63
    /// - `idx` must be in range
64
    /// - `T` must be the appropriate type expected by the custom derive in this usage of this type
65
    #[inline]
66
0
    pub unsafe fn set_field_at<T: VarULE + ?Sized, A: EncodeAsVarULE<T> + ?Sized>(
67
0
        &mut self,
68
0
        idx: usize,
69
0
        value: &A,
70
0
    ) {
71
0
        value.encode_var_ule_write(self.0.get_bytes_at_mut(LEN as u32, idx))
72
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<2, zerovec::varzerovec::components::Index16>>::set_field_at::<zerovec::varzerovec::slice::VarZeroSlice<str>, zerovec::varzerovec::slice::VarZeroSlice<str>>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<2, zerovec::varzerovec::components::Index16>>::set_field_at::<icu_collections::codepointinvlist::cpinvlist::CodePointInversionListULE, icu_collections::codepointinvlist::cpinvlist::CodePointInversionList>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<_, _>>::set_field_at::<_, _>
73
74
    /// Validate field at `index` to see if it is a valid `T` [`VarULE`] type
75
    ///
76
    /// # Safety
77
    ///
78
    /// - `index` must be in range
79
    #[inline]
80
0
    pub unsafe fn validate_field<T: VarULE + ?Sized>(&self, index: usize) -> Result<(), UleError> {
81
0
        T::validate_bytes(self.0.get_unchecked(LEN as u32, index))
82
0
    }
83
84
    /// Get field at `index` as a value of type T
85
    ///
86
    /// # Safety
87
    ///
88
    /// - `index` must be in range
89
    /// - Element at `index` must have been created with the [`VarULE`] type T
90
    #[inline]
91
0
    pub unsafe fn get_field<T: VarULE + ?Sized>(&self, index: usize) -> &T {
92
0
        T::from_bytes_unchecked(self.0.get_unchecked(LEN as u32, index))
93
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<2, zerovec::varzerovec::components::Index16>>::get_field::<zerovec::varzerovec::slice::VarZeroSlice<str>>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<2, zerovec::varzerovec::components::Index16>>::get_field::<icu_collections::codepointinvlist::cpinvlist::CodePointInversionListULE>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE<_, _>>::get_field::<_>
94
95
    /// Construct from a byte slice
96
    ///
97
    /// # Safety
98
    /// - byte slice must be a valid `VarZeroLengthlessSlice<[u8], Format>` with length `LEN`
99
    #[inline]
100
0
    pub unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
101
        // &Self is transparent over &VZS<..> with the right format
102
0
        let slice = VarZeroLengthlessSlice::<[u8], Format>::from_bytes_unchecked(bytes);
103
0
        &*(slice as *const VarZeroLengthlessSlice<[u8], Format>
104
0
            as *const MultiFieldsULE<LEN, Format>)
105
0
    }
106
107
    /// Get the bytes behind this value
108
0
    pub fn as_bytes(&self) -> &[u8] {
109
0
        self.0.as_bytes()
110
0
    }
111
}
112
113
impl<const LEN: usize, Format: VarZeroVecFormat> fmt::Debug for MultiFieldsULE<LEN, Format> {
114
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
115
0
        write!(f, "MultiFieldsULE<{LEN}>({:?})", self.0.as_bytes())
116
0
    }
117
}
118
/// This lets us conveniently use the `EncodeAsVarULE` functionality to create
119
/// `VarZeroVec<[u8]>`s that have the right amount of space for elements
120
/// without having to duplicate any unsafe code
121
#[repr(transparent)]
122
struct BlankSliceEncoder(usize);
123
124
unsafe impl EncodeAsVarULE<[u8]> for BlankSliceEncoder {
125
0
    fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R {
126
        // unnecessary if the other two are implemented
127
0
        unreachable!()
128
    }
129
130
    #[inline]
131
0
    fn encode_var_ule_len(&self) -> usize {
132
0
        self.0
133
0
    }
Unexecuted instantiation: <zerovec::ule::multi::BlankSliceEncoder as zerovec::ule::encode::EncodeAsVarULE<[u8]>>::encode_var_ule_len
Unexecuted instantiation: <zerovec::ule::multi::BlankSliceEncoder as zerovec::ule::encode::EncodeAsVarULE<[u8]>>::encode_var_ule_len
134
135
    #[inline]
136
0
    fn encode_var_ule_write(&self, _dst: &mut [u8]) {
137
        // do nothing
138
0
    }
Unexecuted instantiation: <zerovec::ule::multi::BlankSliceEncoder as zerovec::ule::encode::EncodeAsVarULE<[u8]>>::encode_var_ule_write
Unexecuted instantiation: <zerovec::ule::multi::BlankSliceEncoder as zerovec::ule::encode::EncodeAsVarULE<[u8]>>::encode_var_ule_write
139
}
140
141
// Safety (based on the safety checklist on the VarULE trait):
142
//  1. MultiFieldsULE does not include any uninitialized or padding bytes (achieved by being transparent over a VarULE type)
143
//  2. MultiFieldsULE is aligned to 1 byte (achieved by being transparent over a VarULE type)
144
//  3. The impl of `validate_bytes()` returns an error if any byte is not valid.
145
//  4. The impl of `validate_bytes()` returns an error if the slice cannot be used in its entirety
146
//  5. The impl of `from_bytes_unchecked()` returns a reference to the same data.
147
//  6. All other methods are defaulted
148
//  7. `MultiFieldsULE` byte equality is semantic equality (achieved by being transparent over a VarULE type)
149
unsafe impl<const LEN: usize, Format: VarZeroVecFormat> VarULE for MultiFieldsULE<LEN, Format> {
150
    /// Note: `MultiFieldsULE` is usually used in cases where one should be calling .`validate_field()` directly for
151
    /// each field, rather than using the regular `VarULE` impl.
152
    ///
153
    /// This impl exists so that `EncodeAsVarULE` can work.
154
    #[inline]
155
0
    fn validate_bytes(slice: &[u8]) -> Result<(), UleError> {
156
0
        VarZeroLengthlessSlice::<[u8], Format>::parse_bytes(LEN as u32, slice).map(|_| ())
157
0
    }
158
159
    #[inline]
160
0
    unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
161
        // &Self is transparent over &VZS<..>
162
0
        let slice = VarZeroLengthlessSlice::<[u8], Format>::from_bytes_unchecked(bytes);
163
0
        &*(slice as *const VarZeroLengthlessSlice<[u8], Format>
164
0
            as *const MultiFieldsULE<LEN, Format>)
165
0
    }
166
}