| Crates.io | global-registry |
| lib.rs | global-registry |
| version | 0.1.0 |
| created_at | 2025-08-29 01:41:09.037418+00 |
| updated_at | 2025-08-29 01:41:09.037418+00 |
| description | A global type registration system for Rust |
| homepage | |
| repository | https://github.com/arthur-zhang/global-registry |
| max_upload_size | |
| id | 1815078 |
| size | 44,500 |
A thread-safe global type registration system for Rust that allows you to register types globally by their TypeId and retrieve them later. Perfect for implementing registries, factories, plugin systems, and dependency injection patterns.
RwLock for safe concurrent access across multiple threadsArc<T>Add this to your Cargo.toml:
[dependencies]
global-registry = "0.1.0"
use global_registry::{TypeRegistry, register};
#[derive(Clone, Debug)]
struct DatabaseConfig {
host: String,
port: u16,
}
fn main() {
// Register a type globally
register!(DatabaseConfig, DatabaseConfig {
host: "localhost".to_string(),
port: 5432,
}).unwrap();
// Retrieve and use the registered type
let config = TypeRegistry::global()
.get_cloned::<DatabaseConfig>()
.unwrap();
println!("Connecting to {}:{}", config.host, config.port);
}
use global_registry::{register_arc, get};
use std::sync::Arc;
#[derive(Debug)]
struct DatabaseConnection {
host: String,
connected: bool,
}
fn main() {
let connection = DatabaseConnection {
host: "localhost".to_string(),
connected: true,
};
// Register with Arc (automatically wraps in Arc::new)
register_arc!(DatabaseConnection, connection).unwrap();
// Get shared Arc reference
let arc_conn = get!(DatabaseConnection).unwrap();
println!("Connection: {:?}", arc_conn);
// Can be cloned and shared across threads
let conn_clone = arc_conn.clone();
}
use global_registry::{FactoryRegistry, Factory};
trait DatabaseService {
fn connect(&self) -> String;
}
struct PostgreSQLService;
impl DatabaseService for PostgreSQLService {
fn connect(&self) -> String {
"Connected to PostgreSQL".to_string()
}
}
fn main() {
let factory_registry = FactoryRegistry::global();
// Register a factory function
let factory: Factory<PostgreSQLService> = Box::new(|| PostgreSQLService);
factory_registry.register_factory(factory).unwrap();
// Create instances on demand
let service = factory_registry.create::<PostgreSQLService>().unwrap();
println!("{}", service.connect());
}
The main registry for storing typed values.
TypeRegistry::new() - Create a new registry instanceTypeRegistry::global() - Get the global singleton registryregister(value) - Register a value by its typeregister_or_replace(value) - Register or overwrite existing valueget_cloned() - Get a cloned copy (requires Clone trait)get() - Get an Arc<T> reference to the registered valueregister_arc(value) - Register an Arc<T> valueis_registered::<T>() - Check if a type is registeredunregister::<T>() - Remove a type from the registryclear() - Clear all registered typeslen() - Get number of registered typesSpecialized registry for factory functions that create instances on demand.
FactoryRegistry::new() - Create a new factory registryFactoryRegistry::global() - Get the global factory registryregister_factory(factory) - Register a factory functioncreate::<T>() - Create an instance using the registered factoryregister!(Type, value) - Register a value in the global registryregister_arc!(Type, value) - Register a value wrapped in Arc (creates Arc::new() internally)get!(Type) - Get an Arc reference from the global registryget_cloned!(Type) - Get a cloned copy from the global registryuse global_registry::{register, TypeRegistry};
#[derive(Clone, Debug)]
struct AppConfig {
debug: bool,
max_connections: usize,
}
// Register configuration at startup
register!(AppConfig, AppConfig {
debug: true,
max_connections: 100,
}).unwrap();
// Access configuration anywhere in your app
fn get_max_connections() -> usize {
TypeRegistry::global()
.get_cloned::<AppConfig>()
.unwrap()
.max_connections
}
use global_registry::{register, TypeRegistry};
trait Plugin: Send + Sync {
fn name(&self) -> &str;
fn execute(&self, input: &str) -> String;
}
#[derive(Clone)]
struct EmailPlugin {
smtp_server: String,
}
impl Plugin for EmailPlugin {
fn name(&self) -> &str { "Email Plugin" }
fn execute(&self, input: &str) -> String {
format!("Sending email via {}: {}", self.smtp_server, input)
}
}
// Register plugins
register!(EmailPlugin, EmailPlugin {
smtp_server: "smtp.example.com".to_string(),
}).unwrap();
// Use plugins
fn send_notification(message: &str) {
let plugin = TypeRegistry::global()
.get_cloned::<EmailPlugin>()
.unwrap();
println!("{}", plugin.execute(message));
}
use global_registry::{register_arc, get};
use std::sync::Arc;
trait UserRepository: Send + Sync {
fn find_user(&self, id: u32) -> Option<String>;
}
struct DatabaseUserRepository {
connection_string: String,
}
impl UserRepository for DatabaseUserRepository {
fn find_user(&self, id: u32) -> Option<String> {
Some(format!("User {} from {}", id, self.connection_string))
}
}
// Register dependency
register_arc!(DatabaseUserRepository, DatabaseUserRepository {
connection_string: "postgresql://localhost/myapp".to_string(),
}).unwrap();
// Inject dependency
fn get_user_service() -> Arc<DatabaseUserRepository> {
get!(DatabaseUserRepository).unwrap()
}
use global_registry::{register_arc, get};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
type Cache = Arc<Mutex<HashMap<String, String>>>;
// Register shared cache
register_arc!(Cache, Arc::new(Mutex::new(HashMap::new()))).unwrap();
fn cache_set(key: String, value: String) {
let cache = get!(Cache).unwrap();
cache.lock().unwrap().insert(key, value);
}
fn cache_get(key: &str) -> Option<String> {
let cache = get!(Cache).unwrap();
cache.lock().unwrap().get(key).cloned()
}
The registry is fully thread-safe and designed for concurrent access:
use global_registry::{register, TypeRegistry};
use std::sync::Arc;
use std::thread;
#[derive(Clone, Debug)]
struct Counter(usize);
fn main() {
register!(Counter, Counter(0)).unwrap();
let handles: Vec<_> = (0..10)
.map(|i| {
thread::spawn(move || {
// Each thread can safely access the registry
let counter = TypeRegistry::global()
.get_cloned::<Counter>()
.unwrap();
println!("Thread {}: {:?}", i, counter);
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
}
The crate provides comprehensive error types:
use global_registry::{RegistryError, register};
#[derive(Clone)]
struct MyType;
match register!(MyType, MyType) {
Ok(()) => println!("Registered successfully"),
Err(RegistryError::TypeAlreadyExists) => println!("Type already registered"),
Err(RegistryError::TypeNotFound) => println!("Type not found"),
Err(RegistryError::LockError) => println!("Failed to acquire lock"),
Err(RegistryError::InvalidCast) => println!("Type casting failed"),
}
use global_registry::TypeRegistry;
// Create isolated registry instances for different contexts
let user_registry = TypeRegistry::new();
let system_registry = TypeRegistry::new();
// Each registry maintains its own separate state
user_registry.register(UserConfig::default()).unwrap();
system_registry.register(SystemConfig::default()).unwrap();
use global_registry::{register_arc, get};
// Register different types
register_arc!(String, "Hello, World!".to_string()).unwrap();
register_arc!(i32, 42).unwrap();
register_arc!(Vec<String>, vec!["a".to_string(), "b".to_string()]).unwrap();
// Retrieve with full type safety
let message: Arc<String> = get!(String).unwrap();
let number: Arc<i32> = get!(i32).unwrap();
let list: Arc<Vec<String>> = get!(Vec<String>).unwrap();
The repository includes comprehensive examples:
basic_usage.rs - Basic registration and retrievalplugin_system.rs - Dynamic plugin system implementationfactory_pattern.rs - Factory pattern with different database servicesarc_usage_demo.rs - Shared ownership with ArcRun examples:
cargo run --example basic_usage
cargo run --example plugin_system
cargo run --example factory_pattern
cargo run --example arc_usage_demo
Run the test suite:
cargo test
Run tests with output:
cargo test -- --nocapture
Contributions are welcome! Here's how you can help:
git checkout -b feature/amazing-featurecargo testgit commit -m 'Add amazing feature'git push origin feature/amazing-featureThis project is licensed under either of
at your option.
Happy coding! ๐ฆ