heroicons 0.2.0

Easily include Heroicons SVGs in Rust
Documentation
use std::fmt::{self, Display, Formatter};

#[derive(Clone, Debug, PartialEq)]
pub struct Svg<'a> {
    pub attrs: Vec<Attribute<'a>>,
    pub children: &'static [SvgChild],
}

impl<'a> Svg<'a> {
    pub fn render(&self) -> String {
        let mut buffer = String::with_capacity(512);
        self.render_to(&mut buffer);
        buffer
    }

    pub fn render_to(&self, buffer: &mut String) {
        buffer.push_str("<svg");
        self.attrs.iter().for_each(|attr| attr.push_segments(buffer));
        buffer.push('>');
        self.children.iter().for_each(|ch| ch.push_segments(buffer));
        buffer.push_str("</svg>");
    }
}

pub trait ToSvg {
    fn to_svg(&self) -> Svg<'_>;
}

impl Display for Svg<'_> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.write_str(&self.render())
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct SvgChild {
    pub tag_name: &'static str,
    pub attrs: &'static [Attribute<'static>],
}

impl SvgChild {
    pub fn push_segments(&self, buffer: &mut String) {
        buffer.push('<');
        buffer.push_str(self.tag_name);
        self.attrs.iter().for_each(|attr| attr.push_segments(buffer));
        buffer.push_str("/>");
    }
}

#[derive(Clone, Debug, PartialEq)]
pub struct Attribute<'a>(&'a str, &'a str);

impl<'a> Attribute<'a> {
    pub fn push_segments(&self, buffer: &mut String) {
        let &Attribute(name, value) = self;

        buffer.push(' ');
        buffer.push_str(name);
        buffer.push_str("=\"");

        if name == "id" || name == "class" {
            html_escape::encode_double_quoted_attribute_to_string(
                value, buffer,
            );
        } else {
            buffer.push_str(value);
        }

        buffer.push('\"');
    }
}

include!(concat!(env!("OUT_DIR"), "/generated_from_icon_impl.rs"));