icu_locale_core/shortvec/
mod.rs
1mod litemap;
43
44#[cfg(feature = "alloc")]
45use alloc::boxed::Box;
46#[cfg(feature = "alloc")]
47use alloc::vec;
48#[cfg(feature = "alloc")]
49use alloc::vec::Vec;
50use core::ops::Deref;
51use core::ops::DerefMut;
52
53#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
56pub(crate) enum ShortBoxSliceInner<T> {
57 ZeroOne(Option<T>),
58 #[cfg(feature = "alloc")]
59 Multi(Box<[T]>),
60}
61
62impl<T> Default for ShortBoxSliceInner<T> {
63 fn default() -> Self {
64 use ShortBoxSliceInner::*;
65 ZeroOne(None)
66 }
67}
68
69#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
73pub(crate) struct ShortBoxSlice<T>(ShortBoxSliceInner<T>);
74
75impl<T> Default for ShortBoxSlice<T> {
76 fn default() -> Self {
77 Self(Default::default())
78 }
79}
80
81impl<T> ShortBoxSlice<T> {
82 #[inline]
84 pub const fn new() -> Self {
85 use ShortBoxSliceInner::*;
86 Self(ZeroOne(None))
87 }
88
89 #[inline]
91 pub const fn new_single(item: T) -> Self {
92 use ShortBoxSliceInner::*;
93 Self(ZeroOne(Some(item)))
94 }
95
96 #[cfg(feature = "alloc")]
100 pub fn push(&mut self, item: T) {
101 use ShortBoxSliceInner::*;
102 self.0 = match core::mem::replace(&mut self.0, ZeroOne(None)) {
103 ZeroOne(None) => ZeroOne(Some(item)),
104 ZeroOne(Some(prev_item)) => Multi(vec![prev_item, item].into_boxed_slice()),
105 Multi(items) => {
106 let mut items = items.into_vec();
107 items.push(item);
108 Multi(items.into_boxed_slice())
109 }
110 };
111 }
112
113 #[inline]
117 pub const fn single(&self) -> Option<&T> {
118 use ShortBoxSliceInner::*;
119 match self.0 {
120 ZeroOne(Some(ref v)) => Some(v),
121 _ => None,
122 }
123 }
124
125 pub fn into_single(self) -> Option<T> {
129 use ShortBoxSliceInner::*;
130 match self.0 {
131 ZeroOne(Some(v)) => Some(v),
132 _ => None,
133 }
134 }
135
136 #[inline]
138 pub fn len(&self) -> usize {
139 use ShortBoxSliceInner::*;
140 match self.0 {
141 ZeroOne(None) => 0,
142 ZeroOne(_) => 1,
143 #[cfg(feature = "alloc")]
144 Multi(ref v) => v.len(),
145 }
146 }
147
148 #[inline]
150 pub const fn is_empty(&self) -> bool {
151 use ShortBoxSliceInner::*;
152 matches!(self.0, ZeroOne(None))
153 }
154
155 #[cfg(feature = "alloc")]
159 pub fn insert(&mut self, index: usize, elt: T) {
160 use ShortBoxSliceInner::*;
161 assert!(
162 index <= self.len(),
163 "insertion index (is {}) should be <= len (is {})",
164 index,
165 self.len()
166 );
167
168 self.0 = match core::mem::replace(&mut self.0, ZeroOne(None)) {
169 ZeroOne(None) => ZeroOne(Some(elt)),
170 ZeroOne(Some(item)) => {
171 let items = if index == 0 {
172 vec![elt, item].into_boxed_slice()
173 } else {
174 vec![item, elt].into_boxed_slice()
175 };
176 Multi(items)
177 }
178 Multi(items) => {
179 let mut items = items.into_vec();
180 items.insert(index, elt);
181 Multi(items.into_boxed_slice())
182 }
183 }
184 }
185
186 pub fn remove(&mut self, index: usize) -> T {
190 use ShortBoxSliceInner::*;
191 assert!(
192 index < self.len(),
193 "removal index (is {}) should be < len (is {})",
194 index,
195 self.len()
196 );
197
198 let (replaced, removed_item) = match core::mem::replace(&mut self.0, ZeroOne(None)) {
199 ZeroOne(None) => unreachable!(),
200 ZeroOne(Some(v)) => (ZeroOne(None), v),
201 #[cfg(feature = "alloc")]
202 Multi(v) => {
203 let mut v = v.into_vec();
204 let removed_item = v.remove(index);
205 match v.len() {
206 #[allow(clippy::unwrap_used)]
207 1 => (ZeroOne(Some(v.pop().unwrap())), removed_item),
209 _ => (Multi(v.into_boxed_slice()), removed_item),
211 }
212 }
213 };
214 self.0 = replaced;
215 removed_item
216 }
217
218 #[inline]
220 pub fn clear(&mut self) {
221 use ShortBoxSliceInner::*;
222 let _ = core::mem::replace(&mut self.0, ZeroOne(None));
223 }
224
225 #[allow(dead_code)]
227 pub fn retain<F>(&mut self, mut f: F)
228 where
229 F: FnMut(&T) -> bool,
230 {
231 use ShortBoxSliceInner::*;
232 match core::mem::take(&mut self.0) {
233 ZeroOne(Some(one)) if f(&one) => self.0 = ZeroOne(Some(one)),
234 ZeroOne(_) => self.0 = ZeroOne(None),
235 #[cfg(feature = "alloc")]
236 Multi(slice) => {
237 let mut vec = slice.into_vec();
238 vec.retain(f);
239 *self = ShortBoxSlice::from(vec)
240 }
241 };
242 }
243}
244
245impl<T> Deref for ShortBoxSlice<T> {
246 type Target = [T];
247
248 fn deref(&self) -> &Self::Target {
249 use ShortBoxSliceInner::*;
250 match self.0 {
251 ZeroOne(None) => &[],
252 ZeroOne(Some(ref v)) => core::slice::from_ref(v),
253 #[cfg(feature = "alloc")]
254 Multi(ref v) => v,
255 }
256 }
257}
258
259impl<T> DerefMut for ShortBoxSlice<T> {
260 fn deref_mut(&mut self) -> &mut Self::Target {
261 use ShortBoxSliceInner::*;
262 match self.0 {
263 ZeroOne(None) => &mut [],
264 ZeroOne(Some(ref mut v)) => core::slice::from_mut(v),
265 #[cfg(feature = "alloc")]
266 Multi(ref mut v) => v,
267 }
268 }
269}
270
271#[cfg(feature = "alloc")]
272impl<T> From<Vec<T>> for ShortBoxSlice<T> {
273 fn from(v: Vec<T>) -> Self {
274 use ShortBoxSliceInner::*;
275 match v.len() {
276 0 => Self(ZeroOne(None)),
277 #[allow(clippy::unwrap_used)] 1 => Self(ZeroOne(Some(v.into_iter().next().unwrap()))),
279 _ => Self(Multi(v.into_boxed_slice())),
280 }
281 }
282}
283
284#[cfg(feature = "alloc")]
285impl<T> FromIterator<T> for ShortBoxSlice<T> {
286 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
287 use ShortBoxSliceInner::*;
288 let mut iter = iter.into_iter();
289 match (iter.next(), iter.next()) {
290 (Some(first), Some(second)) => {
291 let mut vec = Vec::with_capacity(iter.size_hint().0.saturating_add(3));
293 vec.push(first);
294 vec.push(second);
295 vec.extend(iter);
296 Self(Multi(vec.into_boxed_slice()))
297 }
298 (first, _) => Self(ZeroOne(first)),
299 }
300 }
301}
302
303#[derive(Debug)]
305pub struct ShortBoxSliceIntoIter<T>(ShortBoxSliceIntoIterInner<T>);
306
307#[derive(Debug)]
308pub(crate) enum ShortBoxSliceIntoIterInner<T> {
309 ZeroOne(Option<T>),
310 #[cfg(feature = "alloc")]
311 Multi(alloc::vec::IntoIter<T>),
312}
313
314impl<T> Iterator for ShortBoxSliceIntoIter<T> {
315 type Item = T;
316 fn next(&mut self) -> Option<T> {
317 use ShortBoxSliceIntoIterInner::*;
318 match &mut self.0 {
319 ZeroOne(option) => option.take(),
320 #[cfg(feature = "alloc")]
321 Multi(into_iter) => into_iter.next(),
322 }
323 }
324}
325
326impl<T> IntoIterator for ShortBoxSlice<T> {
327 type Item = T;
328 type IntoIter = ShortBoxSliceIntoIter<T>;
329
330 fn into_iter(self) -> Self::IntoIter {
331 match self.0 {
332 ShortBoxSliceInner::ZeroOne(option) => {
333 ShortBoxSliceIntoIter(ShortBoxSliceIntoIterInner::ZeroOne(option))
334 }
335 #[cfg(feature = "alloc")]
338 ShortBoxSliceInner::Multi(boxed_slice) => ShortBoxSliceIntoIter(
339 ShortBoxSliceIntoIterInner::Multi(boxed_slice.into_vec().into_iter()),
340 ),
341 }
342 }
343}
344
345#[cfg(test)]
346mod tests {
347 use super::*;
348
349 #[test]
350 #[allow(clippy::get_first)]
351 fn test_new_single_const() {
352 const MY_CONST_SLICE: ShortBoxSlice<i32> = ShortBoxSlice::new_single(42);
353
354 assert_eq!(MY_CONST_SLICE.len(), 1);
355 assert_eq!(MY_CONST_SLICE.get(0), Some(&42));
356 }
357
358 #[test]
359 #[allow(clippy::redundant_pattern_matching)]
360 fn test_get_single() {
361 let mut vec = ShortBoxSlice::new();
362 assert!(matches!(vec.single(), None));
363
364 vec.push(100);
365 assert!(matches!(vec.single(), Some(_)));
366
367 vec.push(200);
368 assert!(matches!(vec.single(), None));
369 }
370}