former 2.43.0

A flexible implementation of the Builder pattern supporting nested builders and collection-specific subformers. Simplify the construction of complex objects.
Documentation
//! Example demonstrating custom mutation logic using the `FormerMutator` trait with storage-specific fields.

#![allow(missing_docs)]

// This example illustrates how to use the `FormerMutator` trait for implementing custom mutations
// and demonstrates the concept of storage-specific fields in the forming process.
//
// #### Storage-Specific Fields
//
// Storage-specific fields are intermediate fields that exist only in the storage structure during
// the forming process. These fields are not present in the final formed structure but are instrumental
// in complex forming operations, such as conditional mutations, temporary state tracking, or accumulations.
//
// These fields are used to manage intermediate data or state that aids in the construction
// of the final object but does not necessarily have a direct representation in the object's schema. For
// instance, counters, flags, or temporary computation results that determine the final state of the object.
//
// The `FormerMutator` trait facilitates the implementation of custom mutation logic. It acts on the internal
// state (context and storage) just before the final forming operation is completed, right before the `FormingEnd`
// callback is invoked. This trait is crucial for making last-minute adjustments or computations based on the
// accumulated state in the storage.
//
// In this example, the fields `a` and `b` are defined only within the storage and used
// within the custom mutator to enrich or modify the field `c` of the formed entity. This approach
// allows for a richer and more flexible formation logic that can adapt based on the intermediate state
// held within the storage.
//
// #### Differences from `FormingEnd`
//
// Unlike `FormingEnd`, which is primarily 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`.
//

#[cfg(any(not(feature = "derive_former"), not(feature = "enabled")))]
fn main() {}
#[cfg(all(feature = "derive_former", feature = "enabled"))]
fn main() {
  #[ cfg( feature = "enabled" ) ]
  use former::Former;

  #[ derive( Debug, PartialEq, Former ) ]
  #[ storage_fields( a : i32, b : Option< String > ) ]
  #[ mutator( custom ) ]
  pub struct Struct1 {
    c: String,
  }

  // = former mutator

  impl<Context, Formed> former::FormerMutator for Struct1FormerDefinitionTypes<Context, Formed> {
    // Mutates the context and storage of the entity just before the formation process completes.
    #[ inline ]
    fn form_mutation(storage: &mut Self::Storage, _context: &mut ::core::option::Option<Self::Context>) {
      storage.a.get_or_insert_with(Default::default);
      storage.b.get_or_insert_with(Default::default);
      storage.c = Some(format!("{:?} - {}", storage.a.unwrap(), storage.b.as_ref().unwrap()));
    }
  }

  let got = Struct1::former().a(13).b("abc").c("def").form();
  let exp = Struct1 {
    c: "13 - abc".to_string(),
  };
  assert_eq!(got, exp);
  dbg!(got);
  // > got = Struct1 {
  // >  c : "13 - abc",
  // > }
}