graphrefly_operators/lib.rs
1//! Built-in operator node types for `GraphReFly`.
2//!
3//! Operators in this crate are specialized node types implemented
4//! directly against the Core protocol — they are not "user fns wrapped
5//! in nodes." A `map` operator's plumbing (dirty propagation, equals
6//! dedup, batch handling) runs entirely in Rust; only the user-supplied
7//! `(T) -> U` callback crosses the FFI boundary on each fire.
8//!
9//! # Status (Slice C-3, 2026-05-06)
10//!
11//! Transform module: [`map`], [`filter`], [`scan`], [`reduce`],
12//! [`distinct_until_changed`], [`pairwise`] (Slice C-1, D009–D019).
13//! Combine module: [`combine_latest`], [`merge`], [`with_latest_from`]
14//! (Slice C-2, D020–D023). Flow module: [`take`], [`skip`],
15//! [`take_while`], [`last`], [`last_with_default`] + [`first`],
16//! [`find`], [`element_at`] sugar (Slice C-3, D024–D029). Per-operator
17//! state lives behind a generic
18//! [`OperatorScratch`](graphrefly_core::op_state::OperatorScratch)
19//! slot on `NodeRecord` (D026 — replaces the typed `operator_state`
20//! field used by Slices C-1 / C-2).
21//!
22//! # Module layout (planned)
23//!
24//! - [`transform`] — map, filter, scan, reduce, distinctUntilChanged,
25//! pairwise (✅ Slice C-1)
26//! - [`combine`] — combine, merge, withLatestFrom (✅ Slice C-2)
27//! - [`flow`] — take, skip, takeWhile, last + first/find/element_at
28//! sugar (✅ Slice C-3)
29//! - [`temporal`] — sample, debounce, throttle, delay, audit, interval,
30//! timeout, buffer_time, window_time
31//! (✅ Slice T)
32//! - `switching` — switchMap, mergeMap, concatMap
33//! - `gating` — valve, gate, budgetGate, policyGate
34//! - `resilience` — retry, circuitBreaker, timeout, fallback,
35//! rateLimiter, tokenBucket
36//!
37//! # Layering
38//!
39//! This crate depends on `graphrefly-core` only (per the user-direction
40//! constraint that operators do not depend on `graphrefly-graph`).
41//! Operator factories accept `&Core` directly. User callbacks travel
42//! through the [`OperatorBinding`] super-trait of `BindingBoundary`,
43//! which the binding crate (e.g., a `TestOperatorBinding` for tests, the
44//! napi-rs / pyo3 bindings in production) implements.
45
46#![forbid(unsafe_code)]
47#![warn(rust_2018_idioms, unreachable_pub)]
48#![warn(clippy::pedantic)]
49#![allow(
50 clippy::module_name_repetitions,
51 clippy::missing_errors_doc,
52 clippy::missing_panics_doc,
53 clippy::doc_markdown
54)]
55
56pub mod binding;
57pub mod buffer;
58pub mod combine;
59pub mod control;
60pub mod error;
61pub mod flow;
62pub mod higher_order;
63pub mod ops_impl;
64pub mod producer;
65pub mod source;
66pub mod stratify;
67pub mod temporal;
68pub mod transform;
69
70pub use binding::OperatorBinding;
71pub use buffer::{buffer, buffer_count, window, window_count};
72pub use combine::{combine as combine_latest, merge, with_latest_from, MergeRegistration};
73pub use control::{on_first_data, repeat, rescue, settle, tap, tap_observer, valve};
74pub use error::OperatorFactoryError;
75pub use flow::{
76 element_at, find, first, last, last_with_default, skip, take, take_while, FlowRegistration,
77};
78pub use higher_order::{
79 concat_map, exhaust_map, merge_map, merge_map_with_concurrency, switch_map, HigherOrderBinding,
80 ProjectFn,
81};
82pub use ops_impl::{concat, race, take_until, zip};
83pub use producer::{
84 default_producer_deactivate, MailboxEmitter, ProducerBinding, ProducerBuildFn, ProducerCtx,
85 ProducerEmitter, ProducerNodeState, ProducerStorage, SubscribeOutcome,
86};
87pub use source::{empty, from_iter, never, of, throw_error};
88pub use stratify::stratify_branch;
89pub use temporal::{
90 audit, buffer_time, debounce, delay, interval, sample, throttle, timeout, window_time,
91};
92pub use transform::{
93 distinct_until_changed, filter, map, pairwise, reduce, scan, OperatorRegistration,
94};