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}