use super::Value;
#[derive(Clone, Debug, PartialEq)]
pub enum ValueTuple {
One(Value),
Two(Value, Value),
Three(Value, Value, Value),
Many(Vec<Value>),
}
impl ValueTuple {
#[must_use]
pub fn len(&self) -> usize {
match self {
Self::One(_) => 1,
Self::Two(_, _) => 2,
Self::Three(_, _, _) => 3,
Self::Many(v) => v.len(),
}
}
#[must_use]
pub fn is_empty(&self) -> bool {
match self {
Self::Many(v) => v.is_empty(),
_ => false,
}
}
#[must_use]
pub fn into_vec(self) -> Vec<Value> {
match self {
Self::One(v) => vec![v],
Self::Two(v1, v2) => vec![v1, v2],
Self::Three(v1, v2, v3) => vec![v1, v2, v3],
Self::Many(v) => v,
}
}
pub fn iter(&self) -> ValueTupleIter<'_> {
ValueTupleIter {
tuple: self,
index: 0,
}
}
}
impl IntoIterator for ValueTuple {
type Item = Value;
type IntoIter = std::vec::IntoIter<Value>;
fn into_iter(self) -> Self::IntoIter {
self.into_vec().into_iter()
}
}
pub struct ValueTupleIter<'a> {
tuple: &'a ValueTuple,
index: usize,
}
impl<'a> Iterator for ValueTupleIter<'a> {
type Item = &'a Value;
fn next(&mut self) -> Option<Self::Item> {
let result = match self.tuple {
ValueTuple::One(v) if self.index == 0 => Some(v),
ValueTuple::Two(v1, v2) => match self.index {
0 => Some(v1),
1 => Some(v2),
_ => None,
},
ValueTuple::Three(v1, v2, v3) => match self.index {
0 => Some(v1),
1 => Some(v2),
2 => Some(v3),
_ => None,
},
ValueTuple::Many(v) => v.get(self.index),
_ => None,
};
if result.is_some() {
self.index += 1;
}
result
}
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.tuple.len().saturating_sub(self.index);
(remaining, Some(remaining))
}
}
impl ExactSizeIterator for ValueTupleIter<'_> {}
impl<V: Into<Value>> From<V> for ValueTuple {
fn from(v: V) -> Self {
Self::One(v.into())
}
}
impl<V1, V2> From<(V1, V2)> for ValueTuple
where
V1: Into<Value>,
V2: Into<Value>,
{
fn from((v1, v2): (V1, V2)) -> Self {
Self::Two(v1.into(), v2.into())
}
}
impl<V1, V2, V3> From<(V1, V2, V3)> for ValueTuple
where
V1: Into<Value>,
V2: Into<Value>,
V3: Into<Value>,
{
fn from((v1, v2, v3): (V1, V2, V3)) -> Self {
Self::Three(v1.into(), v2.into(), v3.into())
}
}