evobench_tools/utillib/
slice_or_box.rs

1//! `Cow<'t, [T]>` requires `T` to implement `ToOwned`,
2//! i.e. `to_owned()` wants to make a deep copy,
3//! apparently. `SliceOrBox` is just about the outermost
4//! layer. (`RefOrOwned` only represents a reference or owned value of
5//! the same type and hence does not work for this, either.)
6
7// And a RefOrBox, same but without the explicit [ ], would not work
8// because then the type would become unsized.
9
10use std::ops::Deref;
11
12use super::ref_or_owned::RefOrOwned;
13
14#[derive(Clone, Debug)]
15pub enum SliceOrBox<'t, T> {
16    Slice(&'t [T]),
17    Box(Box<[T]>),
18}
19
20impl<'t, T> SliceOrBox<'t, T> {
21    /// Into the inner owned representation, or convert that to
22    /// owned. Removes the wrapping.
23    pub fn into_owned(self) -> Box<[T]>
24    where
25        T: Clone,
26    {
27        match self {
28            SliceOrBox::Slice(borrowed) => borrowed.to_owned().into(),
29            SliceOrBox::Box(owned) => owned,
30        }
31    }
32
33    // pub fn to_owned(&self) -> SliceOrBox<'static, T> {
34    // ..  because ToOwned requires Borrow. But, into_owned and the wrap again is fine for now?
35    // }
36}
37
38impl<'t, T> AsRef<[T]> for SliceOrBox<'t, T> {
39    fn as_ref(&self) -> &[T] {
40        match self {
41            SliceOrBox::Slice(r) => r,
42            SliceOrBox::Box(r) => r,
43        }
44    }
45}
46
47impl<'t, T> From<&'t [T]> for SliceOrBox<'t, T> {
48    fn from(value: &'t [T]) -> Self {
49        Self::Slice(value)
50    }
51}
52
53impl<'t, T> From<Box<[T]>> for SliceOrBox<'t, T> {
54    fn from(value: Box<[T]>) -> Self {
55        Self::Box(value)
56    }
57}
58
59impl<'t, T, const N: usize> From<[T; N]> for SliceOrBox<'t, T> {
60    fn from(value: [T; N]) -> Self {
61        Self::Box(value.into())
62    }
63}
64
65impl<'t, T> From<Vec<T>> for SliceOrBox<'t, T> {
66    fn from(value: Vec<T>) -> Self {
67        Self::Box(value.into())
68    }
69}
70
71impl<'t, T> Deref for SliceOrBox<'t, T> {
72    type Target = [T];
73
74    fn deref(&self) -> &Self::Target {
75        self.as_ref()
76    }
77}
78
79// Need these so that Option<SliceOrBox<..>> can be compared, right?
80// "Why do I have to do this when Deref exists??"
81
82impl<'t, T: PartialEq> PartialEq for SliceOrBox<'t, T> {
83    fn eq(&self, other: &Self) -> bool {
84        self.as_ref() == other.as_ref()
85    }
86}
87
88impl<'t, T: Eq> Eq for SliceOrBox<'t, T> {}
89
90impl<'t, T: PartialOrd> PartialOrd for SliceOrBox<'t, T> {
91    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
92        self.as_ref().partial_cmp(other.as_ref())
93    }
94}
95
96impl<'t, T: Ord> Ord for SliceOrBox<'t, T> {
97    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
98        self.as_ref().cmp(other.as_ref())
99    }
100}
101
102pub enum SliceOrBoxIterator<'t, T> {
103    Slice(std::slice::Iter<'t, T>),
104    Box(std::vec::IntoIter<T>),
105}
106
107impl<'t, T> Iterator for SliceOrBoxIterator<'t, T> {
108    type Item = RefOrOwned<'t, T>;
109
110    fn next(&mut self) -> Option<Self::Item> {
111        match self {
112            SliceOrBoxIterator::Slice(it) => it.next().map(RefOrOwned::Ref),
113            SliceOrBoxIterator::Box(it) => it.next().map(RefOrOwned::Owned),
114        }
115    }
116}
117
118impl<'t, T> IntoIterator for SliceOrBox<'t, T> {
119    type Item = RefOrOwned<'t, T>;
120
121    type IntoIter = SliceOrBoxIterator<'t, T>;
122
123    fn into_iter(self) -> Self::IntoIter {
124        match self {
125            SliceOrBox::Slice(items) => SliceOrBoxIterator::Slice(items.into_iter()),
126            // IntoIterator for Box somehow only has a borrowing
127            // implementation in std, thus convert to a Vec first
128            // (that should be cheap?)
129            SliceOrBox::Box(items) => SliceOrBoxIterator::Box(Vec::from(items).into_iter()),
130        }
131    }
132}