4 releases
Uses new Rust 2024
new 0.2.2 | Apr 25, 2025 |
---|---|
0.2.1 | Apr 25, 2025 |
0.1.6-beta | Apr 24, 2025 |
#103 in Configuration
389 downloads per month
95KB
1.5K
SLoC
confucius - Configuration Management Library in Rust
______ ____ _
/ ____/___ ____ / __/_ _________(_)_ _______
/ / / __ \/ __ \/ /_/ / / / ___/ / / / / / ___/
/ /___/ /_/ / / / / __/ /_/ / /__/ / / /_/ (__ )
\____/\____/_/ /_/_/ \__,_/\___/_/_/\__,_/____/
"Wisdom in configuration"
confucius
is a Rust library that simplifies configuration file management for applications. Designed to be flexible and intuitive, it offers support for various formats and includes advanced features such as file inclusion and automatic configuration file discovery.
Features
- Automatic search for configuration files in standard paths
- Support for various configuration formats:
- INI
- TOML
- YAML
- JSON
- Inclusion mechanism for importing multiple files or with glob patterns
- Format identification via shebang (
#!config/FORMAT
) - Support for inline comments (
# comment
) - Support for text values in double quotes
Search Paths
The library automatically searches for configuration files in the following paths (in order of priority), where appname
is the name of the application:
/etc/appname/appname.conf
/etc/appname.conf
/opt/etc/appname.conf
/home/username/.config/appname/appname.conf
/home/username/.config/appname.conf
<executable_path>/appname.conf
Installation
Add this dependency to your Cargo.toml
:
[dependencies]
confucius = "0.1.5-beta"
Usage Example
use confucius::{Config, ConfigValue, ConfigFormat};
use std::path::Path;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Create a configuration for an app called "myapp"
let mut config = Config::new("myapp");
// Load the configuration from default paths
match config.load() {
Ok(_) => println!("Configuration loaded successfully!"),
Err(e) => {
println!("Error loading configuration: {}", e);
// Load from a specific path
config.load_from_file(Path::new("/path/to/myapp.conf"))?;
}
}
// Read values
if let Some(server) = config.get("server", "hostname") {
if let Some(hostname) = server.as_string() {
println!("Server: {}", hostname);
}
}
// Modify values
config.set("app", "version", ConfigValue::String("1.1.0".to_string()));
// Save the configuration
config.save()?;
Ok(())
}
Configuration Validation
confucius
offers a powerful validation system that allows you to verify that the values in your configuration meet certain constraints:
use confucius::validation::{ValidationSchema, ValidationExt, FieldDefinition, FieldConstraint, ValueType};
// Create a validation schema
let mut schema = ValidationSchema::new();
// Define sections and fields
schema
.required_section("server")
.field(
"server",
"port",
FieldDefinition::new(ValueType::Integer)
.required()
.constraint(FieldConstraint::integer().min_int(1).max_int(65535))
);
// Validate the configuration
match config.validate(&schema) {
Ok(_) => println!("Valid configuration!"),
Err(errors) => println!("Errors: {}", errors),
}
For more details on validation, see the dedicated section.
Examples of Supported Configuration Formats
INI Format
#!config/ini
# This is a comment
[app]
name = "My Application"
version = "1.0.0"
debug = true # Inline comment
[server]
hostname = "localhost"
port = 8080
# Include other configuration files
include=/etc/myapp/extra.conf
include=/etc/myapp/conf.d/*.conf
TOML Format
#!config/toml
# This is a comment
[app]
name = "My Application"
version = "1.0.0"
debug = true
[server]
hostname = "localhost"
port = 8080
# Include other configuration files
include = [
"/etc/myapp/extra.conf",
"/etc/myapp/conf.d/*.conf"
]
# TOML format also supports arrays and nested tables
[database]
connections = [
{ name = "main", host = "localhost", port = 5432 },
{ name = "replica", host = "replica.example.com", port = 5432 }
]
YAML Format
#!config/yaml
# This is a comment
app:
name: "My Application"
version: "1.0.0"
debug: true
server:
hostname: "localhost"
port: 8080
# Include other configuration files
include:
- /etc/myapp/extra.conf
- /etc/myapp/conf.d/*.conf
# YAML format supports complex data structures
database:
connections:
- name: main
host: localhost
port: 5432
- name: replica
host: replica.example.com
port: 5432
JSON Format
#!config/json
{
"app": {
"name": "My Application",
"version": "1.0.0",
"debug": true
},
"server": {
"hostname": "localhost",
"port": 8080
},
"include": [
"/etc/myapp/extra.conf",
"/etc/myapp/conf.d/*.conf"
],
"database": {
"connections": [
{
"name": "main",
"host": "localhost",
"port": 5432
},
{
"name": "replica",
"host": "replica.example.com",
"port": 5432
}
]
}
}
Include Mechanism
The library supports the inclusion of other configuration files through the include
directive:
# Include a single file
include=/path/to/extra.conf
# Include all files with .conf extension in a directory
include=/path/to/conf.d/*.conf
Configuration Validation
confucius
offers a powerful validation system that allows you to define a schema for configuration files and verify that values meet the defined constraints.
Features of the Validation System
- Definition of required sections and fields
- Specification of expected data types
- Custom constraints for each data type
- Default values that are automatically applied
- Detailed error messages
Validation Usage Example
use confucius::{Config, ConfigValue};
use confucius::validation::{ValidationSchema, ValidationExt, FieldDefinition, FieldConstraint, ValueType};
// Create a validation schema
let mut schema = ValidationSchema::new();
// Define required sections
schema.required_section("server");
// Define fields for the "server" section
schema.field(
"server",
"hostname",
FieldDefinition::new(ValueType::String)
.required()
.description("Server hostname")
.constraint(FieldConstraint::string()
.min_length(3)
.max_length(255))
);
schema.field(
"server",
"port",
FieldDefinition::new(ValueType::Integer)
.required()
.description("Server port")
.constraint(FieldConstraint::integer()
.min_int(1)
.max_int(65535))
);
// Load the configuration
let mut config = Config::new("myapp");
config.load()?;
// Apply default values defined in the schema
config.apply_defaults(&schema);
// Validate the configuration
match config.validate(&schema) {
Ok(_) => println!("The configuration is valid!"),
Err(errors) => println!("Validation errors: {}", errors),
}
// Alternatively, we can do both operations in a single call
match config.validate_and_apply_defaults(&schema) {
Ok(_) => println!("The configuration is valid!"),
Err(errors) => println!("Validation errors: {}", errors),
}
Available Constraint Types
String Constraints
FieldConstraint::string()
.min_length(3) // Minimum length
.max_length(255) // Maximum length
.pattern("^[a-z]+$") // Regex pattern
.allowed_string_values(vec!["value1", "value2"]) // Allowed values
Integer Constraints
FieldConstraint::integer()
.min_int(1) // Minimum value
.max_int(1000) // Maximum value
.allowed_int_values(vec![1, 2, 3]) // Allowed values
Float Constraints
FieldConstraint::float()
.min_float(0.0) // Minimum value
.max_float(100.0) // Maximum value
Array Constraints
FieldConstraint::array()
.min_length(1) // Minimum length
.max_length(10) // Maximum length
.item_type( // Element type
FieldDefinition::new(ValueType::String)
.constraint(FieldConstraint::string().min_length(3))
)
Custom Constraints
FieldConstraint::custom(
|value| {
// Custom validation function
// Returns Ok(()) if the value is valid, Err(String) otherwise
Ok(())
},
"Constraint description"
)
Future Development
- Support for overriding through environment variables
- Hot-reload functionality to reload configuration when it changes
- Performance improvements with serialization support using serde
- Addition of custom formatting options for file writing
License
This project is released under the MIT license.
Dependencies
~5–13MB
~156K SLoC