{"id":13524601,"url":"https://github.com/seniorjoinu/ic-stable-memory","last_synced_at":"2025-04-14T17:07:09.919Z","repository":{"id":45502370,"uuid":"432847356","full_name":"seniorjoinu/ic-stable-memory","owner":"seniorjoinu","description":"Lets you store canister data directly in stable memory","archived":false,"fork":false,"pushed_at":"2023-05-10T15:18:22.000Z","size":1053,"stargazers_count":42,"open_issues_count":3,"forks_count":11,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-14T17:07:02.366Z","etag":null,"topics":["dfinity","ic","internet-computer","memory","rust","stable-memory"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seniorjoinu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-28T23:12:58.000Z","updated_at":"2024-12-25T16:18:14.000Z","dependencies_parsed_at":"2024-11-02T09:30:31.996Z","dependency_job_id":"2b6186cf-6cd4-46d1-9ab3-002f0e52a4bf","html_url":"https://github.com/seniorjoinu/ic-stable-memory","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seniorjoinu%2Fic-stable-memory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seniorjoinu%2Fic-stable-memory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seniorjoinu%2Fic-stable-memory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seniorjoinu%2Fic-stable-memory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seniorjoinu","download_url":"https://codeload.github.com/seniorjoinu/ic-stable-memory/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248923766,"owners_count":21183953,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dfinity","ic","internet-computer","memory","rust","stable-memory"],"created_at":"2024-08-01T06:01:11.615Z","updated_at":"2025-04-14T17:07:09.889Z","avatar_url":"https://github.com/seniorjoinu.png","language":"Rust","funding_links":[],"categories":["Storage and Databases"],"sub_categories":["Candid implementations"],"readme":"![test coverage 88.82%](https://badgen.net/badge/coverage/88.82%25/green)\n\n# IC Stable Memory\n\nAllows using canister's stable memory as main memory.\n\n## Features\n* `8` stable data structures:\n  * `SBox` in replacement for `Box`\n  * `SVec` and `SLog` in replacement for `Vec`\n  * `SHashMap` in replacement for `HashMap`\n  * `SHashSet` in replacement for `HashSet`\n  * `SBTreeMap` in replacement for `BTreeMap`\n  * `SBTreeSet` in replacement for `BTreeSet`\n  * `SCertifiedBTreeMap` in replacement for Dfinity's `RBTree`\n  * `SCertifiedBTreeSet` as a thin wrapper for `SCertifiedBTreeMap\u003cT, ()\u003e`\n* Enforced Rust's borrower rules: \n  * data structures drop automatically when leaving the scope\n  * data structures own their inner values, allowing by-reference access\n* The API allows programmatic reaction to `OutOfMemory` errors, while keeping it almost identical to `std`\n* Complete toolset to build your own stable data structure\n\n## Installation\n```toml\n# cargo.toml\n\n[dependencies]\nic-stable-memory = \"0.4\"\n```\n\n## Quick example\nLet's build a `Todo` app, since they're very popular :)\n\n```rust\nuse candid::{CandidType, Deserialize};\nuse ic_cdk_macros::{init, post_upgrade, pre_upgrade, query, update};\nuse ic_stable_memory::collections::SVec;\nuse ic_stable_memory::derive::{CandidAsDynSizeBytes, StableType};\nuse ic_stable_memory::{\n  retrieve_custom_data, stable_memory_init, stable_memory_post_upgrade,\n  stable_memory_pre_upgrade, store_custom_data, SBox,\n};\nuse std::cell::RefCell;\n\n#[derive(CandidType, Deserialize, StableType, CandidAsDynSizeBytes, Debug, Clone)]\nstruct Task {\n  title: String,\n  description: String,\n}\n\n// If you can implement AsFixedSizeBytes for your data type, \n// you can store it directly, without wrapping in SBox\ntype State = SVec\u003cSBox\u003cTask\u003e\u003e;\n\nthread_local! {\n  static STATE: RefCell\u003cOption\u003cState\u003e\u003e = RefCell::default();\n}\n\n#[update]\nfn add_task(task: Task) {\n  STATE.with(|s| {\n    let boxed_task = SBox::new(task).expect(\"Out of memory\");\n    s.borrow_mut()\n            .as_mut()\n            .unwrap()\n            .push(boxed_task)\n            .expect(\"Out of memory\");\n  });\n}\n\n#[update]\nfn remove_task(idx: u32) {\n  STATE.with(|s| {\n    s.borrow_mut().as_mut().unwrap().remove(idx as usize);\n  });\n}\n\n#[update]\nfn swap_tasks(idx_1: u32, idx_2: u32) {\n  STATE.with(|s| {\n    s.borrow_mut()\n            .as_mut()\n            .unwrap()\n            .swap(idx_1 as usize, idx_2 as usize);\n  });\n}\n\n#[query]\nfn get_todo_list() -\u003e Vec\u003cTask\u003e {\n  STATE.with(|s| {\n    let mut result = Vec::new();\n\n    for task in s.borrow().as_ref().unwrap().iter() {\n      result.push(task.clone());\n    }\n\n    result\n  })\n}\n\n#[init]\nfn init() {\n  stable_memory_init();\n\n  STATE.with(|s| {\n    *s.borrow_mut() = Some(SVec::new());\n  });\n}\n\n#[pre_upgrade]\nfn pre_upgrade() {\n  let state: State = STATE.with(|s| s.borrow_mut().take().unwrap());\n  let boxed_state = SBox::new(state).expect(\"Out of memory\");\n\n  store_custom_data(0, boxed_state);\n\n  stable_memory_pre_upgrade().expect(\"Out of memory\");\n}\n\n#[post_upgrade]\nfn post_upgrade() {\n  stable_memory_post_upgrade();\n\n  let state = retrieve_custom_data::\u003cState\u003e(0).unwrap().into_inner();\n  STATE.with(|s| {\n    *s.borrow_mut() = Some(state);\n  });\n}\n```\n\n## Documentation\n0. [Quick start](./docs/quick-start.md)\n1. [Complete API documentation](https://docs.rs/ic-stable-memory/)\n2. [How to migrate a running canister](./docs/migration.md)\n3. [How to handle `OutOfMemory` errors](./docs/out-of-memory-error-handling.md)\n4. [How to ensure data upgradability](./docs/upgradeability.md)\n5. [How to implement encoding traits](./docs/encoding.md)\n6. [How to save cycles and make it faster](./docs/perfomance.md)\n7. [Benchmarks](./docs/benchmarks.md)\n8. [How to build your own stable data structure](./docs/user-defined-data-structures.md)\n9. [What's under the hood](./docs/architecture.md)\n\n## Example projects\n* [Simple token canister](./examples/token)\n* [Performance counter canister](./examples/performance_counter)\n* [Stable certified assets canister](https://github.com/seniorjoinu/ic-stable-certified-assets)\n\n## Versioning\n`ic-stable-memory` follows semantic versioning guidelines and takes them one step further. You're safe to update this\ndependency when minor or patch version changes. But if the major version changes, it means that your canister won't be\nable to work with the new version and you shouldn't update. Such an event won't happen often and, in fact, this library\nhas a lot of room to improve without breaking changes, but this may happen.\n\n## Contribution\nThis is an emerging software, so any help is greatly appreciated.\nFeel free to propose PR's, architecture tips, bug reports or any other feedback via Github issues.\n\n## Test coverage check\n* `cargo install grcov`\n* `rustup component add llvm-tools-preview`\n* `./coverage.sh --test` (won't rebuild without `--test`)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseniorjoinu%2Fic-stable-memory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseniorjoinu%2Fic-stable-memory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseniorjoinu%2Fic-stable-memory/lists"}