SaDi - Semi-automatic Dependency Injector
A lightweight, type-safe dependency injection container for Rust applications. SaDi provides ergonomic service registration (including trait-object bindings), transient and singleton lifetimes, semi-automatic dependency resolution, and circular dependency detection.
โจ Features
- ๐ Type-Safe: Leverages Rust's type system for compile-time safety
- ๐ Transient Services: Create new instances on each request
- ๐ Singleton Services: Shared instances with reference counting via
Arc/Rc - ๐ Circular Detection: Prevents infinite loops in dependency graphs
- โ Error Handling: Comprehensive error types with detailed messages
- ๐ Optional Logging: Tracing integration with feature gates
- ๐ Zero-Cost Abstractions: Feature gates enable compile-time optimization
- ๐งต Thread-Safe by Default: Uses
Arc+RwLockfor concurrent access - ๐ฆ Module System: Organize services into reusable modules
- ๐๏ธ Enterprise Ready: Supports layered architecture, repository pattern, and use cases
๐ฆ Installation
Add this to your Cargo.toml:
[]
= { = "../sadi" } # For local development
Or from crates.io (when published):
[]
= "1.1.0"
๐ Quick Start
use ;
// Define your services
;
๏ฟฝ Examples
SaDi includes three comprehensive examples showcasing different use cases and patterns:
1. Basic Example
Location: examples/basic/
A simple introduction to SaDi fundamentals:
- Service registration with
InjectorandProvider - Transient and singleton lifetimes
- Basic dependency resolution with
try_resolve() - Error handling with
Resulttypes
Run:
2. Complex Example (Advanced Patterns)
Location: examples/complex/
Demonstrates enterprise-grade architecture with:
- Domain Layer: Clear entity definitions and repository interfaces
- Application Layer: Use case pattern for business logic
- Infrastructure Layer: SQLite persistence with concrete implementations
- Dependency Injection: Multi-level service composition
- Module System: Modular DI configuration with imported modules
Architecture:
core/
โโโ domain/ (User, Todo entities & repository traits)
โโโ application/ (CreateUserUseCase, GetAllTodoUseCase, etc.)
infra/
โโโ di/ (Modules & dependency registration)
โโโ persistence/ (SQLite repositories)
Run:
Run Tests:
3. Axum REST API Example
Location: examples/axum/
Real-world REST API integration with Axum web framework:
- HTTP handler functions with DI-resolved dependencies
- Structured JSON responses with error handling
- CRUD endpoints for Users and Todos
- Service state management via Axum's
Stateextractor - Dependency resolution per-request
Features:
POST /users- Create userGET /users- List all usersGET /users/{id}- Get user by IDDELETE /users/{id}- Delete userPOST /todos- Create todoGET /todos- List all todosPUT /todos/{id}/status- Update todo statusDELETE /todos/{id}- Delete todo
Run:
# Terminal 1: Start server
# Terminal 2: Run comprehensive test suite
The test suite includes:
- Server health checks
- Sequential dependency extraction between requests
- HTTP status code validation
- JSON response parsing and assertion
๏ฟฝ๐ Usage Guide
Service Registration
Transient Services
Create new instances on each request:
use ;
use Uuid;
let injector = new;
// Transient: new instance each time (default behavior)
injector.;
let logger1 = injector.;
let logger2 = injector.;
// logger1 and logger2 are different instances
Singleton Services
Create once and share across all dependents:
use ;
let injector = new;
// Singleton: same instance every time
injector.;
let config1 = injector.;
let config2 = injector.;
// config1 and config2 point to the same instance
Error Handling
SaDi provides both panicking and non-panicking variants:
use ;
let injector = new;
injector.;
// Non-panicking (try_resolve returns Result)
match injector.
// Trying to resolve an unregistered type
match injector.
Dependency Injection
Services can depend on other services. Use module-based registration for clean organization:
use ;
// Define a module for persistence services
;
let injector = new;
let module = PersistenceModule;
module.providers;
let repo = injector.;
๐ Advanced Features
Circular Dependency Detection
SaDi automatically detects and prevents circular dependencies by tracking resolution paths:
use ;
// Example: attempting to create circular dependencies will fail
let injector = new;
// These registrations will create a circular dependency
// Attempting to resolve either service will result in an error
// Error: "Circular dependency detected in resolution path"
Tracing Integration
Enable the tracing feature for automatic logging (the crate's default feature includes tracing):
[]
= { = "../sadi", = ["tracing"] }
use ;
use info;
;
async
๐งช Testing
Unit Tests
Run the crate test suite:
# Run all tests for the workspace
# Run tests for the sadi crate only
# Run with tracing feature
# Run documentation tests
๐ Project Structure
sadi/
โโโ sadi/ # SaDi library crate
โ โโโ src/ # core implementation (container, macros, types)
โ โโโ README.md # This file
โโโ examples/
โ โโโ basic/ # Basic usage example with simple DI
โ โโโ complex/ # Advanced DI patterns with SQLite, repositories, use cases
โ โ โโโ src/
โ โ โ โโโ core/ # Domain (entities, use cases)
โ โ โ โโโ infra/ # Infrastructure (persistence, DI configuration)
โ โ โโโ test.sh # Test script for complex example
โ โโโ axum/ # REST API with Axum web framework
โ โโโ src/
โ โ โโโ main.rs # HTTP handlers with DI integration
โ โโโ test.sh # Comprehensive API test suite
โโโ README.md
๐ง Configuration
Feature Flags
SaDi exposes a small set of feature flags. See sadi/Cargo.toml for the authoritative list, but the crate currently defines:
thread-safe(enabled by default) โ switches internal shared pointer and synchronization primitives toArc+RwLock/Mutexfor thread-safe containers.tracing(enabled by default) โ integrates with thetracingcrate to emit logs during registration/resolution.
The workspace default enables both thread-safe and tracing. To opt out of thread-safe behavior (use Rc instead of Arc), disable the thread-safe feature.
Environment Variables
When using the tracing feature, you can control logging levels:
# Set log level
RUST_LOG=debug
# Enable only SaDi logs
RUST_LOG=sadi=info
๐ค Contributing
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
Development Setup
- Clone the repository:
- Run tests:
- Check formatting:
- Run clippy:
๐ Roadmap & TODO
๐งต Thread Safety
- Arc-based Container: Thread-safe version of SaDi using
Arcinstead ofRc(implemented behind thethread-safefeature) - Send + Sync Services: Support for
Send + Syncservices in thread-safe mode (enforced by API bounds) - Concurrent Access: Concurrent reads/writes supported via
RwLock/Mutexin thread-safe mode - Lock-free Operations: Minimize contention in high-concurrency scenarios
๐ง Advanced Features
- Lazy Initialization: Singleton instances are created on first
provide(implemented inFactory) - Service Metrics: Internal container metrics for observability (resolution counts, timing)
๐ฆ Ecosystem Integration
- Async Factory Support: Enable async/await in factory functions for Tokio/async-std runtimes
- Actix-web Integration: Extension trait and extractors for Actix-web framework
- Axum Integration: Demonstrated with REST API example and state management
- Create a plugin to automatically resolve dependency
- Rocket Integration: Layer and extractor support for Rocket web framework
๏ฟฝ๏ธ Architectural Patterns
- Repository Pattern: Demonstrated in complex example with SQLite repositories
- Layered Architecture: Clean separation of domain, application, and infrastructure layers
- Use Case Pattern: Business logic encapsulated in use cases with DI
- Web Framework Integration: Explored with Axum web framework
๏ฟฝ๐ ๏ธ Developer Experience
- Derive Macros: Auto-generate factory functions from service structs (
#[injectable]) - Error Suggestions: Better error messages with fix suggestions
๐ Observability
- OpenTelemetry: Built-in telemetry and distributed tracing
- Prometheus Metrics: Expose container metrics for monitoring
๐ฏ Performance
- Memory Optimization: Reduced memory footprint for large containers
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments
- Inspired by dependency injection patterns from other languages and frameworks
- Built with โค๏ธ using Rust's powerful type system
- Thanks to the Rust community for excellent crates and documentation
SaDi - A semi-automatic dependency injection container for Rust
Repository: binary-sea/sadi
Made with โค๏ธ by the Binary Sea Team