global-registry

Crates.ioglobal-registry
lib.rsglobal-registry
version0.1.0
created_at2025-08-29 01:41:09.037418+00
updated_at2025-08-29 01:41:09.037418+00
descriptionA global type registration system for Rust
homepage
repositoryhttps://github.com/arthur-zhang/global-registry
max_upload_size
id1815078
size44,500
Arthur.Zhang (arthur-zhang)

documentation

README

Global Registry

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.

Rust License: MIT OR Apache-2.0

โœจ Features

  • ๐Ÿ”’ Thread-safe: Built with RwLock for safe concurrent access across multiple threads
  • ๐ŸŒ Global registry: Singleton pattern for application-wide type registration
  • ๐Ÿญ Factory pattern: Dedicated factory registry for lazy instance creation
  • ๐Ÿ“ฆ Type-safe: Leverages Rust's type system for compile-time safety
  • ๐Ÿ”„ Arc support: Built-in support for shared ownership with Arc<T>
  • โšก Zero-cost abstractions: Minimal runtime overhead
  • ๐Ÿงช Well tested: Comprehensive test coverage with real-world examples

๐Ÿ“ฆ Installation

Add this to your Cargo.toml:

[dependencies]
global-registry = "0.1.0"

๐Ÿš€ Quick Start

Basic Registration and Retrieval

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);
}

Shared Ownership with Arc

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();
}

Factory Pattern

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());
}

๐Ÿ“š API Reference

Core Registry

TypeRegistry

The main registry for storing typed values.

  • TypeRegistry::new() - Create a new registry instance
  • TypeRegistry::global() - Get the global singleton registry
  • register(value) - Register a value by its type
  • register_or_replace(value) - Register or overwrite existing value
  • get_cloned() - Get a cloned copy (requires Clone trait)
  • get() - Get an Arc<T> reference to the registered value
  • register_arc(value) - Register an Arc<T> value
  • is_registered::<T>() - Check if a type is registered
  • unregister::<T>() - Remove a type from the registry
  • clear() - Clear all registered types
  • len() - Get number of registered types

Factory Registry

Specialized registry for factory functions that create instances on demand.

  • FactoryRegistry::new() - Create a new factory registry
  • FactoryRegistry::global() - Get the global factory registry
  • register_factory(factory) - Register a factory function
  • create::<T>() - Create an instance using the registered factory

Convenient Macros

  • register!(Type, value) - Register a value in the global registry
  • register_arc!(Type, value) - Register a value wrapped in Arc (creates Arc::new() internally)
  • get!(Type) - Get an Arc reference from the global registry
  • get_cloned!(Type) - Get a cloned copy from the global registry

๐ŸŽฏ Use Cases

1. Configuration Management

use 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
}

2. Plugin System

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));
}

3. Dependency Injection

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()
}

4. Caching System

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()
}

๐Ÿ›ก๏ธ Thread Safety

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();
    }
}

โš ๏ธ Error Handling

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"),
}

๐Ÿ”ง Advanced Usage

Custom Registry Instances

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();

Type Registration Patterns

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();

๐Ÿงช Examples

The repository includes comprehensive examples:

Run examples:

cargo run --example basic_usage
cargo run --example plugin_system
cargo run --example factory_pattern
cargo run --example arc_usage_demo

๐Ÿงช Testing

Run the test suite:

cargo test

Run tests with output:

cargo test -- --nocapture

๐Ÿค Contributing

Contributions are welcome! Here's how you can help:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Make your changes with tests
  4. Run the test suite: cargo test
  5. Commit your changes: git commit -m 'Add amazing feature'
  6. Push to the branch: git push origin feature/amazing-feature
  7. Open a Pull Request

Development Guidelines

  • Write tests for new features
  • Follow Rust's naming conventions
  • Add documentation for public APIs
  • Ensure thread safety for concurrent operations

๐Ÿ“„ License

This project is licensed under either of

at your option.

๐Ÿ™ Acknowledgments

  • Built with โค๏ธ for the Rust community
  • Inspired by dependency injection patterns from other languages
  • Thanks to all contributors and users providing feedback

Happy coding! ๐Ÿฆ€

Commit count: 2

cargo fmt