Coverage Report

Created: 2025-09-27 06:43

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