Crate filecaster

Source
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 the filecaster-derive crate, allowing you to use #[derive(FromFile)].
  • serde: Enables serde serialization/deserialization support for the FromFile trait.
  • merge: Enables merge crate support, allowing for merging multiple partial configurations.

Traits§

FromFile
Marker for types that can be built from an Option<Shadow> produced by the macro.

Derive Macros§

FromFile
Implements the FromFile trait.