1#[cfg(feature = "cow-stats")]
5use std::sync::atomic::Ordering;
6use std::{borrow::Borrow, mem, ops::Deref, sync::Arc, vec};
7
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10#[cfg(feature = "cow-stats")]
11pub mod stats {
12 use std::sync::atomic::{AtomicU64, Ordering};
13
14 pub static MUTATIONS: AtomicU64 = AtomicU64::new(0);
15 pub static COPIES: AtomicU64 = AtomicU64::new(0);
16 pub static ELEMENTS_COPIED: AtomicU64 = AtomicU64::new(0);
17 pub static CLONES: AtomicU64 = AtomicU64::new(0);
18 pub static BYTES_CLONED: AtomicU64 = AtomicU64::new(0);
19 pub static EMPTY_CLONES: AtomicU64 = AtomicU64::new(0);
20
21 #[derive(Debug, Clone, Copy)]
22 pub struct Snapshot {
23 pub mutations: u64,
24 pub copies: u64,
25 pub elements_copied: u64,
26 pub clones: u64,
27 pub bytes_cloned: u64,
28 pub empty_clones: u64,
29 }
30
31 pub fn reset() {
32 MUTATIONS.store(0, Ordering::Relaxed);
33 COPIES.store(0, Ordering::Relaxed);
34 ELEMENTS_COPIED.store(0, Ordering::Relaxed);
35 CLONES.store(0, Ordering::Relaxed);
36 BYTES_CLONED.store(0, Ordering::Relaxed);
37 EMPTY_CLONES.store(0, Ordering::Relaxed);
38 }
39
40 pub fn snapshot() -> Snapshot {
41 Snapshot {
42 mutations: MUTATIONS.load(Ordering::Relaxed),
43 copies: COPIES.load(Ordering::Relaxed),
44 elements_copied: ELEMENTS_COPIED.load(Ordering::Relaxed),
45 clones: CLONES.load(Ordering::Relaxed),
46 bytes_cloned: BYTES_CLONED.load(Ordering::Relaxed),
47 empty_clones: EMPTY_CLONES.load(Ordering::Relaxed),
48 }
49 }
50}
51
52#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Hash)]
53pub struct CowVec<T>
54where
55 T: Clone + PartialEq,
56{
57 inner: Arc<Vec<T>>,
58}
59
60impl<T> CowVec<T>
61where
62 T: Clone + PartialEq,
63{
64 pub fn with_capacity(capacity: usize) -> Self {
65 let aligned_capacity = (capacity + 7) & !7;
66 Self {
67 inner: Arc::new(Vec::with_capacity(aligned_capacity)),
68 }
69 }
70
71 pub fn with_aligned_capacity(capacity: usize) -> Self {
72 let simd_alignment = 32 / mem::size_of::<T>().max(1);
73 let aligned_capacity = capacity.div_ceil(simd_alignment) * simd_alignment;
74 Self {
75 inner: Arc::new(Vec::with_capacity(aligned_capacity)),
76 }
77 }
78
79 pub fn len(&self) -> usize {
80 self.inner.len()
81 }
82
83 pub fn is_empty(&self) -> bool {
84 self.len() == 0
85 }
86
87 pub fn capacity(&self) -> usize {
88 self.inner.capacity()
89 }
90}
91
92#[macro_export]
93macro_rules! cow_vec {
94 () => {
95 $crate::util::cowvec::CowVec::new(Vec::new())
96 };
97 ($($elem:expr),+ $(,)?) => {
98 $crate::util::cowvec::CowVec::new(vec![$($elem),+])
99 };
100}
101
102impl<T> Default for CowVec<T>
103where
104 T: Clone + PartialEq,
105{
106 fn default() -> Self {
107 Self {
108 inner: Arc::new(Vec::new()),
109 }
110 }
111}
112
113impl<T: Clone + PartialEq> PartialEq<[T]> for &CowVec<T> {
114 fn eq(&self, other: &[T]) -> bool {
115 self.inner.as_slice() == other
116 }
117}
118
119impl<T: Clone + PartialEq> PartialEq<[T]> for CowVec<T> {
120 fn eq(&self, other: &[T]) -> bool {
121 self.inner.as_slice() == other
122 }
123}
124
125impl<T: Clone + PartialEq> PartialEq<CowVec<T>> for [T] {
126 fn eq(&self, other: &CowVec<T>) -> bool {
127 self == other.inner.as_slice()
128 }
129}
130
131impl<T: Clone + PartialEq> Clone for CowVec<T> {
132 fn clone(&self) -> Self {
133 #[cfg(feature = "cow-stats")]
134 {
135 stats::CLONES.fetch_add(1, Ordering::Relaxed);
136 let len = self.inner.len();
137 if len == 0 {
138 stats::EMPTY_CLONES.fetch_add(1, Ordering::Relaxed);
139 }
140 stats::BYTES_CLONED.fetch_add((len * mem::size_of::<T>()) as u64, Ordering::Relaxed);
141 }
142 CowVec {
143 inner: Arc::clone(&self.inner),
144 }
145 }
146}
147
148impl<T: Clone + PartialEq> CowVec<T> {
149 pub fn new(vec: Vec<T>) -> Self {
150 CowVec {
151 inner: Arc::new(vec),
152 }
153 }
154
155 pub fn from_rc(rc: Arc<Vec<T>>) -> Self {
156 CowVec {
157 inner: rc,
158 }
159 }
160
161 pub fn try_into_vec(self) -> Result<Vec<T>, Self> {
162 match Arc::try_unwrap(self.inner) {
163 Ok(vec) => Ok(vec),
164 Err(arc) => Err(CowVec {
165 inner: arc,
166 }),
167 }
168 }
169
170 pub fn into_inner(self) -> Vec<T> {
171 match Arc::try_unwrap(self.inner) {
172 Ok(vec) => vec,
173 Err(arc) => (*arc).clone(),
174 }
175 }
176
177 pub fn as_slice(&self) -> &[T] {
178 &self.inner
179 }
180
181 pub fn is_owned(&self) -> bool {
182 Arc::strong_count(&self.inner) == 1
183 }
184
185 pub fn is_shared(&self) -> bool {
186 Arc::strong_count(&self.inner) > 1
187 }
188
189 pub fn get(&self, idx: usize) -> Option<&T> {
190 self.inner.get(idx)
191 }
192
193 pub fn make_mut(&mut self) -> &mut Vec<T> {
194 #[cfg(feature = "cow-stats")]
195 {
196 stats::MUTATIONS.fetch_add(1, Ordering::Relaxed);
197 if Arc::strong_count(&self.inner) > 1 {
198 stats::COPIES.fetch_add(1, Ordering::Relaxed);
199 stats::ELEMENTS_COPIED.fetch_add(self.inner.len() as u64, Ordering::Relaxed);
200 }
201 }
202 Arc::make_mut(&mut self.inner)
203 }
204
205 pub fn set(&mut self, idx: usize, value: T) {
206 self.make_mut()[idx] = value;
207 }
208
209 pub fn push(&mut self, value: T) {
210 self.make_mut().push(value);
211 }
212
213 pub fn clear(&mut self) {
214 self.make_mut().clear();
215 }
216
217 pub fn extend(&mut self, iter: impl IntoIterator<Item = T>) {
218 self.make_mut().extend(iter);
219 }
220
221 pub fn extend_from_slice(&mut self, slice: &[T]) {
222 self.make_mut().extend_from_slice(slice);
223 }
224
225 pub fn reorder(&mut self, indices: &[usize]) {
226 let vec = self.make_mut();
227 let len = vec.len();
228 assert_eq!(len, indices.len());
229
230 let mut visited = vec![false; len];
231 for start in 0..len {
232 if visited[start] || indices[start] == start {
233 continue;
234 }
235 let mut current = start;
236 while !visited[current] {
237 visited[current] = true;
238 let next = indices[current];
239 if next == start {
240 break;
241 }
242 vec.swap(current, next);
243 current = next;
244 }
245 }
246 }
247
248 pub fn aligned_chunks(&self, chunk_size: usize) -> impl Iterator<Item = &[T]> {
249 self.inner.chunks(chunk_size)
250 }
251
252 pub fn aligned_chunks_mut(&mut self, chunk_size: usize) -> impl Iterator<Item = &mut [T]> {
253 self.make_mut().chunks_mut(chunk_size)
254 }
255
256 pub fn is_simd_aligned(&self) -> bool {
257 let alignment = 32;
258 let ptr = self.inner.as_ptr() as usize;
259 ptr.is_multiple_of(alignment)
260 }
261
262 pub fn take(&self, n: usize) -> Self {
263 let len = n.min(self.len());
264 CowVec::new(self.inner[..len].to_vec())
265 }
266}
267
268impl<T: Clone + PartialEq> IntoIterator for CowVec<T> {
269 type Item = T;
270 type IntoIter = vec::IntoIter<T>;
271
272 fn into_iter(self) -> Self::IntoIter {
273 match Arc::try_unwrap(self.inner) {
274 Ok(vec) => vec.into_iter(),
275 Err(arc) => (*arc).clone().into_iter(),
276 }
277 }
278}
279
280impl<T: Clone + PartialEq> Deref for CowVec<T> {
281 type Target = [T];
282
283 fn deref(&self) -> &Self::Target {
284 self.as_slice()
285 }
286}
287
288impl<T: Clone + PartialEq> Borrow<[T]> for CowVec<T> {
289 fn borrow(&self) -> &[T] {
290 self.as_slice()
291 }
292}
293
294impl<T> Serialize for CowVec<T>
295where
296 T: Clone + PartialEq + Serialize,
297{
298 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
299 where
300 S: Serializer,
301 {
302 self.inner.serialize(serializer)
303 }
304}
305
306impl<'de, T> Deserialize<'de> for CowVec<T>
307where
308 T: Clone + PartialEq + Deserialize<'de>,
309{
310 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
311 where
312 D: Deserializer<'de>,
313 {
314 let vec = Vec::<T>::deserialize(deserializer)?;
315 Ok(CowVec {
316 inner: Arc::new(vec),
317 })
318 }
319}
320
321#[cfg(test)]
322pub mod tests {
323 use super::CowVec;
324
325 #[test]
326 fn test_new() {
327 let cow = CowVec::new(vec![1, 2, 3]);
328 assert_eq!(cow.get(0), Some(&1));
329 assert_eq!(cow.get(1), Some(&2));
330 assert_eq!(cow.get(2), Some(&3));
331 }
332
333 #[test]
334 fn test_is_owned() {
335 let mut owned = CowVec::new(Vec::with_capacity(16));
336 owned.extend([1, 2]);
337
338 assert!(owned.is_owned());
339
340 let shared = owned.clone();
341 assert!(!owned.is_owned());
342 assert!(!shared.is_owned());
343
344 drop(shared);
345
346 assert!(owned.is_owned());
347 }
348
349 #[test]
350 fn test_is_shared() {
351 let mut owned = CowVec::new(Vec::with_capacity(16));
352 owned.extend([1, 2]);
353
354 assert!(!owned.is_shared());
355
356 let shared = owned.clone();
357 assert!(owned.is_shared());
358 assert!(shared.is_shared());
359
360 drop(shared);
361
362 assert!(!owned.is_shared());
363 }
364
365 #[test]
366 fn test_extend() {
367 let mut owned = CowVec::new(Vec::with_capacity(16));
368 owned.extend([1, 2]);
369
370 let ptr_before_owned = ptr_of(&owned);
371 owned.extend([9, 9, 24]);
372 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(owned.len(), 5);
374
375 let mut shared = owned.clone();
376
377 let ptr_before_shared = ptr_of(&shared);
378 shared.extend([9, 9, 24]);
379 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(owned.len(), 5);
381 }
382
383 #[test]
384 fn test_push() {
385 let mut owned = CowVec::new(Vec::with_capacity(16));
386 owned.extend([1, 2]);
387
388 let ptr_before_owned = ptr_of(&owned);
389 owned.push(99);
390 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(owned.len(), 3);
392
393 let mut shared = owned.clone();
394
395 let ptr_before_shared = ptr_of(&shared);
396 shared.push(99);
397 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(owned.len(), 3);
399 }
400
401 #[test]
402 fn test_set() {
403 let mut owned = CowVec::new(Vec::with_capacity(16));
404 owned.extend([1, 2]);
405
406 let ptr_before_owned = ptr_of(&owned);
407 owned.set(1, 99);
408 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(*owned, [1, 99]);
410
411 let mut shared = owned.clone();
412
413 let ptr_before_shared = ptr_of(&shared);
414 shared.set(1, 99);
415 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(*owned, [1, 99]);
417 }
418
419 #[test]
420 fn test_reorder() {
421 let mut owned = CowVec::new(Vec::with_capacity(16));
422 owned.extend([1, 2]);
423
424 let ptr_before_owned = ptr_of(&owned);
425 owned.reorder(&[1usize, 0]);
426 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(*owned, [2, 1]);
428
429 let mut shared = owned.clone();
430
431 let ptr_before_shared = ptr_of(&shared);
432 shared.reorder(&[1usize, 0]);
433 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(*shared, [1, 2]);
435 }
436
437 #[test]
438 fn test_reorder_identity() {
439 let mut cow = CowVec::new(vec![10, 20, 30]);
440 cow.reorder(&[0, 1, 2]); assert_eq!(cow.as_slice(), &[10, 20, 30]);
442 }
443
444 #[test]
445 fn test_reorder_basic() {
446 let mut cow = CowVec::new(vec![10, 20, 30]);
447 cow.reorder(&[2, 0, 1]);
448 assert_eq!(cow.as_slice(), &[30, 10, 20]);
449 }
450
451 fn ptr_of(v: &CowVec<i32>) -> *const i32 {
452 v.as_slice().as_ptr()
453 }
454}