1mod inspect;
11
12use core::fmt;
13use core::ops::{Deref, DerefMut};
14use fuchsia_inspect::{
15 BoolProperty, BytesProperty, DoubleProperty, IntProperty, Node, Property, StringProperty,
16 UintProperty,
17};
18pub use inspect::{AttachError, Inspect, WithInspect};
19use std::marker::PhantomData;
20
21#[doc(hidden)]
25pub use fuchsia_inspect::Node as InspectNode;
26
27pub use fuchsia_inspect_derive_macro::{Inspect, Unit};
40
41pub trait Unit {
44 type Data: Default;
49
50 fn inspect_create(&self, parent: &Node, name: impl AsRef<str>) -> Self::Data;
53
54 fn inspect_update(&self, data: &mut Self::Data);
56}
57
58impl Unit for String {
59 type Data = StringProperty;
60
61 fn inspect_create(&self, parent: &Node, name: impl AsRef<str>) -> Self::Data {
62 parent.create_string(name.as_ref(), self)
63 }
64
65 fn inspect_update(&self, data: &mut Self::Data) {
66 data.set(self);
67 }
68}
69
70impl Unit for Vec<u8> {
71 type Data = BytesProperty;
72
73 fn inspect_create(&self, parent: &Node, name: impl AsRef<str>) -> Self::Data {
74 parent.create_bytes(name.as_ref(), self)
75 }
76
77 fn inspect_update(&self, data: &mut Self::Data) {
78 data.set(self);
79 }
80}
81
82macro_rules! impl_unit_primitive {
89 ({ $($impl_t:ty), *}, $inspect_t:ty, $prop_name:ident, $prop_name_cap:ident) => {
90 $(
91 paste::paste! {
92 impl Unit for $impl_t {
93 type Data = [<$prop_name_cap Property>];
94
95 fn inspect_create(&self, parent: &Node, name: impl AsRef<str>) -> Self::Data {
96 parent.[<create_ $prop_name>](name.as_ref(), *self as $inspect_t)
97 }
98
99 fn inspect_update(&self, data: &mut Self::Data) {
100 data.set(*self as $inspect_t);
101 }
102 }
103 }
104 )*
105 };
106}
107
108impl_unit_primitive!({ u8, u16, u32, u64, usize }, u64, uint, Uint);
110impl_unit_primitive!({ i8, i16, i32, i64, isize }, i64, int, Int);
111impl_unit_primitive!({ f32, f64 }, f64, double, Double);
112impl_unit_primitive!({ bool }, bool, bool, Bool);
113
114pub struct OptionData<T: Unit> {
117 name: String,
120
121 inspect_parent: Node,
124
125 inspect_data: Option<T::Data>,
127}
128
129impl<T: Unit> Default for OptionData<T> {
130 fn default() -> Self {
131 Self { name: String::default(), inspect_parent: Node::default(), inspect_data: None }
132 }
133}
134
135impl<T: Unit> Unit for Option<T> {
136 type Data = OptionData<T>;
137
138 fn inspect_create(&self, parent: &Node, name: impl AsRef<str>) -> Self::Data {
139 Self::Data {
140 name: String::from(name.as_ref()),
141 inspect_parent: parent.clone_weak(),
142 inspect_data: self.as_ref().map(|inner| inner.inspect_create(parent, name.as_ref())),
143 }
144 }
145
146 fn inspect_update(&self, data: &mut Self::Data) {
147 match (self.as_ref(), &mut data.inspect_data) {
148 (None, ref mut inspect_data) => **inspect_data = None,
150
151 (Some(inner), None) => {
153 data.inspect_data = Some(inner.inspect_create(&data.inspect_parent, &data.name));
154 }
155
156 (Some(inner), Some(ref mut inner_inspect_data)) => {
158 inner.inspect_update(inner_inspect_data);
159 }
160 }
161 }
162}
163
164pub trait Render {
167 type Base;
169
170 type Data: Default;
172
173 fn create(base: &Self::Base, parent: &Node, name: impl AsRef<str>) -> Self::Data;
175
176 fn update(base: &Self::Base, data: &mut Self::Data);
178}
179
180pub struct IOwned<R: Render> {
186 _base: R::Base,
187 _inspect_data: R::Data,
188}
189
190impl<R: Render> IOwned<R> {
191 pub fn new(value: R::Base) -> Self {
193 let _inspect_data = R::Data::default();
194 Self { _base: value, _inspect_data }
195 }
196
197 pub fn attached(value: R::Base, parent: &Node, name: impl AsRef<str>) -> Self {
199 let _inspect_data = R::create(&value, parent, name.as_ref());
200 Self { _base: value, _inspect_data }
201 }
202
203 pub fn as_mut(&mut self) -> IOwnedMutGuard<'_, R> {
206 IOwnedMutGuard(self)
207 }
208
209 pub fn iset(&mut self, value: R::Base) {
211 self._base = value;
212 R::update(&self._base, &mut self._inspect_data);
213 }
214
215 pub fn into_inner(self) -> R::Base {
216 self._base
217 }
218}
219
220impl<R: Render> Inspect for &mut IOwned<R> {
221 fn iattach(self, parent: &Node, name: impl AsRef<str>) -> Result<(), AttachError> {
222 self._inspect_data = R::create(&self._base, parent, name.as_ref());
223 Ok(())
224 }
225}
226
227impl<R, B> fmt::Debug for IOwned<R>
228where
229 R: Render<Base = B>,
230 B: fmt::Debug,
231{
232 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
233 fmt::Debug::fmt(&self._base, f)
234 }
235}
236
237impl<R, B> fmt::Display for IOwned<R>
238where
239 R: Render<Base = B>,
240 B: fmt::Display,
241{
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243 fmt::Display::fmt(&self._base, f)
244 }
245}
246
247impl<R, B> Default for IOwned<R>
248where
249 R: Render<Base = B>,
250 B: Default,
251{
252 fn default() -> Self {
253 let _inspect_data = R::Data::default();
254 let _base = B::default();
255 Self { _base, _inspect_data }
256 }
257}
258
259impl<R: Render> Deref for IOwned<R> {
260 type Target = R::Base;
261 fn deref(&self) -> &Self::Target {
262 &self._base
263 }
264}
265
266pub struct IOwnedMutGuard<'a, R: Render>(&'a mut IOwned<R>);
270
271impl<R: Render> Deref for IOwnedMutGuard<'_, R> {
272 type Target = R::Base;
273 fn deref(&self) -> &R::Base {
274 &self.0._base
275 }
276}
277
278impl<R: Render> DerefMut for IOwnedMutGuard<'_, R> {
279 fn deref_mut(&mut self) -> &mut R::Base {
280 &mut self.0._base
281 }
282}
283
284impl<R: Render> Drop for IOwnedMutGuard<'_, R> {
285 fn drop(&mut self) {
286 R::update(&self.0._base, &mut self.0._inspect_data);
287 }
288}
289
290#[doc(hidden)]
291pub struct ValueMarker<B: Unit>(PhantomData<B>);
292
293impl<B: Unit> Render for ValueMarker<B> {
294 type Base = B;
295 type Data = B::Data;
296
297 fn create(base: &Self::Base, parent: &Node, name: impl AsRef<str>) -> Self::Data {
298 base.inspect_create(parent, name.as_ref())
299 }
300
301 fn update(base: &Self::Base, data: &mut Self::Data) {
302 base.inspect_update(data);
303 }
304}
305
306pub type IValue<B> = IOwned<ValueMarker<B>>;
309
310impl<B: Unit> From<B> for IValue<B> {
311 fn from(value: B) -> Self {
312 Self::new(value)
313 }
314}
315
316#[doc(hidden)]
317pub struct DebugMarker<B: fmt::Debug>(PhantomData<B>);
318
319impl<B: fmt::Debug> Render for DebugMarker<B> {
320 type Base = B;
321 type Data = StringProperty;
322
323 fn create(base: &Self::Base, parent: &Node, name: impl AsRef<str>) -> Self::Data {
324 parent.create_string(name.as_ref(), format!("{:?}", base))
325 }
326
327 fn update(base: &Self::Base, data: &mut Self::Data) {
328 data.set(&format!("{:?}", base));
329 }
330}
331
332pub type IDebug<B> = IOwned<DebugMarker<B>>;
335
336impl<B: fmt::Debug> From<B> for IDebug<B> {
337 fn from(value: B) -> Self {
338 Self::new(value)
339 }
340}