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 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
mod boxed;
mod rodeo;
mod rodeo_reader;
mod rodeo_resolver;
mod tests;
mod threaded_ref;
mod threaded_rodeo;
use crate::{Key, LassoResult, Spur};
#[cfg(feature = "no-std")]
use alloc::boxed::Box;
/// A generic interface over any underlying interner, allowing storing and accessing
/// interned strings
///
/// Note that because single-threaded [`Rodeo`](crate::Rodeo)s require mutable access to use, this
/// trait does so as well. For use with [`ThreadedRodeo`](crate::ThreadedRodeo), the trait is
/// implemented for `&ThreadedRodeo` as well to allow access through shared references.
pub trait Interner<K = Spur>: Reader<K> + Resolver<K> {
/// Get the key for a string, interning it if it does not yet exist
///
/// # Panics
///
/// Panics if the key's [`try_from_usize`](Key::try_from_usize) function fails. With the default
/// keys, this means that you've interned more strings than it can handle. (For [`Spur`] this
/// means that `u32::MAX - 1` unique strings were interned)
///
fn get_or_intern(&mut self, val: &str) -> K;
/// Get the key for a string, interning it if it does not yet exist
fn try_get_or_intern(&mut self, val: &str) -> LassoResult<K>;
/// Get the key for a static string, interning it if it does not yet exist
///
/// This will not reallocate or copy the given string
///
/// # Panics
///
/// Panics if the key's [`try_from_usize`](Key::try_from_usize) function fails. With the default
/// keys, this means that you've interned more strings than it can handle. (For [`Spur`] this
/// means that `u32::MAX - 1` unique strings were interned)
///
fn get_or_intern_static(&mut self, val: &'static str) -> K;
/// Get the key for a static string, interning it if it does not yet exist
///
/// This will not reallocate or copy the given string
fn try_get_or_intern_static(&mut self, val: &'static str) -> LassoResult<K>;
}
/// A generic interface over interners that can be turned into both a [`Reader`] and a [`Resolver`]
/// directly.
pub trait IntoReaderAndResolver<K = Spur>: IntoReader<K> + IntoResolver<K>
where
K: Key,
{
}
/// A generic interface over interners that can be turned into a [`Reader`].
pub trait IntoReader<K = Spur>: Interner<K>
where
K: Key,
{
/// The type of [`Reader`] the interner will be converted into
type Reader: Reader<K>;
/// Consumes the current [`Interner`] and converts it into a [`Reader`] to allow
/// contention-free access of the interner from multiple threads
#[must_use]
fn into_reader(self) -> Self::Reader
where
Self: 'static;
/// An implementation detail to allow calling [`Interner::into_reader()`] on dynamically
/// dispatched interners
#[doc(hidden)]
#[must_use]
fn into_reader_boxed(self: Box<Self>) -> Self::Reader
where
Self: 'static;
}
/// A generic interface that allows using any underlying interner for
/// both its reading and resolution capabilities, allowing both
/// `str -> key` and `key -> str` lookups
pub trait Reader<K = Spur>: Resolver<K> {
/// Get a key for the given string value if it exists
fn get(&self, val: &str) -> Option<K>;
/// Returns `true` if the current interner contains the given string
fn contains(&self, val: &str) -> bool;
}
/// A generic interface over [`Reader`]s that can be turned into a [`Resolver`].
pub trait IntoResolver<K = Spur>: Reader<K>
where
K: Key,
{
/// The type of [`Resolver`] the reader will be converted into
type Resolver: Resolver<K>;
/// Consumes the current [`Reader`] and makes it into a [`Resolver`], allowing
/// contention-free access from multiple threads with the lowest possible memory consumption
#[must_use]
fn into_resolver(self) -> Self::Resolver
where
Self: 'static;
/// An implementation detail to allow calling [`Reader::into_resolver()`] on dynamically
/// dispatched readers
#[doc(hidden)]
#[must_use]
fn into_resolver_boxed(self: Box<Self>) -> Self::Resolver
where
Self: 'static;
}
/// A generic interface that allows using any underlying interner only
/// for its resolution capabilities, allowing only `key -> str` lookups
pub trait Resolver<K = Spur> {
/// Resolves the given key into a string
///
/// # Panics
///
/// Panics if the key is not contained in the current [`Resolver`]
///
fn resolve<'a>(&'a self, key: &K) -> &'a str;
/// Attempts to resolve the given key into a string, returning `None`
/// if it cannot be found
fn try_resolve<'a>(&'a self, key: &K) -> Option<&'a str>;
/// Resolves a string by its key without preforming bounds checks
///
/// # Safety
///
/// The key must be valid for the current [`Resolver`]
///
unsafe fn resolve_unchecked<'a>(&'a self, key: &K) -> &'a str;
/// Returns `true` if the current interner contains the given key
fn contains_key(&self, key: &K) -> bool;
/// Gets the number of currently interned strings
fn len(&self) -> usize;
/// Returns `true` if there are no currently interned strings
#[cfg_attr(feature = "inline-more", inline)]
fn is_empty(&self) -> bool {
self.len() == 0
}
}