facet_default/lib.rs
1//! # facet-default
2//!
3//! Derive [`Default`] for your types using facet's plugin system with custom field defaults.
4//!
5//! ## Usage
6//!
7//! ```ignore
8//! use facet::Facet;
9//! use facet_default as _;
10//!
11//! #[derive(Facet, Debug)]
12//! #[facet(derive(Default))]
13//! pub struct Config {
14//! #[facet(default = "localhost")]
15//! host: String,
16//! #[facet(default = 8080u16)]
17//! port: u16,
18//! // No attribute = uses Default::default()
19//! debug: bool,
20//! }
21//! ```
22//!
23//! ## Attributes
24//!
25//! ### Field Level
26//!
27//! - `#[facet(default = literal)]` - Use a literal value
28//! - `#[facet(default)]` - Use `Default::default()` for the field type
29//!
30//! Fields without attributes use `Default::default()`.
31//!
32//! ## Enums
33//!
34//! For enums, mark the default variant:
35//!
36//! ```ignore
37//! #[derive(Facet, Debug)]
38//! #[facet(derive(Default))]
39//! #[repr(u8)]
40//! pub enum Status {
41//! #[facet(default::variant)]
42//! Pending,
43//! Active,
44//! Done,
45//! }
46//! ```
47
48// ============================================================================
49// ATTRIBUTE GRAMMAR
50// ============================================================================
51
52facet::define_attr_grammar! {
53 ns "default";
54 crate_path ::facet_default;
55
56 /// Default attribute types for configuring Default implementation.
57 pub enum Attr {
58 /// Mark an enum variant as the default.
59 ///
60 /// Usage: `#[facet(default::variant)]`
61 Variant,
62 }
63}
64
65// ============================================================================
66// PLUGIN TEMPLATE
67// ============================================================================
68
69/// Plugin chain entry point.
70///
71/// Called by `#[derive(Facet)]` when `#[facet(derive(Default))]` is present.
72#[macro_export]
73macro_rules! __facet_invoke {
74 (
75 @tokens { $($tokens:tt)* }
76 @remaining { $($remaining:tt)* }
77 @plugins { $($plugins:tt)* }
78 @facet_crate { $($facet_crate:tt)* }
79 ) => {
80 $crate::__facet_invoke_internal! {
81 @tokens { $($tokens)* }
82 @remaining { $($remaining)* }
83 @plugins {
84 $($plugins)*
85 @plugin {
86 @name { "Default" }
87 @template {
88 impl ::core::default::Default for @Self {
89 fn default() -> Self {
90 @if_struct {
91 Self {
92 @for_field {
93 @field_name: @field_default_expr,
94 }
95 }
96 }
97 @if_enum {
98 @for_variant {
99 @if_attr(default::variant) {
100 Self::@variant_name @variant_default_construction
101 }
102 }
103 }
104 }
105 }
106 }
107 }
108 }
109 @facet_crate { $($facet_crate)* }
110 }
111 };
112}
113
114/// Internal macro that either chains to next plugin or calls finalize
115#[doc(hidden)]
116#[macro_export]
117macro_rules! __facet_invoke_internal {
118 // No more plugins - call finalize
119 (
120 @tokens { $($tokens:tt)* }
121 @remaining { }
122 @plugins { $($plugins:tt)* }
123 @facet_crate { $($facet_crate:tt)* }
124 ) => {
125 $($facet_crate)*::__facet_finalize! {
126 @tokens { $($tokens)* }
127 @plugins { $($plugins)* }
128 @facet_crate { $($facet_crate)* }
129 }
130 };
131
132 // More plugins - chain to next
133 (
134 @tokens { $($tokens:tt)* }
135 @remaining { $next:path $(, $rest:path)* $(,)? }
136 @plugins { $($plugins:tt)* }
137 @facet_crate { $($facet_crate:tt)* }
138 ) => {
139 $next! {
140 @tokens { $($tokens)* }
141 @remaining { $($rest),* }
142 @plugins { $($plugins)* }
143 @facet_crate { $($facet_crate)* }
144 }
145 };
146}