ixa/data_structures/
value_vec.rs

1/*!
2`ValueVec<T>`: a by-value, ref-less vector with interior mutability.
3
4You can convert to and from a `Vec<T>` at zero cost.
5
6Key properties:
7- All mutating operations use `&self` (immutable receiver).
8- No references to elements are ever given out.
9- Elements are inserted/removed/moved **by value**.
10- Getting a value returns a `Clone` (or `Copy`) of the stored element.
11- Many shared immutable references to a `ValueVec` can exist simultaneously safely.
12
13Trade-offs:
14- You can’t borrow into the backing memory; you pay cloning cost to read.
15- In return, the backing storage may reallocate at will without invalidating
16  any external references (because none are ever issued).
17
18Functionality:
19
20For any functionality of `Vec<T>` that `ValueVec<T>` doesn't provide,
21you can use `into_vec` to convert to a `Vec<T>` at zero cost.
22
23Soundness:
24
25We require `T` to be `Copy` to avoid subtle soundness issues. However, this requirement
26could be replaced with a requirement that prevents re-entrance into methods of
27`ValueVec<T>` (directly or indirectly) from the `Drop` or `Clone` implementations of `T`.
28
29*/
30
31use std::cell::UnsafeCell;
32use std::fmt::Debug;
33
34/**
35A by-value, `ref`-less vector with interior mutability. Values of type `V` can be moved into and out of the vector. We require `V` to be `Copy` to avoid subtle soundness issues.
36*/
37pub struct ValueVec<V: Copy> {
38    data: UnsafeCell<Vec<V>>,
39}
40
41impl<V: Copy> ValueVec<V> {
42    /// Creates an empty `ValueVec`.
43    pub fn new() -> Self {
44        Self {
45            data: UnsafeCell::new(Vec::new()),
46        }
47    }
48
49    /// Creates with capacity.
50    pub fn with_capacity(cap: usize) -> Self {
51        Self {
52            data: UnsafeCell::new(Vec::with_capacity(cap)),
53        }
54    }
55
56    /// Current number of elements.
57    #[inline]
58    pub fn len(&self) -> usize {
59        // Safety: This is already an immutable operation
60        unsafe { (&*self.data.get()).len() }
61    }
62
63    /// Current capacity of the backing Vec.
64    #[inline]
65    pub fn capacity(&self) -> usize {
66        // Safety: This is already an immutable operation
67        unsafe { (&*self.data.get()).capacity() }
68    }
69
70    /// Returns true if the vector has no elements.
71    #[inline]
72    pub fn is_empty(&self) -> bool {
73        self.len() == 0
74    }
75
76    /// Ensures capacity for at least `additional` more elements.
77    pub fn reserve(&self, additional: usize) {
78        self.with_vec(|v| v.reserve(additional));
79    }
80
81    /// Shrinks the capacity as much as possible.
82    pub fn shrink_to_fit(&self) {
83        self.with_vec(|v| v.shrink_to_fit());
84    }
85
86    /// Pushes a value (by move) onto the end.
87    pub fn push(&self, value: V) {
88        self.with_vec(|v| v.push(value));
89    }
90
91    /// Pops and **returns** the last element (by move), or `None` if empty.
92    pub fn pop(&self) -> Option<V> {
93        self.with_vec(|v| v.pop())
94    }
95
96    /// Returns the value of the element at `index`, if `index` is in range. Returns `None` if `index` is out of bounds.
97    /// This is a bounds-checked variant of [`ValueVec::at`].
98    pub fn get(&self, index: usize) -> Option<V> {
99        unsafe { (&*self.data.get()).get(index).copied() }
100    }
101
102    /// Returns the value at `index`. Panics if `index` is out of bounds.
103    ///
104    /// Use [`ValueVec::get`] for a bounds-checked version of this method.
105    pub fn at(&self, index: usize) -> V {
106        unsafe { (&*self.data.get())[index] }
107    }
108
109    /// Moves a value into the slot at `index`, returning the old value (via move). Panics if `index` is out of bounds.
110    pub fn replace(&self, index: usize, value: V) -> V {
111        self.with_vec(|v| core::mem::replace(&mut v[index], value))
112    }
113
114    /// Sets the value of the slot at `index` to `value`. Panics if `index` is out of bounds.
115    pub fn set(&self, index: usize, value: V) {
116        self.with_vec(|v| v[index] = value)
117    }
118
119    /// Swaps the value at `index` with the provided one in place. Panics if `index` is out of bounds.
120    ///
121    /// The existing value ends up in `*value`.
122    pub fn swap_value(&self, index: usize, value: &mut V) {
123        self.with_vec(|v| {
124            core::mem::swap(&mut v[index], value);
125        })
126    }
127
128    /// Inserts `value` at position `index`, shifting elements to the right. Panics if `index` is out of bounds.
129    pub fn insert(&self, index: usize, value: V) {
130        self.with_vec(|v| {
131            v.insert(index, value);
132        })
133    }
134
135    /// Removes and returns the element at `index`, shifting elements left. Panics if `index` is out of bounds.
136    pub fn remove(&self, index: usize) -> V {
137        self.with_vec(|v| v.remove(index))
138    }
139
140    /// Removes and returns the element at `index` by swapping in the last element.
141    ///
142    /// O(1) removal when order does not matter.
143    pub fn swap_remove(&self, index: usize) -> V {
144        self.with_vec(|v| v.swap_remove(index))
145    }
146
147    /// Returns `true` if the `ValueVec` contains an element with the given value.
148    pub fn contains(&self, value: &V) -> bool
149    where
150        V: PartialEq,
151    {
152        self.with_vec(|v| v.contains(value))
153    }
154
155    /// Clears all elements.
156    pub fn clear(&self) {
157        self.with_vec(|v| v.clear());
158    }
159
160    /// Extends the vector by moving in elements from an iterator.
161    pub fn extend<I>(&self, iter: I)
162    where
163        I: IntoIterator<Item = V>,
164    {
165        self.with_vec(|v| v.extend(iter));
166    }
167
168    pub fn resize(&self, new_len: usize, value: V) {
169        self.with_vec(|v| v.resize(new_len, value));
170    }
171
172    pub fn resize_with<F>(&self, new_len: usize, f: F)
173    where
174        F: FnMut() -> V,
175    {
176        self.with_vec(|v| v.resize_with(new_len, f));
177    }
178
179    /// Returns a **snapshot** `Vec<V>` by cloning all elements.
180    ///
181    /// Use `From<ValueVec<V>> for Vec<V>` for a zero-cost conversion if you don't want to clone.
182    pub fn to_vec(&self) -> Vec<V>
183    where
184        V: Clone,
185    {
186        unsafe { (&*self.data.get()).clone() }
187    }
188
189    /// Applies `f` with exclusive access to the inner Vec.
190    ///
191    /// **Safety:** `with_vec` temporarily obtains an exclusive `&mut Vec<V>`
192    /// from the internal `UnsafeCell` and passes it to the provided closure.
193    /// This is considered sound **only under controlled internal use**:
194    ///
195    /// - The mutable borrow does not escape the function.
196    /// - No references to elements are ever returned or stored; all access
197    ///   to elements occurs by value (move or clone).
198    /// - Only one mutable borrow of the internal `Vec` exists at a time,
199    ///   and it ends before the method returns.
200    ///
201    /// The one additional requirement for soundness is that the closure
202    /// passed to `with_vec` must not re-enter any other `ValueVec` method
203    /// (directly or indirectly) while it holds the mutable borrow. Such
204    /// re-entrancy could occur, for example, from a user-defined `Drop` or
205    /// `Clone` implementation of `V` that calls back into the same instance,
206    /// and would cause overlapping borrows of the internal `Vec`, leading to
207    /// undefined behavior.
208    ///
209    /// This function remains private to ensure that every closure passed to
210    /// it is under our control and has been manually verified to uphold the
211    /// no-reentrancy invariant. Its soundness depends on that internal
212    /// discipline.
213    #[inline]
214    fn with_vec<R>(&self, f: impl FnOnce(&mut Vec<V>) -> R) -> R {
215        // SAFETY: `UnsafeCell` permits obtaining a unique mutable reference here.
216        // We never let any references escape, and we serialize access by construction
217        // (each method call performs one short-lived exclusive borrow of the Vec).
218        let vec: &mut Vec<V> = unsafe { &mut *self.data.get() };
219        f(vec)
220    }
221}
222
223impl<V: Copy> Default for ValueVec<V> {
224    fn default() -> Self {
225        Self::new()
226    }
227}
228
229impl<V: Copy + Debug> Debug for ValueVec<V> {
230    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
231        // SAFETY: We create a temporary shared reference to the inner Vec.
232        // No mutable borrows of the Vec exist concurrently by design.
233        let vec = unsafe { &*self.data.get() };
234        vec.fmt(f)
235    }
236}
237
238impl<V: Copy> From<Vec<V>> for ValueVec<V> {
239    /// Wraps an existing `Vec` without copying its elements.
240    fn from(src: Vec<V>) -> Self {
241        Self {
242            data: UnsafeCell::new(src),
243        }
244    }
245}
246
247impl<V: Copy> From<ValueVec<V>> for Vec<V> {
248    fn from(val: ValueVec<V>) -> Self {
249        val.data.into_inner()
250    }
251}
252
253impl<V: Copy> IntoIterator for ValueVec<V> {
254    type Item = V;
255    type IntoIter = std::vec::IntoIter<V>;
256
257    fn into_iter(self) -> Self::IntoIter {
258        // SAFETY: We are consuming `self`, so there can be no remaining references
259        // to the inner Vec. It is therefore safe to move it out of the UnsafeCell.
260        let vec = self.data.into_inner();
261        vec.into_iter()
262    }
263}
264
265impl<V: Copy> FromIterator<V> for ValueVec<V> {
266    fn from_iter<I: IntoIterator<Item = V>>(iter: I) -> Self {
267        Self::from(Vec::from_iter(iter))
268    }
269}
270
271#[cfg(test)]
272mod tests {
273    use super::ValueVec;
274
275    #[test]
276    fn push_pop() {
277        let v = ValueVec::new();
278        assert!(v.is_empty());
279        v.push(1);
280        v.push(2);
281        v.push(3);
282        assert_eq!(v.len(), 3);
283        assert_eq!(v.pop(), Some(3));
284        assert_eq!(v.pop(), Some(2));
285        assert_eq!(v.pop(), Some(1));
286        assert_eq!(v.pop(), None);
287    }
288
289    #[test]
290    fn get_cloned_and_replace() {
291        let v = ValueVec::new();
292        v.extend([10, 20, 30]);
293        assert_eq!(v.get(1), Some(20));
294        assert_eq!(v.replace(1, 99), 20);
295        assert_eq!(v.get(1), Some(99));
296    }
297
298    #[test]
299    fn insert_and_remove() {
300        let v = ValueVec::new();
301        v.extend([1, 2, 3]);
302        v.insert(1, 9); // [1, 9, 2, 3]
303        assert_eq!(v.len(), 4);
304        assert_eq!(v.remove(2), 2); // [1, 9, 3]
305        assert_eq!(v.get(0), Some(1));
306        assert_eq!(v.at(1), 9);
307        assert_eq!(v.at(2), 3);
308        assert_eq!(v.remove(1), 9);
309    }
310
311    #[test]
312    fn swap_remove_works() {
313        let v = ValueVec::new();
314        v.extend([10, 20, 30, 40]);
315        let got = v.swap_remove(1);
316        assert_eq!(got, 20);
317        // Order not guaranteed after swap_remove, but len decreased:
318        assert_eq!(v.len(), 3);
319        let snapshot = v.to_vec();
320        assert!(snapshot.contains(&10));
321        assert!(snapshot.contains(&30));
322        assert!(snapshot.contains(&40));
323        assert!(!snapshot.contains(&20));
324
325        let v: Vec<i32> = v.into();
326        assert_eq!(snapshot, v);
327    }
328
329    #[test]
330    fn to_vec_clone_snapshot() {
331        let v = ValueVec::new();
332        v.extend(["a", "b"]);
333        let snap = v.to_vec();
334        assert_eq!(snap, vec!["a", "b"]);
335        // Mutate original; snapshot unaffected.
336        v.push("c");
337        assert_eq!(v.len(), 3);
338        assert_eq!(snap.len(), 2);
339    }
340
341    #[test]
342    fn debug_impl() {
343        let v = ValueVec::from(vec![1, 2, 3]);
344        let s = format!("{v:?}");
345        println!("{}", s);
346        assert!(!s.contains("ValueVec"));
347        assert!(s.contains("[1, 2, 3]"));
348    }
349
350    #[test]
351    fn from_vec_wraps_without_copy() {
352        let v = vec![1, 2, 3];
353        let vv = ValueVec::from(v);
354        // We can't check memory identity directly, but we can check content and len.
355        assert_eq!(vv.len(), 3);
356        assert_eq!(vv.at(0), 1);
357        assert_eq!(vv.at(1), 2);
358        assert_eq!(vv.at(2), 3);
359        // Original vector is consumed and cannot be used.
360    }
361
362    #[test]
363    fn into_vec_unwraps_without_copy() {
364        let vv = ValueVec::from(vec!["a", "b"]);
365        let v: Vec<_> = vv.into(); // moves out inner Vec
366        assert_eq!(v, vec!["a", "b"]);
367    }
368
369    #[test]
370    fn round_trip_from_vec_into_vec() {
371        let original = vec![10, 20, 30];
372        let vv = ValueVec::from(original);
373        let roundtrip: Vec<_> = vv.into();
374        assert_eq!(roundtrip, vec![10, 20, 30]);
375    }
376
377    #[test]
378    fn into_iterator_consumes_valuevec() {
379        let vv = ValueVec::from(vec![1, 2, 3]);
380        let collected: Vec<_> = vv.into_iter().collect();
381        assert_eq!(collected, vec![1, 2, 3]);
382    }
383
384    #[test]
385    fn into_iterator_and_into_vec_equivalence() {
386        let vv1 = ValueVec::from(vec![5, 6, 7]);
387        let vv2 = ValueVec::from(vec![5, 6, 7]);
388        let collected_from_iter: Vec<_> = vv1.into_iter().collect();
389        let collected_from_into: Vec<_> = vv2.into();
390        assert_eq!(collected_from_iter, collected_from_into);
391    }
392
393    #[test]
394    fn from_iterator_collect() {
395        let source = [1, 2, 3, 4, 5];
396        let vv: ValueVec<i32> = source.iter().copied().collect();
397        assert_eq!(vv.len(), 5);
398        assert_eq!(vv.at(0), 1);
399        assert_eq!(vv.at(4), 5);
400    }
401}