use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor};
use serde::ser::{SerializeSeq, Serializer};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::iter::FromIterator;
use std::marker::PhantomData;
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum ZeroOneOrMany<T> {
None,
One(T),
Many(Vec<T>),
}
impl<T> ZeroOneOrMany<T> {
#[inline]
pub fn none() -> Self {
ZeroOneOrMany::None
}
#[inline]
pub fn one(item: T) -> Self {
ZeroOneOrMany::One(item)
}
#[inline]
pub fn many(items: Vec<T>) -> Self {
if items.is_empty() {
ZeroOneOrMany::None
} else {
ZeroOneOrMany::Many(items)
}
}
#[inline]
pub fn from_hashmap<K, V>(map: ::hashbrown::HashMap<K, V>) -> ZeroOneOrMany<(K, V)> {
let items: Vec<(K, V)> = map.into_iter().collect();
ZeroOneOrMany::many(items)
}
#[inline]
pub fn from_array_tuple<K, V, F>(f: F) -> ZeroOneOrMany<(K, V)>
where
F: FnOnce() -> ::hashbrown::HashMap<K, V>,
{
Self::from_hashmap(f())
}
#[inline]
pub fn merge<I>(items: I) -> Self
where
I: IntoIterator<Item = ZeroOneOrMany<T>>,
T: Clone + 'static,
{
let vec: Vec<T> = items
.into_iter()
.flat_map(|zoom| zoom.into_iter())
.collect();
Self::many(vec)
}
#[inline]
pub fn merge_refs<'a, I>(items: I) -> ZeroOneOrMany<&'a T>
where
I: IntoIterator<Item = &'a ZeroOneOrMany<T>>,
{
let vec: Vec<&T> = items.into_iter().flat_map(|zoom| zoom.iter()).collect();
ZeroOneOrMany::many(vec)
}
#[inline]
pub fn len(&self) -> usize {
match self {
ZeroOneOrMany::None => 0,
ZeroOneOrMany::One(_) => 1,
ZeroOneOrMany::Many(v) => v.len(),
}
}
#[inline]
pub fn is_empty(&self) -> bool {
matches!(self, ZeroOneOrMany::None)
}
#[inline]
pub fn first(&self) -> Option<&T> {
match self {
ZeroOneOrMany::None => None,
ZeroOneOrMany::One(item) => Some(item),
ZeroOneOrMany::Many(v) => v.first(),
}
}
#[inline]
pub fn rest(&self) -> Vec<&T> {
match self {
ZeroOneOrMany::None => vec![],
ZeroOneOrMany::One(_) => vec![],
ZeroOneOrMany::Many(v) if v.len() > 1 => v[1..].iter().collect(),
ZeroOneOrMany::Many(_) => vec![],
}
}
#[inline]
pub fn rest_iter(&self) -> impl Iterator<Item = &T> {
match self {
ZeroOneOrMany::None => [].iter(),
ZeroOneOrMany::One(_) => [].iter(),
ZeroOneOrMany::Many(v) if v.len() > 1 => v[1..].iter(),
ZeroOneOrMany::Many(_) => [].iter(),
}
}
#[inline]
pub fn with_pushed(self, item: T) -> Self {
match self {
ZeroOneOrMany::None => ZeroOneOrMany::One(item),
ZeroOneOrMany::One(first) => {
let vec = vec![first, item];
ZeroOneOrMany::Many(vec)
}
ZeroOneOrMany::Many(mut v) => {
v.push(item);
ZeroOneOrMany::Many(v)
}
}
}
#[inline]
pub fn with_inserted(self, idx: usize, item: T) -> Self {
match self {
ZeroOneOrMany::None if idx == 0 => ZeroOneOrMany::One(item),
ZeroOneOrMany::None => panic!("Index {idx} out of bounds"),
ZeroOneOrMany::One(first) if idx == 0 => {
let vec = vec![item, first];
ZeroOneOrMany::Many(vec)
}
ZeroOneOrMany::One(first) if idx == 1 => {
let vec = vec![first, item];
ZeroOneOrMany::Many(vec)
}
ZeroOneOrMany::One(_) => panic!("Index {idx} out of bounds"),
ZeroOneOrMany::Many(mut v) => {
v.insert(idx, item);
ZeroOneOrMany::Many(v)
}
}
}
#[inline]
pub fn map<U, F: FnMut(T) -> U>(self, mut f: F) -> ZeroOneOrMany<U> {
match self {
ZeroOneOrMany::None => ZeroOneOrMany::None,
ZeroOneOrMany::One(item) => ZeroOneOrMany::One(f(item)),
ZeroOneOrMany::Many(v) => ZeroOneOrMany::Many(v.into_iter().map(f).collect()),
}
}
#[inline]
pub fn try_map<U, E, F: FnMut(T) -> Result<U, E>>(
self,
mut f: F,
) -> Result<ZeroOneOrMany<U>, E> {
match self {
ZeroOneOrMany::None => Ok(ZeroOneOrMany::None),
ZeroOneOrMany::One(item) => Ok(ZeroOneOrMany::One(f(item)?)),
ZeroOneOrMany::Many(v) => {
let mut result = Vec::with_capacity(v.len());
for item in v {
result.push(f(item)?);
}
Ok(ZeroOneOrMany::Many(result))
}
}
}
#[inline]
pub fn iter(&self) -> Box<dyn Iterator<Item = &T> + '_> {
match self {
ZeroOneOrMany::None => Box::new([].iter()),
ZeroOneOrMany::One(item) => Box::new(std::iter::once(item)),
ZeroOneOrMany::Many(v) => Box::new(v.iter()),
}
}
}
impl<T: Clone + 'static> IntoIterator for ZeroOneOrMany<T> {
type Item = T;
type IntoIter = Box<dyn Iterator<Item = T>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
match self {
ZeroOneOrMany::None => Box::new(std::iter::empty()),
ZeroOneOrMany::One(item) => Box::new(std::iter::once(item)),
ZeroOneOrMany::Many(v) => Box::new(v.into_iter()),
}
}
}
impl<'a, T> IntoIterator for &'a ZeroOneOrMany<T> {
type Item = &'a T;
type IntoIter = Box<dyn Iterator<Item = &'a T> + 'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
Box::new(self.iter())
}
}
impl<T: Serialize> Serialize for ZeroOneOrMany<T> {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
match self {
ZeroOneOrMany::None => {
let seq = ser.serialize_seq(Some(0))?;
seq.end()
}
ZeroOneOrMany::One(item) => {
let mut seq = ser.serialize_seq(Some(1))?;
seq.serialize_element(item)?;
seq.end()
}
ZeroOneOrMany::Many(v) => {
let mut seq = ser.serialize_seq(Some(v.len()))?;
for item in v {
seq.serialize_element(item)?;
}
seq.end()
}
}
}
}
impl<'de, T: Deserialize<'de>> Deserialize<'de> for ZeroOneOrMany<T> {
fn deserialize<D: Deserializer<'de>>(de: D) -> Result<Self, D::Error> {
struct V<T>(PhantomData<T>);
impl<'de, T: Deserialize<'de>> Visitor<'de> for V<T> {
type Value = ZeroOneOrMany<T>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("null, a sequence, or single value")
}
#[inline]
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(ZeroOneOrMany::None)
}
#[inline]
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(ZeroOneOrMany::None)
}
#[inline]
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: SeqAccess<'de>,
{
let mut vec = Vec::new();
while let Some(elem) = seq.next_element()? {
vec.push(elem);
}
Ok(ZeroOneOrMany::many(vec))
}
#[inline]
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
let v = Deserialize::deserialize(de::value::MapAccessDeserializer::new(map))?;
Ok(ZeroOneOrMany::One(v))
}
}
de.deserialize_any(V(PhantomData))
}
}
impl<T> From<T> for ZeroOneOrMany<T> {
#[inline]
fn from(value: T) -> Self {
ZeroOneOrMany::One(value)
}
}
impl<T> From<Vec<T>> for ZeroOneOrMany<T> {
#[inline]
fn from(vec: Vec<T>) -> Self {
ZeroOneOrMany::many(vec)
}
}
impl<T> FromIterator<T> for ZeroOneOrMany<T> {
#[inline]
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
ZeroOneOrMany::many(iter.into_iter().collect())
}
}
impl<T> From<ZeroOneOrMany<T>> for Vec<T> {
#[inline]
fn from(value: ZeroOneOrMany<T>) -> Self {
match value {
ZeroOneOrMany::None => vec![],
ZeroOneOrMany::One(item) => vec![item],
ZeroOneOrMany::Many(v) => v,
}
}
}