State
State<T> is the SDK abstraction for storing one typed value under one fixed key. This page explains each operation in detail.
Declare
State is declared as a handle bound to a key and a type. There are two ways to create one:
- As a module-level constant at compile time - when the key is a fixed string known when writing the code:
use myrmic_sdk::db::state::State;
const THRESHOLD: State<f32> = State::new_const("threshold");
- At runtime-from within a handler-when the key is dynamic and depends on information available only while the program is running:
let state = State::<f32>::new(&device_id);
Both bind to the default scope - private to the cell. To use a custom scope, pass it explicitly using new_const_in or new_in:
use myrmic_sdk::db::Scope;
// Compile time - private with a custom schema
const THRESHOLD: State<f32> = State::new_const_in(
"threshold",
Scope::private_in(Some("config")),
);
// Runtime - public, shared across cells using the same scope
let state = State::<f32>::new_in(
&device_id,
Scope::public("my-app"),
);
Write
The state handle exposes a save method. It takes a reference to the value and writes it to the runtime database under the handle's key, overwriting any existing value.
THRESHOLD.save(&30.0)?;
To write under a different key without declaring a separate handle, use save_to. It takes the key and a reference to the value:
THRESHOLD.save_to("threshold-zone-a", &30.0)?;
Read
The state handle exposes a load method. It reads the value from the runtime database and returns it, or None if no value has been stored yet - provide a fallback to handle that case.
let value = THRESHOLD.load()?.unwrap_or(25.0);
To read from a different key without declaring a separate handle, use load_from. It takes the key and returns the value the same way:
let value = THRESHOLD.load_from("threshold-zone-a")?.unwrap_or(25.0);
Modify
Modifying a stored value is a read-change-write cycle. The state handle provides several methods for this, grouped by how the mutation is expressed.
Closure
A closure-based approach passes the current value by mutable reference, runs the closure on it, and saves the result back.
The state handle exposes a modify method. It applies the closure to the stored value, saves the result, and returns the updated value - or None if nothing was stored:
let updated = THRESHOLD.modify(|value| {
*value += 1.0;
})?;
To apply the closure on a different key, use modify_at:
let updated = THRESHOLD.modify_at("threshold-zone-a", |value| {
*value += 1.0;
})?;
Guard
A guard follows Rust's RAII pattern - it loads the value, lets you mutate it directly, and saves it back automatically when it is dropped.
The state handle exposes a guard method. It returns a guard only when a value is already stored - None if nothing is there:
if let Some(mut guard) = THRESHOLD.guard()? {
*guard += 1.0;
}
To open a guard on a different key, use guard_at:
if let Some(mut guard) = THRESHOLD.guard_at("threshold-zone-a")? {
*guard += 1.0;
}
To always get a guard - even when nothing is stored yet - use guard_or_default. It falls back to the type's default when nothing is stored and then yields the guard:
let mut guard = THRESHOLD.guard_or_default()?;
*guard += 1.0;
To do the same on a different key, use guard_or_default_at:
let mut guard = THRESHOLD.guard_or_default_at("threshold-zone-a")?;
*guard += 1.0;
Upsert
Upsert ensures a value is always present - it returns what is stored, or saves the type's default and returns it if nothing is there.
The state handle exposes an upsert method:
let value = THRESHOLD.upsert()?;
To do the same on a different key, use upsert_at:
let value = THRESHOLD.upsert_at("threshold-zone-a")?;
To apply a closure before saving - starting from the type's default when nothing is stored - use upsert_with. It always runs the closure and returns the updated value:
let value = THRESHOLD.upsert_with(|value| {
*value += 1.0;
})?;
To do the same on a different key, use upsert_with_at:
let value = THRESHOLD.upsert_with_at("threshold-zone-a", |value| {
*value += 1.0;
})?;
See also
- How to work with state and storage - back to the guide
- Key-value store - many typed values under different keys