stringleton_registry/
lib.rs

1//! Registry helper crate for `stringleton`
2//!
3//! You probably don't need to use this crate directly. Use the
4//! [`stringleton`](../stringleton) crate or the
5//! [`stringleton-dylib`](../stringleton-dylib) crate instead.
6//!
7//! This crate exists to support both static and dynamic linking when using
8//! `stringleton`.
9//!
10//! All binaries in a process must use the same symbol registry, so when a
11//! dynamic library (`dylib`) dependency is using `stringleton`, this crate must
12//! also be compiled as a dynamic library, which is ensured by the [linkage
13//! rules](https://doc.rust-lang.org/reference/linkage.html).
14//!
15//! This only works automatically when such a dependency is "implicitly" linked
16//! (i.e. it is a direct dependency in `Cargo.toml`). If dynamic libraries are
17//! being loaded at runtime by the host process, Cargo must be instructed to
18//! dynamically link against the registry, which can be achieved by using the
19//! `stringleton-dylib` crate in the main binary instead of `stringleton`.
20//!
21//! Note that if a dependency is a `cdylib` (crate-type), that dependency must
22//! explicitly link against `stringleton-dylib` for this trick to work. This is
23//! not necessary when building a normal Rust `dylib`.
24
25#![no_std]
26
27#[cfg(feature = "std")]
28extern crate std;
29
30#[cfg(any(feature = "std", feature = "alloc"))]
31extern crate alloc;
32
33mod registry;
34mod site;
35mod static_symbol;
36mod symbol;
37
38pub use registry::*;
39pub use site::*;
40pub use static_symbol::*;
41pub use symbol::*;
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46
47    #[cfg(target_arch = "wasm32")]
48    wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);
49    #[cfg(target_arch = "wasm32")]
50    use wasm_bindgen_test::wasm_bindgen_test as test;
51
52    #[test]
53    #[cfg(feature = "alloc")]
54    fn new() {
55        let a = Symbol::new("a");
56        let b = Symbol::new("b");
57        let a2 = Symbol::new("a");
58        assert_eq!(a, a2);
59        assert_ne!(a, b);
60    }
61
62    #[test]
63    fn new_static() {
64        static UNIQUE_SYMBOL: &str =
65            "This is a globally unique string that exists nowhere else in the test binary.";
66
67        let a = Symbol::new_static(&"a");
68        let b = Symbol::new_static(&"b");
69        let a2 = Symbol::new_static(&"a");
70        assert_eq!(a, a2);
71        assert_ne!(a, b);
72
73        let unique = Symbol::new_static(&UNIQUE_SYMBOL);
74        assert_eq!(
75            std::ptr::from_ref(unique.inner()),
76            std::ptr::from_ref(&UNIQUE_SYMBOL)
77        );
78    }
79
80    #[cfg(feature = "alloc")]
81    #[test]
82    fn address() {
83        let a = Symbol::new_static(&"a");
84        let a2 = Symbol::new(alloc::string::String::from("a"));
85        assert_eq!(a, a2);
86        assert_eq!(a.to_ffi(), a2.to_ffi());
87        let a3 = Symbol::try_from_ffi(a.to_ffi()).unwrap();
88        assert_eq!(a3, a);
89    }
90}