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}