Skip to content

Commit 7cb5bb0

Browse files
Generate types for each font awesome icon
1 parent df52c2b commit 7cb5bb0

File tree

2 files changed

+72
-9
lines changed

2 files changed

+72
-9
lines changed

crates/font-awesome-as-a-crate/build.rs

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::{
2+
collections::HashMap,
23
env,
4+
fmt::Write as FmtWrite,
35
fs::{read_dir, File},
46
io::{Read, Write},
57
path::Path,
@@ -11,13 +13,26 @@ fn main() {
1113
write_fontawesome_sprite();
1214
}
1315

16+
fn capitalize_first_letter(s: &str) -> String {
17+
let mut c = s.chars();
18+
match c.next() {
19+
None => String::new(),
20+
Some(f) => f.to_uppercase().chain(c).collect(),
21+
}
22+
}
23+
1424
fn write_fontawesome_sprite() {
25+
let mut types = HashMap::new();
1526
let dest_path = Path::new(&env::var("OUT_DIR").unwrap()).join("fontawesome.rs");
1627
let mut dest_file = File::create(dest_path).unwrap();
1728
dest_file
1829
.write_all(b"const fn fontawesome_svg(dir:&str,file:&str)->&'static str{match(dir.as_bytes(),file.as_bytes()){")
1930
.expect("fontawesome fn write");
20-
for dirname in &["brands", "regular", "solid"] {
31+
for (dirname, trait_name) in &[
32+
("brands", "Brands"),
33+
("regular", "Regular"),
34+
("solid", "Solid"),
35+
] {
2136
let dir = read_dir(Path::new("fontawesome-free-6.2.0-desktop/svgs").join(dirname)).unwrap();
2237
let mut data = String::new();
2338
for file in dir {
@@ -32,20 +47,45 @@ fn write_fontawesome_sprite() {
3247
.expect("fontawesome file read");
3348
// if this assert goes off, add more hashes here and in the format! below
3449
assert!(!data.contains("###"), "file {filename} breaks raw string");
50+
let filename = filename.replace(".svg", "");
3551
dest_file
3652
.write_all(
37-
format!(
38-
r####"(b"{dirname}",b"{filename}")=>r#"{data}"#,"####,
39-
data = data,
40-
dirname = dirname,
41-
filename = filename.replace(".svg", ""),
42-
)
43-
.as_bytes(),
53+
format!(r####"(b"{dirname}",b"{filename}")=>r#"{data}"#,"####).as_bytes(),
4454
)
4555
.expect("write fontawesome file");
56+
types
57+
.entry(filename)
58+
.or_insert_with(|| (data.clone(), Vec::with_capacity(3)))
59+
.1
60+
.push(trait_name);
4661
}
4762
}
4863
dest_file
49-
.write_all(b"_=>\"\"}}")
64+
.write_all(b"_=>\"\"}} pub mod icons { use super::{IconStr, Regular, Brands, Solid};")
5065
.expect("fontawesome fn write");
66+
67+
for (icon, (data, kinds)) in types {
68+
let mut type_name = "Icon".to_string();
69+
type_name.extend(icon.split('-').map(capitalize_first_letter));
70+
let kinds = kinds.iter().fold(String::new(), |mut acc, k| {
71+
let _ = writeln!(acc, "impl {k} for {type_name} {{}}");
72+
acc
73+
});
74+
dest_file
75+
.write_all(
76+
format!(
77+
"\n#[derive(Debug, Clone, Copy, PartialEq, Eq)]
78+
pub struct {type_name};
79+
impl IconStr for {type_name} {{
80+
fn icon_name(&self) -> &'static str {{ r#\"{icon}\"# }}
81+
fn icon_str(&self) -> &'static str {{ r#\"{data}\"# }}
82+
}}
83+
{kinds}"
84+
)
85+
.as_bytes(),
86+
)
87+
.expect("write fontawesome file types");
88+
}
89+
90+
dest_file.write_all(b"}").expect("fontawesome fn write");
5191
}

crates/font-awesome-as-a-crate/src/lib.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,29 @@ pub const fn svg(type_: Type, name: &str) -> Result<&'static str, NameError> {
8787
Ok(svg)
8888
}
8989

90+
pub trait IconStr {
91+
/// Name of the icon, like "triangle-exclamation".
92+
fn icon_name(&self) -> &'static str;
93+
/// The SVG content of the icon.
94+
fn icon_str(&self) -> &'static str;
95+
}
96+
97+
pub trait Brands: IconStr {
98+
fn get_type() -> Type {
99+
Type::Brands
100+
}
101+
}
102+
pub trait Regular: IconStr {
103+
fn get_type() -> Type {
104+
Type::Regular
105+
}
106+
}
107+
pub trait Solid: IconStr {
108+
fn get_type() -> Type {
109+
Type::Solid
110+
}
111+
}
112+
90113
#[cfg(test)]
91114
mod tests {
92115
const fn usable_as_const_() {

0 commit comments

Comments
 (0)