Skip to main content

brokapi_sansio/
lib.rs

1//! Sans-io core trait and test harness: protocol logic with no sockets, timers or async runtime.
2//!
3//! A broker connector is split in two. The protocol layer decides what a frame means and what to
4//! send next. The runtime owns the sockets and the clock. This crate is the seam between them:
5//!
6//! - [`BrokerCore`] is the trait a protocol core implements. Frames and the current time go in.
7//!   Events ([`EventSink`]), outbound messages ([`Outbound`]) and the next wake-up time come out.
8//! - [`Harness`] drives a core with recorded frames and virtual time, so a protocol can be tested
9//!   without a network and without waiting.
10//! - Helpers every core needs: [`JsonFrameBuffer`] (reassemble JSON split over frames),
11//!   [`SubscriptionSet`] (the wanted subscriptions), [`OrderFsm`] and [`OrderRegistry`] (the life
12//!   of an order, including the `Unknown` outcome).
13//!
14//! The crate does no I/O at all, and the examples in it run with no mock. The connectors that
15//! use it run against the broker mocks, see `brokapi-mocks`.
16//!
17//! The book is at <https://brokapi.ru/docs/>.
18//!
19//! # Examples
20//!
21//! Reassemble a JSON message that arrived in two pieces, then track an order through its life:
22//!
23//! ```
24//! use std::time::Instant;
25//! use brokapi_core::{BrokerOrderId, ClientOrderId, OrderState};
26//! use brokapi_sansio::{BufferPush, JsonFrameBuffer, OrderFsm, OrderSignal};
27//!
28//! let mut buf = JsonFrameBuffer::new();
29//! assert_eq!(buf.push(r#"{"type":"order","#), BufferPush::Incomplete);
30//! let BufferPush::Complete(frames) = buf.push(r#""id":"42"}"#) else { panic!("expected a frame") };
31//! assert_eq!(frames, vec![r#"{"type":"order","id":"42"}"#.to_string()]);
32//!
33//! let mut order = OrderFsm::new(ClientOrderId::new_v4(), Instant::now());
34//! order.apply(OrderSignal::Ack { broker_id: BrokerOrderId::new("42") }, Instant::now())?;
35//! assert!(matches!(order.state(), OrderState::Acked { .. }));
36//! # Ok::<(), brokapi_sansio::FsmError>(())
37//! ```
38
39#![warn(missing_docs)]
40
41mod core;
42mod event;
43mod harness;
44mod json_buffer;
45mod order_fsm;
46mod outbound;
47mod subscription;
48
49pub use core::BrokerCore;
50pub use event::{CoreEvent, EventSink};
51pub use harness::{FrameRecord, Harness};
52pub use json_buffer::{BufferPush, JsonFrameBuffer};
53pub use order_fsm::{FsmError, OrderFsm, OrderRegistry, OrderSignal};
54pub use outbound::Outbound;
55pub use subscription::{DesiredSubscription, SubscriptionKind, SubscriptionSet};