1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
//! Backends for the [`StringInterner`](`crate::StringInterner`). //! //! The backend is the method or strategy that handles the actual interning. //! There are trade-offs for the different kinds of backends. A user should //! find the backend that suits their use case best. mod bucket; mod simple; mod string; #[cfg(feature = "backends")] pub use self::{ bucket::BucketBackend, simple::SimpleBackend, string::StringBackend, }; use crate::Symbol; #[cfg(not(feature = "backends"))] /// Indicates that no proper backend is in use. pub struct NoBackend<S>(core::marker::PhantomData<S>); cfg_if::cfg_if! { if #[cfg(feature = "backends")] { /// The default backend recommended for general use. pub type DefaultBackend<S> = BucketBackend<S>; } else { /// The `backends` crate feature is disabled thus there is no default backend. pub type DefaultBackend<S> = NoBackend<S>; } } /// Types implementing this trait may act as backends for the string interner. /// /// The job of a backend is to actually store, manage and organize the interned /// strings. Different backends have different trade-offs. Users should pick /// their backend with hinsight of their personal use-case. pub trait Backend<S>: Default where S: Symbol, { /// Creates a new backend for the given capacity. /// /// The capacity denotes how many strings are expected to be interned. fn with_capacity(cap: usize) -> Self; /// Interns the given string and returns its interned ref and symbol. /// /// # Note /// /// The backend must make sure that the returned symbol maps back to the /// original string in its [`resolve`](`Backend::resolve`) method. fn intern(&mut self, string: &str) -> S; /// Interns the given static string and returns its interned ref and symbol. /// /// # Note /// /// The backend must make sure that the returned symbol maps back to the /// original string in its [`resolve`](`Backend::resolve`) method. #[inline] fn intern_static(&mut self, string: &'static str) -> S { // The default implementation simply forwards to the normal [`intern`] // implementation. Backends that can optimize for this use case should // implement this method. self.intern(string) } /// Resolves the given symbol to its original string contents. fn resolve(&self, symbol: S) -> Option<&str>; /// Resolves the given symbol to its original string contents. /// /// # Safety /// /// Does not perform validity checks on the given symbol and relies /// on the caller to be provided with a symbol that has been generated /// by the [`intern`](`Backend::intern`) or /// [`intern_static`](`Backend::intern_static`) methods of the same /// interner backend. unsafe fn resolve_unchecked(&self, symbol: S) -> &str; }