Skip to content

Instantly share code, notes, and snippets.

@rust-play
Created September 18, 2019 20:05
Show Gist options
  • Save rust-play/65b3b20f31d094a242cea902707dceed to your computer and use it in GitHub Desktop.
Save rust-play/65b3b20f31d094a242cea902707dceed to your computer and use it in GitHub Desktop.
Code shared from the Rust Playground
use std::collections::HashMap;
trait Renderable: core::fmt::Debug {
fn render(&self) -> String;
}
impl<A: Renderable, B: Renderable> Renderable for (A, B) {
fn render(&self) -> String {
format!("{}{}", self.0.render(), self.1.render())
}
}
impl<A: Renderable, B: Renderable, C: Renderable> Renderable for (A, B, C) {
fn render(&self) -> String {
format!("{}{}{}", self.0.render(), self.1.render(), self.2.render())
}
}
#[derive(Debug)]
struct SimpleElement<'a, T: Renderable> {
tag_name: &'a str,
attrs: HashMap<&'a str, &'a str>,
contents: Option<T>,
}
impl<'a, T: Renderable> Renderable for SimpleElement<'a, T> {
fn render(&self) -> String {
let attrs: String = self.attrs.iter().map(|(key, value)| format!(" {}={:?}", key, value)).collect();
match &self.contents {
None => format!("<{}{} />", self.tag_name, attrs),
Some(renderable) => {
format!("<{tag_name}{attrs}>{contents}</{tag_name}>", tag_name=self.tag_name, attrs=attrs, contents=renderable.render())
}
}
}
}
#[derive(Debug)]
struct TextElement<'a>(&'a str);
impl<'a> Renderable for TextElement<'a> {
fn render(&self) -> String {
self.0.to_string()
}
}
impl Renderable for () {
fn render(&self) -> String {
"".to_string()
}
}
macro_rules! map {
($($key:expr => $value:expr),*) => {{
let mut map = HashMap::new();
$(
map.insert($key, $value);
)*
map
}}
}
macro_rules! text {
($t:expr) => { TextElement($t) }
}
macro_rules! tag {
($tag_name:ident [$($key:ident = $value:expr),*] $renderables:block) => {{
SimpleElement {
tag_name: stringify!($tag_name),
attrs: map! {
$(stringify!($key) => $value),*
},
contents: Some($renderables),
}
}};
($tag_name:ident [$($key:ident = $value:expr),*]) => {{
SimpleElement {
tag_name: stringify!($tag_name),
attrs: map! {
$(stringify!($key) => $value),*
},
contents: None,
}
}};
($tag_name:ident $renderables:block) => {{
SimpleElement {
tag_name: stringify!($tag_name),
attrs: HashMap::new(),
contents: Some($renderables),
}
}};
($tag_name:ident) => {{
SimpleElement {
tag_name: stringify!($tag_name),
attrs: HashMap::new(),
contents: None,
}
}}
}
macro_rules! comp {
($tag_name:ident [$($key:ident = $value:expr),*] $renderables:block) => {{
$tag_name {
$($key: $value),*
children: $renderables,
}
}};
($tag_name:ident [$($key:ident = $value:expr),*]) => {{
$tag_name {
$($key: $value),*
}
}};
($tag_name:ident $renderables:block) => {{
$tag_name {
children: $renderables,
}
}};
($tag_name:ident) => {{
$tag_name
}}
}
// macro_rules! fragment {
// }
#[derive(Debug)]
struct Hello<'a> {
name: &'a str
}
impl<'a> Renderable for Hello<'a> {
fn render(&self) -> String {
format!("Hello, {}", self.name)
}
}
fn main() {
// dbg!(
// SimpleElement { tag_name: "a".into(), attrs: map! { "href".into() => "hello".into() }, contents: Some((text!("hello world!"), text!("What's up?"))) }.render()
// );
let el = tag! {
a [href = "https://pokemon.com", title = "hello world!"] {
tag!(em {
(
comp!(Hello[name="Gal"]),
text!(", what's up?")
)
})
}
};
dbg!(el.render());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment