Skip to main content

Recallable

Trait Recallable 

Source
pub trait Recallable {
    type Memento;
}
Expand description

A type that declares a companion memento type.

This trait intentionally does not prescribe one canonical memento shape for container-like types. For example, one Option-like wrapper may choose Self as its memento while another may choose Option<T::Memento> and perform selective inner updates.

§Usage

use recallable::{Recall, Recallable};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize)]
pub struct Accumulator<T> {
    prev_control_signal: T,
    #[serde(skip)]
    filter: fn(&i32) -> bool,
    accumulated: u32,
}

//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
// If we derive `Recallable` and `Recall` for `Accumulator`, the equivalent companion memento
// type and the `Recallable`/`Recall` implementations can be generated automatically.
// The generated companion type is exposed as
// `<Accumulator<T> as Recallable>::Memento`; its concrete struct name is an implementation
// detail of the derive.
//
// When deriving `Recallable`, a `From<Accumulator>` implementation is generated if the
// `impl_from` feature is enabled. For derived implementations, mark non-state fields with
// `#[recallable(skip)]` (and add `#[serde(skip)]` as needed when using serde).
// For `#[recallable]` fields, the derived `From` impl also requires
// `<FieldType as Recallable>::Memento: From<FieldType>`.

#[derive(PartialEq, Deserialize)]
pub struct AccumulatorMemento<T> {
    prev_control_signal: T,
    accumulated: u32,
}

impl<T> Recallable for Accumulator<T> {
    type Memento = AccumulatorMemento<T>;
}

impl<T> From<Accumulator<T>> for AccumulatorMemento<T> {
    fn from(acc: Accumulator<T>) -> Self {
        Self {
            prev_control_signal: acc.prev_control_signal,
            accumulated: acc.accumulated,
        }
    }
}

impl<T> Recall for Accumulator<T> {
    fn recall(&mut self, memento: Self::Memento) {
        self.prev_control_signal = memento.prev_control_signal;
        self.accumulated = memento.accumulated;
    }
}
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

fn main() {
    let accumulator = Accumulator {
        prev_control_signal: 6,
        filter: |x: &i32| *x > 300,
        accumulated: 15,
    };

    let state_bytes = postcard::to_vec::<_, 128>(&accumulator).unwrap();
    let accumulator_memento: <Accumulator<i32> as Recallable>::Memento =
        postcard::from_bytes(&state_bytes).unwrap();

    let mut recovered_accumulator = Accumulator {
        prev_control_signal: -1,
        accumulated: 0,
        ..accumulator
    };

    recovered_accumulator.recall(accumulator_memento);

    assert_eq!(recovered_accumulator.prev_control_signal, accumulator.prev_control_signal);
    assert_eq!(recovered_accumulator.accumulated, accumulator.accumulated);
}

Declares the associated memento type.

Required Associated Types§

Source

type Memento

The type of memento associated with this structure.

Implementors§