/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zerovec-0.11.4/src/varzerovec/owned.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  |  | // The mutation operations in this file should panic to prevent undefined behavior  | 
6  |  | #![allow(clippy::unwrap_used)]  | 
7  |  | #![allow(clippy::expect_used)]  | 
8  |  | #![allow(clippy::indexing_slicing)]  | 
9  |  | #![allow(clippy::panic)]  | 
10  |  |  | 
11  |  | use super::*;  | 
12  |  | use crate::ule::*;  | 
13  |  | use alloc::vec::Vec;  | 
14  |  | use core::any;  | 
15  |  | use core::convert::TryInto;  | 
16  |  | use core::marker::PhantomData;  | 
17  |  | use core::ops::Deref;  | 
18  |  | use core::ops::Range;  | 
19  |  | use core::{fmt, ptr, slice}; | 
20  |  |  | 
21  |  | use super::components::IntegerULE;  | 
22  |  |  | 
23  |  | /// A fully-owned [`VarZeroVec`]. This type has no lifetime but has the same  | 
24  |  | /// internal buffer representation of [`VarZeroVec`], making it cheaply convertible to  | 
25  |  | /// [`VarZeroVec`] and [`VarZeroSlice`].  | 
26  |  | ///  | 
27  |  | /// The `F` type parameter is a [`VarZeroVecFormat`] (see its docs for more details), which can be used to select the  | 
28  |  | /// precise format of the backing buffer with various size and performance tradeoffs. It defaults to [`Index16`].  | 
29  |  | pub struct VarZeroVecOwned<T: ?Sized, F = Index16> { | 
30  |  |     marker1: PhantomData<T>,  | 
31  |  |     marker2: PhantomData<F>,  | 
32  |  |     // safety invariant: must parse into a valid VarZeroVecComponents  | 
33  |  |     entire_slice: Vec<u8>,  | 
34  |  | }  | 
35  |  |  | 
36  |  | impl<T: ?Sized, F> Clone for VarZeroVecOwned<T, F> { | 
37  | 0  |     fn clone(&self) -> Self { | 
38  | 0  |         VarZeroVecOwned { | 
39  | 0  |             marker1: PhantomData,  | 
40  | 0  |             marker2: PhantomData,  | 
41  | 0  |             entire_slice: self.entire_slice.clone(),  | 
42  | 0  |         }  | 
43  | 0  |     }  | 
44  |  | }  | 
45  |  |  | 
46  |  | // The effect of a shift on the indices in the varzerovec.  | 
47  |  | #[derive(PartialEq)]  | 
48  |  | enum ShiftType { | 
49  |  |     Insert,  | 
50  |  |     Replace,  | 
51  |  |     Remove,  | 
52  |  | }  | 
53  |  |  | 
54  |  | impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Deref for VarZeroVecOwned<T, F> { | 
55  |  |     type Target = VarZeroSlice<T, F>;  | 
56  | 0  |     fn deref(&self) -> &VarZeroSlice<T, F> { | 
57  | 0  |         self.as_slice()  | 
58  | 0  |     } Unexecuted instantiation: <zerovec::varzerovec::owned::VarZeroVecOwned<zerovec::zerovec::slice::ZeroSlice<icu_properties::props::Script>> as core::ops::deref::Deref>::deref Unexecuted instantiation: <zerovec::varzerovec::owned::VarZeroVecOwned<str> as core::ops::deref::Deref>::deref Unexecuted instantiation: <zerovec::varzerovec::owned::VarZeroVecOwned<_, _> as core::ops::deref::Deref>::deref  | 
59  |  | }  | 
60  |  |  | 
61  |  | impl<T: VarULE + ?Sized, F> VarZeroVecOwned<T, F> { | 
62  |  |     /// Construct an empty VarZeroVecOwned  | 
63  | 0  |     pub fn new() -> Self { | 
64  | 0  |         Self { | 
65  | 0  |             marker1: PhantomData,  | 
66  | 0  |             marker2: PhantomData,  | 
67  | 0  |             entire_slice: Vec::new(),  | 
68  | 0  |         }  | 
69  | 0  |     }  | 
70  |  | }  | 
71  |  |  | 
72  |  | impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> { | 
73  |  |     /// Construct a VarZeroVecOwned from a [`VarZeroSlice`] by cloning the internal data  | 
74  | 0  |     pub fn from_slice(slice: &VarZeroSlice<T, F>) -> Self { | 
75  | 0  |         Self { | 
76  | 0  |             marker1: PhantomData,  | 
77  | 0  |             marker2: PhantomData,  | 
78  | 0  |             entire_slice: slice.as_bytes().into(),  | 
79  | 0  |         }  | 
80  | 0  |     }  | 
81  |  |  | 
82  |  |     /// Construct a VarZeroVecOwned from a list of elements  | 
83  | 0  |     pub fn try_from_elements<A>(elements: &[A]) -> Result<Self, &'static str>  | 
84  | 0  |     where  | 
85  | 0  |         A: EncodeAsVarULE<T>,  | 
86  |  |     { | 
87  | 0  |         Ok(if elements.is_empty() { | 
88  | 0  |             Self::from_slice(VarZeroSlice::new_empty())  | 
89  |  |         } else { | 
90  |  |             Self { | 
91  | 0  |                 marker1: PhantomData,  | 
92  | 0  |                 marker2: PhantomData,  | 
93  |  |                 // TODO(#1410): Rethink length errors in VZV.  | 
94  | 0  |                 entire_slice: components::get_serializable_bytes_non_empty::<T, A, F>(elements)  | 
95  | 0  |                     .ok_or(F::Index::TOO_LARGE_ERROR)?,  | 
96  |  |             }  | 
97  |  |         })  | 
98  | 0  |     }  | 
99  |  |  | 
100  |  |     /// Obtain this `VarZeroVec` as a [`VarZeroSlice`]  | 
101  | 0  |     pub fn as_slice(&self) -> &VarZeroSlice<T, F> { | 
102  | 0  |         let slice: &[u8] = &self.entire_slice;  | 
103  |  |         unsafe { | 
104  |  |             // safety: the slice is known to come from a valid parsed VZV  | 
105  | 0  |             VarZeroSlice::from_bytes_unchecked(slice)  | 
106  |  |         }  | 
107  | 0  |     } Unexecuted instantiation: <zerovec::varzerovec::owned::VarZeroVecOwned<zerovec::zerovec::slice::ZeroSlice<icu_properties::props::Script>>>::as_slice Unexecuted instantiation: <zerovec::varzerovec::owned::VarZeroVecOwned<str>>::as_slice Unexecuted instantiation: <zerovec::varzerovec::owned::VarZeroVecOwned<_, _>>::as_slice  | 
108  |  |  | 
109  |  |     /// Try to allocate a buffer with enough capacity for `capacity`  | 
110  |  |     /// elements. Since `T` can take up an arbitrary size this will  | 
111  |  |     /// just allocate enough space for 4-byte Ts  | 
112  | 0  |     pub(crate) fn with_capacity(capacity: usize) -> Self { | 
113  | 0  |         Self { | 
114  | 0  |             marker1: PhantomData,  | 
115  | 0  |             marker2: PhantomData,  | 
116  | 0  |             entire_slice: Vec::with_capacity(capacity * (F::Index::SIZE + 4)),  | 
117  | 0  |         }  | 
118  | 0  |     }  | 
119  |  |  | 
120  |  |     /// Try to reserve space for `capacity`  | 
121  |  |     /// elements. Since `T` can take up an arbitrary size this will  | 
122  |  |     /// just allocate enough space for 4-byte Ts  | 
123  | 0  |     pub(crate) fn reserve(&mut self, capacity: usize) { | 
124  | 0  |         self.entire_slice.reserve(capacity * (F::Index::SIZE + 4))  | 
125  | 0  |     }  | 
126  |  |  | 
127  |  |     /// Get the position of a specific element in the data segment.  | 
128  |  |     ///  | 
129  |  |     /// If `idx == self.len()`, it will return the size of the data segment (where a new element would go).  | 
130  |  |     ///  | 
131  |  |     /// ## Safety  | 
132  |  |     /// `idx <= self.len()` and `self.as_encoded_bytes()` is well-formed.  | 
133  | 0  |     unsafe fn element_position_unchecked(&self, idx: usize) -> usize { | 
134  | 0  |         let len = self.len();  | 
135  | 0  |         let out = if idx == len { | 
136  | 0  |             self.entire_slice.len() - F::Len::SIZE - (F::Index::SIZE * (len - 1))  | 
137  | 0  |         } else if let Some(idx) = self.index_data(idx) { | 
138  | 0  |             idx.iule_to_usize()  | 
139  |  |         } else { | 
140  | 0  |             0  | 
141  |  |         };  | 
142  | 0  |         debug_assert!(out + F::Len::SIZE + (len - 1) * F::Index::SIZE <= self.entire_slice.len());  | 
143  | 0  |         out  | 
144  | 0  |     }  | 
145  |  |  | 
146  |  |     /// Get the range of a specific element in the data segment.  | 
147  |  |     ///  | 
148  |  |     /// ## Safety  | 
149  |  |     /// `idx < self.len()` and `self.as_encoded_bytes()` is well-formed.  | 
150  | 0  |     unsafe fn element_range_unchecked(&self, idx: usize) -> core::ops::Range<usize> { | 
151  | 0  |         let start = self.element_position_unchecked(idx);  | 
152  | 0  |         let end = self.element_position_unchecked(idx + 1);  | 
153  | 0  |         debug_assert!(start <= end, "{start} > {end}"); | 
154  | 0  |         start..end  | 
155  | 0  |     }  | 
156  |  |  | 
157  |  |     /// Set the number of elements in the list without any checks.  | 
158  |  |     ///  | 
159  |  |     /// ## Safety  | 
160  |  |     /// No safe functions may be called until `self.as_encoded_bytes()` is well-formed.  | 
161  | 0  |     unsafe fn set_len(&mut self, len: usize) { | 
162  | 0  |         assert!(len <= F::Len::MAX_VALUE as usize);  | 
163  | 0  |         let len_bytes = len.to_le_bytes();  | 
164  | 0  |         let len_ule = F::Len::iule_from_usize(len).expect(F::Len::TOO_LARGE_ERROR);  | 
165  | 0  |         self.entire_slice[0..F::Len::SIZE].copy_from_slice(ULE::slice_as_bytes(&[len_ule]));  | 
166  |  |         // Double-check that the length fits in the length field  | 
167  | 0  |         assert_eq!(len_bytes[F::Len::SIZE..].iter().sum::<u8>(), 0);  | 
168  | 0  |     }  | 
169  |  |  | 
170  |  |     /// Get the range in the full data for a given index. Returns None for index 0  | 
171  |  |     /// since there is no stored index for it.  | 
172  | 0  |     fn index_range(index: usize) -> Option<Range<usize>> { | 
173  | 0  |         let index_minus_one = index.checked_sub(1)?;  | 
174  | 0  |         let pos = F::Len::SIZE + F::Index::SIZE * index_minus_one;  | 
175  | 0  |         Some(pos..pos + F::Index::SIZE)  | 
176  | 0  |     }  | 
177  |  |  | 
178  |  |     /// Return the raw bytes representing the given `index`. Returns None when given index 0  | 
179  |  |     ///  | 
180  |  |     /// ## Safety  | 
181  |  |     /// The index must be valid, and self.as_encoded_bytes() must be well-formed  | 
182  | 0  |     unsafe fn index_data(&self, index: usize) -> Option<&F::Index> { | 
183  | 0  |         let index_range = Self::index_range(index)?;  | 
184  | 0  |         Some(&F::Index::slice_from_bytes_unchecked(&self.entire_slice[index_range])[0])  | 
185  | 0  |     }  | 
186  |  |  | 
187  |  |     /// Return the mutable slice representing the given `index`. Returns None when given index 0  | 
188  |  |     ///  | 
189  |  |     /// ## Safety  | 
190  |  |     /// The index must be valid. self.as_encoded_bytes() must have allocated space  | 
191  |  |     /// for this index, but need not have its length appropriately set.  | 
192  | 0  |     unsafe fn index_data_mut(&mut self, index: usize) -> Option<&mut F::Index> { | 
193  | 0  |         let ptr = self.entire_slice.as_mut_ptr();  | 
194  | 0  |         let range = Self::index_range(index)?;  | 
195  |  |  | 
196  |  |         // Doing this instead of just `get_unchecked_mut()` because it's unclear  | 
197  |  |         // if `get_unchecked_mut()` can be called out of bounds on a slice even  | 
198  |  |         // if we know the buffer is larger.  | 
199  | 0  |         let data = slice::from_raw_parts_mut(ptr.add(range.start), F::Index::SIZE);  | 
200  | 0  |         Some(&mut F::Index::iule_from_bytes_unchecked_mut(data)[0])  | 
201  | 0  |     }  | 
202  |  |  | 
203  |  |     /// Shift the indices starting with and after `starting_index` by the provided `amount`.  | 
204  |  |     ///  | 
205  |  |     /// ## Panics  | 
206  |  |     /// Should never be called with a starting index of 0, since that index cannot be shifted.  | 
207  |  |     ///  | 
208  |  |     /// ## Safety  | 
209  |  |     /// Adding `amount` to each index after `starting_index` must not result in the slice from becoming malformed.  | 
210  |  |     /// The length of the slice must be correctly set.  | 
211  | 0  |     unsafe fn shift_indices(&mut self, starting_index: usize, amount: i32) { | 
212  | 0  |         let normalized_idx = starting_index  | 
213  | 0  |             .checked_sub(1)  | 
214  | 0  |             .expect("shift_indices called with a 0 starting index"); | 
215  | 0  |         let len = self.len();  | 
216  | 0  |         let indices = F::Index::iule_from_bytes_unchecked_mut(  | 
217  | 0  |             &mut self.entire_slice[F::Len::SIZE..F::Len::SIZE + F::Index::SIZE * (len - 1)],  | 
218  |  |         );  | 
219  | 0  |         for idx in &mut indices[normalized_idx..] { | 
220  | 0  |             let mut new_idx = idx.iule_to_usize();  | 
221  | 0  |             if amount > 0 { | 
222  | 0  |                 new_idx = new_idx.checked_add(amount.try_into().unwrap()).unwrap();  | 
223  | 0  |             } else { | 
224  | 0  |                 new_idx = new_idx.checked_sub((-amount).try_into().unwrap()).unwrap();  | 
225  | 0  |             }  | 
226  | 0  |             *idx = F::Index::iule_from_usize(new_idx).expect(F::Index::TOO_LARGE_ERROR);  | 
227  |  |         }  | 
228  | 0  |     }  | 
229  |  |  | 
230  |  |     /// Get this [`VarZeroVecOwned`] as a borrowed [`VarZeroVec`]  | 
231  |  |     ///  | 
232  |  |     /// If you wish to repeatedly call methods on this [`VarZeroVecOwned`],  | 
233  |  |     /// it is more efficient to perform this conversion first  | 
234  | 0  |     pub fn as_varzerovec<'a>(&'a self) -> VarZeroVec<'a, T, F> { | 
235  | 0  |         self.as_slice().into()  | 
236  | 0  |     }  | 
237  |  |  | 
238  |  |     /// Empty the vector  | 
239  | 0  |     pub fn clear(&mut self) { | 
240  | 0  |         self.entire_slice.clear()  | 
241  | 0  |     }  | 
242  |  |  | 
243  |  |     /// Consume this vector and return the backing buffer  | 
244  |  |     #[inline]  | 
245  | 0  |     pub fn into_bytes(self) -> Vec<u8> { | 
246  | 0  |         self.entire_slice  | 
247  | 0  |     }  | 
248  |  |  | 
249  |  |     /// Invalidate and resize the data at an index, optionally inserting or removing the index.  | 
250  |  |     /// Also updates affected indices and the length.  | 
251  |  |     ///  | 
252  |  |     /// `new_size` is the encoded byte size of the element that is going to be inserted  | 
253  |  |     ///  | 
254  |  |     /// Returns a slice to the new element data - it doesn't contain uninitialized data but its value is indeterminate.  | 
255  |  |     ///  | 
256  |  |     /// ## Safety  | 
257  |  |     /// - `index` must be a valid index, or, if `shift_type == ShiftType::Insert`, `index == self.len()` is allowed.  | 
258  |  |     /// - `new_size` musn't result in the data segment growing larger than `F::Index::MAX_VALUE`.  | 
259  | 0  |     unsafe fn shift(&mut self, index: usize, new_size: usize, shift_type: ShiftType) -> &mut [u8] { | 
260  |  |         // The format of the encoded data is:  | 
261  |  |         //  - four bytes of "len"  | 
262  |  |         //  - len*4 bytes for an array of indices  | 
263  |  |         //  - the actual data to which the indices point  | 
264  |  |         //  | 
265  |  |         // When inserting or removing an element, the size of the indices segment must be changed,  | 
266  |  |         // so the data before the target element must be shifted by 4 bytes in addition to the  | 
267  |  |         // shifting needed for the new element size.  | 
268  | 0  |         let len = self.len();  | 
269  | 0  |         let slice_len = self.entire_slice.len();  | 
270  |  |  | 
271  | 0  |         let prev_element = match shift_type { | 
272  |  |             ShiftType::Insert => { | 
273  | 0  |                 let pos = self.element_position_unchecked(index);  | 
274  |  |                 // In the case of an insert, there's no previous element,  | 
275  |  |                 // so it's an empty range at the new position.  | 
276  | 0  |                 pos..pos  | 
277  |  |             }  | 
278  | 0  |             _ => self.element_range_unchecked(index),  | 
279  |  |         };  | 
280  |  |  | 
281  |  |         // How much shifting must be done in bytes due to removal/insertion of an index.  | 
282  | 0  |         let index_shift: i64 = match shift_type { | 
283  | 0  |             ShiftType::Insert => F::Index::SIZE as i64,  | 
284  | 0  |             ShiftType::Replace => 0,  | 
285  | 0  |             ShiftType::Remove => -(F::Index::SIZE as i64),  | 
286  |  |         };  | 
287  |  |         // The total shift in byte size of the owned slice.  | 
288  | 0  |         let shift: i64 =  | 
289  | 0  |             new_size as i64 - (prev_element.end - prev_element.start) as i64 + index_shift;  | 
290  | 0  |         let new_slice_len = slice_len.wrapping_add(shift as usize);  | 
291  | 0  |         if shift > 0 { | 
292  | 0  |             if new_slice_len > F::Index::MAX_VALUE as usize { | 
293  | 0  |                 panic!(  | 
294  | 0  |                     "Attempted to grow VarZeroVec to an encoded size that does not fit within the length size used by {}", | 
295  | 0  |                     any::type_name::<F>()  | 
296  |  |                 );  | 
297  | 0  |             }  | 
298  | 0  |             self.entire_slice.resize(new_slice_len, 0);  | 
299  | 0  |         }  | 
300  |  |  | 
301  |  |         // Now that we've ensured there's enough space, we can shift the data around.  | 
302  |  |         { | 
303  |  |             // Note: There are no references introduced between pointer creation and pointer use, and all  | 
304  |  |             //       raw pointers are derived from a single &mut. This preserves pointer provenance.  | 
305  | 0  |             let slice_range = self.entire_slice.as_mut_ptr_range();  | 
306  |  |             // The start of the indices buffer  | 
307  | 0  |             let indices_start = slice_range.start.add(F::Len::SIZE);  | 
308  | 0  |             let old_slice_end = slice_range.start.add(slice_len);  | 
309  | 0  |             let data_start = indices_start.add((len - 1) * F::Index::SIZE);  | 
310  | 0  |             let prev_element_p =  | 
311  | 0  |                 data_start.add(prev_element.start)..data_start.add(prev_element.end);  | 
312  |  |  | 
313  |  |             // The memory range of the affected index.  | 
314  |  |             // When inserting: where the new index goes.  | 
315  |  |             // When removing:  where the index being removed is.  | 
316  |  |             // When replacing: unused.  | 
317  |  |             // Will be None when the affected index is index 0, which is special  | 
318  | 0  |             let index_range = if let Some(index_minus_one) = index.checked_sub(1) { | 
319  | 0  |                 let index_start = indices_start.add(F::Index::SIZE * index_minus_one);  | 
320  | 0  |                 Some(index_start..index_start.add(F::Index::SIZE))  | 
321  |  |             } else { | 
322  | 0  |                 None  | 
323  |  |             };  | 
324  |  |  | 
325  | 0  |             unsafe fn shift_bytes(block: Range<*const u8>, to: *mut u8) { | 
326  | 0  |                 debug_assert!(block.end >= block.start);  | 
327  | 0  |                 ptr::copy(block.start, to, block.end.offset_from(block.start) as usize);  | 
328  | 0  |             }  | 
329  |  |  | 
330  | 0  |             if shift_type == ShiftType::Remove { | 
331  | 0  |                 if let Some(ref index_range) = index_range { | 
332  | 0  |                     shift_bytes(index_range.end..prev_element_p.start, index_range.start);  | 
333  | 0  |                 } else { | 
334  |  |                     // We are removing the first index, so we skip the second index and copy it over. The second index  | 
335  |  |                     // is now zero and unnecessary.  | 
336  | 0  |                     shift_bytes(  | 
337  | 0  |                         indices_start.add(F::Index::SIZE)..prev_element_p.start,  | 
338  | 0  |                         indices_start,  | 
339  |  |                     )  | 
340  |  |                 }  | 
341  | 0  |             }  | 
342  |  |  | 
343  |  |             // Shift data after the element to its new position.  | 
344  | 0  |             shift_bytes(  | 
345  | 0  |                 prev_element_p.end..old_slice_end,  | 
346  | 0  |                 prev_element_p  | 
347  | 0  |                     .start  | 
348  | 0  |                     .offset((new_size as i64 + index_shift) as isize),  | 
349  |  |             );  | 
350  |  |  | 
351  | 0  |             let first_affected_index = match shift_type { | 
352  |  |                 ShiftType::Insert => { | 
353  | 0  |                     if let Some(index_range) = index_range { | 
354  | 0  |                         // Move data before the element forward by 4 to make space for a new index.  | 
355  | 0  |                         shift_bytes(index_range.start..prev_element_p.start, index_range.end);  | 
356  | 0  |                         let index_data = self  | 
357  | 0  |                             .index_data_mut(index)  | 
358  | 0  |                             .expect("If index_range is some, index is > 0 and should not panic in index_data_mut"); | 
359  | 0  |                         *index_data = F::Index::iule_from_usize(prev_element.start)  | 
360  | 0  |                             .expect(F::Index::TOO_LARGE_ERROR);  | 
361  | 0  |                     } else { | 
362  | 0  |                         // We are adding a new index 0. There's nothing in the indices array for index 0, but the element  | 
363  | 0  |                         // that is currently at index 0 will become index 1 and need a value  | 
364  | 0  |                         // We first shift bytes to make space  | 
365  | 0  |                         shift_bytes(  | 
366  | 0  |                             indices_start..prev_element_p.start,  | 
367  | 0  |                             indices_start.add(F::Index::SIZE),  | 
368  | 0  |                         );  | 
369  | 0  |                         // And then we write a temporary zero to the zeroeth index, which will get shifted later  | 
370  | 0  |                         let index_data = self  | 
371  | 0  |                             .index_data_mut(1)  | 
372  | 0  |                             .expect("Should be able to write to index 1"); | 
373  | 0  |                         *index_data = F::Index::iule_from_usize(0).expect("0 is always valid!"); | 
374  | 0  |                     }  | 
375  |  |  | 
376  | 0  |                     self.set_len(len + 1);  | 
377  | 0  |                     index + 1  | 
378  |  |                 }  | 
379  |  |                 ShiftType::Remove => { | 
380  | 0  |                     self.set_len(len - 1);  | 
381  | 0  |                     if index == 0 { | 
382  |  |                         // We don't need to shift index 0 since index 0 is not stored in the indices buffer  | 
383  | 0  |                         index + 1  | 
384  |  |                     } else { | 
385  | 0  |                         index  | 
386  |  |                     }  | 
387  |  |                 }  | 
388  | 0  |                 ShiftType::Replace => index + 1,  | 
389  |  |             };  | 
390  |  |             // No raw pointer use should occur after this point (because of self.index_data and self.set_len).  | 
391  |  |  | 
392  |  |             // Set the new slice length. This must be done after shifting data around to avoid uninitialized data.  | 
393  | 0  |             self.entire_slice.set_len(new_slice_len);  | 
394  |  |             // Shift the affected indices.  | 
395  | 0  |             self.shift_indices(first_affected_index, (shift - index_shift) as i32);  | 
396  |  |         };  | 
397  |  |  | 
398  | 0  |         debug_assert!(self.verify_integrity());  | 
399  |  |  | 
400  |  |         // Return a mut slice to the new element data.  | 
401  | 0  |         let element_pos = F::Len::SIZE  | 
402  | 0  |             + (self.len() - 1) * F::Index::SIZE  | 
403  | 0  |             + self.element_position_unchecked(index);  | 
404  | 0  |         &mut self.entire_slice[element_pos..element_pos + new_size]  | 
405  | 0  |     }  | 
406  |  |  | 
407  |  |     /// Checks the internal invariants of the vec to ensure safe code will not cause UB.  | 
408  |  |     /// Returns whether integrity was verified.  | 
409  |  |     ///  | 
410  |  |     /// Note: an index is valid if it doesn't point to data past the end of the slice and is  | 
411  |  |     /// less than or equal to all future indices. The length of the index segment is not part of each index.  | 
412  | 0  |     fn verify_integrity(&self) -> bool { | 
413  | 0  |         if self.is_empty() { | 
414  | 0  |             if self.entire_slice.is_empty() { | 
415  | 0  |                 return true;  | 
416  |  |             } else { | 
417  | 0  |                 panic!(  | 
418  | 0  |                     "VarZeroVecOwned integrity: Found empty VarZeroVecOwned with a nonempty slice"  | 
419  |  |                 );  | 
420  |  |             }  | 
421  | 0  |         }  | 
422  | 0  |         let len = unsafe { | 
423  | 0  |             <F::Len as ULE>::slice_from_bytes_unchecked(&self.entire_slice[..F::Len::SIZE])[0]  | 
424  | 0  |                 .iule_to_usize()  | 
425  |  |         };  | 
426  | 0  |         if len == 0 { | 
427  |  |             // An empty vec must have an empty slice: there is only a single valid byte representation.  | 
428  | 0  |             panic!("VarZeroVecOwned integrity: Found empty VarZeroVecOwned with a nonempty slice"); | 
429  | 0  |         }  | 
430  | 0  |         if self.entire_slice.len() < F::Len::SIZE + (len - 1) * F::Index::SIZE { | 
431  | 0  |             panic!("VarZeroVecOwned integrity: Not enough room for the indices"); | 
432  | 0  |         }  | 
433  | 0  |         let data_len = self.entire_slice.len() - F::Len::SIZE - (len - 1) * F::Index::SIZE;  | 
434  | 0  |         if data_len > F::Index::MAX_VALUE as usize { | 
435  | 0  |             panic!("VarZeroVecOwned integrity: Data segment is too long"); | 
436  | 0  |         }  | 
437  |  |  | 
438  |  |         // Test index validity.  | 
439  | 0  |         let indices = unsafe { | 
440  | 0  |             F::Index::slice_from_bytes_unchecked(  | 
441  | 0  |                 &self.entire_slice[F::Len::SIZE..F::Len::SIZE + (len - 1) * F::Index::SIZE],  | 
442  |  |             )  | 
443  |  |         };  | 
444  | 0  |         for idx in indices { | 
445  | 0  |             if idx.iule_to_usize() > data_len { | 
446  | 0  |                 panic!("VarZeroVecOwned integrity: Indices must not point past the data segment"); | 
447  | 0  |             }  | 
448  |  |         }  | 
449  | 0  |         for window in indices.windows(2) { | 
450  | 0  |             if window[0].iule_to_usize() > window[1].iule_to_usize() { | 
451  | 0  |                 panic!("VarZeroVecOwned integrity: Indices must be in non-decreasing order"); | 
452  | 0  |             }  | 
453  |  |         }  | 
454  | 0  |         true  | 
455  | 0  |     }  | 
456  |  |  | 
457  |  |     /// Insert an element at the end of this vector  | 
458  | 0  |     pub fn push<A: EncodeAsVarULE<T> + ?Sized>(&mut self, element: &A) { | 
459  | 0  |         self.insert(self.len(), element)  | 
460  | 0  |     }  | 
461  |  |  | 
462  |  |     /// Insert an element at index `idx`  | 
463  | 0  |     pub fn insert<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) { | 
464  | 0  |         let len = self.len();  | 
465  | 0  |         if index > len { | 
466  | 0  |             panic!("Called out-of-bounds insert() on VarZeroVec, index {index} len {len}"); | 
467  | 0  |         }  | 
468  |  |  | 
469  | 0  |         let value_len = element.encode_var_ule_len();  | 
470  |  |  | 
471  | 0  |         if len == 0 { | 
472  | 0  |             let header_len = F::Len::SIZE; // Index array is size 0 for len = 1  | 
473  | 0  |             let cap = header_len + value_len;  | 
474  | 0  |             self.entire_slice.resize(cap, 0);  | 
475  | 0  |             self.entire_slice[0] = 1; // set length  | 
476  | 0  |             element.encode_var_ule_write(&mut self.entire_slice[header_len..]);  | 
477  | 0  |             return;  | 
478  | 0  |         }  | 
479  |  |  | 
480  | 0  |         assert!(value_len < F::Index::MAX_VALUE as usize);  | 
481  | 0  |         unsafe { | 
482  | 0  |             let place = self.shift(index, value_len, ShiftType::Insert);  | 
483  | 0  |             element.encode_var_ule_write(place);  | 
484  | 0  |         }  | 
485  | 0  |     }  | 
486  |  |  | 
487  |  |     /// Remove the element at index `idx`  | 
488  | 0  |     pub fn remove(&mut self, index: usize) { | 
489  | 0  |         let len = self.len();  | 
490  | 0  |         if index >= len { | 
491  | 0  |             panic!("Called out-of-bounds remove() on VarZeroVec, index {index} len {len}"); | 
492  | 0  |         }  | 
493  | 0  |         if len == 1 { | 
494  |  |             // This is removing the last element. Set the slice to empty to ensure all empty vecs have empty data slices.  | 
495  | 0  |             self.entire_slice.clear();  | 
496  | 0  |             return;  | 
497  | 0  |         }  | 
498  | 0  |         unsafe { | 
499  | 0  |             self.shift(index, 0, ShiftType::Remove);  | 
500  | 0  |         }  | 
501  | 0  |     }  | 
502  |  |  | 
503  |  |     /// Replace the element at index `idx` with another  | 
504  | 0  |     pub fn replace<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) { | 
505  | 0  |         let len = self.len();  | 
506  | 0  |         if index >= len { | 
507  | 0  |             panic!("Called out-of-bounds replace() on VarZeroVec, index {index} len {len}"); | 
508  | 0  |         }  | 
509  |  |  | 
510  | 0  |         let value_len = element.encode_var_ule_len();  | 
511  |  |  | 
512  | 0  |         assert!(value_len < F::Index::MAX_VALUE as usize);  | 
513  | 0  |         unsafe { | 
514  | 0  |             let place = self.shift(index, value_len, ShiftType::Replace);  | 
515  | 0  |             element.encode_var_ule_write(place);  | 
516  | 0  |         }  | 
517  | 0  |     }  | 
518  |  | }  | 
519  |  |  | 
520  |  | impl<T: VarULE + ?Sized, F: VarZeroVecFormat> fmt::Debug for VarZeroVecOwned<T, F>  | 
521  |  | where  | 
522  |  |     T: fmt::Debug,  | 
523  |  | { | 
524  | 0  |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | 
525  | 0  |         VarZeroSlice::fmt(self, f)  | 
526  | 0  |     }  | 
527  |  | }  | 
528  |  |  | 
529  |  | impl<T: VarULE + ?Sized, F> Default for VarZeroVecOwned<T, F> { | 
530  | 0  |     fn default() -> Self { | 
531  | 0  |         Self::new()  | 
532  | 0  |     }  | 
533  |  | }  | 
534  |  |  | 
535  |  | impl<T, A, F> PartialEq<&'_ [A]> for VarZeroVecOwned<T, F>  | 
536  |  | where  | 
537  |  |     T: VarULE + ?Sized,  | 
538  |  |     T: PartialEq,  | 
539  |  |     A: AsRef<T>,  | 
540  |  |     F: VarZeroVecFormat,  | 
541  |  | { | 
542  |  |     #[inline]  | 
543  | 0  |     fn eq(&self, other: &&[A]) -> bool { | 
544  | 0  |         self.iter().eq(other.iter().map(|t| t.as_ref()))  | 
545  | 0  |     }  | 
546  |  | }  | 
547  |  |  | 
548  |  | impl<'a, T: ?Sized + VarULE, F: VarZeroVecFormat> From<&'a VarZeroSlice<T, F>>  | 
549  |  |     for VarZeroVecOwned<T, F>  | 
550  |  | { | 
551  | 0  |     fn from(other: &'a VarZeroSlice<T, F>) -> Self { | 
552  | 0  |         Self::from_slice(other)  | 
553  | 0  |     }  | 
554  |  | }  | 
555  |  |  | 
556  |  | #[cfg(test)]  | 
557  |  | mod test { | 
558  |  |     use super::VarZeroVecOwned;  | 
559  |  |     #[test]  | 
560  |  |     fn test_insert_integrity() { | 
561  |  |         let mut items: Vec<String> = Vec::new();  | 
562  |  |         let mut zerovec = VarZeroVecOwned::<str>::new();  | 
563  |  |  | 
564  |  |         // Insert into an empty vec.  | 
565  |  |         items.insert(0, "1234567890".into());  | 
566  |  |         zerovec.insert(0, "1234567890");  | 
567  |  |         assert_eq!(zerovec, &*items);  | 
568  |  |  | 
569  |  |         zerovec.insert(1, "foo3");  | 
570  |  |         items.insert(1, "foo3".into());  | 
571  |  |         assert_eq!(zerovec, &*items);  | 
572  |  |  | 
573  |  |         // Insert at the end.  | 
574  |  |         items.insert(items.len(), "qwertyuiop".into());  | 
575  |  |         zerovec.insert(zerovec.len(), "qwertyuiop");  | 
576  |  |         assert_eq!(zerovec, &*items);  | 
577  |  |  | 
578  |  |         items.insert(0, "asdfghjkl;".into());  | 
579  |  |         zerovec.insert(0, "asdfghjkl;");  | 
580  |  |         assert_eq!(zerovec, &*items);  | 
581  |  |  | 
582  |  |         items.insert(2, "".into());  | 
583  |  |         zerovec.insert(2, "");  | 
584  |  |         assert_eq!(zerovec, &*items);  | 
585  |  |     }  | 
586  |  |  | 
587  |  |     #[test]  | 
588  |  |     // ensure that inserting empty items works  | 
589  |  |     fn test_empty_inserts() { | 
590  |  |         let mut items: Vec<String> = Vec::new();  | 
591  |  |         let mut zerovec = VarZeroVecOwned::<str>::new();  | 
592  |  |  | 
593  |  |         // Insert into an empty vec.  | 
594  |  |         items.insert(0, "".into());  | 
595  |  |         zerovec.insert(0, "");  | 
596  |  |         assert_eq!(zerovec, &*items);  | 
597  |  |  | 
598  |  |         items.insert(0, "".into());  | 
599  |  |         zerovec.insert(0, "");  | 
600  |  |         assert_eq!(zerovec, &*items);  | 
601  |  |  | 
602  |  |         items.insert(0, "1234567890".into());  | 
603  |  |         zerovec.insert(0, "1234567890");  | 
604  |  |         assert_eq!(zerovec, &*items);  | 
605  |  |  | 
606  |  |         items.insert(0, "".into());  | 
607  |  |         zerovec.insert(0, "");  | 
608  |  |         assert_eq!(zerovec, &*items);  | 
609  |  |     }  | 
610  |  |  | 
611  |  |     #[test]  | 
612  |  |     fn test_small_insert_integrity() { | 
613  |  |         // Tests that insert() works even when there  | 
614  |  |         // is not enough space for the new index in entire_slice.len()  | 
615  |  |         let mut items: Vec<String> = Vec::new();  | 
616  |  |         let mut zerovec = VarZeroVecOwned::<str>::new();  | 
617  |  |  | 
618  |  |         // Insert into an empty vec.  | 
619  |  |         items.insert(0, "abc".into());  | 
620  |  |         zerovec.insert(0, "abc");  | 
621  |  |         assert_eq!(zerovec, &*items);  | 
622  |  |  | 
623  |  |         zerovec.insert(1, "def");  | 
624  |  |         items.insert(1, "def".into());  | 
625  |  |         assert_eq!(zerovec, &*items);  | 
626  |  |     }  | 
627  |  |  | 
628  |  |     #[test]  | 
629  |  |     #[should_panic]  | 
630  |  |     fn test_insert_past_end() { | 
631  |  |         VarZeroVecOwned::<str>::new().insert(1, "");  | 
632  |  |     }  | 
633  |  |  | 
634  |  |     #[test]  | 
635  |  |     fn test_remove_integrity() { | 
636  |  |         let mut items: Vec<&str> = vec!["apples", "bananas", "eeples", "", "baneenees", "five", ""];  | 
637  |  |         let mut zerovec = VarZeroVecOwned::<str>::try_from_elements(&items).unwrap();  | 
638  |  |  | 
639  |  |         for index in [0, 2, 4, 0, 1, 1, 0] { | 
640  |  |             items.remove(index);  | 
641  |  |             zerovec.remove(index);  | 
642  |  |             assert_eq!(zerovec, &*items, "index {}, len {}", index, items.len()); | 
643  |  |         }  | 
644  |  |     }  | 
645  |  |  | 
646  |  |     #[test]  | 
647  |  |     fn test_removing_last_element_clears() { | 
648  |  |         let mut zerovec = VarZeroVecOwned::<str>::try_from_elements(&["buy some apples"]).unwrap();  | 
649  |  |         assert!(!zerovec.as_bytes().is_empty());  | 
650  |  |         zerovec.remove(0);  | 
651  |  |         assert!(zerovec.as_bytes().is_empty());  | 
652  |  |     }  | 
653  |  |  | 
654  |  |     #[test]  | 
655  |  |     #[should_panic]  | 
656  |  |     fn test_remove_past_end() { | 
657  |  |         VarZeroVecOwned::<str>::new().remove(0);  | 
658  |  |     }  | 
659  |  |  | 
660  |  |     #[test]  | 
661  |  |     fn test_replace_integrity() { | 
662  |  |         let mut items: Vec<&str> = vec!["apples", "bananas", "eeples", "", "baneenees", "five", ""];  | 
663  |  |         let mut zerovec = VarZeroVecOwned::<str>::try_from_elements(&items).unwrap();  | 
664  |  |  | 
665  |  |         // Replace with an element of the same size (and the first element)  | 
666  |  |         items[0] = "blablah";  | 
667  |  |         zerovec.replace(0, "blablah");  | 
668  |  |         assert_eq!(zerovec, &*items);  | 
669  |  |  | 
670  |  |         // Replace with a smaller element  | 
671  |  |         items[1] = "twily";  | 
672  |  |         zerovec.replace(1, "twily");  | 
673  |  |         assert_eq!(zerovec, &*items);  | 
674  |  |  | 
675  |  |         // Replace an empty element  | 
676  |  |         items[3] = "aoeuidhtns";  | 
677  |  |         zerovec.replace(3, "aoeuidhtns");  | 
678  |  |         assert_eq!(zerovec, &*items);  | 
679  |  |  | 
680  |  |         // Replace the last element  | 
681  |  |         items[6] = "0123456789";  | 
682  |  |         zerovec.replace(6, "0123456789");  | 
683  |  |         assert_eq!(zerovec, &*items);  | 
684  |  |  | 
685  |  |         // Replace with an empty element  | 
686  |  |         items[2] = "";  | 
687  |  |         zerovec.replace(2, "");  | 
688  |  |         assert_eq!(zerovec, &*items);  | 
689  |  |     }  | 
690  |  |  | 
691  |  |     #[test]  | 
692  |  |     #[should_panic]  | 
693  |  |     fn test_replace_past_end() { | 
694  |  |         VarZeroVecOwned::<str>::new().replace(0, "");  | 
695  |  |     }  | 
696  |  | }  |