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}