diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8b45424..a508781 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -11,7 +11,7 @@ env: jobs: build-std: - name: Build and test (std) + name: Build and test runs-on: ${{ matrix.os }} strategy: matrix: @@ -28,7 +28,7 @@ jobs: - name: Run dylib-tests run: cargo test -p dylib-tests --features debug-assertions build-miri: - name: Build and test (Miri) + name: Miri runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -37,6 +37,21 @@ jobs: components: miri - name: Build run: cargo +nightly miri test --features debug-assertions + wasm: + name: WASM + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Install wasm-pack + run: curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh + - name: Test stringleton-registry (Chrome) + run: cd stringleton-registry && wasm-pack test --headless --chrome --features debug-assertions && cd .. + - name: Test stringleton (Chrome) + run: cd stringleton && wasm-pack test --headless --chrome --features debug-assertions && cd .. + - name: Test stringleton-registry (Firefox) + run: cd stringleton-registry && wasm-pack test --headless --firefox --features debug-assertions && cd .. + - name: Test stringleton (Firefox) + run: cd stringleton && wasm-pack test --headless --firefox --features debug-assertions && cd .. lint: name: Lint runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 1e35a90..787d61b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,12 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" +[[package]] +name = "bumpalo" +version = "3.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" + [[package]] name = "c-dynamic-library" version = "0.1.0" @@ -15,6 +21,21 @@ dependencies = [ "stringleton-dylib", ] +[[package]] +name = "cc" +version = "1.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "check-codegen" version = "0.1.0" @@ -73,6 +94,16 @@ dependencies = [ "foldhash", ] +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + [[package]] name = "linkme" version = "0.3.32" @@ -93,6 +124,22 @@ dependencies = [ "syn", ] +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[package]] +name = "minicov" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +dependencies = [ + "cc", + "walkdir", +] + [[package]] name = "once_cell" version = "1.21.1" @@ -127,6 +174,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "serde" version = "1.0.219" @@ -147,6 +203,12 @@ dependencies = [ "syn", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "spin" version = "0.9.8" @@ -161,6 +223,7 @@ dependencies = [ "hashbrown", "linkme", "stringleton-registry", + "wasm-bindgen-test", ] [[package]] @@ -180,6 +243,7 @@ dependencies = [ "once_cell", "serde", "spin", + "wasm-bindgen-test", ] [[package]] @@ -198,3 +262,199 @@ name = "unicode-ident" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "wasm-bindgen-test" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66c8d5e33ca3b6d9fa3b4676d774c5778031d27a578c2b007f905acf816152c3" +dependencies = [ + "js-sys", + "minicov", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-bindgen-test-macro", +] + +[[package]] +name = "wasm-bindgen-test-macro" +version = "0.3.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17d5042cc5fa009658f9a7333ef24291b1291a25b6382dd68862a7f3b969f69b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/README.md b/README.md index df155da..c2239c1 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,20 @@ The latter can be supported by the `spin` and `critical-section` features: Do not use these features unless you are familiar with the tradeoffs. +## WASM caveats + +`stringleton` works in WASM binaries, but since the `wasm32-unknown-unknown` +does not support static constructors, the `sym!(..)` macro will fall back to a +slightly slower implementation that uses atomics and a single branch. (Note that +WASM is normally single-threaded, so atomic operations have no overhead.) + +Please note that it is *not* possible to pass a `Symbol` across a WASM boundary, +because the host and the guest have different views of memory, and use separate +registries. However, it is possible to pass an opaque `u64` representing the +symbol across such a boundary using `Symbol::to_ffi()` and +`Symbol::try_from_ffi()`. Getting the string representation of the symbol is +only possible on the side that owns the symbol. + ## Name The name is a portmanteau of "string" and "singleton". diff --git a/stringleton-registry/Cargo.toml b/stringleton-registry/Cargo.toml index e9d9812..64c413c 100644 --- a/stringleton-registry/Cargo.toml +++ b/stringleton-registry/Cargo.toml @@ -25,6 +25,9 @@ spin = { version = "0.9.8", optional = true, default-features = false, features "rwlock", ] } +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = "0.3" + [features] default = ["std"] std = ["alloc"] diff --git a/stringleton-registry/lib.rs b/stringleton-registry/lib.rs index 8b0ee69..110cb00 100644 --- a/stringleton-registry/lib.rs +++ b/stringleton-registry/lib.rs @@ -39,3 +39,52 @@ pub use registry::*; pub use site::*; pub use static_symbol::*; pub use symbol::*; + +#[cfg(test)] +mod tests { + use super::*; + + #[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; + + #[test] + #[cfg(feature = "alloc")] + fn new() { + let a = Symbol::new("a"); + let b = Symbol::new("b"); + let a2 = Symbol::new("a"); + assert_eq!(a, a2); + assert_ne!(a, b); + } + + #[test] + fn new_static() { + static UNIQUE_SYMBOL: &str = + "This is a globally unique string that exists nowhere else in the test binary."; + + let a = Symbol::new_static(&"a"); + let b = Symbol::new_static(&"b"); + let a2 = Symbol::new_static(&"a"); + assert_eq!(a, a2); + assert_ne!(a, b); + + let unique = Symbol::new_static(&UNIQUE_SYMBOL); + assert_eq!( + std::ptr::from_ref(unique.inner()), + std::ptr::from_ref(&UNIQUE_SYMBOL) + ); + } + + #[cfg(feature = "alloc")] + #[test] + fn address() { + let a = Symbol::new_static(&"a"); + let a2 = Symbol::new(alloc::string::String::from("a")); + assert_eq!(a, a2); + assert_eq!(a.to_ffi(), a2.to_ffi()); + let a3 = Symbol::try_from_ffi(a.to_ffi()).unwrap(); + assert_eq!(a3, a); + } +} diff --git a/stringleton-registry/site.rs b/stringleton-registry/site.rs index 30a7d3a..ba55246 100644 --- a/stringleton-registry/site.rs +++ b/stringleton-registry/site.rs @@ -21,7 +21,7 @@ pub struct Site { /// threads), so access is trivially synchronized. /// - After static initializers, this field is only ever read immutably. inner: UnsafeCell<&'static &'static str>, - #[cfg(any(miri, feature = "debug-assertions"))] + #[cfg(any(miri, target_arch = "wasm32", feature = "debug-assertions"))] initialized: AtomicBool, } @@ -39,7 +39,7 @@ impl Site { pub const fn new(string: &'static &'static str) -> Self { Self { inner: UnsafeCell::new(string), - #[cfg(any(miri, feature = "debug-assertions"))] + #[cfg(any(miri, target_arch = "wasm32", feature = "debug-assertions"))] initialized: AtomicBool::new(false), } } @@ -64,7 +64,7 @@ impl Site { #[doc(hidden)] #[inline(always)] pub unsafe fn initialize(&self, interned: Symbol) { - #[cfg(any(miri, feature = "debug-assertions"))] + #[cfg(any(miri, target_arch = "wasm32", feature = "debug-assertions"))] { self.initialized .store(true, core::sync::atomic::Ordering::SeqCst); @@ -85,13 +85,13 @@ impl Site { #[inline(always)] #[must_use] pub unsafe fn get_ref_after_ctor(&'static self) -> &'static Symbol { - #[cfg(miri)] + #[cfg(any(miri, target_arch = "wasm32"))] unsafe { // Slow path. return get_without_ctor_support(self); } - #[cfg(not(miri))] + #[cfg(not(any(miri, target_arch = "wasm32")))] unsafe { // Fast path. get_with_ctor_support(self) @@ -117,7 +117,7 @@ impl Site { /// /// Must be called after static ctors have run. #[inline(always)] -#[allow(unused)] // unused under `cfg(miri)` +#[allow(unused)] // unused under `cfg(any(miri, target_arch = "wasm32"))` unsafe fn get_with_ctor_support(site: &'static Site) -> &'static Symbol { #[cfg(feature = "debug-assertions")] { @@ -146,7 +146,7 @@ unsafe fn get_with_ctor_support(site: &'static Site) -> &'static Symbol { /// `ctor` are not supported there. It performs an atomic check on every access, /// and is therefore a lot slower. #[inline(always)] -#[cfg(miri)] +#[cfg(any(miri, target_arch = "wasm32"))] unsafe fn get_without_ctor_support(site: &'static Site) -> &'static Symbol { // CAUTION: // @@ -183,7 +183,7 @@ unsafe fn get_without_ctor_support(site: &'static Site) -> &'static Symbol { } } -#[cfg(miri)] +#[cfg(any(miri, target_arch = "wasm32"))] unsafe fn initialize_atomic(inner_ptr: *mut *mut &'static str, initialized: &'static AtomicBool) { // Cast to an atomic pointer let atomic_inner: &AtomicPtr<&'static str> = unsafe { diff --git a/stringleton-registry/symbol.rs b/stringleton-registry/symbol.rs index abcd61c..8e77596 100644 --- a/stringleton-registry/symbol.rs +++ b/stringleton-registry/symbol.rs @@ -381,46 +381,3 @@ const _: () = { } } }; - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - #[cfg(feature = "alloc")] - fn new() { - let a = Symbol::new("a"); - let b = Symbol::new("b"); - let a2 = Symbol::new("a"); - assert_eq!(a, a2); - assert_ne!(a, b); - } - - #[test] - fn new_static() { - static UNIQUE_SYMBOL: &str = - "This is a globally unique string that exists nowhere else in the test binary."; - - let a = Symbol::new_static(&"a"); - let b = Symbol::new_static(&"b"); - let a2 = Symbol::new_static(&"a"); - assert_eq!(a, a2); - assert_ne!(a, b); - - let unique = Symbol::new_static(&UNIQUE_SYMBOL); - assert_eq!( - std::ptr::from_ref(unique.inner()), - std::ptr::from_ref(&UNIQUE_SYMBOL) - ); - } - - #[test] - fn address() { - let a = Symbol::new_static(&"a"); - let a2 = Symbol::new(String::from("a")); - assert_eq!(a, a2); - assert_eq!(a.to_ffi(), a2.to_ffi()); - let a3 = Symbol::try_from_ffi(a.to_ffi()).unwrap(); - assert_eq!(a3, a); - } -} diff --git a/stringleton/Cargo.toml b/stringleton/Cargo.toml index 27b51ab..c9b7307 100644 --- a/stringleton/Cargo.toml +++ b/stringleton/Cargo.toml @@ -8,7 +8,6 @@ repository = "https://github.com/simonask/stringleton" homepage = "https://docs.rs/stringleton/latest/stringleton" keywords = ["string", "interner", "intern", "str", "symbol"] description = "Extremely fast string interning library" -readme = "../README.md" [lib] path = "lib.rs" @@ -22,6 +21,9 @@ stringleton-registry = { version = "0.1.1", path = "../stringleton-registry", de [dev-dependencies] hashbrown.workspace = true +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +wasm-bindgen-test = "0.3" + [features] default = ["std"] std = ["alloc", "stringleton-registry/std"] diff --git a/stringleton/README.md b/stringleton/README.md index df155da..c2239c1 100644 --- a/stringleton/README.md +++ b/stringleton/README.md @@ -181,6 +181,20 @@ The latter can be supported by the `spin` and `critical-section` features: Do not use these features unless you are familiar with the tradeoffs. +## WASM caveats + +`stringleton` works in WASM binaries, but since the `wasm32-unknown-unknown` +does not support static constructors, the `sym!(..)` macro will fall back to a +slightly slower implementation that uses atomics and a single branch. (Note that +WASM is normally single-threaded, so atomic operations have no overhead.) + +Please note that it is *not* possible to pass a `Symbol` across a WASM boundary, +because the host and the guest have different views of memory, and use separate +registries. However, it is possible to pass an opaque `u64` representing the +symbol across such a boundary using `Symbol::to_ffi()` and +`Symbol::try_from_ffi()`. Getting the string representation of the symbol is +only possible on the side that owns the symbol. + ## Name The name is a portmanteau of "string" and "singleton". diff --git a/stringleton/lib.rs b/stringleton/lib.rs index 437c6d3..cddbe6e 100644 --- a/stringleton/lib.rs +++ b/stringleton/lib.rs @@ -65,8 +65,8 @@ macro_rules! sym { }; (@impl $sym:expr) => {{ // Note: Using `crate` to refer to the calling crate - this is deliberate. - #[$crate::internal::linkme::distributed_slice(crate::_stringleton_enabled::TABLE)] - #[linkme(crate = $crate::internal::linkme)] + #[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 { // SAFETY: This site will be initialized by the static ctor because @@ -133,8 +133,8 @@ macro_rules! static_sym { // Tiny function just to get the `Site` for this symbol. fn _stringleton_static_symbol_call_site() -> &'static $crate::internal::Site { // Note: Using `crate` to refer to the calling crate - this is deliberate. - #[$crate::internal::linkme::distributed_slice(crate::_stringleton_enabled::TABLE)] - #[linkme(crate = $crate::internal::linkme)] + #[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 } @@ -183,6 +183,7 @@ macro_rules! static_sym { 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)] @@ -203,6 +204,7 @@ macro_rules! enable { #[allow(unused)] #[doc(hidden)] + #[cfg(not(target_arch = "wasm32"))] pub use _stringleton_enabled::_stringleton_register_symbols; }; ($krate:path) => { @@ -218,3 +220,65 @@ pub mod internal { 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)); + } +} diff --git a/stringleton/tests/basic.rs b/stringleton/tests/basic.rs deleted file mode 100644 index 8fda849..0000000 --- a/stringleton/tests/basic.rs +++ /dev/null @@ -1,52 +0,0 @@ -use hashbrown::HashMap; - -use stringleton::{StaticSymbol, Symbol, static_sym, sym}; - -stringleton::enable!(); - -#[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)); -}