• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> {
clone(&self) -> Self37     fn clone(&self) -> Self {
38         VarZeroVecOwned {
39             marker1: PhantomData,
40             marker2: PhantomData,
41             entire_slice: self.entire_slice.clone(),
42         }
43     }
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>;
deref(&self) -> &VarZeroSlice<T, F>56     fn deref(&self) -> &VarZeroSlice<T, F> {
57         self.as_slice()
58     }
59 }
60 
61 impl<T: VarULE + ?Sized, F> VarZeroVecOwned<T, F> {
62     /// Construct an empty VarZeroVecOwned
new() -> Self63     pub fn new() -> Self {
64         Self {
65             marker1: PhantomData,
66             marker2: PhantomData,
67             entire_slice: Vec::new(),
68         }
69     }
70 }
71 
72 impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroVecOwned<T, F> {
73     /// Construct a VarZeroVecOwned from a [`VarZeroSlice`] by cloning the internal data
from_slice(slice: &VarZeroSlice<T, F>) -> Self74     pub fn from_slice(slice: &VarZeroSlice<T, F>) -> Self {
75         Self {
76             marker1: PhantomData,
77             marker2: PhantomData,
78             entire_slice: slice.as_bytes().into(),
79         }
80     }
81 
82     /// Construct a VarZeroVecOwned from a list of elements
try_from_elements<A>(elements: &[A]) -> Result<Self, &'static str> where A: EncodeAsVarULE<T>,83     pub fn try_from_elements<A>(elements: &[A]) -> Result<Self, &'static str>
84     where
85         A: EncodeAsVarULE<T>,
86     {
87         Ok(if elements.is_empty() {
88             Self::from_slice(VarZeroSlice::new_empty())
89         } else {
90             Self {
91                 marker1: PhantomData,
92                 marker2: PhantomData,
93                 // TODO(#1410): Rethink length errors in VZV.
94                 entire_slice: components::get_serializable_bytes_non_empty::<T, A, F>(elements)
95                     .ok_or(F::Index::TOO_LARGE_ERROR)?,
96             }
97         })
98     }
99 
100     /// Obtain this `VarZeroVec` as a [`VarZeroSlice`]
as_slice(&self) -> &VarZeroSlice<T, F>101     pub fn as_slice(&self) -> &VarZeroSlice<T, F> {
102         let slice: &[u8] = &self.entire_slice;
103         unsafe {
104             // safety: the slice is known to come from a valid parsed VZV
105             VarZeroSlice::from_bytes_unchecked(slice)
106         }
107     }
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
with_capacity(capacity: usize) -> Self112     pub(crate) fn with_capacity(capacity: usize) -> Self {
113         Self {
114             marker1: PhantomData,
115             marker2: PhantomData,
116             entire_slice: Vec::with_capacity(capacity * (F::Index::SIZE + 4)),
117         }
118     }
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
reserve(&mut self, capacity: usize)123     pub(crate) fn reserve(&mut self, capacity: usize) {
124         self.entire_slice.reserve(capacity * (F::Index::SIZE + 4))
125     }
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.
element_position_unchecked(&self, idx: usize) -> usize133     unsafe fn element_position_unchecked(&self, idx: usize) -> usize {
134         let len = self.len();
135         let out = if idx == len {
136             self.entire_slice.len() - F::Len::SIZE - (F::Index::SIZE * (len - 1))
137         } else if let Some(idx) = self.index_data(idx) {
138             idx.iule_to_usize()
139         } else {
140             0
141         };
142         debug_assert!(out + F::Len::SIZE + (len - 1) * F::Index::SIZE <= self.entire_slice.len());
143         out
144     }
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.
element_range_unchecked(&self, idx: usize) -> core::ops::Range<usize>150     unsafe fn element_range_unchecked(&self, idx: usize) -> core::ops::Range<usize> {
151         let start = self.element_position_unchecked(idx);
152         let end = self.element_position_unchecked(idx + 1);
153         debug_assert!(start <= end, "{start} > {end}");
154         start..end
155     }
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.
set_len(&mut self, len: usize)161     unsafe fn set_len(&mut self, len: usize) {
162         assert!(len <= F::Len::MAX_VALUE as usize);
163         let len_bytes = len.to_le_bytes();
164         let len_ule = F::Len::iule_from_usize(len).expect(F::Len::TOO_LARGE_ERROR);
165         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         assert_eq!(len_bytes[F::Len::SIZE..].iter().sum::<u8>(), 0);
168     }
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.
index_range(index: usize) -> Option<Range<usize>>172     fn index_range(index: usize) -> Option<Range<usize>> {
173         let index_minus_one = index.checked_sub(1)?;
174         let pos = F::Len::SIZE + F::Index::SIZE * index_minus_one;
175         Some(pos..pos + F::Index::SIZE)
176     }
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
index_data(&self, index: usize) -> Option<&F::Index>182     unsafe fn index_data(&self, index: usize) -> Option<&F::Index> {
183         let index_range = Self::index_range(index)?;
184         Some(&F::Index::slice_from_bytes_unchecked(&self.entire_slice[index_range])[0])
185     }
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.
index_data_mut(&mut self, index: usize) -> Option<&mut F::Index>192     unsafe fn index_data_mut(&mut self, index: usize) -> Option<&mut F::Index> {
193         let ptr = self.entire_slice.as_mut_ptr();
194         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         let data = slice::from_raw_parts_mut(ptr.add(range.start), F::Index::SIZE);
200         Some(&mut F::Index::iule_from_bytes_unchecked_mut(data)[0])
201     }
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.
shift_indices(&mut self, starting_index: usize, amount: i32)211     unsafe fn shift_indices(&mut self, starting_index: usize, amount: i32) {
212         let normalized_idx = starting_index
213             .checked_sub(1)
214             .expect("shift_indices called with a 0 starting index");
215         let len = self.len();
216         let indices = F::Index::iule_from_bytes_unchecked_mut(
217             &mut self.entire_slice[F::Len::SIZE..F::Len::SIZE + F::Index::SIZE * (len - 1)],
218         );
219         for idx in &mut indices[normalized_idx..] {
220             let mut new_idx = idx.iule_to_usize();
221             if amount > 0 {
222                 new_idx = new_idx.checked_add(amount.try_into().unwrap()).unwrap();
223             } else {
224                 new_idx = new_idx.checked_sub((-amount).try_into().unwrap()).unwrap();
225             }
226             *idx = F::Index::iule_from_usize(new_idx).expect(F::Index::TOO_LARGE_ERROR);
227         }
228     }
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
as_varzerovec<'a>(&'a self) -> VarZeroVec<'a, T, F>234     pub fn as_varzerovec<'a>(&'a self) -> VarZeroVec<'a, T, F> {
235         self.as_slice().into()
236     }
237 
238     /// Empty the vector
clear(&mut self)239     pub fn clear(&mut self) {
240         self.entire_slice.clear()
241     }
242 
243     /// Consume this vector and return the backing buffer
244     #[inline]
into_bytes(self) -> Vec<u8>245     pub fn into_bytes(self) -> Vec<u8> {
246         self.entire_slice
247     }
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`.
shift(&mut self, index: usize, new_size: usize, shift_type: ShiftType) -> &mut [u8]259     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         let len = self.len();
269         let slice_len = self.entire_slice.len();
270 
271         let prev_element = match shift_type {
272             ShiftType::Insert => {
273                 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                 pos..pos
277             }
278             _ => self.element_range_unchecked(index),
279         };
280 
281         // How much shifting must be done in bytes due to removal/insertion of an index.
282         let index_shift: i64 = match shift_type {
283             ShiftType::Insert => F::Index::SIZE as i64,
284             ShiftType::Replace => 0,
285             ShiftType::Remove => -(F::Index::SIZE as i64),
286         };
287         // The total shift in byte size of the owned slice.
288         let shift: i64 =
289             new_size as i64 - (prev_element.end - prev_element.start) as i64 + index_shift;
290         let new_slice_len = slice_len.wrapping_add(shift as usize);
291         if shift > 0 {
292             if new_slice_len > F::Index::MAX_VALUE as usize {
293                 panic!(
294                     "Attempted to grow VarZeroVec to an encoded size that does not fit within the length size used by {}",
295                     any::type_name::<F>()
296                 );
297             }
298             self.entire_slice.resize(new_slice_len, 0);
299         }
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             let slice_range = self.entire_slice.as_mut_ptr_range();
306             // The start of the indices buffer
307             let indices_start = slice_range.start.add(F::Len::SIZE);
308             let old_slice_end = slice_range.start.add(slice_len);
309             let data_start = indices_start.add((len - 1) * F::Index::SIZE);
310             let prev_element_p =
311                 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             let index_range = if let Some(index_minus_one) = index.checked_sub(1) {
319                 let index_start = indices_start.add(F::Index::SIZE * index_minus_one);
320                 Some(index_start..index_start.add(F::Index::SIZE))
321             } else {
322                 None
323             };
324 
325             unsafe fn shift_bytes(block: Range<*const u8>, to: *mut u8) {
326                 debug_assert!(block.end >= block.start);
327                 ptr::copy(block.start, to, block.end.offset_from(block.start) as usize);
328             }
329 
330             if shift_type == ShiftType::Remove {
331                 if let Some(ref index_range) = index_range {
332                     shift_bytes(index_range.end..prev_element_p.start, index_range.start);
333                 } 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                     shift_bytes(
337                         indices_start.add(F::Index::SIZE)..prev_element_p.start,
338                         indices_start,
339                     )
340                 }
341             }
342 
343             // Shift data after the element to its new position.
344             shift_bytes(
345                 prev_element_p.end..old_slice_end,
346                 prev_element_p
347                     .start
348                     .offset((new_size as i64 + index_shift) as isize),
349             );
350 
351             let first_affected_index = match shift_type {
352                 ShiftType::Insert => {
353                     if let Some(index_range) = index_range {
354                         // Move data before the element forward by 4 to make space for a new index.
355                         shift_bytes(index_range.start..prev_element_p.start, index_range.end);
356                         let index_data = self
357                             .index_data_mut(index)
358                             .expect("If index_range is some, index is > 0 and should not panic in index_data_mut");
359                         *index_data = F::Index::iule_from_usize(prev_element.start)
360                             .expect(F::Index::TOO_LARGE_ERROR);
361                     } else {
362                         // We are adding a new index 0. There's nothing in the indices array for index 0, but the element
363                         // that is currently at index 0 will become index 1 and need a value
364                         // We first shift bytes to make space
365                         shift_bytes(
366                             indices_start..prev_element_p.start,
367                             indices_start.add(F::Index::SIZE),
368                         );
369                         // And then we write a temporary zero to the zeroeth index, which will get shifted later
370                         let index_data = self
371                             .index_data_mut(1)
372                             .expect("Should be able to write to index 1");
373                         *index_data = F::Index::iule_from_usize(0).expect("0 is always valid!");
374                     }
375 
376                     self.set_len(len + 1);
377                     index + 1
378                 }
379                 ShiftType::Remove => {
380                     self.set_len(len - 1);
381                     if index == 0 {
382                         // We don't need to shift index 0 since index 0 is not stored in the indices buffer
383                         index + 1
384                     } else {
385                         index
386                     }
387                 }
388                 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             self.entire_slice.set_len(new_slice_len);
394             // Shift the affected indices.
395             self.shift_indices(first_affected_index, (shift - index_shift) as i32);
396         };
397 
398         debug_assert!(self.verify_integrity());
399 
400         // Return a mut slice to the new element data.
401         let element_pos = F::Len::SIZE
402             + (self.len() - 1) * F::Index::SIZE
403             + self.element_position_unchecked(index);
404         &mut self.entire_slice[element_pos..element_pos + new_size]
405     }
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.
verify_integrity(&self) -> bool412     fn verify_integrity(&self) -> bool {
413         if self.is_empty() {
414             if self.entire_slice.is_empty() {
415                 return true;
416             } else {
417                 panic!(
418                     "VarZeroVecOwned integrity: Found empty VarZeroVecOwned with a nonempty slice"
419                 );
420             }
421         }
422         let len = unsafe {
423             <F::Len as ULE>::slice_from_bytes_unchecked(&self.entire_slice[..F::Len::SIZE])[0]
424                 .iule_to_usize()
425         };
426         if len == 0 {
427             // An empty vec must have an empty slice: there is only a single valid byte representation.
428             panic!("VarZeroVecOwned integrity: Found empty VarZeroVecOwned with a nonempty slice");
429         }
430         if self.entire_slice.len() < F::Len::SIZE + (len - 1) * F::Index::SIZE {
431             panic!("VarZeroVecOwned integrity: Not enough room for the indices");
432         }
433         let data_len = self.entire_slice.len() - F::Len::SIZE - (len - 1) * F::Index::SIZE;
434         if data_len > F::Index::MAX_VALUE as usize {
435             panic!("VarZeroVecOwned integrity: Data segment is too long");
436         }
437 
438         // Test index validity.
439         let indices = unsafe {
440             F::Index::slice_from_bytes_unchecked(
441                 &self.entire_slice[F::Len::SIZE..F::Len::SIZE + (len - 1) * F::Index::SIZE],
442             )
443         };
444         for idx in indices {
445             if idx.iule_to_usize() > data_len {
446                 panic!("VarZeroVecOwned integrity: Indices must not point past the data segment");
447             }
448         }
449         for window in indices.windows(2) {
450             if window[0].iule_to_usize() > window[1].iule_to_usize() {
451                 panic!("VarZeroVecOwned integrity: Indices must be in non-decreasing order");
452             }
453         }
454         true
455     }
456 
457     /// Insert an element at the end of this vector
push<A: EncodeAsVarULE<T> + ?Sized>(&mut self, element: &A)458     pub fn push<A: EncodeAsVarULE<T> + ?Sized>(&mut self, element: &A) {
459         self.insert(self.len(), element)
460     }
461 
462     /// Insert an element at index `idx`
insert<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A)463     pub fn insert<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) {
464         let len = self.len();
465         if index > len {
466             panic!("Called out-of-bounds insert() on VarZeroVec, index {index} len {len}");
467         }
468 
469         let value_len = element.encode_var_ule_len();
470 
471         if len == 0 {
472             let header_len = F::Len::SIZE; // Index array is size 0 for len = 1
473             let cap = header_len + value_len;
474             self.entire_slice.resize(cap, 0);
475             self.entire_slice[0] = 1; // set length
476             element.encode_var_ule_write(&mut self.entire_slice[header_len..]);
477             return;
478         }
479 
480         assert!(value_len < F::Index::MAX_VALUE as usize);
481         unsafe {
482             let place = self.shift(index, value_len, ShiftType::Insert);
483             element.encode_var_ule_write(place);
484         }
485     }
486 
487     /// Remove the element at index `idx`
remove(&mut self, index: usize)488     pub fn remove(&mut self, index: usize) {
489         let len = self.len();
490         if index >= len {
491             panic!("Called out-of-bounds remove() on VarZeroVec, index {index} len {len}");
492         }
493         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             self.entire_slice.clear();
496             return;
497         }
498         unsafe {
499             self.shift(index, 0, ShiftType::Remove);
500         }
501     }
502 
503     /// Replace the element at index `idx` with another
replace<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A)504     pub fn replace<A: EncodeAsVarULE<T> + ?Sized>(&mut self, index: usize, element: &A) {
505         let len = self.len();
506         if index >= len {
507             panic!("Called out-of-bounds replace() on VarZeroVec, index {index} len {len}");
508         }
509 
510         let value_len = element.encode_var_ule_len();
511 
512         assert!(value_len < F::Index::MAX_VALUE as usize);
513         unsafe {
514             let place = self.shift(index, value_len, ShiftType::Replace);
515             element.encode_var_ule_write(place);
516         }
517     }
518 }
519 
520 impl<T: VarULE + ?Sized, F: VarZeroVecFormat> fmt::Debug for VarZeroVecOwned<T, F>
521 where
522     T: fmt::Debug,
523 {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result524     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
525         VarZeroSlice::fmt(self, f)
526     }
527 }
528 
529 impl<T: VarULE + ?Sized, F> Default for VarZeroVecOwned<T, F> {
default() -> Self530     fn default() -> Self {
531         Self::new()
532     }
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]
eq(&self, other: &&[A]) -> bool543     fn eq(&self, other: &&[A]) -> bool {
544         self.iter().eq(other.iter().map(|t| t.as_ref()))
545     }
546 }
547 
548 impl<'a, T: ?Sized + VarULE, F: VarZeroVecFormat> From<&'a VarZeroSlice<T, F>>
549     for VarZeroVecOwned<T, F>
550 {
from(other: &'a VarZeroSlice<T, F>) -> Self551     fn from(other: &'a VarZeroSlice<T, F>) -> Self {
552         Self::from_slice(other)
553     }
554 }
555 
556 #[cfg(test)]
557 mod test {
558     use super::VarZeroVecOwned;
559     #[test]
test_insert_integrity()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
test_empty_inserts()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]
test_small_insert_integrity()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]
test_insert_past_end()630     fn test_insert_past_end() {
631         VarZeroVecOwned::<str>::new().insert(1, "");
632     }
633 
634     #[test]
test_remove_integrity()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]
test_removing_last_element_clears()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]
test_remove_past_end()656     fn test_remove_past_end() {
657         VarZeroVecOwned::<str>::new().remove(0);
658     }
659 
660     #[test]
test_replace_integrity()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]
test_replace_past_end()693     fn test_replace_past_end() {
694         VarZeroVecOwned::<str>::new().replace(0, "");
695     }
696 }
697