#[derive(PartialEq, Eq, Debug, Clone)]
pub struct OneOrMany<T> {
first: T,
rest: Vec<T>,
}
#[derive(Debug, thiserror::Error)]
#[error("Cannot create OneOrMany with an empty vector.")]
pub struct EmptyListError;
impl<T: Clone> OneOrMany<T> {
pub fn first(&self) -> T {
self.first.clone()
}
pub fn rest(&self) -> Vec<T> {
self.rest.clone()
}
pub fn push(&mut self, item: T) {
self.rest.push(item);
}
pub fn len(&self) -> usize {
1 + self.rest.len()
}
pub fn is_empty(&self) -> bool {
false
}
pub fn one(item: T) -> Self {
OneOrMany {
first: item,
rest: vec![],
}
}
pub fn many(items: Vec<T>) -> Result<Self, EmptyListError> {
let mut iter = items.into_iter();
Ok(OneOrMany {
first: match iter.next() {
Some(item) => item,
None => return Err(EmptyListError),
},
rest: iter.collect(),
})
}
pub fn merge(one_or_many_items: Vec<OneOrMany<T>>) -> Result<Self, EmptyListError> {
let items = one_or_many_items
.into_iter()
.flat_map(|one_or_many| one_or_many.into_iter())
.collect::<Vec<_>>();
OneOrMany::many(items)
}
pub fn iter(&self) -> Iter<T> {
Iter {
first: Some(&self.first),
rest: self.rest.iter(),
}
}
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
IterMut {
first: Some(&mut self.first),
rest: self.rest.iter_mut(),
}
}
}
pub struct Iter<'a, T> {
first: Option<&'a T>,
rest: std::slice::Iter<'a, T>,
}
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(first) = self.first.take() {
Some(first)
} else {
self.rest.next()
}
}
}
pub struct IntoIter<T> {
first: Option<T>,
rest: std::vec::IntoIter<T>,
}
impl<T: Clone> IntoIterator for OneOrMany<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
IntoIter {
first: Some(self.first),
rest: self.rest.into_iter(),
}
}
}
impl<T: Clone> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(first) = self.first.take() {
Some(first)
} else {
self.rest.next()
}
}
}
pub struct IterMut<'a, T> {
first: Option<&'a mut T>,
rest: std::slice::IterMut<'a, T>,
}
impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
if let Some(first) = self.first.take() {
Some(first)
} else {
self.rest.next()
}
}
}
#[cfg(test)]
mod test {
use super::OneOrMany;
#[test]
fn test_single() {
let one_or_many = OneOrMany::one("hello".to_string());
assert_eq!(one_or_many.iter().count(), 1);
one_or_many.iter().for_each(|i| {
assert_eq!(i, "hello");
});
}
#[test]
fn test() {
let one_or_many = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
assert_eq!(one_or_many.iter().count(), 2);
one_or_many.iter().enumerate().for_each(|(i, item)| {
if i == 0 {
assert_eq!(item, "hello");
}
if i == 1 {
assert_eq!(item, "word");
}
});
}
#[test]
fn test_one_or_many_into_iter_single() {
let one_or_many = OneOrMany::one("hello".to_string());
assert_eq!(one_or_many.clone().into_iter().count(), 1);
one_or_many.into_iter().for_each(|i| {
assert_eq!(i, "hello".to_string());
});
}
#[test]
fn test_one_or_many_into_iter() {
let one_or_many = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
assert_eq!(one_or_many.clone().into_iter().count(), 2);
one_or_many.into_iter().enumerate().for_each(|(i, item)| {
if i == 0 {
assert_eq!(item, "hello".to_string());
}
if i == 1 {
assert_eq!(item, "word".to_string());
}
});
}
#[test]
fn test_one_or_many_merge() {
let one_or_many_1 = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
let one_or_many_2 = OneOrMany::one("sup".to_string());
let merged = OneOrMany::merge(vec![one_or_many_1, one_or_many_2]).unwrap();
assert_eq!(merged.iter().count(), 3);
merged.iter().enumerate().for_each(|(i, item)| {
if i == 0 {
assert_eq!(item, "hello");
}
if i == 1 {
assert_eq!(item, "word");
}
if i == 2 {
assert_eq!(item, "sup");
}
});
}
#[test]
fn test_mut_single() {
let mut one_or_many = OneOrMany::one("hello".to_string());
assert_eq!(one_or_many.iter_mut().count(), 1);
one_or_many.iter_mut().for_each(|i| {
assert_eq!(i, "hello");
});
}
#[test]
fn test_mut() {
let mut one_or_many =
OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
assert_eq!(one_or_many.iter_mut().count(), 2);
one_or_many.iter_mut().enumerate().for_each(|(i, item)| {
if i == 0 {
item.push_str(" world");
assert_eq!(item, "hello world");
}
if i == 1 {
assert_eq!(item, "word");
}
});
}
#[test]
fn test_one_or_many_error() {
assert!(OneOrMany::<String>::many(vec![]).is_err())
}
#[test]
fn test_len_single() {
let one_or_many = OneOrMany::one("hello".to_string());
assert_eq!(one_or_many.len(), 1);
}
#[test]
fn test_len_many() {
let one_or_many = OneOrMany::many(vec!["hello".to_string(), "word".to_string()]).unwrap();
assert_eq!(one_or_many.len(), 2);
}
}