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