move_symbol_pool/
lib.rs

1// Copyright (c) The Diem Core Contributors
2// Copyright (c) The Move Contributors
3// SPDX-License-Identifier: Apache-2.0
4
5//! A global, uniqued cache of strings that is never purged. Inspired by
6//! [servo/string-cache].
7//!
8//! This module provides storage for strings that are meant to remain in use for
9//! the entire running duration of a program. Strings that are stored in this
10//! global, static cache are never evicted, and so the memory consumed by them
11//! can only ever grow.
12//!
13//! The strings can be accessed via the [`Symbol`] type, which acts as a pointer
14//! to the underlying string data.
15//!
16//! NOTE: If you're looking for a `#[forbid(unsafe_code)]` attribute here, you
17//! won't find one: symbol-pool (and its inspiration, servo/string-cache) uses
18//! `unsafe` Rust in order to store and dereference `Symbol` pointers to
19//! strings.
20//!
21//! [servo/string-cache]: https://github.com/servo/string-cache
22//! [`Symbol`]: crate::Symbol
23
24mod pool;
25pub mod symbol;
26
27use once_cell::sync::Lazy;
28use pool::Pool;
29use std::sync::Mutex;
30
31pub use symbol::Symbol;
32
33/// The global, unique cache of strings.
34pub(crate) static SYMBOL_POOL: Lazy<Mutex<Pool>> = Lazy::new(|| Mutex::new(Pool::new()));
35
36#[cfg(test)]
37mod tests {
38    use crate::{Pool, Symbol, SYMBOL_POOL};
39    use std::mem::replace;
40
41    #[test]
42    fn test_serialization() {
43        // Internally, a Symbol behaves like a pointer. Naively serializing it
44        // as an address in the pool is incorrect, as it may be serialized by
45        // one process with its own pool, and deserialized by another process
46        // with a different pool.
47        let s = Symbol::from("serialize me!");
48        let serialized = serde_json::to_string(&s).unwrap();
49
50        // Artificially reset the pool for testing purposes. The address pointed
51        // to by the Symbol is now no longer valid.
52        let _ = replace(&mut SYMBOL_POOL.lock().unwrap().0, Pool::new().0);
53
54        // Below, test that deserialization still succeeds.
55        let deserialized: Symbol = serde_json::from_str(&serialized).unwrap();
56        assert_eq!(deserialized.as_str(), "serialize me!");
57    }
58}