1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
//! # hyphae - High-Performance Reactive Programming Library
//!
//! A high-performance, type-safe concurrent reactive programming library with
//! heterogeneous cell combinations and comprehensive dependency tracking.
//!
//! ## Features
//!
//! - **Fast Reads**: Uses `arc-swap` for atomic value snapshots
//! - **Type-Safe**: Full compile-time type checking with heterogeneous cell support
//! - **Automatic Propagation**: Changes flow through dependency chains automatically
//! - **Dependency Tracking**: Inspect and visualize cell relationships
//! - **Thread-Safe**: Safe concurrent access across threads
//!
//! ## Quick Start
//!
//! ```rust
//! use hyphae::{Cell, MapExt, Materialize, Mutable, Watchable, JoinExt, Pipeline, Signal, flat};
//!
//! // Create reactive cells
//! let x = Cell::new(5).with_name("x");
//! let y = Cell::new(10).with_name("y");
//!
//! // Pure operators (map/filter/...) return pipelines — no allocation
//! // until you materialize.
//! let doubled = x.clone().map(|val| val * 2).materialize().with_name("doubled");
//!
//! // Combine multiple cells with join + flat!. join stays lazy, then creates
//! // its required fan-in coalescing boundary when the chain is materialized.
//! let sum = x.clone().join(y).map(flat!(|a, b| a + b)).materialize().with_name("sum");
//!
//! // Subscribe on the materialized cell
//! let _guard = sum.subscribe(|signal| {
//! if let Signal::Value(value) = signal {
//! println!("Sum changed to: {}", value);
//! }
//! });
//!
//! x.set(20); // Triggers updates
//! ```
//!
//! ## Pipelines vs Cells
//!
//! Pure operators (`map`, `filter`, `try_map`, `tap`, `map_ok`, `map_err`,
//! `catch_error`, `unwrap_or`) return a [`Pipeline`] — an uncompiled chain
//! that has not yet been materialized into a [`Cell`]. Chaining pipelines
//! fuses closures at compile time; the fused closure runs only when a
//! consumer calls [`Materialize::materialize`].
//!
//! [`Cell`] is the materialized, cached, multicast form. Subscribing requires
//! a cell — there is no `Pipeline::subscribe` by design, forcing callers to
//! make the memoization decision explicit.
//! [`Definite`] pipelines materialize to `Cell<T>`; [`Empty`] pipelines such
//! as `filter` materialize to `Cell<Option<T>>` because they may not have an
//! honest initial value.
//!
//! Operators that need state or multiple sources (`debounce`, `buffer_*`,
//! `join`, `merge`, `switch_map`, and others) are lazy pipelines too. Their
//! state and any required fan-in boundary are created only when the pipeline
//! is installed. Materialize at the point where a cached value, [`Gettable`],
//! or [`Watchable`] boundary is required.
//!
//! Derived collection views (`CellMap::get`, `entries`, `items`, `keys`,
//! `size`, `len`, `diffs`, and their `CellSet` counterparts) also expose
//! definite pipelines. Some reuse an internal cell today, making terminal
//! materialization a no-op, but callers cannot rely on that implementation
//! detail as an implicit observation boundary.
//!
//! See the [Hyphae 3.0 migration guide](https://github.com/ignition-is-go/hyphae/blob/main/docs/migrating-to-v3.md)
//! for owned-input and sharing examples.
//!
//! ## Combining Cells
//!
//! Use `join()` to combine cells, and the `flat!` macro to avoid nested tuple destructuring.
//! `join` consumes its inputs into a lazy pipeline. It creates its required
//! fan-in coalescing boundary only when the chain is materialized:
//!
//! ```rust
//! use hyphae::{Cell, Gettable, JoinExt, MapExt, Materialize, flat};
//!
//! let a = Cell::new(1);
//! let b = Cell::new(2);
//! let c = Cell::new(3);
//! let d = Cell::new(4);
//!
//! // Without flat!: |(((a, b), c), d)| - deeply nested
//! // With flat!: |a, b, c, d| - clean and simple
//! let sum = a
//! .join(b)
//! .materialize()
//! .join(c)
//! .materialize()
//! .join(d)
//! .map(flat!(|a, b, c, d| a + b + c + d))
//! .materialize();
//! assert_eq!(sum.get(), 10);
//! ```
//!
//! ## Map Queries vs `CellMap`s
//!
//! Pure [`CellMap`] operators return consuming, non-`Clone` [`MapQuery`] plans.
//! [`MapQuery`] exposes associated [`MapQuery::Key`] and [`MapQuery::Value`]
//! types. Semantic operators state their cardinality and key behavior:
//! `select`/`select_by`, `map_values`/`filter_map_values`,
//! `map_entries`/`filter_map_entries`, and `flat_map_entries`.
//!
//! Plans compile to a statically typed, monomorphized runtime. Recognized
//! key-preserving and join regions fuse; rekeys and unsupported shapes remain
//! physical boundaries. No intermediate *observable* `CellMap` is created.
//! [`MapQuery::materialize`] is the sole observation boundary: it consumes the
//! plan, installs one subscription per interned physical root, and returns the
//! cached output map. Materialize once and clone that map to share work.
//!
//! Named zero-sized [`ForeignKeyRelation`] markers give typed FK joins their
//! semantic relationship, partition, and index identity. Repeated uses of one
//! raw physical right source and relation share an index within a materialized
//! plan; transformed rights intentionally do not alias it.
//!
//! Query closures must be deterministic, externally side-effect-free, and
//! nonblocking. They may run repeatedly or concurrently, and their invocation
//! count, order, and thread are not API guarantees. Output publication remains
//! deterministic, ordered, and synchronously settled. See [`map_query`] for
//! exact execution, collision, teardown, completion/error, and panic contracts.
//!
//! Native builds with the `scheduler` feature may adaptively dispatch eligible
//! join-region work to Hyphae's shared dedicated worker pool. Wasm and builds
//! without that feature execute map queries sequentially.
//!
//! ## `CellMap` Quick Start
//!
//! ```rust
//! use hyphae::{CellMap, MapQuery, traits::{InnerJoinExt, MapValuesExt}};
//!
//! let users = CellMap::<String, &'static str>::new();
//! let scores = CellMap::<String, i32>::new();
//! users.insert("u1".into(), "alice");
//! scores.insert("u1".into(), 42);
//!
//! // Chained operators return plan nodes — no intermediate CellMap
//! // until materialize().
//! let view = users
//! .clone()
//! .inner_join(scores.clone())
//! .map_values(|_, (name, score)| format!("{name}:{score}"))
//! .materialize();
//!
//! assert!(view.contains_key(&"u1".to_string()));
//! ```
pub
pub
// Both are available on wasm: the registry is fully portable; the `server`
// module keeps a uniform public API but its TCP transport (tokio/mio) is
// native-only, so on wasm `start_server` returns an inert handle.
pub use ;
pub use ;
pub use BoundedOutput;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;
pub use NestedMap;
pub use ;
pub use batch;
pub use Signal;
pub use ;
pub use SubscriptionGuard;
pub use ;