From 748db052ff9a942b191d5fe4867549ce25db1232 Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Mon, 14 Jul 2025 21:30:58 +0300 Subject: [PATCH] docs: add lib docs --- .github/workflows/ci.yml | 64 ++++++++++++++++++++++++++------- src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a694ac7..13ab7b3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ env: RUSTFLAGS: --deny warnings RUSTDOCFLAGS: --deny warnings jobs: - # Run tests. + # Run tests test: name: Tests runs-on: ubuntu-latest @@ -20,17 +20,29 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Install dependencies - run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends \ + libasound2-dev libudev-dev libwayland-dev \ + libxkbcommon-dev - name: Populate target directory from cache uses: Leafwing-Studios/cargo-cache@v2 with: sweep-cache: true - - name: Run tests + - name: Install cargo-nextest + run: cargo install cargo-nextest --locked + - name: Run tests with nextest run: | - cargo test --locked --workspace --all-features --all-targets + cargo nextest run \ + --all-features \ + --all-targets # Workaround for https://github.com/rust-lang/cargo/issues/6669 - cargo test --locked --workspace --all-features --doc - # Run clippy lints. + cargo test \ + --locked \ + --workspace \ + --all-features \ + --doc + # Run clippy lints clippy: name: Clippy runs-on: ubuntu-latest @@ -43,14 +55,24 @@ jobs: with: components: clippy - name: Install dependencies - run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends \ + libasound2-dev libudev-dev libwayland-dev \ + libxkbcommon-dev - name: Populate target directory from cache uses: Leafwing-Studios/cargo-cache@v2 with: sweep-cache: true - name: Run clippy lints - run: cargo clippy --locked --workspace --all-features -- --deny warnings - # Check formatting. + run: | + cargo clippy \ + --locked \ + --workspace \ + --all-features \ + -- \ + --deny warnings + # Check formatting format: name: Format runs-on: ubuntu-latest @@ -63,8 +85,12 @@ jobs: with: components: rustfmt - name: Run cargo fmt - run: cargo fmt --all -- --check - # Check documentation. + run: | + cargo fmt \ + --all \ + -- \ + --check + # Check documentation doc: name: Docs runs-on: ubuntu-latest @@ -75,10 +101,22 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable - name: Install dependencies - run: sudo apt-get update; sudo apt-get install --no-install-recommends libasound2-dev libudev-dev libwayland-dev libxkbcommon-dev + run: | + sudo apt-get update + sudo apt-get install --no-install-recommends \ + libasound2-dev libudev-dev libwayland-dev \ + libxkbcommon-dev - name: Populate target directory from cache uses: Leafwing-Studios/cargo-cache@v2 with: sweep-cache: true - name: Check documentation - run: cargo doc --locked --workspace --all-features --document-private-items --no-deps + run: | + cargo doc \ + --locked \ + --workspace \ + --all \ + --features \ + --document-private \ + --items \ + --no-deps diff --git a/src/lib.rs b/src/lib.rs index 8f08b12..7b74788 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,76 @@ +//! # filecaster +//! +//! `filecaster` is a small `proc-macro` crate that provides a derive‐macro +//! `#[derive(FromFile)]` to make it trivial to load partial configurations +//! from files, merge them with defaults, and get a fully‐populated struct. +//! +//! ## What it does +//! +//! For any struct with named fields, `#[derive(FromFile)]` generates: +//! +//! 1. A companion `NameFile` struct in which each field is wrapped +//! in `Option<...>`. +//! 2. A constructor `YourStruct::from_file(file: Option) -> YourStruct` +//! that takes your partially‐filled file struct, fills in `None` fields +//! with either: +//! - an expression you supply via `#[from_file(default = ...)]`, or +//! - `Default::default()` (requires `T: Default`) +//! 3. An implementation of `From> for YourStruct`. +//! +//! Because each field in the file‐struct is optional, you can deserialize +//! e.g. JSON, YAML or TOML into it via Serde, then call `.from_file(...)` +//! to get your final struct. +//! +//! ## Optional per‐field defaults +//! +//! Use a `#[from_file(default = )]` attribute on any field to override +//! the fallback value. You may supply any expression valid in that struct’s +//! context. If you omit it, the macro will require `T: Default` and call +//! `unwrap_or_default()`. +//! +//! Example: +//! +//! ```rust +//! use from_file::FromFile; +//! +//! #[derive(Debug, Clone, FromFile)] +//! #[serde(default)] +//! struct AppConfig { +//! /// If the user does not specify a host, use `"127.0.0.1"`. +//! #[from_file(default = "127.0.0.1")] +//! host: String, +//! +//! /// Number of worker threads; defaults to `4`. +//! #[from_file(default = 4)] +//! workers: usize, +//! +//! /// If not set, use `false`. +//! auto_reload: bool, // requires `bool: Default` +//! } +//! +//! // After deserializing the partial config from disk (e.g. with Serde): +//! let file: Option = serde_yaml::from_str(yaml_text).ok(); +//! let cfg: AppConfig = AppConfig::from_file(file); +//! println!("{cfg:#?}"); +//! ``` +//! +//! ## Feature flags +//! +//! - `merge` +//! If you enable the `merge` feature, the generated `File` struct will +//! also derive `merge::Merge`, and you can layer multiple partial files +//! together before calling `.from_file(...)`. Any field‐level merge strategy +//! annotations (`#[merge(...)]`) are applied automatically. +//! +//! ## Limitations +//! +//! - Only works on structs with _named_ fields (no tuple‐structs or enums). +//! - All fields without a `#[from_file(default = ...)]` must implement `Default`. +//! +//! ## License +//! +//! MIT OR Apache-2.0 + mod from_file; pub(crate) use from_file::impl_from_file; @@ -5,6 +78,10 @@ use proc_macro::TokenStream; use proc_macro_error::proc_macro_error; use syn::{DeriveInput, parse_macro_input}; +/// Implements the `FromFile` derive macro. +/// +/// This macro processes the `#[from_file]` attribute on structs to generate +/// code for loading data from files. #[proc_macro_error] #[proc_macro_derive(FromFile, attributes(from_file))] pub fn derive_from_file(input: TokenStream) -> TokenStream {