Skip to main content

zerovec/varzerovec/
lengthless.rs

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
5use super::components::VarZeroVecComponents;
6use super::*;
7use crate::ule::*;
8use core::marker::PhantomData;
9
10/// A slice representing the index and data tables of a [`VarZeroVec`],
11/// *without* any length fields. The length field is expected to be stored elsewhere.
12///
13/// Without knowing the length this is of course unsafe to use directly.
14#[repr(transparent)]
15#[derive(#[automatically_derived]
impl<T: ::core::cmp::PartialEq + ?Sized, F: ::core::cmp::PartialEq>
    ::core::cmp::PartialEq for VarZeroLengthlessSlice<T, F> {
    #[inline]
    fn eq(&self, other: &VarZeroLengthlessSlice<T, F>) -> bool {
        self.marker == other.marker && self.entire_slice == other.entire_slice
    }
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq + ?Sized, F: ::core::cmp::Eq> ::core::cmp::Eq for
    VarZeroLengthlessSlice<T, F> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<PhantomData<(F, T)>>;
        let _: ::core::cmp::AssertParamIsEq<[u8]>;
    }
}Eq)]
16pub(crate) struct VarZeroLengthlessSlice<T: ?Sized, F> {
17    marker: PhantomData<(F, T)>,
18    /// The original slice this was constructed from
19    // Safety invariant: This field must have successfully passed through
20    // VarZeroVecComponents::parse_bytes_with_length() with the length
21    // associated with this value.
22    entire_slice: [u8],
23}
24
25impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroLengthlessSlice<T, F> {
26    /// Obtain a [`VarZeroVecComponents`] borrowing from the internal buffer
27    ///
28    /// Safety: `len` must be the length associated with this value
29    #[inline]
30    pub(crate) unsafe fn as_components<'a>(&'a self, len: u32) -> VarZeroVecComponents<'a, T, F> {
31        unsafe {
32            // safety: VarZeroSlice is guaranteed to parse here
33            VarZeroVecComponents::from_bytes_unchecked_with_length(len, &self.entire_slice)
34        }
35    }
36
37    /// Parse a [`VarZeroLengthlessSlice`] from a slice of the appropriate format
38    ///
39    /// Slices of the right format can be obtained via [`VarZeroSlice::as_bytes()`]
40    pub fn parse_bytes<'a>(len: u32, slice: &'a [u8]) -> Result<&'a Self, UleError> {
41        let _ = VarZeroVecComponents::<T, F>::parse_bytes_with_length(len, slice)
42            .map_err(|_| UleError::parse::<Self>())?;
43        unsafe {
44            // Safety: We just verified that it is of the correct format.
45            Ok(Self::from_bytes_unchecked(slice))
46        }
47    }
48
49    /// Uses a `&[u8]` buffer as a `VarZeroLengthlessSlice<T>` without any verification.
50    ///
51    /// # Safety
52    ///
53    /// `bytes` need to be an output from [`VarZeroLengthlessSlice::as_bytes()`], or alternatively
54    /// successfully pass through `parse_bytes` (with `len`)
55    ///
56    /// The length associated with this value will be the length associated with the original slice.
57    pub(crate) const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
58        // self is really just a wrapper around a byte slice
59        &*(bytes as *const [u8] as *const Self)
60    }
61
62    /// Uses a `&mut [u8]` buffer as a `VarZeroLengthlessSlice<T>` without any verification.
63    ///
64    /// # Safety
65    ///
66    /// `bytes` need to be an output from [`VarZeroLengthlessSlice::as_bytes()`], or alternatively
67    /// be valid to be passed to `from_bytes_unchecked_with_length`
68    ///
69    /// The length associated with this value will be the length associated with the original slice.
70    pub(crate) unsafe fn from_bytes_unchecked_mut(bytes: &mut [u8]) -> &mut Self {
71        // self is really just a wrapper around a byte slice
72        &mut *(bytes as *mut [u8] as *mut VarZeroLengthlessSlice<T, F>)
73    }
74
75    /// Get one of this slice's elements
76    ///
77    /// # Safety
78    ///
79    /// `index` must be in range, and `len` must be the length associated with this
80    /// instance of [`VarZeroLengthlessSlice`].
81    pub(crate) unsafe fn get_unchecked(&self, len: u32, idx: usize) -> &T {
82        self.as_components(len).get_unchecked(idx)
83    }
84
85    /// Get a reference to the entire encoded backing buffer of this slice
86    ///
87    /// The bytes can be passed back to [`Self::parse_bytes()`].
88    ///
89    /// To take the bytes as a vector, see [`VarZeroVec::into_bytes()`].
90    #[inline]
91    pub(crate) const fn as_bytes(&self) -> &[u8] {
92        &self.entire_slice
93    }
94
95    /// Get the bytes behind this as a mutable slice
96    ///
97    /// # Safety
98    ///
99    ///  - `len` is the length associated with this [`VarZeroLengthlessSlice`]
100    ///  - The resultant slice is only mutated in a way such that it remains a valid `T`
101    ///
102    /// # Panics
103    ///
104    ///  Panics when idx is not in bounds for this slice
105    pub(crate) unsafe fn get_bytes_at_mut(&mut self, len: u32, idx: usize) -> &mut [u8] {
106        let components = self.as_components(len);
107        let range = components.get_things_range(idx);
108        let offset = components.get_indices_size();
109
110        // get_indices_size() returns the start of the things slice, and get_things_range()
111        // returns a range in-bounds of the things slice
112        #[expect(clippy::indexing_slicing)]
113        &mut self.entire_slice[offset..][range]
114    }
115}