Skip to main content

Recallable

Derive Macro Recallable 

Source
#[derive(Recallable)]
{
    // Attributes available to this derive:
    #[recallable]
}
Expand description

Derive macro that generates a companion memento struct and the Recallable trait impl.

The memento struct mirrors the original but replaces #[recallable]-annotated fields with their <FieldType as Recallable>::Memento type and omits #[recallable(skip)] fields. The generated companion type has the same visibility as the input struct. Its fields are always emitted without visibility modifiers, so they remain private to the containing module. This is intentional: mementos are meant to be created and consumed alongside the companion struct, primarily via Recall::recall and TryRecall::try_recall, with only occasional same-file testing or debugging use. For container-like field types, this is whatever memento shape that field type chose; the macro does not special-case merge semantics. When the impl_from feature is enabled, #[derive(Recallable)] also generates From<Struct> for the memento type, which requires <FieldType as Recallable>::Memento: From<FieldType> for each #[recallable] field.

Lifetime parameters are supported only when the generated memento can stay owned: non-skipped fields may not borrow one of the struct’s lifetimes. Skipped borrowed fields and lifetime-only markers such as PhantomData<&'a T> are allowed.

This example requires the serde feature.

use recallable::{Recall, Recallable};

#[derive(Clone, Debug, serde::Serialize, Recallable, Recall)]
struct Outer {
    label: String,
    #[recallable]
    inner: Inner,
}

#[derive(Clone, Debug, serde::Serialize, Recallable, Recall)]
struct Inner {
    count: u32,
}

// The memento type is accessible via the associated type
let memento: <Outer as Recallable>::Memento =
    serde_json::from_str(r#"{"label":"updated","inner":{"count":99}}"#).unwrap();

let mut outer = Outer { label: "original".into(), inner: Inner { count: 0 } };
outer.recall(memento);
assert_eq!(outer.label, "updated");
assert_eq!(outer.inner.count, 99);

Derive macro that generates the companion memento type and Recallable impl.

The generated memento type:

  • mirrors the original struct shape (named/tuple/unit),
  • includes fields unless marked with #[recallable(skip)],
  • uses the same visibility as the input struct,
  • keeps all generated fields private by omitting field-level visibility modifiers,
  • also derives serde::Deserialize when the serde feature is enabled for the macro crate.

For #[recallable] fields, the generated memento field type is exactly <FieldType as Recallable>::Memento. The macro does not prescribe one canonical container semantics; it uses whatever memento shape the field type defines.

The companion struct itself is generated as an internal implementation detail. The supported way to name it is <Struct as Recallable>::Memento. It is intended to be produced and consumed alongside the source struct, primarily through Recall::recall/TryRecall::try_recall, not as a field-inspection surface with widened visibility.

The Recallable impl sets type Memento to that generated type and adds any required generic bounds.

The generated memento struct always derives Clone, Debug, and PartialEq. When the serde feature is enabled, it also derives serde::Deserialize. All non-skipped field types must implement these derived traits.

To suppress the default Clone, Debug, and PartialEq derives (and their corresponding trait bounds), annotate the struct with #[recallable(skip_memento_default_derives)]. When serde is enabled, Deserialize is still derived on the memento even with this attribute.

When the impl_from feature is enabled for the macro crate, a From<Struct> implementation is also generated for the memento type. For #[recallable] fields, that additionally requires <FieldType as Recallable>::Memento: From<FieldType>.