mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2025-12-06 03:36:42 +01:00
60 lines
1.8 KiB
Rust
60 lines
1.8 KiB
Rust
use crate::*;
|
|
|
|
/// Composable renderable with static dispatch.
|
|
pub trait Content<E: Output>: Sized {
|
|
/// Return opaque [Render]able.
|
|
fn content (&self) -> Option<impl Render<E> + '_> { Option::<()>::None }
|
|
}
|
|
|
|
/// The platonic ideal unit of [Content]: total emptiness at dead center (e=1vg^sqrt(-1))
|
|
impl<E: Output> Content<E> for () {}
|
|
|
|
impl<E: Output> Content<E> for fn(&mut E) {
|
|
fn content (&self) -> Option<impl Render<E> + '_> {
|
|
Some(self)
|
|
}
|
|
}
|
|
|
|
impl<E: Output, T: Render<E>> Content<E> for fn()->T {
|
|
fn content (&self) -> Option<impl Render<E> + '_> {
|
|
Some(self())
|
|
}
|
|
}
|
|
|
|
impl<E: Output, T: Content<E>> Content<E> for Option<T> {
|
|
fn content (&self) -> Option<impl Render<E> + '_> {
|
|
if let Some(content) = self {
|
|
content.content()
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
/// You can render from an opaque pointer.
|
|
impl<E: Output> Content<E> for &dyn Render<E> where Self: Sized {
|
|
fn content (&self) -> Option<impl Render<E> + '_> {
|
|
#[allow(suspicious_double_ref_op)]
|
|
Some(self.deref())
|
|
}
|
|
}
|
|
|
|
/// Implement composable content for a struct.
|
|
#[macro_export] macro_rules! content {
|
|
// Implement for all [Output]s.
|
|
(|$self:ident:$Struct:ty| $content:expr) => {
|
|
impl<E: Output> Content<E> for $Struct {
|
|
fn content (&$self) -> impl Render<E> + '_ { Some($content) }
|
|
}
|
|
};
|
|
// Implement for specific [Output].
|
|
($Output:ty:|
|
|
$self:ident:
|
|
$Struct:ident$(<$($($L:lifetime)? $($T:ident)? $(:$Trait:path)?),+>)?
|
|
|$content:expr) => {
|
|
impl $(<$($($L)? $($T)? $(:$Trait)?),+>)? Content<$Output>
|
|
for $Struct $(<$($($L)? $($T)?),+>)? {
|
|
fn content (&$self) -> impl Render<$Output> + '_ { $content }
|
|
}
|
|
};
|
|
}
|