test coverage 88.82%

IC Stable Memory

Allows using canister's stable memory as main memory.

Features

Installation

```toml

cargo.toml

[dependencies] ic-stable-memory = "0.4" ```

Quick example

Let's build a Todo app, since they're very popular :)

```rust use candid::{CandidType, Deserialize}; use iccdkmacros::{init, postupgrade, preupgrade, query, update}; use icstablememory::collections::SVec; use icstablememory::derive::{CandidAsDynSizeBytes, StableType}; use icstablememory::{ retrievecustomdata, stablememoryinit, stablememorypostupgrade, stablememorypreupgrade, storecustomdata, SBox, }; use std::cell::RefCell;

[derive(CandidType, Deserialize, StableType, CandidAsDynSizeBytes, Debug, Clone)]

struct Task { title: String, description: String, }

// If you can implement AsFixedSizeBytes for your data type, // you can store it directly, without wrapping in SBox type State = SVec>;

thread_local! { static STATE: RefCell> = RefCell::default(); }

[update]

fn addtask(task: Task) { STATE.with(|s| { let boxedtask = SBox::new(task).expect("Out of memory"); s.borrowmut() .asmut() .unwrap() .push(boxed_task) .expect("Out of memory"); }); }

[update]

fn removetask(idx: u32) { STATE.with(|s| { s.borrowmut().as_mut().unwrap().remove(idx as usize); }); }

[update]

fn swaptasks(idx1: u32, idx2: u32) { STATE.with(|s| { s.borrowmut() .asmut() .unwrap() .swap(idx1 as usize, idx_2 as usize); }); }

[query]

fn gettodolist() -> Vec { STATE.with(|s| { let mut result = Vec::new();

for task in s.borrow().as_ref().unwrap().iter() {
  result.push(task.clone());
}

result

}) }

[init]

fn init() { stablememoryinit();

STATE.with(|s| { *s.borrow_mut() = Some(SVec::new()); }); }

[pre_upgrade]

fn preupgrade() { let state: State = STATE.with(|s| s.borrowmut().take().unwrap()); let boxed_state = SBox::new(state).expect("Out of memory");

storecustomdata(0, boxed_state);

stablememorypre_upgrade().expect("Out of memory"); }

[post_upgrade]

fn postupgrade() { stablememorypostupgrade();

let state = retrievecustomdata::(0).unwrap().intoinner(); STATE.with(|s| { *s.borrowmut() = Some(state); }); } ```

Documentation

  1. Quick start
  2. Complete API documentation
  3. How to migrate a running canister
  4. How to handle OutOfMemory errors
  5. How to ensure data upgradability
  6. How to implement encoding traits
  7. How to save cycles and make it faster
  8. Benchmarks
  9. How to build your own stable data structure
  10. What's under the hood

Example projects

Versioning

ic-stable-memory follows semantic versioning guidelines and takes them one step further. You're safe to update this dependency when minor or patch version changes. But if the major version changes, it means that your canister won't be able to work with the new version and you shouldn't update. Such an event won't happen often and, in fact, this library has a lot of room to improve without breaking changes, but this may happen.

Contribution

This is an emerging software, so any help is greatly appreciated. Feel free to propose PR's, architecture tips, bug reports or any other feedback via Github issues.

Test coverage check