ic-stable-structures 0.7.2

A collection of data structures for fearless canister upgrades.
Documentation
# The Memory Trait

Stable structures are responsible for managing their own memory.
To provide maximum flexibility, the library introduces the `Memory` trait:

```rust
pub trait Memory {
    /// Equivalent to WebAssembly memory.size.
    fn size(&self) -> u64;

    /// Equivalent to WebAssembly memory.grow.
    /// Returns the previous size, or -1 if the grow fails.
    fn grow(&self, pages: u64) -> i64;

    /// Copies bytes from this memory to the heap (in Wasm, memory 0).
    /// Panics or traps if out of bounds.
    fn read(&self, offset: u64, dst: &mut [u8]);

    /// Writes bytes from the heap (in Wasm, memory 0) to this memory.
    /// Panics or traps if out of bounds.
    fn write(&self, offset: u64, src: &[u8]);
}
```

The `Memory` trait intentionally models a [WebAssembly memory instance](https://webassembly.github.io/multi-memory/core/exec/runtime.html#memory-instances).
This design choice ensures consistency with the interface of memories available to canisters.
It also provides future compatibility with potential multi-memory support in canisters.

## Panics  

⚠️ `read` and `write` **assume the caller will not access memory outside the current size**.

If the range `[offset … offset + len)` exceeds available memory, the call panics (in native tests) or traps (in a Wasm canister).
Callers must store and check data lengths themselves or use higher-level containers such as `StableVec`.

## Available Memory Implementations

The library provides several implementations of the `Memory` trait, each designed for specific use cases:

- `Ic0StableMemory`: Stores data in the Internet Computer's stable memory
- `VectorMemory`: An in-memory implementation backed by a Rust `Vec<u8>`
- `DefaultMemoryImpl`: A smart implementation that automatically selects the appropriate memory backend:
  - Uses `Ic0StableMemory` when running in an Internet Computer canister (wasm32 target)
  - Falls back to `VectorMemory` in other environments (like tests or non-IC contexts)

Additional implementations such as `FileMemory` and `RestrictedMemory` exist but are less commonly used.

```admonish note ""
In most cases, you should use `DefaultMemoryImpl` as your memory implementation.
```

### Usage Example

Here's how to initialize a stable `BTreeMap` using `DefaultMemoryImpl`:

```rust
use ic_stable_structures::{BTreeMap, DefaultMemoryImpl};
let mut map: BTreeMap<u64, u64, _> = BTreeMap::init(DefaultMemoryImpl::default());
```

```admonish warning ""
**Important**: Stable structures cannot share memories.
Each memory must be dedicated to a single stable structure.
```

While the above example works correctly, it demonstrates a potential issue: the `BTreeMap` will use the entire stable memory.
This becomes problematic when trying to use multiple stable structures.
For example, the following code will fail in a canister:

```rust
use ic_stable_structures::{BTreeMap, DefaultMemoryImpl};
let mut map_1: BTreeMap<u64, u64, _> = BTreeMap::init(DefaultMemoryImpl::default());
let mut map_2: BTreeMap<u64, u64, _> = BTreeMap::init(DefaultMemoryImpl::default());

map_1.insert(1, 2);
map_2.insert(1, 3);
assert_eq!(map_1.get(&1), Some(2)); // This assertion fails.
```

The code fails because both `map_1` and `map_2` are using the same stable memory.
This causes changes in one map to affect or corrupt the other.

To solve this problem, the library provides the [MemoryManager](./memory-manager.md), which creates up to 255 virtual memories from a single memory instance.
We'll explore this solution in the next section.