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