Expand description
§filecaster
filecaster provides the core FromFile trait, which is used in conjunction with the
filecaster-derive crate to enable automatic deserialization and merging of
configuration from various file formats into Rust structs.
This crate defines the fundamental interface for types that can be constructed
from an optional “shadow” representation, typically deserialized from a file.
The filecaster-derive crate provides a procedural macro to automatically
implement this trait for your structs, handling default values and merging logic.
§How it works
The FromFile trait defines how a final configuration struct (Self) can be
constructed from an optional intermediate “shadow” struct (Self::Shadow).
The filecaster-derive macro generates this Shadow struct and the
from_file implementation for your configuration types.
When you derive FromFile for a struct, filecaster-derive creates a
corresponding YourStructFile (the Shadow type) where all fields are
wrapped in Option<T>. This YourStructFile can then be deserialized
from a file (e.g., JSON, TOML, YAML) using serde.
The from_file method then takes this Option<YourStructFile> and
constructs your final YourStruct, applying default values for any fields
that were None in the YourStructFile.
§Example
While the FromFile trait is implemented via the filecaster-derive macro,
here’s a conceptual example of how it’s used:
use filecaster::FromFile;
use serde::{Deserialize, Serialize};
// This struct would typically have `#[derive(FromFile)]`
// from the `filecaster-derive` crate.
#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
struct AppConfig {
host: String,
port: u16,
auto_reload: bool,
}
// The `Shadow` type is automatically generated by `filecaster-derive`
// and would look something like this:
#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
struct AppConfigFile {
host: Option<String>,
port: Option<u16>,
auto_reload: Option<bool>,
}
// The `FromFile` implementation is also automatically generated.
// For demonstration, here's a simplified manual implementation:
impl FromFile for AppConfig {
type Shadow = AppConfigFile;
fn from_file(file: Option<Self::Shadow>) -> Self {
let file = file.unwrap_or_default();
AppConfig {
host: file.host.unwrap_or_else(|| "127.0.0.1".to_string()),
port: file.port.unwrap_or(8080),
auto_reload: file.auto_reload.unwrap_or(true),
}
}
}
fn example() {
// Simulate deserializing from a file
let file_content = r#"{ "host": "localhost", "port": 3000 }"#;
let partial_config: AppConfigFile = serde_json::from_str(file_content).unwrap();
// Construct the final config using the FromFile trait
let config = AppConfig::from_file(Some(partial_config));
assert_eq!(config.host, "localhost");
assert_eq!(config.port, 3000);
assert_eq!(config.auto_reload, false); // `Default::default()` for bool is `false`
println!("Final Config: {:#?}", config);
// Example with no file content (all defaults)
let default_config = AppConfig::from_file(None);
assert_eq!(default_config.host, "127.0.0.1");
assert_eq!(default_config.port, 8080);
assert_eq!(default_config.auto_reload, false);
}§Feature flags
derive: Enables thefilecaster-derivecrate, allowing you to use#[derive(FromFile)].serde: Enablesserdeserialization/deserialization support for theFromFiletrait.merge: Enablesmergecrate support, allowing for merging multiple partial configurations.
Traits§
- From
File - Marker for types that can be built from an
Option<Shadow>produced by the macro.