#![doc = include_str!("README.md")]
pub use stringleton_registry::{Registry, StaticSymbol, Symbol};
#[macro_export]
#[allow(clippy::crate_in_macro_def)]
macro_rules! sym {
($sym:ident) => {
$crate::sym!(@impl stringify!($sym))
};
($sym:literal) => {
$crate::sym!(@impl $sym)
};
(@impl $sym:expr) => {{
#[cfg_attr(not(target_arch = "wasm32"), $crate::internal::linkme::distributed_slice(crate::_stringleton_enabled::TABLE))]
#[cfg_attr(not(target_arch = "wasm32"), linkme(crate = $crate::internal::linkme))]
static SITE: $crate::internal::Site = $crate::internal::Site::new(&$sym);
unsafe {
SITE.get_after_ctor()
}}
}
}
#[macro_export]
#[allow(clippy::crate_in_macro_def)]
macro_rules! static_sym {
($sym:ident) => {
$crate::static_sym!(@impl stringify!($sym))
};
($sym:literal) => {
$crate::static_sym!(@impl $sym)
};
(@impl $sym:expr) => {{
unsafe {
$crate::StaticSymbol::new_unchecked({
fn _stringleton_static_symbol_call_site() -> &'static $crate::internal::Site {
#[cfg_attr(not(target_arch = "wasm32"), $crate::internal::linkme::distributed_slice(crate::_stringleton_enabled::TABLE))]
#[cfg_attr(not(target_arch = "wasm32"), linkme(crate = $crate::internal::linkme))]
static SITE: $crate::internal::Site = $crate::internal::Site::new(&$sym);
&SITE
}
_stringleton_static_symbol_call_site
})
}
}}
}
#[macro_export]
macro_rules! enable {
() => {
#[doc(hidden)]
#[cfg(not(target_arch = "wasm32"))]
pub(crate) mod _stringleton_enabled {
#[$crate::internal::linkme::distributed_slice]
#[linkme(crate = $crate::internal::linkme)]
#[doc(hidden)]
pub(crate) static TABLE: [$crate::internal::Site] = [..];
$crate::internal::ctor::declarative::ctor! {
#[ctor]
#[doc(hidden)]
pub fn _stringleton_register_symbols() {
unsafe {
$crate::internal::Registry::register_sites(&TABLE);
}
}
}
}
#[allow(unused)]
#[doc(hidden)]
#[cfg(not(target_arch = "wasm32"))]
pub use _stringleton_enabled::_stringleton_register_symbols;
};
($krate:path) => {
#[doc(hidden)]
pub(crate) use $krate::_stringleton_enabled;
};
}
#[doc(hidden)]
pub mod internal {
pub use ctor;
pub use linkme;
pub use stringleton_registry::Registry;
pub use stringleton_registry::Site;
}
#[cfg(test)]
enable!();
#[cfg(test)]
mod tests {
#[cfg(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::wasm_bindgen_test as test;
use hashbrown::HashMap;
use super::{StaticSymbol, Symbol, static_sym, sym};
#[test]
#[cfg(feature = "alloc")]
fn basic() {
let a = sym!(a);
let b = sym!(b);
let c = sym!(c);
let a2 = sym!(a);
assert_ne!(a, b);
assert_ne!(a, c);
assert_ne!(b, c);
assert_eq!(a, a2);
}
#[test]
fn sym_macro() {
let ident: Symbol = sym!(hello);
let string: Symbol = sym!("hello");
let dynamic = Symbol::new_static(&"hello");
assert_eq!(ident, string);
assert_eq!(ident, dynamic);
let mut map = HashMap::new();
map.insert(ident, 1);
map.insert(string, 2);
map.insert(dynamic, 3);
assert_eq!(map.len(), 1);
assert!(map.into_iter().eq([(ident, 3)]));
assert_eq!(ident.to_string(), "hello");
assert_eq!(ident.as_str(), "hello");
let t = sym!(SYM_CACHE);
assert_eq!(t, "SYM_CACHE");
}
#[test]
fn statics() {
static A: StaticSymbol = static_sym!(a);
const A2: StaticSymbol = static_sym!(a);
const C: StaticSymbol = static_sym!(c);
assert_eq!(A, A2);
assert_eq!(A, sym!(a));
assert_ne!(A2, sym!(b));
assert_eq!(C, sym!(c));
}
}