1- use  std:: { 
2-     collections:: HashMap , 
3-     env, 
4-     fmt:: Write  as  FmtWrite , 
5-     fs:: { read_dir,  File } , 
6-     io:: { Read ,  Write } , 
7-     path:: Path , 
8- } ; 
1+ use  proc_macro2:: Literal ; 
2+ use  quote:: { format_ident,  quote} ; 
3+ use  std:: { collections:: HashMap ,  env,  fs,  path:: Path } ; 
94
105fn  main ( )  { 
116    println ! ( "cargo::rustc-check-cfg=cfg(font_awesome_out_dir)" ) ; 
@@ -22,70 +17,94 @@ fn capitalize_first_letter(s: &str) -> String {
2217} 
2318
2419fn  write_fontawesome_sprite ( )  { 
20+     let  mut  match_arms = vec ! [ ] ; 
2521    let  mut  types = HashMap :: new ( ) ; 
26-     let  dest_path = Path :: new ( & env:: var ( "OUT_DIR" ) . unwrap ( ) ) . join ( "fontawesome.rs" ) ; 
27-     let  mut  dest_file = File :: create ( dest_path) . unwrap ( ) ; 
28-     dest_file
29-         . write_all ( b"const fn fontawesome_svg(dir:&str,file:&str)->&'static str{match(dir.as_bytes(),file.as_bytes()){" ) 
30-         . expect ( "fontawesome fn write" ) ; 
22+ 
3123    for  ( dirname,  trait_name)  in  & [ 
3224        ( "brands" ,  "Brands" ) , 
3325        ( "regular" ,  "Regular" ) , 
3426        ( "solid" ,  "Solid" ) , 
3527    ]  { 
36-         let  dir = read_dir ( Path :: new ( "fontawesome-free-6.2.0-desktop/svgs" ) . join ( dirname) ) . unwrap ( ) ; 
37-         let  mut  data = String :: new ( ) ; 
28+         let  dir =
29+             fs:: read_dir ( Path :: new ( "fontawesome-free-6.2.0-desktop/svgs" ) . join ( dirname) ) . unwrap ( ) ; 
30+ 
3831        for  file in  dir { 
3932            let  file = file. expect ( "fontawesome directory access" ) ; 
33+             let  data = fs:: read_to_string ( & file. path ( ) ) . expect ( "fontawesome file read" ) ; 
34+ 
4035            let  filename = file
4136                . file_name ( ) 
4237                . into_string ( ) 
43-                 . expect ( "fontawesome filenames are unicode" ) ; 
44-             let  mut  file = File :: open ( file. path ( ) ) . expect ( "fontawesome file access" ) ; 
45-             data. clear ( ) ; 
46-             file. read_to_string ( & mut  data) 
47-                 . expect ( "fontawesome file read" ) ; 
48-             // if this assert goes off, add more hashes here and in the format! below 
49-             assert ! ( !data. contains( "###" ) ,  "file {filename} breaks raw string" ) ; 
50-             let  filename = filename. replace ( ".svg" ,  "" ) ; 
51-             dest_file
52-                 . write_all ( 
53-                     format ! ( r####"(b"{dirname}",b"{filename}")=>r#"{data}"#,"#### ) . as_bytes ( ) , 
54-                 ) 
55-                 . expect ( "write fontawesome file" ) ; 
38+                 . expect ( "fontawesome filenames are unicode" ) 
39+                 . replace ( ".svg" ,  "" ) ; 
40+ 
41+             let  dirname_literal = Literal :: byte_string ( dirname. as_bytes ( ) ) ; 
42+             let  filename_literal = Literal :: byte_string ( filename. as_bytes ( ) ) ; 
43+             match_arms. push ( quote !  { 
44+                 ( #dirname_literal,  #filename_literal)  => #data, 
45+             } ) ; 
46+ 
5647            types
5748                . entry ( filename) 
5849                . or_insert_with ( || ( data. clone ( ) ,  Vec :: with_capacity ( 3 ) ) ) 
5950                . 1 
6051                . push ( trait_name) ; 
6152        } 
6253    } 
63-     dest_file
64-         . write_all ( b"_=>\" \" }} pub mod icons { use super::{IconStr, Regular, Brands, Solid};" ) 
65-         . expect ( "fontawesome fn write" ) ; 
54+ 
55+     let  mut  types_output = vec ! [ ] ; 
6656
6757    for  ( icon,  ( data,  kinds) )  in  types { 
6858        let  mut  type_name = "Icon" . to_string ( ) ; 
6959        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
60+         let  type_name = format_ident ! ( "{}" ,  type_name) ; 
61+ 
62+         let  kind_impls:  Vec < _ >  = kinds
63+             . iter ( ) 
64+             . map ( |k| { 
65+                 let  k = format_ident ! ( "{}" ,  k) ; 
66+                 quote !  { 
67+                     impl  #k for  #type_name { } 
68+                 } 
69+             } ) 
70+             . collect ( ) ; 
71+ 
72+         types_output. push ( quote !  { 
73+             #[ derive( Debug ,  Clone ,  Copy ,  PartialEq ,  Eq ) ] 
74+             pub  struct  #type_name; 
75+ 
76+             impl  IconStr  for  #type_name { 
77+                 fn  icon_name( & self )  -> & ' static  str  {  #icon } 
78+                 fn  icon_str( & self )  -> & ' static  str  {  #data } 
79+             } 
80+ 
81+             #( #kind_impls) * 
7382        } ) ; 
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" ) ; 
8883    } 
8984
90-     dest_file. write_all ( b"}" ) . expect ( "fontawesome fn write" ) ; 
85+     let  token_stream = quote !  { 
86+         const  fn  fontawesome_svg( dir:  & str ,  file:  & str )  -> & ' static  str  { 
87+             // we are using byte literals to match because they can be evaluated in a 
88+             // `const` context, and `str` cannot. 
89+             match ( dir. as_bytes( ) ,  file. as_bytes( ) )  { 
90+                 #( #match_arms) * 
91+                 _=> "" 
92+             } 
93+         } 
94+ 
95+         pub  mod  icons { 
96+             use  super :: { IconStr ,  Regular ,  Brands ,  Solid } ; 
97+ 
98+             #( #types_output) * 
99+         } 
100+     } ; 
101+ 
102+     let  dest_path = Path :: new ( & env:: var ( "OUT_DIR" ) . unwrap ( ) ) . join ( "fontawesome.rs" ) ; 
103+ 
104+     let  output = format ! ( 
105+         "{}" , 
106+         prettyplease:: unparse( & syn:: parse2( token_stream) . unwrap( ) ) 
107+     ) ; 
108+ 
109+     fs:: write ( & dest_path,  output. as_bytes ( ) ) . expect ( "fontawesome output write" ) ; 
91110} 
0 commit comments