Skip to main content

cadencr_tab_backend/
lib.rs

1//! Write the native backend of a [Cadencr](https://github.com/merkr-software/CadencR)
2//! custom tab.
3//!
4//! A custom tab may ship a native executable that Cadencr starts per
5//! conversation and talks to over stdin/stdout, one JSON object per line.
6//! The protocol is the contract — see [`docs/TAB_BACKEND_PROTOCOL.md`][doc] —
7//! and this crate is one way to implement it:
8//!
9//! ```no_run
10//! use std::process::ExitCode;
11//!
12//! use cadencr_tab_backend::{serve, Context, Error};
13//! use serde_json::{json, Value};
14//!
15//! fn handle(cx: &Context) -> Result<Value, Error> {
16//!     match cx.method() {
17//!         "greet" => {
18//!             let name: String = cx.params()?;
19//!             Ok(json!(format!("hello, {name}")))
20//!         }
21//!         other => Err(Error::unknown_method(other)),
22//!     }
23//! }
24//!
25//! fn main() -> ExitCode {
26//!     serve(handle)
27//! }
28//! ```
29//!
30//! [`serve`] reads and checks the `hello`, answers `ready`, then runs each
31//! request on a small worker pool (a slow request does not hold up the
32//! others; responses may be written out of order), turns a handler panic into
33//! an [`codes::INTERNAL_ERROR`] response, logs and skips malformed lines, and
34//! returns once stdin closes. On Unix it also reserves stdin and stdout for
35//! the protocol: anything else printed to stdout goes to stderr, the log,
36//! and child processes see `/dev/null` as stdin.
37//!
38//! Features: `api` adds a blocking client for the Cadencr API
39//! ([`Context::api`]); `conformance` adds [`conformance::run`], which checks
40//! any backend binary against the protocol. [`testing`] drives a handler
41//! in-process.
42//!
43//! [doc]: https://github.com/merkr-software/CadencR/blob/main/docs/TAB_BACKEND_PROTOCOL.md
44
45#[cfg(feature = "api")]
46pub mod api;
47#[cfg(feature = "conformance")]
48pub mod conformance;
49mod context;
50mod error;
51mod framing;
52mod incoming;
53pub mod protocol;
54mod server;
55mod stdio_guard;
56pub mod testing;
57
58pub use context::{Context, Handler};
59pub use error::{codes, Error};
60pub use protocol::PROTOCOL_VERSION;
61pub use server::{serve, serve_with, Config, ServeError, SDK};