use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(untagged)]
pub enum OneOrMany<T> {
One(T),
Many(Vec<T>),
}
impl<T> Default for OneOrMany<T> {
fn default() -> Self {
Self::Many(Vec::new())
}
}
impl<T> OneOrMany<T> {
pub fn any<F>(&self, f: F) -> bool
where
F: Fn(&T) -> bool,
{
match self {
Self::One(value) => f(value),
Self::Many(values) => values.iter().any(f),
}
}
pub fn len(&self) -> usize {
match self {
Self::One(_) => 1,
Self::Many(values) => values.len(),
}
}
pub fn is_empty(&self) -> bool {
match self {
Self::One(_) => false,
Self::Many(values) => values.is_empty(),
}
}
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq<T>,
{
match self {
Self::One(value) => x == value,
Self::Many(values) => values.contains(x),
}
}
pub fn as_slice(&self) -> &[T] {
match self {
Self::One(t) => std::slice::from_ref(t),
Self::Many(l) => l.as_slice(),
}
}
pub fn first(&self) -> Option<&T> {
match self {
Self::One(value) => Some(value),
Self::Many(values) => values.first(),
}
}
pub fn to_single(&self) -> Option<&T> {
match self {
Self::One(value) => Some(value),
Self::Many(values) => values.first(),
}
}
pub fn to_single_mut(&mut self) -> Option<&mut T> {
match self {
Self::One(value) => Some(value),
Self::Many(values) => values.first_mut(),
}
}
pub fn into_single(self) -> Option<T> {
match self {
Self::One(value) => Some(value),
Self::Many(values) => {
let mut it = values.into_iter();
let value = it.next()?;
if it.next().is_none() {
Some(value)
} else {
None
}
}
}
}
pub fn into_vec(self) -> Vec<T> {
match self {
Self::One(t) => vec![t],
Self::Many(v) => v,
}
}
}
impl<T> IntoIterator for OneOrMany<T> {
type Item = T;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
match self {
Self::One(value) => vec![value].into_iter(),
Self::Many(values) => values.into_iter(),
}
}
}
impl<'a, T> IntoIterator for &'a OneOrMany<T> {
type Item = &'a T;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
match self {
OneOrMany::One(value) => vec![value].into_iter(),
OneOrMany::Many(values) => values.iter().collect::<Vec<Self::Item>>().into_iter(),
}
}
}
#[derive(Debug, Serialize, Clone, PartialEq, Eq)]
#[serde(untagged)]
pub enum OneOrManyRef<'a, T> {
One(&'a T),
Many(&'a [T]),
}
impl<'a, T> OneOrManyRef<'a, T> {
pub fn from_slice(s: &'a [T]) -> Self {
match s {
[t] => Self::One(t),
_ => Self::Many(s),
}
}
pub fn is_empty(&self) -> bool {
matches!(self, Self::Many([]))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_empty_many() {
let v: OneOrMany<i32> = OneOrMany::default();
assert!(matches!(v, OneOrMany::Many(ref v) if v.is_empty()));
}
#[test]
fn len_one() {
assert_eq!(OneOrMany::One(42).len(), 1);
}
#[test]
fn len_many() {
assert_eq!(OneOrMany::Many(vec![1, 2, 3]).len(), 3);
}
#[test]
fn len_many_empty() {
assert_eq!(OneOrMany::<i32>::Many(vec![]).len(), 0);
}
#[test]
fn is_empty_one_is_false() {
assert!(!OneOrMany::One(42).is_empty());
}
#[test]
fn is_empty_many_empty() {
assert!(OneOrMany::<i32>::Many(vec![]).is_empty());
}
#[test]
fn is_empty_many_nonempty() {
assert!(!OneOrMany::Many(vec![1]).is_empty());
}
#[test]
fn any_one_true() {
assert!(OneOrMany::One(42).any(|x| *x == 42));
}
#[test]
fn any_one_false() {
assert!(!OneOrMany::One(42).any(|x| *x == 99));
}
#[test]
fn any_many_true() {
assert!(OneOrMany::Many(vec![1, 2, 3]).any(|x| *x == 2));
}
#[test]
fn any_many_false() {
assert!(!OneOrMany::Many(vec![1, 2, 3]).any(|x| *x == 99));
}
#[test]
fn contains_one_found() {
assert!(OneOrMany::One("hello").contains(&"hello"));
}
#[test]
fn contains_one_not_found() {
assert!(!OneOrMany::One("hello").contains(&"world"));
}
#[test]
fn contains_many_found() {
assert!(OneOrMany::Many(vec!["a", "b"]).contains(&"b"));
}
#[test]
fn contains_many_not_found() {
assert!(!OneOrMany::Many(vec!["a", "b"]).contains(&"c"));
}
#[test]
fn as_slice_one() {
let v = OneOrMany::One(42);
assert_eq!(v.as_slice(), &[42]);
}
#[test]
fn as_slice_many() {
let v = OneOrMany::Many(vec![1, 2]);
assert_eq!(v.as_slice(), &[1, 2]);
}
#[test]
fn first_one() {
assert_eq!(OneOrMany::One(42).first(), Some(&42));
}
#[test]
fn first_many() {
assert_eq!(OneOrMany::Many(vec![10, 20]).first(), Some(&10));
}
#[test]
fn first_many_empty() {
assert_eq!(OneOrMany::<i32>::Many(vec![]).first(), None);
}
#[test]
fn to_single_one() {
assert_eq!(OneOrMany::One(42).to_single(), Some(&42));
}
#[test]
fn to_single_many_single_element() {
assert_eq!(OneOrMany::Many(vec![42]).to_single(), Some(&42));
}
#[test]
fn to_single_many_empty() {
assert_eq!(OneOrMany::<i32>::Many(vec![]).to_single(), None);
}
#[test]
fn to_single_mut_one() {
let mut v = OneOrMany::One(42);
*v.to_single_mut().unwrap() = 99;
assert_eq!(v, OneOrMany::One(99));
}
#[test]
fn to_single_mut_many() {
let mut v = OneOrMany::Many(vec![1, 2]);
*v.to_single_mut().unwrap() = 99;
assert_eq!(v, OneOrMany::Many(vec![99, 2]));
}
#[test]
fn to_single_mut_many_empty() {
let mut v = OneOrMany::<i32>::Many(vec![]);
assert!(v.to_single_mut().is_none());
}
#[test]
fn into_single_one() {
assert_eq!(OneOrMany::One(42).into_single(), Some(42));
}
#[test]
fn into_single_many_single() {
assert_eq!(OneOrMany::Many(vec![42]).into_single(), Some(42));
}
#[test]
fn into_single_many_multiple() {
assert_eq!(OneOrMany::Many(vec![1, 2]).into_single(), None);
}
#[test]
fn into_single_many_empty() {
assert_eq!(OneOrMany::<i32>::Many(vec![]).into_single(), None);
}
#[test]
fn into_vec_one() {
assert_eq!(OneOrMany::One(42).into_vec(), vec![42]);
}
#[test]
fn into_vec_many() {
assert_eq!(OneOrMany::Many(vec![1, 2, 3]).into_vec(), vec![1, 2, 3]);
}
#[test]
fn into_iter_one() {
let v: Vec<i32> = OneOrMany::One(42).into_iter().collect();
assert_eq!(v, vec![42]);
}
#[test]
fn into_iter_many() {
let v: Vec<i32> = OneOrMany::Many(vec![1, 2]).into_iter().collect();
assert_eq!(v, vec![1, 2]);
}
#[test]
fn ref_into_iter_one() {
let v = OneOrMany::One(42);
let refs: Vec<&i32> = (&v).into_iter().collect();
assert_eq!(refs, vec![&42]);
}
#[test]
fn ref_into_iter_many() {
let v = OneOrMany::Many(vec![1, 2]);
let refs: Vec<&i32> = (&v).into_iter().collect();
assert_eq!(refs, vec![&1, &2]);
}
#[test]
fn serde_one_roundtrip() {
let v = OneOrMany::One("hello".to_string());
let json = serde_json::to_string(&v).unwrap();
assert_eq!(json, r#""hello""#);
let back: OneOrMany<String> = serde_json::from_str(&json).unwrap();
assert_eq!(back, v);
}
#[test]
fn serde_many_roundtrip() {
let v = OneOrMany::Many(vec!["a".to_string(), "b".to_string()]);
let json = serde_json::to_string(&v).unwrap();
assert_eq!(json, r#"["a","b"]"#);
let back: OneOrMany<String> = serde_json::from_str(&json).unwrap();
assert_eq!(back, v);
}
#[test]
fn from_slice_single() {
let data = [42];
let r = OneOrManyRef::from_slice(&data);
assert!(matches!(r, OneOrManyRef::One(&42)));
}
#[test]
fn from_slice_multiple() {
let data = [1, 2, 3];
let r = OneOrManyRef::from_slice(&data);
assert!(matches!(r, OneOrManyRef::Many(&[1, 2, 3])));
}
#[test]
fn from_slice_empty() {
let data: [i32; 0] = [];
let r = OneOrManyRef::from_slice(&data);
assert!(matches!(r, OneOrManyRef::Many(&[])));
}
#[test]
fn one_or_many_ref_is_empty() {
let data: [i32; 0] = [];
assert!(OneOrManyRef::from_slice(&data).is_empty());
assert!(!OneOrManyRef::from_slice(&[1]).is_empty());
assert!(!OneOrManyRef::from_slice(&[1, 2]).is_empty());
}
}