pmpx_loader/lib.rs
1//! The host side of the plugin ABI: load a library, agree on capabilities, call it.
2//!
3//! This crate is the only place in the host that touches plugin memory, and together with
4//! `pmpx-plugin-abi` it is the only place that contains `unsafe` at all. Everything above it
5//! (`pmpx-engine`, the CLI) works with `String`, `PathBuf` and `Vec<OsString>`.
6//!
7//! What it deliberately does **not** do:
8//!
9//! - **No file I/O.** A plugin may ask for the contents of a file it declared; this crate forwards
10//! that question to a [`ContextSource`]'s [`Files`] provider, and the engine answers it (reading
11//! files, with whatever limits it wants, is the engine's decision). That is what keeps the ABI
12//! layer free of file-system policy.
13//! - **No policy.** It does not decide which plugin to load, what a verb means, or whether an empty
14//! program is acceptable. It loads, checks, calls, and reports what came back.
15//! - **No printing.** Every failure is a typed error with a message; the CLI renders it.
16//!
17//! # Calling one plugin
18//!
19//! ```no_run
20//! use pmpx_loader::{ContextSource, Plugin};
21//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
22//! // SAFETY: loading a dynamic library runs whatever code is inside it.
23//! let plugin = unsafe { Plugin::open(std::path::Path::new("/path/to/libpmpx_plugin_x.so"))? };
24//! println!("{} ({})", plugin.name(), plugin.family());
25//! # Ok(())
26//! # }
27//! ```
28//!
29//! # Panics
30//!
31//! A panic must not cross an `extern "C"` boundary: since Rust 1.81 that aborts the process at the
32//! boundary, so a host frame can never catch it. The plugin's own shell wraps every entry point in
33//! `catch_unwind`, and that is the only defence there is -- a host that must survive a hostile
34//! plugin has to run it out of process, which is out of scope here.
35#![deny(missing_docs)]
36#![deny(unsafe_op_in_unsafe_fn)]
37
38mod context;
39mod error;
40mod plugin;
41
42pub use context::{ContextSource, Files, NoFiles};
43pub use error::{CallError, LoadError};
44pub use plugin::{Command, Plugin, Tables};