1#![no_std]
17#![forbid(unsafe_code)]
18
19extern crate alloc;
20
21#[cfg(any(feature = "std", feature = "initiate", feature = "defer",))]
27extern crate std;
28
29#[cfg(feature = "defer")]
30mod defer;
31#[cfg(feature = "initiate")]
32mod initiate;
33
34#[cfg(all(test, feature = "derive", feature = "initiate"))]
35extern crate self as inspect;
36
37#[cfg(feature = "defer")]
38pub use defer::*;
39#[cfg(feature = "initiate")]
40pub use initiate::*;
41
42#[cfg(feature = "derive")]
446pub use inspect_derive::Inspect;
447#[cfg(feature = "derive")]
451pub use inspect_derive::InspectMut;
452
453use alloc::borrow::Cow;
454use alloc::borrow::ToOwned;
455use alloc::boxed::Box;
456use alloc::format;
457use alloc::rc::Rc;
458use alloc::string::String;
459use alloc::string::ToString;
460use alloc::sync::Arc;
461use alloc::vec::Vec;
462use core::fmt;
463use core::fmt::Arguments;
464use core::fmt::Debug;
465use core::fmt::Display;
466use core::num::Wrapping;
467
468pub struct Request<'a> {
470 path: &'a str,
471 depth: usize,
472 node: &'a mut InternalNode,
473 value: Option<&'a str>,
474 sensitivity: SensitivityLevel,
475 number_format: NumberFormat,
476}
477
478#[cfg_attr(
479 any(feature = "defer", feature = "initiate"),
480 derive(mesh::MeshPayload)
481)]
482#[derive(Debug, Default, Copy, Clone)]
483enum NumberFormat {
484 #[default]
485 Decimal,
486 Hex,
487 Binary,
488 Counter,
489}
490
491#[cfg(any(feature = "defer", feature = "initiate"))]
492struct RequestRoot<'a> {
493 path: &'a str,
494 node: InternalNode,
495 depth: usize,
496 value: Option<&'a str>,
497 sensitivity: SensitivityLevel,
498 number_format: NumberFormat,
499}
500
501#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Default)]
506#[cfg_attr(
507 any(feature = "defer", feature = "initiate"),
508 derive(mesh::MeshPayload)
509)]
510#[cfg_attr(
511 any(feature = "defer", feature = "initiate"),
512 mesh(package = "inspect")
513)]
514#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
515pub enum SensitivityLevel {
516 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(1))]
518 Safe,
519 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(2))]
522 #[default]
523 Unspecified,
524 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(3))]
527 Sensitive,
528}
529
530#[cfg(any(feature = "defer", feature = "initiate"))]
531impl<'a> RequestRoot<'a> {
532 fn new(
533 path: &'a str,
534 depth: usize,
535 value: Option<&'a str>,
536 sensitivity: SensitivityLevel,
537 number_format: NumberFormat,
538 ) -> Self {
539 Self {
540 path,
541 node: InternalNode::Unevaluated,
542 depth,
543 value,
544 sensitivity,
545 number_format,
546 }
547 }
548
549 fn request(&mut self) -> Request<'_> {
550 Request::new(
551 self.path,
552 self.depth,
553 &mut self.node,
554 self.value,
555 self.sensitivity,
556 self.number_format,
557 )
558 }
559}
560
561pub struct Response<'a> {
563 path: &'a str,
565 path_without_slashes: Option<&'a str>,
567 depth: usize,
568 cell: &'a mut InternalNode,
569 value: Option<&'a str>,
570 sensitivity: SensitivityLevel,
571 number_format: NumberFormat,
572}
573
574#[derive(Debug)]
575enum Action<'a, 'b> {
576 Process {
577 name: &'a str,
578 sensitivity: SensitivityLevel,
579 new_path: &'b str,
580 new_depth: usize,
581 },
582 Skip,
583 DepthExhausted {
584 name: &'a str,
585 sensitivity: SensitivityLevel,
586 },
587}
588
589impl<'a, 'b> Action<'a, 'b> {
590 fn eval(child: Child<'a>, resp: &Response<'b>) -> Self {
593 let path = resp.path_without_slashes.unwrap();
594 if resp.depth == 0 {
595 return Self::Skip;
598 }
599 if resp.sensitivity < child.sensitivity {
600 return Self::Skip;
602 }
603 if let Some(rest) = path.strip_prefix(child.name) {
604 if rest.is_empty() || rest.as_bytes()[0] == b'/' {
605 Self::Process {
608 name: child.name,
609 sensitivity: child.sensitivity,
610 new_path: rest,
611 new_depth: resp.depth,
612 }
613 } else {
614 Self::Skip
617 }
618 } else if child.name.starts_with(path) {
619 let remaining_name = if path.is_empty() {
620 child.name
622 } else {
623 if child.name.as_bytes()[path.len()] != b'/' {
624 return Self::Skip;
626 }
627 &child.name[path.len() + 1..]
629 };
630 match remaining_name.match_indices('/').nth(resp.depth - 1) {
632 None => Self::Process {
633 name: child.name,
634 sensitivity: child.sensitivity,
635 new_path: "",
636 new_depth: resp.depth - 1,
637 },
638 Some((n, _)) => Self::DepthExhausted {
639 name: &child.name[..child.name.len() - remaining_name.len() + n],
640 sensitivity: child.sensitivity,
641 },
642 }
643 } else {
644 Self::Skip
645 }
646 }
647}
648
649struct Child<'a> {
650 name: &'a str,
651 sensitivity: SensitivityLevel,
652}
653
654impl Response<'_> {
655 pub fn field<T>(&mut self, name: &str, value: T) -> &mut Self
670 where
671 T: Inspect,
672 {
673 self.inspect_field(name, &value)
674 }
675
676 pub fn sensitivity_field<T>(
678 &mut self,
679 name: &str,
680 sensitivity: SensitivityLevel,
681 value: T,
682 ) -> &mut Self
683 where
684 T: Inspect,
685 {
686 self.sensitivity_inspect_field(name, sensitivity, &value)
687 }
688
689 pub fn hex<T>(&mut self, name: &str, value: T) -> &mut Self
691 where
692 T: Inspect,
693 {
694 self.field(name, AsHex(value))
695 }
696
697 pub fn counter<T>(&mut self, name: &str, value: T) -> &mut Self
699 where
700 T: Inspect,
701 {
702 self.field(name, AsCounter(value))
703 }
704
705 pub fn sensitivity_counter<T>(
709 &mut self,
710 name: &str,
711 sensitivity: SensitivityLevel,
712 value: T,
713 ) -> &mut Self
714 where
715 T: Inspect,
716 {
717 self.sensitivity_field(name, sensitivity, AsCounter(value))
718 }
719
720 pub fn binary<T>(&mut self, name: &str, value: T) -> &mut Self
724 where
725 T: Inspect,
726 {
727 self.field(name, AsBinary(value))
728 }
729
730 pub fn display(&mut self, name: &str, value: &impl Display) -> &mut Self {
745 self.field_with(name, || value.to_string())
746 }
747
748 pub fn display_debug(&mut self, name: &str, value: &impl Debug) -> &mut Self {
758 self.field(name, format_args!("{value:?}"))
759 }
760
761 pub fn field_with<F, V>(&mut self, name: &str, f: F) -> &mut Self
763 where
764 F: FnOnce() -> V,
765 V: Inspect,
766 {
767 self.sensitivity_field_with(name, SensitivityLevel::Unspecified, f)
768 }
769
770 pub fn sensitivity_field_with<F, V>(
772 &mut self,
773 name: &str,
774 sensitivity: SensitivityLevel,
775 f: F,
776 ) -> &mut Self
777 where
778 F: FnOnce() -> V,
779 V: Inspect,
780 {
781 if let Some(req) = self.child_request(Child { name, sensitivity }) {
782 (f)().inspect(req)
783 }
784 self
785 }
786
787 pub fn field_mut<T>(&mut self, name: &str, value: &mut T) -> &mut Self
789 where
790 T: InspectMut + ?Sized,
791 {
792 self.inspect_field(name, value)
793 }
794
795 pub fn sensitivity_field_mut<T>(
797 &mut self,
798 name: &str,
799 sensitivity: SensitivityLevel,
800 value: &mut T,
801 ) -> &mut Self
802 where
803 T: InspectMut + ?Sized,
804 {
805 self.sensitivity_inspect_field(name, sensitivity, value)
806 }
807
808 pub fn field_mut_with<F, V, E>(&mut self, name: &str, f: F) -> &mut Self
810 where
811 F: FnOnce(Option<&str>) -> Result<V, E>,
812 V: Into<ValueKind>,
813 E: Into<Box<dyn core::error::Error + Send + Sync>>,
814 {
815 self.child(name, |req| match req.update() {
816 Ok(req) => match (f)(Some(req.new_value())) {
817 Ok(v) => req.succeed(v),
818 Err(err) => req.fail(err),
819 },
820 Err(req) => req.value((f)(None).ok().unwrap()),
821 })
822 }
823
824 fn child_request(&mut self, child: Child<'_>) -> Option<Request<'_>> {
825 if self.path_without_slashes.is_none() {
826 self.path_without_slashes = Some(self.path.trim_start_matches('/'));
827 }
828
829 match Action::eval(child, self) {
830 Action::Process {
831 name,
832 sensitivity,
833 new_path,
834 new_depth,
835 } => {
836 let children = self.cell.as_dir();
837 children.push(InternalEntry {
838 name: name.to_owned(),
839 node: InternalNode::Unevaluated,
840 sensitivity,
841 });
842 let entry = children.last_mut().unwrap();
843 Some(Request::new(
844 new_path,
845 new_depth,
846 &mut entry.node,
847 self.value,
848 self.sensitivity,
849 self.number_format,
850 ))
851 }
852 Action::Skip => None,
853 Action::DepthExhausted { name, sensitivity } => {
854 self.cell.as_dir().push(InternalEntry {
855 name: name.to_owned(),
856 node: InternalNode::DepthExhausted,
857 sensitivity,
858 });
859 None
860 }
861 }
862 }
863
864 fn inspect_field(&mut self, name: &str, child: impl InspectMut) -> &mut Self {
866 self.sensitivity_inspect_field(name, SensitivityLevel::Unspecified, child)
867 }
868
869 #[inline(never)] fn sensitivity_inspect_field(
872 &mut self,
873 name: &str,
874 sensitivity: SensitivityLevel,
875 mut child: impl InspectMut,
876 ) -> &mut Self {
877 if let Some(req) = self.child_request(Child { name, sensitivity }) {
878 child.inspect_mut(req);
879 }
880 self
881 }
882
883 #[cfg_attr(
888 feature = "initiate",
889 doc = r##"
890```rust
891# use inspect::{inspect, Inspect, Request};
892# use core::time::Duration;
893
894struct Child(u32);
895impl Inspect for Child {
896 fn inspect(&self, req: Request) {
897 req.respond().field("x", self.0);
898 }
899}
900
901struct Parent(Vec<Child>);
902impl Inspect for Parent {
903 fn inspect(&self, req: Request) {
904 req.respond().fields("children", self.0.iter().enumerate());
905 }
906}
907
908assert_eq!(
909 inspect(
910 "",
911 &Parent(vec![Child(5), Child(12)]),
912 )
913 .results()
914 .to_string(),
915 r#"{children: {0: {x: 5}, 1: {x: 12}}}"#
916);
917```
918"##
919 )]
920 pub fn fields<I, N, C>(&mut self, name: &str, children: I) -> &mut Self
921 where
922 I: Iterator<Item = (N, C)>,
923 N: ToString,
924 C: Inspect,
925 {
926 self.child(name, |req| {
927 let mut resp = req.respond();
928 for (name, child) in children {
929 resp.inspect_field(&name.to_string(), &child);
930 }
931 })
932 }
933
934 #[cfg_attr(
939 feature = "initiate",
940 doc = r##"
941```rust
942# use inspect::{inspect, InspectMut, Request};
943# use std::time::Duration;
944struct Child(u32);
945impl InspectMut for Child {
946 fn inspect_mut(&mut self, req: Request) {
947 req.respond().field("x", self.0);
948 }
949}
950
951struct Parent(Vec<Child>);
952impl InspectMut for Parent {
953 fn inspect_mut(&mut self, req: Request) {
954 req.respond().fields_mut("children", self.0.iter_mut().enumerate());
955 }
956}
957
958assert_eq!(
959 inspect(
960 "",
961 &mut Parent(vec![Child(5), Child(12)]),
962 )
963 .results()
964 .to_string(),
965 r#"{children: {0: {x: 5}, 1: {x: 12}}}"#
966);
967```
968"##
969 )]
970 pub fn fields_mut<I, N, C>(&mut self, name: &str, children: I) -> &mut Self
971 where
972 I: Iterator<Item = (N, C)>,
973 N: ToString,
974 C: InspectMut,
975 {
976 self.child(name, |req| {
977 let mut resp = req.respond();
978 for (name, child) in children {
979 resp.inspect_field(&name.to_string(), child);
980 }
981 })
982 }
983
984 pub fn child<F: FnOnce(Request<'_>)>(&mut self, name: &str, f: F) -> &mut Self {
989 self.sensitivity_child(name, SensitivityLevel::Unspecified, f)
990 }
991
992 pub fn sensitivity_child<F: FnOnce(Request<'_>)>(
997 &mut self,
998 name: &str,
999 sensitivity: SensitivityLevel,
1000 f: F,
1001 ) -> &mut Self {
1002 if let Some(req) = self.child_request(Child { name, sensitivity }) {
1003 f(req);
1004 }
1005 self
1006 }
1007
1008 pub fn merge(&mut self, mut child: impl InspectMut) -> &mut Self {
1011 child.inspect_mut(self.request());
1012 self
1013 }
1014
1015 pub fn request(&mut self) -> Request<'_> {
1018 let children = self.cell.as_dir();
1019 children.push(InternalEntry {
1020 name: String::new(),
1021 node: InternalNode::Unevaluated,
1022 sensitivity: SensitivityLevel::Unspecified,
1023 });
1024 let entry = children.last_mut().unwrap();
1025 Request::new(
1026 self.path,
1027 self.depth,
1028 &mut entry.node,
1029 self.value,
1030 self.sensitivity,
1031 self.number_format,
1032 )
1033 }
1034}
1035
1036impl Drop for Response<'_> {
1037 fn drop(&mut self) {
1038 if self.depth > 0 {
1039 let _ = self.cell.as_dir();
1041 } else {
1042 *self.cell = InternalNode::DepthExhausted;
1045 }
1046 }
1047}
1048
1049impl<'a> Request<'a> {
1050 fn new(
1051 path: &'a str,
1052 depth: usize,
1053 cell: &'a mut InternalNode,
1054 value: Option<&'a str>,
1055 sensitivity: SensitivityLevel,
1056 number_format: NumberFormat,
1057 ) -> Self {
1058 Self {
1059 path,
1060 depth,
1061 node: cell,
1062 value,
1063 sensitivity,
1064 number_format,
1065 }
1066 }
1067
1068 #[must_use]
1070 pub fn with_decimal_format(mut self) -> Self {
1071 self.number_format = NumberFormat::Decimal;
1072 self
1073 }
1074
1075 #[must_use]
1077 pub fn with_hex_format(mut self) -> Self {
1078 self.number_format = NumberFormat::Hex;
1079 self
1080 }
1081
1082 #[must_use]
1084 pub fn with_binary_format(mut self) -> Self {
1085 self.number_format = NumberFormat::Binary;
1086 self
1087 }
1088
1089 #[must_use]
1091 pub fn with_counter_format(mut self) -> Self {
1092 self.number_format = NumberFormat::Counter;
1093 self
1094 }
1095
1096 pub fn value(self, value: impl Into<ValueKind>) {
1098 self.value_(value.into());
1099 }
1100 fn value_(self, value: ValueKind) {
1101 let node = if self.path.is_empty() {
1102 if self.value.is_none() {
1103 InternalNode::Value(value.with_format(self.number_format))
1104 } else {
1105 InternalNode::Failed(InternalError::Immutable)
1106 }
1107 } else {
1108 InternalNode::Failed(InternalError::NotADirectory)
1109 };
1110 *self.node = node;
1111 }
1112
1113 pub fn update(self) -> Result<UpdateRequest<'a>, Self> {
1117 if let Some(value) = self.value {
1118 if !self.path.is_empty() {
1119 return Err(self);
1120 }
1121 Ok(UpdateRequest {
1122 node: self.node,
1123 value,
1124 number_format: self.number_format,
1125 })
1126 } else {
1127 Err(self)
1128 }
1129 }
1130
1131 pub fn respond(self) -> Response<'a> {
1135 Response {
1136 path: self.path,
1137 path_without_slashes: None,
1138 depth: self.depth,
1139 cell: self.node,
1140 value: self.value,
1141 sensitivity: self.sensitivity,
1142 number_format: self.number_format,
1143 }
1144 }
1145
1146 pub fn ignore(self) {
1148 *self.node = InternalNode::Ignored;
1149 }
1150
1151 pub fn is_update(&self) -> bool {
1153 self.value.is_some()
1154 }
1155
1156 pub fn sensitivity(&self) -> SensitivityLevel {
1158 self.sensitivity
1159 }
1160}
1161
1162pub struct UpdateRequest<'a> {
1164 node: &'a mut InternalNode,
1165 value: &'a str,
1166 number_format: NumberFormat,
1167}
1168
1169impl UpdateRequest<'_> {
1170 pub fn new_value(&self) -> &str {
1172 self.value
1173 }
1174
1175 pub fn succeed(self, value: impl Into<ValueKind>) {
1177 self.succeed_(value.into());
1178 }
1179 fn succeed_(self, value: ValueKind) {
1180 *self.node = InternalNode::Value(value.with_format(self.number_format));
1181 }
1182
1183 pub fn fail<E: Into<Box<dyn core::error::Error + Send + Sync>>>(self, err: E) {
1185 *self.node = InternalNode::failed(err.into());
1186 }
1187}
1188
1189#[derive(Debug, Clone, PartialEq)]
1192#[cfg_attr(
1193 any(feature = "defer", feature = "initiate"),
1194 derive(mesh::MeshPayload),
1195 mesh(package = "inspect")
1196)]
1197#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1198pub struct Value {
1199 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(1))]
1201 pub kind: ValueKind,
1202 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(2))]
1204 pub flags: ValueFlags,
1205}
1206
1207impl Value {
1208 pub fn new(kind: impl Into<ValueKind>) -> Self {
1210 Self {
1211 kind: kind.into(),
1212 flags: Default::default(),
1213 }
1214 }
1215
1216 pub fn hex(kind: impl Into<ValueKind>) -> Self {
1218 Self::new(kind).into_hex()
1219 }
1220
1221 pub fn counter(kind: impl Into<ValueKind>) -> Self {
1223 Self::new(kind).into_counter()
1224 }
1225
1226 pub fn binary(kind: impl Into<ValueKind>) -> Self {
1228 Self::new(kind).into_binary()
1229 }
1230
1231 pub fn into_hex(self) -> Self {
1233 Self {
1234 kind: self.kind,
1235 flags: self.flags.with_hex(true),
1236 }
1237 }
1238
1239 pub fn into_counter(self) -> Self {
1241 Self {
1242 kind: self.kind,
1243 flags: self.flags.with_count(true),
1244 }
1245 }
1246
1247 pub fn into_binary(self) -> Self {
1249 Self {
1250 kind: self.kind,
1251 flags: self.flags.with_binary(true),
1252 }
1253 }
1254}
1255
1256#[derive(Debug, Clone, PartialEq)]
1258#[cfg_attr(
1259 any(feature = "defer", feature = "initiate"),
1260 derive(mesh::MeshPayload),
1261 mesh(package = "inspect")
1262)]
1263#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1264pub enum ValueKind {
1265 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(1))]
1267 Signed(i64),
1268 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(2))]
1270 Unsigned(u64),
1271 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(3))]
1273 Float(f32),
1274 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(4))]
1276 Double(f64),
1277 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(5))]
1279 Bool(bool),
1280 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(6))]
1282 String(String),
1283 #[cfg_attr(any(feature = "defer", feature = "initiate"), mesh(7))]
1285 Bytes(Vec<u8>),
1286}
1287
1288impl ValueKind {
1289 fn with_format(self, format: NumberFormat) -> Value {
1290 match self {
1291 Self::Signed(_) | Self::Unsigned(_) => match format {
1292 NumberFormat::Decimal => Value::new(self),
1293 NumberFormat::Hex => Value::hex(self).into_hex(),
1294 NumberFormat::Binary => Value::binary(self).into_binary(),
1295 NumberFormat::Counter => Value::counter(self).into_counter(),
1296 },
1297 v => v.into(),
1298 }
1299 }
1300}
1301
1302#[bitfield_struct::bitfield(u64)]
1304#[derive(PartialEq)]
1305#[cfg_attr(
1306 any(feature = "defer", feature = "initiate"),
1307 derive(mesh::MeshPayload),
1308 mesh(package = "inspect")
1309)]
1310#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
1311pub struct ValueFlags {
1312 pub hex: bool,
1314 pub count: bool,
1316 pub binary: bool,
1318
1319 #[bits(61)]
1320 _reserved: u64,
1321}
1322
1323impl Display for Value {
1324 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1325 match &self.kind {
1326 ValueKind::Signed(n) => {
1327 if self.flags.hex() {
1328 write!(f, "{:#x}", &n)
1329 } else if self.flags.binary() {
1330 write!(f, "{:#b}", &n)
1331 } else {
1332 Display::fmt(&n, f)
1333 }
1334 }
1335 ValueKind::Unsigned(n) => {
1336 if self.flags.hex() {
1337 write!(f, "{:#x}", &n)
1338 } else if self.flags.binary() {
1339 write!(f, "{:#b}", &n)
1340 } else {
1341 Display::fmt(&n, f)
1342 }
1343 }
1344 ValueKind::Float(n) => Display::fmt(&n, f),
1345 ValueKind::Double(n) => Display::fmt(&n, f),
1346 ValueKind::Bool(b) => Display::fmt(&b, f),
1347 ValueKind::String(s) => Debug::fmt(&s, f),
1348 ValueKind::Bytes(b) => {
1349 f.write_str("<")?;
1350 for &b in b {
1351 write!(f, "{:02x}", b)?;
1352 }
1353 f.write_str(">")
1354 }
1355 }
1356 }
1357}
1358
1359impl<T> From<T> for Value
1360where
1361 ValueKind: From<T>,
1362{
1363 fn from(v: T) -> Self {
1364 Value {
1365 kind: v.into(),
1366 flags: Default::default(),
1367 }
1368 }
1369}
1370
1371macro_rules! from_as {
1372 ($x:ident, $to:ty, $($ty:ty),* $(,)?) => {
1373 $(
1374 impl From<$ty> for ValueKind {
1375 fn from(v: $ty) -> Self {
1376 Self::$x(v as $to)
1377 }
1378 }
1379 )*
1380 };
1381}
1382
1383from_as!(Unsigned, u64, u8, u16, u32, u64, usize);
1384from_as!(Signed, i64, i8, i16, i32, i64, isize);
1385
1386macro_rules! from_get {
1387 ($x:ident, $to:ty, $($ty:ty),* $(,)?) => {
1388 $(
1389 impl From<$ty> for ValueKind {
1390 fn from(v: $ty) -> Self {
1391 Self::$x(v.get() as $to)
1392 }
1393 }
1394 )*
1395 };
1396}
1397
1398from_get!(
1399 Unsigned,
1400 u64,
1401 core::num::NonZeroU8,
1402 core::num::NonZeroU16,
1403 core::num::NonZeroU32,
1404 core::num::NonZeroU64,
1405 core::num::NonZeroUsize
1406);
1407from_get!(
1408 Signed,
1409 i64,
1410 core::num::NonZeroI8,
1411 core::num::NonZeroI16,
1412 core::num::NonZeroI32,
1413 core::num::NonZeroI64,
1414 core::num::NonZeroIsize
1415);
1416
1417impl From<f32> for ValueKind {
1418 fn from(v: f32) -> Self {
1419 Self::Float(v)
1420 }
1421}
1422
1423impl From<f64> for ValueKind {
1424 fn from(v: f64) -> Self {
1425 Self::Double(v)
1426 }
1427}
1428
1429impl From<bool> for ValueKind {
1430 fn from(v: bool) -> Self {
1431 Self::Bool(v)
1432 }
1433}
1434
1435impl From<&'_ str> for ValueKind {
1436 fn from(v: &str) -> Self {
1437 Self::String(v.to_owned())
1438 }
1439}
1440
1441impl From<String> for ValueKind {
1442 fn from(v: String) -> Self {
1443 Self::String(v)
1444 }
1445}
1446
1447#[cfg(feature = "std")]
1448impl From<&'_ std::ffi::CStr> for ValueKind {
1449 fn from(v: &std::ffi::CStr) -> Self {
1450 Self::String(v.to_string_lossy().to_string())
1451 }
1452}
1453
1454#[cfg(feature = "std")]
1455impl From<std::ffi::CString> for ValueKind {
1456 fn from(v: std::ffi::CString) -> Self {
1457 Self::String(v.to_string_lossy().to_string())
1458 }
1459}
1460
1461impl From<&'_ [u8]> for ValueKind {
1462 fn from(v: &[u8]) -> Self {
1463 Self::Bytes(v.to_vec())
1464 }
1465}
1466
1467impl<const N: usize> From<[u8; N]> for ValueKind {
1468 fn from(v: [u8; N]) -> Self {
1469 Self::Bytes(v.to_vec())
1470 }
1471}
1472
1473impl From<Vec<u8>> for ValueKind {
1474 fn from(v: Vec<u8>) -> Self {
1475 Self::Bytes(v)
1476 }
1477}
1478
1479impl From<Arguments<'_>> for ValueKind {
1480 fn from(v: Arguments<'_>) -> Self {
1481 Self::String(v.to_string())
1482 }
1483}
1484
1485impl<T: Into<ValueKind> + Clone> From<&'_ T> for ValueKind {
1486 fn from(v: &T) -> Self {
1487 v.clone().into()
1488 }
1489}
1490
1491impl Inspect for () {
1492 fn inspect(&self, req: Request<'_>) {
1493 req.respond();
1494 }
1495}
1496
1497impl InspectMut for () {
1498 fn inspect_mut(&mut self, req: Request<'_>) {
1499 req.respond();
1500 }
1501}
1502
1503macro_rules! inspect_value_immut {
1504 ($($(#[$attr:meta])* $ty:ty),* $(,)?) => {
1505 $(
1506 $(#[$attr])*
1507 impl Inspect for $ty {
1508 fn inspect(&self, req: Request<'_>) {
1509 req.value(self)
1510 }
1511 }
1512 )*
1513 };
1514}
1515
1516macro_rules! inspect_value {
1517 ($($(#[$attr:meta])* $ty:ty),* $(,)?) => {
1518 inspect_value_immut!($($ty,)*);
1519 $(
1520 $(#[$attr])*
1521 impl InspectMut for $ty {
1522 fn inspect_mut(&mut self, req: Request<'_>) {
1523 match req.update() {
1524 Ok(req) => match req.new_value().parse::<Self>() {
1525 Ok(v) => {
1526 *self = v.clone();
1527 req.succeed(v);
1528 }
1529 Err(err) => req.fail(err),
1530 }
1531 Err(req) => req.value(&*self),
1532 }
1533 }
1534 }
1535 )*
1536 };
1537}
1538
1539inspect_value_immut! {
1540 str,
1541 #[cfg(feature = "std")]
1542 std::ffi::CStr,
1543 #[cfg(feature = "std")]
1544 std::ffi::CString,
1545 [u8],
1546 Vec<u8>,
1547 Arguments<'_>,
1548}
1549
1550inspect_value! {
1551 u8,
1552 u16,
1553 u32,
1554 u64,
1555 usize,
1556 i8,
1557 i16,
1558 i32,
1559 i64,
1560 isize,
1561 core::num::NonZeroU8,
1562 core::num::NonZeroU16,
1563 core::num::NonZeroU32,
1564 core::num::NonZeroU64,
1565 core::num::NonZeroUsize,
1566 core::num::NonZeroI8,
1567 core::num::NonZeroI16,
1568 core::num::NonZeroI32,
1569 core::num::NonZeroI64,
1570 core::num::NonZeroIsize,
1571 f32,
1572 f64,
1573 bool,
1574 String,
1575}
1576
1577impl<const N: usize> Inspect for [u8; N] {
1578 fn inspect(&self, req: Request<'_>) {
1579 self.as_slice().inspect(req)
1580 }
1581}
1582
1583pub struct AtomicMut<T>(pub T);
1586
1587macro_rules! inspect_atomic_value {
1588 ($(($ty:ident, $backing:ty)),* $(,)?) => {
1589 $(
1590
1591 impl Inspect for core::sync::atomic::$ty {
1592 fn inspect(&self, req: Request<'_>) {
1593 req.value(self.load(core::sync::atomic::Ordering::Relaxed))
1594 }
1595 }
1596
1597 impl Inspect for AtomicMut<&core::sync::atomic::$ty> {
1602 fn inspect(&self, req: Request<'_>) {
1603 let mut value = self.0.load(core::sync::atomic::Ordering::Relaxed);
1604 let is_update = req.is_update();
1605 value.inspect_mut(req);
1606 if is_update {
1607 self.0.store(value, core::sync::atomic::Ordering::Relaxed);
1608 }
1609 }
1610 }
1611
1612 )*
1613 };
1614}
1615
1616inspect_atomic_value! {
1617 (AtomicBool, bool),
1618 (AtomicU8, u8),
1619 (AtomicU16, u16),
1620 (AtomicU32, u32),
1621 (AtomicU64, u64),
1622 (AtomicUsize, usize),
1623 (AtomicI8, i8),
1624 (AtomicI16, i16),
1625 (AtomicI32, i32),
1626 (AtomicI64, i64),
1627 (AtomicIsize, isize),
1628}
1629
1630impl<T: Inspect> Inspect for Wrapping<T> {
1631 fn inspect(&self, req: Request<'_>) {
1632 self.0.inspect(req)
1633 }
1634}
1635
1636impl<T: InspectMut> InspectMut for Wrapping<T> {
1637 fn inspect_mut(&mut self, req: Request<'_>) {
1638 self.0.inspect_mut(req)
1639 }
1640}
1641
1642#[cfg(feature = "filepath")]
1643impl Inspect for std::fs::File {
1644 fn inspect(&self, req: Request<'_>) {
1645 use filepath::FilePath;
1646 if let Ok(path) = self.path() {
1647 req.value(path.display().to_string());
1648 } else {
1649 req.ignore();
1650 }
1651 }
1652}
1653
1654pub struct AsDisplay<T>(pub T);
1657
1658impl<T: Display> Inspect for AsDisplay<T> {
1659 fn inspect(&self, req: Request<'_>) {
1660 req.value(self.0.to_string())
1661 }
1662}
1663
1664pub struct AsDebug<T>(pub T);
1667
1668impl<T: Debug> InspectMut for AsDebug<T> {
1669 fn inspect_mut(&mut self, req: Request<'_>) {
1670 req.value(format!("{:?}", self.0))
1671 }
1672}
1673
1674impl<T: Debug> Inspect for AsDebug<T> {
1675 fn inspect(&self, req: Request<'_>) {
1676 req.value(format!("{:?}", self.0))
1677 }
1678}
1679
1680macro_rules! hexbincount {
1681 ($tr:ident, $fmt:expr) => {
1682 impl<T: Inspect> Inspect for $tr<T> {
1683 fn inspect(&self, mut req: Request<'_>) {
1684 req.number_format = $fmt;
1685 self.0.inspect(req);
1686 }
1687 }
1688
1689 impl<T: InspectMut> InspectMut for $tr<T> {
1690 fn inspect_mut(&mut self, mut req: Request<'_>) {
1691 req.number_format = $fmt;
1692 self.0.inspect_mut(req);
1693 }
1694 }
1695 };
1696}
1697
1698#[derive(Clone, Copy)]
1701pub struct AsHex<T>(pub T);
1702
1703hexbincount!(AsHex, NumberFormat::Hex);
1704
1705pub struct AsBinary<T>(pub T);
1708
1709hexbincount!(AsBinary, NumberFormat::Binary);
1710
1711pub struct AsCounter<T>(pub T);
1714
1715hexbincount!(AsCounter, NumberFormat::Counter);
1716
1717pub struct AsBytes<T>(pub T);
1722
1723impl<T> Inspect for AsBytes<T>
1724where
1725 T: Clone + IntoIterator,
1726 Vec<u8>: Extend<T::Item>,
1727{
1728 fn inspect(&self, req: Request<'_>) {
1729 let mut v = Vec::new();
1730 v.extend(self.0.clone());
1731 req.value(ValueKind::Bytes(v))
1732 }
1733}
1734
1735#[doc(hidden)]
1736pub mod derive_helpers {
1737 pub fn call<T, F, R>(t: T, f: F) -> R
1739 where
1740 F: Fn(T) -> R,
1741 {
1742 f(t)
1743 }
1744}
1745
1746#[derive(Default)]
1754pub struct Iterated<I>(I);
1755
1756pub fn iter_by_key<I, K, V>(iter: impl IntoIterator<IntoIter = I>) -> Iterated<I>
1769where
1770 I: Clone + Iterator<Item = (K, V)>,
1771{
1772 Iterated(iter.into_iter())
1773}
1774
1775pub fn iter_by_index<I, V>(
1788 iter: impl IntoIterator<IntoIter = I>,
1789) -> Iterated<core::iter::Enumerate<I>>
1790where
1791 I: Clone + Iterator<Item = V>,
1792{
1793 iter_by_key(iter.into_iter().enumerate())
1794}
1795
1796impl<I, K, V> Iterated<I>
1797where
1798 I: Clone + Iterator<Item = (K, V)>,
1799{
1800 pub fn map_key<F, K2>(self, mut f: F) -> Iterated<impl Clone + Iterator<Item = (K2, V)>>
1812 where
1813 F: Clone + FnMut(K) -> K2,
1814 {
1815 iter_by_key(self.0.map(move |(k, v)| (f(k), v)))
1816 }
1817
1818 pub fn map_value<F, V2>(self, mut f: F) -> Iterated<impl Clone + Iterator<Item = (K, V2)>>
1830 where
1831 F: Clone + FnMut(V) -> V2,
1832 {
1833 iter_by_key(self.0.map(move |(k, v)| (k, f(v))))
1834 }
1835
1836 pub fn prefix<'a>(
1848 self,
1849 prefix: &'a str,
1850 ) -> Iterated<impl 'a + Clone + Iterator<Item = (String, V)>>
1851 where
1852 K: Display,
1853 I: 'a,
1854 K: 'a,
1855 V: 'a,
1856 {
1857 self.map_key(move |k| format!("{}{}", prefix, k))
1858 }
1859}
1860
1861impl<I, K, V> Inspect for Iterated<I>
1862where
1863 I: Clone + Iterator<Item = (K, V)>,
1864 K: ToString,
1865 V: Inspect,
1866{
1867 fn inspect(&self, req: Request<'_>) {
1868 let mut resp = req.respond();
1869 for (name, value) in self.0.clone() {
1870 resp.field(&name.to_string(), value);
1871 }
1872 }
1873}
1874
1875#[derive(Debug)]
1876#[cfg_attr(
1877 any(feature = "defer", feature = "initiate"),
1878 derive(mesh::MeshPayload)
1879)]
1880#[cfg_attr(not(any(feature = "defer", feature = "initiate")), expect(dead_code))]
1881enum InternalNode {
1882 Unevaluated,
1883 Failed(InternalError),
1884 DepthExhausted,
1885 Value(Value),
1886 Dir(Vec<InternalEntry>),
1887 Ignored,
1888 #[cfg(any(feature = "defer", feature = "initiate"))]
1889 Deferred(mesh::OneshotReceiver<InternalNode>),
1890 #[cfg(any(feature = "defer", feature = "initiate"))]
1891 DirResolved(Vec<InternalEntry>),
1892}
1893
1894#[derive(Debug)]
1895#[cfg_attr(
1896 any(feature = "defer", feature = "initiate"),
1897 derive(mesh::MeshPayload)
1898)]
1899#[cfg_attr(not(any(feature = "defer", feature = "initiate")), expect(dead_code))]
1902struct InternalEntry {
1903 name: String,
1904 node: InternalNode,
1905 sensitivity: SensitivityLevel,
1906}
1907
1908impl InternalNode {
1909 fn as_dir(&mut self) -> &mut Vec<InternalEntry> {
1910 match self {
1911 Self::Dir(children) => children,
1912 _ => {
1913 *self = Self::Dir(Vec::new());
1914 let Self::Dir(children) = self else {
1915 unreachable!()
1916 };
1917 children
1918 }
1919 }
1920 }
1921}
1922
1923#[derive(Debug)]
1924#[cfg_attr(
1925 any(feature = "defer", feature = "initiate"),
1926 derive(mesh::MeshPayload)
1927)]
1928#[cfg_attr(not(any(feature = "defer", feature = "initiate")), expect(dead_code))]
1929enum InternalError {
1930 Immutable,
1931 Update(String),
1932 NotADirectory,
1933 Unresolved,
1934 Mesh(String),
1935}
1936
1937impl InternalNode {
1938 fn failed(err: Box<dyn core::error::Error + Send + Sync>) -> Self {
1939 use core::fmt::Write;
1940
1941 let mut s = err.to_string();
1942 let mut src = err.source();
1943 while let Some(err) = src {
1944 src = err.source();
1945 let _ = write!(&mut s, ": {err}");
1946 }
1947 InternalNode::Failed(InternalError::Update(s))
1948 }
1949}
1950
1951pub trait InspectMut {
1956 fn inspect_mut(&mut self, req: Request<'_>);
1958}
1959
1960impl<T: Inspect + ?Sized> InspectMut for &'_ T {
1961 fn inspect_mut(&mut self, req: Request<'_>) {
1962 self.inspect(req);
1963 }
1964}
1965
1966impl<T: InspectMut + ?Sized> InspectMut for &'_ mut T {
1967 fn inspect_mut(&mut self, req: Request<'_>) {
1968 T::inspect_mut(*self, req)
1969 }
1970}
1971
1972impl<T: InspectMut + ?Sized> InspectMut for Box<T> {
1973 fn inspect_mut(&mut self, req: Request<'_>) {
1974 T::inspect_mut(self.as_mut(), req)
1975 }
1976}
1977
1978impl<T: InspectMut> InspectMut for Option<T> {
1979 fn inspect_mut(&mut self, req: Request<'_>) {
1980 if let Some(val) = self {
1981 val.inspect_mut(req);
1982 } else {
1983 req.ignore();
1984 }
1985 }
1986}
1987
1988pub trait Inspect {
2059 fn inspect(&self, req: Request<'_>);
2061}
2062
2063impl<T: Inspect + ?Sized> Inspect for &'_ T {
2064 fn inspect(&self, req: Request<'_>) {
2065 T::inspect(*self, req)
2066 }
2067}
2068
2069impl<T: Inspect + ?Sized> Inspect for &'_ mut T {
2070 fn inspect(&self, req: Request<'_>) {
2071 T::inspect(*self, req)
2072 }
2073}
2074
2075impl<T: Inspect + ?Sized> Inspect for Box<T> {
2076 fn inspect(&self, req: Request<'_>) {
2077 T::inspect(self.as_ref(), req)
2078 }
2079}
2080
2081impl<T: Inspect + ?Sized> Inspect for Rc<T> {
2082 fn inspect(&self, req: Request<'_>) {
2083 T::inspect(self.as_ref(), req)
2084 }
2085}
2086
2087impl<T: Inspect + ?Sized> Inspect for Arc<T> {
2088 fn inspect(&self, req: Request<'_>) {
2089 T::inspect(self.as_ref(), req)
2090 }
2091}
2092
2093impl<T: Inspect + ?Sized> Inspect for parking_lot::Mutex<T> {
2094 fn inspect(&self, req: Request<'_>) {
2095 T::inspect(&*self.lock(), req)
2096 }
2097}
2098
2099impl<T: Inspect + ?Sized> Inspect for parking_lot::RwLock<T> {
2100 fn inspect(&self, req: Request<'_>) {
2101 T::inspect(&*self.read(), req)
2102 }
2103}
2104
2105#[cfg(feature = "std")]
2106impl<T: Inspect> Inspect for std::sync::OnceLock<T> {
2107 fn inspect(&self, req: Request<'_>) {
2108 <_ as Inspect>::inspect(&self.get(), req)
2109 }
2110}
2111
2112impl<T: Inspect> Inspect for Option<T> {
2113 fn inspect(&self, req: Request<'_>) {
2114 if let Some(val) = self {
2115 val.inspect(req);
2116 } else {
2117 req.ignore();
2118 }
2119 }
2120}
2121
2122impl<T: ?Sized + Inspect + ToOwned> Inspect for Cow<'_, T> {
2123 fn inspect(&self, req: Request<'_>) {
2124 self.as_ref().inspect(req)
2125 }
2126}
2127
2128impl<T> Inspect for *mut T {
2129 fn inspect(&self, req: Request<'_>) {
2130 req.with_hex_format().value(*self as usize)
2131 }
2132}
2133
2134impl<T> Inspect for *const T {
2135 fn inspect(&self, req: Request<'_>) {
2136 req.with_hex_format().value(*self as usize)
2137 }
2138}
2139
2140impl Inspect for ValueKind {
2141 fn inspect(&self, req: Request<'_>) {
2142 req.value(self.clone());
2143 }
2144}
2145
2146impl Inspect for Value {
2147 fn inspect(&self, req: Request<'_>) {
2148 let req = if self.flags.count() {
2149 req.with_counter_format()
2150 } else if self.flags.hex() {
2151 req.with_hex_format()
2152 } else if self.flags.binary() {
2153 req.with_binary_format()
2154 } else {
2155 req
2156 };
2157 req.value(self.kind.clone());
2158 }
2159}
2160
2161pub struct Adhoc<F>(F);
2163
2164impl<F> InspectMut for Adhoc<F>
2165where
2166 F: FnMut(Request<'_>),
2167{
2168 fn inspect_mut(&mut self, req: Request<'_>) {
2169 (self.0)(req)
2170 }
2171}
2172
2173impl<F> Inspect for Adhoc<F>
2174where
2175 F: Fn(Request<'_>),
2176{
2177 fn inspect(&self, req: Request<'_>) {
2178 (self.0)(req)
2179 }
2180}
2181
2182pub fn adhoc<F>(f: F) -> Adhoc<F>
2185where
2186 F: Fn(Request<'_>),
2187{
2188 Adhoc(f)
2189}
2190
2191pub fn adhoc_mut<F>(f: F) -> Adhoc<F>
2194where
2195 F: FnMut(Request<'_>),
2196{
2197 Adhoc(f)
2198}
2199
2200#[cfg(all(test, feature = "derive", feature = "initiate"))]
2201mod tests {
2202 use crate::AsBytes;
2203 use crate::AtomicMut;
2204 use crate::Error;
2205 use crate::Inspect;
2206 use crate::InspectMut;
2207 use crate::InspectionBuilder;
2208 use crate::Node;
2209 use crate::Request;
2210 use crate::SensitivityLevel;
2211 use crate::ValueKind;
2212 use crate::adhoc;
2213 use crate::adhoc_mut;
2214 use crate::inspect;
2215 use crate::update;
2216 use alloc::boxed::Box;
2217 use alloc::string::String;
2218 use alloc::string::ToString;
2219 use alloc::vec;
2220 use alloc::vec::Vec;
2221 use core::time::Duration;
2222 use expect_test::Expect;
2223 use expect_test::expect;
2224 use futures::FutureExt;
2225 use pal_async::DefaultDriver;
2226 use pal_async::async_test;
2227 use pal_async::timer::Instant;
2228 use pal_async::timer::PolledTimer;
2229
2230 fn expected_node(node: Node, expect: Expect) -> Node {
2231 expect.assert_eq(&std::format!("{node:#}"));
2232 node
2233 }
2234
2235 async fn inspect_async(
2236 driver: &DefaultDriver,
2237 path: &str,
2238 depth: Option<usize>,
2239 timeout: Duration,
2240 obj: impl InspectMut,
2241 ) -> Node {
2242 let deadline = Instant::now() + timeout;
2243 let mut result = InspectionBuilder::new(path).depth(depth).inspect(obj);
2244 let mut timer = PolledTimer::new(driver);
2245 futures::select! { _ = result.resolve().fuse() => {}
2247 _ = timer.sleep_until(deadline).fuse() => {}
2248 };
2249 result.results()
2250 }
2251
2252 async fn inspect_async_expect(
2253 driver: &DefaultDriver,
2254 path: &str,
2255 depth: Option<usize>,
2256 timeout: Duration,
2257 obj: impl InspectMut,
2258 expect: Expect,
2259 ) -> Node {
2260 expected_node(
2261 inspect_async(driver, path, depth, timeout, obj).await,
2262 expect,
2263 )
2264 }
2265
2266 fn inspect_sync(path: &str, depth: Option<usize>, obj: impl InspectMut) -> Node {
2267 let mut result = InspectionBuilder::new(path).depth(depth).inspect(obj);
2268 result.resolve().now_or_never();
2269 result.results()
2270 }
2271
2272 fn inspect_sync_expect(
2273 path: &str,
2274 depth: Option<usize>,
2275 obj: impl InspectMut,
2276 expect: Expect,
2277 ) -> Node {
2278 expected_node(inspect_sync(path, depth, obj), expect)
2279 }
2280
2281 #[derive(Default)]
2282 struct Foo {
2283 xx: u32,
2284 xy: bool,
2285 xz: Vec<Foo>,
2286 }
2287
2288 impl Inspect for Foo {
2289 fn inspect(&self, req: Request<'_>) {
2290 let mut resp = req.respond();
2291 resp.field("xx", self.xx)
2292 .field("xy", self.xy)
2293 .fields("", self.xz.iter().enumerate());
2294 }
2295 }
2296
2297 #[test]
2298 fn test() {
2299 let f = Foo {
2300 xx: 1,
2301 xy: true,
2302 xz: vec![
2303 Foo {
2304 xx: 3,
2305 xy: false,
2306 xz: vec![],
2307 },
2308 Foo {
2309 xx: 5,
2310 xy: true,
2311 xz: vec![],
2312 },
2313 ],
2314 };
2315 let node = inspect_sync_expect(
2316 "",
2317 None,
2318 &f,
2319 expect!([r#"
2320 {
2321 0: {
2322 xx: 3,
2323 xy: false,
2324 },
2325 1: {
2326 xx: 5,
2327 xy: true,
2328 },
2329 xx: 1,
2330 xy: true,
2331 }"#]),
2332 );
2333 let expected_json =
2334 expect!([r#"{"0":{"xx":3,"xy":false},"1":{"xx":5,"xy":true},"xx":1,"xy":true}"#]);
2335 expected_json.assert_eq(&node.json().to_string());
2336 }
2337
2338 #[async_test]
2339 async fn test_deferred(driver: DefaultDriver) {
2340 inspect_async_expect(
2341 &driver,
2342 "",
2343 None,
2344 Duration::from_secs(1),
2345 adhoc(|req| {
2346 let foo = req.defer();
2347 std::thread::spawn(|| foo.inspect(&Foo::default()));
2348 }),
2349 expect!([r#"
2350 {
2351 xx: 0,
2352 xy: false,
2353 }"#]),
2354 )
2355 .await;
2356 }
2357
2358 #[async_test]
2359 async fn test_dropped(driver: DefaultDriver) {
2360 inspect_async_expect(
2361 &driver,
2362 "",
2363 None,
2364 Duration::from_secs(86400),
2365 adhoc(|req| {
2366 drop(req.defer());
2367 }),
2368 expect!("error (unresolved)"),
2369 )
2370 .await;
2371 }
2372
2373 #[test]
2374 fn test_path() {
2375 let mut obj = adhoc(|req| {
2376 req.respond().field("a", 1).child("b", |req| {
2377 req.respond().field("c", 2).field("d", 2).child("e", |req| {
2378 req.respond();
2379 });
2380 });
2381 });
2382 inspect_sync_expect("a", None, &mut obj, expect!("1"));
2383 inspect_sync_expect("///a", None, &mut obj, expect!("1"));
2384 inspect_sync_expect(
2385 "b",
2386 None,
2387 &mut obj,
2388 expect!([r#"
2389 {
2390 c: 2,
2391 d: 2,
2392 e: {},
2393 }"#]),
2394 );
2395 inspect_sync_expect("b/c", None, &mut obj, expect!("2"));
2396 inspect_sync_expect("b////c", None, &mut obj, expect!("2"));
2397 inspect_sync_expect("b/c/", None, &mut obj, expect!("error (not a directory)"));
2398 inspect_sync_expect("b/c/x", None, &mut obj, expect!("error (not a directory)"));
2399 inspect_sync_expect("b/e", None, &mut obj, expect!("{}"));
2400 inspect_sync_expect("b/e/", None, &mut obj, expect!("{}"));
2401 inspect_sync_expect("b/e///", None, &mut obj, expect!("{}"));
2402 inspect_sync_expect("b/f", None, &mut obj, expect!("error (not found)"));
2403 }
2404
2405 #[async_test]
2406 async fn test_timeout(driver: DefaultDriver) {
2407 inspect_async_expect(
2408 &driver,
2409 "",
2410 None,
2411 Duration::from_millis(10),
2412 adhoc(|req| {
2413 let foo = req.defer();
2414 std::thread::spawn(|| {
2415 std::thread::sleep(Duration::from_millis(250));
2416 foo.inspect(&Foo::default())
2417 });
2418 }),
2419 expect!("error (unresolved)"),
2420 )
2421 .await;
2422 }
2423
2424 #[test]
2425 fn test_merge() {
2426 let mut obj = adhoc(|req| {
2427 req.respond()
2428 .field("a", 1)
2429 .request()
2430 .respond()
2431 .field("b", 2);
2432 });
2433
2434 inspect_sync_expect(
2435 "",
2436 None,
2437 &mut obj,
2438 expect!([r#"
2439 {
2440 a: 1,
2441 b: 2,
2442 }"#]),
2443 );
2444 inspect_sync_expect("a", None, &mut obj, expect!("1"));
2445 inspect_sync_expect("b", None, &mut obj, expect!("2"));
2446 inspect_sync_expect("c", None, &mut obj, expect!("error (not found)"));
2447 }
2448
2449 #[test]
2450 fn test_named_merge() {
2451 let mut obj = adhoc(|req| {
2452 req.respond()
2453 .field("a", 1)
2454 .field("a", 2)
2455 .child("x", |req| {
2456 req.respond().field("b", 3).child("c", |req| {
2457 req.respond().field("y", 4);
2458 });
2459 })
2460 .child("x", |req| {
2461 req.respond().field("b", 4).child("d", |req| {
2462 req.respond().field("y", 5);
2463 });
2464 });
2465 });
2466
2467 inspect_sync_expect(
2468 "",
2469 None,
2470 &mut obj,
2471 expect!([r#"
2472 {
2473 a: 2,
2474 x: {
2475 b: 4,
2476 c: {
2477 y: 4,
2478 },
2479 d: {
2480 y: 5,
2481 },
2482 },
2483 }"#]),
2484 );
2485 inspect_sync_expect(
2486 "x",
2487 None,
2488 &mut obj,
2489 expect!([r#"
2490 {
2491 b: 4,
2492 c: {
2493 y: 4,
2494 },
2495 d: {
2496 y: 5,
2497 },
2498 }"#]),
2499 );
2500 }
2501
2502 #[test]
2503 fn test_update() {
2504 struct Foo {
2505 immut: u32,
2506 mut_: u32,
2507 child: Option<Box<Foo>>,
2508 }
2509
2510 impl InspectMut for Foo {
2511 fn inspect_mut(&mut self, req: Request<'_>) {
2512 let mut resp = req.respond();
2513 resp.field("immut", self.immut)
2514 .field_mut("mut", &mut self.mut_)
2515 .field_mut("child", &mut self.child);
2516 }
2517 }
2518
2519 let mut foo = Foo {
2520 immut: 1,
2521 mut_: 2,
2522 child: Some(Box::new(Foo {
2523 immut: 101,
2524 mut_: 102,
2525 child: None,
2526 })),
2527 };
2528 assert_eq!(
2529 update("immut", "12", &mut foo)
2530 .now_or_never()
2531 .unwrap()
2532 .unwrap_err(),
2533 Error::Immutable
2534 );
2535 assert_eq!(
2536 update("mut/", "4", &mut foo)
2537 .now_or_never()
2538 .unwrap()
2539 .unwrap_err(),
2540 Error::NotADirectory
2541 );
2542 assert_eq!(
2543 update("mut", "3", &mut foo)
2544 .now_or_never()
2545 .unwrap()
2546 .unwrap()
2547 .kind,
2548 ValueKind::Unsigned(3)
2549 );
2550 assert_eq!(
2551 update("//child/mut", "103", &mut foo)
2552 .now_or_never()
2553 .unwrap()
2554 .unwrap()
2555 .kind,
2556 ValueKind::Unsigned(103)
2557 );
2558 assert_eq!(foo.mut_, 3);
2559 assert_eq!(foo.child.as_ref().unwrap().mut_, 103);
2560 }
2561
2562 #[test]
2563 fn test_nest() {
2564 let mut obj = adhoc(|req| {
2565 req.respond().field("x/a/b", 1).field("x/a/c", 2);
2566 });
2567
2568 inspect_sync_expect(
2569 "",
2570 None,
2571 &mut obj,
2572 expect!([r#"
2573 {
2574 x: {
2575 a: {
2576 b: 1,
2577 c: 2,
2578 },
2579 },
2580 }"#]),
2581 );
2582 inspect_sync_expect(
2583 "x/a",
2584 None,
2585 &mut obj,
2586 expect!([r#"
2587 {
2588 b: 1,
2589 c: 2,
2590 }"#]),
2591 );
2592 inspect_sync_expect(
2593 "x",
2594 Some(0),
2595 &mut obj,
2596 expect!([r#"
2597 {
2598 a: _,
2599 }"#]),
2600 );
2601 inspect_sync_expect(
2602 "x",
2603 Some(2),
2604 &mut obj,
2605 expect!([r#"
2606 {
2607 a: {
2608 b: 1,
2609 c: 2,
2610 },
2611 }"#]),
2612 );
2613 }
2614
2615 #[test]
2616 fn test_depth() {
2617 let mut obj = adhoc(|req| {
2618 req.respond()
2619 .field("1a", 0)
2620 .field("1b", 0)
2621 .field("1c", 0)
2622 .child("1d", |req| {
2623 req.respond().field("2a", 0).child("2b", |req| {
2624 req.respond().child("3a", |req| {
2625 req.respond().field_with("xxx", || -> u32 { panic!() });
2626 });
2627 });
2628 })
2629 .field("1d/2b/3b", 0);
2630 });
2631
2632 inspect_sync_expect(
2633 "1d",
2634 Some(0),
2635 &mut obj,
2636 expect!([r#"
2637 {
2638 2a: 0,
2639 2b: _,
2640 }"#]),
2641 );
2642 inspect_sync_expect(
2643 "",
2644 Some(0),
2645 &mut obj,
2646 expect!([r#"
2647 {
2648 1a: 0,
2649 1b: 0,
2650 1c: 0,
2651 1d: _,
2652 }"#]),
2653 );
2654 inspect_sync_expect(
2655 "",
2656 Some(1),
2657 &mut obj,
2658 expect!([r#"
2659 {
2660 1a: 0,
2661 1b: 0,
2662 1c: 0,
2663 1d: {
2664 2a: 0,
2665 2b: _,
2666 },
2667 }"#]),
2668 );
2669 }
2670
2671 #[test]
2672 fn test_hex() {
2673 let mut obj = adhoc(|req| {
2674 req.respond().hex("a", 0x1234);
2675 });
2676 inspect_sync_expect(
2677 "",
2678 Some(0),
2679 &mut obj,
2680 expect!([r#"
2681 {
2682 a: 0x1234,
2683 }"#]),
2684 );
2685 }
2686
2687 #[test]
2688 fn test_binary() {
2689 let mut obj = adhoc(|req| {
2690 req.respond().binary("a", 0b1001000110100);
2691 });
2692 inspect_sync_expect(
2693 "",
2694 Some(0),
2695 &mut obj,
2696 expect!([r#"
2697 {
2698 a: 0b1001000110100,
2699 }"#]),
2700 );
2701 }
2702
2703 #[test]
2704 fn test_since() {
2705 let mut n = 500_u32;
2706 let mut b = false;
2707 let mut obj = adhoc_mut(|req| {
2708 req.respond()
2709 .counter("c", n)
2710 .field("f", n)
2711 .child("d", |req| {
2712 let mut resp = req.respond();
2713 if !b {
2714 resp.field("1_a", true).field("1_b", true);
2715 } else {
2716 resp.field("1_c", true);
2717 }
2718 resp.field("2", true).counter("3", n);
2719 if !b {
2720 resp.field("4_a", true);
2721 } else {
2722 resp.field("4_b", true).field("4_c", true);
2723 }
2724 });
2725 n += 100;
2726 b = true;
2727 });
2728 let old = inspect_sync("", Some(1), &mut obj);
2729 let new = inspect_sync("", Some(1), &mut obj);
2730
2731 let diff = new.since(&old, Duration::from_secs(2));
2732
2733 expected_node(
2734 diff,
2735 expect!([r#"
2736 {
2737 c: 50,
2738 d: {
2739 1_c: true,
2740 2: true,
2741 3: 50,
2742 4_b: true,
2743 4_c: true,
2744 },
2745 f: 600,
2746 }"#]),
2747 );
2748 }
2749
2750 #[test]
2751 fn test_bytes() {
2752 inspect_sync_expect(
2753 "",
2754 Some(1),
2755 &AsBytes([0xab, 0xcd, 0xef]),
2756 expect!("<abcdef>"),
2757 );
2758 }
2759
2760 #[test]
2761 fn test_sensitivity() {
2762 let mut obj = adhoc(|req| {
2763 req.respond()
2764 .sensitivity_field("1a", SensitivityLevel::Safe, 0)
2765 .sensitivity_field("1b", SensitivityLevel::Unspecified, 0)
2766 .sensitivity_field("1c", SensitivityLevel::Sensitive, 0)
2767 .sensitivity_child("1d", SensitivityLevel::Safe, |req| {
2768 req.respond()
2769 .sensitivity_field("2a", SensitivityLevel::Sensitive, 0)
2770 .sensitivity_child("2b", SensitivityLevel::Safe, |req| {
2771 req.respond().sensitivity_child(
2772 "3a",
2773 SensitivityLevel::Sensitive,
2774 |req| {
2775 req.respond().sensitivity_field(
2776 "4a",
2777 SensitivityLevel::Safe,
2778 0,
2779 );
2780 },
2781 );
2782 });
2783 })
2784 .sensitivity_field("1d/2b/3b", SensitivityLevel::Unspecified, 0)
2785 .sensitivity_child("", SensitivityLevel::Sensitive, |req| {
2786 req.respond()
2787 .sensitivity_field("1e", SensitivityLevel::Safe, 0);
2788 });
2789 });
2790
2791 fn inspect_sync(
2792 path: &str,
2793 sensitivity: Option<SensitivityLevel>,
2794 obj: impl InspectMut,
2795 ) -> Node {
2796 let mut result = InspectionBuilder::new(path)
2797 .sensitivity(sensitivity)
2798 .inspect(obj);
2799 result.resolve().now_or_never();
2800 result.results()
2801 }
2802
2803 expected_node(
2804 inspect_sync("", Some(SensitivityLevel::Safe), &mut obj),
2805 expect!([r#"
2806 {
2807 1a: 0,
2808 1d: {
2809 2b: {},
2810 },
2811 }"#]),
2812 );
2813 expected_node(
2814 inspect_sync("", Some(SensitivityLevel::Unspecified), &mut obj),
2815 expect!([r#"
2816 {
2817 1a: 0,
2818 1b: 0,
2819 1d: {
2820 2b: {
2821 3b: 0,
2822 },
2823 },
2824 }"#]),
2825 );
2826 expected_node(
2827 inspect_sync("", Some(SensitivityLevel::Sensitive), &mut obj),
2828 expect!([r#"
2829 {
2830 1a: 0,
2831 1b: 0,
2832 1c: 0,
2833 1d: {
2834 2a: 0,
2835 2b: {
2836 3a: {
2837 4a: 0,
2838 },
2839 3b: 0,
2840 },
2841 },
2842 1e: 0,
2843 }"#]),
2844 );
2845 expected_node(
2846 inspect_sync("", None, &mut obj),
2847 expect!([r#"
2848 {
2849 1a: 0,
2850 1b: 0,
2851 1c: 0,
2852 1d: {
2853 2a: 0,
2854 2b: {
2855 3a: {
2856 4a: 0,
2857 },
2858 3b: 0,
2859 },
2860 },
2861 1e: 0,
2862 }"#]),
2863 );
2864 expected_node(
2865 inspect_sync("", Some(SensitivityLevel::Sensitive), &mut obj),
2866 expect!([r#"
2867 {
2868 1a: 0,
2869 1b: 0,
2870 1c: 0,
2871 1d: {
2872 2a: 0,
2873 2b: {
2874 3a: {
2875 4a: 0,
2876 },
2877 3b: 0,
2878 },
2879 },
2880 1e: 0,
2881 }"#]),
2882 );
2883 }
2884
2885 #[test]
2886 fn test_derive() {
2887 use std::marker::PhantomData;
2888
2889 #[derive(InspectMut)]
2890 struct Derived {
2891 dec: u32,
2892 #[inspect(hex, rename = "hex")]
2893 val2: u64,
2894 #[inspect(binary)]
2895 bin: u8,
2896 inner: Inner,
2897 #[inspect(mut)]
2898 inner_mut: InnerMut,
2899 #[inspect(flatten)]
2900 flattened: Inner,
2901 #[inspect(skip)]
2902 _skip: bool,
2903 t: Transparent,
2904 t2: Newtype,
2905 #[inspect(format = "{:02x}")]
2906 minute: u8,
2907 #[inspect(debug)]
2908 debug: (),
2909 #[inspect(display)]
2910 display: u8,
2911 var: Enum,
2912 ignored: Ignored,
2913 tr1: Tr1,
2914 tr2: Tr2,
2915 #[inspect(iter_by_index, hex)]
2916 hex_array: [u8; 4],
2917 hex_inner: HexInner,
2918 #[inspect(hex)]
2919 inner_as_hex: Inner,
2920 }
2921
2922 #[derive(Clone, Inspect)]
2923 struct Inner {
2924 val: u32,
2925 }
2926
2927 #[derive(InspectMut)]
2928 struct InnerMut {
2929 val: String,
2930 }
2931
2932 #[derive(Inspect)]
2933 #[inspect(hex)]
2934 struct HexInner {
2935 val: u32,
2936 }
2937
2938 #[derive(Inspect)]
2939 #[inspect(transparent)]
2940 struct Transparent {
2941 inner: Inner,
2942 }
2943
2944 #[derive(Inspect)]
2945 #[inspect(transparent)]
2946 struct Newtype(Inner, PhantomData<()>);
2947
2948 #[derive(Inspect)]
2949 #[inspect(transparent(hex))]
2950 struct Tr1(u32, PhantomData<()>);
2951
2952 #[derive(Inspect)]
2953 #[inspect(transparent)]
2954 struct Tr2(#[inspect(debug)] ());
2955
2956 #[derive(Inspect)]
2957 #[expect(dead_code)]
2958 enum Enum {
2959 Foo,
2960 BarBaz,
2961 #[inspect(rename = "brother")]
2962 Other,
2963 }
2964
2965 #[derive(Inspect)]
2966 #[inspect(skip)]
2967 struct Ignored {
2968 _x: fn(),
2969 }
2970
2971 let mut obj = Derived {
2972 dec: 5,
2973 val2: 4,
2974 bin: 3,
2975 inner: Inner { val: 3 },
2976 inner_mut: InnerMut {
2977 val: "hi".to_string(),
2978 },
2979 _skip: true,
2980 flattened: Inner { val: 8 },
2981 t: Transparent {
2982 inner: Inner { val: 1 },
2983 },
2984 t2: Newtype(Inner { val: 2 }, PhantomData),
2985 debug: (),
2986 display: 10,
2987 minute: 7,
2988 var: Enum::BarBaz,
2989 ignored: Ignored { _x: || () },
2990 tr1: Tr1(10, PhantomData),
2991 tr2: Tr2(()),
2992 hex_array: [100, 101, 102, 103],
2993 hex_inner: HexInner { val: 100 },
2994 inner_as_hex: Inner { val: 100 },
2995 };
2996
2997 inspect_sync_expect(
2998 "",
2999 None,
3000 &mut obj,
3001 expect!([r#"
3002 {
3003 bin: 0b11,
3004 debug: "()",
3005 dec: 5,
3006 display: "10",
3007 hex: 0x4,
3008 hex_array: {
3009 0: 0x64,
3010 1: 0x65,
3011 2: 0x66,
3012 3: 0x67,
3013 },
3014 hex_inner: {
3015 val: 0x64,
3016 },
3017 inner: {
3018 val: 3,
3019 },
3020 inner_as_hex: {
3021 val: 0x64,
3022 },
3023 inner_mut: {
3024 val: "hi",
3025 },
3026 minute: "07",
3027 t: {
3028 val: 1,
3029 },
3030 t2: {
3031 val: 2,
3032 },
3033 tr1: 0xa,
3034 tr2: "()",
3035 val: 8,
3036 var: "bar_baz",
3037 }"#]),
3038 );
3039 }
3040
3041 #[test]
3042 fn test_derive_enum() {
3043 #[expect(dead_code)]
3044 #[derive(Inspect)]
3045 enum EmptyUnitEmum {}
3046
3047 #[expect(dead_code)]
3048 #[derive(Inspect)]
3049 #[inspect(untagged)]
3050 enum EmptyUntaggedEmum {}
3051
3052 #[expect(dead_code)]
3053 #[derive(Inspect)]
3054 enum UnitEnum {
3055 A,
3056 B,
3057 C,
3058 }
3059
3060 inspect_sync_expect("", None, &UnitEnum::B, expect!([r#""b""#]));
3061
3062 #[expect(dead_code)]
3063 #[derive(Inspect)]
3064 #[inspect(tag = "tag")]
3065 enum TaggedEnum {
3066 A { x: u32 },
3067 B(#[inspect(rename = "y")] bool),
3068 }
3069
3070 inspect_sync_expect(
3071 "",
3072 None,
3073 &TaggedEnum::B(true),
3074 expect!([r#"
3075 {
3076 tag: "b",
3077 y: true,
3078 }"#]),
3079 );
3080
3081 #[expect(dead_code)]
3082 #[derive(Inspect)]
3083 #[inspect(external_tag)]
3084 enum ExternallyTaggedEnum {
3085 A {
3086 x: u32,
3087 },
3088 B(#[inspect(rename = "y")] bool),
3089 #[inspect(transparent)]
3090 C(u32),
3091 }
3092
3093 inspect_sync_expect(
3094 "",
3095 None,
3096 &ExternallyTaggedEnum::B(true),
3097 expect!([r#"
3098 {
3099 b: {
3100 y: true,
3101 },
3102 }"#]),
3103 );
3104
3105 inspect_sync_expect(
3106 "",
3107 None,
3108 &ExternallyTaggedEnum::C(5),
3109 expect!([r#"
3110 {
3111 c: 5,
3112 }"#]),
3113 );
3114
3115 #[expect(dead_code)]
3116 #[derive(Inspect)]
3117 #[inspect(untagged)]
3118 enum UntaggedEnum {
3119 A { x: u32 },
3120 B(#[inspect(rename = "y")] bool),
3121 }
3122
3123 inspect_sync_expect(
3124 "",
3125 None,
3126 &UntaggedEnum::B(true),
3127 expect!([r#"
3128 {
3129 y: true,
3130 }"#]),
3131 );
3132 }
3133
3134 #[test]
3135 fn test_derive_extra() {
3136 #[derive(Inspect)]
3137 #[inspect(extra = "Foo::inspect_extra")]
3138 struct Foo {
3139 x: u32,
3140 y: u32,
3141 }
3142
3143 impl Foo {
3144 fn inspect_extra(&self, resp: &mut inspect::Response<'_>) {
3145 resp.field("sum", self.x + self.y);
3146 }
3147 }
3148
3149 inspect_sync_expect(
3150 "",
3151 None,
3152 &Foo { x: 2, y: 5 },
3153 expect!([r#"
3154 {
3155 sum: 7,
3156 x: 2,
3157 y: 5,
3158 }"#]),
3159 );
3160 }
3161
3162 #[test]
3163 fn test_derive_sensitivity() {
3164 #[derive(Inspect)]
3165 struct Foo {
3166 #[inspect(safe)]
3167 a: u32,
3168 b: u32,
3169 #[inspect(sensitive)]
3170 c: u32,
3171 #[inspect(safe)]
3172 d: Bar,
3173 }
3174 #[derive(Inspect)]
3175 struct Bar {
3176 #[inspect(sensitive)]
3177 a: u32,
3178 #[inspect(safe)]
3179 b: Baz,
3180 }
3181 #[derive(Inspect)]
3182 struct Baz {
3183 #[inspect(sensitive)]
3184 a: Qux,
3185 b: u32,
3186 }
3187 #[derive(Inspect)]
3188 struct Qux {
3189 #[inspect(safe)]
3190 a: u32,
3191 }
3192
3193 fn inspect_sync(
3194 path: &str,
3195 sensitivity: Option<SensitivityLevel>,
3196 obj: impl Inspect,
3197 ) -> Node {
3198 let mut result = InspectionBuilder::new(path)
3199 .sensitivity(sensitivity)
3200 .inspect(&obj);
3201 result.resolve().now_or_never();
3202 result.results()
3203 }
3204
3205 let obj = Foo {
3206 a: 0,
3207 b: 0,
3208 c: 0,
3209 d: Bar {
3210 a: 0,
3211 b: Baz {
3212 a: Qux { a: 0 },
3213 b: 0,
3214 },
3215 },
3216 };
3217
3218 expected_node(
3219 inspect_sync("", Some(SensitivityLevel::Safe), &obj),
3220 expect!([r#"
3221 {
3222 a: 0,
3223 d: {
3224 b: {},
3225 },
3226 }"#]),
3227 );
3228 expected_node(
3229 inspect_sync("", Some(SensitivityLevel::Unspecified), &obj),
3230 expect!([r#"
3231 {
3232 a: 0,
3233 b: 0,
3234 d: {
3235 b: {
3236 b: 0,
3237 },
3238 },
3239 }"#]),
3240 );
3241 let node = expected_node(
3242 inspect_sync("", Some(SensitivityLevel::Sensitive), &obj),
3243 expect!([r#"
3244 {
3245 a: 0,
3246 b: 0,
3247 c: 0,
3248 d: {
3249 a: 0,
3250 b: {
3251 a: {
3252 a: 0,
3253 },
3254 b: 0,
3255 },
3256 },
3257 }"#]),
3258 );
3259 assert_eq!(
3260 node,
3261 inspect_sync("", Some(SensitivityLevel::Sensitive), &obj)
3262 );
3263 }
3264
3265 #[test]
3267 fn test_atomic_mut() {
3268 let mut v = core::sync::atomic::AtomicBool::new(false);
3269 let obj = AtomicMut(&v);
3270 update("", "true", &obj).now_or_never().unwrap().unwrap();
3271 assert!(*v.get_mut());
3272 }
3273}