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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
use TokenStream;
use ;
/// A feature's manifest: its name, and the reducers it exports.
///
/// ```ignore
/// feature! {
/// pub Tabs {
/// exports { contracts::Tabs }
/// }
/// }
/// ```
///
/// It makes the feature's type - one `Bound` per export, in the order listed -
/// and what it exports. What installs it is an [`installs`] function.
/// The function that installs a feature: whatever it returns is the feature,
/// its second argument is what it is installed with.
///
/// ```ignore
/// #[installs]
/// fn tabs(cx: &FeatureInitContext, context: &str) -> anyhow::Result<Tabs> {
/// let (tabs, _) = cx.state::<contracts::Tabs>().driven_by(|push| TabsActor::new(push));
/// Ok(Tabs(tabs))
/// }
/// ```
///
/// Named for what the function does rather than for the trait: `#[feature]`
/// is ambiguous with Rust's own `feature` attribute.
/// A test run once per seed, each time on a fresh `Harness`, with the order of
/// everything it sets off decided by the seed.
///
/// A failing seed is named in the panic; `SEED=<n> cargo test` runs that order
/// alone, and again.
///
/// `exclusive = "key"` runs it one at a time with every other test in the
/// process that names the same key - for what a process has one of, a global
/// store say, which tests on their own threads would otherwise fight over.
///
/// ```ignore
/// #[guinea::test(iterations = 200)]
/// fn the_latest_query_wins(h: &mut Harness) {
/// h.install::<Search>(&()).unwrap();
/// h.dispatch::<Results>().emit(Query("gu".into()));
/// h.dispatch::<Results>().emit(Query("guinea".into()));
/// h.settled();
/// assert_eq!(h.state::<Results>().query, "guinea");
/// }
/// ```
/// Writes `type Installs = ();` and the `install` that goes with it, for a
/// page or layout that installs nothing.
///
/// Only that. Declaring what a segment installs is what makes the declaration
/// an obligation of the body; declaring that it installs *nothing* is
/// ceremony, and stable Rust has no conditional default body to remove it.
///
/// ```ignore
/// #[segment]
/// impl Page for Splash {
/// type Params = ();
/// fn view(cx: &mut PageCx<'_>) { .. }
/// }
/// ```
/// Writes down what an `impl Page` for the iced backend left out.
///
/// ```ignore
/// #[page]
/// impl Page for Services {
/// type Params = ServicesParams;
///
/// fn install(ctx: &FeatureInitContext, _: &Self::Params) -> anyhow::Result<()> { .. }
/// fn view(&self, cx: &PageCx<'_>) -> View<Self::Message> { .. }
/// }
/// ```
///
/// An omitted `Params` becomes `()` and an omitted `Message` becomes
/// `Infallible`; a node with the defaulted message also gets the empty
/// `update` that goes with it. Nothing else - a macro that derived a
/// declaration from a body would be a second source of truth wearing the
/// clothes of one.
/// [`iced_page`] for a layout, which has no route parameters of its own.
/// [`iced_page`] for the windows-reactor backend.
///
/// The same macro because the two backends are the same kind of thing: the
/// reactor's second preview is Elm - state in structs, events as enums - so a
/// page there has the same five items a page here does, and leaving out the
/// empty ones is the same job.
/// [`winui_page`] for a layout.
/// Declares an actor's manifest:
///
/// ```ignore
/// actor! {
/// ProcessActor<P: ProcessesPort + 'static> {
/// handlers { Kill, Refresh }
/// publishes { ProcessKilled }
/// subscribes { SettingsChanged }
/// }
/// }
/// ```
/// `routes! { Route { layout(TabsLayout) { page(Processes, "/:context/processes")
/// { context: String } ... } } }` - the tree's `{}` nesting *is* the segment
/// chain (no attribute stack to track); `page(...)`'s type also names the
/// generated variant, so there's one name per leaf, not two kept in sync by
/// hand. Generates the enum itself plus `path`/`parse` (string <-> enum),
/// `RouteChain` (enum -> segment chain), and `ToUri` (enum -> `AppUri`, just
/// the generated `.path()` string parsed - no per-app glue needed).
/// Puts a type on the global bus: `impl Event for T {}`.
/// Makes an enum of unit variants the application's marks: each variant is a
/// name, written as the variant is.
/// Lets a tool send this type to the running application as JSON: as an
/// action to whichever scope answers it, as an event on the global bus, or
/// both. The type derives `serde::Deserialize` too.
///
/// ```ignore
/// #[derive(Clone, Debug, Deserialize, guinea::Remote)]
/// #[remote(action)]
/// pub struct Kill(pub u32);
/// ```
/// Makes a function an actor's handler for one message: `impl Handler<M>`
/// written from its signature.
///
/// A handler takes what it uses and nothing else. The actor, then the message
/// itself - destructured right in the argument when that reads better:
///
/// <!-- shown: a handler that takes the message -->
/// ```rust,ignore
/// pub struct Add(pub u32);
///
/// #[derive(Debug)]
/// pub struct Counting {
/// push: Push<Count>,
/// }
///
/// actor! {
/// Counting {
/// handlers { Add }
/// }
/// }
///
/// #[handler]
/// fn add(this: &mut Counting, Add(by): Add) {
/// this.push.send(by);
/// }
/// ```
/// <!-- /shown -->
///
/// A handler that sends on, publishes, or starts background work takes a
/// third argument, its `Cx`. Written bare: the actor and the message are the
/// two arguments before it, and the macro writes them in. `Cx` is typed by the
/// message it handles, which is what `actor!`'s flow checks - a handler of
/// `Refresh` declared `Refresh => { bg Counted }` may spawn work that answers
/// `Counted`, and nothing else compiles:
///
/// <!-- shown: a handler that starts work -->
/// ```rust,ignore
/// pub struct Refresh;
/// pub struct Counted(pub u32);
///
/// #[derive(Debug)]
/// pub struct Counting {
/// push: Push<Count>,
/// }
///
/// actor! {
/// Counting {
/// handlers { Refresh => { bg Counted }, Counted }
/// }
/// }
///
/// // `cx` is `Cx<Counting, Refresh>`: the macro writes in what the two
/// // arguments before it already say.
/// #[handler]
/// fn refresh(_this: &mut Counting, _: Refresh, cx: Cx) {
/// cx.spawn_bg::<Counted, _>(async {
/// guinea::core::executor::random_delay().await;
/// Counted(7)
/// });
/// }
///
/// #[handler]
/// fn counted(this: &mut Counting, Counted(n): Counted) {
/// this.push.send(n);
/// }
/// ```
/// <!-- /shown -->
///
/// An `async fn` runs off the UI thread. It takes the actor's
/// `AsyncContext` instead of the actor - the actor itself stays on the UI
/// thread - and ends with the actor: dropped at its next await once the actor
/// is gone, unless it listens for that itself.
///
/// <!-- shown: an async handler -->
/// ```rust,ignore
/// pub struct Load(pub u32);
/// pub struct Loaded(pub u32);
///
/// #[derive(Debug)]
/// pub struct Loader {
/// push: Push<Count>,
/// }
///
/// actor! {
/// Loader {
/// handlers { Load, Loaded }
/// }
/// }
///
/// // Runs off the UI thread, and ends with the actor: `cx` knows when it is
/// // gone, and sends back to it while it is not.
/// #[handler]
/// async fn load(cx: AsyncContext<Loader>, Load(n): Load) {
/// guinea::core::executor::random_delay().await;
/// cx.send(Loaded(n * 2));
/// }
///
/// #[handler]
/// fn loaded(this: &mut Loader, Loaded(n): Loaded) {
/// this.push.send(n);
/// }
/// ```
/// <!-- /shown -->
///
/// A return type makes the handler an answer to `AsyncBus::request`: the
/// value it returns is the reply, sent exactly once, by the generated code and
/// nothing else. That holds for both the plain and the `async` form.