Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/zerovec-0.10.4/src/ule/multi.rs
Line
Count
Source (jump to first uncovered line)
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::Index32;
7
use crate::VarZeroSlice;
8
use core::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.
13
///
14
/// Logically, consider it to be `(V1, V2, V3, ..)`
15
/// where `V1` etc are potentially different [`VarULE`] types.
16
///
17
/// Internally, it is represented by a VarZeroSlice.
18
#[derive(PartialEq, Eq, Debug)]
19
#[repr(transparent)]
20
pub struct MultiFieldsULE(VarZeroSlice<[u8], Index32>);
21
22
impl MultiFieldsULE {
23
    /// Compute the amount of bytes needed to support elements with lengths `lengths`
24
    #[inline]
25
0
    pub fn compute_encoded_len_for(lengths: &[usize]) -> usize {
26
0
        #[allow(clippy::expect_used)] // See #1410
27
0
        unsafe {
28
0
            // safe since BlankSliceEncoder is transparent over usize
29
0
            let lengths = &*(lengths as *const [usize] as *const [BlankSliceEncoder]);
30
0
            crate::varzerovec::components::compute_serializable_len::<_, _, Index32>(lengths)
31
0
                .expect("Too many bytes to encode") as usize
32
0
        }
33
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::compute_encoded_len_for
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::compute_encoded_len_for
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::compute_encoded_len_for
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::compute_encoded_len_for
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::compute_encoded_len_for
34
35
    /// Construct a partially initialized MultiFieldsULE backed by a mutable byte buffer
36
0
    pub fn new_from_lengths_partially_initialized<'a>(
37
0
        lengths: &[usize],
38
0
        output: &'a mut [u8],
39
0
    ) -> &'a mut Self {
40
0
        unsafe {
41
0
            // safe since BlankSliceEncoder is transparent over usize
42
0
            let lengths = &*(lengths as *const [usize] as *const [BlankSliceEncoder]);
43
0
            crate::varzerovec::components::write_serializable_bytes::<_, _, Index32>(
44
0
                lengths, output,
45
0
            );
46
0
            debug_assert!(
47
0
                <VarZeroSlice<[u8], Index32>>::validate_byte_slice(output).is_ok(),
48
0
                "Encoded slice must be valid VarZeroSlice"
49
            );
50
            // Safe since write_serializable_bytes produces a valid VarZeroSlice buffer
51
0
            let slice = <VarZeroSlice<[u8], Index32>>::from_byte_slice_unchecked_mut(output);
52
0
            // safe since `Self` is transparent over VarZeroSlice
53
0
            mem::transmute::<&mut VarZeroSlice<_, Index32>, &mut Self>(slice)
54
0
        }
55
0
    }
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(idx))
69
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<str, str>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<zerovec::varzerovec::slice::VarZeroSlice<str>, zerovec::varzerovec::slice::VarZeroSlice<str>>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<icu_collections::codepointinvlist::cpinvlist::CodePointInversionListULE, icu_collections::codepointinvlist::cpinvlist::CodePointInversionList>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<_, _>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<str, str>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<zerovec::varzerovec::slice::VarZeroSlice<str>, zerovec::varzerovec::slice::VarZeroSlice<str>>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::set_field_at::<icu_collections::codepointinvlist::cpinvlist::CodePointInversionListULE, icu_collections::codepointinvlist::cpinvlist::CodePointInversionList>
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>(
78
0
        &self,
79
0
        index: usize,
80
0
    ) -> Result<(), ZeroVecError> {
81
0
        T::validate_byte_slice(self.0.get_unchecked(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_byte_slice_unchecked(self.0.get_unchecked(index))
93
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<str>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<zerovec::varzerovec::slice::VarZeroSlice<str>>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<icu_collections::codepointinvlist::cpinvlist::CodePointInversionListULE>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<_>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<str>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<zerovec::varzerovec::slice::VarZeroSlice<str>>
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE>::get_field::<icu_collections::codepointinvlist::cpinvlist::CodePointInversionListULE>
94
95
    /// Construct from a byte slice
96
    ///
97
    /// # Safety
98
    /// - byte slice must be a valid VarZeroSlice<[u8]>
99
    #[inline]
100
0
    pub unsafe fn from_byte_slice_unchecked(bytes: &[u8]) -> &Self {
101
0
        // &Self is transparent over &VZS<..>
102
0
        mem::transmute(<VarZeroSlice<[u8]>>::from_byte_slice_unchecked(bytes))
103
0
    }
104
}
105
106
/// This lets us conveniently use the EncodeAsVarULE functionality to create
107
/// `VarZeroVec<[u8]>`s that have the right amount of space for elements
108
/// without having to duplicate any unsafe code
109
#[repr(transparent)]
110
struct BlankSliceEncoder(usize);
111
112
unsafe impl EncodeAsVarULE<[u8]> for BlankSliceEncoder {
113
0
    fn encode_var_ule_as_slices<R>(&self, _: impl FnOnce(&[&[u8]]) -> R) -> R {
114
0
        // unnecessary if the other two are implemented
115
0
        unreachable!()
116
    }
117
118
    #[inline]
119
0
    fn encode_var_ule_len(&self) -> usize {
120
0
        self.0
121
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
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
Unexecuted instantiation: <zerovec::ule::multi::BlankSliceEncoder as zerovec::ule::encode::EncodeAsVarULE<[u8]>>::encode_var_ule_len
122
123
    #[inline]
124
0
    fn encode_var_ule_write(&self, _dst: &mut [u8]) {
125
0
        // do nothing
126
0
    }
127
}
128
129
// Safety (based on the safety checklist on the VarULE trait):
130
//  1. MultiFieldsULE does not include any uninitialized or padding bytes (achieved by being transparent over a VarULE type)
131
//  2. MultiFieldsULE is aligned to 1 byte (achieved by being transparent over a VarULE type)
132
//  3. The impl of `validate_byte_slice()` returns an error if any byte is not valid.
133
//  4. The impl of `validate_byte_slice()` returns an error if the slice cannot be used in its entirety
134
//  5. The impl of `from_byte_slice_unchecked()` returns a reference to the same data.
135
//  6. All other methods are defaulted
136
//  7. `MultiFieldsULE` byte equality is semantic equality (achieved by being transparent over a VarULE type)
137
unsafe impl VarULE for MultiFieldsULE {
138
    /// Note: MultiFieldsULE is usually used in cases where one should be calling .validate_field() directly for
139
    /// each field, rather than using the regular VarULE impl.
140
    ///
141
    /// This impl exists so that EncodeAsVarULE can work.
142
    #[inline]
143
0
    fn validate_byte_slice(slice: &[u8]) -> Result<(), ZeroVecError> {
144
0
        <VarZeroSlice<[u8], Index32>>::validate_byte_slice(slice)
145
0
    }
146
147
    #[inline]
148
0
    unsafe fn from_byte_slice_unchecked(bytes: &[u8]) -> &Self {
149
0
        // &Self is transparent over &VZS<..>
150
0
        mem::transmute(<VarZeroSlice<[u8], Index32>>::from_byte_slice_unchecked(
151
0
            bytes,
152
0
        ))
153
0
    }
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE as zerovec::ule::VarULE>::from_byte_slice_unchecked
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE as zerovec::ule::VarULE>::from_byte_slice_unchecked
Unexecuted instantiation: <zerovec::ule::multi::MultiFieldsULE as zerovec::ule::VarULE>::from_byte_slice_unchecked
154
}