pub trait Attribute {
type Text<'a>: 'a + AsRef<str> + Into<String> + ToString
where
Self: 'a;
fn text(&self) -> Option<Self::Text<'_>>;
}
pub trait AsAttribute<T>: Attribute {}
macro_rules! define_attribute_values{
($($typ:ty),* $(,)?) => {
$(
impl Attribute for $typ {
type Text<'a> = String;
fn text(&self) -> Option<Self::Text<'_>> {
Some(self.to_string())
}
}
impl AsAttribute<$typ> for $typ {}
)*
}
}
define_attribute_values!(i8, i16, i32, i64);
define_attribute_values!(u8, u16, u32, u64);
define_attribute_values!(f32, f64);
define_attribute_values!(usize);
impl Attribute for String {
type Text<'a> = &'a str;
fn text(&self) -> Option<Self::Text<'_>> {
Some(self)
}
}
impl AsAttribute<String> for String {}
impl<T: Attribute> Attribute for Option<T> {
type Text<'a>
= T::Text<'a>
where
T: 'a;
fn text(&self) -> Option<Self::Text<'_>> {
self.as_ref()?.text()
}
}
impl<U: Attribute, T: AsAttribute<U>> AsAttribute<U> for Option<T> {}
impl Attribute for bool {
type Text<'a> = &'static str;
fn text(&self) -> Option<Self::Text<'_>> {
if *self {
Some("")
} else {
None
}
}
}
impl AsAttribute<bool> for bool {}
impl<'a> Attribute for &'a str {
type Text<'b>
= &'b str
where
'a: 'b;
fn text(&self) -> Option<Self::Text<'_>> {
Some(*self)
}
}
impl AsAttribute<String> for &str {}
impl<'a> Attribute for &'a String {
type Text<'b>
= &'b str
where
'a: 'b;
fn text(&self) -> Option<Self::Text<'_>> {
Some(self.as_str())
}
}
impl AsAttribute<String> for &String {}