#[derive(Clone, Debug)]
pub enum Shape<N = ()> {
Base,
Optional(N, Box<Shape<N>>),
Iterable(Box<Shape<N>>),
}
impl<N> Shape<N> {
pub fn optional(meta: N, inner: Shape<N>) -> Self {
Shape::Optional(meta, Box::new(inner))
}
pub fn iterable(inner: Shape<N>) -> Self {
Shape::Iterable(Box::new(inner))
}
pub fn has_iterable_layer(&self) -> bool {
match self {
Shape::Base => false,
Shape::Optional(_, inner) => inner.has_iterable_layer(),
Shape::Iterable(_) => true,
}
}
}
pub fn fold_shape<N, T>(
s: &Shape<N>,
on_base: &dyn Fn() -> T,
on_optional: &dyn Fn(T, &N, &Shape<N>) -> T,
on_iterable: &dyn Fn(T) -> T,
) -> T {
match s {
Shape::Base => on_base(),
Shape::Optional(meta, inner) => {
let inner_val = fold_shape(inner, on_base, on_optional, on_iterable);
on_optional(inner_val, meta, inner)
}
Shape::Iterable(inner) => {
let inner_val = fold_shape(inner, on_base, on_optional, on_iterable);
on_iterable(inner_val)
}
}
}