myth_core/utils/
interner.rs1use lasso::Spur;
8use std::borrow::Cow;
9
10#[cfg(not(target_arch = "wasm32"))]
11use lasso::ThreadedRodeo;
12
13#[cfg(target_arch = "wasm32")]
14use lasso::Rodeo;
15#[cfg(target_arch = "wasm32")]
16use std::cell::UnsafeCell;
17
18#[cfg(not(target_arch = "wasm32"))]
20static INTERNER: std::sync::LazyLock<ThreadedRodeo> = std::sync::LazyLock::new(ThreadedRodeo::new);
21
22#[cfg(target_arch = "wasm32")]
23thread_local! {
29 static INTERNER: UnsafeCell<Rodeo> = UnsafeCell::new(Rodeo::new());
30}
31
32pub type Symbol = Spur;
37
38#[cfg(not(target_arch = "wasm32"))]
43#[inline]
44pub fn intern(s: &str) -> Symbol {
45 INTERNER.get_or_intern(s)
46}
47
48#[cfg(target_arch = "wasm32")]
49#[inline]
50pub fn intern(s: &str) -> Symbol {
51 INTERNER.with(|interner| unsafe { (*interner.get()).get_or_intern(s) })
55}
56
57#[cfg(not(target_arch = "wasm32"))]
62#[inline]
63pub fn get(s: &str) -> Option<Symbol> {
64 INTERNER.get(s)
65}
66
67#[cfg(target_arch = "wasm32")]
68#[inline]
69pub fn get(s: &str) -> Option<Symbol> {
70 INTERNER.with(|interner| unsafe { (*interner.get()).get(s) })
72}
73
74#[cfg(not(target_arch = "wasm32"))]
82#[inline]
83pub fn resolve(sym: Symbol) -> Cow<'static, str> {
84 Cow::Borrowed(INTERNER.resolve(&sym))
85}
86
87#[cfg(target_arch = "wasm32")]
89#[inline]
90pub fn resolve(sym: Symbol) -> Cow<'static, str> {
91 INTERNER.with(|interner| unsafe { Cow::Owned((*interner.get()).resolve(&sym).to_string()) })
92}
93
94pub fn preload_common_macros() {
99 let common = [
100 "USE_IBL",
102 "USE_IOR",
103 "USE_SPECULAR",
104 "USE_CLEARCOAT",
105 "USE_SHEEN",
106 "USE_IRIDESCENCE",
107 "USE_ANISOTROPY",
108 "USE_TRANSMISSION",
109 "USE_DISPERSION",
110 "HAS_MAP",
112 "HAS_NORMAL_MAP",
113 "HAS_ROUGHNESS_MAP",
114 "HAS_METALNESS_MAP",
115 "HAS_EMISSIVE_MAP",
116 "HAS_AO_MAP",
117 "HAS_SPECULAR_MAP",
118 "HAS_SPECULAR_INTENSITY_MAP",
119 "HAS_CLEARCOAT_MAP",
120 "HAS_CLEARCOAT_ROUGHNESS_MAP",
121 "HAS_CLEARCOAT_NORMAL_MAP",
122 "HAS_SHEEN_COLOR_MAP",
123 "HAS_SHEEN_ROUGHNESS_MAP",
124 "HAS_IRIDESCENCE_MAP",
125 "HAS_IRIDESCENCE_THICKNESS_MAP",
126 "HAS_ANISOTROPY_MAP",
127 "HAS_TRANSMISSION_MAP",
128 "HAS_THICKNESS_MAP",
129 "HAS_UV",
131 "HAS_NORMAL",
132 "HAS_COLOR",
133 "HAS_TANGENT",
134 "HAS_SKINNING",
135 "HAS_MORPH_TARGETS",
136 "HAS_MORPH_NORMALS",
137 "HAS_MORPH_TANGENTS",
138 "SUPPORT_SKINNING",
139 "HAS_ENV_MAP",
141 "HAS_SHADOWS",
142 "USE_SSAO",
143 "USE_SCREEN_SPACE_FEATURES",
144 "USE_SSS",
145 "USE_SSR",
146 "HAS_MRT_SSSS",
147 "ALPHA_MODE",
149 "OPAQUE",
150 "MASK",
151 "BLEND",
152 "BLEND_MASK",
153 "ALPHA_TO_COVERAGE",
154 "HDR",
155 "IN_TRANSPARENT_PASS",
156 "TONE_MAPPING_MODE",
158 "NEUTRAL",
159 "LINEAR",
160 "REINHARD",
161 "CINEON",
162 "ACES_FILMIC",
163 "AGX",
164 "AGX_LOOK",
165 "0",
167 "1",
168 "true",
169 "false",
170 ];
171
172 for name in common {
173 intern(name);
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 #[test]
182 fn test_intern_and_resolve() {
183 let s1 = intern("hello");
184 let s2 = intern("hello");
185 let s3 = intern("world");
186
187 assert_eq!(s1, s2);
188 assert_ne!(s1, s3);
189
190 assert_eq!(resolve(s1), "hello");
191 assert_eq!(resolve(s3), "world");
192 }
193
194 #[test]
195 fn test_get() {
196 let _ = intern("existing");
197
198 assert!(get("existing").is_some());
199 assert!(get("non_existing").is_none());
200 }
201}