icu_locale_core/shortvec/
mod.rs1mod 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(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ShortBoxSliceInner<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ShortBoxSliceInner::ZeroOne(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ZeroOne", &__self_0),
ShortBoxSliceInner::Two(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Two",
&__self_0),
}
}
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for ShortBoxSliceInner<T> {
#[inline]
fn clone(&self) -> ShortBoxSliceInner<T> {
match self {
ShortBoxSliceInner::ZeroOne(__self_0) =>
ShortBoxSliceInner::ZeroOne(::core::clone::Clone::clone(__self_0)),
ShortBoxSliceInner::Two(__self_0) =>
ShortBoxSliceInner::Two(::core::clone::Clone::clone(__self_0)),
}
}
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for
ShortBoxSliceInner<T> {
#[inline]
fn eq(&self, other: &ShortBoxSliceInner<T>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(ShortBoxSliceInner::ZeroOne(__self_0),
ShortBoxSliceInner::ZeroOne(__arg1_0)) =>
__self_0 == __arg1_0,
(ShortBoxSliceInner::Two(__self_0),
ShortBoxSliceInner::Two(__arg1_0)) => __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for ShortBoxSliceInner<T> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<Option<T>>;
let _: ::core::cmp::AssertParamIsEq<[T; 2]>;
}
}Eq, #[automatically_derived]
impl<T: ::core::hash::Hash> ::core::hash::Hash for ShortBoxSliceInner<T> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
ShortBoxSliceInner::ZeroOne(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
ShortBoxSliceInner::Two(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}Hash, #[automatically_derived]
impl<T: ::core::cmp::PartialOrd> ::core::cmp::PartialOrd for
ShortBoxSliceInner<T> {
#[inline]
fn partial_cmp(&self, other: &ShortBoxSliceInner<T>)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(ShortBoxSliceInner::ZeroOne(__self_0),
ShortBoxSliceInner::ZeroOne(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(ShortBoxSliceInner::Two(__self_0),
ShortBoxSliceInner::Two(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd, #[automatically_derived]
impl<T: ::core::cmp::Ord> ::core::cmp::Ord for ShortBoxSliceInner<T> {
#[inline]
fn cmp(&self, other: &ShortBoxSliceInner<T>) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(ShortBoxSliceInner::ZeroOne(__self_0),
ShortBoxSliceInner::ZeroOne(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(ShortBoxSliceInner::Two(__self_0),
ShortBoxSliceInner::Two(__arg1_0)) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}Ord)]
56pub(crate) enum ShortBoxSliceInner<T> {
57 ZeroOne(Option<T>),
58 #[cfg(feature = "alloc")]
59 Multi(Box<[T]>),
60 #[cfg(not(feature = "alloc"))]
61 Two([T; 2]),
62}
63
64impl<T> Default for ShortBoxSliceInner<T> {
65 fn default() -> Self {
66 use ShortBoxSliceInner::*;
67 ZeroOne(None)
68 }
69}
70
71#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ShortBoxSlice<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "ShortBoxSlice",
&&self.0)
}
}Debug, #[automatically_derived]
impl<T: ::core::clone::Clone> ::core::clone::Clone for ShortBoxSlice<T> {
#[inline]
fn clone(&self) -> ShortBoxSlice<T> {
ShortBoxSlice(::core::clone::Clone::clone(&self.0))
}
}Clone, #[automatically_derived]
impl<T: ::core::cmp::PartialEq> ::core::cmp::PartialEq for ShortBoxSlice<T> {
#[inline]
fn eq(&self, other: &ShortBoxSlice<T>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<T: ::core::cmp::Eq> ::core::cmp::Eq for ShortBoxSlice<T> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_receiver_is_total_eq(&self) -> () {
let _: ::core::cmp::AssertParamIsEq<ShortBoxSliceInner<T>>;
}
}Eq, #[automatically_derived]
impl<T: ::core::hash::Hash> ::core::hash::Hash for ShortBoxSlice<T> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, #[automatically_derived]
impl<T: ::core::cmp::PartialOrd> ::core::cmp::PartialOrd for ShortBoxSlice<T>
{
#[inline]
fn partial_cmp(&self, other: &ShortBoxSlice<T>)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0)
}
}PartialOrd, #[automatically_derived]
impl<T: ::core::cmp::Ord> ::core::cmp::Ord for ShortBoxSlice<T> {
#[inline]
fn cmp(&self, other: &ShortBoxSlice<T>) -> ::core::cmp::Ordering {
::core::cmp::Ord::cmp(&self.0, &other.0)
}
}Ord)]
75pub(crate) struct ShortBoxSlice<T>(ShortBoxSliceInner<T>);
76
77impl<T> Default for ShortBoxSlice<T> {
78 fn default() -> Self {
79 Self(Default::default())
80 }
81}
82
83impl<T> ShortBoxSlice<T> {
84 #[inline]
86 pub const fn new() -> Self {
87 use ShortBoxSliceInner::*;
88 Self(ZeroOne(None))
89 }
90
91 #[inline]
93 pub const fn new_single(item: T) -> Self {
94 use ShortBoxSliceInner::*;
95 Self(ZeroOne(Some(item)))
96 }
97
98 pub fn new_double(first: T, second: T) -> Self {
99 use ShortBoxSliceInner::*;
100 #[cfg(feature = "alloc")]
101 return Self(Multi(vec![first, second].into_boxed_slice()));
102 #[cfg(not(feature = "alloc"))]
103 return Self(Two([first, second]));
104 }
105
106 #[cfg(feature = "alloc")]
110 pub fn push(&mut self, item: T) {
111 use ShortBoxSliceInner::*;
112 self.0 = match core::mem::replace(&mut self.0, ZeroOne(None)) {
113 ZeroOne(None) => ZeroOne(Some(item)),
114 ZeroOne(Some(prev_item)) => Multi(vec![prev_item, item].into_boxed_slice()),
115 Multi(items) => {
116 let mut items = items.into_vec();
117 items.push(item);
118 Multi(items.into_boxed_slice())
119 }
120 };
121 }
122
123 #[inline]
127 pub const fn single(&self) -> Option<&T> {
128 use ShortBoxSliceInner::*;
129 match self.0 {
130 ZeroOne(Some(ref v)) => Some(v),
131 _ => None,
132 }
133 }
134
135 pub fn into_single(self) -> Option<T> {
139 use ShortBoxSliceInner::*;
140 match self.0 {
141 ZeroOne(Some(v)) => Some(v),
142 _ => None,
143 }
144 }
145
146 #[inline]
148 pub fn len(&self) -> usize {
149 use ShortBoxSliceInner::*;
150 match self.0 {
151 ZeroOne(None) => 0,
152 ZeroOne(_) => 1,
153 #[cfg(feature = "alloc")]
154 Multi(ref v) => v.len(),
155 #[cfg(not(feature = "alloc"))]
156 Two(_) => 2,
157 }
158 }
159
160 #[inline]
162 pub const fn is_empty(&self) -> bool {
163 use ShortBoxSliceInner::*;
164 #[allow(non_exhaustive_omitted_patterns)] match self.0 {
ZeroOne(None) => true,
_ => false,
}matches!(self.0, ZeroOne(None))
165 }
166
167 #[cfg(feature = "alloc")]
171 pub fn insert(&mut self, index: usize, elt: T) {
172 use ShortBoxSliceInner::*;
173 assert!(
174 index <= self.len(),
175 "insertion index (is {}) should be <= len (is {})",
176 index,
177 self.len()
178 );
179
180 self.0 = match core::mem::replace(&mut self.0, ZeroOne(None)) {
181 ZeroOne(None) => ZeroOne(Some(elt)),
182 ZeroOne(Some(item)) => {
183 let items = if index == 0 {
184 vec![elt, item].into_boxed_slice()
185 } else {
186 vec![item, elt].into_boxed_slice()
187 };
188 Multi(items)
189 }
190 Multi(items) => {
191 let mut items = items.into_vec();
192 items.insert(index, elt);
193 Multi(items.into_boxed_slice())
194 }
195 }
196 }
197
198 pub fn remove(&mut self, index: usize) -> T {
202 use ShortBoxSliceInner::*;
203 if !(index < self.len()) {
{
::core::panicking::panic_fmt(format_args!("removal index (is {0}) should be < len (is {1})",
index, self.len()));
}
};assert!(
204 index < self.len(),
205 "removal index (is {}) should be < len (is {})",
206 index,
207 self.len()
208 );
209
210 let (replaced, removed_item) = match core::mem::replace(&mut self.0, ZeroOne(None)) {
211 ZeroOne(None) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
212 ZeroOne(Some(v)) => (ZeroOne(None), v),
213 #[cfg(feature = "alloc")]
214 Multi(v) => {
215 let mut v = v.into_vec();
216 let removed_item = v.remove(index);
217 match v.len() {
218 #[expect(clippy::unwrap_used)]
219 1 => (ZeroOne(Some(v.pop().unwrap())), removed_item),
221 _ => (Multi(v.into_boxed_slice()), removed_item),
223 }
224 }
225 #[cfg(not(feature = "alloc"))]
226 Two([f, s]) => (ZeroOne(Some(f)), s),
227 };
228 self.0 = replaced;
229 removed_item
230 }
231
232 #[inline]
234 pub fn clear(&mut self) {
235 use ShortBoxSliceInner::*;
236 let _ = core::mem::replace(&mut self.0, ZeroOne(None));
237 }
238
239 #[allow(dead_code)]
241 pub fn retain<F>(&mut self, mut f: F)
242 where
243 F: FnMut(&T) -> bool,
244 {
245 use ShortBoxSliceInner::*;
246 match core::mem::take(&mut self.0) {
247 ZeroOne(Some(one)) if f(&one) => self.0 = ZeroOne(Some(one)),
248 ZeroOne(_) => self.0 = ZeroOne(None),
249 #[cfg(feature = "alloc")]
250 Multi(slice) => {
251 let mut vec = slice.into_vec();
252 vec.retain(f);
253 *self = ShortBoxSlice::from(vec)
254 }
255 #[cfg(not(feature = "alloc"))]
256 Two([first, second]) => {
257 *self = match (Some(first).filter(&mut f), Some(second).filter(&mut f)) {
258 (None, None) => ShortBoxSlice::new(),
259 (None, Some(x)) | (Some(x), None) => ShortBoxSlice::new_single(x),
260 (Some(f), Some(s)) => ShortBoxSlice::new_double(f, s),
261 }
262 }
263 };
264 }
265}
266
267impl<T> Deref for ShortBoxSlice<T> {
268 type Target = [T];
269
270 fn deref(&self) -> &Self::Target {
271 use ShortBoxSliceInner::*;
272 match self.0 {
273 ZeroOne(None) => &[],
274 ZeroOne(Some(ref v)) => core::slice::from_ref(v),
275 #[cfg(feature = "alloc")]
276 Multi(ref v) => v,
277 #[cfg(not(feature = "alloc"))]
278 Two(ref v) => v,
279 }
280 }
281}
282
283impl<T> DerefMut for ShortBoxSlice<T> {
284 fn deref_mut(&mut self) -> &mut Self::Target {
285 use ShortBoxSliceInner::*;
286 match self.0 {
287 ZeroOne(None) => &mut [],
288 ZeroOne(Some(ref mut v)) => core::slice::from_mut(v),
289 #[cfg(feature = "alloc")]
290 Multi(ref mut v) => v,
291 #[cfg(not(feature = "alloc"))]
292 Two(ref mut v) => v,
293 }
294 }
295}
296
297#[cfg(feature = "alloc")]
298impl<T> From<Vec<T>> for ShortBoxSlice<T> {
299 fn from(v: Vec<T>) -> Self {
300 use ShortBoxSliceInner::*;
301 match v.len() {
302 0 => Self(ZeroOne(None)),
303 #[expect(clippy::unwrap_used)] 1 => Self(ZeroOne(Some(v.into_iter().next().unwrap()))),
305 _ => Self(Multi(v.into_boxed_slice())),
306 }
307 }
308}
309
310#[cfg(feature = "alloc")]
311impl<T> FromIterator<T> for ShortBoxSlice<T> {
312 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
313 use ShortBoxSliceInner::*;
314 let mut iter = iter.into_iter();
315 match (iter.next(), iter.next()) {
316 (Some(first), Some(second)) => {
317 let mut vec = Vec::with_capacity(iter.size_hint().0.saturating_add(3));
319 vec.push(first);
320 vec.push(second);
321 vec.extend(iter);
322 Self(Multi(vec.into_boxed_slice()))
323 }
324 (first, _) => Self(ZeroOne(first)),
325 }
326 }
327}
328
329#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for ShortBoxSliceIntoIter<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ShortBoxSliceIntoIter", &&self.0)
}
}Debug)]
331pub struct ShortBoxSliceIntoIter<T>(ShortBoxSliceIntoIterInner<T>);
332
333#[derive(#[automatically_derived]
impl<T: ::core::fmt::Debug> ::core::fmt::Debug for
ShortBoxSliceIntoIterInner<T> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
ShortBoxSliceIntoIterInner::ZeroOne(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"ZeroOne", &__self_0),
ShortBoxSliceIntoIterInner::Two(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Two",
&__self_0),
}
}
}Debug)]
334pub(crate) enum ShortBoxSliceIntoIterInner<T> {
335 ZeroOne(Option<T>),
336 #[cfg(feature = "alloc")]
337 Multi(alloc::vec::IntoIter<T>),
338 #[cfg(not(feature = "alloc"))]
339 Two(core::array::IntoIter<T, 2>),
340}
341
342impl<T> Iterator for ShortBoxSliceIntoIter<T> {
343 type Item = T;
344 fn next(&mut self) -> Option<T> {
345 use ShortBoxSliceIntoIterInner::*;
346 match &mut self.0 {
347 ZeroOne(option) => option.take(),
348 #[cfg(feature = "alloc")]
349 Multi(into_iter) => into_iter.next(),
350 #[cfg(not(feature = "alloc"))]
351 Two(into_iter) => into_iter.next(),
352 }
353 }
354}
355
356impl<T> IntoIterator for ShortBoxSlice<T> {
357 type Item = T;
358 type IntoIter = ShortBoxSliceIntoIter<T>;
359
360 fn into_iter(self) -> Self::IntoIter {
361 match self.0 {
362 ShortBoxSliceInner::ZeroOne(option) => {
363 ShortBoxSliceIntoIter(ShortBoxSliceIntoIterInner::ZeroOne(option))
364 }
365 #[cfg(feature = "alloc")]
368 ShortBoxSliceInner::Multi(boxed_slice) => ShortBoxSliceIntoIter(
369 ShortBoxSliceIntoIterInner::Multi(boxed_slice.into_vec().into_iter()),
370 ),
371 #[cfg(not(feature = "alloc"))]
372 ShortBoxSliceInner::Two(arr) => {
373 ShortBoxSliceIntoIter(ShortBoxSliceIntoIterInner::Two(arr.into_iter()))
374 }
375 }
376 }
377}
378
379#[cfg(test)]
380mod tests {
381 use super::*;
382
383 #[test]
384 #[expect(clippy::get_first)]
385 fn test_new_single_const() {
386 const MY_CONST_SLICE: ShortBoxSlice<i32> = ShortBoxSlice::new_single(42);
387
388 assert_eq!(MY_CONST_SLICE.len(), 1);
389 assert_eq!(MY_CONST_SLICE.get(0), Some(&42));
390 }
391
392 #[test]
393 #[expect(clippy::redundant_pattern_matching)]
394 fn test_get_single() {
395 let mut vec = ShortBoxSlice::new();
396 assert!(matches!(vec.single(), None));
397
398 vec.push(100);
399 assert!(matches!(vec.single(), Some(_)));
400
401 vec.push(200);
402 assert!(matches!(vec.single(), None));
403 }
404}