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}