io_m2dir/lib.rs
1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3
4//! # io-m2dir
5//!
6//! I/O-free m2dir coroutines: every filesystem exchange needed to
7//! deliver, read, flag and remove messages in the
8//! [m2dir](https://man.sr.ht/~bitfehler/m2dir/) mail storage format is a
9//! resumable state machine emitting filesystem requests instead of
10//! performing I/O itself, so the caller owns the syscalls and pumps the
11//! coroutine (see the `client` feature for a ready-made std-blocking
12//! pump).
13//!
14//! The crate ships two of the standard Pimalaya layers: the I/O-free
15//! coroutines (no_std core, always present) and a std-blocking client
16//! (`client` feature, default) backed by [`std::fs`]. There is no full
17//! client layer: m2dir is local storage, so there is no socket to open.
18//!
19//! ## Layout
20//!
21//! The source tree groups coroutines by the object they act on, one
22//! folder per object with a sibling module carrying the shared types:
23//! [`m2dir`] (create, delete, list a mailbox directory, plus the
24//! [`m2dir::M2dir`] handle), [`entry`] (store, get, list, delete a
25//! message, plus [`entry::M2dirEntry`]) and [`flag`] (add, remove, set
26//! flags, plus [`flag::M2dirFlags`]). Code reused across objects lives
27//! at the crate root: the [`coroutine`] contract, the [`M2dirStore`]
28//! root wrapper, the [`M2dirPath`] newtype and the private checksum
29//! helpers. The std [`client`] spans every object.
30//!
31//! [`M2dirStore`]: store::M2dirStore
32//! [`M2dirPath`]: path::M2dirPath
33//!
34//! ## The coroutine contract
35//!
36//! Every coroutine implements [`coroutine::M2dirCoroutine`], mirroring
37//! the shape of `core::ops::Coroutine`: a `resume` step returns a
38//! [`coroutine::M2dirCoroutineState`], either a yield or the terminal
39//! result. io-m2dir is filesystem-flavoured, so every coroutine picks
40//! the shared [`coroutine::M2dirYield`], which gathers every primitive
41//! the crate emits: directory create, read and remove; file create,
42//! read, exists and remove; path rename; and the process id and random
43//! bytes needed to mint entry identifiers. The caller services each
44//! yield and feeds the matching [`coroutine::M2dirArg`] back on the next
45//! resume.
46//!
47//! ## The std client
48//!
49//! [`client::M2dirClient`] (`client` feature) wraps a filesystem root
50//! pointing at an m2store and exposes one method per coroutine, running
51//! each to completion against [`std::fs`]. It supplies the process id
52//! and a xorshift64* random nonce the coroutines ask for, and adds a
53//! thread-scoped parallel bulk read for reading many entries at once.
54//!
55//! ## Conventions
56//!
57//! The conventions every Pimalaya repository shares (the sans-I/O
58//! coroutine approach, no_std, module and naming rules) are described in
59//! the [Pimalaya ARCHITECTURE](https://github.com/pimalaya/.github/blob/master/ARCHITECTURE.md)
60//! and [GUIDELINES](https://github.com/pimalaya/.github/blob/master/GUIDELINES.md).
61//! Public types follow the M2dir-Target-Verb naming scheme
62//! (`M2dirEntryStore`, `M2dirFlagAdd`) with Options, Output and Error
63//! companions. Runnable snippets live in each coroutine module's
64//! rustdoc, and the integration test exercises the full client surface.
65
66#[macro_use]
67extern crate alloc;
68#[cfg(feature = "client")]
69extern crate std;
70
71mod checksum;
72
73#[cfg(feature = "client")]
74pub mod client;
75pub mod coroutine;
76pub mod entry;
77pub mod flag;
78pub mod m2dir;
79pub mod path;
80pub mod store;