use crate::frame::{Packer, Unpacker};
use crate::schema::{Reader, Schema, Shape};
use crate::{Value, ValueRef};
#[derive(Debug, Clone, PartialEq)]
pub struct OneOrList<T>(pub Vec<T>);
impl<T: Schema> Schema for OneOrList<T> {
fn shape() -> Shape {
Shape::List(T::shape)
}
fn read(v: &ValueRef<'_>, cx: &mut Reader<'_>) -> Option<Self> {
match v {
ValueRef::List([]) => {
cx.problem("an empty list: at least one");
None
}
ValueRef::List(_) => Vec::<T>::read(v, cx).map(OneOrList),
_ => T::read(v, cx).map(|one| OneOrList(vec![one])),
}
}
fn write(&self) -> Value {
match self.0.as_slice() {
[one] => one.write(),
many => Value::List(many.iter().map(Schema::write).collect()),
}
}
fn pack(&self, p: &mut Packer) {
T::pack_list(&self.0, p);
}
fn unpack(u: &mut Unpacker<'_>) -> Option<Self> {
T::unpack_list(u)
.filter(|items| !items.is_empty())
.map(OneOrList)
}
}