use std::marker::PhantomData;
use crate::tree::Tag;
use crate::value::{ToValue, Value};
pub enum Make<T, V> {
Fn(Box<dyn Fn(&T) -> V>),
Static(V),
Empty,
}
impl<T> Make<T, Value> {
pub fn resolve(&self, input: &T) -> Value {
match self {
Make::Fn(f) => (f)(input),
Make::Static(v) => v.clone(),
Make::Empty => Value::Nil,
}
}
pub fn resolve_static(&self) -> Option<Value> {
match self {
Make::Static(v) => Some(v.clone()),
_ => None,
}
}
}
impl<T> Make<T, Tag> {
pub fn resolve(&self, input: &T) -> Option<Tag> {
match self {
Make::Fn(f) => Some((f)(input)),
Make::Static(t) => Some(t.clone()),
Make::Empty => None,
}
}
}
impl<T> Make<T, String> {
pub fn resolve(&self, input: &T) -> Option<String> {
match self {
Make::Fn(f) => Some((f)(input)),
Make::Static(v) => Some(v.clone()),
Make::Empty => None,
}
}
pub fn resolve_static(&self) -> Option<String> {
match self {
Make::Static(v) => Some(v.clone()),
_ => None,
}
}
}
impl<T> From<&'static str> for Make<T, Value> {
fn from(s: &'static str) -> Self {
Make::Static(Value::text(s))
}
}
impl<T> From<Value> for Make<T, Value> {
fn from(value: Value) -> Self {
Make::Static(value)
}
}
impl<T: ToValue> From<Auto<T>> for Make<T, Value> {
fn from(_: Auto<T>) -> Self {
Make::Fn(Box::new(|t: &T| t.to_value()))
}
}
impl<T, F, O> From<F> for Make<T, O>
where
F: Fn(&T) -> O + 'static,
{
fn from(f: F) -> Self {
Make::Fn(Box::new(f))
}
}
impl<T> From<&'static str> for Make<T, String> {
fn from(s: &'static str) -> Self {
Make::Static(s.to_string())
}
}
impl<T> From<String> for Make<T, String> {
fn from(s: String) -> Self {
Make::Static(s)
}
}
pub enum Reference {
Www(String),
}
pub struct Ann<T> {
pub label: String,
pub value: Make<T, Value>,
pub doc: Option<String>,
pub refs: Vec<Reference>,
pub tags: Vec<Make<T, Tag>>,
pub splain: Make<T, String>,
}
impl<T> Ann<T> {
pub fn splain(mut self, s: impl Into<Make<T, String>>) -> Ann<T> {
self.splain = s.into();
self
}
pub fn doc(mut self, s: impl AsRef<str>) -> Ann<T> {
self.doc = Some(s.as_ref().to_string());
self
}
pub fn www(mut self, s: impl AsRef<str>) -> Ann<T> {
self.refs.push(Reference::Www(s.as_ref().into()));
self
}
pub fn label(mut self, s: impl AsRef<str>) -> Ann<T> {
self.label = s.as_ref().to_string();
self
}
pub fn tag(mut self, s: impl Into<Make<T, Tag>>) -> Ann<T> {
self.tags.push(s.into());
self
}
pub fn value(mut self, e: impl Into<Make<T, Value>>) -> Ann<T> {
self.value = e.into();
self
}
}
pub struct Auto<T: ToValue>(PhantomData<T>);
pub const fn auto<T: ToValue>() -> Auto<T> {
Auto(PhantomData)
}
pub fn ann<T>(label: impl AsRef<str>, value: impl Into<Make<T, Value>>) -> Ann<T> {
Ann {
label: label.as_ref().to_string(),
value: value.into(),
tags: vec![],
refs: vec![],
doc: None,
splain: Make::Empty,
}
}