martin 1.5.0

Blazing fast and lightweight tile server with PostGIS, MBTiles, and PMTiles support
Documentation
use std::vec::IntoIter;

use serde::{Deserialize, Serialize};

/// An enum that can hold no values, one value, or many values of type T.
#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum OptOneMany<T> {
    /// No values present.
    #[default]
    NoVals,
    /// Exactly one value present.
    One(T),
    /// Multiple values present.
    Many(Vec<T>),
}

impl<T> IntoIterator for OptOneMany<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        match self {
            Self::NoVals => Vec::new().into_iter(),
            Self::One(v) => vec![v].into_iter(),
            Self::Many(v) => v.into_iter(),
        }
    }
}

impl<T> OptOneMany<T> {
    /// Creates a new `OptOneMany` from an iterator.
    ///
    /// Returns `NoVals` if the iterator is empty, `One` if it contains exactly one item,
    /// and `Many` if it contains multiple items.
    pub fn new<I: IntoIterator<Item = T>>(iter: I) -> Self {
        let mut iter = iter.into_iter();
        match (iter.next(), iter.next()) {
            (Some(first), Some(second)) => {
                let mut vec = Vec::with_capacity(iter.size_hint().0 + 2);
                vec.push(first);
                vec.push(second);
                vec.extend(iter);
                Self::Many(vec)
            }
            (Some(first), None) => Self::One(first),
            (None, _) => Self::NoVals,
        }
    }

    /// Returns `true` if this contains no values.
    pub fn is_none(&self) -> bool {
        matches!(self, Self::NoVals)
    }

    /// Returns `true` if this contains no values or an empty vector.
    pub fn is_empty(&self) -> bool {
        match self {
            Self::NoVals => true,
            Self::One(_) => false,
            Self::Many(v) => v.is_empty(),
        }
    }

    /// Returns an iterator over the contained values.
    pub fn iter(&self) -> impl Iterator<Item = &T> {
        match self {
            Self::NoVals => [].iter(),
            Self::One(v) => std::slice::from_ref(v).iter(),
            Self::Many(v) => v.iter(),
        }
    }

    /// Returns an optional iterator over the contained values.
    ///
    /// Returns `None` for `NoVals`, `Some(iterator)` for `One` and `Many`.
    pub fn opt_iter(&self) -> Option<impl Iterator<Item = &T>> {
        match self {
            Self::NoVals => None,
            Self::One(v) => Some(std::slice::from_ref(v).iter()),
            Self::Many(v) => Some(v.iter()),
        }
    }

    /// Returns a mutable iterator over the contained values.
    pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
        match self {
            Self::NoVals => [].iter_mut(),
            Self::One(v) => std::slice::from_mut(v).iter_mut(),
            Self::Many(v) => v.iter_mut(),
        }
    }

    /// Returns a slice view of the contained values.
    pub fn as_slice(&self) -> &[T] {
        match self {
            Self::NoVals => &[],
            Self::One(item) => std::slice::from_ref(item),
            Self::Many(v) => v.as_slice(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::OptOneMany::{Many, NoVals, One};
    use super::*;

    #[test]
    fn test_one_or_many_new() {
        assert_eq!(OptOneMany::new(vec![1, 2, 3]), Many(vec![1, 2, 3]));
        assert_eq!(OptOneMany::new(vec![1]), One(1));
        assert_eq!(OptOneMany::new(Vec::<i32>::new()), NoVals);
    }

    #[test]
    fn test_one_or_many_iter() {
        let mut noval: OptOneMany<i32> = NoVals;
        let mut one = One(1);
        let mut many = Many(vec![1, 2, 3]);

        assert_eq!(noval.iter_mut().collect::<Vec<_>>(), Vec::<&i32>::new());
        assert_eq!(one.iter_mut().collect::<Vec<_>>(), vec![&1]);
        assert_eq!(many.iter_mut().collect::<Vec<_>>(), vec![&1, &2, &3]);

        assert_eq!(noval.iter().collect::<Vec<_>>(), Vec::<&i32>::new());
        assert_eq!(one.iter().collect::<Vec<_>>(), vec![&1]);
        assert_eq!(many.iter().collect::<Vec<_>>(), vec![&1, &2, &3]);

        assert_eq!(noval.opt_iter().map(Iterator::collect::<Vec<_>>), None);
        assert_eq!(one.opt_iter().map(Iterator::collect), Some(vec![&1]));
        assert_eq!(
            many.opt_iter().map(Iterator::collect),
            Some(vec![&1, &2, &3])
        );

        assert_eq!(noval.into_iter().collect::<Vec<_>>(), Vec::<i32>::new());
        assert_eq!(one.into_iter().collect::<Vec<_>>(), vec![1]);
        assert_eq!(many.into_iter().collect::<Vec<_>>(), vec![1, 2, 3]);
    }

    #[test]
    fn test_one_or_many_as_slice() {
        let noval: OptOneMany<i32> = NoVals;
        assert_eq!(noval.as_slice(), Vec::<i32>::new().as_slice());
        assert_eq!(One(1).as_slice(), &[1]);
        assert_eq!(Many(vec![1, 2, 3]).as_slice(), &[1, 2, 3]);
    }
}