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
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
// SPDX-FileCopyrightText: Copyright (c) 2026 Mike Li/Mikewolfli/Wei Li(mikewolfli@163.com)
// SPDX-License-Identifier: MIT
//! Single source of truth for compile-time runtime-profile facts.
//!
//! # Why this module exists
//!
//! Before it, the questions "does this build have an OS runtime?", "does it
//! stream input from an OS backend?", "is the complete widget set compiled in?"
//! were each re-answered with a hand-written conjunction of `feature` tests, at
//! every call site. `src/lib.rs` alone carried six copies of
//! `runtime_profile_name()`, two of `runtime_route_name()`, three of
//! `init_runtime_backend()`, and four of `init_i18n_runtime()` — all differing
//! only in their `cfg` attribute. `src/` held roughly 1500 further
//! `feature = "mini" | "embedded"` tests.
//!
//! Copies of a conjunction drift. `full_widgets` and `stripped_widgets` already
//! exist in `build.rs` for exactly that reason, and the earlier `full_widgets`
//! bug (370 compile errors under `embedded`, caused by `not(mini)` being read as
//! "full") is the proof: two spellings of "the complete set", silently
//! disagreeing.
//!
//! # The contract
//!
//! This is the **only** module in `src/` allowed to test a profile feature name.
//! Everything else asks a semantic question here:
//!
//! ```ignore
//! if crate::platform::profile::has_os_runtime() { /* … */ }
//! ```
//!
//! `mini` and `embedded` remain the *input* — they are Cargo features and cannot
//! be redefined. What changes is that the **translation from features to facts**
//! happens once, here, and the rest of the crate is free of the feature names
//! (BLUE15 rules #57/#58).
use crateBox;
use crateRuntimeProfile;
use crateRenderEngine;
/// What kind of device this build targets.
///
/// This is the `mini`/`embedded` distinction reduced to the only two facts that
/// actually differ, so the 1500 scattered feature tests cannot come back.
///
/// Named `ProfileClass` rather than `DeviceClass` because
/// [`crate::core::DeviceClass`] already names *form factors* (Desktop/Tablet/
/// Mobile/Projector) — a different question, and two same-named types would be a
/// trap (principle #49).
/// `true` when this build targets OpenHarmony / HarmonyOS.
///
/// # Why this predicate exists (and why it tests `target_env`, not `target_os`)
///
/// Every OpenHarmony Rust target is spelled `*-unknown-linux-ohos`
/// (`aarch64`, `armv7`, `x86_64`, `loongarch64`). Despite the name, rustc reports
/// `target_os = "linux"` for them — verified with
/// `rustc --target aarch64-unknown-linux-ohos --print cfg`:
///
/// ```text
/// target_abi=""
/// target_env="ohos" <- the only discriminator
/// target_family="unix"
/// target_os="linux"
/// ```
///
/// So `cfg(target_os = "ohos")` can never match, and a backend selected by it
/// silently falls through to whatever the `linux` arm provides. The honest test is
/// `target_env`, which is exactly the field OpenHarmony's target spec overrides.
///
/// `cfg(unix)` is deliberately **not** used here: it is true for both OpenHarmony
/// and ordinary Linux, so it cannot tell them apart.
///
/// Note that this is a *compile-time target fact*, so it is legitimately a `cfg` in
/// the sense of BLUE15 principle #42: it describes the execution environment the
/// artifact is built for, not "which OS the developer happens to use".
///
/// The `harmony` Cargo feature remains the way to select the backend on a
/// *non*-OpenHarmony host for development and testing.
pub const
/// Compile-time proof that the discriminator above is the only one that works.
///
/// Phrased as an implication so it is evaluated — and vacuously true — on every
/// target. The earlier form (`if cfg!(target_env = "ohos") { const { .. } }`)
/// looked equivalent but was not: an inline `const` block is const-evaluated even
/// in a branch that is never taken, so the assertion also fired on Windows,
/// macOS and wasm (where `target_os` is not `linux`) and broke `cargo test --lib`
/// there. As an implication the check is real on OpenHarmony and inert elsewhere.
const _: = assert!;
/// How this build is driven at runtime.
///
/// The pair distinguishes "the OS owns the loop" from "the library owns the
/// loop", while `ProfileClass` names which memory/host budget applies. Encoding
/// both keeps the two independent: a `Surface` device is still OS-hosted when a
/// caller supplies the loop, and `mini` is never OS-hosted.
/// The device class this build targets.
///
/// Note that a build with **no** device feature at all reports
/// [`ProfileClass::Surface`] rather than `Device`: such a build has no OS runtime
/// to host a window, and the earlier code recorded that as `"unknown"`.
pub const
/// How this build is driven at runtime.
pub const
/// `true` when this build has an OS runtime that can host a window.
///
/// Equivalent to `stripped_widgets` being off *and* a device profile being on.
/// Callers use this to decide whether to talk to a real backend
/// (`platform::get_platform`) or to the surface-only fallback.
pub const
/// `true` when this build streams input from an OS backend.
///
/// Today this is the same predicate as [`has_os_runtime`], but the two are kept
/// separate because they are separate questions: a build could grow a window
/// without an input pump (a kiosk renderer), and the input modules should not
/// have to change when it does.
pub const
/// `true` when the complete widget set is compiled in.
///
/// Reads the `build.rs` alias, so this stays correct for builds that select no
/// device profile at all (`--no-default-features --features gpu`), where
/// `not(any(mini, embedded))` would wrongly answer `true`.
pub const
/// `true` when a reduced widget set is compiled in (`mini` or `embedded`).
pub const
/// `true` when the widget set was *not* deliberately reduced.
///
/// This is the precise meaning of the `not(any(feature = "mini",
/// feature = "embedded"))` conjunction that was hand-written at 350+ call sites.
/// It is deliberately **not** the same as [`full_widget_set`]: a build that
/// selects no device profile (`--no-default-features --features gpu`) has an
/// unreduced widget set but no device transport, so `widgets_unstripped()` is
/// true while `full_widget_set()` is false. Collapsing the two would silently
/// change what such a build compiles (rule #47).
pub const
/// `true` when this build is the alloc-frugal `mini` profile.
///
/// The `mini` profile has no platform singleton and a much smaller memory budget.
/// This accessor exists so an upper layer that *legitimately* differs there asks a
/// semantic question instead of testing the feature name.
pub const
/// `true` when this build targets the `embedded` surface profile.
///
/// Distinct from [`stripped_widget_set`], which is also true under `mini`. A
/// caller that needs "embedded specifically" — for example when naming the
/// fallback platform — must not get `mini` folded in.
pub const
/// Human-readable profile name, reported by `RUST_WIDGETS_TRACE_RUNTIME`.
///
/// Kept as a single `match` on the typed facts rather than a fresh `cfg` tower,
/// so adding a profile means adding one arm instead of one more divergent
/// `cfg`-gated function.
pub const
/// Human-readable name of the mechanism that lands widgets.
///
/// Replaces the two `runtime_route_name()` overloads in `src/lib.rs`, which split
/// on the OS backend feature. The answer is now single-valued and deliberately so:
/// BLUE15 #55 requires the control-landing mechanism to be unique *and runtime
/// auditable*, so this reports the mechanism (`self-drawn`) rather than the runtime
/// question — a build with an OS backend still paints its own controls.
///
/// The runtime question is answered separately by [`has_os_runtime`] and reported
/// next to this in the `RUST_WIDGETS_TRACE_RUNTIME` line as `host=…`, so nothing is
/// lost by no longer overloading the word "route" with it.
///
/// The value also keeps mechanism vocabulary out of user-visible output: the
/// previous spelling was `native-platform`, which named the implementation instead
/// of what it does (principle #52).
pub const
/// Which loop drives this build, for the `RUST_WIDGETS_TRACE_RUNTIME` audit line.
///
/// `os-hosted` — the OS owns the window and pumps its own event loop (desktop,
/// tablet, mobile). `surface-only` — the library drives its own loop over a bare
/// drawing surface (`embedded`, `mini`, and any host without an OS backend).
///
/// Kept beside [`route_name`] because the two facts used to be one string; they are
/// independent, and a reader of the trace line needs both.
pub const
/// What this build's self-hosted runtime must provide.
///
/// # Why a table
///
/// `embedded` and `mini` differ in exactly two facts — whether an OS window
/// exists, and whether the alloc-frugal caps apply — but before this table those
/// two facts were re-derived at every call site that needed a budget: buffer size,
/// texture cap, font cache, event queue. Each derivation was a fresh chance to
/// disagree, and the answers below were previously derived in
/// `src/embedded/flags.rs` by reading two unrelated atomic flags. That forwarding
/// layer has since been deleted (BLUE16 Phase C-2): this table was the truth
/// source it forwarded to, and had real consumers while the layer had none.
///
/// Encoding the whole policy once means a new profile is a new row here, and a
/// caller that needs a budget asks this table instead of testing a feature name
/// (rules #57/#58).
///
/// # Fields
///
/// * `os_window` — does an OS own a window this build paints into?
/// * `recommended_window` — default window size, in logical pixels.
/// * `max_widgets` — upper bound on simultaneously mounted controls.
/// * `max_texture` — largest square texture the surface may allocate, in pixels.
/// * `font_cache_bytes` — glyph atlas budget.
/// * `event_queue` — depth of the platform event queue.
/// The resource policy for this build's profile.
///
/// The three arms correspond to the three `ProfileClass` values, so a new profile
/// cannot be added without deciding its budget — this `match` is exhaustive by
/// construction rather than by a comment asking the next person to remember.
///
/// A device profile keeps desktop-sized budgets: it has both an OS window and a
/// full allocator. `Surface` (a bare render surface, no OS runtime) sits in the
/// middle, and `Minimal` (`mini`) is deliberately frugal.
pub const
/// Runtime profile category, for code that needs the `core` enum rather than
/// this module's typed facts.
pub const
/// The minimum touch-target size this build's device class recommends.
///
/// # Why this belongs here rather than in the theme
///
/// It is a fact about the **build's device class**, which is a platform decision, and the theme is
/// the consumer of that fact (principle #37: a middle layer that needs a platform fact asks for it
/// through a runtime accessor instead of sniffing the environment itself). `TouchTargetSize`
/// already carries the right numbers per class; this is the single place that decides which class
/// the running build is.
///
/// # Why `embed` is mapped the way it is
///
/// `desktop`, `tablet` and `mobile` are the three device profiles, and each has its own entry.
/// Anything else is either a bare surface (no pointer precision advantage over a finger, so the
/// embedded figure applies) or `mini`, which has no interactive controls at all — the embedded
/// figure is returned for it so the value is always defined, and no `mini` control consults it.
pub const
/// The device's text-size preference, as a multiplier on the nominal font size.
///
/// # Why this is a platform fact
///
/// Every OS has one: Android's `fontScale` from `Configuration`, iOS's
/// `UIContentSizeCategory`, Windows' text-scaling percentage, and the browser's own zoom on the
/// web. The library cannot observe any of them directly from a middle layer without committing a
/// layering violation, so the semantic — "how much should text grow?" — is answered here and the
/// OS knowledge stays in the backends.
///
/// # Why it returns 1.0 rather than a guessed value
///
/// A backend that has not been taught to report a preference inherits this, which means "no
/// scaling" — an honest answer, and the one that matches what the library actually does. Inventing
/// a plausible-looking factor would make `LayoutContext::font_scale` describe a device that is not
/// there, which is the fabricated-capability shape rule #37 forbids.
///
/// The value is bounded to a range a layout can survive. An unbounded preference (some platforms
/// report very large sizes for accessibility) multiplied into a fixed row height produces text that
/// cannot fit its own control; the clamp keeps a control legible rather than letting it become
/// unusable, and `AppBar`'s own clamp is what eventually removes that ceiling.
/// The render engine this profile drives its loop with.
///
/// This is the single selection point for the `embedded`-versus-native runtime
/// decision that `src/lib.rs` used to make with three separate `cfg`-gated
/// function pairs.
/// Brings up the runtime this profile uses.
///
/// The `mini` profile has no platform singleton at all (`get_platform` does not
/// exist there), so the OS-hosted branch cannot be written as a runtime `if`:
/// the `cfg` must eliminate the call. Keeping that `cfg` **here** — and nowhere
/// else in the crate — is the whole point of this module (rules #57/#58).
/// Runs the runtime's event loop.
/// Requests runtime shutdown.
/// Initializes whatever optional subsystems this profile supports.
///
/// Replaces the four `init_i18n_runtime()` overloads: rather than a separate
/// `cfg`-gated function per profile, one function asks the compiled-in feature
/// flags. A profile without the `i18n` feature simply logs why it skipped.