serde-libconfigasaurus
A Rust serde implementation for the libconfig configuration format.
Supported Types
All libconfig value types are supported:
| libconfig type | Rust / Value type |
|---|---|
| boolean | bool / Value::Bool |
| integer | i32 / Value::Integer |
| integer64 | i64 / Value::Integer64 |
| float | f64 / Value::Float |
| string | String / Value::String |
array [...] |
Vec<T> / Value::Array (homogeneous scalars) |
list (...) |
tuples, Vec of aggregates / Value::List (heterogeneous values) |
group {...} |
structs / Value::Group (named settings) |
Integer literals support decimal, hex (0xFF), binary (0b1010), and octal (0o17 / 0q17) formats. Values exceeding the 32-bit range are automatically promoted to 64-bit, or use the L / LL suffix explicitly (100L).
Rust enums round-trip too: unit variants are written as strings ("Variant"), and data-carrying variants as single-setting groups ({ Variant = value; }).
Quick Start
[]
= "0.4"
= { = "1.0", = ["derive"] }
Typed Deserialization
use Deserialize;
use from_str;
let config = r#"
hostname = "localhost";
port = 8080;
ssl = true;
"#;
let server: Server = from_str.unwrap;
Serialization
use Serialize;
use to_string;
let settings = AppSettings ;
// The top level of a libconfig document is an implicit setting list;
// braces only appear around nested groups.
let output = to_string.unwrap;
// name = "My App";
// version = 1;
Dynamic Config
When you don't know the structure at compile time, use Config for dynamic access:
use Config;
let cfg = from_str.unwrap;
// Index with dotted paths
assert_eq!;
assert_eq!;
assert_eq!;
Reading from a File
use Config;
let cfg = from_file.unwrap;
println!;
More API
to_value/from_valueconvert between any serde type andValueConfig::to_filewrites a document back to disk;from_reader/to_writerwork with anyRead/Write- Parse errors carry positions:
err.line(),err.column() Optionfields round-trip naturally:Nonefields are omitted on write, and absent settings read back asNonesetaccepts anything convertible into aValue:cfg.set("port", 8080)WriteOptionscontrols output style (float precision, scientific notation, tab width,:vs=, brace placement, separators) — all combinations emit grammar-valid text- Custom
@includeresolvers viaConfig::from_str_with_include_fn(wildcards, search paths — theconfig_set_include_funcequivalent) &strstruct fields deserialize zero-copy when the string needs no escape decoding or concatenation
Setting Paths
Values can be read, written, and removed using libconfig-style dotted paths. Array and list elements are addressed with bracket notation ([index]) or bare numeric segments:
use ;
let mut cfg = from_str.unwrap;
// Read
assert_eq!;
assert_eq!; // bare numeric also works
// Write (set existing) — anything convertible into a Value works
cfg.set.unwrap;
assert_eq!;
// Write (auto-creates intermediate groups)
cfg.set.unwrap;
assert_eq!;
// Remove (returns the removed value)
let mut cfg = from_str.unwrap;
let removed = cfg.remove;
assert_eq!;
assert!;
// Remove array element (subsequent elements shift down)
let mut cfg = from_str.unwrap;
cfg.remove.unwrap;
assert_eq!;
Format Features
- Top-level implicit groups (no outer braces required)
- Case-insensitive booleans (
true,True,TRUE,FaLsE) - Adjacent string concatenation (
"hello" " world"->"hello world") - Comments:
#,//,/* */ - Setting separators: semicolons, commas, or whitespace (all optional)
- Both
=and:as key-value delimiters @include "file.cfg"directives (viaConfig::from_str/Config::from_file, with*_with_include_dirvariants to set the include directory)
Spec Conformance
Parsing and serialization follow the libconfig manual (v1.8.2), including its Appendix B grammar:
- The document root is a setting list (
<configuration> ::= <setting-list> | <empty>); top-level braces are rejected on parse and never written — braces delimit nested groups only - Setting names must match
[A-Za-z*][-A-Za-z0-9_*]*(validated on read and write) - Duplicate setting names within a group are rejected
- Arrays may only contain scalar values of a single type; anything else
belongs in a list (serialization picks
[...]vs(...)automatically) - Out-of-range integer conversions and float-to-integer coercions are errors, not silent truncations; non-finite floats refuse to serialize
- Strings must be double-quoted;
\xNNescapes take exactly two hex digits
The manual (including its Appendix B grammar) is the sole authority for this crate's behavior. Output has additionally been cross-checked against the C libconfig library as a comparison point; where an installed C version disagrees with the manual (e.g. pre-1.8 versions lacking binary/octal literals, trailing commas, or 64-bit auto-promotion), the manual wins.
Documented deviations: \xNN escapes ≥ 0x80 map to Unicode code points
(Rust strings cannot hold bare bytes), integers are accepted where floats are
expected (lossless), and the serde-level from_str does not process
@include directives (use Config for that).
Examples
License
MIT OR Apache-2.0