17个不稳定版本 (3个重大变更)
0.4.4 | 2023年4月6日 |
---|---|
0.4.3 | 2023年3月28日 |
0.4.1 | 2023年2月22日 |
0.4.0-rc1 | 2022年10月24日 |
0.1.0 | 2022年7月11日 |
#482 in 魔法豆
每月下载量:760
460KB
11K SLoC
IC稳定内存
允许使用canister的稳定内存作为主内存。
功能
8
稳定数据结构SBox
替代Box
SVec
和SLog
替代Vec
SHashMap
替代HashMap
SHashSet
替代HashSet
SBTreeMap
替代BTreeMap
SBTreeSet
替代BTreeSet
SCertifiedBTreeMap
替代Dfinity的RBTree
- 强制执行Rust的借用规则
- 数据结构在离开作用域时自动释放
- 数据结构拥有其内部值,允许引用访问
- API允许程序性响应
OutOfMemory
错误,同时保持其几乎与std
相同 - 完整的工具集以构建自己的稳定数据结构
安装
# cargo.toml
[dependencies]
ic-stable-memory = "0.4"
快速示例
让我们构建一个Todo
应用,因为它们非常受欢迎 :)
use candid::{CandidType, Deserialize};
use ic_cdk_macros::{init, post_upgrade, pre_upgrade, query, update};
use ic_stable_memory::collections::SVec;
use ic_stable_memory::derive::{CandidAsDynSizeBytes, StableType};
use ic_stable_memory::{
retrieve_custom_data, stable_memory_init, stable_memory_post_upgrade,
stable_memory_pre_upgrade, store_custom_data, 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<SBox<Task>>;
thread_local! {
static STATE: RefCell<Option<State>> = RefCell::default();
}
#[update]
fn add_task(task: Task) {
STATE.with(|s| {
let boxed_task = SBox::new(task).expect("Out of memory");
s.borrow_mut()
.as_mut()
.unwrap()
.push(boxed_task)
.expect("Out of memory");
});
}
#[update]
fn remove_task(idx: u32) {
STATE.with(|s| {
s.borrow_mut().as_mut().unwrap().remove(idx as usize);
});
}
#[update]
fn swap_tasks(idx_1: u32, idx_2: u32) {
STATE.with(|s| {
s.borrow_mut()
.as_mut()
.unwrap()
.swap(idx_1 as usize, idx_2 as usize);
});
}
#[query]
fn get_todo_list() -> Vec<Task> {
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() {
stable_memory_init();
STATE.with(|s| {
*s.borrow_mut() = Some(SVec::new());
});
}
#[pre_upgrade]
fn pre_upgrade() {
let state: State = STATE.with(|s| s.borrow_mut().take().unwrap());
let boxed_state = SBox::new(state).expect("Out of memory");
store_custom_data(0, boxed_state);
stable_memory_pre_upgrade().expect("Out of memory");
}
#[post_upgrade]
fn post_upgrade() {
stable_memory_post_upgrade();
let state = retrieve_custom_data::<State>(0).unwrap().into_inner();
STATE.with(|s| {
*s.borrow_mut() = Some(state);
});
}
文档
- 快速入门
- 完整的API文档
- 如何迁移正在运行的canister
- 如何处理
OutOfMemory
错误 - 如何确保数据可升级性
- 如何实现编码特征
- 如何节省cycles并使其更快
- 基准测试
- 如何构建自己的稳定数据结构
- 内部机制是什么
示例项目
版本控制
ic-stable-memory
遵循语义版本控制指南,并将其推进了一步。当小版本或补丁版本发生变化时,您可以安全地更新此依赖项。但如果主要版本发生变化,这意味着您的罐将无法与新版本一起工作,您不应更新。这种情况不会经常发生,实际上,这个库有很多改进空间,无需破坏性变更,但这种情况可能发生。
贡献
这是一个新兴的软件,因此任何帮助都将受到高度重视。请随时通过Github问题提出PR、架构建议、错误报告或其他反馈。
测试覆盖率检查
cargo安装grcov
rustup组件添加 llvm-tools-preview
./coverage.sh --test
(没有--test
将不会重建)
依赖项
~4–13MB
~133K SLoC