use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::hash::{Hash, Hasher};
use proc_macro2::TokenStream;
pub struct CustomType {
name: &'static str,
default: Option<Box<dyn CustomDefaultImpl>>,
}
impl CustomType {
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name,
default: None,
}
}
#[must_use]
pub fn name(&self) -> &'static str {
self.name
}
#[must_use]
pub fn default(&self, s: &str) -> Option<TokenStream> {
self.default.as_ref()?.exec(s)
}
#[must_use]
pub fn with_default<X: CustomDefaultImpl>(mut self, x: X) -> Self {
self.default = Some(Box::new(x));
self
}
}
impl Clone for CustomType {
fn clone(&self) -> Self {
Self {
name: self.name,
default: self
.default
.as_ref()
.map(|x| CustomDefaultImpl::clone(&**x)),
}
}
}
impl Debug for CustomType {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
f.debug_struct("CustomType")
.field("name", &self.name)
.field("default", &self.default.is_some())
.finish()
}
}
impl Eq for CustomType {}
impl PartialEq for CustomType {
fn eq(&self, other: &Self) -> bool {
self.name.eq(other.name)
}
}
impl Hash for CustomType {
fn hash<H: Hasher>(&self, state: &mut H) {
self.name.hash(state);
}
}
pub trait CustomDefaultImpl: Send + Sync + 'static {
fn exec(&self, s: &str) -> Option<TokenStream>;
fn clone(&self) -> Box<dyn CustomDefaultImpl>;
}
impl<X> CustomDefaultImpl for X
where
X: Fn(&str) -> Option<TokenStream> + Clone + Send + Sync + 'static,
{
fn exec(&self, s: &str) -> Option<TokenStream> {
(*self)(s)
}
fn clone(&self) -> Box<dyn CustomDefaultImpl> {
Box::new(self.clone())
}
}