#[derive(Debug, Clone, Copy)]
pub struct TriList<T>([Option<T>; 3]);
impl<T> TriList<T> {
pub fn new(arr: [Option<T>; 3]) -> Self {
Self(arr)
}
pub fn empty() -> Self {
Self([None, None, None])
}
pub fn to_array(&self) -> &[Option<T>; 3] {
&self.0
}
pub fn into_vec(self) -> Vec<T> {
self.into_iter().collect()
}
pub fn iter(&self) -> TriListIter<'_, T> {
TriListIter(&self.0)
}
pub fn contains(&self, needle: &T) -> bool
where
T: PartialEq,
{
self.0[0].as_ref() == Some(needle)
|| self.0[1].as_ref() == Some(needle)
|| self.0[2].as_ref() == Some(needle)
}
}
impl<T> IntoIterator for TriList<T> {
type Item = T;
type IntoIter = TriListIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
TriListIntoIter {
data: self.0,
pos: 0,
}
}
}
#[derive(Debug)]
pub struct TriListIntoIter<T>{
data: [Option<T>; 3],
pos: u8,
}
impl<T> Iterator for TriListIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
loop {
if self.pos >= 3 {
return None;
}
if let Some(out) = self.data[self.pos as usize].take() {
return Some(out);
} else {
self.pos += 1;
}
}
}
}
impl<'a, T> IntoIterator for &'a TriList<T> {
type Item = &'a T;
type IntoIter = TriListIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug)]
pub struct TriListIter<'a, T>(&'a [Option<T>]);
impl<'a, T> Iterator for TriListIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.0.split_first() {
None => return None, Some((head, tail)) => {
self.0 = tail;
if let Some(out) = &head {
return Some(out);
}
}
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct DiList<T>([Option<T>; 2]);
impl<T> DiList<T> {
pub fn full(a: T, b: T) -> Self {
Self([Some(a), Some(b)])
}
pub fn single(elem: T) -> Self {
Self([Some(elem), None])
}
pub fn empty() -> Self {
Self([None, None])
}
pub fn from_options(a: Option<T>, b: Option<T>) -> Self {
match (a, b) {
(Some(a), Some(b)) => Self::full(a, b),
(Some(x), None) | (None, Some(x)) => Self::single(x),
(None, None) => Self::empty(),
}
}
pub fn len(&self) -> usize {
match () {
() if self.0[1].is_some() => 2,
() if self.0[0].is_some() => 1,
_ => 0,
}
}
pub fn into_vec(self) -> Vec<T> {
self.into_iter().collect()
}
pub fn iter(&self) -> DiListIter<'_, T> {
DiListIter(&self.0[..self.len()])
}
pub fn contains(&self, needle: &T) -> bool
where
T: PartialEq,
{
self.0[0].as_ref() == Some(needle) || self.0[1].as_ref() == Some(needle)
}
}
impl<T> IntoIterator for DiList<T> {
type Item = T;
type IntoIter = DiListIntoIter<T>;
fn into_iter(self) -> Self::IntoIter {
DiListIntoIter(self.0)
}
}
#[derive(Debug)]
pub struct DiListIntoIter<T>([Option<T>; 2]);
impl<T> Iterator for DiListIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.0[0].is_some() {
self.0[0].take()
} else {
self.0[1].take()
}
}
fn fold<B, F>(mut self, mut init: B, mut f: F) -> B
where
F: FnMut(B, Self::Item) -> B,
{
if let Some(elem) = self.0[0].take() {
init = f(init, elem);
}
if let Some(elem) = self.0[1].take() {
init = f(init, elem);
}
init
}
}
impl<'a, T> IntoIterator for &'a DiList<T> {
type Item = &'a T;
type IntoIter = DiListIter<'a, T>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[derive(Debug)]
pub struct DiListIter<'a, T>(&'a [Option<T>]);
impl<'a, T> Iterator for DiListIter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.0.split_first() {
None => return None,
Some((head, tail)) => {
self.0 = tail;
return head.as_ref();
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tri_list_empty() {
let l: TriList<String> = TriList::empty();
assert_eq!(l.to_array(), &[None, None, None]);
assert_eq!(l.iter().count(), 0);
assert_eq!(l.into_iter().count(), 0);
}
#[test]
fn tri_list_full() {
let l = TriList::new([Some("anna"), Some("bob"), Some("claire")]);
assert_eq!(l.to_array(), &[Some("anna"), Some("bob"), Some("claire")]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"anna", &"bob", &"claire"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["anna", "bob", "claire"]);
}
#[test]
fn tri_list_holes() {
let l = TriList::new([None, Some("b"), Some("c")]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"b", &"c"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["b", "c"]);
let l = TriList::new([Some("a"), None, Some("c")]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"a", &"c"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["a", "c"]);
let l = TriList::new([Some("a"), Some("b"), None]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"a", &"b"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["a", "b"]);
}
#[test]
fn tri_list_singles() {
let l = TriList::new([Some("a"), None, None]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"a"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["a"]);
let l = TriList::new([None, Some("b"), None]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"b"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["b"]);
let l = TriList::new([None, None, Some("c")]);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"c"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["c"]);
}
#[test]
fn di_list_empty() {
let l: DiList<String> = DiList::empty();
assert_eq!(l.len(), 0);
assert_eq!(l.iter().count(), 0);
assert_eq!(l.into_iter().count(), 0);
}
#[test]
fn di_list_full() {
let l = DiList::full("anna", "bob");
assert_eq!(l.len(), 2);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"anna", &"bob"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["anna", "bob"]);
}
#[test]
fn di_list_singles() {
let l = DiList::single("a");
assert_eq!(l.len(), 1);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"a"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["a"]);
}
#[test]
fn di_list_from_options() {
let l: DiList<String> = DiList::from_options(None, None);
assert_eq!(l.len(), 0);
assert_eq!(l.iter().count(), 0);
assert_eq!(l.into_iter().count(), 0);
let l = DiList::from_options(Some("anna"), None);
assert_eq!(l.len(), 1);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"anna"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["anna"]);
let l = DiList::from_options(None, Some("anna"));
assert_eq!(l.len(), 1);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"anna"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["anna"]);
let l = DiList::from_options(Some("anna"), Some("bob"));
assert_eq!(l.len(), 2);
assert_eq!(l.iter().collect::<Vec<_>>(), [&"anna", &"bob"]);
assert_eq!(l.into_iter().collect::<Vec<_>>(), ["anna", "bob"]);
}
}