use core::fmt;
use core::ops::ControlFlow;
pub use crate::template::components::VarName;
pub trait Context: Sized {
#[must_use]
fn visit<V: Visitor>(&self, visitor: V) -> V::Result;
}
pub trait Visitor: Sized + private::Sealed {
type Result;
type ListVisitor: ListVisitor<Result = Self::Result>;
type AssocVisitor: AssocVisitor<Result = Self::Result>;
#[must_use]
fn var_name(&self) -> VarName<'_>;
#[must_use]
fn visit_undefined(self) -> Self::Result;
#[must_use]
fn visit_string<T: fmt::Display>(self, v: T) -> Self::Result;
#[must_use]
fn visit_list(self) -> Self::ListVisitor;
#[must_use]
fn visit_assoc(self) -> Self::AssocVisitor;
}
pub trait ListVisitor: Sized + private::Sealed {
type Result;
#[must_use]
fn visit_item<T: fmt::Display>(&mut self, item: T) -> ControlFlow<Self::Result>;
#[must_use]
fn finish(self) -> Self::Result;
#[must_use]
fn visit_items_and_finish<T, I>(mut self, items: I) -> Self::Result
where
T: fmt::Display,
I: IntoIterator<Item = T>,
{
match items.into_iter().try_for_each(|item| self.visit_item(item)) {
ControlFlow::Break(v) => v,
ControlFlow::Continue(()) => self.finish(),
}
}
}
pub trait AssocVisitor: Sized + private::Sealed {
type Result;
#[must_use]
fn visit_entry<K: fmt::Display, V: fmt::Display>(
&mut self,
key: K,
value: V,
) -> ControlFlow<Self::Result>;
#[must_use]
fn finish(self) -> Self::Result;
#[must_use]
fn visit_entries_and_finish<K, V, I>(mut self, entries: I) -> Self::Result
where
K: fmt::Display,
V: fmt::Display,
I: IntoIterator<Item = (K, V)>,
{
match entries
.into_iter()
.try_for_each(|(key, value)| self.visit_entry(key, value))
{
ControlFlow::Break(v) => v,
ControlFlow::Continue(()) => self.finish(),
}
}
}
pub(super) mod private {
pub trait Sealed {}
}