former_types/
forming.rs

1//! Module `forming`
2//!
3//! This module defines a collection of traits that are crucial for implementing a structured and extensible builder pattern.
4//! The traits provided manage the various stages of the forming process, handling the initiation, mutation, and completion
5//! of constructing complex data structures. These traits facilitate the creation of flexible and maintainable formation
6//! logic that can accommodate complex construction scenarios, including nested and conditional formations.
7
8/// Provides a mechanism for mutating the context and storage just before the forming process is completed.
9///
10/// The `FormerMutator` trait allows for the implementation of custom mutation logic on the internal state
11/// of an entity (context and storage) just before the final forming operation is completed. This mutation
12/// occurs immediately before the `FormingEnd` callback is invoked.
13///
14/// #### Differences from `FormingEnd`
15///
16/// Unlike `FormingEnd`, which is responsible for integrating and finalizing the formation process of a field within
17/// a parent former, `form_mutation` directly pertains to the entity itself. This method is designed to be independent
18/// of whether the forming process is occurring within the context of a superformer or if the structure is a standalone
19/// or nested field. This makes `form_mutation` suitable for entity-specific transformations that should not interfere
20/// with the hierarchical forming logic managed by `FormingEnd`.
21///
22/// #### Use Cases
23///
24/// - Applying last-minute changes to the data being formed.
25/// - Setting or modifying properties that depend on the final state of the storage or context.
26/// - Storage-specific fields which are not present in formed structure.
27///
28/// Look example `former_custom_mutator.rs`
29pub trait FormerMutator
30where
31  Self: crate::FormerDefinitionTypes,
32{
33  /// Mutates the context and storage of the entity just before the formation process completes.
34  ///
35  /// This function is invoked immediately prior to the `FormingEnd` callback during the forming process.
36  /// It provides a hook for implementing custom logic that modifies the internal state (storage and context)
37  /// of the entity. `form_mutation` is particularly useful for adjustments or updates that need to reflect
38  /// in the entity just before it is finalized and returned.
39  ///
40  #[ inline ]
41  fn form_mutation( _storage : &mut Self::Storage, _context : &mut ::core::option::Option<  Self::Context  > ) {}
42}
43
44// impl< Definition > crate::FormerMutator
45// for Definition
46// where
47//   Definition : crate::FormerDefinitionTypes,
48// {
49// }
50
51/// Defines a handler for the end of a subforming process, enabling the return of the original context.
52///
53/// This trait is designed to be flexible, allowing for various end-of-forming behaviors in builder patterns.
54/// Implementors can define how to transform or pass through the context during the forming process's completion.
55///
56/// # Parameters
57/// - `Storage`: The type of the collection being processed.
58/// - `Context`: The type of the context that might be altered or returned upon completion.
59pub trait FormingEnd< Definition : crate::FormerDefinitionTypes >
60{
61  /// Called at the end of the subforming process to return the modified or original context.
62  ///
63  /// # Parameters
64  /// - `collection`: The collection being processed.
65  /// - `context`: Optional context to be transformed or returned.
66  ///
67  /// # Returns
68  /// Returns the transformed or original context based on the implementation.
69  fn call( &self, storage : Definition::Storage, context : core::option::Option<  Definition::Context  > ) -> Definition::Formed;
70}
71
72impl< Definition, F > FormingEnd< Definition > for F
73where
74  F : Fn( Definition::Storage, core::option::Option<  Definition::Context  > ) -> Definition::Formed,
75  Definition : crate::FormerDefinitionTypes,
76{
77  #[ inline( always ) ]
78  fn call( &self, storage : Definition::Storage, context : core::option::Option<  Definition::Context  > ) -> Definition::Formed
79  {
80    self( storage, context )
81  }
82}
83
84/// A `FormingEnd` implementation that directly returns the formed collection as the final product of the forming process.
85///
86/// This struct is particularly useful when the end result of the forming process is simply the formed collection itself,
87/// without needing to integrate or process additional contextual information. It's ideal for scenarios where the final
88/// entity is directly derived from the storage state without further transformations or context-dependent adjustments.
89#[ derive( Debug, Default ) ]
90pub struct ReturnPreformed;
91
92impl< Definition > FormingEnd< Definition > for ReturnPreformed
93where
94  Definition::Storage : crate::StoragePreform< Preformed = Definition::Formed >,
95  Definition : crate::FormerDefinitionTypes,
96{
97  /// Transforms the storage into its final formed state and returns it, bypassing context processing.
98  #[ inline( always ) ]
99  fn call( &self, storage : Definition::Storage, _context : core::option::Option<  Definition::Context  > ) -> Definition::Formed
100  {
101    crate::StoragePreform::preform( storage )
102  }
103}
104
105/// A `FormingEnd` implementation that returns the storage itself as the formed entity, disregarding any contextual data.
106///
107/// This struct is suited for straightforward forming processes where the storage already represents the final state of the
108/// entity, and no additional processing or transformation of the storage is required. It simplifies use cases where the
109/// storage does not undergo a transformation into a different type at the end of the forming process.
110#[ derive( Debug, Default ) ]
111pub struct ReturnStorage;
112
113impl< Definition, T > FormingEnd< Definition > for ReturnStorage
114where
115  Definition : crate::FormerDefinitionTypes< Context = (), Storage = T, Formed = T >,
116{
117  /// Returns the storage as the final product of the forming process, ignoring any additional context.
118  #[ inline( always ) ]
119  fn call( &self, storage : Definition::Storage, _context : core::option::Option<  ()  > ) -> Definition::Formed
120  {
121    storage
122  }
123}
124
125/// A placeholder `FormingEnd` used when no end operation is required or applicable.
126///
127/// This implementation is useful in generic or templated scenarios where a `FormingEnd` is required by the interface,
128/// but no meaningful end operation is applicable. It serves a role similar to `core::marker::PhantomData` by filling
129/// generic parameter slots without contributing operational logic.
130#[ derive( Debug, Default ) ]
131pub struct NoEnd;
132
133impl< Definition > FormingEnd< Definition > for NoEnd
134where
135  Definition : crate::FormerDefinitionTypes,
136{
137  /// Intentionally causes a panic if called, as its use indicates a configuration error.
138  #[ inline( always ) ]
139  fn call( &self, _storage : Definition::Storage, _context : core::option::Option<  Definition::Context  > ) -> Definition::Formed
140  {
141    unreachable!();
142  }
143}
144
145#[ allow( unused_extern_crates ) ]
146#[ cfg( all( feature = "no_std", feature = "use_alloc" ) ) ]
147extern crate alloc;
148#[ cfg( all( feature = "no_std", feature = "use_alloc" ) ) ]
149use alloc::boxed::Box;
150
151/// A wrapper around a closure to be used as a `FormingEnd`.
152///
153/// This struct allows for dynamic dispatch of a closure that matches the
154/// `FormingEnd` trait's `call` method signature. It is useful for cases where
155/// a closure needs to be stored or passed around as an object implementing
156/// `FormingEnd`.
157#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
158#[ allow( clippy::type_complexity ) ]
159pub struct FormingEndClosure< Definition : crate::FormerDefinitionTypes >
160{
161  closure : Box< dyn Fn( Definition::Storage, Option<  Definition::Context  > ) -> Definition::Formed >,
162  _marker : core::marker::PhantomData< Definition::Storage >,
163}
164
165#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
166impl< T, Definition > From< T > for FormingEndClosure< Definition >
167where
168  T : Fn( Definition::Storage, Option<  Definition::Context  > ) -> Definition::Formed + 'static,
169  Definition : crate::FormerDefinitionTypes,
170{
171  #[ inline( always ) ]
172  fn from( closure : T ) -> Self
173  {
174    Self
175    {
176      closure : Box::new( closure ),
177      _marker : core::marker::PhantomData,
178    }
179  }
180}
181
182#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
183impl< Definition : crate::FormerDefinitionTypes > FormingEndClosure< Definition >
184{
185  /// Constructs a new `FormingEndClosure` with the provided closure.
186  ///
187  /// # Parameters
188  ///
189  /// * `closure` - A closure that matches the expected signature for transforming a collection
190  ///   and context into a new context. This closure is stored and called by the
191  ///   `call` method of the `FormingEnd` trait implementation.
192  ///
193  /// # Returns
194  ///
195  /// Returns an instance of `FormingEndClosure` encapsulating the provided closure.
196  pub fn new( closure : impl Fn( Definition::Storage, Option<  Definition::Context  > ) -> Definition::Formed + 'static ) -> Self
197  {
198    Self
199    {
200      closure : Box::new( closure ),
201      _marker : core::marker::PhantomData,
202    }
203  }
204}
205
206#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
207use core::fmt;
208#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
209impl< Definition : crate::FormerDefinitionTypes > fmt::Debug for FormingEndClosure< Definition >
210{
211  fn fmt( &self, f : &mut fmt::Formatter< '_ > ) -> fmt::Result
212  {
213    f.debug_struct( "FormingEndClosure" )
214      .field( "closure", &format_args! { "- closure -" } )
215      .field( "_marker", &self._marker )
216      .finish()
217  }
218}
219
220#[ cfg( any( not( feature = "no_std" ), feature = "use_alloc" ) ) ]
221impl< Definition : crate::FormerDefinitionTypes > FormingEnd< Definition > for FormingEndClosure< Definition >
222{
223  fn call( &self, storage : Definition::Storage, context : Option<  Definition::Context  > ) -> Definition::Formed
224  {
225    ( self.closure )( storage, context )
226  }
227}
228
229/// A trait for initiating a structured subforming process with contextual and intermediary storage linkage.
230///
231/// This trait is crucial for the `derive(Former)` macro implementation, where it facilitates the creation
232/// of a subformer that integrates seamlessly within a builder pattern chain. It handles intermediary storage
233/// to accumulate state or data before finally transforming it into the final `Formed` structure.
234///
235/// `FormerBegin` is particularly important in scenarios where complex, hierarchical structures are formed,
236/// allowing a former to be reused within another former. This reusability and the ability to maintain both transient
237/// state (`Storage`) and contextual information (`Context`) are essential for multi-step construction or transformation
238/// processes that culminate in the generation of a final product (`Formed`).
239///
240/// During code generation via the `derive(Former)` macro, `FormerBegin` provides the necessary scaffolding to
241/// initiate the subforming process. This setup is critical for ensuring that all elements involved in the formation
242/// are aligned from the onset, particularly when one former is nested within another, facilitating the creation
243/// of complex hierarchical data structures.
244///
245pub trait FormerBegin< 'storage, Definition >
246where
247  Definition : crate::FormerDefinition,
248  Definition::Storage : 'storage,
249  Definition::Context : 'storage,
250  Definition::End : 'storage,
251{
252  /// Launches the subforming process with an initial storage and context, setting up an `on_end` completion handler.
253  ///
254  /// This method initializes the formation process by providing the foundational elements necessary for
255  /// building the entity. It allows for the configuration of initial states and contextual parameters, which
256  /// are critical for accurately reflecting the intended final state of the entity.
257  ///
258  /// # Parameters
259  ///
260  /// * `storage` - An optional initial state for the intermediary storage structure. This parameter allows
261  ///   for the pre-configuration of storage, which can be crucial for entities requiring specific initial states.
262  /// * `context` - An optional initial setting providing contextual information for the subforming process.
263  ///   This context can influence how the formation process progresses, especially in complex forming scenarios.
264  /// * `on_end` - A completion handler responsible for transforming the accumulated `Storage` into the final `Formed` structure.
265  ///   This parameter is vital for ensuring that the transition from `Storage` to `Formed` is handled correctly,
266  ///   incorporating any last-minute adjustments or validations necessary for the entity's integrity.
267  ///
268  /// # Returns
269  ///
270  /// Returns an instance of Former.
271  ///
272  fn former_begin
273  (
274    storage : core::option::Option<  Definition::Storage  >,
275    context : core::option::Option<  Definition::Context  >,
276    on_end : Definition::End,
277  ) -> Self;
278}