imping_runtime/inherits.rs
1//! Base classes: which types derive from which, and pointer upcasts.
2
3/// Marks `Self` as deriving from `B`, so a pointer to a `Self` is also a valid
4/// pointer to its `B`.
5///
6/// Generated bindings implement it for every ancestor of a class, and give the
7/// class `Deref` and `DerefMut` to its direct base so references reach base
8/// fields and coerce to base references. For raw pointers, use
9/// [`Upcast::upcast`].
10///
11/// # Safety
12///
13/// `Self` must have a defined layout (`repr(C)` or `repr(transparent)`) with a
14/// `B` at offset 0, and every valid `Self` must hold a valid `B` there.
15///
16/// # Examples
17///
18/// ```
19/// use imping_runtime::{Inherits, Upcast};
20///
21/// #[repr(C)]
22/// struct Entity { health: i32 }
23/// #[repr(C)]
24/// struct Player { base: Entity, level: i32 }
25///
26/// // SAFETY: `Player` is `repr(C)` and starts with its `Entity`.
27/// unsafe impl Inherits<Entity> for Player {}
28///
29/// fn heal(entity: *mut Entity) {
30/// // SAFETY: the caller passes a live entity.
31/// unsafe { (*entity).health = 100 };
32/// }
33///
34/// let mut player = Player { base: Entity { health: 1 }, level: 3 };
35/// let pointer: *mut Player = &mut player;
36/// heal(pointer.upcast());
37/// assert_eq!(player.base.health, 100);
38/// ```
39pub unsafe trait Inherits<B> {}
40
41mod sealed {
42 pub trait Sealed {}
43 impl<T> Sealed for *mut T {}
44 impl<T> Sealed for *const T {}
45}
46
47/// Converts a raw pointer to a class into a pointer to one of its base
48/// classes, keeping it `*mut` or `*const`.
49///
50/// A plain cast, valid because of [`Inherits`]. It never dereferences, so null
51/// and dangling pointers stay null or dangling. Implemented only for raw
52/// pointers.
53///
54/// # Examples
55///
56/// A type that isn't a base doesn't compile:
57///
58/// ```compile_fail
59/// use imping_runtime::Upcast;
60///
61/// #[repr(C)]
62/// struct Entity { health: i32 }
63/// #[repr(C)]
64/// struct Item { count: i32 }
65///
66/// let item: *mut Item = core::ptr::null_mut();
67/// let entity: *mut Entity = item.upcast(); // `Item` does not inherit `Entity`
68/// ```
69pub trait Upcast: sealed::Sealed {
70 /// The type the pointer points to.
71 type Pointee;
72 /// The same kind of pointer (`*mut` or `*const`) to a base class `B`.
73 type Cast<B>;
74
75 /// Returns this pointer as a pointer to its base class `B`.
76 ///
77 /// `B` is usually inferred from where the result goes; name it with
78 /// `upcast::<B>()` otherwise.
79 fn upcast<B>(self) -> Self::Cast<B>
80 where
81 Self::Pointee: Inherits<B>;
82}
83
84impl<T> Upcast for *mut T {
85 type Pointee = T;
86 type Cast<B> = *mut B;
87
88 fn upcast<B>(self) -> *mut B
89 where
90 T: Inherits<B>,
91 {
92 self.cast()
93 }
94}
95
96impl<T> Upcast for *const T {
97 type Pointee = T;
98 type Cast<B> = *const B;
99
100 fn upcast<B>(self) -> *const B
101 where
102 T: Inherits<B>,
103 {
104 self.cast()
105 }
106}