6868
6969#![ recursion_limit = "128" ]
7070
71+ use proc_macro2:: { Ident , Literal , TokenStream } ;
7172use quote:: quote;
7273use std:: collections:: BTreeSet ;
7374use std:: fs:: File ;
@@ -185,8 +186,7 @@ impl AtomType {
185186 /// Write generated code to destination [`Vec<u8>`] and return it as [`String`]
186187 ///
187188 /// Used mostly for testing or displaying a value.
188- pub fn write_to_string ( & mut self , mut destination : Vec < u8 > ) -> io:: Result < String >
189- {
189+ pub fn write_to_string ( & mut self , mut destination : Vec < u8 > ) -> io:: Result < String > {
190190 destination. write_all (
191191 self . to_tokens ( )
192192 . to_string ( )
@@ -223,6 +223,23 @@ impl AtomType {
223223 let empty_string_index = atoms. iter ( ) . position ( |s| s. is_empty ( ) ) . unwrap ( ) as u32 ;
224224 let indices = 0 ..atoms. len ( ) as u32 ;
225225
226+ fn is_valid_ident ( name : & str ) -> bool {
227+ let begins_with_letter_or_underscore = name
228+ . chars ( )
229+ . next ( )
230+ . is_some_and ( |c| c. is_alphabetic ( ) || c == '_' ) ;
231+ let is_alphanumeric = name. chars ( ) . all ( |c| c. is_alphanumeric ( ) || c == '_' ) ;
232+
233+ begins_with_letter_or_underscore && is_alphanumeric
234+ }
235+
236+ let atoms_for_idents: Vec < & str > = atoms. iter ( ) . filter ( |x| is_valid_ident ( x) ) . collect ( ) ;
237+ let atom_idents: Vec < Ident > = atoms_for_idents. iter ( ) . map ( |atom| new_term ( atom) ) . collect ( ) ;
238+
239+ let istrs_for_idents: Vec < & str > =
240+ inline_strs. iter ( ) . filter ( |x| is_valid_ident ( x) ) . collect ( ) ;
241+ let istr_idents: Vec < Ident > = istrs_for_idents. iter ( ) . map ( |atom| new_term ( atom) ) . collect ( ) ;
242+
226243 let hashes: Vec < u32 > = atoms
227244 . iter ( )
228245 . map ( |string| {
@@ -249,8 +266,9 @@ impl AtomType {
249266 Some ( ref doc) => quote ! ( #[ doc = #doc] ) ,
250267 None => quote ! ( ) ,
251268 } ;
252- let new_term =
253- |string : & str | proc_macro2:: Ident :: new ( string, proc_macro2:: Span :: call_site ( ) ) ;
269+ fn new_term ( string : & str ) -> Ident {
270+ Ident :: new ( string, proc_macro2:: Span :: call_site ( ) )
271+ }
254272 let static_set_name = new_term ( & format ! ( "{}StaticSet" , type_name) ) ;
255273 let type_name = new_term ( type_name) ;
256274 let macro_name = new_term ( & * self . macro_name ) ;
@@ -264,6 +282,16 @@ impl AtomType {
264282 new_term ( & name)
265283 } ;
266284 let const_names: Vec < _ > = atoms. iter ( ) . copied ( ) . map ( new_const_name) . collect ( ) ;
285+ let ident_const_names: Vec < _ > = atoms_for_idents
286+ . iter ( )
287+ . copied ( )
288+ . map ( new_const_name)
289+ . collect ( ) ;
290+ let ident_inline_const_names: Vec < _ > = istrs_for_idents
291+ . iter ( )
292+ . copied ( )
293+ . map ( new_const_name)
294+ . collect ( ) ;
267295
268296 // Inline strings
269297 let ( inline_const_names, inline_values_and_lengths) : ( Vec < _ > , Vec < _ > ) = inline_strs
@@ -323,6 +351,12 @@ impl AtomType {
323351 #(
324352 ( #inline_strs) => { #module:: #inline_const_names } ;
325353 ) *
354+ #(
355+ ( #atom_idents) => { #module:: #ident_const_names } ;
356+ ) *
357+ #(
358+ ( #istr_idents) => { #module:: #ident_inline_const_names } ;
359+ ) *
326360 }
327361 }
328362 }
@@ -340,11 +374,13 @@ impl AtomType {
340374fn test_iteration_order ( ) {
341375 let x1 = crate :: AtomType :: new ( "foo::Atom" , "foo_atom!" )
342376 . atoms ( & [ "x" , "xlink" , "svg" , "test" ] )
343- . write_to_string ( Vec :: new ( ) ) . expect ( "write to string cache x1" ) ;
377+ . write_to_string ( Vec :: new ( ) )
378+ . expect ( "write to string cache x1" ) ;
344379
345380 let x2 = crate :: AtomType :: new ( "foo::Atom" , "foo_atom!" )
346381 . atoms ( & [ "x" , "xlink" , "svg" , "test" ] )
347- . write_to_string ( Vec :: new ( ) ) . expect ( "write to string cache x2" ) ;
382+ . write_to_string ( Vec :: new ( ) )
383+ . expect ( "write to string cache x2" ) ;
348384
349385 assert_eq ! ( x1, x2) ;
350386}
0 commit comments