konfik_derive/
lib.rs

1// SPDX-License-Identifier: MIT
2// Copyright (c) 2025 kingananas20
3
4//! # `konfik_derive`
5//!
6//! Procedural macro derive for the [`konfik`](https://docs.rs/konfik) configuration parsing library.
7//!
8//! This crate provides the `#[derive(Config)]` macro that automatically implements the necessary
9//! traits for structs to work seamlessly with the `konfik` configuration loader.
10
11mod analyze_field;
12mod generate_config_meta;
13
14use generate_config_meta::generate_config_meta;
15use proc_macro::TokenStream;
16use quote::quote;
17use syn::{Data, DeriveInput, parse_macro_input};
18
19/// # `Konfik`
20///
21/// Implements `ConfigMeta` and `LoadConfig` for itself.
22///
23/// # Panics
24/// Panics when appliead to structs without named fields and
25/// on non struct types.
26#[proc_macro_derive(Konfik, attributes(konfik, serde, command))]
27pub fn derive_config(input: TokenStream) -> TokenStream {
28    let input = parse_macro_input!(input as DeriveInput);
29    let name = &input.ident;
30
31    let Data::Struct(data) = &input.data else {
32        return syn::Error::new_spanned(&input, "Only structs are supported")
33            .to_compile_error()
34            .into();
35    };
36
37    let config_meta = generate_config_meta(&data.fields, name);
38
39    TokenStream::from(quote! {
40        #config_meta
41
42        impl ::konfik::LoadConfig for #name {
43            fn load() -> Result<Self, ::konfik::Error> {
44                ::konfik::ConfigLoader::default().load()
45            }
46        }
47    })
48}
49
50/// # `Nested`
51///
52/// Implements `ConfigMeta` for itself.
53#[proc_macro_derive(Nested, attributes(konfik, serde, command))]
54pub fn derive_nested_types(input: TokenStream) -> TokenStream {
55    let input = parse_macro_input!(input as DeriveInput);
56    let name = &input.ident;
57
58    let Data::Struct(data) = &input.data else {
59        return syn::Error::new_spanned(&input, "Only structs are supported")
60            .to_compile_error()
61            .into();
62    };
63
64    let config_meta = generate_config_meta(&data.fields, name);
65
66    TokenStream::from(quote! {
67        #config_meta
68    })
69}