Skip to main content

one_or_many/
lib.rs

1#![deny(clippy::missing_inline_in_public_items)]
2
3mod iter;
4pub use iter::Iter;
5#[cfg(feature = "surrealdb")]
6mod query_result_impl;
7
8use std::{
9    clone::Clone,
10    ops::{Index, IndexMut},
11    slice::SliceIndex,
12};
13
14#[cfg(feature = "serde")]
15use serde::{Deserialize, Serialize};
16
17/// A type that can be either one value, many values, or no values.
18///
19/// Especially useful when working with deserialing data
20///
21/// To let it be useful in other contexts, it aims to implement many of the same traits and functions as `Vec<T>` and `Option<T>`.
22#[derive(Debug, PartialEq, Eq, Default)]
23#[cfg_attr(feature = "serde", derive(Serialize))]
24#[cfg_attr(feature = "serde", serde(untagged))]
25pub enum OneOrMany<T> {
26    One(Box<T>),
27    Many(Vec<T>),
28    #[default]
29    None,
30}
31
32#[cfg(feature = "serde")]
33impl<'de, T> Deserialize<'de> for OneOrMany<T>
34where
35    T: Deserialize<'de> + Clone,
36{
37    #[inline]
38    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
39    where
40        D: serde::Deserializer<'de>,
41    {
42        #[derive(Deserialize)]
43        #[serde(untagged)]
44        enum Inner<T> {
45            One(Box<T>),
46            Many(Vec<T>),
47            None,
48        }
49
50        let inner = Inner::deserialize(deserializer)?;
51        Ok(match inner {
52            Inner::One(t) => Self::One(t),
53            Inner::Many(t) if t.is_empty() => Self::None,
54            Inner::Many(t) if t.len() == 1 => Self::One(Box::new(t[0].clone())),
55            Inner::Many(t) => Self::Many(t),
56            Inner::None => Self::None,
57        })
58    }
59}
60
61impl<T> OneOrMany<T> {
62    /// Returns the number of elements in the `OneOrMany`.
63    #[inline]
64    #[must_use]
65    pub const fn len(&self) -> usize {
66        match self {
67            Self::One(_) => 1,
68            Self::Many(t) => t.len(),
69            Self::None => 0,
70        }
71    }
72
73    /// Returns `true` if the `OneOrMany` is empty.
74    #[inline]
75    #[must_use]
76    pub const fn is_empty(&self) -> bool {
77        self.len() == 0
78    }
79
80    /// Returns the value at the given index, or `None` if the index is out of bounds.
81    #[inline]
82    #[must_use]
83    pub fn get(&self, index: usize) -> Option<&T> {
84        match self {
85            Self::One(t) if index == 0 => Some(t),
86            Self::One(_) | Self::None => None,
87            Self::Many(t) => t.get(index),
88        }
89    }
90
91    /// Returns the first value, or `None` if the `OneOrMany` is empty.
92    #[inline]
93    #[must_use]
94    pub const fn first(&self) -> Option<&T> {
95        match self {
96            Self::One(t) => Some(t),
97            Self::Many(v) => v.as_slice().first(),
98            Self::None => None,
99        }
100    }
101
102    /// Returns `true` if the `OneOrMany` contains the given value.
103    #[inline]
104    pub fn contains(&self, genre: &T) -> bool
105    where
106        T: PartialEq,
107    {
108        match self {
109            Self::One(t) => t.as_ref() == genre,
110            Self::Many(t) => t.contains(genre),
111            Self::None => false,
112        }
113    }
114
115    /// Pushes a new value onto the end of the `OneOrMany`.
116    #[inline]
117    pub fn push(&mut self, new: T)
118    where
119        T: ToOwned<Owned = T>,
120    {
121        match self {
122            Self::One(t) => {
123                *self = Self::Many(vec![t.to_owned(), new]);
124            }
125            Self::Many(t) => t.push(new),
126            Self::None => *self = Self::One(Box::new(new)),
127        }
128    }
129
130    /// Pops a value from the end of the `OneOrMany`.
131    #[inline]
132    pub fn pop(&mut self) -> Option<T>
133    where
134        T: ToOwned<Owned = T>,
135    {
136        match self {
137            Self::One(t) => {
138                let old = t.to_owned();
139                *self = Self::None;
140                Some(old)
141            }
142            Self::Many(t) => {
143                let old = t.pop();
144                if t.len() == 1 {
145                    *self = Self::One(Box::new(t[0].to_owned()));
146                }
147                old
148            }
149            Self::None => None,
150        }
151    }
152
153    /// Checks if the `OneOrMany` is `None`.
154    #[inline]
155    #[must_use]
156    pub const fn is_none(&self) -> bool {
157        matches!(self, Self::None)
158    }
159
160    /// Checks if the `OneOrMany` is `One`.
161    #[inline]
162    #[must_use]
163    pub const fn is_one(&self) -> bool {
164        matches!(self, Self::One(_))
165    }
166
167    /// Checks if the `OneOrMany` is `Many`.
168    #[inline]
169    #[must_use]
170    pub const fn is_many(&self) -> bool {
171        matches!(self, Self::Many(_))
172    }
173
174    /// Checks if the `OneOrMany` is `One` or `Many`.
175    #[inline]
176    #[must_use]
177    pub const fn is_some(&self) -> bool {
178        self.is_one() || self.is_many()
179    }
180
181    /// Gets a slice of the `OneOrMany`.
182    #[inline]
183    #[must_use]
184    pub const fn as_slice(&self) -> &[T] {
185        match self {
186            Self::One(t) => std::slice::from_ref(t),
187            Self::Many(t) => t.as_slice(),
188            Self::None => &[],
189        }
190    }
191
192    /// Gets a mutable slice of the `OneOrMany`.
193    #[inline]
194    pub fn as_mut_slice(&mut self) -> &mut [T] {
195        match self {
196            Self::One(t) => std::slice::from_mut(t),
197            Self::Many(t) => t.as_mut_slice(),
198            Self::None => &mut [],
199        }
200    }
201
202    /// remove duplicates from the `OneOrMany`
203    ///
204    /// internally converts to a `HashSet` and back
205    #[inline]
206    pub fn dedup(&mut self)
207    where
208        T: Clone + Eq + std::hash::Hash,
209    {
210        let mut set = std::collections::HashSet::new();
211        let mut new = Vec::new();
212        for t in self.as_slice() {
213            if set.insert(t) {
214                new.push(t.clone());
215            }
216        }
217        *self = Self::from(new);
218    }
219
220    /// remove duplicates from the `OneOrMany` by some key
221    ///
222    /// internally converts to a `HashSet` and back
223    #[inline]
224    pub fn dedup_by_key<F, K>(&mut self, mut key: F)
225    where
226        F: FnMut(&T) -> K,
227        K: Eq + std::hash::Hash,
228        T: Clone,
229    {
230        let mut set = std::collections::HashSet::new();
231        let mut new = Vec::new();
232        for t in self.as_slice() {
233            let key = key(t);
234            if set.insert(key) {
235                new.push(t.to_owned());
236            }
237        }
238        *self = Self::from(new);
239    }
240}
241
242impl<T: Clone> Clone for OneOrMany<T> {
243    #[inline]
244    fn clone(&self) -> Self {
245        match self {
246            Self::One(t) => Self::One(t.clone()),
247            Self::Many(t) => Self::Many(t.clone()),
248            Self::None => Self::None,
249        }
250    }
251}
252
253impl<T> From<T> for OneOrMany<T> {
254    #[inline]
255    fn from(t: T) -> Self {
256        Self::One(Box::new(t))
257    }
258}
259
260impl<T> From<Box<T>> for OneOrMany<T> {
261    #[inline]
262    fn from(t: Box<T>) -> Self {
263        Self::One(t)
264    }
265}
266
267impl<T> From<Option<T>> for OneOrMany<T> {
268    #[inline]
269    fn from(t: Option<T>) -> Self {
270        t.map(Box::new).map_or(Self::None, Self::One)
271    }
272}
273impl<T> From<Option<Box<T>>> for OneOrMany<T> {
274    #[inline]
275    fn from(t: Option<Box<T>>) -> Self {
276        t.map_or(Self::None, Self::One)
277    }
278}
279
280impl<T> From<Option<Vec<T>>> for OneOrMany<T> {
281    #[inline]
282    fn from(t: Option<Vec<T>>) -> Self {
283        t.map_or(Self::None, Into::into)
284    }
285}
286
287impl<T> From<Option<Self>> for OneOrMany<T> {
288    #[inline]
289    fn from(t: Option<Self>) -> Self {
290        t.unwrap_or(Self::None)
291    }
292}
293
294impl<T: Clone> From<&[T]> for OneOrMany<T> {
295    #[inline]
296    fn from(t: &[T]) -> Self {
297        if t.is_empty() {
298            Self::None
299        } else if t.len() == 1 {
300            Self::One(Box::new(t[0].clone()))
301        } else {
302            Self::Many(t.into())
303        }
304    }
305}
306
307impl<T> From<Vec<T>> for OneOrMany<T> {
308    #[inline]
309    fn from(t: Vec<T>) -> Self {
310        if t.len() <= 1 {
311            t.into_iter()
312                .next()
313                .map(Box::new)
314                .map_or(Self::None, Self::One)
315        } else {
316            Self::Many(t)
317        }
318    }
319}
320
321impl<T> From<OneOrMany<T>> for Vec<T> {
322    #[inline]
323    fn from(value: OneOrMany<T>) -> Self {
324        match value {
325            OneOrMany::One(one) => vec![*one],
326            OneOrMany::Many(many) => many,
327            OneOrMany::None => vec![],
328        }
329    }
330}
331
332// implement index traits by delegating to the slice
333impl<T, I: SliceIndex<[T]>> Index<I> for OneOrMany<T> {
334    type Output = I::Output;
335
336    #[inline]
337    fn index(&self, index: I) -> &Self::Output {
338        Index::index(self.as_slice(), index)
339    }
340}
341impl<T, I: SliceIndex<[T]>> IndexMut<I> for OneOrMany<T> {
342    #[inline]
343    fn index_mut(&mut self, index: I) -> &mut Self::Output {
344        IndexMut::index_mut(self.as_mut_slice(), index)
345    }
346}
347
348// implement partial ord
349// None < One < Many
350impl<T> PartialOrd<Self> for OneOrMany<T>
351where
352    T: PartialOrd,
353{
354    #[inline]
355    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
356        match (self, other) {
357            (Self::One(t1), Self::One(t2)) => t1.partial_cmp(t2),
358            (Self::Many(t1), Self::Many(t2)) => t1.partial_cmp(t2),
359            (Self::None, Self::None) => Some(std::cmp::Ordering::Equal),
360            (Self::None, _) => Some(std::cmp::Ordering::Less),
361            (_, Self::None) => Some(std::cmp::Ordering::Greater),
362            (Self::One(_), _) => Some(std::cmp::Ordering::Less),
363            (_, Self::One(_)) => Some(std::cmp::Ordering::Greater),
364        }
365    }
366}
367
368// implement ord
369// None < One < Many
370impl<T> Ord for OneOrMany<T>
371where
372    T: Ord,
373{
374    #[inline]
375    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
376        match (self, other) {
377            (Self::One(t1), Self::One(t2)) => t1.cmp(t2),
378            (Self::Many(t1), Self::Many(t2)) => t1.cmp(t2),
379            (Self::None, Self::None) => std::cmp::Ordering::Equal,
380            (Self::None, _) => std::cmp::Ordering::Less,
381            (_, Self::None) => std::cmp::Ordering::Greater,
382            (Self::One(_), _) => std::cmp::Ordering::Less,
383            (_, Self::One(_)) => std::cmp::Ordering::Greater,
384        }
385    }
386}
387
388// implement Extend
389impl<T> Extend<T> for OneOrMany<T>
390where
391    T: ToOwned<Owned = T>,
392{
393    #[inline]
394    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
395        for item in iter {
396            self.push(item);
397        }
398    }
399}
400
401// implement Hash
402impl<T> std::hash::Hash for OneOrMany<T>
403where
404    T: std::hash::Hash,
405{
406    #[inline]
407    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
408        match self {
409            Self::One(t) => {
410                1u8.hash(state);
411                t.hash(state);
412            }
413            Self::Many(t) => {
414                2u8.hash(state);
415                t.hash(state);
416            }
417            Self::None => {
418                0u8.hash(state);
419            }
420        }
421    }
422}
423
424#[cfg(test)]
425mod tests {
426    use super::*;
427    use pretty_assertions::{assert_eq, assert_ne};
428    use rstest::rstest;
429
430    #[rstest]
431    #[case::none(OneOrMany::<usize>::None, "null")]
432    #[case::none(OneOrMany::<usize>::None, "[]")]
433    #[case::one(OneOrMany::from(1), "1")]
434    #[case::one(OneOrMany::from(1), "[1]")]
435    #[case::many(OneOrMany::Many(vec![1, 2, 3]), "[1, 2, 3]")]
436    fn test_deserialize(#[case] expected: OneOrMany<usize>, #[case] input: &str)
437    where
438        usize: serde::de::DeserializeOwned,
439    {
440        let actual: OneOrMany<usize> = serde_json::from_str(input).unwrap();
441        assert_eq!(actual, expected);
442    }
443
444    #[rstest]
445    #[case::none(OneOrMany::<usize>::None, 0)]
446    #[case::one(OneOrMany::from(1), 1)]
447    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 3)]
448    fn test_len<T>(#[case] input: OneOrMany<T>, #[case] expected: usize) {
449        let actual = input.len();
450        assert_eq!(actual, expected);
451    }
452
453    #[rstest]
454    #[case::none(OneOrMany::<usize>::None, true)]
455    #[case::one(OneOrMany::from(1), false)]
456    #[case::many(OneOrMany::Many(vec![1, 2, 3]), false)]
457    fn test_is_empty<T>(#[case] input: OneOrMany<T>, #[case] expected: bool) {
458        let actual = input.is_empty();
459        assert_eq!(actual, expected);
460    }
461
462    #[rstest]
463    #[case::none(OneOrMany::<usize>::None,0, None)]
464    #[case::none(OneOrMany::<usize>::None,1, None)]
465    #[case::one(OneOrMany::from(1), 0, Some(&1))]
466    #[case::one(OneOrMany::from(1), 1, None)]
467    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0, Some(&1))]
468    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 1, Some(&2))]
469    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 2, Some(&3))]
470    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 3, None)]
471    fn test_get<T>(#[case] input: OneOrMany<T>, #[case] index: usize, #[case] expected: Option<&T>)
472    where
473        T: PartialEq + std::fmt::Debug,
474    {
475        let actual = input.get(index);
476        assert_eq!(actual, expected);
477    }
478
479    #[rstest]
480    #[case::none(OneOrMany::<usize>::None, None)]
481    #[case::one(OneOrMany::from(1), Some(&1))]
482    #[case::many(OneOrMany::Many(vec![1, 2, 3]), Some(&1))]
483    fn test_first<T>(#[case] input: OneOrMany<T>, #[case] expected: Option<&T>)
484    where
485        T: PartialEq + std::fmt::Debug,
486    {
487        let actual = input.first();
488        assert_eq!(actual, expected);
489    }
490
491    #[rstest]
492    #[case::none(OneOrMany::<usize>::None, 2, false)]
493    #[case::one(OneOrMany::from(1), 1, true)]
494    #[case::one(OneOrMany::from(1), 0, false)]
495    #[case::many(OneOrMany::Many(vec![1, 2, 3]),2, true)]
496    #[case::many(OneOrMany::Many(vec![1, 2, 3]),4, false)]
497    fn test_contains<T>(#[case] input: OneOrMany<T>, #[case] value: T, #[case] expected: bool)
498    where
499        T: PartialEq + std::fmt::Debug,
500    {
501        let actual = input.contains(&value);
502        assert_eq!(actual, expected);
503    }
504
505    #[rstest]
506    #[case::none(OneOrMany::<usize>::None, 1, OneOrMany::from(1))]
507    #[case::one(OneOrMany::from(1), 2, OneOrMany::Many(vec![1, 2]))]
508    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 4, OneOrMany::Many(vec![1, 2, 3, 4]))]
509    fn test_push<T>(#[case] mut input: OneOrMany<T>, #[case] new: T, #[case] expected: OneOrMany<T>)
510    where
511        T: Clone + PartialEq + std::fmt::Debug,
512    {
513        input.push(new);
514        assert_eq!(input, expected);
515    }
516
517    #[rstest]
518    #[case::none(OneOrMany::<usize>::None, None, OneOrMany::<usize>::None)]
519    #[case::one(OneOrMany::from(1), Some(1), OneOrMany::<usize>::None)]
520    #[case::many(OneOrMany::Many(vec![1, 2]), Some(2), OneOrMany::from(1))]
521    #[case::many(OneOrMany::Many(vec![1, 2, 3]), Some(3), OneOrMany::Many(vec![1, 2]))]
522    fn test_pop<T>(
523        #[case] mut input: OneOrMany<T>,
524        #[case] expected: Option<T>,
525        #[case] expected_output: OneOrMany<T>,
526    ) where
527        T: Clone + PartialEq + std::fmt::Debug,
528    {
529        let result = input.pop();
530        assert_eq!(result, expected);
531        assert_eq!(input, expected_output);
532    }
533
534    #[rstest]
535    #[case::none(OneOrMany::<usize>::None, true)]
536    #[case::one(OneOrMany::from(1), false)]
537    #[case::many(OneOrMany::Many(vec![1, 2, 3]), false)]
538    fn test_is_none<T>(#[case] input: OneOrMany<T>, #[case] expected: bool)
539    where
540        T: PartialEq + std::fmt::Debug,
541    {
542        let actual = input.is_none();
543        assert_eq!(actual, expected);
544    }
545
546    #[rstest]
547    #[case::none(OneOrMany::<usize>::None, false)]
548    #[case::one(OneOrMany::from(1), true)]
549    #[case::many(OneOrMany::Many(vec![1, 2, 3]), false)]
550    fn test_is_one<T>(#[case] input: OneOrMany<T>, #[case] expected: bool)
551    where
552        T: PartialEq + std::fmt::Debug,
553    {
554        let actual = input.is_one();
555        assert_eq!(actual, expected);
556    }
557
558    #[rstest]
559    #[case::none(OneOrMany::<usize>::None, false)]
560    #[case::one(OneOrMany::from(1), false)]
561    #[case::many(OneOrMany::Many(vec![1, 2, 3]), true)]
562    fn test_is_many<T>(#[case] input: OneOrMany<T>, #[case] expected: bool)
563    where
564        T: PartialEq + std::fmt::Debug,
565    {
566        let actual = input.is_many();
567        assert_eq!(actual, expected);
568    }
569
570    #[rstest]
571    #[case::none(OneOrMany::<usize>::None, false)]
572    #[case::one(OneOrMany::from(1), true)]
573    #[case::many(OneOrMany::Many(vec![1, 2, 3]), true)]
574    fn test_is_some<T>(#[case] input: OneOrMany<T>, #[case] expected: bool)
575    where
576        T: PartialEq + std::fmt::Debug,
577    {
578        let actual = input.is_some();
579        assert_eq!(actual, expected);
580    }
581
582    #[rstest]
583    #[case::none(OneOrMany::<usize>::None, vec![])]
584    #[case::one(OneOrMany::from(1), vec![1])]
585    #[case::many(OneOrMany::Many(vec![1, 2, 3]), vec![1, 2, 3])]
586    fn test_as_slice<T>(#[case] input: OneOrMany<T>, #[case] expected: Vec<T>)
587    where
588        T: PartialEq + std::fmt::Debug,
589    {
590        assert_eq!(input.as_slice(), expected.as_slice());
591    }
592
593    #[rstest]
594    #[case::none(OneOrMany::<usize>::None, vec![])]
595    #[case::one(OneOrMany::from(1), vec![1])]
596    #[case::many(OneOrMany::Many(vec![1, 2, 3]), vec![1, 2, 3])]
597    fn test_as_mut_slice<T>(#[case] mut input: OneOrMany<T>, #[case] mut expected: Vec<T>)
598    where
599        T: PartialEq + std::fmt::Debug,
600    {
601        assert_eq!(input.as_mut_slice(), expected.as_mut_slice());
602    }
603
604    #[rstest]
605    #[case::one(1, OneOrMany::from(1))]
606    fn test_from<T>(#[case] input: T, #[case] expected: OneOrMany<T>)
607    where
608        T: Clone + PartialEq + std::fmt::Debug,
609    {
610        let actual = OneOrMany::from(input);
611        assert_eq!(actual, expected);
612    }
613
614    #[rstest]
615    #[case::none(vec![], OneOrMany::<usize>::None)]
616    #[case::one(vec![1], OneOrMany::from(1))]
617    #[case::many(vec![1, 2, 3], OneOrMany::Many(vec![1, 2, 3]))]
618    fn test_from_vec<T>(#[case] input: Vec<T>, #[case] expected: OneOrMany<T>)
619    where
620        T: PartialEq + std::fmt::Debug,
621    {
622        let actual = OneOrMany::from(input);
623        assert_eq!(actual, expected);
624    }
625
626    #[rstest]
627    #[case::none(&[], OneOrMany::<usize>::None)]
628    #[case::one(&[1], OneOrMany::from(1))]
629    #[case::many(&[1, 2, 3], OneOrMany::Many(vec![1, 2, 3]))]
630    fn test_from_slice<T>(#[case] input: &[T], #[case] expected: OneOrMany<T>)
631    where
632        T: PartialEq + std::fmt::Debug + Clone,
633    {
634        let actual = OneOrMany::from(input);
635        assert_eq!(actual, expected);
636    }
637
638    #[rstest]
639    #[case::none(None, OneOrMany::<usize>::None)]
640    #[case::one(Some(1), OneOrMany::from(1))]
641    fn test_from_option(#[case] input: Option<usize>, #[case] expected: OneOrMany<usize>) {
642        let actual = OneOrMany::from(input);
643        assert_eq!(actual, expected);
644    }
645
646    #[rstest]
647    #[case::none(None, OneOrMany::<usize>::None)]
648    #[case::one(Some(OneOrMany::from(1)), OneOrMany::from(1))]
649    #[case::many(Some(OneOrMany::Many(vec![1, 2, 3])), OneOrMany::Many(vec![1, 2, 3]))]
650    fn test_from_option_self(
651        #[case] input: Option<OneOrMany<usize>>,
652        #[case] expected: OneOrMany<usize>,
653    ) {
654        let actual = OneOrMany::from(input);
655        assert_eq!(actual, expected);
656    }
657
658    #[rstest]
659    #[case::none(Option::<Vec<usize>>::None, OneOrMany::None)]
660    #[case::one(Some(vec![1]), OneOrMany::from(1))]
661    #[case::many(Some(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]))]
662    fn test_from_option_vec(#[case] input: Option<Vec<usize>>, #[case] expected: OneOrMany<usize>) {
663        let actual = OneOrMany::from(input);
664        assert_eq!(actual, expected);
665    }
666
667    #[rstest]
668    #[case::none(OneOrMany::<usize>::None, vec![])]
669    #[case::one(OneOrMany::from(1), vec![1])]
670    #[case::many(OneOrMany::Many(vec![1, 2, 3]), vec![1, 2, 3])]
671    fn test_into_vec(#[case] input: OneOrMany<usize>, #[case] expected: Vec<usize>) {
672        let actual = Vec::from(input);
673        assert_eq!(actual, expected);
674    }
675
676    #[rstest]
677    #[should_panic = "index out of bounds: the len is 0 but the index is 0"]
678    #[case::none(OneOrMany::<usize>::None, 0, 0)]
679    #[case::one(OneOrMany::from(1), 0, 1)]
680    #[should_panic = "index out of bounds: the len is 1 but the index is 1"]
681    #[case::one(OneOrMany::from(1), 1, 0)]
682    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0, 1)]
683    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 1, 2)]
684    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 2, 3)]
685    #[should_panic = "index out of bounds: the len is 3 but the index is 3"]
686    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 3, 4)]
687    fn test_index<T>(#[case] input: OneOrMany<T>, #[case] index: usize, #[case] expected: T)
688    where
689        T: PartialEq + std::fmt::Debug + Copy,
690    {
691        let actual = input[index];
692        assert_eq!(actual, expected);
693    }
694
695    #[rstest]
696    #[case::none(OneOrMany::<usize>::None, 0..0, &[])]
697    #[should_panic = "range end index 1 out of range for slice of length 0"]
698    #[case::none(OneOrMany::<usize>::None, 0..1, &[])]
699    #[case::one(OneOrMany::from(1), 0..0, &[])]
700    #[case::one(OneOrMany::from(1), 0..1, &[1])]
701    #[should_panic = "range end index 2 out of range for slice of length 1"]
702    #[case::one(OneOrMany::from(1), 1..2, &[])]
703    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..0, &[])]
704    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..1, &[1])]
705    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 1..2, &[2])]
706    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 2..3, &[3])]
707    #[should_panic = "range end index 4 out of range for slice of length 3"]
708    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 3..4, &[])]
709    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..3, &[1, 2, 3])]
710    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..2, &[1, 2])]
711    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 1..3, &[2, 3])]
712    fn test_index_slice<'a, T, I>(
713        #[case] input: OneOrMany<T>,
714        #[case] index: I,
715        #[case] expected: &[T],
716    ) where
717        T: PartialEq + std::fmt::Debug,
718        I: std::slice::SliceIndex<[T], Output = [T]>,
719    {
720        let actual = &input[index];
721        assert_eq!(actual, expected);
722    }
723
724    #[rstest]
725    #[case::none(OneOrMany::<usize>::None, 0..0, &[])]
726    #[should_panic = "range end index 1 out of range for slice of length 0"]
727    #[case::none(OneOrMany::<usize>::None, 0..1, &[])]
728    #[case::one(OneOrMany::from(1), 0..0, &[])]
729    #[case::one(OneOrMany::from(1), 0..1, &[1])]
730    #[should_panic = "range end index 2 out of range for slice of length 1"]
731    #[case::one(OneOrMany::from(1), 1..2, &[])]
732    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..0, &[])]
733    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..1, &[1])]
734    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 1..2, &[2])]
735    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 2..3, &[3])]
736    #[should_panic = "range end index 4 out of range for slice of length 3"]
737    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 3..4, &[])]
738    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..3, &[1, 2, 3])]
739    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 0..2, &[1, 2])]
740    #[case::many(OneOrMany::Many(vec![1, 2, 3]), 1..3, &[2, 3])]
741    fn test_index_mut_slice<'a, T, I>(
742        #[case] mut input: OneOrMany<T>,
743        #[case] index: I,
744        #[case] expected: &[T],
745    ) where
746        T: PartialEq + std::fmt::Debug,
747        I: std::slice::SliceIndex<[T], Output = [T]>,
748    {
749        let actual = &mut input[index];
750        assert_eq!(actual, expected);
751    }
752
753    #[rstest]
754    #[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None, Some(std::cmp::Ordering::Equal))]
755    #[case::none(OneOrMany::<usize>::None, OneOrMany::from(1), Some(std::cmp::Ordering::Less))]
756    #[case::none(OneOrMany::<usize>::None, OneOrMany::Many(vec![1, 2, 3]), Some(std::cmp::Ordering::Less))]
757    #[case::one(OneOrMany::from(1), OneOrMany::<usize>::None, Some(std::cmp::Ordering::Greater))]
758    #[case::one(
759        OneOrMany::from(1),
760        OneOrMany::from(1),
761        Some(std::cmp::Ordering::Equal)
762    )]
763    #[case::one(OneOrMany::from(1), OneOrMany::from(2), Some(std::cmp::Ordering::Less))]
764    #[case::one(
765        OneOrMany::from(1),
766        OneOrMany::from(0),
767        Some(std::cmp::Ordering::Greater)
768    )]
769    #[case::one(OneOrMany::from(1), OneOrMany::Many(vec![1, 2, 3]), Some(std::cmp::Ordering::Less))]
770    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::<usize>::None, Some(std::cmp::Ordering::Greater))]
771    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::from(1), Some(std::cmp::Ordering::Greater))]
772    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]), Some(std::cmp::Ordering::Equal))]
773    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![2, 3]), Some(std::cmp::Ordering::Less))]
774    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3, 4]), Some(std::cmp::Ordering::Less))]
775    fn test_partial_cmp<T>(
776        #[case] input: OneOrMany<T>,
777        #[case] other: OneOrMany<T>,
778        #[case] expected: Option<std::cmp::Ordering>,
779    ) where
780        T: std::fmt::Debug + PartialOrd,
781    {
782        let actual = input.partial_cmp(&other);
783        assert_eq!(actual, expected);
784    }
785
786    #[rstest]
787    #[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None, std::cmp::Ordering::Equal)]
788    #[case::none(OneOrMany::<usize>::None, OneOrMany::from(1), std::cmp::Ordering::Less)]
789    #[case::none(OneOrMany::<usize>::None, OneOrMany::Many(vec![1, 2, 3]), std::cmp::Ordering::Less)]
790    #[case::one(OneOrMany::from(1), OneOrMany::<usize>::None, std::cmp::Ordering::Greater)]
791    #[case::one(OneOrMany::from(1), OneOrMany::from(1), std::cmp::Ordering::Equal)]
792    #[case::one(OneOrMany::from(1), OneOrMany::from(2), std::cmp::Ordering::Less)]
793    #[case::one(OneOrMany::from(1), OneOrMany::from(0), std::cmp::Ordering::Greater)]
794    #[case::one(OneOrMany::from(1), OneOrMany::Many(vec![1, 2, 3]), std::cmp::Ordering::Less)]
795    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::<usize>::None, std::cmp::Ordering::Greater)]
796    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::from(1), std::cmp::Ordering::Greater)]
797    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]), std::cmp::Ordering::Equal)]
798    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![2, 3]), std::cmp::Ordering::Less)]
799    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3, 4]), std::cmp::Ordering::Less)]
800    fn test_cmp<T>(
801        #[case] input: OneOrMany<T>,
802        #[case] other: OneOrMany<T>,
803        #[case] expected: std::cmp::Ordering,
804    ) where
805        T: std::fmt::Debug + Ord,
806    {
807        let actual = input.cmp(&other);
808        assert_eq!(actual, expected);
809    }
810
811    #[rstest]
812    #[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None)]
813    #[case::one(OneOrMany::from(1), OneOrMany::from(1))]
814    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]))]
815    fn test_eq<T>(#[case] input: OneOrMany<T>, #[case] other: OneOrMany<T>)
816    where
817        T: PartialEq + std::fmt::Debug,
818    {
819        assert_eq!(input, other);
820    }
821
822    #[rstest]
823    #[case::none(OneOrMany::<usize>::None, OneOrMany::from(1))]
824    #[case::one(OneOrMany::from(1), OneOrMany::Many(vec![1, 2, 3]))]
825    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::<usize>::None)]
826    fn test_ne<T>(#[case] input: OneOrMany<T>, #[case] other: OneOrMany<T>)
827    where
828        T: PartialEq + std::fmt::Debug,
829    {
830        assert_ne!(input, other);
831    }
832
833    #[rstest]
834    #[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None)]
835    #[case::one(OneOrMany::from(1), OneOrMany::from(1))]
836    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]))]
837    #[case::many(OneOrMany::Many(vec![1, 1, 2, 3, 2]), OneOrMany::Many(vec![1, 2, 3]))]
838    #[case::many(OneOrMany::Many(vec![1, 1, 1]), OneOrMany::from(1))]
839    fn test_dedup<T>(#[case] mut input: OneOrMany<T>, #[case] expected: OneOrMany<T>)
840    where
841        T: Clone + Eq + std::hash::Hash + std::fmt::Debug,
842    {
843        input.dedup();
844        assert_eq!(input, expected);
845    }
846
847    #[rstest]
848    #[case::none(OneOrMany::<usize>::None, OneOrMany::<usize>::None)]
849    #[case::one(OneOrMany::from(1), OneOrMany::from(1))]
850    #[case::many(OneOrMany::Many(vec![1, 2, 3]), OneOrMany::Many(vec![1, 2, 3]))]
851    #[case::many(OneOrMany::Many(vec![1, 1, 2, 3, 2]), OneOrMany::Many(vec![1, 2, 3]))]
852    #[case::many(OneOrMany::Many(vec![1, 1, 1]), OneOrMany::from(1))]
853    fn test_dedup_by_key<T>(#[case] mut input: OneOrMany<T>, #[case] expected: OneOrMany<T>)
854    where
855        T: Clone + Eq + std::hash::Hash + std::fmt::Debug,
856    {
857        input.dedup_by_key(Clone::clone);
858        assert_eq!(input, expected);
859    }
860
861    #[rstest]
862    #[case::none_with_none(OneOrMany::<usize>::None, vec![], OneOrMany::<usize>::None)]
863    #[case::none_with_one(OneOrMany::<usize>::None, vec![1], OneOrMany::from(1))]
864    #[case::none_with_many(OneOrMany::<usize>::None, vec![1, 2, 3], OneOrMany::Many(vec![1, 2, 3]))]
865    #[case::none_with_many(OneOrMany::<usize>::None, vec![1, 1, 2, 3], OneOrMany::Many(vec![1, 1, 2, 3]))]
866    #[case::one_with_none(OneOrMany::from(1), vec![], OneOrMany::from(1))]
867    #[case::one_with_one(OneOrMany::from(1), vec![2], OneOrMany::Many(vec![1, 2]))]
868    #[case::one_with_one(OneOrMany::from(1), vec![1], OneOrMany::Many(vec![1, 1]))]
869    #[case::one_with_many(OneOrMany::from(1), vec![2, 3, 4], OneOrMany::Many(vec![1, 2, 3, 4]))]
870    #[case::one_with_many(OneOrMany::from(1), vec![1, 2, 3], OneOrMany::Many(vec![1, 1, 2, 3]))]
871    #[case::many_with_none(OneOrMany::Many(vec![1, 2, 3]), vec![], OneOrMany::Many(vec![1, 2, 3]))]
872    #[case::many_with_one(OneOrMany::Many(vec![1, 2, 3]), vec![4], OneOrMany::Many(vec![1, 2, 3, 4]))]
873    #[case::many_with_one(OneOrMany::Many(vec![1, 2, 3]), vec![1], OneOrMany::Many(vec![1, 2, 3, 1]))]
874    #[case::many_with_many(OneOrMany::Many(vec![1, 2, 3]), vec![4, 5, 6], OneOrMany::Many(vec![1, 2, 3, 4, 5, 6]))]
875    #[case::many_with_many(OneOrMany::Many(vec![1, 2, 3]), vec![3, 5, 6], OneOrMany::Many(vec![1, 2, 3, 3, 5, 6]))]
876    fn test_extend<T>(
877        #[case] mut base: OneOrMany<T>,
878        #[case] extend: impl IntoIterator<Item = T>,
879        #[case] expected: OneOrMany<T>,
880    ) where
881        T: Clone + PartialEq + std::fmt::Debug,
882    {
883        base.extend(extend);
884        assert_eq!(base, expected);
885    }
886}