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
// SPDX-License-Identifier: MIT OR Apache-2.0
//! Resource diagnostics for widget-heavy UIs.
//!
//! Two complementary signals:
//!
//! 1. [`census`](crate::diag::census) walks a widget subtree and counts objects and nesting depth.
//! This is the portable, deterministic metric — it counts real `lv_obj`
//! instances regardless of how the C heap is configured, and every
//! object-reduction technique (virtualised lists, drawing instead of
//! instantiating, freeing off-screen trees) moves it directly.
//!
//! 2. [`ResourceProbe`](crate::diag::ResourceProbe) is a pluggable hook for *live* heap and task-stack
//! figures. There is no portable way to read these — on host they are not
//! meaningful, and on ESP32 the heap and task stacks are owned by the
//! application (esp-hal / FreeRTOS), not the library. Apps supply an impl;
//! the default [`NullProbe`](crate::diag::NullProbe) reports nothing.
//!
//! ## Why not `lv_mem_monitor`?
//!
//! With `LV_USE_STDLIB_MALLOC = LV_STDLIB_CLIB` (the configuration these
//! bindings ship with), LVGL has no internal pool to introspect — it delegates
//! straight to libc `malloc`, so `lv_mem_monitor` reports nothing useful. The
//! figure that actually matters on target is the *system* heap (esp-hal), which
//! a [`ResourceProbe`](crate::diag::ResourceProbe) exposes.
use crateObj;
/// Estimated bytes per `lv_obj`, measured on ESP32-S3 (`lv_obj_t` + `spec_attr`
/// + a small `styles[]`). The audit in
/// `docs/cr-navigator-modal-background-tree-residency.md` puts this at
/// ~120–200 B; we use the midpoint for estimates.
pub const BYTES_PER_OBJECT_EST: u32 = 160;
/// A census of a widget subtree: how many objects it holds and how deep it
/// nests. Both numbers drive heap *and* stack cost — object count dominates
/// heap, nesting depth bounds the recursion depth of layout, style refresh and
/// draw (and therefore the LVGL task's stack high-water mark).
/// A per-view resource ceiling. Pair with [`Census::exceeds`] (or
/// [`assert_budget`]) to fail loudly in debug builds when a view's widget tree
/// grows past its envelope, instead of silently OOMing a memory-constrained
/// target at runtime.
/// Walk `root` and all descendants, returning the subtree [`Census`].
///
/// `root` is typically a screen (`lv_screen_active`) or a container. The walk
/// recurses to `max_depth`; widget trees are normally wide rather than deep, so
/// this stays shallow — see the "flatten the tree" guidance.
/// In a debug build, panic if `root`'s census exceeds `budget`; no-op in
/// release. Use as a guard right after a view's `create()` so a regression in
/// widget count fails CI/HIL rather than a customer's device.
/// A pluggable source of live heap and task-stack figures.
///
/// All methods default to `None` ("unknown"); implement only what a platform
/// can answer. On ESP32 an app typically backs `free_heap_bytes` with
/// `esp_alloc` heap stats and `stack_high_water_bytes` with the FreeRTOS task
/// high-water mark.
/// A [`ResourceProbe`] that knows nothing — the host default. Live heap and
/// stack are not meaningful off-target, so every method returns `None`.
;