1use alloc::vec::Vec;
5use smallvec::SmallVec;
6
7use crate::Backing;
8use crate::ClosedRange;
9use crate::Endpoint;
10use crate::RangeVec;
11
12#[derive(Clone, Debug)]
18pub struct RangeCase<T: Endpoint> {
19 inner: Backing<T>,
20 normalized: bool,
21}
22
23impl<T: Endpoint> RangeCase<T> {
24 #[inline(always)]
28 pub fn from_vec(inner: Vec<(T, T)>) -> Self {
29 Self {
30 inner: inner.into(),
31 normalized: false,
32 }
33 }
34
35 pub fn from_smallvec<const N: usize>(inner: SmallVec<[(T, T); N]>) -> Self {
39 #[cfg_attr(
41 not(feature = "inline_storage"),
42 allow(clippy::absurd_extreme_comparisons)
43 )]
44 let inner: Backing<T> = if inner.len() <= crate::INLINE_SIZE {
45 inner.into_iter().collect()
46 } else {
47 inner.into_vec().into()
48 };
49
50 Self {
51 inner,
52 normalized: false,
53 }
54 }
55
56 pub fn from_slice(slice: impl AsRef<[(T, T)]>) -> Self {
60 Self::from_smallvec::<{ crate::INLINE_SIZE }>(SmallVec::from_slice(slice.as_ref()))
61 }
62
63 #[inline(always)]
67 pub fn from_range_vec(set: RangeVec<T>) -> Self {
68 Self {
69 inner: set.into_inner(),
70 normalized: true,
71 }
72 }
73
74 #[inline(always)]
78 pub fn into_inner(self) -> Backing<T> {
79 self.inner
80 }
81
82 #[inline(always)]
87 pub fn unerase(self) -> Result<RangeVec<T>, Backing<T>> {
88 if self.normalized {
89 Ok(unsafe { RangeVec::new_unchecked(self.inner) })
90 } else {
91 Err(self.inner)
92 }
93 }
94}
95
96impl<T: Endpoint> From<RangeVec<T>> for RangeCase<T> {
97 #[inline(always)]
98 fn from(item: RangeVec<T>) -> RangeCase<T> {
99 RangeCase::from_range_vec(item)
100 }
101}
102
103impl<T: Endpoint> From<Vec<(T, T)>> for RangeCase<T> {
104 #[inline(always)]
105 fn from(item: Vec<(T, T)>) -> RangeCase<T> {
106 RangeCase::from_vec(item)
107 }
108}
109
110impl<T: Endpoint, const N: usize> From<SmallVec<[(T, T); N]>> for RangeCase<T> {
111 #[inline(always)]
112 fn from(item: SmallVec<[(T, T); N]>) -> RangeCase<T> {
113 RangeCase::from_smallvec(item)
114 }
115}
116
117impl<T: Endpoint> From<&[(T, T)]> for RangeCase<T> {
118 #[inline(always)]
119 fn from(item: &[(T, T)]) -> RangeCase<T> {
120 RangeCase::from_slice(item)
121 }
122}
123
124impl<T: Endpoint, const N: usize> From<&[(T, T); N]> for RangeCase<T> {
125 #[inline(always)]
126 fn from(item: &[(T, T); N]) -> RangeCase<T> {
127 RangeCase::from_slice(item)
128 }
129}
130
131impl<T: Endpoint, const N: usize> From<[(T, T); N]> for RangeCase<T> {
132 #[inline(always)]
133 fn from(item: [(T, T); N]) -> RangeCase<T> {
134 RangeCase::from_slice(item)
135 }
136}
137
138impl<T: Endpoint> From<(T, T)> for RangeCase<T> {
139 #[inline(always)]
140 fn from(item: (T, T)) -> RangeCase<T> {
141 RangeCase::from_slice([item])
142 }
143}
144
145impl<T: Endpoint> From<Option<(T, T)>> for RangeCase<T> {
146 #[inline(always)]
147 fn from(item: Option<(T, T)>) -> RangeCase<T> {
148 RangeCase::from_slice(item.as_slice())
149 }
150}
151
152impl<T: Endpoint, Item> core::iter::FromIterator<Item> for RangeCase<T>
153where
154 Item: ClosedRange<EndT = T>,
155{
156 fn from_iter<It: IntoIterator<Item = Item>>(iter: It) -> Self {
157 Self::from_smallvec::<{ crate::INLINE_SIZE }>(iter.into_iter().map(|x| x.get()).collect())
158 }
159}
160
161#[cfg_attr(coverage_nightly, coverage(off))]
162#[test]
163fn test_smoke() {
164 use alloc::vec;
165 use smallvec::smallvec;
166
167 {
168 let empty_1: RangeCase<u8> = RangeCase::from_slice([]);
169 let empty_2: RangeCase<_> = None.into();
170 assert_eq!(empty_1.into_inner(), empty_2.into_inner());
171 }
172
173 let x: RangeCase<_> = vec![(1u8, 2u8)].into();
174 assert_eq!(x.clone().into_inner().into_vec(), vec![(1u8, 2u8)]);
175
176 {
178 let y: RangeCase<_> = (1u8, 2u8).into();
179 assert_eq!(x.clone().into_inner(), y.into_inner());
180
181 let y: RangeCase<_> = Some((1u8, 2u8)).into();
182 assert_eq!(x.clone().into_inner(), y.into_inner());
183 }
184
185 {
186 let x: RangeCase<_> = (&[(1u8, 2u8), (3u8, 4u8), (10u8, 255u8)][..]).into();
187 assert_eq!(
188 x.into_inner().into_vec(),
189 vec![(1u8, 2u8), (3u8, 4u8), (10u8, 255u8)]
190 );
191
192 let x: RangeCase<_> = [(1u8, 2u8)].into();
193 assert_eq!(x.into_inner().into_vec(), vec![(1u8, 2u8)]);
194
195 let x: RangeCase<_> = (&[(1u8, 2u8)]).into();
196 assert_eq!(x.into_inner().into_vec(), vec![(1u8, 2u8)]);
197 }
198
199 {
200 let smallvec: Backing<u8> = smallvec![(1u8, 2u8)];
201 let x: RangeCase<_> = smallvec.into();
202 assert_eq!(x.unerase().unwrap_err().into_vec(), vec![(1u8, 2u8)]);
203
204 let smallvec: Backing<u8> = smallvec![(1u8, 2u8), (10u8, 12u8), (20u8, 30u8)];
205 let x: RangeCase<_> = smallvec.into();
206 assert_eq!(
207 x.unerase().unwrap_err().into_vec(),
208 vec![(1u8, 2u8), (10u8, 12u8), (20u8, 30u8)]
209 );
210 }
211
212 {
213 let smallervec: SmallVec<[(u8, u8); 0]> = smallvec![(1u8, 2u8)];
214 let x: RangeCase<_> = smallervec.into();
215 assert_eq!(x.unerase().unwrap_err().into_vec(), vec![(1u8, 2u8)]);
216
217 let smallervec: SmallVec<[(u8, u8); 0]> = smallvec![(1u8, 2u8), (3u8, 4u8), (10u8, 11u8)];
218 let x: RangeCase<_> = smallervec.into();
219 assert_eq!(
220 x.unerase().unwrap_err().into_vec(),
221 vec![(1u8, 2u8), (3u8, 4u8), (10u8, 11u8)]
222 );
223 }
224
225 {
226 let largervec: SmallVec<[(u8, u8); crate::INLINE_SIZE + 1]> = smallvec![(1u8, 2u8)];
227 let x: RangeCase<_> = largervec.into();
228 assert_eq!(x.unerase().unwrap_err().into_vec(), vec![(1u8, 2u8)]);
229
230 let largervec: SmallVec<[(u8, u8); crate::INLINE_SIZE + 1]> =
231 smallvec![(1u8, 2u8), (3u8, 4u8), (10u8, 11u8)];
232 let x: RangeCase<_> = largervec.into();
233 assert_eq!(
234 x.unerase().unwrap_err().into_vec(),
235 vec![(1u8, 2u8), (3u8, 4u8), (10u8, 11u8)]
236 );
237 }
238
239 let itcase: RangeCase<u8> = RangeCase::from_iter(&[(1u8, 2u8)]);
240 assert_eq!(itcase.unerase().unwrap_err().into_vec(), vec![(1u8, 2u8)]);
241
242 let vec = unsafe { RangeVec::new_unchecked(smallvec![(1u8, 2u8)]) };
243 let x: RangeCase<_> = vec.clone().into();
244 assert_eq!(x.unerase().unwrap(), vec);
245}