abi_stable/type_level/
downcasting.rs

1use crate::{
2    sabi_types::MaybeCmp,
3    std_types::utypeid::{no_utypeid, some_utypeid, UTypeId},
4};
5
6/// Passed to trait object constructors to make the
7/// trait object downcast capable,
8/// as opposed to [`TD_Opaque`](./struct.TD_Opaque.html).
9///
10/// [The `from_value`/`from_ptr`/`from_const` methods here
11/// ](../../docs/sabi_trait_inherent/index.html#methods) take this type.
12///
13/// # Example
14///
15/// ```rust
16/// use abi_stable::{
17///     sabi_trait::doc_examples::Action_TO,
18///     std_types::RBox,
19///     type_level::downcasting::TD_CanDowncast,
20/// };
21///
22/// // The type annotation is purely for the reader.
23/// let mut object: Action_TO<'static, RBox<()>> =
24///     Action_TO::from_value(100_usize, TD_CanDowncast);
25///
26/// assert_eq!(object.obj.downcast_as::<u8>().ok(), None);
27/// assert_eq!(object.obj.downcast_as::<char>().ok(), None);
28/// assert_eq!(object.obj.downcast_as::<usize>().ok(), Some(&100_usize));
29///
30/// ```
31#[allow(non_camel_case_types)]
32#[derive(Copy, Clone)]
33pub struct TD_CanDowncast;
34
35/// Passed to trait object constructors to make it impossible to downcast the
36/// trait object,
37/// as opposed to [`TD_CanDowncast`](./struct.TD_CanDowncast.html).
38///
39/// [The `from_value`/`from_ptr`/`from_const` methods here
40/// ](../../docs/sabi_trait_inherent/index.html#methods) take this type.
41///
42/// # Example
43///
44/// ```rust
45/// use abi_stable::{
46///     sabi_trait::doc_examples::Action_TO,
47///     std_types::RBox,
48///     type_level::downcasting::TD_Opaque,
49/// };
50///
51/// // The type annotation is purely for the reader.
52/// let mut object: Action_TO<'static, RBox<()>> =
53///     Action_TO::from_value(100_usize, TD_Opaque);
54///
55/// assert_eq!(object.obj.downcast_as::<u8>().ok(), None);
56///
57/// assert_eq!(object.obj.downcast_as::<char>().ok(), None);
58///
59/// // Because `Action_TO::from-value` was passed `TD_Opaque`,
60/// // the trait object can't be downcasted
61/// assert_eq!(object.obj.downcast_as::<usize>().ok(), None);
62///
63/// ```
64#[allow(non_camel_case_types)]
65#[derive(Copy, Clone)]
66pub struct TD_Opaque;
67
68/// Gets a function optionally returning the `UTypeId` of `T`.
69///
70/// Whether the function returns `MaybeCmp::Just(typeid)` is determined by implementors:
71///
72/// - `TD_CanDowncast`: the function always returns `MaybeCmp::Just(typeid)`.
73///
74/// - `TD_Opaque`: the function always returns `MaybeCmp::Nothing`.
75pub trait GetUTID<T> {
76    /// the function.
77    const UID: extern "C" fn() -> MaybeCmp<UTypeId>;
78}
79
80impl<T> GetUTID<T> for TD_CanDowncast
81where
82    T: 'static,
83{
84    const UID: extern "C" fn() -> MaybeCmp<UTypeId> = some_utypeid::<T>;
85}
86
87impl<T> GetUTID<T> for TD_Opaque {
88    const UID: extern "C" fn() -> MaybeCmp<UTypeId> = no_utypeid;
89}