rusty_esp_core/lib.rs
1#![cfg_attr(not(feature = "std"), no_std)]
2// `deny`, not `forbid`, for exactly ONE exception: `pcm::as_i16`/`as_i16_mut`,
3// six lines that view an aligned `&[u8]` as `&[i16]`. Everything else in this
4// crate still rejects `unsafe` at compile time, and the two exceptions carry
5// `#[allow(unsafe_code)]` on the function, so `git grep unsafe_code` finds
6// every one of them.
7//
8// Why it is here at all: on a 32-bit core, `i16::from_le_bytes([b[0], b[1]])`
9// over a `&[u8]` cannot use a halfword load, because the load needs 2-byte
10// alignment the compiler cannot prove a byte slice has. Measured on an
11// ESP32-S3, that costs the audio elements 42-59% -- `StereoToMono` spent 56
12// of its 72 loop instructions marshalling bytes into i16s and back.
13//
14// Why not `bytemuck`, which does exactly this and needs no `unsafe` here:
15// this crate is the base of nine repos and has ZERO dependencies, which is
16// worth more than six auditable lines. Swapping to `bytemuck::try_cast_slice`
17// is a three-line change if that trade is ever re-made.
18#![deny(unsafe_code)]
19//! `rusty_esp_core` — the shared vocabulary of the Janus ESP family.
20//!
21//! Every Janus package (`rusty_esp_audio`, `rusty_esp_image`, `rusty_esp_video`,
22//! `rusty_esp_signal`, `rusty_esp_iroh`, `rusty_esp_mid`) speaks these types at
23//! its boundary, so a camera frame from one crate flows into an encoder in
24//! another and onto the mesh in a third with no conversion and no copy.
25//!
26//! What lives here, and the rule that keeps it small:
27//!
28//! | Module | Holds | Rule |
29//! |---|---|---|
30//! | [`time`] | [`Micros`], a monotonic device timestamp; [`WallOffset`], the host's device→wall mapping with its error bound | value type, no clock |
31//! | [`error`] | [`Error`], one `Copy` error for the family | no `String`, no `alloc` |
32//! | [`frame`] | [`Frame`], a **borrowed** image/video frame | planes over caller memory |
33//! | [`pcm`] | [`PcmBlock`], a **borrowed** interleaved PCM block | same |
34//! | [`capability`] | [`Manifest`], what a device can do, canonically encoded; [`capability::ParsedManifest`] reads it back (`alloc`) | signed by `rusty_esp_mid` |
35//! | [`media`] | [`MediaPacket`], a **borrowed** coded packet and its [`Codec`] | the shape every transport frames |
36//! | [`hal`] | [`Clock`], [`Rng`], [`Kv`] — the three seams every backend fills | traits only |
37//!
38//! Nothing here is a driver, an allocator, a codec, or a product type. If a
39//! type needs `esp-hal`, ESP-IDF, or a codec crate to define it, it does not
40//! belong in this crate.
41//!
42//! **Why borrowed frames.** The FFmpeg-shaped `Vec<Vec<u8>>`-per-frame model
43//! is one-plus-N heap allocations per frame, returned by value. On a chip with
44//! 512 KB of SRAM that is the wrong shape at every level: allocation count,
45//! ownership, and the trait signatures it forces. Janus frames are views over
46//! memory the caller (a DMA ring, a static arena, a `Vec` on the host) already
47//! owns. Sources write into caller buffers; encoders read views.
48//!
49//! Feature ladder: `std` ⊃ `alloc` ⊃ core-only. The crate compiles for
50//! `riscv32imac-unknown-none-elf` with `--no-default-features`.
51
52#[cfg(feature = "alloc")]
53extern crate alloc;
54
55pub mod capability;
56pub mod error;
57pub mod frame;
58pub mod hal;
59pub mod media;
60pub mod pcm;
61pub mod prelude;
62pub mod time;
63
64pub use capability::{Capability, Chip, Declared, Manifest, Status};
65pub use error::Error;
66pub use frame::{Frame, FrameMut, Geometry, PixelFormat, Plane, PlaneMut, Planes, PlanesMut};
67pub use hal::{Clock, Kv, Rng};
68pub use media::{Codec, MediaPacket};
69pub use pcm::{PcmBlock, PcmFormat, SampleFormat};
70pub use time::{Micros, WallOffset};
71
72/// Crate version, for capability manifests and logs.
73pub const VERSION: &str = env!("CARGO_PKG_VERSION");
74
75/// The wire/format version of every canonical encoding this crate defines.
76/// Bump only with an accept-both reader already shipped (see the Janus plan,
77/// "changing a format others already read").
78pub const FORMAT_VERSION: u8 = 1;