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
//! **Where the seat was pointed**, remembered between runs (yog's
//! `docs/REMOTE.md` §7; DESIGN §4.13).
//!
//! REMOTE §7 rules that per-seat UI state never crosses the boundary and is the
//! seat's own. This is the first of it that is durable, and where it goes is
//! the decision that mattered: under `paths::state_root` and never under
//! `paths::data_root`, because everything under the second is
//! operator-provisioned and irreplaceable by anything on this box, and a
//! regenerable subtree beside it would make a rebuild look like a revocation.
//! The whole of that argument is `crate::paths`'s module doc.
//!
//! # It may never become a way for the seat to fail to start
//!
//! [`read`] has exactly one answer for a file that is absent, unreadable,
//! truncated, or written by a build that spelled things differently: **no
//! place**, which is a window that opens on the roster — the same window a
//! first run gets. There is no refusal here and no repair path, because a
//! forgotten selection is a keypress and a startup error is an outage.
//!
//! That is also why the aim is not checked against anything. A wall that has
//! gone is a wall no channel resolves, and the standing set already declines to
//! ask about one (`crate::state::Standing::aimed`) — so a stale place is inert
//! by a rule that was already there, and validating it here would be a second
//! answer to a question already settled.
//!
//! # What it holds, and how it grows
//!
//! The wall the window was aimed at, the accordion beside it (DESIGN §4.39):
//! which engine is open, what each engine's last opening ranks as, and the
//! wall last aimed under each — and the edges the operator dragged, which are
//! the width of the one list pane and how many rows the composer's field
//! stands at (§4.39 again, bl-46e5, bl-b9a3). **A JSON object rather than lines**, so
//! the next fact REMOTE §7 names — a scroll, a draft — is a key beside these
//! rather than a format. An unknown key is ignored and a missing
//! key is absence, which is the reply vocabulary's own rungs 3 and 4 applied to
//! this box's own file: a build that reads a file a newer build wrote loses
//! what it does not know and keeps what it does.
//!
//! **Why the accordion is here and not across the boundary**: §4.39's ruling,
//! and it is not §4.25's pin exception. A channel is a client-side fact, named
//! by this box and held by no other, so the order this box shows its channels
//! in can be nobody else's and there is no engine to assert it into.
use BTreeMap;
use ;
use ;
use crate;
/// The file, under the state root. One name, so there is nothing to configure.
const FILE: &str = "place.json";
/// The aim, and the two words it is written as.
const AIM: &str = "aim";
const CHANNEL: &str = "channel";
const ADDRESS: &str = "address";
/// The accordion's three, beside the aim (DESIGN §4.39).
const OPEN: &str = "open";
const OPENED: &str = "opened";
const AIMED: &str = "aimed";
/// The dragged edges, one key each and flat: a width and a row count are
/// facts an operator set one at a time, not one object with a shape to keep.
///
/// **One width key since DESIGN §4.39's fold** (bl-b9a3). It was
/// `roster_width` and `convs_width`, and neither is read any more: a file
/// written by a build that had two is read by this one as a seat that has
/// dragged nothing, which is this module's own rung-4 rule — an unknown key
/// is ignored and a missing key is absence — costing exactly one drag.
const LIST_WIDTH: &str = "list_width";
const COMPOSER_ROWS: &str = "composer_rows";
/// **Everything the seat remembers between runs.** One value, because it is
/// one file: read whole at boot and written whole once the event loop has
/// returned, so nothing here costs a frame anything.
///
/// **`Eq` is not derived** and cannot be: a dragged width is points, and a
/// float has no total equality. Nothing here needs one.
/// Where the place is kept under `root`.
/// **Where the seat was pointed and how it was arranged**, or the empty place
/// — which is every way this can fail and the answer a first run gets.
/// One dragged width, in points, or absence.
/// The aim, where the file carries a whole one. A half-written aim is no aim:
/// an address with no channel names nothing this seat can resolve.
/// One name-keyed table, dropping every row this build cannot read — rung 3,
/// per row rather than per key, so one unreadable entry costs one entry.
/// **Write the place down.** Aimed at nothing is a place too — an operator who
/// left the roster comes back to it — so this is called with whatever the last
/// frame held rather than only when there is something to say.
///
/// It answers a refusal rather than swallowing one. A read that fails has a
/// correct answer and this does not: the only alternative to saying so is
/// losing the operator's place in silence, and by the time this runs there is
/// no window left to paint it in.