Usage
You can use noml
both as a command-line tool for validating and converting configuration files, and as a library in your Rust projects.
Command-Line Interface (CLI)
The noml
CLI provides a simple way to work with NOML files.
Validate a NOML file:
Parse and display the structure of a NOML file:
Show version information:
In your Rust project
To use noml
in your project, add it as a dependency in your Cargo.toml
:
[]
= "0.4.0"
You can also enable the chrono
feature for date/time support and the async
feature for async operations:
[]
= { = "0.4.0", = ["chrono", "async"] }
Examples
Here are some examples of how to use the noml
library in your Rust code.
Basic Parsing
You can easily parse a NOML string and access its values.
use parse;
let source = r#"
name = "my-app"
version = "1.0.0"
debug = true
[server]
host = "localhost"
port = 8080
"#;
let config = parse?;
// Access top-level values
assert_eq!;
assert_eq!;
// Access nested values
assert_eq!;
assert_eq!;
Using Environment Variables
noml
can pull values from environment variables using the env()
function, with an optional default value.
use parse;
use env;
// Set an environment variable for the test
set_var;
let source = r#"
db_url = env("DATABASE_URL")
secret_key = env("API_KEY", "default-secret")
"#;
let config = parse?;
assert_eq!;
assert_eq!;
HTTP Includes (Async Feature)
With the async
feature enabled, you can include configuration from remote HTTP/HTTPS URLs:
use parse_from_file_async;
// config.noml content:
// base_config = include "https://config.example.com/app-defaults.noml"
// api_key = env("API_KEY")
// debug = true
async
HTTP Includes Features:
- ✅ Secure HTTPS Support: Full support for HTTPS URLs with proper certificate validation
- ⚡ Automatic Caching: Remote configs are cached to improve performance and reduce network requests
- 🔒 Timeout Protection: Configurable request timeouts prevent hanging operations
- 🔄 Error Handling: Clear error messages for network issues, HTTP errors, and parse failures
- 📦 No Nested HTTP: HTTP includes cannot contain other HTTP includes (prevents security issues)
[]
= { = "0.4.0", = ["async"] }
= { = "1.0", = ["full"] }
Working with Native Types
noml
supports special native types for common configuration values like file sizes, durations, IP addresses, and more.
use parse;
let source = r#"
# File sizes and durations
max_upload_size = @size("256MB")
request_timeout = @duration("90s")
# Network and web
website = @url("https://example.com")
server_ip = @ip("192.168.1.100")
# Data formats
app_version = @semver("2.1.0")
secret_data = @base64("SGVsbG8gV29ybGQ=")
user_id = @uuid("550e8400-e29b-41d4-a716-446655440000")
"#;
let config = parse?;
// The values are parsed and validated
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Available Native Types:
@size("10MB")
- File/memory sizes (KB, MB, GB, etc.)@duration("30s")
- Time durations (s, m, h, d)@url("https://...")
- URL validation@ip("192.168.1.1")
- IP address validation (IPv4/IPv6)@semver("1.2.3")
- Semantic version parsing@base64("SGVsbG8=")
- Base64 encoded data@uuid("550e8400-...")
- UUID format validation
Working with Arrays and Tables
noml
fully supports arrays, inline tables, and arrays of tables, similar to TOML.
use parse;
let source = r#"
# An array of strings
allowed_roles = ["admin", "editor", "viewer"]
# An inline table
point = { x = 1.0, y = -1.0 }
# An array of tables
[[users]]
name = "Alice"
email = "alice@example.com"
[[users]]
name = "Bob"
email = "bob@example.com"
"#;
let config = parse?;
// Access array elements
let roles = config.get.unwrap.as_array?;
assert_eq!;
assert_eq!;
// Access inline table values
assert_eq!;
// Access values from an array of tables
let users = config.get.unwrap.as_array?;
assert_eq!;
assert_eq!;
High-Level Configuration Management
For more advanced use cases, the Config
struct provides a high-level API for loading, modifying, and saving configurations.
use Config;
use fs;
// Create a temporary file for the example
let temp_dir = tempdir?;
let file_path = temp_dir.path.join;
write?;
// Load the configuration from a file
let mut config = from_file?;
assert_eq!;
// Modify the configuration
config.set?;
config.set?;
// Save the changes back to the file
config.save?;
// Verify the changes
let updated_config = from_file?;
assert_eq!;
assert_eq!;
Async Support 🚀
noml
supports async operations for modern Rust applications! Enable the async
feature:
[]
= { = "0.4.0", = ["async"] }
= { = "1.0", = ["full"] }
All parsing and file operations are available in async variants:
use ;
async
Thread Safety: All NOML types (Value
, Config
) are Send + Sync
, making them safe to share between async tasks and threads. Perfect for concurrent applications and microservices!
Performance: Async operations are non-blocking and integrate seamlessly with tokio
, async-std
, and other async runtimes.
Run the async demo: cargo run --example async_demo --features async
Schema Validation ✅
noml
includes built-in schema validation to catch configuration errors early:
use ;
// Load your configuration
let config = from_string?;
// Define expected schema
let schema = new
.require_string
.require_integer
.optional_bool
.build;
// Validate configuration against schema
config.validate_schema?;
// Or create more complex schemas
let db_schema = new
.required_field
.required_field
.allow_additional;
let app_schema = new
.required_field
.required_field
.required_field;
config.validate_schema?;
Benefits:
- 🛡️ Early Error Detection: Catch configuration issues before runtime
- 🎯 Type Safety: Ensure values are the expected types
- 📋 Required Fields: Validate that critical configuration is present
- 🔍 Clear Error Messages: Detailed validation failure reports