facet_kdl_legacy/
lib.rs

1#![warn(missing_docs)]
2#![allow(clippy::result_large_err)]
3#![doc = include_str!("../README.md")]
4
5mod deserialize;
6mod error;
7mod serialize;
8
9// Re-export span types from facet-reflect
10pub use facet_reflect::{Span, Spanned};
11
12// Re-export error types
13pub use error::{KdlError, KdlErrorKind};
14
15// Re-export deserialization
16pub use deserialize::{from_str, from_str_owned};
17
18// Re-export serialization
19pub use serialize::{to_string, to_writer};
20
21mod kdl_wrapper;
22pub use kdl_wrapper::Kdl;
23
24#[cfg(feature = "axum")]
25mod axum;
26#[cfg(feature = "axum")]
27pub use self::axum::KdlRejection;
28
29// KDL extension attributes for use with #[facet(kdl::attr)] syntax.
30//
31// After importing `use facet_kdl_legacy as kdl;`, users can write:
32//   #[facet(kdl::child)]
33//   #[facet(kdl::children)]
34//   #[facet(kdl::children = "custom_name")]
35//   #[facet(kdl::property)]
36//   #[facet(kdl::argument)]
37//   #[facet(kdl::arguments)]
38//   #[facet(kdl::node_name)]
39
40// Generate KDL attribute grammar using the grammar DSL.
41// This generates:
42// - `Attr` enum with all KDL attribute variants
43// - `__attr!` macro that dispatches to attribute handlers and returns ExtensionAttr
44// - `__parse_attr!` macro for parsing (internal use)
45facet::define_attr_grammar! {
46    ns "kdl";
47    crate_path ::facet_kdl_legacy;
48
49    /// KDL attribute types for field and container configuration.
50    pub enum Attr {
51        /// Marks a field as a single KDL child node.
52        ///
53        /// Can optionally specify a custom node name to match:
54        /// - `#[facet(kdl::child)]` - matches by field name
55        /// - `#[facet(kdl::child = "custom")]` - matches nodes named "custom"
56        Child(Option<&'static str>),
57        /// Marks a field as collecting multiple KDL children into a Vec, HashMap, or Set.
58        ///
59        /// When a struct has a single `#[facet(kdl::children)]` field, all child nodes
60        /// are collected into that field (catch-all behavior).
61        ///
62        /// When a struct has multiple `#[facet(kdl::children)]` fields, nodes are routed
63        /// based on matching the node name to the singular form of the field name:
64        /// - `dependency` nodes → `dependencies` field
65        /// - `sample` nodes → `samples` field
66        /// - `item` nodes → `items` field
67        ///
68        /// Supported pluralization patterns:
69        /// - Simple `s`: `item` → `items`
70        /// - `ies` ending: `dependency` → `dependencies`
71        /// - `es` ending: `box` → `boxes`
72        ///
73        /// To override automatic singularization, specify a custom node name:
74        /// - `#[facet(kdl::children = "kiddo")]` matches nodes named `kiddo`
75        Children(Option<&'static str>),
76        /// Marks a field as a KDL property (key=value)
77        Property,
78        /// Marks a field as a single KDL positional argument
79        Argument,
80        /// Marks a field as collecting all KDL positional arguments
81        Arguments,
82        /// Marks a field as storing the KDL node name during deserialization.
83        /// Use this to capture the name of the current node into a field.
84        ///
85        /// Example:
86        /// ```ignore
87        /// #[derive(Facet)]
88        /// struct Node {
89        ///     #[facet(kdl::node_name)]
90        ///     name: String,
91        /// }
92        /// ```
93        NodeName,
94    }
95}