1use std::fmt;
2
3use super::Rc;
4use crate::ImplicitClone;
5
6#[derive(PartialEq, Eq)]
32pub enum IArray<T: ImplicitClone + 'static> {
33 Static(&'static [T]),
35 Rc(Rc<[T]>),
37}
38
39impl<T: fmt::Debug + ImplicitClone + 'static> fmt::Debug for IArray<T> {
41 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42 match self {
43 Self::Static(a) => a.fmt(f),
44 Self::Rc(a) => a.fmt(f),
45 }
46 }
47}
48
49impl<T: ImplicitClone + 'static> Clone for IArray<T> {
50 fn clone(&self) -> Self {
51 match self {
52 Self::Static(a) => Self::Static(a),
53 Self::Rc(a) => Self::Rc(a.clone()),
54 }
55 }
56}
57
58impl<T: ImplicitClone + 'static> Default for IArray<T> {
59 fn default() -> Self {
60 Self::EMPTY
61 }
62}
63
64impl<T: ImplicitClone + 'static> FromIterator<T> for IArray<T> {
65 fn from_iter<I: IntoIterator<Item = T>>(it: I) -> Self {
66 let mut it = it.into_iter();
67 match it.size_hint() {
68 (_, Some(0)) => Self::EMPTY,
69 (_, Some(1)) => {
70 if let Some(element) = it.next() {
71 Self::from([element])
72 } else {
73 Self::EMPTY
74 }
75 }
76 _ => Self::Rc(Rc::from_iter(it)),
77 }
78 }
79}
80
81impl<T: ImplicitClone + 'static> ImplicitClone for IArray<T> {}
82
83impl<T: ImplicitClone + 'static> From<&'static [T]> for IArray<T> {
84 fn from(a: &'static [T]) -> IArray<T> {
85 IArray::Static(a)
86 }
87}
88
89impl<T: ImplicitClone + 'static> From<Vec<T>> for IArray<T> {
90 fn from(a: Vec<T>) -> IArray<T> {
91 IArray::Rc(Rc::from(a))
92 }
93}
94
95impl<T: ImplicitClone + 'static> From<Rc<[T]>> for IArray<T> {
96 fn from(a: Rc<[T]>) -> IArray<T> {
97 IArray::Rc(a)
98 }
99}
100
101impl<T: ImplicitClone + 'static> From<&IArray<T>> for IArray<T> {
102 fn from(a: &IArray<T>) -> IArray<T> {
103 a.clone()
104 }
105}
106
107impl<T: ImplicitClone + 'static, const N: usize> From<[T; N]> for IArray<T> {
108 fn from(a: [T; N]) -> IArray<T> {
109 IArray::Rc(Rc::from(a))
110 }
111}
112
113#[derive(Debug)]
115pub struct IArrayIntoIter<T: ImplicitClone + 'static> {
116 array: IArray<T>,
117 left: usize,
118 right: usize,
119}
120
121impl<T: ImplicitClone + 'static> IntoIterator for IArray<T> {
122 type Item = T;
123 type IntoIter = IArrayIntoIter<T>;
124
125 fn into_iter(self) -> <Self as IntoIterator>::IntoIter {
126 IArrayIntoIter {
127 left: 0,
128 right: self.len(),
129 array: self,
130 }
131 }
132}
133
134impl<T: ImplicitClone + 'static> Iterator for IArrayIntoIter<T> {
135 type Item = T;
136
137 fn next(&mut self) -> Option<Self::Item> {
138 if self.left >= self.right {
139 return None;
140 }
141 let item = &self.array[self.left];
142 self.left += 1;
143 Some(item.clone())
144 }
145}
146
147impl<T: ImplicitClone + 'static> DoubleEndedIterator for IArrayIntoIter<T> {
148 fn next_back(&mut self) -> Option<Self::Item> {
149 if self.left >= self.right {
150 return None;
151 }
152 self.right -= 1;
153 Some(self.array[self.right].clone())
154 }
155}
156
157impl<T: ImplicitClone + 'static> IArray<T> {
158 pub const EMPTY: Self = Self::Static(&[]);
160
161 #[inline]
172 pub fn len(&self) -> usize {
173 match self {
174 Self::Static(a) => a.len(),
175 Self::Rc(a) => a.len(),
176 }
177 }
178
179 #[inline]
192 pub fn is_empty(&self) -> bool {
193 match self {
194 Self::Static(a) => a.is_empty(),
195 Self::Rc(a) => a.is_empty(),
196 }
197 }
198
199 #[inline]
212 pub fn as_slice(&self) -> &[T] {
213 match self {
214 Self::Static(a) => a,
215 Self::Rc(a) => a,
216 }
217 }
218
219 #[inline]
230 pub fn get(&self, index: usize) -> Option<&T> {
231 match self {
232 Self::Static(a) => a.get(index),
233 Self::Rc(a) => a.get(index),
234 }
235 }
236
237 #[inline]
262 pub fn get_mut(&mut self) -> Option<&mut [T]> {
263 match self {
264 Self::Rc(ref mut rc) => Rc::get_mut(rc),
265 Self::Static(_) => None,
266 }
267 }
268
269 #[inline]
313 pub fn make_mut(&mut self) -> &mut [T] {
314 match self {
315 Self::Rc(ref mut rc) => {
316 if Rc::get_mut(rc).is_none() {
321 *rc = rc.iter().cloned().collect::<Rc<[T]>>();
322 }
323 Rc::get_mut(rc).unwrap()
324 }
325 Self::Static(slice) => {
326 *self = Self::Rc(slice.iter().cloned().collect());
327 match self {
328 Self::Rc(rc) => Rc::get_mut(rc).unwrap(),
329 _ => unreachable!(),
330 }
331 }
332 }
333 }
334}
335
336impl<'a, T, U, const N: usize> PartialEq<&'a [U; N]> for IArray<T>
337where
338 T: PartialEq<U> + ImplicitClone,
339{
340 fn eq(&self, other: &&[U; N]) -> bool {
341 match self {
342 Self::Static(a) => a.eq(other),
343 Self::Rc(a) => a.eq(*other),
344 }
345 }
346}
347
348impl<T, U, const N: usize> PartialEq<[U; N]> for IArray<T>
349where
350 T: PartialEq<U> + ImplicitClone,
351{
352 fn eq(&self, other: &[U; N]) -> bool {
353 match self {
354 Self::Static(a) => a.eq(other),
355 Self::Rc(a) => a.eq(other),
356 }
357 }
358}
359
360impl<T, U> PartialEq<[U]> for IArray<T>
361where
362 T: PartialEq<U> + ImplicitClone,
363{
364 fn eq(&self, other: &[U]) -> bool {
365 match self {
366 Self::Static(a) => a.eq(&other),
367 Self::Rc(a) => a.eq(other),
368 }
369 }
370}
371
372impl<'a, T, U> PartialEq<&'a [U]> for IArray<T>
373where
374 T: PartialEq<U> + ImplicitClone,
375{
376 fn eq(&self, other: &&[U]) -> bool {
377 match self {
378 Self::Static(a) => a.eq(other),
379 Self::Rc(a) => a.eq(*other),
380 }
381 }
382}
383
384impl<T> std::ops::Deref for IArray<T>
385where
386 T: ImplicitClone,
387{
388 type Target = [T];
389
390 fn deref(&self) -> &Self::Target {
391 self.as_slice()
392 }
393}
394
395#[cfg(feature = "serde")]
396impl<T: serde::Serialize + ImplicitClone> serde::Serialize for IArray<T> {
397 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
398 <[T] as serde::Serialize>::serialize(self, serializer)
399 }
400}
401
402#[cfg(feature = "serde")]
403impl<'de, T: serde::Deserialize<'de> + ImplicitClone> serde::Deserialize<'de> for IArray<T> {
404 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
405 <Vec<T> as serde::Deserialize>::deserialize(deserializer).map(IArray::<T>::from)
406 }
407}
408
409#[cfg(test)]
410mod test_array {
411 use super::*;
412
413 #[test]
414 fn array_in_array() {
415 let array_1 = [1, 2, 3].into_iter().collect::<IArray<u32>>();
416 let array_2 = [4, 5, 6].into_iter().collect::<IArray<u32>>();
417 let array_of_array = [array_1, array_2]
418 .into_iter()
419 .collect::<IArray<IArray<u32>>>();
420 assert_eq!(array_of_array, [[1, 2, 3], [4, 5, 6]]);
421 }
422
423 #[test]
424 fn array_holding_rc_items() {
425 struct Item;
426 let _array = [Rc::new(Item)].into_iter().collect::<IArray<Rc<Item>>>();
427 }
428
429 #[test]
430 fn from_iter_is_optimized() {
431 let array_0 = [].into_iter().collect::<IArray<u32>>();
432 assert!(matches!(array_0, IArray::Static(_)));
433 let array_2 = [1, 2].into_iter().collect::<IArray<u32>>();
434 assert!(matches!(array_2, IArray::Rc(_)));
435 {
436 let it = [1].into_iter().filter(|x| x % 2 == 0);
437 assert_eq!(it.size_hint(), (0, Some(1)));
438 let array_0_to_1 = it.collect::<IArray<u32>>();
439 assert!(matches!(array_0_to_1, IArray::Static(_)));
440 }
441 {
442 let it = [2].into_iter().filter(|x| x % 2 == 0);
443 assert_eq!(it.size_hint(), (0, Some(1)));
444 let array_0_to_1 = it.collect::<IArray<u32>>();
445 assert!(matches!(array_0_to_1, IArray::Rc(_)));
446 }
447 }
448
449 #[test]
450 fn static_array() {
451 const _ARRAY: IArray<u32> = IArray::Static(&[1, 2, 3]);
452 }
453
454 #[test]
455 fn deref_slice() {
456 assert!(IArray::Static(&[1, 2, 3]).contains(&1));
457 }
458
459 #[test]
460 fn tuple_in_array() {
461 const _ARRAY_2: IArray<(u32, u32)> = IArray::EMPTY;
462 const _ARRAY_5: IArray<(u32, u32, u32, u32, u32)> = IArray::EMPTY;
463 }
464
465 #[test]
466 fn floats_in_array() {
467 const _ARRAY_F32: IArray<f32> = IArray::EMPTY;
468 const _ARRAY_F64: IArray<f64> = IArray::EMPTY;
469 }
470
471 #[test]
472 fn from() {
473 let x: IArray<u32> = IArray::EMPTY;
474 let _out = IArray::from(&x);
475
476 let _array: IArray<u32> = IArray::from(&[1, 2, 3][..]);
477 let _array: IArray<u32> = IArray::from(vec![1, 2, 3]);
478 let _array: IArray<u32> = IArray::from(Rc::from(vec![1, 2, 3]));
479 let _array: IArray<u32> = IArray::from([1]);
480 }
481
482 #[test]
483 fn recursion() {
484 #[derive(Clone)]
485 struct _Node {
486 _children: IArray<_Node>,
487 }
488
489 impl ImplicitClone for _Node {}
490 }
491
492 #[test]
493 fn into_iter() {
494 let array = IArray::Static(&[1, 2, 3]);
495 assert_eq!(array.iter().next().unwrap(), &1);
496 assert_eq!(array.into_iter().next().unwrap(), 1);
497 }
498}