1pub use derive_refineable::Refineable;
2
3/// A trait for types that can be refined with partial updates.
4///
5/// The `Refineable` trait enables hierarchical configuration patterns where a base configuration
6/// can be selectively overridden by refinements. This is particularly useful for styling and
7/// settings, and theme hierarchies.
8///
9/// # Derive Macro
10///
11/// The `#[derive(Refineable)]` macro automatically generates a companion refinement type and
12/// implements this trait. For a struct `Style`, it creates `StyleRefinement` where each field is
13/// wrapped appropriately:
14///
15/// - **Refineable fields** (marked with `#[refineable]`): Become the corresponding refinement type
16/// (e.g., `Bar` becomes `BarRefinement`)
17/// - **Optional fields** (`Option<T>`): Remain as `Option<T>`
18/// - **Regular fields**: Become `Option<T>`
19///
20/// ## Attributes
21///
22/// The derive macro supports these attributes on the struct:
23/// - `#[refineable(Debug)]`: Implements `Debug` for the refinement type
24/// - `#[refineable(Serialize)]`: Derives `Serialize` which skips serializing `None`
25/// - `#[refineable(OtherTrait)]`: Derives additional traits on the refinement type
26///
27/// Fields can be marked with:
28/// - `#[refineable]`: Field is itself refineable (uses nested refinement type)
29pub trait Refineable: Clone {
30 type Refinement: Refineable<Refinement = Self::Refinement> + IsEmpty + Default;
31
32 /// Applies the given refinement to this instance, modifying it in place.
33 ///
34 /// Only non-empty values in the refinement are applied.
35 ///
36 /// * For refineable fields, this recursively calls `refine`.
37 /// * For other fields, the value is replaced if present in the refinement.
38 fn refine(&mut self, refinement: &Self::Refinement);
39
40 /// Returns a new instance with the refinement applied, equivalent to cloning `self` and calling
41 /// `refine` on it.
42 fn refined(self, refinement: Self::Refinement) -> Self;
43
44 /// Creates an instance from a cascade by merging all refinements atop the default value.
45 fn from_cascade(cascade: &Cascade<Self>) -> Self
46 where
47 Self: Default + Sized,
48 {
49 Self::default().refined(cascade.merged())
50 }
51
52 /// Returns `true` if this instance would contain all values from the refinement.
53 ///
54 /// For refineable fields, this recursively checks `is_superset_of`. For other fields, this
55 /// checks if the refinement's `Some` values match this instance's values.
56 fn is_superset_of(&self, refinement: &Self::Refinement) -> bool;
57
58 /// Returns a refinement that represents the difference between this instance and the given
59 /// refinement.
60 ///
61 /// For refineable fields, this recursively calls `subtract`. For other fields, the field is
62 /// `None` if the field's value is equal to the refinement.
63 fn subtract(&self, refinement: &Self::Refinement) -> Self::Refinement;
64}
65
66pub trait IsEmpty {
67 /// Returns `true` if applying this refinement would have no effect.
68 fn is_empty(&self) -> bool;
69}
70
71/// A cascade of refinements that can be merged in priority order.
72///
73/// A cascade maintains a sequence of optional refinements where later entries
74/// take precedence over earlier ones. The first slot (index 0) is always the
75/// base refinement and is guaranteed to be present.
76///
77/// This is useful for implementing configuration hierarchies like CSS cascading,
78/// where styles from different sources (user agent, user, author) are combined
79/// with specific precedence rules.
80pub struct Cascade<S: Refineable>(Vec<Option<S::Refinement>>);
81
82impl<S: Refineable + Default> Default for Cascade<S> {
83 fn default() -> Self {
84 Self(vec![Some(Default::default())])
85 }
86}
87
88/// A handle to a specific slot in a cascade.
89///
90/// Slots are used to identify specific positions in the cascade where
91/// refinements can be set or updated.
92#[derive(Copy, Clone)]
93pub struct CascadeSlot(usize);
94
95impl<S: Refineable + Default> Cascade<S> {
96 /// Reserves a new slot in the cascade and returns a handle to it.
97 ///
98 /// The new slot is initially empty (`None`) and can be populated later
99 /// using `set()`.
100 pub fn reserve(&mut self) -> CascadeSlot {
101 self.0.push(None);
102 CascadeSlot(self.0.len() - 1)
103 }
104
105 /// Returns a mutable reference to the base refinement (slot 0).
106 ///
107 /// The base refinement is always present and serves as the foundation
108 /// for the cascade.
109 pub fn base(&mut self) -> &mut S::Refinement {
110 self.0[0].as_mut().unwrap()
111 }
112
113 /// Sets the refinement for a specific slot in the cascade.
114 ///
115 /// Setting a slot to `None` effectively removes it from consideration
116 /// during merging.
117 pub fn set(&mut self, slot: CascadeSlot, refinement: Option<S::Refinement>) {
118 self.0[slot.0] = refinement
119 }
120
121 /// Merges all refinements in the cascade into a single refinement.
122 ///
123 /// Refinements are applied in order, with later slots taking precedence.
124 /// Empty slots (`None`) are skipped during merging.
125 pub fn merged(&self) -> S::Refinement {
126 let mut merged = self.0[0].clone().unwrap();
127 for refinement in self.0.iter().skip(1).flatten() {
128 merged.refine(refinement);
129 }
130 merged
131 }
132}