facet_peek/
lib.rs

1#![warn(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4//! Allows peeking (reading from) shapes
5
6use facet_trait::{Facet, TypeNameOpts};
7
8mod value;
9pub use value::*;
10
11mod struct_;
12pub use struct_::*;
13
14mod list;
15pub use list::*;
16
17mod map;
18pub use map::*;
19
20use facet_trait::{Def, OpaqueConst, Shape};
21
22/// Lets you peek at the innards of a value
23///
24/// It's possible (in some cases..) to escape the borrow checker by setting `'mem` to `'static`,
25/// in which case, you're entirely on your own.
26#[derive(Clone, Copy)]
27#[non_exhaustive]
28pub enum Peek<'mem> {
29    /// cf. [`PeekValue`]
30    Value(PeekValue<'mem>),
31
32    /// cf. [`PeekList`]
33    List(PeekList<'mem>),
34
35    /// cf. [`PeekMap`]
36    Map(PeekMap<'mem>),
37
38    /// cf. [`PeekStruct`]
39    Struct(PeekStruct<'mem>),
40}
41
42impl<'mem> core::ops::Deref for Peek<'mem> {
43    type Target = PeekValue<'mem>;
44
45    fn deref(&self) -> &Self::Target {
46        match self {
47            Peek::Value(value) => value,
48            Peek::List(list) => list,
49            Peek::Map(map) => map,
50            Peek::Struct(struct_) => struct_,
51        }
52    }
53}
54
55impl<'mem> Peek<'mem> {
56    /// Creates a new peek from a reference to some initialized value that implements `Facet`
57    pub fn new<S: Facet>(s: &'mem S) -> Self {
58        // This is safe because we're creating an Opaque pointer to read-only data
59        // The pointer will be valid for the lifetime 'mem
60        let data = OpaqueConst::from_ref(s);
61        unsafe { Self::unchecked_new(data, S::SHAPE) }
62    }
63
64    /// Creates a new peek, for easy manipulation of some opaque data.
65    ///
66    /// # Safety
67    ///
68    /// `data` must be initialized and well-aligned, and point to a value
69    /// of the type described by `shape`.
70    pub unsafe fn unchecked_new(data: OpaqueConst<'mem>, shape: &'static Shape) -> Self {
71        let value = unsafe { PeekValue::unchecked_new(data, shape) };
72        match shape.def {
73            Def::Struct(def) => Peek::Struct(PeekStruct::new(value, def)),
74            Def::Map(def) => Peek::Map(PeekMap::new(value, def)),
75            Def::List(def) => Peek::List(PeekList::new(value, def)),
76            Def::Scalar { .. } => Peek::Value(value),
77            Def::Enum { .. } => todo!(),
78            _ => todo!("unsupported def: {:?}", shape.def),
79        }
80    }
81
82    /// Coerce this to a value so we can use display, debug, etc.
83    pub fn as_value(self) -> PeekValue<'mem> {
84        match self {
85            Self::Value(v) => v,
86            Self::List(l) => *l,
87            Self::Map(m) => *m,
88            Self::Struct(s) => *s,
89        }
90    }
91}
92
93impl core::fmt::Debug for Peek<'_> {
94    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95        let value = self.as_value();
96        if value.debug(f).is_none() {
97            value.type_name(f, TypeNameOpts::infinite())?;
98            write!(f, "(⋯)")?;
99        }
100        Ok(())
101    }
102}
103
104impl core::fmt::Display for Peek<'_> {
105    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
106        let value = self.as_value();
107        if value.display(f).is_none() {
108            value.type_name(f, TypeNameOpts::infinite())?;
109            write!(f, "(⋯)")?;
110        }
111        Ok(())
112    }
113}