Skip to main content

yog_data/schema/
one_or_list.rs

1//! One value, or a list of them: `"a"` or `["a", "b"]` — what the game's
2//! formats accept where several will do (an ingredient's items, a state's
3//! models to pick from).
4
5use super::{Reader, Schema, Shape};
6use crate::{Value, ValueRef};
7
8/// One value or several, read either way and written back the same way (one
9/// as itself). Never empty: an empty list is a problem.
10#[derive(Debug, Clone, PartialEq)]
11pub struct OneOrList<T>(pub Vec<T>);
12
13impl<T: Schema> Schema for OneOrList<T> {
14    fn shape() -> Shape {
15        Shape::List(T::shape)
16    }
17    fn read(v: &ValueRef<'_>, cx: &mut Reader) -> Option<Self> {
18        match v {
19            ValueRef::List([]) => {
20                cx.problem("an empty list: at least one");
21                None
22            }
23            ValueRef::List(_) => Vec::<T>::read(v, cx).map(OneOrList),
24            _ => T::read(v, cx).map(|one| OneOrList(vec![one])),
25        }
26    }
27    fn write(&self) -> Value {
28        match self.0.as_slice() {
29            [one] => one.write(),
30            many => Value::List(many.iter().map(Schema::write).collect()),
31        }
32    }
33}