facet_trait/
lib.rs

1#![warn(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4pub use facet_spez;
5
6pub use facet_opaque::*;
7pub use facet_types::*;
8
9mod impls;
10
11mod macros;
12pub use macros::*;
13
14/// Allows querying the [`Shape`] of a type, which in turn lets us inspect any fields, build a value of
15/// this type progressively, etc.
16///
17/// # Safety
18///
19/// If you implement this wrong, all the safe abstractions in `facet-peek`, `facet-poke`,
20/// all the serializers, deserializers, the entire ecosystem is unsafe.
21///
22/// You're responsible for describing the type layout properly, and annotating all the invariants.
23pub unsafe trait Facet: Sized {
24    /// The shape of this type
25    const SHAPE: &'static Shape;
26
27    /// An instance of this type — which doesn't have to be valid, but it has to
28    /// "not be UB". We never actually read from it, or even actually use it for
29    /// dynamic dispatch, we only use it for inference tricks.
30    const ARCHETYPE: Self;
31
32    /// Returns true if the type of `self` is equal to the type of `other`
33    fn type_eq<Other: Facet>() -> bool {
34        Self::SHAPE == Other::SHAPE
35    }
36}
37
38/// Extension trait to provide `is_type` and `assert_type`
39pub trait ShapeExt {
40    /// Check if this shape is of the given type
41    fn is_type<Other: Facet>(&'static self) -> bool;
42
43    /// Assert that this shape is of the given type, panicking if it's not
44    fn assert_type<Other: Facet>(&'static self);
45}
46
47impl ShapeExt for Shape {
48    /// Check if this shape is of the given type
49    fn is_type<Other: Facet>(&'static self) -> bool {
50        self == Other::SHAPE
51    }
52
53    /// Assert that this shape is of the given type, panicking if it's not
54    fn assert_type<Other: Facet>(&'static self) {
55        assert!(
56            self.is_type::<Other>(),
57            "Type mismatch: expected {}, found {self}",
58            Other::SHAPE,
59        );
60    }
61}