weaveffi/lib.rs
1//! WeaveFFI: write safe Rust, get a stable C ABI and bindings for 11 languages.
2//!
3//! This is the single crate a Rust producer depends on. Annotate an ordinary
4//! module with [`macro@module`], tag the items you want to export, and call
5//! [`export_runtime!`] once. The [`macro@module`] expansion emits the
6//! `extern "C"` thunks that the generated language bindings call, marshalling
7//! every argument and result through the audited [`abi`] runtime so you never
8//! write `unsafe` glue by hand. Every C symbol starts with the crate's name
9//! (`calculator_math_add` below).
10//!
11//! ```ignore
12//! #[weaveffi::module]
13//! pub mod math {
14//! /// The module's error domain; `Display` supplies the runtime message.
15//! #[weaveffi::error]
16//! #[derive(Debug)]
17//! pub enum MathError {
18//! /// Division by zero.
19//! DivisionByZero = 1,
20//! }
21//!
22//! impl std::fmt::Display for MathError {
23//! fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24//! f.write_str("division by zero")
25//! }
26//! }
27//!
28//! /// Add two integers.
29//! #[weaveffi::export]
30//! pub fn add(a: i32, b: i32) -> i32 {
31//! a + b
32//! }
33//!
34//! /// Divide, reporting division by zero through the ABI's error channel.
35//! #[weaveffi::export]
36//! pub fn div(a: i32, b: i32) -> Result<i32, MathError> {
37//! a.checked_div(b).ok_or(MathError::DivisionByZero)
38//! }
39//! }
40//!
41//! // Export the runtime symbols (memory, errors, cancel tokens) once.
42//! weaveffi::export_runtime!();
43//! ```
44//!
45//! The macro also embeds the API in the built library, which is what
46//! `weaveffi generate` (run in the crate) reads to emit the header and
47//! bindings, so the producer and the bindings can't drift: the bindings
48//! describe exactly what the library was compiled with.
49//!
50//! # What you get
51//!
52//! * [`macro@module`] - the driver attribute on an exported `mod`.
53//! * [`macro@export`] - export a function (`async fn` is asynchronous; a
54//! `Result`-returning fn is fallible).
55//! * [`macro@record`] - a by-value struct serialized across the ABI.
56//! * [`macro@enumeration`] - a `#[repr(i32)]` C-style enum, or a rich enum
57//! with data-carrying variants.
58//! * [`macro@interface`] - an opaque, reference-counted object type; pass one
59//! as `&T` or `Arc<T>`, return one as `Self`, `T`, or `Arc<T>`.
60//! * [`macro@error`] - the module's error domain.
61//! * [`macro@callback_interface`] - a trait the consumer implements; accept
62//! one as `Arc<dyn Trait>` (or `Option<Arc<dyn Trait>>`). Its methods
63//! return `Result<T, ForeignError>`; [`macro@throws`] lets one report the
64//! module's domain errors.
65//! * [`macro@cancellable`] - mark an `async fn` as accepting a cancel token.
66//! * [`set_spawner`] - install the executor async exports run on; the default
67//! is a small pool of worker threads, or Tokio with the `tokio` feature.
68//! * [`export_runtime!`] - export the runtime symbols (memory, errors, cancel
69//! tokens, ABI version) under the crate's prefix, once per library.
70//! * [`abi`] - the C ABI runtime: the error struct, memory helpers, and the
71//! marshalling converters the expansion calls.
72//!
73//! # Features
74//!
75//! * `leak-check` counts live objects, callbacks, iterators, cancel tokens,
76//! and returned allocations, reported by `{prefix}_debug_live` so a test
77//! harness can assert a consumer released everything. Off by default.
78//! * `tokio` runs exported `async fn`s on Tokio: the current runtime when a
79//! launcher is called from inside one, otherwise a multi-thread runtime
80//! created on first use. [`set_spawner`] still overrides it. Off by
81//! default.
82
83#![deny(missing_docs)]
84#![warn(clippy::missing_errors_doc)]
85#![warn(clippy::missing_panics_doc)]
86#![warn(clippy::missing_safety_doc)]
87#![warn(clippy::doc_markdown)]
88
89pub mod abi;
90
91/// An owned, lazily-pulled iterator returned by a producer function whose IDL
92/// return type is `iter<T>`. Construct one from any iterator with
93/// [`Iter::new`](abi::Iter::new); the [`macro@module`] expansion turns
94/// it into the opaque iterator handle the generated bindings consume.
95pub use abi::Iter;
96
97/// The producer's handle on a consumer's cancel token, accepted as the final
98/// parameter of a `#[weaveffi::cancellable]` `async fn`. When the consumer
99/// cancels, the runtime drops the function's future and completes the call
100/// with the cancelled code; poll
101/// [`is_cancelled`](abi::CancelToken::is_cancelled) only for
102/// cooperative cleanup (work on other threads, say).
103pub use abi::CancelToken;
104
105/// A consumer's callback-interface implementation failed. Every callback
106/// trait method returns `Result<T, ForeignError>`, so the failure arrives as
107/// an `Err`; a method marked `#[weaveffi::throws]` can decode a declared
108/// domain error from it with [`ForeignError::domain`](abi::ForeignError::domain).
109pub use abi::ForeignError;
110
111/// A module's error domain: the trait the `#[weaveffi::error]` expansion
112/// implements so [`ForeignError::domain`](abi::ForeignError::domain) can
113/// decode a typed error a callback reported.
114pub use abi::ErrorDomain;
115
116/// Maps a producer error onto the ABI's `(code, message)` pair. A fallible
117/// `#[weaveffi::export]` function reports `Err(e)` through its trailing
118/// `out_err` slot using this trait: `String` and `&str` errors get the
119/// generic code `-1` out of the box, while a `#[weaveffi::error]` enum (or a
120/// manual [`ErrorReport`] impl) surfaces the named codes of an IDL error
121/// domain, with its `Display` output as the message.
122pub use abi::ErrorReport;
123
124/// Install the process-wide executor that exported `async fn`s run on. Call it
125/// once at startup (before the first async export is launched) to hand futures
126/// to a runtime of your choice; until then, and if never called, futures run
127/// on the default executor (a small worker pool, or Tokio with the `tokio`
128/// feature).
129pub use abi::set_spawner;
130
131/// The executor hook [`set_spawner`] accepts: anything callable as
132/// `Fn(BoxFuture)` that is `Send + Sync + 'static`.
133pub use abi::Spawner;
134
135/// The type-erased `Send + 'static` future a [`Spawner`] receives.
136pub use abi::BoxFuture;
137
138pub use weaveffi_macros::{
139 callback_interface, cancellable, enumeration, error, export, export_runtime, interface, module,
140 record, throws,
141};