store_custom_data

Function store_custom_data 

Source
pub fn store_custom_data<T: StableType + AsDynSizeBytes>(
    idx: usize,
    data: SBox<T>,
)
Expand description

Persists a pointer to an SBox between canister upgrades mapped to some unique usize key.

See also retrieve_custom_data.

Despite the fact that stable memory data structures from this crate store all data completely on stable memory, they themselves are stored on stack. Exactly how standard data structures (Vec, for example) store their data on heap, but themselves are stored on stack. This means that in order to persist this data structures between canister upgrades, we have to temporary store them on stable memory aswell.

This function allows one to do that, by assigning a unique usize index to the stored data, which was previously stored in SBox.

This function should be used in the #[pre_upgrade] canister method. Right before stable_memory_pre_upgrade() invocation. This function can be used multiple times, but one should make sure they always keep track of keys they are assigning custom data to. An attempt to assign two values to a single key will lead to losing the data that was assigned first. Be careful!

Internally calls StableMemoryAllocator::store_custom_data.

§Example

static mut STATE: Option<SHashMap<u64, u64>> = None;

#[ic_cdk_macros::pre_upgrade]
fn pre_upgrade() {
    let state = unsafe { STATE.take().unwrap() };
    let boxed_state = SBox::new(state).expect("Out of memory");

    store_custom_data(1, boxed_state);

    // always as a last expression of "pre_upgrade"
    stable_memory_pre_upgrade();
}

#[ic_cdk_macros::post_upgrade]
fn post_upgrade() {
    // always as a first expression of "post_upgrade"
    stable_memory_post_upgrade();

    let boxed_state = retrieve_custom_data::<SHashMap<u64, u64>>(1)
        .expect("Key not found");

    unsafe { STATE = Some(boxed_state.into_inner()); }
}

One can also persist other data this way


#[ic_cdk_macros::pre_upgrade]
fn pre_upgrade() {
    let very_important_string = String::from("THE PASSWORD IS 42");
    let boxed_string = SBox::new(very_important_string)
        .expect("Out of memory");
     
    store_custom_data(2, boxed_string);

    // always as a last expression of "pre_upgrade"
    stable_memory_pre_upgrade();
}

#[ic_cdk_macros::post_upgrade]
fn post_upgrade() {
    // always as a first expression of "post_upgrade"
    stable_memory_post_upgrade();

    let boxed_string = retrieve_custom_data::<String>(2)
        .expect("Key not found");

    let very_important_string = boxed_string.into_inner();
}

§Panics

Panics if there is no initialized stable memory allocator.