1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
//! The SDK for writing Myrmic cells: WebAssembly modules that deploy and
//! self-organize across a swarm of devices.
//!
//! Myrmic runs application logic as *cells* — portable, isolated Wasm units
//! the runtime deploys, supervises, and connects across embedded, mobile, and
//! server targets. This crate is what a cell links against: it turns plain
//! Rust functions into the exports the runtime invokes, and wraps everything
//! the host offers in safe Rust APIs.
//!
//! # A minimal cell
//!
//! A cell is a `no_std` library crate. There is no `main` and no allocator or
//! panic-handler boilerplate — the default `cell-init` feature emits those via
//! [`cell_prelude!`]. Handlers are free functions marked with the attributes
//! below:
//!
//!
//! The [`tests/fixtures/cell-*`](https://github.com/peeriot/myrmic/tree/master/tests/fixtures)
//! crates are complete working cells exercising each feature; they are the
//! best starting templates.
//!
//! # Handlers
//!
//! | Attribute | Export invoked when | Payload |
//! |---|---|---|
//! | [`#[init]`](macro@init) | Once per incarnation: first deploy, and again on every respawn/restart | optional spawn argument |
//! | [`#[cmd]`](macro@cmd) | Another cell [`send`]s the command (or a timer tick / gateway call names it) | any [`Decoder`]; replies go through a [`Callback`] parameter |
//! | [`#[evt]`](macro@evt) | A subscribed event is [`publish`]ed | the event's payload |
//! | [`#[monitor]`](macro@monitor) | A child cell dies (crash, stop, termination, node loss) | [`monitor::CellLost`] |
//!
//! Every handler takes a leading [`Metadata`] (the cell's own [`Sri`] and the
//! sender's) and returns [`Result`]. Payload types derive [`Message`] to pick
//! their wire codec ([`Json`] by default, or any [`Codec`] via
//! `#[codec(...)]`).
//!
//! # What the host offers
//!
//! - **Messaging** — [`send`] commands to a cell, [`publish`] events to
//! subscribers, reply via [`Callback`].
//! - **Storage** (the *datalayer*, module [`db`]) — typed handles
//! [`Kv`](db::tree::Kv), [`Table`](db::table::Table),
//! [`State`](db::state::State), plus blob, time-series, and semantic
//! stores. Private db state survives restarts and respawns.
//! - **Spawning & supervision** — [`declare!`] a child class, spawn it with
//! [`ClassHandle`], get [`monitor`](macro@monitor) callbacks when it dies,
//! [`terminate_cell`] / [`stop_self`] to tear down.
//! - **Timers** — [`delay`], [`interval`], [`interval_at`] schedule future
//! invocations of a named command export.
//! - **Time** — [`now`] (swarm-synchronised wall clock), [`uptime`]
//! (monotonic), [`wait`].
//! - **Logging** — [`trace!`] … [`error!`] macros and their `_str` variants.
//! - **Signal layer** — [`tap`](mod@tap)s onto host-side signals, [`gpio`]
//! pins, [`ble`] centrals/peripherals.
//! - **Bridges** — [`import!`](macro@import) generates typed clients for
//! HTTP APIs and MQTT brokers from YAML specs.
//! - **Gateway** — [`gateway`] mounts blob scopes as static assets and routes
//! HTTP to commands.
//!
//! # Execution model
//!
//! Cells are single-threaded: the runtime invokes one export at a time, so
//! handlers never race each other. A panic is logged with its location and
//! traps the module; the parent (if any) hears about it through its
//! [`monitor`](macro@monitor) handler. Durable state belongs in the
//! datalayer — volatile resources like timers die with the incarnation and
//! are re-established in [`#[init]`](macro@init).
//!
//! # Feature flags
//!
//! | Feature | Default | Enables |
//! |---|---|---|
//! | `alloc` | yes | heap, codecs, everything payload-shaped |
//! | `cells` | yes | messaging, spawning, timers, handler attributes |
//! | `db` | yes | the datalayer APIs |
//! | `cell-init` | yes | the allocator/panic-handler prelude a deployable cell needs |
//! | `eio` | no | `embedded-io` codecs for the shared wire types |
//! | `types-web` | no | `myrmic-common`'s web wire types, for a build that takes that crate without its defaults |
//!
//! The default set is the only configuration that builds today: without
//! `alloc` the mandatory `serde_json` dependency has no allocator, and
//! `myrmic-common` is taken with its own defaults, so the shared `cells`,
//! `db` and `types-web` items - [`types::web`] among them - are present no
//! matter what is selected above.
//!
//! # Further reading
//!
//! The [Myrmic book](https://book.myrmic.dev/) carries the quickstart,
//! tutorials (observability, BLE), and architecture chapters; this crate's
//! docs are the API reference.
// using the crate just from Wasm -> no need to worry about casting to i32
// using the crate just from Wasm -> no need to worry about casting to i32
// temporary: disable pedantic checks for sdk crate
// temporary: accepted in current sdk types
// temporary: whitelist pedantic lint noise in sdk API surface
// temporary: whitelist pedantic lint noise in sdk API surface
// temporary: whitelist pedantic lint noise in sdk API docs
extern crate alloc;
pub use ;
/// The raw payload buffer type the [`Decoder`]/[`Encoder`] traits work in terms of.
pub type Bytes = ;
pub use ;
pub use Value as JsonValue;
pub use ;
pub use ;
pub use ;
pub use signal_layer;
pub use types;
pub use ;
/// Everything a supervising parent needs: the [`monitor`](macro@crate::monitor)
/// handler's payload types and [`stop_self`] for escalation.
///
/// ```ignore
/// use myrmic_sdk::monitor::{CellLost, LostReason};
///
/// #[myrmic_sdk::monitor]
/// fn lost(md: myrmic_sdk::Metadata, l: CellLost) -> myrmic_sdk::Result<()> {
/// // respawn / escalate / ignore
/// Ok(())
/// }
/// ```
pub use ;
/// Declares a reference to a child cell class by name, returning a
/// [`ClassHandle`] to spawn it with.
///
/// The name is resolved to the child's content hash at deploy time and patched
/// into the module; the reference is stable across redeploys and independent of
/// how the child class is registered. Bind it once and reuse it:
///
/// ```
/// # fn demo(i: u32) -> Result<(), myrmic_sdk::SpawnError> {
/// const CHILD: myrmic_sdk::ClassHandle = myrmic_sdk::declare!("child");
/// CHILD.new().name(format!("child-{i}")).spawn()?;
/// # Ok(())
/// # }
/// ```
;
}
/// Support items referenced by exported macros; not a stable API.
pub use CellEvent;
pub use ble;
pub use ;
pub use db;
pub use gateway;
pub use ;
pub use ;
pub use WireType;
pub use ;
pub use *;
/// Re-exported so that `import_cell!`-generated types can derive `Serialize`/`Deserialize`
/// without the consumer crate needing a direct `serde` dependency.
pub use serde;
/// The handler-export attributes, usable as `#[myrmic_sdk::cmd]` etc.
pub use ;
/// Derives for the [`Codec`]-backed `Decoder`/`Encoder`
/// impls, usable as `#[derive(myrmic_sdk::Message)]`.
pub use Message;
pub use __DefaultHeap;
pub use ;
// The prelude emits a `#[panic_handler]` and the wasm allocator, which only
// compile for the wasm32 cell target.
cell_prelude!;
// Re-export so the macros can refer to embedded-alloc via `$crate::...`
// and the *consumer* crate doesn't need to depend on the deps of the sdk crate.
/// Re-exports the `import!` macro's generated code depends on. Not public API.