aboutsummaryrefslogtreecommitdiff
path: root/mingling_core/src/any/group.rs
blob: 71fe65db656662214646f5041e5337adde4adb7d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/// Member ID for types within a program
///
/// This trait provides a member ID for program-internal types, used to determine
/// the downcast type during dispatch, routing, rendering, and other stages.
///
/// # Safety
///
/// This trait is typically provided by the corresponding [`Grouped Derive`](https://docs.rs/mingling/latest/mingling/derive.Grouped.html).
/// If implemented manually, **make sure** the ID is **exactly identical** to
/// the name registered by the `register_type!` macro; otherwise, undefined
/// behavior will inevitably occur when the program routes to that type!
///
/// # Manual impl
///
/// In general, we recommend using [`#[derive(Grouped)]`](https://docs.rs/mingling/latest/mingling/derive.Grouped.html) to implement it.
/// However, if you must implement it manually, please follow exactly this pattern:
///
/// ```
/// # use mingling_core::Grouped;
/// enum ThisProgram {
///     // Global ID registered by `register_type!`
///     StateMyType,
/// }
///
/// struct StateMyType;
///
/// // SAFETY: This ensures the StateMyType variant during ThisProgram dispatch always corresponds to this type
/// unsafe impl Grouped<ThisProgram> for StateMyType {
///     fn member_id() -> ThisProgram {
///         // must semantically correspond to the type itself!
///         ThisProgram::StateMyType
///     }
/// }
/// ```
pub unsafe trait Grouped<Group>
where
    Self: Sized + 'static,
{
    /// Get the member ID for this type
    ///
    /// # Safety
    ///
    /// The returned enum variant must exactly correspond to this type itself,
    /// i.e., the returned `Group` enum variant must semantically represent this
    /// type itself. If an incorrect variant is returned, it will cause a type
    /// casting error and lead to undefined behavior.
    ///
    /// # Example
    ///
    /// ```
    /// # use mingling_core::Grouped;
    /// # enum ThisProgram {
    /// #     StateMyType,
    /// # }
    /// # struct StateMyType;
    /// # unsafe impl Grouped<ThisProgram> for StateMyType {
    /// // The following macro registers the type ID
    /// // mingling::macros::register_type!(StateMyType);
    ///
    /// fn member_id() -> ThisProgram {
    ///     // must semantically correspond to the type itself!
    ///     ThisProgram::StateMyType
    /// }
    /// # }
    /// ```
    fn member_id() -> Group;
}