inspect/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! This module implements the inspect framework, which allows an object to
5//! expose its state for diagnostics purposes as a hierarchy. All such subtrees
6//! are linked together into a single tree for the process, and clients can
7//! query information from arbitrary portions of the tree by path.
8//!
9//! To participate in the tree, an object implements the [`Inspect`] trait and
10//! arranges for itself to be inspected, usually automatically via an existing
11//! parent-child relationship.
12//!
13//! For most cases, users should use the derive version of [`Inspect`](derive@Inspect)
14//! as this will automatically update the implementation as new fields are added.
15
16#![no_std]
17
18extern crate alloc;
19
20// Enable `std` for features that depend on it.
21//
22// Don't just have these features depend on the "std" feature, because they
23// might be able to remove their `std` dependency in the future. (Most of them
24// are blocked on `core::error::Error` not being stable yet.)
25#[cfg(any(feature = "std", feature = "initiate", feature = "defer",))]
26extern crate std;
27
28#[cfg(feature = "defer")]
29mod defer;
30#[cfg(feature = "initiate")]
31mod initiate;
32
33#[cfg(all(test, feature = "derive", feature = "initiate"))]
34extern crate self as inspect;
35
36#[cfg(feature = "defer")]
37pub use defer::*;
38#[cfg(feature = "initiate")]
39pub use initiate::*;
40
41/// Derives the [`Inspect`] trait for a struct or enum.
42///
43/// [`InspectMut`](derive@InspectMut) can also be derived using the same
44/// attributes.
45///
46/// # Structs
47///
48/// By default, the macro implements [`Inspect`] or [`InspectMut`] by calling
49/// [`Request::respond`] and then calling [`Response::field`] on each field by
50/// reference. You can use attributes to control this behavior.
51///
52/// Attributes are comma separated and nested inside the `inspect` attribute,
53/// e.g. `#[inspect(hex, rename = "foo")]`.
54///
55/// If you derive `Inspect` on a struct with the `bitfield` attribute, then it
56/// is assumed to be from the `bitfield-struct` crate. The derived
57/// implementation will have a field for each bitfield field, plus one called
58/// `raw` with the raw value in hexadecimal. Be sure to put the `derive`
59/// attribute above the `bitfield` attribute for this to work.
60///
61/// ## Struct attributes
62///
63/// ### `transparent(attrs)`
64///
65/// Forward the request to a single field of the struct.
66///
67/// `(attrs)` is optional. If provided, these are attributes to apply to the
68/// field. This is useful when the field is generated by another macro (such as
69/// `bitflags!`) and you cannot put attributes on it.
70///
71/// This attribute requires that there be exactly one non-skipped field. Fields
72/// of type [`PhantomData`](std::marker::PhantomData) are automatically skipped.
73///
74/// Note that it is not sufficient to mark any extraneous fields' _types_ with
75/// `skip`--you must mark the individual fields with the `skip` attribute.
76///
77/// ### `skip`
78///
79/// Skip this type when inspected so that they do not appear in inspect output.
80/// Calls [`Request::ignore`].
81///
82/// ### `with`
83///
84/// Wraps the type with `expr`, so that the inspect implementation is deferred
85/// to `expr(&field)`.
86///
87/// `expr` is often a type constructor such as [`AsDisplay`] or [`AsDebug`] (but
88/// note that there are shorthand attributes `display` and `debug` for these
89/// types).
90///
91/// ### `display`
92///
93/// Inspect the type by formatting it as a string, using the type's [`ToString`]
94/// implementation.
95///
96/// Usually implementing [`Inspect`] for the type should be preferred to this in
97/// order to preserve structured data. However, this may be useful if the
98/// display string is the canonical way to view a field's data.
99///
100/// This is equivalent to `with = "inspect::AsDisplay"`. See [`AsDisplay`].
101///
102/// ### `debug`
103///
104/// Inspect the type by formatting it as a string, using the type's [`Debug`]
105/// implementation.
106///
107/// Usually implementing [`Inspect`] for the type should be preferred to this in
108/// order to preserve structured data. However, this may be useful if the debug
109/// string is the canonical way to view a field's data, as with `bitfields!` or
110/// `open_enum!`.
111///
112/// This is equivalent to `with = "inspect::AsDebug"`. See [`AsDebug`].
113///
114/// ### `extra = "expr"`
115///
116/// In addition to inspecting each field as normal, call `expr(self, resp)`.
117/// This allows you to add synthetic fields to the struct without manually
118/// implementing inspect for all fields.
119///
120/// ```no_run
121/// # use inspect::Inspect;
122/// #[derive(Inspect)]
123/// #[inspect(extra = "Foo::inspect_extra")]
124/// struct Foo {
125///     x: u32,
126///     y: u32,
127/// }
128///
129/// impl Foo {
130///     fn inspect_extra(&self, resp: &mut inspect::Response<'_>) {
131///         resp.field("sum", self.x + self.y);
132///     }
133/// }
134/// ```
135///
136/// ## Field attributes
137///
138/// ### `rename = "custom_name"`
139///
140/// Set the name of the field to "custom_name". By default, fields have the same
141/// name as their Rust identifier.
142///
143/// ### `field`
144///
145/// Inspect the field using its [`Inspect`] implementation, by calling
146/// [`Response::field`] with `&field`.
147///
148/// This is the default.
149///
150/// ### `with = "expr"`
151///
152/// Wraps the field with `expr`, so that `expr(&field)` is the inspected value.
153/// This is useful when the field cannot implement `Inspect`, but you can wrap
154/// it in an object that can.
155///
156/// `expr` is often a type constructor such as [`AsDisplay`] or [`AsDebug`] (but
157/// note that there are shorthand attributes `display` and `debug` for these
158/// types).
159///
160/// This can also be used to implement helper functions that implement
161/// [`Inspect`] to allow complex types to use the the derive macro.
162///
163/// #### Examples
164/// The following structure has a field that is not normally inspectable, but we
165/// can use the derive macro with a helper pattern of making a new helper
166/// function, along with the `with` attribute.
167///
168///
169/// ```no_run
170/// # use inspect::Inspect;
171/// struct NotInspectable {
172///     complex_field: u64 // use your imaginatation to pretend this is a complex field
173/// }
174///
175/// #[derive(Inspect)]
176/// struct Foo {
177///     #[inspect(with = "inspect_awesome_data")]
178///     awesome_data: NotInspectable,
179///     data: String,
180/// }
181///
182/// pub fn inspect_awesome_data(id: &NotInspectable) -> impl Inspect {
183///     // Do some complex field transformation to a string here...
184///     format!("{}, {:x}", (id.complex_field * 42), id.complex_field)
185///     // Since String via str has an implementation for Inspect, we can return the value directly.
186/// }
187///
188/// // In general, inspect helper functions would be defined as the following in another sub module and used
189/// // as `[inspect(with = "inspect_helpers::awesome_data")]` but rustdoc limitations prevent this.
190/// // mod inspect_helpers {
191/// //     use super::*;
192/// //
193/// //     pub(super) fn awesome_data(id: &NotInspectable) -> impl Inspect { ... }
194/// // }
195/// ```
196///
197/// ### `display`
198///
199/// Inspect the field by formatting it as a string, using the field's
200/// [`ToString`] implementation.
201///
202/// This is equivalent to `with = "inspect::AsDisplay"`. See [`AsDisplay`].
203///
204/// ### `debug`
205///
206/// Inspect the field by formatting it as a string, using the field's
207/// [`std::fmt::Debug`] implementation.
208///
209/// In general, implementing [`Inspect`] for the field should be preferred to
210/// this in order to preserve structured data.
211///
212/// This is equivalent to `with = "inspect::AsDebug"`. See [`AsDebug`].
213///
214/// ### `format = "format"`
215///
216/// Inspect the field by formatting it as a string, using the provided format.
217///
218/// For example, `format = "id{:02x}"` might be useful on a field that
219/// represents a 2-digit hex identifier.
220///
221/// ### `hex`
222///
223/// Inspect the field as a hex-formatted numeric value. Calls [`Response::hex`]
224/// with `&field`.
225///
226/// ### `binary`
227///
228/// Inspect the field as a binary-formatted numeric value. Calls
229/// [`Response::hex`] with `&field`.
230///
231/// ### `bytes`
232///
233/// Inspect the field as a list of bytes. The field must be iterable with an
234/// item type of `u8` or `&u8`.
235///
236/// ### `flatten`
237///
238/// Merge the contents of the field into this inspection node, without an
239/// intermediate child node. Calls [`Response::merge`] with `&field`.
240///
241/// This is useful when your struct is split into an outer and inner type that
242/// are logically the same type from a diagnostics perspective. In this case,
243/// you probably would not want to expose the implementation detail of the inner
244/// type.
245///
246/// ### `iter_by_key`
247///
248/// Inspects a list of items, iterating them by calling
249/// [`into_iter()`](IntoIterator::into_iter) on the field. Each item must have
250/// type `(K, V)`, where `K: Display` and `V: Inspect`. `K` is used as the field
251/// name.
252///
253/// ### `iter_by_index`
254///
255/// Inspects a list of items, enumerating them by calling
256/// [`into_iter()`](IntoIterator::into_iter) on the field. Each item must have
257/// type `V: Inspect`. The field name is the index in the enumeration, starting
258/// with `0`.
259///
260/// #### Example
261///
262/// ```no_run
263/// # use inspect::Inspect;
264/// # use std::sync::Arc;
265/// #[derive(Inspect)]
266/// struct Foo {
267///     id: u32,
268///     #[inspect(flatten)]
269///     inner: Arc<Inner>,
270/// }
271///
272/// #[derive(Inspect)]
273/// struct Inner {
274///     state: String,
275/// }
276/// ```
277///
278/// ### `skip`
279///
280/// Skip inspecting this field.
281///
282/// ### `mut`
283///
284/// Pass the field as a mutable reference to the appropriate method so that its
285/// [`InspectMut`] implementation is called instead of its [`Inspect`]
286/// implementation.
287///
288/// This is only valid in uses of the [`InspectMut`](derive@InspectMut) derive
289/// macro.
290///
291/// This can be used in conjunction with other attributes:
292///
293/// * `field`: calls [`Response::field_mut`] with `&mut field`.
294/// * `flatten`: calls [`Response::merge`] with `&mut field`.
295/// * `transparent` (struct attribute): calls [`InspectMut::inspect_mut`] on the
296///   sole unskipped field.
297/// ## Example
298///
299/// ```no_run
300/// # use inspect::{Inspect, InspectMut};
301/// # use std::sync::Arc;
302/// # use std::path::PathBuf;
303/// #[derive(InspectMut)]
304/// struct Outer {
305///     #[inspect(hex)]
306///     id: u32,                // will be displayed as hex
307///     count: usize,
308///     #[inspect(mut)]
309///     max_buffers: usize,     // can be changed via `update()`
310///     #[inspect(skip)]
311///     signal: Box<dyn Send>,  // won't be present in inspect output
312///     #[inspect(flatten)]
313///     inner: Arc<Inner>,      // contents will be merged in
314/// }
315///
316/// #[derive(Inspect)]
317/// struct Inner {
318///     #[inspect(format = "{:016x}")]
319///     uuid: u128,             // will be displayed as a 0-padded hex string
320/// }
321/// ```
322///
323/// # Unit-only enums
324///
325/// The macro supports enums, with multiple different output formats:
326///
327/// By default, deriving `Inspect` or `InspectMut` on an enum only works if the
328/// enum variants are all unit variants. In this case, the inspect output is a
329/// string containing the name of the enum variant converted from the standard
330/// `PascalCase` to `snake_case`.
331///
332///  For example:
333///
334/// ```no_run
335/// # use inspect::Inspect;
336/// #[derive(Inspect)]
337/// enum State {
338///     NotRunning, // will be displayed as "not_running"
339///     Running,    // will be displayed as "running"
340/// }
341/// ```
342///
343/// For `InspectMut`, the enum variant name is parsed for update requests.
344///
345/// # Enums with fields
346///
347/// To derive `Inspect` for an enum whose variants might contain fields, you
348/// must select an output format.
349///
350/// ## Output formats
351///
352/// In each of the formats below, when the variant name is used in the output,
353/// it is converted from `PascalCase` to `snake_case`. You can specify an
354/// alternate name with the `rename` attribute, e.g. `#[inspect(rename =
355/// "paused")]`.
356///
357/// ### `tag = "tag_name"`
358///
359/// Includes the variant name as a field called `tag_name`, and flattens all the
360/// variant's fields into the object.
361///
362/// ```no_run
363/// # use inspect::Inspect;
364/// #[derive(Inspect)]
365/// #[inspect(tag = "state")]
366/// enum State {
367///     Stopped,
368///     Running { with_optimizations: bool },
369/// }
370/// ```
371///
372/// Example output for `State::Running { with_optimizations: true }`:
373///
374/// ```text
375/// {
376///     state: "running"
377///     with_optimizations: true
378/// }
379/// ```
380///
381/// ### `external_tag`
382///
383/// Writes a single field named for the variant, with the variant's fields as
384/// children.
385///
386/// ```no_run
387/// # use inspect::Inspect;
388/// #[derive(Inspect)]
389/// #[inspect(external_tag)]
390/// enum State {
391///     Stopped,
392///     Running { with_optimizations: bool },
393/// }
394/// ```
395///
396/// Example output for `State::Running { with_optimizations: true }`:
397///
398/// ```text
399/// {
400///     running: {
401///         with_optimizations: true
402///     }
403/// }
404/// ```
405///
406/// ### `untagged`
407///
408/// Flattens the variant's fields as in `tag`, but does not include the variant
409/// name anywhere.
410///
411/// ```no_run
412/// # use inspect::Inspect;
413/// #[derive(Inspect)]
414/// #[inspect(untagged)]
415/// enum DiskBacking {
416///     File { file_path: String },
417///     Memory { ramdisk_size: u64 },
418/// }
419/// ```
420///
421/// Example output for `State::File { file_path: "file.img" }`:
422///
423/// ```text
424/// {
425///     file_path: "file.img"
426/// }
427/// ```
428///
429/// ## Additional attributes
430///
431/// On enums, as with structs, you can put the [`skip`](#skip), [`with`](#with),
432/// [`display`](#display), [`debug`](#debug), or [`extra`](#extra--expr)
433/// attributes to specify alternate inspect behavior.
434///
435/// On each enum variant, you can use [`transparent`](#transparentattrs) as you
436/// would with a struct.
437///
438/// On enum variant fields, you can use any attribute that you would use with a
439/// struct field.
440#[cfg(feature = "derive")]
441pub use inspect_derive::Inspect;
442/// Derives the [`InspectMut`] trait for a struct or enum.
443///
444/// See the [`Inspect`](derive@Inspect) derive macro for more details.
445#[cfg(feature = "derive")]
446pub use inspect_derive::InspectMut;
447
448use alloc::borrow::Cow;
449use alloc::borrow::ToOwned;
450use alloc::boxed::Box;
451use alloc::format;
452use alloc::rc::Rc;
453use alloc::string::String;
454use alloc::string::ToString;
455use alloc::sync::Arc;
456use alloc::vec::Vec;
457use core::fmt;
458use core::fmt::Arguments;
459use core::fmt::Debug;
460use core::fmt::Display;
461use core::num::Wrapping;
462
463/// An inspection request.
464pub struct Request<'a> {
465    path: &'a str,
466    depth: usize,
467    node: &'a mut InternalNode,
468    value: Option<&'a str>,
469    sensitivity: SensitivityLevel,
470}
471
472#[cfg(any(feature = "defer", feature = "initiate"))]
473struct RequestRoot<'a> {
474    path: &'a str,
475    node: InternalNode,
476    depth: usize,
477    value: Option<&'a str>,
478    sensitivity: SensitivityLevel,
479}
480
481/// The sensitivity level for an inspection node or request.
482/// Requests will only return nodes at or below their sensitivity level.
483/// For example, a request set to `SensitivityLevel::Safe` will not return nodes
484/// with `SensitivityLevel::Sensitive` or `SensitivityLevel::Unknown`.
485#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Default)]
486#[cfg_attr(
487    any(feature = "defer", feature = "initiate"),
488    derive(mesh::MeshPayload)
489)]
490#[cfg_attr(
491    any(feature = "defer", feature = "initiate"),
492    mesh(package = "inspect")
493)]
494#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
495pub enum SensitivityLevel {
496    /// The node doesn't contain sensitive information and is always safe to expose.
497    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(1))]
498    Safe,
499    /// The node might contain sensitive information and should only be exposed
500    /// in a secure context.
501    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(2))]
502    #[default]
503    Unspecified,
504    /// The node contains sensitive information and should only be exposed in a
505    /// secure context.
506    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(3))]
507    Sensitive,
508}
509
510#[cfg(any(feature = "defer", feature = "initiate"))]
511impl<'a> RequestRoot<'a> {
512    fn new(
513        path: &'a str,
514        depth: usize,
515        value: Option<&'a str>,
516        sensitivity: SensitivityLevel,
517    ) -> Self {
518        Self {
519            path,
520            node: InternalNode::Unevaluated,
521            depth,
522            value,
523            sensitivity,
524        }
525    }
526
527    fn request(&mut self) -> Request<'_> {
528        Request::new(
529            self.path,
530            self.depth,
531            &mut self.node,
532            self.value,
533            self.sensitivity,
534        )
535    }
536}
537
538/// A type used to build an inspection response.
539pub struct Response<'a> {
540    /// Full remaining path, including leading `/`s.
541    path: &'a str,
542    /// Cache of remaining path without leading '/'s.
543    path_without_slashes: Option<&'a str>,
544    depth: usize,
545    cell: &'a mut InternalNode,
546    value: Option<&'a str>,
547    sensitivity: SensitivityLevel,
548}
549
550#[derive(Debug)]
551enum Action<'a, 'b> {
552    Process {
553        name: &'a str,
554        sensitivity: SensitivityLevel,
555        new_path: &'b str,
556        new_depth: usize,
557    },
558    Skip,
559    DepthExhausted {
560        name: &'a str,
561        sensitivity: SensitivityLevel,
562    },
563}
564
565impl<'a, 'b> Action<'a, 'b> {
566    // Determine which action to take for the field with `name`, given the
567    // remaining `path` and the remaining `depth`.
568    fn eval(child: Child<'a>, resp: &Response<'b>) -> Self {
569        let path = resp.path_without_slashes.unwrap();
570        if resp.depth == 0 {
571            // Don't return any subfields if the depth is exhausted, since depth
572            // exhausted will be reported for the current node.
573            return Self::Skip;
574        }
575        if resp.sensitivity < child.sensitivity {
576            // Don't return any subfields if the request's sensitivity level is too low.
577            return Self::Skip;
578        }
579        if let Some(rest) = path.strip_prefix(child.name) {
580            if rest.is_empty() || rest.as_bytes()[0] == b'/' {
581                // Exact or prefix match, e.g. name and path are both "foo", or
582                // name is "foo", path is "foo/bar".
583                Self::Process {
584                    name: child.name,
585                    sensitivity: child.sensitivity,
586                    new_path: rest,
587                    new_depth: resp.depth,
588                }
589            } else {
590                // Mismatch, e.g. name is "foo", path is "foobar", or this is a
591                // prefix match but this node is a value.
592                Self::Skip
593            }
594        } else if child.name.starts_with(path) {
595            let remaining_name = if path.is_empty() {
596                // Path is empty, so allow all names.
597                child.name
598            } else {
599                if child.name.as_bytes()[path.len()] != b'/' {
600                    // Mismatch, e.g. name is "foobar", path is "foo".
601                    return Self::Skip;
602                }
603                // Prefix match, e.g. name is "foo/bar", path is "foo".
604                &child.name[path.len() + 1..]
605            };
606            // Ensure there is enough depth for the name.
607            match remaining_name.match_indices('/').nth(resp.depth - 1) {
608                None => Self::Process {
609                    name: child.name,
610                    sensitivity: child.sensitivity,
611                    new_path: "",
612                    new_depth: resp.depth - 1,
613                },
614                Some((n, _)) => Self::DepthExhausted {
615                    name: &child.name[..child.name.len() - remaining_name.len() + n],
616                    sensitivity: child.sensitivity,
617                },
618            }
619        } else {
620            Self::Skip
621        }
622    }
623}
624
625struct Child<'a> {
626    name: &'a str,
627    sensitivity: SensitivityLevel,
628}
629
630impl Response<'_> {
631    /// Adds a field to the response.
632    ///
633    /// ```no_run
634    /// # use inspect::{Request, Response};
635    /// # use std::path::Path;
636    /// fn inspect_data(a: u32, b: &str, c: bool, maybe: Option<u32>, req: Request) {
637    ///     req.respond()
638    ///        .field("a", a)
639    ///        .field("b", b)
640    ///        .field("c", c)
641    ///        .field("maybe", maybe)
642    ///        .field("computed", format_args!("{a}-{b}"));
643    /// }
644    /// ```
645    pub fn field<T>(&mut self, name: &str, value: T) -> &mut Self
646    where
647        T: Inspect,
648    {
649        self.inspect_field(name, &value)
650    }
651
652    /// Adds a field to the response with a [`SensitivityLevel`].
653    pub fn sensitivity_field<T>(
654        &mut self,
655        name: &str,
656        sensitivity: SensitivityLevel,
657        value: T,
658    ) -> &mut Self
659    where
660        T: Inspect,
661    {
662        self.sensitivity_inspect_field(name, sensitivity, &value)
663    }
664
665    /// Adds a hexadecimal field to the response.
666    ///
667    /// This is a convenience method for `field(name, Value::hex(value))`.
668    pub fn hex<T>(&mut self, name: &str, value: T) -> &mut Self
669    where
670        T: Into<Value>,
671    {
672        self.field_with(name, || value.into().into_hex())
673    }
674
675    /// Adds a counter field to the response.
676    ///
677    /// This is a convenience method for `field(name, Value::counter(value))`.
678    pub fn counter<T>(&mut self, name: &str, value: T) -> &mut Self
679    where
680        T: Into<Value>,
681    {
682        self.field_with(name, || value.into().into_counter())
683    }
684
685    /// Adds a counter field to the response.
686    ///
687    /// This is a convenience method for `sensitivity_field(name, sensitivity, Value::counter(value))`.
688    pub fn sensitivity_counter<T>(
689        &mut self,
690        name: &str,
691        sensitivity: SensitivityLevel,
692        value: T,
693    ) -> &mut Self
694    where
695        T: Into<Value>,
696    {
697        self.sensitivity_field_with(name, sensitivity, || value.into().into_counter())
698    }
699
700    /// Adds a binary field to the response.
701    ///
702    /// This is a convenience method for `field(name, Value::binary(value))`.
703    pub fn binary<T>(&mut self, name: &str, value: T) -> &mut Self
704    where
705        T: Into<Value>,
706    {
707        self.field_with(name, || value.into().into_binary())
708    }
709
710    /// Adds a string field that implements [`std::fmt::Display`].
711    ///
712    /// This is a convenience method for `field_with(name, ||
713    /// value.to_string())`. It lazily allocates the string only when the
714    /// inspector requests it, so it is more efficient than using `format!` or
715    /// `to_string()`.
716    ///
717    /// ```no_run
718    /// # use inspect::{Request, Response};
719    /// # use std::path::Path;
720    /// fn inspect_data(path: &Path, id: u32, req: Request) {
721    ///     req.respond().display("path", &path.display());
722    /// }
723    /// ```
724    pub fn display(&mut self, name: &str, value: &impl Display) -> &mut Self {
725        self.field_with(name, || value.to_string())
726    }
727
728    /// Adds a string field that implements [`std::fmt::Debug`].
729    ///
730    /// This is a convenience method for `field(name, format_args!("{value:?}"))`.
731    ///
732    /// Take care not to overuse this. This is best used for fields that have a
733    /// short or natural `Debug` implementation, such as dataless enums. If your
734    /// field is an aggregate type whose `Debug` implementation has a
735    /// complicated structure, consider implementing `Inspect` on the type and
736    /// calling [`field`](`Self::field`).
737    pub fn display_debug(&mut self, name: &str, value: &impl Debug) -> &mut Self {
738        self.field(name, format_args!("{value:?}"))
739    }
740
741    /// Adds a field to the response, calling `f` to get its value.
742    pub fn field_with<F, V>(&mut self, name: &str, f: F) -> &mut Self
743    where
744        F: FnOnce() -> V,
745        V: Inspect,
746    {
747        self.sensitivity_field_with(name, SensitivityLevel::Unspecified, f)
748    }
749
750    /// Adds a field to the response with a [`SensitivityLevel`], calling `f` to get its value.
751    pub fn sensitivity_field_with<F, V>(
752        &mut self,
753        name: &str,
754        sensitivity: SensitivityLevel,
755        f: F,
756    ) -> &mut Self
757    where
758        F: FnOnce() -> V,
759        V: Inspect,
760    {
761        if let Some(req) = self.child_request(Child { name, sensitivity }) {
762            (f)().inspect(req)
763        }
764        self
765    }
766
767    /// Adds a mutable field to the response.
768    pub fn field_mut<T>(&mut self, name: &str, value: &mut T) -> &mut Self
769    where
770        T: InspectMut + ?Sized,
771    {
772        self.inspect_field(name, value)
773    }
774
775    /// Adds a mutable field to the response with a [`SensitivityLevel`].
776    pub fn sensitivity_field_mut<T>(
777        &mut self,
778        name: &str,
779        sensitivity: SensitivityLevel,
780        value: &mut T,
781    ) -> &mut Self
782    where
783        T: InspectMut + ?Sized,
784    {
785        self.sensitivity_inspect_field(name, sensitivity, value)
786    }
787
788    /// Adds a mutable field with custom get/update function.
789    pub fn field_mut_with<F, V, E>(&mut self, name: &str, f: F) -> &mut Self
790    where
791        F: FnOnce(Option<&str>) -> Result<V, E>,
792        V: Into<Value>,
793        E: Into<Box<dyn core::error::Error + Send + Sync>>,
794    {
795        self.child(name, |req| match req.update() {
796            Ok(req) => match (f)(Some(req.new_value())) {
797                Ok(v) => req.succeed(v.into()),
798                Err(err) => req.fail(err),
799            },
800            Err(req) => req.value((f)(None).ok().unwrap().into()),
801        })
802    }
803
804    fn child_request(&mut self, child: Child<'_>) -> Option<Request<'_>> {
805        if self.path_without_slashes.is_none() {
806            self.path_without_slashes = Some(self.path.trim_start_matches('/'));
807        }
808
809        match Action::eval(child, self) {
810            Action::Process {
811                name,
812                sensitivity,
813                new_path,
814                new_depth,
815            } => {
816                let children = self.cell.as_dir();
817                children.push(InternalEntry {
818                    name: name.to_owned(),
819                    node: InternalNode::Unevaluated,
820                    sensitivity,
821                });
822                let entry = children.last_mut().unwrap();
823                Some(Request::new(
824                    new_path,
825                    new_depth,
826                    &mut entry.node,
827                    self.value,
828                    self.sensitivity,
829                ))
830            }
831            Action::Skip => None,
832            Action::DepthExhausted { name, sensitivity } => {
833                self.cell.as_dir().push(InternalEntry {
834                    name: name.to_owned(),
835                    node: InternalNode::DepthExhausted,
836                    sensitivity,
837                });
838                None
839            }
840        }
841    }
842
843    /// Inspects a child object.
844    fn inspect_field(&mut self, name: &str, child: impl InspectMut) -> &mut Self {
845        self.sensitivity_inspect_field(name, SensitivityLevel::Unspecified, child)
846    }
847
848    /// Inspects a child object with a [`SensitivityLevel`].
849    #[inline(never)] // Testing shows a significant code size reduction with this.
850    fn sensitivity_inspect_field(
851        &mut self,
852        name: &str,
853        sensitivity: SensitivityLevel,
854        mut child: impl InspectMut,
855    ) -> &mut Self {
856        if let Some(req) = self.child_request(Child { name, sensitivity }) {
857            child.inspect_mut(req);
858        }
859        self
860    }
861
862    /// Inspects a list of children objects as children of the node `name`.
863    ///
864    /// Each element of `children` should be a tuple (`child_name`, `child`).
865    /// `child_name` must be convertible to a string.
866    #[cfg_attr(
867        feature = "initiate",
868        doc = r##"
869```rust
870# use inspect::{inspect, Inspect, Request};
871# use core::time::Duration;
872
873struct Child(u32);
874impl Inspect for Child {
875    fn inspect(&self, req: Request) {
876        req.respond().field("x", self.0);
877    }
878}
879
880struct Parent(Vec<Child>);
881impl Inspect for Parent {
882    fn inspect(&self, req: Request) {
883        req.respond().fields("children", self.0.iter().enumerate());
884    }
885}
886
887assert_eq!(
888    inspect(
889        "",
890        &Parent(vec![Child(5), Child(12)]),
891    )
892    .results()
893    .to_string(),
894    r#"{children: {0: {x: 5}, 1: {x: 12}}}"#
895);
896```
897"##
898    )]
899    pub fn fields<I, N, C>(&mut self, name: &str, children: I) -> &mut Self
900    where
901        I: Iterator<Item = (N, C)>,
902        N: ToString,
903        C: Inspect,
904    {
905        self.child(name, |req| {
906            let mut resp = req.respond();
907            for (name, child) in children {
908                resp.inspect_field(&name.to_string(), &child);
909            }
910        })
911    }
912
913    /// Inspects a list of children objects as children of the node `name`.
914    ///
915    /// Each element of `children` should be a tuple (`child_name`, `child`).
916    /// `child_name` must be convertible to a string.
917    #[cfg_attr(
918        feature = "initiate",
919        doc = r##"
920```rust
921# use inspect::{inspect, InspectMut, Request};
922# use std::time::Duration;
923struct Child(u32);
924impl InspectMut for Child {
925    fn inspect_mut(&mut self, req: Request) {
926        req.respond().field("x", self.0);
927    }
928}
929
930struct Parent(Vec<Child>);
931impl InspectMut for Parent {
932    fn inspect_mut(&mut self, req: Request) {
933        req.respond().fields_mut("children", self.0.iter_mut().enumerate());
934    }
935}
936
937assert_eq!(
938    inspect(
939        "",
940        &mut Parent(vec![Child(5), Child(12)]),
941    )
942    .results()
943    .to_string(),
944    r#"{children: {0: {x: 5}, 1: {x: 12}}}"#
945);
946```
947"##
948    )]
949    pub fn fields_mut<I, N, C>(&mut self, name: &str, children: I) -> &mut Self
950    where
951        I: Iterator<Item = (N, C)>,
952        N: ToString,
953        C: InspectMut,
954    {
955        self.child(name, |req| {
956            let mut resp = req.respond();
957            for (name, child) in children {
958                resp.inspect_field(&name.to_string(), child);
959            }
960        })
961    }
962
963    /// Adds a child node to the inspection response.
964    ///
965    /// If `name` is empty, then the results of the inspection are merged into
966    /// this node.
967    pub fn child<F: FnOnce(Request<'_>)>(&mut self, name: &str, f: F) -> &mut Self {
968        self.sensitivity_child(name, SensitivityLevel::Unspecified, f)
969    }
970
971    /// Adds a child node to the inspection response with a [`SensitivityLevel`].
972    ///
973    /// If `name` is empty, then the results of the inspection are merged into
974    /// this node.
975    pub fn sensitivity_child<F: FnOnce(Request<'_>)>(
976        &mut self,
977        name: &str,
978        sensitivity: SensitivityLevel,
979        f: F,
980    ) -> &mut Self {
981        if let Some(req) = self.child_request(Child { name, sensitivity }) {
982            f(req);
983        }
984        self
985    }
986
987    /// Inspects an object and merges its responses into this node without
988    /// creating a child node.
989    pub fn merge(&mut self, mut child: impl InspectMut) -> &mut Self {
990        child.inspect_mut(self.request());
991        self
992    }
993
994    /// Gets another request for this response. The response to that request
995    /// will be merged into this response.
996    pub fn request(&mut self) -> Request<'_> {
997        let children = self.cell.as_dir();
998        children.push(InternalEntry {
999            name: String::new(),
1000            node: InternalNode::Unevaluated,
1001            sensitivity: SensitivityLevel::Unspecified,
1002        });
1003        let entry = children.last_mut().unwrap();
1004        Request::new(
1005            self.path,
1006            self.depth,
1007            &mut entry.node,
1008            self.value,
1009            self.sensitivity,
1010        )
1011    }
1012}
1013
1014impl Drop for Response<'_> {
1015    fn drop(&mut self) {
1016        if self.depth > 0 {
1017            // Ensure the children node was created.
1018            let _ = self.cell.as_dir();
1019        } else {
1020            // No children were collected, but this node had to be inspected in
1021            // case it was a value and not a directory node.
1022            *self.cell = InternalNode::DepthExhausted;
1023        }
1024    }
1025}
1026
1027impl<'a> Request<'a> {
1028    fn new(
1029        path: &'a str,
1030        depth: usize,
1031        cell: &'a mut InternalNode,
1032        value: Option<&'a str>,
1033        sensitivity: SensitivityLevel,
1034    ) -> Self {
1035        Self {
1036            path,
1037            depth,
1038            node: cell,
1039            value,
1040            sensitivity,
1041        }
1042    }
1043
1044    /// Responds to the request with a value.
1045    pub fn value(self, value: Value) {
1046        let node = if self.path.is_empty() {
1047            if self.value.is_none() {
1048                InternalNode::Value(value)
1049            } else {
1050                InternalNode::Failed(InternalError::Immutable)
1051            }
1052        } else {
1053            InternalNode::Failed(InternalError::NotADirectory)
1054        };
1055        *self.node = node;
1056    }
1057
1058    /// Returns an object used for handling an update request.
1059    ///
1060    /// If this is not an update request, returns `Err(self)`.
1061    pub fn update(self) -> Result<UpdateRequest<'a>, Self> {
1062        if let Some(value) = self.value {
1063            if !self.path.is_empty() {
1064                return Err(self);
1065            }
1066            Ok(UpdateRequest {
1067                node: self.node,
1068                value,
1069            })
1070        } else {
1071            Err(self)
1072        }
1073    }
1074
1075    /// Responds to the inspection request with a directory node.
1076    ///
1077    /// Returns an object that can be used to provide the inspection results.
1078    pub fn respond(self) -> Response<'a> {
1079        Response {
1080            path: self.path,
1081            path_without_slashes: None,
1082            depth: self.depth,
1083            cell: self.node,
1084            value: self.value,
1085            sensitivity: self.sensitivity,
1086        }
1087    }
1088
1089    /// Removes this node from the inspection output.
1090    pub fn ignore(self) {
1091        *self.node = InternalNode::Ignored;
1092    }
1093
1094    /// If true, this is an update request.
1095    pub fn is_update(&self) -> bool {
1096        self.value.is_some()
1097    }
1098
1099    /// Gets the sensitivity level for this request.
1100    pub fn sensitivity(&self) -> SensitivityLevel {
1101        self.sensitivity
1102    }
1103}
1104
1105/// An update request, used for updating a value.
1106pub struct UpdateRequest<'a> {
1107    node: &'a mut InternalNode,
1108    value: &'a str,
1109}
1110
1111impl UpdateRequest<'_> {
1112    /// Gets the requested new value.
1113    pub fn new_value(&self) -> &str {
1114        self.value
1115    }
1116
1117    /// Report that the update succeeded, with a new value of `value`.
1118    pub fn succeed(self, value: Value) {
1119        *self.node = InternalNode::Value(value);
1120    }
1121
1122    /// Report that the update failed, with the reason in `err`.
1123    pub fn fail<E: Into<Box<dyn core::error::Error + Send + Sync>>>(self, err: E) {
1124        *self.node = InternalNode::failed(err.into());
1125    }
1126}
1127
1128/// A child inspection value. This is not constructed directly but exists to
1129/// provide `From` implementations from the allowed value types.
1130#[derive(Debug, Clone, PartialEq)]
1131#[cfg_attr(
1132    any(feature = "defer", feature = "initiate"),
1133    derive(mesh::MeshPayload),
1134    mesh(package = "inspect")
1135)]
1136#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1137pub struct Value {
1138    /// The kind and associated value.
1139    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(1))]
1140    pub kind: ValueKind,
1141    /// Flags affecting how the value is displayed.
1142    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(2))]
1143    pub flags: ValueFlags,
1144}
1145
1146impl Value {
1147    /// Creates a new value from `kind`.
1148    pub fn new(kind: impl Into<ValueKind>) -> Self {
1149        Self {
1150            kind: kind.into(),
1151            flags: Default::default(),
1152        }
1153    }
1154
1155    /// Creates a new hexadecimal value from `kind`.
1156    pub fn hex(kind: impl Into<ValueKind>) -> Self {
1157        Self::new(kind).into_hex()
1158    }
1159
1160    /// Creates a new counter value from `kind`.
1161    pub fn counter(kind: impl Into<ValueKind>) -> Self {
1162        Self::new(kind).into_counter()
1163    }
1164
1165    /// Creates a new binary value from `kind`.
1166    pub fn binary(kind: impl Into<ValueKind>) -> Self {
1167        Self::new(kind).into_binary()
1168    }
1169
1170    /// Returns this value as a hexadecimal.
1171    pub fn into_hex(self) -> Self {
1172        Self {
1173            kind: self.kind,
1174            flags: self.flags.with_hex(true),
1175        }
1176    }
1177
1178    /// Returns this value as a counter.
1179    pub fn into_counter(self) -> Self {
1180        Self {
1181            kind: self.kind,
1182            flags: self.flags.with_count(true),
1183        }
1184    }
1185
1186    /// Returns this value as a binary.
1187    pub fn into_binary(self) -> Self {
1188        Self {
1189            kind: self.kind,
1190            flags: self.flags.with_binary(true),
1191        }
1192    }
1193}
1194
1195/// The different kinds of values that can be emitted.
1196#[derive(Debug, Clone, PartialEq)]
1197#[cfg_attr(
1198    any(feature = "defer", feature = "initiate"),
1199    derive(mesh::MeshPayload),
1200    mesh(package = "inspect")
1201)]
1202#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1203pub enum ValueKind {
1204    /// A signed integer.
1205    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(1))]
1206    Signed(i64),
1207    /// An unsigned integer.
1208    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(2))]
1209    Unsigned(u64),
1210    /// A 32-bit floating point.
1211    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(3))]
1212    Float(f32),
1213    /// A 64-bit floating point.
1214    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(4))]
1215    Double(f64),
1216    /// A Boolean value.
1217    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(5))]
1218    Bool(bool),
1219    /// A string.
1220    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(6))]
1221    String(String),
1222    /// Opaque binary data.
1223    #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(7))]
1224    Bytes(Vec<u8>),
1225}
1226
1227/// Flags specifying additional metadata on values.
1228#[bitfield_struct::bitfield(u64)]
1229#[derive(PartialEq)]
1230#[cfg_attr(
1231    any(feature = "defer", feature = "initiate"),
1232    derive(mesh::MeshPayload),
1233    mesh(package = "inspect")
1234)]
1235#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1236pub struct ValueFlags {
1237    /// This value should be displayed as hexadecimal.
1238    pub hex: bool,
1239    /// This value is a count and should be displayed as a rate.
1240    pub count: bool,
1241    /// This value should be displayed as binary.
1242    pub binary: bool,
1243
1244    #[bits(61)]
1245    _reserved: u64,
1246}
1247
1248impl Display for Value {
1249    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1250        match &self.kind {
1251            ValueKind::Signed(n) => {
1252                if self.flags.hex() {
1253                    write!(f, "{:#x}", &n)
1254                } else if self.flags.binary() {
1255                    write!(f, "{:#b}", &n)
1256                } else {
1257                    Display::fmt(&n, f)
1258                }
1259            }
1260            ValueKind::Unsigned(n) => {
1261                if self.flags.hex() {
1262                    write!(f, "{:#x}", &n)
1263                } else if self.flags.binary() {
1264                    write!(f, "{:#b}", &n)
1265                } else {
1266                    Display::fmt(&n, f)
1267                }
1268            }
1269            ValueKind::Float(n) => Display::fmt(&n, f),
1270            ValueKind::Double(n) => Display::fmt(&n, f),
1271            ValueKind::Bool(b) => Display::fmt(&b, f),
1272            ValueKind::String(s) => Debug::fmt(&s, f),
1273            ValueKind::Bytes(b) => {
1274                f.write_str("<")?;
1275                for &b in b {
1276                    write!(f, "{:02x}", b)?;
1277                }
1278                f.write_str(">")
1279            }
1280        }
1281    }
1282}
1283
1284impl<T> From<T> for Value
1285where
1286    ValueKind: From<T>,
1287{
1288    fn from(v: T) -> Self {
1289        Value {
1290            kind: v.into(),
1291            flags: Default::default(),
1292        }
1293    }
1294}
1295
1296macro_rules! from_as {
1297    ($x:ident, $to:ty, $($ty:ty),* $(,)?) => {
1298        $(
1299            impl From<$ty> for ValueKind {
1300                fn from(v: $ty) -> Self {
1301                    Self::$x(v as $to)
1302                }
1303            }
1304        )*
1305    };
1306}
1307
1308from_as!(Unsigned, u64, u8, u16, u32, u64, usize);
1309from_as!(Signed, i64, i8, i16, i32, i64, isize);
1310
1311macro_rules! from_get {
1312    ($x:ident, $to:ty, $($ty:ty),* $(,)?) => {
1313        $(
1314            impl From<$ty> for ValueKind {
1315                fn from(v: $ty) -> Self {
1316                    Self::$x(v.get() as $to)
1317                }
1318            }
1319        )*
1320    };
1321}
1322
1323from_get!(
1324    Unsigned,
1325    u64,
1326    core::num::NonZeroU8,
1327    core::num::NonZeroU16,
1328    core::num::NonZeroU32,
1329    core::num::NonZeroU64,
1330    core::num::NonZeroUsize
1331);
1332from_get!(
1333    Signed,
1334    i64,
1335    core::num::NonZeroI8,
1336    core::num::NonZeroI16,
1337    core::num::NonZeroI32,
1338    core::num::NonZeroI64,
1339    core::num::NonZeroIsize
1340);
1341
1342impl From<f32> for ValueKind {
1343    fn from(v: f32) -> Self {
1344        Self::Float(v)
1345    }
1346}
1347
1348impl From<f64> for ValueKind {
1349    fn from(v: f64) -> Self {
1350        Self::Double(v)
1351    }
1352}
1353
1354impl From<bool> for ValueKind {
1355    fn from(v: bool) -> Self {
1356        Self::Bool(v)
1357    }
1358}
1359
1360impl From<&'_ str> for ValueKind {
1361    fn from(v: &str) -> Self {
1362        Self::String(v.to_owned())
1363    }
1364}
1365
1366impl From<String> for ValueKind {
1367    fn from(v: String) -> Self {
1368        Self::String(v)
1369    }
1370}
1371
1372#[cfg(feature = "std")]
1373impl From<&'_ std::ffi::CStr> for ValueKind {
1374    fn from(v: &std::ffi::CStr) -> Self {
1375        Self::String(v.to_string_lossy().to_string())
1376    }
1377}
1378
1379#[cfg(feature = "std")]
1380impl From<std::ffi::CString> for ValueKind {
1381    fn from(v: std::ffi::CString) -> Self {
1382        Self::String(v.to_string_lossy().to_string())
1383    }
1384}
1385
1386impl From<&'_ [u8]> for ValueKind {
1387    fn from(v: &[u8]) -> Self {
1388        Self::Bytes(v.to_vec())
1389    }
1390}
1391
1392impl<const N: usize> From<[u8; N]> for ValueKind {
1393    fn from(v: [u8; N]) -> Self {
1394        Self::Bytes(v.to_vec())
1395    }
1396}
1397
1398impl From<Vec<u8>> for ValueKind {
1399    fn from(v: Vec<u8>) -> Self {
1400        Self::Bytes(v)
1401    }
1402}
1403
1404impl From<Arguments<'_>> for ValueKind {
1405    fn from(v: Arguments<'_>) -> Self {
1406        Self::String(v.to_string())
1407    }
1408}
1409
1410impl<T: Into<ValueKind> + Clone> From<&'_ T> for ValueKind {
1411    fn from(v: &T) -> Self {
1412        v.clone().into()
1413    }
1414}
1415
1416impl Inspect for () {
1417    fn inspect(&self, req: Request<'_>) {
1418        req.respond();
1419    }
1420}
1421
1422impl InspectMut for () {
1423    fn inspect_mut(&mut self, req: Request<'_>) {
1424        req.respond();
1425    }
1426}
1427
1428macro_rules! inspect_value_immut {
1429    ($($(#[$attr:meta])* $ty:ty),* $(,)?) => {
1430        $(
1431        $(#[$attr])*
1432        impl Inspect for $ty {
1433            fn inspect(&self, req: Request<'_>) {
1434                req.value(self.into())
1435            }
1436        }
1437        )*
1438    };
1439}
1440
1441macro_rules! inspect_value {
1442    ($($(#[$attr:meta])* $ty:ty),* $(,)?) => {
1443        inspect_value_immut!($($ty,)*);
1444        $(
1445        $(#[$attr])*
1446        impl InspectMut for $ty {
1447            fn inspect_mut(&mut self, req: Request<'_>) {
1448                match req.update() {
1449                    Ok(req) => match req.new_value().parse::<Self>() {
1450                        Ok(v) => {
1451                            *self = v.clone();
1452                            req.succeed(v.into());
1453                        }
1454                        Err(err) => req.fail(err),
1455                    }
1456                    Err(req) => req.value((&*self).into()),
1457                }
1458            }
1459        }
1460        )*
1461    };
1462}
1463
1464inspect_value_immut! {
1465    str,
1466    #[cfg(feature = "std")]
1467    std::ffi::CStr,
1468    #[cfg(feature = "std")]
1469    std::ffi::CString,
1470    [u8],
1471    Vec<u8>,
1472    Arguments<'_>,
1473}
1474
1475inspect_value! {
1476    u8,
1477    u16,
1478    u32,
1479    u64,
1480    usize,
1481    i8,
1482    i16,
1483    i32,
1484    i64,
1485    isize,
1486    core::num::NonZeroU8,
1487    core::num::NonZeroU16,
1488    core::num::NonZeroU32,
1489    core::num::NonZeroU64,
1490    core::num::NonZeroUsize,
1491    core::num::NonZeroI8,
1492    core::num::NonZeroI16,
1493    core::num::NonZeroI32,
1494    core::num::NonZeroI64,
1495    core::num::NonZeroIsize,
1496    f32,
1497    f64,
1498    bool,
1499    String,
1500}
1501
1502impl<const N: usize> Inspect for [u8; N] {
1503    fn inspect(&self, req: Request<'_>) {
1504        self.as_slice().inspect(req)
1505    }
1506}
1507
1508/// Inspect wrapper for an atomic value (e.g.,
1509/// [`AtomicBool`](core::sync::atomic::AtomicBool), allowing updates.
1510pub struct AtomicMut<T>(pub T);
1511
1512macro_rules! inspect_atomic_value {
1513    ($(($ty:ident, $backing:ty)),* $(,)?) => {
1514        $(
1515
1516        impl Inspect for core::sync::atomic::$ty {
1517            fn inspect(&self, req: Request<'_>) {
1518                req.value(self.load(core::sync::atomic::Ordering::Relaxed).into())
1519            }
1520        }
1521
1522        // It doesn't make much sense to impl InspectMut, since if you have a &mut
1523        // reference to the Atomic, it's most likely that type didn't need to be
1524        // atomic in the first place.
1525
1526        impl Inspect for AtomicMut<&core::sync::atomic::$ty> {
1527            fn inspect(&self, req: Request<'_>) {
1528                let mut value = self.0.load(core::sync::atomic::Ordering::Relaxed);
1529                let is_update = req.is_update();
1530                value.inspect_mut(req);
1531                if is_update {
1532                    self.0.store(value, core::sync::atomic::Ordering::Relaxed);
1533                }
1534            }
1535        }
1536
1537        )*
1538    };
1539}
1540
1541inspect_atomic_value! {
1542    (AtomicBool,  bool),
1543    (AtomicU8,    u8),
1544    (AtomicU16,   u16),
1545    (AtomicU32,   u32),
1546    (AtomicU64,   u64),
1547    (AtomicUsize, usize),
1548    (AtomicI8,    i8),
1549    (AtomicI16,   i16),
1550    (AtomicI32,   i32),
1551    (AtomicI64,   i64),
1552    (AtomicIsize, isize),
1553}
1554
1555impl<T: Inspect> Inspect for Wrapping<T> {
1556    fn inspect(&self, req: Request<'_>) {
1557        self.0.inspect(req)
1558    }
1559}
1560
1561impl<T: InspectMut> InspectMut for Wrapping<T> {
1562    fn inspect_mut(&mut self, req: Request<'_>) {
1563        self.0.inspect_mut(req)
1564    }
1565}
1566
1567#[cfg(feature = "filepath")]
1568impl Inspect for std::fs::File {
1569    fn inspect(&self, req: Request<'_>) {
1570        use filepath::FilePath;
1571        if let Ok(path) = self.path() {
1572            req.value(path.display().to_string().into());
1573        } else {
1574            req.ignore();
1575        }
1576    }
1577}
1578
1579/// Wrapper around `T` that implements [`Inspect`] by calling
1580/// [`ToString::to_string()`].
1581pub struct AsDisplay<T>(pub T);
1582
1583impl<T: Display> Inspect for AsDisplay<T> {
1584    fn inspect(&self, req: Request<'_>) {
1585        req.value(self.0.to_string().into())
1586    }
1587}
1588
1589/// Wrapper around `T` that implements [`Inspect`] by formatting with the
1590/// [`Debug`] trait.
1591pub struct AsDebug<T>(pub T);
1592
1593impl<T: Debug> InspectMut for AsDebug<T> {
1594    fn inspect_mut(&mut self, req: Request<'_>) {
1595        req.value(format!("{:?}", self.0).into())
1596    }
1597}
1598
1599impl<T: Debug> Inspect for AsDebug<T> {
1600    fn inspect(&self, req: Request<'_>) {
1601        req.value(format!("{:?}", self.0).into())
1602    }
1603}
1604
1605macro_rules! hexbincount {
1606    ($tr:ident, $method:ident, $($ty:ty),* $(,)?) => {
1607        $(
1608            impl Inspect for $tr<$ty> {
1609                fn inspect(&self, req: Request<'_>) {
1610                    req.value(Value::from(self.0).$method());
1611                }
1612            }
1613        )*
1614    };
1615}
1616
1617/// Wrapper around `T` that implements [`Inspect`] by writing a value with
1618/// [`ValueFlags::hex`].
1619#[derive(Clone, Copy)]
1620pub struct AsHex<T>(pub T);
1621
1622hexbincount!(AsHex, into_hex, u8, u16, u32, u64, usize);
1623
1624impl<T> Inspect for AsHex<Wrapping<T>>
1625where
1626    for<'a> AsHex<&'a T>: Inspect,
1627{
1628    fn inspect(&self, req: Request<'_>) {
1629        Inspect::inspect(&AsHex(&self.0.0), req)
1630    }
1631}
1632
1633impl<T: Clone> Inspect for AsHex<&'_ T>
1634where
1635    AsHex<T>: Inspect,
1636{
1637    fn inspect(&self, req: Request<'_>) {
1638        Inspect::inspect(&AsHex(self.0.clone()), req)
1639    }
1640}
1641
1642impl<T> Inspect for AsHex<Option<T>>
1643where
1644    for<'a> AsHex<&'a T>: Inspect,
1645{
1646    fn inspect(&self, req: Request<'_>) {
1647        Inspect::inspect(&self.0.as_ref().map(AsHex), req);
1648    }
1649}
1650
1651/// Wrapper around `T` that implements [`Inspect`] by writing a value with
1652/// [`ValueFlags::binary`].
1653pub struct AsBinary<T>(pub T);
1654
1655hexbincount!(AsBinary, into_binary, u8, u16, u32, u64, usize);
1656
1657impl<T: Clone> Inspect for AsBinary<&'_ T>
1658where
1659    AsBinary<T>: Inspect,
1660{
1661    fn inspect(&self, req: Request<'_>) {
1662        Inspect::inspect(&AsBinary(self.0.clone()), req)
1663    }
1664}
1665
1666impl<T> Inspect for AsBinary<Option<T>>
1667where
1668    for<'a> AsBinary<&'a T>: Inspect,
1669{
1670    fn inspect(&self, req: Request<'_>) {
1671        Inspect::inspect(&self.0.as_ref().map(AsBinary), req);
1672    }
1673}
1674
1675/// Wrapper around `T` that implements [`Inspect`] by writing a value with
1676/// [`ValueFlags::count`].
1677pub struct AsCounter<T>(pub T);
1678
1679hexbincount!(AsCounter, into_counter, u8, u16, u32, u64, usize);
1680
1681impl<T: Clone> Inspect for AsCounter<&'_ T>
1682where
1683    AsCounter<T>: Inspect,
1684{
1685    fn inspect(&self, req: Request<'_>) {
1686        Inspect::inspect(&AsCounter(self.0.clone()), req)
1687    }
1688}
1689
1690/// Wrapper around `T` that implements [`Inspect`] by writing a
1691/// [`ValueKind::Bytes`] value.
1692///
1693/// `T` must be iterable with `u8` or `&u8`.
1694pub struct AsBytes<T>(pub T);
1695
1696impl<T> Inspect for AsBytes<T>
1697where
1698    T: Clone + IntoIterator,
1699    Vec<u8>: Extend<T::Item>,
1700{
1701    fn inspect(&self, req: Request<'_>) {
1702        let mut v = Vec::new();
1703        v.extend(self.0.clone());
1704        req.value(ValueKind::Bytes(v).into())
1705    }
1706}
1707
1708#[doc(hidden)]
1709pub mod derive_helpers {
1710    /// Helps with type inference in inspect_derive output.
1711    pub fn call<T, F, R>(t: T, f: F) -> R
1712    where
1713        F: Fn(T) -> R,
1714    {
1715        f(t)
1716    }
1717}
1718
1719/// Implementation of [`Inspect`] a type that implements [`Iterator`] with an
1720/// item type `(K, V)`.
1721///
1722/// Inspecting this type will respond with a field for each entry in the
1723/// iterator, with `K` for the field's name and `V` for the field's value.
1724///
1725/// Construct with [`iter_by_key`] or [`iter_by_index`].
1726#[derive(Default)]
1727pub struct Iterated<I>(I);
1728
1729/// Wraps an iterator for inspection.
1730///
1731/// # Example
1732///
1733/// ```rust
1734/// # use std::collections::BTreeMap;
1735/// fn inspect(req: inspect::Request<'_>) {
1736///     let v = BTreeMap::from([("foo", 1), ("bar", 2)]);
1737///     // Responds with { foo: 1, bar: 2 }.
1738///     req.respond().field("v", inspect::iter_by_key(&v));
1739/// }
1740/// ```
1741pub fn iter_by_key<I, K, V>(iter: impl IntoIterator<IntoIter = I>) -> Iterated<I>
1742where
1743    I: Clone + Iterator<Item = (K, V)>,
1744{
1745    Iterated(iter.into_iter())
1746}
1747
1748/// Wraps an iterator for inspection, using the index in the enumeration as
1749/// the field name.
1750///
1751/// # Example
1752///
1753/// ```rust
1754/// fn inspect(req: inspect::Request<'_>) {
1755///     let v = vec!["foo", "bar", "baz"];
1756///     // Responds with { 0: "foo", 1: "bar", 2: "baz" }.
1757///     req.respond().field("v", inspect::iter_by_index(&v));
1758/// }
1759/// ```
1760pub fn iter_by_index<I, V>(
1761    iter: impl IntoIterator<IntoIter = I>,
1762) -> Iterated<core::iter::Enumerate<I>>
1763where
1764    I: Clone + Iterator<Item = V>,
1765{
1766    iter_by_key(iter.into_iter().enumerate())
1767}
1768
1769impl<I, K, V> Iterated<I>
1770where
1771    I: Clone + Iterator<Item = (K, V)>,
1772{
1773    /// Maps the key of the iterator with `f`.
1774    ///
1775    /// # Example
1776    ///
1777    /// ```rust
1778    /// fn inspect(req: inspect::Request<'_>) {
1779    ///     let v = vec!["foo", "bar", "baz"];
1780    ///     // Responds with { 1: "foo", 2: "bar", 3: "baz" }.
1781    ///     req.respond().field("v", inspect::iter_by_index(&v).map_key(|k| k + 1));
1782    /// }
1783    /// ```
1784    pub fn map_key<F, K2>(self, mut f: F) -> Iterated<impl Clone + Iterator<Item = (K2, V)>>
1785    where
1786        F: Clone + FnMut(K) -> K2,
1787    {
1788        iter_by_key(self.0.map(move |(k, v)| (f(k), v)))
1789    }
1790
1791    /// Maps the value of the iterator with `f`.
1792    ///
1793    /// # Example
1794    ///
1795    /// ```rust
1796    /// fn inspect(req: inspect::Request<'_>) {
1797    ///     let v = vec![10, 20, 30];
1798    ///     // Responds with { 0: 20, 1: 40, 2: 60 }.
1799    ///     req.respond().field("v", inspect::iter_by_index(&v).map_value(|v| v * 2));
1800    /// }
1801    /// ```
1802    pub fn map_value<F, V2>(self, mut f: F) -> Iterated<impl Clone + Iterator<Item = (K, V2)>>
1803    where
1804        F: Clone + FnMut(V) -> V2,
1805    {
1806        iter_by_key(self.0.map(move |(k, v)| (k, f(v))))
1807    }
1808
1809    /// Prefixes each key with the string `prefix`.
1810    ///
1811    /// # Example
1812    ///
1813    /// ```rust
1814    /// fn inspect(req: inspect::Request<'_>) {
1815    ///     let v = vec![10, 20, 30];
1816    ///     // Responds with { n0: 10, n1: 20, n2: 30 }.
1817    ///     req.respond().field("v", inspect::iter_by_index(&v).prefix("n"));
1818    /// }
1819    /// ```
1820    pub fn prefix<'a>(
1821        self,
1822        prefix: &'a str,
1823    ) -> Iterated<impl 'a + Clone + Iterator<Item = (String, V)>>
1824    where
1825        K: Display,
1826        I: 'a,
1827        K: 'a,
1828        V: 'a,
1829    {
1830        self.map_key(move |k| format!("{}{}", prefix, k))
1831    }
1832}
1833
1834impl<I, K, V> Inspect for Iterated<I>
1835where
1836    I: Clone + Iterator<Item = (K, V)>,
1837    K: ToString,
1838    V: Inspect,
1839{
1840    fn inspect(&self, req: Request<'_>) {
1841        let mut resp = req.respond();
1842        for (name, value) in self.0.clone() {
1843            resp.field(&name.to_string(), value);
1844        }
1845    }
1846}
1847
1848#[derive(Debug)]
1849#[cfg_attr(
1850    any(feature = "defer", feature = "initiate"),
1851    derive(mesh::MeshPayload)
1852)]
1853#[cfg_attr(not(any(feature = "defer", feature = "initiate")), expect(dead_code))]
1854enum InternalNode {
1855    Unevaluated,
1856    Failed(InternalError),
1857    DepthExhausted,
1858    Value(Value),
1859    Dir(Vec<InternalEntry>),
1860    Ignored,
1861    #[cfg(any(feature = "defer", feature = "initiate"))]
1862    Deferred(mesh::OneshotReceiver<InternalNode>),
1863    #[cfg(any(feature = "defer", feature = "initiate"))]
1864    DirResolved(Vec<InternalEntry>),
1865}
1866
1867#[derive(Debug)]
1868#[cfg_attr(
1869    any(feature = "defer", feature = "initiate"),
1870    derive(mesh::MeshPayload)
1871)]
1872// Without the initiate feature we never read fields of the InternalEntry
1873// to produce a user-visible Entry, but we still need those fields.
1874#[cfg_attr(not(any(feature = "defer", feature = "initiate")), expect(dead_code))]
1875struct InternalEntry {
1876    name: String,
1877    node: InternalNode,
1878    sensitivity: SensitivityLevel,
1879}
1880
1881impl InternalNode {
1882    fn as_dir(&mut self) -> &mut Vec<InternalEntry> {
1883        match self {
1884            Self::Dir(children) => children,
1885            _ => {
1886                *self = Self::Dir(Vec::new());
1887                let Self::Dir(children) = self else {
1888                    unreachable!()
1889                };
1890                children
1891            }
1892        }
1893    }
1894}
1895
1896#[derive(Debug)]
1897#[cfg_attr(
1898    any(feature = "defer", feature = "initiate"),
1899    derive(mesh::MeshPayload)
1900)]
1901#[cfg_attr(not(any(feature = "defer", feature = "initiate")), expect(dead_code))]
1902enum InternalError {
1903    Immutable,
1904    Update(String),
1905    NotADirectory,
1906    Unresolved,
1907    Mesh(String),
1908}
1909
1910impl InternalNode {
1911    fn failed(err: Box<dyn core::error::Error + Send + Sync>) -> Self {
1912        use core::fmt::Write;
1913
1914        let mut s = err.to_string();
1915        let mut src = err.source();
1916        while let Some(err) = src {
1917            src = err.source();
1918            let _ = write!(&mut s, ": {err}");
1919        }
1920        InternalNode::Failed(InternalError::Update(s))
1921    }
1922}
1923
1924/// Trait implemented by objects whose state can be inspected and mutated. Most users should not implement this trait
1925/// directly, but instead derive [`InspectMut`](derive@InspectMut).
1926///
1927/// See the [`Inspect`] trait for more information on implementation strategies.
1928pub trait InspectMut {
1929    /// Inspects the object.
1930    fn inspect_mut(&mut self, req: Request<'_>);
1931}
1932
1933impl<T: Inspect + ?Sized> InspectMut for &'_ T {
1934    fn inspect_mut(&mut self, req: Request<'_>) {
1935        self.inspect(req);
1936    }
1937}
1938
1939impl<T: InspectMut + ?Sized> InspectMut for &'_ mut T {
1940    fn inspect_mut(&mut self, req: Request<'_>) {
1941        T::inspect_mut(*self, req)
1942    }
1943}
1944
1945impl<T: InspectMut + ?Sized> InspectMut for Box<T> {
1946    fn inspect_mut(&mut self, req: Request<'_>) {
1947        T::inspect_mut(self.as_mut(), req)
1948    }
1949}
1950
1951impl<T: InspectMut> InspectMut for Option<T> {
1952    fn inspect_mut(&mut self, req: Request<'_>) {
1953        if let Some(val) = self {
1954            val.inspect_mut(req);
1955        } else {
1956            req.ignore();
1957        }
1958    }
1959}
1960
1961/// Trait implemented by objects whose state can be inspected but not mutated.
1962///
1963/// For most cases, users should use the derive version of [`Inspect`](derive@Inspect)
1964/// as this will automatically update the implementation as new fields are added.
1965///
1966/// However there are cases where a user may want to manually implement this trait, such as when
1967/// an inspection result may require multiple struct fields for a single inspection field.
1968/// Users should take advantage of Rust's struct destructuring to introduce compiler errors to
1969/// keep manual `Inspect` trait implementations up to date as the struct changes.
1970///
1971/// # Example
1972/// The following code compiles.
1973/// ```no_run
1974/// # use inspect::Inspect;
1975/// struct Foo {
1976///     id: u32,
1977///     more_stuff: usize,
1978///     super_string: String,
1979/// }
1980///
1981/// impl Inspect for Foo {
1982///     fn inspect(&self, req: inspect::Request<'_>) {
1983///         let Foo {
1984///             id,
1985///             more_stuff,
1986///             super_string,
1987///         } = self;
1988///
1989///         let mut resp = req.respond();
1990///         resp.hex("id", id);
1991///         resp.field("more_stuff", more_stuff);
1992///
1993///         // Only provide the super_string field if id is 2.
1994///         if *id == 2 {
1995///             resp.field("super_string", super_string);
1996///         }
1997///     }
1998/// }
1999/// ```
2000///
2001/// However, someone adding a new field to `Foo` without updating the inspect implementation will no longer compile.
2002/// ```compile_fail
2003/// # use inspect::Inspect;
2004/// struct Foo {
2005///     id: u32,
2006///     more_stuff: usize,
2007///     super_string: String,
2008///     awesome_new_field: String,
2009/// }
2010///
2011/// impl Inspect for Foo {
2012///     fn inspect(&self, req: inspect::Request<'_>) {
2013///         let Foo {
2014///             id,
2015///             more_stuff,
2016///             super_string,
2017///             // Missing awesome_new_field!
2018///         } = self;
2019///
2020///         let mut resp = respond();
2021///         resp.hex("id", id);
2022///         resp.field("more_stuff", more_stuff);
2023///
2024///         // Only provide the super_string field if id is 2.
2025///         if id == 2 {
2026///             resp.field("super_string", super_string);
2027///         }
2028///     }
2029/// }
2030/// ```
2031pub trait Inspect {
2032    /// Inspects the object.
2033    fn inspect(&self, req: Request<'_>);
2034}
2035
2036impl<T: Inspect + ?Sized> Inspect for &'_ T {
2037    fn inspect(&self, req: Request<'_>) {
2038        T::inspect(*self, req)
2039    }
2040}
2041
2042impl<T: Inspect + ?Sized> Inspect for &'_ mut T {
2043    fn inspect(&self, req: Request<'_>) {
2044        T::inspect(*self, req)
2045    }
2046}
2047
2048impl<T: Inspect + ?Sized> Inspect for Box<T> {
2049    fn inspect(&self, req: Request<'_>) {
2050        T::inspect(self.as_ref(), req)
2051    }
2052}
2053
2054impl<T: Inspect + ?Sized> Inspect for Rc<T> {
2055    fn inspect(&self, req: Request<'_>) {
2056        T::inspect(self.as_ref(), req)
2057    }
2058}
2059
2060impl<T: Inspect + ?Sized> Inspect for Arc<T> {
2061    fn inspect(&self, req: Request<'_>) {
2062        T::inspect(self.as_ref(), req)
2063    }
2064}
2065
2066impl<T: Inspect + ?Sized> Inspect for parking_lot::Mutex<T> {
2067    fn inspect(&self, req: Request<'_>) {
2068        T::inspect(&*self.lock(), req)
2069    }
2070}
2071
2072impl<T: Inspect + ?Sized> Inspect for parking_lot::RwLock<T> {
2073    fn inspect(&self, req: Request<'_>) {
2074        T::inspect(&*self.read(), req)
2075    }
2076}
2077
2078#[cfg(feature = "std")]
2079impl<T: Inspect> Inspect for std::sync::OnceLock<T> {
2080    fn inspect(&self, req: Request<'_>) {
2081        <_ as Inspect>::inspect(&self.get(), req)
2082    }
2083}
2084
2085impl<T: Inspect> Inspect for Option<T> {
2086    fn inspect(&self, req: Request<'_>) {
2087        if let Some(val) = self {
2088            val.inspect(req);
2089        } else {
2090            req.ignore();
2091        }
2092    }
2093}
2094
2095impl<T: ?Sized + Inspect + ToOwned> Inspect for Cow<'_, T> {
2096    fn inspect(&self, req: Request<'_>) {
2097        self.as_ref().inspect(req)
2098    }
2099}
2100
2101impl<T> Inspect for *mut T {
2102    fn inspect(&self, req: Request<'_>) {
2103        req.value(Value::hex(*self as usize))
2104    }
2105}
2106
2107impl<T> Inspect for *const T {
2108    fn inspect(&self, req: Request<'_>) {
2109        req.value(Value::hex(*self as usize))
2110    }
2111}
2112
2113impl Inspect for Value {
2114    fn inspect(&self, req: Request<'_>) {
2115        req.value(self.clone());
2116    }
2117}
2118
2119/// Returned by [`adhoc`] or [`adhoc_mut`].
2120pub struct Adhoc<F>(F);
2121
2122impl<F> InspectMut for Adhoc<F>
2123where
2124    F: FnMut(Request<'_>),
2125{
2126    fn inspect_mut(&mut self, req: Request<'_>) {
2127        (self.0)(req)
2128    }
2129}
2130
2131impl<F> Inspect for Adhoc<F>
2132where
2133    F: Fn(Request<'_>),
2134{
2135    fn inspect(&self, req: Request<'_>) {
2136        (self.0)(req)
2137    }
2138}
2139
2140/// Returns an object that implements `Inspect` by calling `f` with the
2141/// inspection request.
2142pub fn adhoc<F>(f: F) -> Adhoc<F>
2143where
2144    F: Fn(Request<'_>),
2145{
2146    Adhoc(f)
2147}
2148
2149/// Returns an object that implements `InspectMut` by calling `f` with the
2150/// inspection request.
2151pub fn adhoc_mut<F>(f: F) -> Adhoc<F>
2152where
2153    F: FnMut(Request<'_>),
2154{
2155    Adhoc(f)
2156}
2157
2158#[cfg(all(test, feature = "derive", feature = "initiate"))]
2159mod tests {
2160    use crate::AsBytes;
2161    use crate::AtomicMut;
2162    use crate::Error;
2163    use crate::Inspect;
2164    use crate::InspectMut;
2165    use crate::InspectionBuilder;
2166    use crate::Node;
2167    use crate::Request;
2168    use crate::SensitivityLevel;
2169    use crate::ValueKind;
2170    use crate::adhoc;
2171    use crate::adhoc_mut;
2172    use crate::inspect;
2173    use crate::update;
2174    use alloc::boxed::Box;
2175    use alloc::string::String;
2176    use alloc::string::ToString;
2177    use alloc::vec;
2178    use alloc::vec::Vec;
2179    use core::time::Duration;
2180    use expect_test::Expect;
2181    use expect_test::expect;
2182    use futures::FutureExt;
2183    use pal_async::DefaultDriver;
2184    use pal_async::async_test;
2185    use pal_async::timer::Instant;
2186    use pal_async::timer::PolledTimer;
2187
2188    fn expected_node(node: Node, expect: Expect) -> Node {
2189        expect.assert_eq(&node.to_string());
2190        node
2191    }
2192
2193    async fn inspect_async(
2194        driver: &DefaultDriver,
2195        path: &str,
2196        depth: Option<usize>,
2197        timeout: Duration,
2198        obj: impl InspectMut,
2199    ) -> Node {
2200        let deadline = Instant::now() + timeout;
2201        let mut result = InspectionBuilder::new(path).depth(depth).inspect(obj);
2202        let mut timer = PolledTimer::new(driver);
2203        futures::select! { // race semantics
2204            _ = result.resolve().fuse() => {}
2205            _ = timer.sleep_until(deadline).fuse() => {}
2206        };
2207        result.results()
2208    }
2209
2210    async fn inspect_async_expect(
2211        driver: &DefaultDriver,
2212        path: &str,
2213        depth: Option<usize>,
2214        timeout: Duration,
2215        obj: impl InspectMut,
2216        expect: Expect,
2217    ) -> Node {
2218        expected_node(
2219            inspect_async(driver, path, depth, timeout, obj).await,
2220            expect,
2221        )
2222    }
2223
2224    fn inspect_sync(path: &str, depth: Option<usize>, obj: impl InspectMut) -> Node {
2225        let mut result = InspectionBuilder::new(path).depth(depth).inspect(obj);
2226        result.resolve().now_or_never();
2227        result.results()
2228    }
2229
2230    fn inspect_sync_expect(
2231        path: &str,
2232        depth: Option<usize>,
2233        obj: impl InspectMut,
2234        expect: Expect,
2235    ) -> Node {
2236        expected_node(inspect_sync(path, depth, obj), expect)
2237    }
2238
2239    #[derive(Default)]
2240    struct Foo {
2241        xx: u32,
2242        xy: bool,
2243        xz: Vec<Foo>,
2244    }
2245
2246    impl Inspect for Foo {
2247        fn inspect(&self, req: Request<'_>) {
2248            let mut resp = req.respond();
2249            resp.field("xx", self.xx)
2250                .field("xy", self.xy)
2251                .fields("", self.xz.iter().enumerate());
2252        }
2253    }
2254
2255    #[test]
2256    fn test() {
2257        let f = Foo {
2258            xx: 1,
2259            xy: true,
2260            xz: vec![
2261                Foo {
2262                    xx: 3,
2263                    xy: false,
2264                    xz: vec![],
2265                },
2266                Foo {
2267                    xx: 5,
2268                    xy: true,
2269                    xz: vec![],
2270                },
2271            ],
2272        };
2273        let node = inspect_sync_expect(
2274            "",
2275            None,
2276            &f,
2277            expect!("{0: {xx: 3, xy: false}, 1: {xx: 5, xy: true}, xx: 1, xy: true}"),
2278        );
2279        let expected_json =
2280            expect!([r#"{"0":{"xx":3,"xy":false},"1":{"xx":5,"xy":true},"xx":1,"xy":true}"#]);
2281        expected_json.assert_eq(&node.json().to_string());
2282    }
2283
2284    #[async_test]
2285    async fn test_deferred(driver: DefaultDriver) {
2286        inspect_async_expect(
2287            &driver,
2288            "",
2289            None,
2290            Duration::from_secs(1),
2291            adhoc(|req| {
2292                let foo = req.defer();
2293                std::thread::spawn(|| foo.inspect(&Foo::default()));
2294            }),
2295            expect!("{xx: 0, xy: false}"),
2296        )
2297        .await;
2298    }
2299
2300    #[async_test]
2301    async fn test_dropped(driver: DefaultDriver) {
2302        inspect_async_expect(
2303            &driver,
2304            "",
2305            None,
2306            Duration::from_secs(86400),
2307            adhoc(|req| {
2308                drop(req.defer());
2309            }),
2310            expect!("error (unresolved)"),
2311        )
2312        .await;
2313    }
2314
2315    #[test]
2316    fn test_path() {
2317        let mut obj = adhoc(|req| {
2318            req.respond().field("a", 1).child("b", |req| {
2319                req.respond().field("c", 2).field("d", 2).child("e", |req| {
2320                    req.respond();
2321                });
2322            });
2323        });
2324        inspect_sync_expect("a", None, &mut obj, expect!("1"));
2325        inspect_sync_expect("///a", None, &mut obj, expect!("1"));
2326        inspect_sync_expect("b", None, &mut obj, expect!("{c: 2, d: 2, e: {}}"));
2327        inspect_sync_expect("b/c", None, &mut obj, expect!("2"));
2328        inspect_sync_expect("b////c", None, &mut obj, expect!("2"));
2329        inspect_sync_expect("b/c/", None, &mut obj, expect!("error (not a directory)"));
2330        inspect_sync_expect("b/c/x", None, &mut obj, expect!("error (not a directory)"));
2331        inspect_sync_expect("b/e", None, &mut obj, expect!("{}"));
2332        inspect_sync_expect("b/e/", None, &mut obj, expect!("{}"));
2333        inspect_sync_expect("b/e///", None, &mut obj, expect!("{}"));
2334        inspect_sync_expect("b/f", None, &mut obj, expect!("error (not found)"));
2335    }
2336
2337    #[async_test]
2338    async fn test_timeout(driver: DefaultDriver) {
2339        inspect_async_expect(
2340            &driver,
2341            "",
2342            None,
2343            Duration::from_millis(10),
2344            adhoc(|req| {
2345                let foo = req.defer();
2346                std::thread::spawn(|| {
2347                    std::thread::sleep(Duration::from_millis(250));
2348                    foo.inspect(&Foo::default())
2349                });
2350            }),
2351            expect!("error (unresolved)"),
2352        )
2353        .await;
2354    }
2355
2356    #[test]
2357    fn test_merge() {
2358        let mut obj = adhoc(|req| {
2359            req.respond()
2360                .field("a", 1)
2361                .request()
2362                .respond()
2363                .field("b", 2);
2364        });
2365
2366        inspect_sync_expect("", None, &mut obj, expect!("{a: 1, b: 2}"));
2367        inspect_sync_expect("a", None, &mut obj, expect!("1"));
2368        inspect_sync_expect("b", None, &mut obj, expect!("2"));
2369        inspect_sync_expect("c", None, &mut obj, expect!("error (not found)"));
2370    }
2371
2372    #[test]
2373    fn test_named_merge() {
2374        let mut obj = adhoc(|req| {
2375            req.respond()
2376                .field("a", 1)
2377                .field("a", 2)
2378                .child("x", |req| {
2379                    req.respond().field("b", 3).child("c", |req| {
2380                        req.respond().field("y", 4);
2381                    });
2382                })
2383                .child("x", |req| {
2384                    req.respond().field("b", 4).child("d", |req| {
2385                        req.respond().field("y", 5);
2386                    });
2387                });
2388        });
2389
2390        inspect_sync_expect(
2391            "",
2392            None,
2393            &mut obj,
2394            expect!("{a: 2, x: {b: 4, c: {y: 4}, d: {y: 5}}}"),
2395        );
2396        inspect_sync_expect("x", None, &mut obj, expect!("{b: 4, c: {y: 4}, d: {y: 5}}"));
2397    }
2398
2399    #[test]
2400    fn test_update() {
2401        struct Foo {
2402            immut: u32,
2403            mut_: u32,
2404            child: Option<Box<Foo>>,
2405        }
2406
2407        impl InspectMut for Foo {
2408            fn inspect_mut(&mut self, req: Request<'_>) {
2409                let mut resp = req.respond();
2410                resp.field("immut", self.immut)
2411                    .field_mut("mut", &mut self.mut_)
2412                    .field_mut("child", &mut self.child);
2413            }
2414        }
2415
2416        let mut foo = Foo {
2417            immut: 1,
2418            mut_: 2,
2419            child: Some(Box::new(Foo {
2420                immut: 101,
2421                mut_: 102,
2422                child: None,
2423            })),
2424        };
2425        assert_eq!(
2426            update("immut", "12", &mut foo)
2427                .now_or_never()
2428                .unwrap()
2429                .unwrap_err(),
2430            Error::Immutable
2431        );
2432        assert_eq!(
2433            update("mut/", "4", &mut foo)
2434                .now_or_never()
2435                .unwrap()
2436                .unwrap_err(),
2437            Error::NotADirectory
2438        );
2439        assert_eq!(
2440            update("mut", "3", &mut foo)
2441                .now_or_never()
2442                .unwrap()
2443                .unwrap()
2444                .kind,
2445            ValueKind::Unsigned(3)
2446        );
2447        assert_eq!(
2448            update("//child/mut", "103", &mut foo)
2449                .now_or_never()
2450                .unwrap()
2451                .unwrap()
2452                .kind,
2453            ValueKind::Unsigned(103)
2454        );
2455        assert_eq!(foo.mut_, 3);
2456        assert_eq!(foo.child.as_ref().unwrap().mut_, 103);
2457    }
2458
2459    #[test]
2460    fn test_nest() {
2461        let mut obj = adhoc(|req| {
2462            req.respond().field("x/a/b", 1).field("x/a/c", 2);
2463        });
2464
2465        inspect_sync_expect("", None, &mut obj, expect!("{x: {a: {b: 1, c: 2}}}"));
2466        inspect_sync_expect("x/a", None, &mut obj, expect!("{b: 1, c: 2}"));
2467        inspect_sync_expect("x", Some(0), &mut obj, expect!("{a: _}"));
2468        inspect_sync_expect("x", Some(2), &mut obj, expect!("{a: {b: 1, c: 2}}"));
2469    }
2470
2471    #[test]
2472    fn test_depth() {
2473        let mut obj = adhoc(|req| {
2474            req.respond()
2475                .field("1a", 0)
2476                .field("1b", 0)
2477                .field("1c", 0)
2478                .child("1d", |req| {
2479                    req.respond().field("2a", 0).child("2b", |req| {
2480                        req.respond().child("3a", |req| {
2481                            req.respond().field_with("xxx", || -> u32 { panic!() });
2482                        });
2483                    });
2484                })
2485                .field("1d/2b/3b", 0);
2486        });
2487
2488        inspect_sync_expect("1d", Some(0), &mut obj, expect!("{2a: 0, 2b: _}"));
2489        inspect_sync_expect(
2490            "",
2491            Some(0),
2492            &mut obj,
2493            expect!("{1a: 0, 1b: 0, 1c: 0, 1d: _}"),
2494        );
2495        inspect_sync_expect(
2496            "",
2497            Some(1),
2498            &mut obj,
2499            expect!("{1a: 0, 1b: 0, 1c: 0, 1d: {2a: 0, 2b: _}}"),
2500        );
2501    }
2502
2503    #[test]
2504    fn test_hex() {
2505        let mut obj = adhoc(|req| {
2506            req.respond().hex("a", 0x1234);
2507        });
2508        inspect_sync_expect("", Some(0), &mut obj, expect!("{a: 0x1234}"));
2509    }
2510
2511    #[test]
2512    fn test_binary() {
2513        let mut obj = adhoc(|req| {
2514            req.respond().binary("a", 0b1001000110100);
2515        });
2516        inspect_sync_expect("", Some(0), &mut obj, expect!("{a: 0b1001000110100}"));
2517    }
2518
2519    #[test]
2520    fn test_since() {
2521        let mut n = 500_u32;
2522        let mut b = false;
2523        let mut obj = adhoc_mut(|req| {
2524            req.respond()
2525                .counter("c", n)
2526                .field("f", n)
2527                .child("d", |req| {
2528                    let mut resp = req.respond();
2529                    if !b {
2530                        resp.field("1_a", true).field("1_b", true);
2531                    } else {
2532                        resp.field("1_c", true);
2533                    }
2534                    resp.field("2", true).counter("3", n);
2535                    if !b {
2536                        resp.field("4_a", true);
2537                    } else {
2538                        resp.field("4_b", true).field("4_c", true);
2539                    }
2540                });
2541            n += 100;
2542            b = true;
2543        });
2544        let old = inspect_sync("", Some(1), &mut obj);
2545        let new = inspect_sync("", Some(1), &mut obj);
2546
2547        let diff = new.since(&old, Duration::from_secs(2));
2548
2549        expected_node(
2550            diff,
2551            expect!("{c: 50, d: {1_c: true, 2: true, 3: 50, 4_b: true, 4_c: true}, f: 600}"),
2552        );
2553    }
2554
2555    #[test]
2556    fn test_bytes() {
2557        inspect_sync_expect(
2558            "",
2559            Some(1),
2560            &AsBytes([0xab, 0xcd, 0xef]),
2561            expect!("<abcdef>"),
2562        );
2563    }
2564
2565    #[test]
2566    fn test_sensitivity() {
2567        let mut obj = adhoc(|req| {
2568            req.respond()
2569                .sensitivity_field("1a", SensitivityLevel::Safe, 0)
2570                .sensitivity_field("1b", SensitivityLevel::Unspecified, 0)
2571                .sensitivity_field("1c", SensitivityLevel::Sensitive, 0)
2572                .sensitivity_child("1d", SensitivityLevel::Safe, |req| {
2573                    req.respond()
2574                        .sensitivity_field("2a", SensitivityLevel::Sensitive, 0)
2575                        .sensitivity_child("2b", SensitivityLevel::Safe, |req| {
2576                            req.respond().sensitivity_child(
2577                                "3a",
2578                                SensitivityLevel::Sensitive,
2579                                |req| {
2580                                    req.respond().sensitivity_field(
2581                                        "4a",
2582                                        SensitivityLevel::Safe,
2583                                        0,
2584                                    );
2585                                },
2586                            );
2587                        });
2588                })
2589                .sensitivity_field("1d/2b/3b", SensitivityLevel::Unspecified, 0)
2590                .sensitivity_child("", SensitivityLevel::Sensitive, |req| {
2591                    req.respond()
2592                        .sensitivity_field("1e", SensitivityLevel::Safe, 0);
2593                });
2594        });
2595
2596        fn inspect_sync(
2597            path: &str,
2598            sensitivity: Option<SensitivityLevel>,
2599            obj: impl InspectMut,
2600        ) -> Node {
2601            let mut result = InspectionBuilder::new(path)
2602                .sensitivity(sensitivity)
2603                .inspect(obj);
2604            result.resolve().now_or_never();
2605            result.results()
2606        }
2607
2608        expected_node(
2609            inspect_sync("", Some(SensitivityLevel::Safe), &mut obj),
2610            expect!("{1a: 0, 1d: {2b: {}}}"),
2611        );
2612        expected_node(
2613            inspect_sync("", Some(SensitivityLevel::Unspecified), &mut obj),
2614            expect!("{1a: 0, 1b: 0, 1d: {2b: {3b: 0}}}"),
2615        );
2616        expected_node(
2617            inspect_sync("", Some(SensitivityLevel::Sensitive), &mut obj),
2618            expect!("{1a: 0, 1b: 0, 1c: 0, 1d: {2a: 0, 2b: {3a: {4a: 0}, 3b: 0}}, 1e: 0}"),
2619        );
2620        expected_node(
2621            inspect_sync("", None, &mut obj),
2622            expect!("{1a: 0, 1b: 0, 1c: 0, 1d: {2a: 0, 2b: {3a: {4a: 0}, 3b: 0}}, 1e: 0}"),
2623        );
2624        expected_node(
2625            inspect_sync("", Some(SensitivityLevel::Sensitive), &mut obj),
2626            expect!("{1a: 0, 1b: 0, 1c: 0, 1d: {2a: 0, 2b: {3a: {4a: 0}, 3b: 0}}, 1e: 0}"),
2627        );
2628    }
2629
2630    #[test]
2631    fn test_derive() {
2632        use std::marker::PhantomData;
2633
2634        #[derive(InspectMut)]
2635        struct Derived {
2636            dec: u32,
2637            #[inspect(hex, rename = "hex")]
2638            val2: u64,
2639            #[inspect(binary)]
2640            bin: u8,
2641            inner: Inner,
2642            #[inspect(mut)]
2643            inner_mut: InnerMut,
2644            #[inspect(flatten)]
2645            flattened: Inner,
2646            #[inspect(skip)]
2647            _skip: bool,
2648            t: Transparent,
2649            t2: Newtype,
2650            #[inspect(format = "{:02x}")]
2651            minute: u8,
2652            #[inspect(debug)]
2653            debug: (),
2654            #[inspect(display)]
2655            display: u8,
2656            var: Enum,
2657            ignored: Ignored,
2658            tr1: Tr1,
2659            tr2: Tr2,
2660        }
2661
2662        #[derive(Clone, Inspect)]
2663        struct Inner {
2664            val: u32,
2665        }
2666
2667        #[derive(InspectMut)]
2668        struct InnerMut {
2669            val: String,
2670        }
2671
2672        #[derive(Inspect)]
2673        #[inspect(transparent)]
2674        struct Transparent {
2675            inner: Inner,
2676        }
2677
2678        #[derive(Inspect)]
2679        #[inspect(transparent)]
2680        struct Newtype(Inner, PhantomData<()>);
2681
2682        #[derive(Inspect)]
2683        #[inspect(transparent(hex))]
2684        struct Tr1(u32, PhantomData<()>);
2685
2686        #[derive(Inspect)]
2687        #[inspect(transparent)]
2688        struct Tr2(#[inspect(debug)] ());
2689
2690        #[derive(Inspect)]
2691        #[expect(dead_code)]
2692        enum Enum {
2693            Foo,
2694            BarBaz,
2695            #[inspect(rename = "brother")]
2696            Other,
2697        }
2698
2699        #[derive(Inspect)]
2700        #[inspect(skip)]
2701        struct Ignored {
2702            _x: fn(),
2703        }
2704
2705        let mut obj = Derived {
2706            dec: 5,
2707            val2: 4,
2708            bin: 3,
2709            inner: Inner { val: 3 },
2710            inner_mut: InnerMut {
2711                val: "hi".to_string(),
2712            },
2713            _skip: true,
2714            flattened: Inner { val: 8 },
2715            t: Transparent {
2716                inner: Inner { val: 1 },
2717            },
2718            t2: Newtype(Inner { val: 2 }, PhantomData),
2719            debug: (),
2720            display: 10,
2721            minute: 7,
2722            var: Enum::BarBaz,
2723            ignored: Ignored { _x: || () },
2724            tr1: Tr1(10, PhantomData),
2725            tr2: Tr2(()),
2726        };
2727
2728        inspect_sync_expect(
2729            "",
2730            None,
2731            &mut obj,
2732            expect!([
2733                r#"{bin: 0b11, debug: "()", dec: 5, display: "10", hex: 0x4, inner: {val: 3}, inner_mut: {val: "hi"}, minute: "07", t: {val: 1}, t2: {val: 2}, tr1: 0xa, tr2: "()", val: 8, var: "bar_baz"}"#
2734            ]),
2735        );
2736    }
2737
2738    #[test]
2739    fn test_derive_enum() {
2740        #[expect(dead_code)]
2741        #[derive(Inspect)]
2742        enum EmptyUnitEmum {}
2743
2744        #[expect(dead_code)]
2745        #[derive(Inspect)]
2746        #[inspect(untagged)]
2747        enum EmptyUntaggedEmum {}
2748
2749        #[expect(dead_code)]
2750        #[derive(Inspect)]
2751        enum UnitEnum {
2752            A,
2753            B,
2754            C,
2755        }
2756
2757        inspect_sync_expect("", None, &UnitEnum::B, expect!([r#""b""#]));
2758
2759        #[expect(dead_code)]
2760        #[derive(Inspect)]
2761        #[inspect(tag = "tag")]
2762        enum TaggedEnum {
2763            A { x: u32 },
2764            B(#[inspect(rename = "y")] bool),
2765        }
2766
2767        inspect_sync_expect(
2768            "",
2769            None,
2770            &TaggedEnum::B(true),
2771            expect!([r#"{tag: "b", y: true}"#]),
2772        );
2773
2774        #[expect(dead_code)]
2775        #[derive(Inspect)]
2776        #[inspect(external_tag)]
2777        enum ExternallyTaggedEnum {
2778            A {
2779                x: u32,
2780            },
2781            B(#[inspect(rename = "y")] bool),
2782            #[inspect(transparent)]
2783            C(u32),
2784        }
2785
2786        inspect_sync_expect(
2787            "",
2788            None,
2789            &ExternallyTaggedEnum::B(true),
2790            expect!("{b: {y: true}}"),
2791        );
2792
2793        inspect_sync_expect("", None, &ExternallyTaggedEnum::C(5), expect!("{c: 5}"));
2794
2795        #[expect(dead_code)]
2796        #[derive(Inspect)]
2797        #[inspect(untagged)]
2798        enum UntaggedEnum {
2799            A { x: u32 },
2800            B(#[inspect(rename = "y")] bool),
2801        }
2802
2803        inspect_sync_expect("", None, &UntaggedEnum::B(true), expect!("{y: true}"));
2804    }
2805
2806    #[test]
2807    fn test_derive_extra() {
2808        #[derive(Inspect)]
2809        #[inspect(extra = "Foo::inspect_extra")]
2810        struct Foo {
2811            x: u32,
2812            y: u32,
2813        }
2814
2815        impl Foo {
2816            fn inspect_extra(&self, resp: &mut inspect::Response<'_>) {
2817                resp.field("sum", self.x + self.y);
2818            }
2819        }
2820
2821        inspect_sync_expect(
2822            "",
2823            None,
2824            &Foo { x: 2, y: 5 },
2825            expect!("{sum: 7, x: 2, y: 5}"),
2826        );
2827    }
2828
2829    #[test]
2830    fn test_derive_sensitivity() {
2831        #[derive(Inspect)]
2832        struct Foo {
2833            #[inspect(safe)]
2834            a: u32,
2835            b: u32,
2836            #[inspect(sensitive)]
2837            c: u32,
2838            #[inspect(safe)]
2839            d: Bar,
2840        }
2841        #[derive(Inspect)]
2842        struct Bar {
2843            #[inspect(sensitive)]
2844            a: u32,
2845            #[inspect(safe)]
2846            b: Baz,
2847        }
2848        #[derive(Inspect)]
2849        struct Baz {
2850            #[inspect(sensitive)]
2851            a: Qux,
2852            b: u32,
2853        }
2854        #[derive(Inspect)]
2855        struct Qux {
2856            #[inspect(safe)]
2857            a: u32,
2858        }
2859
2860        fn inspect_sync(
2861            path: &str,
2862            sensitivity: Option<SensitivityLevel>,
2863            obj: impl Inspect,
2864        ) -> Node {
2865            let mut result = InspectionBuilder::new(path)
2866                .sensitivity(sensitivity)
2867                .inspect(&obj);
2868            result.resolve().now_or_never();
2869            result.results()
2870        }
2871
2872        let obj = Foo {
2873            a: 0,
2874            b: 0,
2875            c: 0,
2876            d: Bar {
2877                a: 0,
2878                b: Baz {
2879                    a: Qux { a: 0 },
2880                    b: 0,
2881                },
2882            },
2883        };
2884
2885        expected_node(
2886            inspect_sync("", Some(SensitivityLevel::Safe), &obj),
2887            expect!("{a: 0, d: {b: {}}}"),
2888        );
2889        expected_node(
2890            inspect_sync("", Some(SensitivityLevel::Unspecified), &obj),
2891            expect!("{a: 0, b: 0, d: {b: {b: 0}}}"),
2892        );
2893        let node = expected_node(
2894            inspect_sync("", Some(SensitivityLevel::Sensitive), &obj),
2895            expect!("{a: 0, b: 0, c: 0, d: {a: 0, b: {a: {a: 0}, b: 0}}}"),
2896        );
2897        assert_eq!(
2898            node,
2899            inspect_sync("", Some(SensitivityLevel::Sensitive), &obj)
2900        );
2901    }
2902
2903    /// Test that you can update via AtomicMut.
2904    #[test]
2905    fn test_atomic_mut() {
2906        let mut v = core::sync::atomic::AtomicBool::new(false);
2907        let obj = AtomicMut(&v);
2908        update("", "true", &obj).now_or_never().unwrap().unwrap();
2909        assert!(*v.get_mut());
2910    }
2911}