pub struct Extensions {
pub map: Arc<DashMap<TypeId, Arc<dyn Any + Send + Sync>>>,
}Expand description
A thread-safe type map for storing arbitrary extensions.
Extensions provides a way to store heterogeneous data in a type-safe manner.
It uses Rust’s type system to ensure that data can only be retrieved with
the correct type, preventing runtime type errors.
§Thread Safety
This type is thread-safe and can be safely shared across threads. All operations use appropriate locking to ensure data consistency.
§Type Storage
Extensions are stored using their TypeId as the key, which means:
- Each type can only have one instance stored at a time
- Generic types with different parameters are considered different types
- Type aliases refer to the same underlying type
§Examples
§Basic Storage and Retrieval
use ignitia::Extensions;
#[derive(Clone, Debug, PartialEq)]
struct UserId(u64);
#[derive(Clone, Debug)]
struct UserName(String);
let mut extensions = Extensions::new();
// Store different types
extensions.insert(UserId(42));
extensions.insert(UserName("Alice".to_string()));
// Retrieve with type safety
let user_id = extensions.get::<UserId>().unwrap();
assert_eq!(user_id.0, 42);
let user_name = extensions.get::<UserName>().unwrap();
assert_eq!(user_name.0, "Alice");§Working with Optional Data
use ignitia::Extensions;
#[derive(Clone)]
struct OptionalData(String);
let extensions = Extensions::new();
// Safe handling of missing data
match extensions.get::<OptionalData>() {
Some(data) => println!("Found: {}", data.0),
None => println!("Data not found"),
}§Using Arc for Expensive Types
use ignitia::Extensions;
use std::sync::Arc;
#[derive(Debug)]
struct ExpensiveData {
large_vector: Vec<u8>,
}
let mut extensions = Extensions::new();
// Store as Arc to avoid expensive clones
let expensive_data = Arc::new(ExpensiveData {
large_vector: vec![0; 1000000],
});
extensions.insert(expensive_data);
// Retrieval returns Arc<Arc<ExpensiveData>>, clone is cheap
if let Some(data) = extensions.get::<Arc<ExpensiveData>>() {
println!("Data length: {}", data.large_vector.len());
}Fields§
§map: Arc<DashMap<TypeId, Arc<dyn Any + Send + Sync>>>Map of extensions.
Implementations§
Source§impl Extensions
impl Extensions
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates a new empty Extensions map.
The map starts with no stored extensions and allocates memory as needed.
§Examples
use ignitia::Extensions;
let extensions = Extensions::new();
assert!(extensions.is_empty());
assert_eq!(extensions.len(), 0);Sourcepub fn insert<T: Send + Sync + 'static>(&mut self, value: T)
pub fn insert<T: Send + Sync + 'static>(&mut self, value: T)
Inserts a value into the extensions map.
If a value of the same type was already present, it will be replaced and the old value will be dropped.
§Type Requirements
T: Send + Sync + 'static: The type must be thread-safe and have static lifetime
§Parameters
value: The value to store in the extensions map
§Examples
use ignitia::Extensions;
#[derive(Clone, Debug, PartialEq)]
struct Config {
debug: bool,
timeout: u64,
}
let mut extensions = Extensions::new();
let config = Config { debug: true, timeout: 30 };
extensions.insert(config.clone());
assert_eq!(extensions.len(), 1);
// Inserting the same type replaces the old value
let new_config = Config { debug: false, timeout: 60 };
extensions.insert(new_config.clone());
assert_eq!(extensions.len(), 1);
let retrieved = extensions.get::<Config>().unwrap();
assert_eq!(retrieved.timeout, 60);§Thread Safety
This method acquires a write lock on the internal map, so it may block if other threads are currently reading or writing.
Sourcepub fn get<T>(&self) -> Option<Arc<T>>
pub fn get<T>(&self) -> Option<Arc<T>>
Gets a reference to a value from the extensions map.
This method returns an Arc<T> for shared ownership of the retrieved value.
The value is cloned from the stored instance, so the original type must
implement Clone.
§Type Requirements
T: Send + Sync + 'static + Clone: The type must be thread-safe, have static lifetime, and be cloneable
§Returns
Some(Arc<T>)if a value of type T existsNoneif no value of type T is stored
§Examples
use ignitia::Extensions;
#[derive(Clone, Debug, PartialEq)]
struct DatabaseUrl(String);
let mut extensions = Extensions::new();
let db_url = DatabaseUrl("postgresql://localhost/mydb".to_string());
extensions.insert(db_url);
// Successful retrieval
let retrieved = extensions.get::<DatabaseUrl>().unwrap();
assert_eq!(retrieved.0, "postgresql://localhost/mydb");
// Type safety - different type returns None
#[derive(Clone)]
struct ApiKey(String);
assert!(extensions.get::<ApiKey>().is_none());§Performance
This method acquires a read lock and performs a hash map lookup by TypeId.
The lookup is O(1) on average, but the clone operation depends on the
complexity of the stored type.
Sourcepub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T>
pub fn remove<T: Send + Sync + 'static>(&mut self) -> Option<T>
Removes a value from the extensions map.
This method takes ownership of the stored value and returns it if it exists.
After removal, subsequent calls to get() or contains() for this type
will return None/false until a new value is inserted.
§Type Requirements
T: Send + Sync + 'static: The type must be thread-safe and have static lifetime
§Returns
Some(T)if a value of type T existed and was removedNoneif no value of type T was stored
§Examples
use ignitia::Extensions;
#[derive(Clone, Debug, PartialEq)]
struct SessionId(String);
let mut extensions = Extensions::new();
let session_id = SessionId("sess_123".to_string());
extensions.insert(session_id.clone());
assert!(extensions.contains::<SessionId>());
// Remove the value
let removed = extensions.remove::<SessionId>().unwrap();
assert_eq!(removed.0, "sess_123");
// Value is no longer present
assert!(!extensions.contains::<SessionId>());
assert!(extensions.get::<SessionId>().is_none());§Thread Safety
This method acquires a write lock on the internal map, so it may block if other threads are currently reading or writing.
Sourcepub fn contains<T: Send + Sync + 'static>(&self) -> bool
pub fn contains<T: Send + Sync + 'static>(&self) -> bool
Checks if the extensions map contains a value of the specified type.
This is a more efficient alternative to get().is_some() when you only
need to check for presence without retrieving the value.
§Type Requirements
T: Send + Sync + 'static: The type must be thread-safe and have static lifetime
§Returns
trueif a value of type T is storedfalseif no value of type T is stored
§Examples
use ignitia::Extensions;
#[derive(Clone)]
struct Feature1Enabled(bool);
#[derive(Clone)]
struct Feature2Enabled(bool);
let mut extensions = Extensions::new();
extensions.insert(Feature1Enabled(true));
assert!(extensions.contains::<Feature1Enabled>());
assert!(!extensions.contains::<Feature2Enabled>());
// Conditional logic based on presence
if extensions.contains::<Feature1Enabled>() {
println!("Feature 1 is configured");
}§Performance
This method only requires a read lock and performs a simple hash map
key existence check, making it more efficient than get() when you
don’t need the actual value.
Sourcepub fn insert_with_typeid(
&mut self,
type_id: TypeId,
value: Arc<dyn Any + Send + Sync>,
) -> Option<Arc<dyn Any + Send + Sync>>
pub fn insert_with_typeid( &mut self, type_id: TypeId, value: Arc<dyn Any + Send + Sync>, ) -> Option<Arc<dyn Any + Send + Sync>>
Insert a value with explicit TypeId, returns the old value if it existed
Sourcepub fn contains_typeid(&self, type_id: TypeId) -> bool
pub fn contains_typeid(&self, type_id: TypeId) -> bool
Check if a TypeId already exists in extensions
Sourcepub fn insert_if_not_exists_typeid(
&mut self,
type_id: TypeId,
value: Arc<dyn Any + Send + Sync>,
) -> bool
pub fn insert_if_not_exists_typeid( &mut self, type_id: TypeId, value: Arc<dyn Any + Send + Sync>, ) -> bool
Insert only if TypeId doesn’t already exist, returns true if inserted, false if already exists
Sourcepub fn get_by_typeid(
&self,
type_id: TypeId,
) -> Option<Ref<'_, TypeId, Arc<dyn Any + Send + Sync>>>
pub fn get_by_typeid( &self, type_id: TypeId, ) -> Option<Ref<'_, TypeId, Arc<dyn Any + Send + Sync>>>
Get a value by TypeId without type checking - returns raw boxed value
Sourcepub fn remove_by_typeid(
&mut self,
type_id: TypeId,
) -> Option<Arc<dyn Any + Send + Sync>>
pub fn remove_by_typeid( &mut self, type_id: TypeId, ) -> Option<Arc<dyn Any + Send + Sync>>
Remove a value by TypeId
Sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Returns the number of extensions stored in the map.
This counts the number of different types stored, not the total memory usage or the number of values within each type.
§Examples
use ignitia::Extensions;
#[derive(Clone)]
struct TypeA(i32);
#[derive(Clone)]
struct TypeB(String);
let mut extensions = Extensions::new();
assert_eq!(extensions.len(), 0);
extensions.insert(TypeA(42));
assert_eq!(extensions.len(), 1);
extensions.insert(TypeB("hello".to_string()));
assert_eq!(extensions.len(), 2);
// Inserting the same type again doesn't increase count
extensions.insert(TypeA(100));
assert_eq!(extensions.len(), 2);§Performance
This operation requires a read lock and calls HashMap::len(),
which is O(1).
Sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Checks if the extensions map is empty.
Returns true if no extensions are stored, false otherwise.
§Examples
use ignitia::Extensions;
#[derive(Clone)]
struct SomeData(String);
let mut extensions = Extensions::new();
assert!(extensions.is_empty());
extensions.insert(SomeData("test".to_string()));
assert!(!extensions.is_empty());
extensions.remove::<SomeData>();
assert!(extensions.is_empty());§Performance
This is equivalent to self.len() == 0 but may be slightly more
efficient depending on the HashMap implementation.
Sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Clears all extensions from the map.
After calling this method, the map will be empty and all stored extensions will be dropped.
§Examples
use ignitia::Extensions;
#[derive(Clone)]
struct Data1(i32);
#[derive(Clone)]
struct Data2(String);
let mut extensions = Extensions::new();
extensions.insert(Data1(42));
extensions.insert(Data2("hello".to_string()));
assert_eq!(extensions.len(), 2);
extensions.clear();
assert!(extensions.is_empty());
assert!(!extensions.contains::<Data1>());
assert!(!extensions.contains::<Data2>());§Thread Safety
This method acquires a write lock on the internal map. All stored values will be dropped while holding the lock.
Trait Implementations§
Source§impl Clone for Extensions
impl Clone for Extensions
Source§fn clone(&self) -> Extensions
fn clone(&self) -> Extensions
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more