molecule_codegen/generator/languages/rust/
utilities.rs

1use case::CaseExt;
2use proc_macro2 as m4;
3
4use std::{collections::HashSet, sync::OnceLock};
5
6static RUST_KEYWORDS: OnceLock<HashSet<&'static str>> = OnceLock::new();
7
8fn rust_keyword() -> &'static HashSet<&'static str> {
9    RUST_KEYWORDS.get_or_init(|| {
10        IntoIterator::into_iter([
11            // strick
12            "as",
13            "struct",
14            "break",
15            "const",
16            "continue",
17            "crate",
18            "else",
19            "enum",
20            "extern",
21            "false",
22            "fn",
23            "for",
24            "if",
25            "impl",
26            "in",
27            "let",
28            "loop",
29            "match",
30            "mod",
31            "move",
32            "mut",
33            "pub",
34            "ref",
35            "return",
36            "self",
37            "Self",
38            "static",
39            "super",
40            "trait",
41            "true",
42            "type",
43            "unsafe",
44            "use",
45            "where",
46            "while",
47            // 2018+
48            "async",
49            "await",
50            "dyn",
51            // reserved
52            "abstract",
53            "become",
54            "box",
55            "do",
56            "final",
57            "macro",
58            "override",
59            "priv",
60            "typeof",
61            "unsized",
62            "virtual",
63            "yield",
64            // 2018+
65            "try",
66            // weak
67            "macro_rules",
68            "union",
69            "'static",
70            // 2024+
71            "gen",
72        ])
73        .collect()
74    })
75}
76
77fn sanitize_identifier(name: &str) -> String {
78    let keywords = rust_keyword();
79    let snake_name = name.to_snake();
80    if keywords.contains(snake_name.as_str()) {
81        snake_name + "_"
82    } else {
83        snake_name
84    }
85}
86
87pub(super) fn usize_lit(num: usize) -> m4::Literal {
88    m4::Literal::usize_unsuffixed(num)
89}
90
91pub(crate) fn ident_new(ident: &str) -> m4::Ident {
92    m4::Ident::new(ident, m4::Span::call_site())
93}
94
95pub(crate) fn ident_name(name: &str, suffix: &str) -> m4::Ident {
96    let span = m4::Span::call_site();
97    m4::Ident::new(&format!("{}{}", name, suffix).to_camel(), span)
98}
99
100pub(super) fn entity_name(name: &str) -> m4::Ident {
101    ident_name(name, "")
102}
103
104pub(super) fn reader_name(name: &str) -> m4::Ident {
105    ident_name(name, "Reader")
106}
107
108pub(super) fn entity_union_name(name: &str) -> m4::Ident {
109    ident_name(name, "Union")
110}
111
112pub(super) fn reader_union_name(name: &str) -> m4::Ident {
113    ident_name(name, "UnionReader")
114}
115
116pub(super) fn union_item_name(name: &str) -> m4::Ident {
117    ident_name(name, "")
118}
119
120pub(super) fn builder_name(name: &str) -> m4::Ident {
121    ident_name(name, "Builder")
122}
123
124pub(crate) fn field_name(name: &str) -> m4::Ident {
125    let span = m4::Span::call_site();
126    m4::Ident::new(&sanitize_identifier(name), span)
127}
128
129pub(super) fn func_name(name: &str) -> m4::Ident {
130    let span = m4::Span::call_site();
131    m4::Ident::new(&sanitize_identifier(name), span)
132}
133
134pub(super) fn entity_iterator_name(name: &str) -> m4::Ident {
135    ident_name(name, "Iterator")
136}
137
138pub(super) fn reader_iterator_name(name: &str) -> m4::Ident {
139    ident_name(name, "ReaderIterator")
140}