Skip to main content

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}