1use std::{ops::Deref, sync::Arc};
5
6use serde::{Deserialize, Deserializer, Serialize, Serializer};
7
8#[derive(Debug, PartialOrd, PartialEq, Ord, Eq, Hash)]
9pub struct CowVec<T>
10where
11 T: Clone + PartialEq,
12{
13 inner: Arc<Vec<T>>,
14}
15
16impl<T> CowVec<T>
17where
18 T: Clone + PartialEq,
19{
20 pub fn with_capacity(capacity: usize) -> Self {
21 let aligned_capacity = (capacity + 7) & !7;
25 Self {
26 inner: Arc::new(Vec::with_capacity(aligned_capacity)),
27 }
28 }
29
30 pub fn with_aligned_capacity(capacity: usize) -> Self {
32 let simd_alignment = 32 / std::mem::size_of::<T>().max(1);
36 let aligned_capacity = ((capacity + simd_alignment - 1) / simd_alignment) * simd_alignment;
37 Self {
38 inner: Arc::new(Vec::with_capacity(aligned_capacity)),
39 }
40 }
41
42 pub fn len(&self) -> usize {
43 self.inner.len()
44 }
45
46 pub fn capacity(&self) -> usize {
47 self.inner.capacity()
48 }
49}
50
51#[macro_export]
52macro_rules! async_cow_vec {
53 () => {
54 $crate::CowVec::new(Vec::new())
55 };
56 ($($elem:expr),+ $(,)?) => {
57 $crate::CowVec::new(vec![$($elem),+])
58 };
59}
60
61impl<T> Default for CowVec<T>
62where
63 T: Clone + PartialEq,
64{
65 fn default() -> Self {
66 Self {
67 inner: Arc::new(Vec::new()),
68 }
69 }
70}
71
72impl<T: Clone + PartialEq> PartialEq<[T]> for &CowVec<T> {
73 fn eq(&self, other: &[T]) -> bool {
74 self.inner.as_slice() == other
75 }
76}
77
78impl<T: Clone + PartialEq> PartialEq<[T]> for CowVec<T> {
79 fn eq(&self, other: &[T]) -> bool {
80 self.inner.as_slice() == other
81 }
82}
83
84impl<T: Clone + PartialEq> PartialEq<CowVec<T>> for [T] {
85 fn eq(&self, other: &CowVec<T>) -> bool {
86 self == other.inner.as_slice()
87 }
88}
89
90impl<T: Clone + PartialEq> Clone for CowVec<T> {
91 fn clone(&self) -> Self {
92 CowVec {
93 inner: Arc::clone(&self.inner),
94 }
95 }
96}
97
98impl<T: Clone + PartialEq> CowVec<T> {
99 pub fn new(vec: Vec<T>) -> Self {
100 CowVec {
101 inner: Arc::new(vec),
102 }
103 }
104
105 pub fn from_rc(rc: Arc<Vec<T>>) -> Self {
106 CowVec {
107 inner: rc,
108 }
109 }
110
111 pub fn as_slice(&self) -> &[T] {
112 &self.inner
113 }
114
115 pub fn is_owned(&self) -> bool {
116 Arc::strong_count(&self.inner) == 1
117 }
118
119 pub fn is_shared(&self) -> bool {
120 Arc::strong_count(&self.inner) > 1
121 }
122
123 pub fn get(&self, idx: usize) -> Option<&T> {
124 self.inner.get(idx)
125 }
126
127 pub fn make_mut(&mut self) -> &mut Vec<T> {
128 Arc::make_mut(&mut self.inner)
129 }
130
131 pub fn set(&mut self, idx: usize, value: T) {
132 self.make_mut()[idx] = value;
133 }
134
135 pub fn push(&mut self, value: T) {
136 self.make_mut().push(value);
137 }
138
139 pub fn extend(&mut self, iter: impl IntoIterator<Item = T>) {
140 self.make_mut().extend(iter);
141 }
142
143 pub fn extend_from_slice(&mut self, slice: &[T]) {
144 self.make_mut().extend_from_slice(slice);
145 }
146
147 pub fn reorder(&mut self, indices: &[usize]) {
148 let vec = self.make_mut();
149 let len = vec.len();
150 assert_eq!(len, indices.len());
151
152 let mut visited = vec![false; len];
153 for start in 0..len {
154 if visited[start] || indices[start] == start {
155 continue;
156 }
157 let mut current = start;
158 while !visited[current] {
159 visited[current] = true;
160 let next = indices[current];
161 if next == start {
162 break;
163 }
164 vec.swap(current, next);
165 current = next;
166 }
167 }
168 }
169
170 pub fn aligned_chunks(&self, chunk_size: usize) -> impl Iterator<Item = &[T]> {
174 self.inner.chunks(chunk_size)
175 }
176
177 pub fn aligned_chunks_mut(&mut self, chunk_size: usize) -> impl Iterator<Item = &mut [T]> {
179 self.make_mut().chunks_mut(chunk_size)
180 }
181
182 pub fn is_simd_aligned(&self) -> bool {
184 let alignment = 32; let ptr = self.inner.as_ptr() as usize;
186 ptr % alignment == 0
187 }
188
189 pub fn take(&self, n: usize) -> Self {
190 let len = n.min(self.len());
191 CowVec::new(self.inner[..len].to_vec())
192 }
193}
194
195impl<T: Clone + PartialEq> IntoIterator for CowVec<T> {
196 type Item = T;
197 type IntoIter = std::vec::IntoIter<T>;
198
199 fn into_iter(self) -> Self::IntoIter {
200 match Arc::try_unwrap(self.inner) {
201 Ok(vec) => vec.into_iter(),
202 Err(arc) => (*arc).clone().into_iter(),
203 }
204 }
205}
206
207impl<T: Clone + PartialEq> Deref for CowVec<T> {
208 type Target = [T];
209
210 fn deref(&self) -> &Self::Target {
211 self.as_slice()
212 }
213}
214
215impl<T> Serialize for CowVec<T>
216where
217 T: Clone + PartialEq + Serialize,
218{
219 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
220 where
221 S: Serializer,
222 {
223 self.inner.serialize(serializer)
224 }
225}
226
227impl<'de, T> Deserialize<'de> for CowVec<T>
228where
229 T: Clone + PartialEq + Deserialize<'de>,
230{
231 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
232 where
233 D: Deserializer<'de>,
234 {
235 let vec = Vec::<T>::deserialize(deserializer)?;
236 Ok(CowVec {
237 inner: Arc::new(vec),
238 })
239 }
240}
241
242#[cfg(test)]
243mod tests {
244 use super::CowVec;
245
246 #[test]
247 fn test_new() {
248 let cow = CowVec::new(vec![1, 2, 3]);
249 assert_eq!(cow.get(0), Some(&1));
250 assert_eq!(cow.get(1), Some(&2));
251 assert_eq!(cow.get(2), Some(&3));
252 }
253
254 #[test]
255 fn test_is_owned() {
256 let mut owned = CowVec::new(Vec::with_capacity(16));
257 owned.extend([1, 2]);
258
259 assert!(owned.is_owned());
260
261 let shared = owned.clone();
262 assert!(!owned.is_owned());
263 assert!(!shared.is_owned());
264
265 drop(shared);
266
267 assert!(owned.is_owned());
268 }
269
270 #[test]
271 fn test_is_shared() {
272 let mut owned = CowVec::new(Vec::with_capacity(16));
273 owned.extend([1, 2]);
274
275 assert!(!owned.is_shared());
276
277 let shared = owned.clone();
278 assert!(owned.is_shared());
279 assert!(shared.is_shared());
280
281 drop(shared);
282
283 assert!(!owned.is_shared());
284 }
285
286 #[test]
287 fn test_extend() {
288 let mut owned = CowVec::new(Vec::with_capacity(16));
289 owned.extend([1, 2]);
290
291 let ptr_before_owned = ptr_of(&owned);
292 owned.extend([9, 9, 24]);
293 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(owned.len(), 5);
295
296 let mut shared = owned.clone();
297
298 let ptr_before_shared = ptr_of(&shared);
299 shared.extend([9, 9, 24]);
300 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(owned.len(), 5);
302 }
303
304 #[test]
305 fn test_push() {
306 let mut owned = CowVec::new(Vec::with_capacity(16));
307 owned.extend([1, 2]);
308
309 let ptr_before_owned = ptr_of(&owned);
310 owned.push(99);
311 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(owned.len(), 3);
313
314 let mut shared = owned.clone();
315
316 let ptr_before_shared = ptr_of(&shared);
317 shared.push(99);
318 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(owned.len(), 3);
320 }
321
322 #[test]
323 fn test_set() {
324 let mut owned = CowVec::new(Vec::with_capacity(16));
325 owned.extend([1, 2]);
326
327 let ptr_before_owned = ptr_of(&owned);
328 owned.set(1, 99);
329 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(*owned, [1, 99]);
331
332 let mut shared = owned.clone();
333
334 let ptr_before_shared = ptr_of(&shared);
335 shared.set(1, 99);
336 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(*owned, [1, 99]);
338 }
339
340 #[test]
341 fn test_reorder() {
342 let mut owned = CowVec::new(Vec::with_capacity(16));
343 owned.extend([1, 2]);
344
345 let ptr_before_owned = ptr_of(&owned);
346 owned.reorder(&[1usize, 0]);
347 assert_eq!(ptr_before_owned, ptr_of(&owned)); assert_eq!(*owned, [2, 1]);
349
350 let mut shared = owned.clone();
351
352 let ptr_before_shared = ptr_of(&shared);
353 shared.reorder(&[1usize, 0]);
354 assert_ne!(ptr_before_shared, ptr_of(&shared)); assert_eq!(*shared, [1, 2]);
356 }
357
358 #[test]
359 fn test_reorder_identity() {
360 let mut cow = CowVec::new(vec![10, 20, 30]);
361 cow.reorder(&[0, 1, 2]); assert_eq!(cow.as_slice(), &[10, 20, 30]);
363 }
364
365 #[test]
366 fn test_reorder_basic() {
367 let mut cow = CowVec::new(vec![10, 20, 30]);
368 cow.reorder(&[2, 0, 1]);
369 assert_eq!(cow.as_slice(), &[30, 10, 20]);
370 }
371
372 fn ptr_of(v: &CowVec<i32>) -> *const i32 {
373 v.as_slice().as_ptr()
374 }
375}