TOML
facet-toml provides TOML serialization and deserialization, built on toml_edit. Perfect for configuration files.
Basic usage
use facet:: Facet ;
# [ derive ( Facet )]
struct Config {
name : String ,
version : String ,
debug : bool ,
}
// Deserialize
let toml = r#"
name = "myapp"
version = "1.0.0"
debug = true
"# ;
let config: Config = facet_toml:: from_str ( toml) ?;
// Serialize
let output = facet_toml:: to_string ( & config) ?;
Nested tables
TOML tables map to nested structs:
# [ derive ( Facet )]
struct Package {
name : String ,
version : String ,
}
# [ derive ( Facet )]
struct Server {
host : String ,
port : u16 ,
}
# [ derive ( Facet )]
struct Config {
package : Package ,
server : Server ,
}
let toml = r#"
[package]
name = "myapp"
version = "1.0.0"
[server]
host = "localhost"
port = 8080
"# ;
let config: Config = facet_toml:: from_str ( toml) ?;
Arrays
TOML arrays work with Vec<T>:
# [ derive ( Facet )]
struct Dependency {
name : String ,
version : String ,
}
# [ derive ( Facet )]
struct Config {
dependencies : Vec < Dependency >,
}
let toml = r#"
[[dependencies]]
name = "serde"
version = "1.0"
[[dependencies]]
name = "tokio"
version = "1.0"
"# ;
let config: Config = facet_toml:: from_str ( toml) ?;
assert_eq! ( config. dependencies . len (), 2 );
Inline tables
Inline tables in TOML are handled automatically:
# Both forms work:
server = { host = "localhost" , port = 8080 }
# Or:
[ server ]
host = "localhost"
port = 8080
Optional fields
Use Option<T> for optional configuration:
# [ derive ( Facet )]
struct Database {
host : String ,
port : Option < u16 >, // Optional in TOML
# [ facet ( default = 10 )]
pool_size : u32 , // Defaults to 10 if missing
}
DateTime support
TOML has native datetime support. Enable the appropriate feature:
[ dependencies ]
facet = { version = "{{ data.versions.facet }}" , features = [ "chrono" ] }
# or "time" or "jiff02"
use chrono::{ DateTime , Utc };
# [ derive ( Facet )]
struct Event {
name : String ,
timestamp : DateTime < Utc >,
}
let toml = r#"
name = "deploy"
timestamp = 2024-01-15T10:30:00Z
"# ;
let event: Event = facet_toml:: from_str ( toml) ?;
Error messages
facet-toml provides helpful error messages with source locations:
Error: missing field `port`
┌─ config.toml:2:1
│
2 │ [server]
│ ^^^^^^^^ expected field `port` here
│
Common patterns
Cargo.toml-style configs
# [ derive ( Facet )]
struct Manifest {
package : Package ,
# [ facet ( default )]
dependencies : HashMap < String , Dependency >,
}
# [ derive ( Facet )]
struct Package {
name : String ,
version : String ,
# [ facet ( default )]
authors : Vec < String >,
}
# [ derive ( Facet )]
# [ facet ( untagged )]
enum Dependency {
Simple ( String ), // "1.0"
Detailed {
version : String ,
# [ facet ( default )]
features : Vec < String >,
},
}
Environment-specific configs
# [ derive ( Facet )]
struct Config {
# [ facet ( default )]
development : Option < ServerConfig >,
# [ facet ( default )]
production : Option < ServerConfig >,
}
# [ derive ( Facet )]
struct ServerConfig {
host : String ,
port : u16 ,
# [ facet ( default )]
tls : bool ,
}
Serialization
Serialize to TOML:
let config = Config {
package : Package {
name : "myapp" . into (),
version : "1.0.0" . into (),
},
server : Server {
host : "localhost" . into (),
port : 8080 ,
},
};
let toml = facet_toml:: to_string ( & config) ?;
println! ( "{}" , toml);
Output:
[ package ]
name = "myapp"
version = "1.0.0"
[ server ]
host = "localhost"
port = 8080
Next steps
- See Ecosystem for third-party type support (chrono, time, etc.)
- Check Attributes Reference for all available attributes
- Read Error handling for more on diagnostics