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-derive
crate, allowing you to use#[derive(FromFile)]
.serde
: Enablesserde
serialization/deserialization support for theFromFile
trait.merge
: Enablesmerge
crate 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.