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