cpp_core/
casts.rs

1//! `static_cast` and `dynamic_cast`.
2
3use crate::Ptr;
4
5/// Converts a class pointer to a base class pointer.
6///
7/// A null pointer is always converted to a null pointer.
8/// Otherwise, the provided pointer must be valid.
9///
10/// It's recommended to perform the conversion by calling `static_upcast`
11/// method on pointer types (`CppBox`, `Ptr`, `Ref`)
12/// instead of importing the trait directly.
13///
14/// Provides access to C++ `static_cast` conversion from derived class to base class.
15/// The conversion in opposite direction can be done with `StaticDowncast`.
16///
17/// If `T1` class is derived (in C++) from `T2` class (directly or indirectly),
18/// `StaticUpcast<T2>` is implemented for `T1`.
19/// The implementation is generated by `ritual` automatically.
20///
21/// Note that Rust functions associated with this trait have runtime overhead.
22/// In C++, `static_cast` is usually a no-op if there is no multiple inheritance,
23/// and multiple inheritance requires pointer adjustment. However, Rust compiler
24/// and `ritual` do not have any information about these implementation details,
25/// so all calls of `static_cast` are wrapper in FFI functions.
26pub trait StaticUpcast<T>: Sized {
27    /// Convert type of a const pointer.
28    ///
29    /// ### Safety
30    ///
31    /// This operation is safe as long as `ptr` is either valid or null.
32    unsafe fn static_upcast(ptr: Ptr<Self>) -> Ptr<T>;
33}
34
35impl<T> StaticUpcast<T> for T {
36    unsafe fn static_upcast(ptr: Ptr<T>) -> Ptr<T> {
37        ptr
38    }
39}
40
41/// Converts a class pointer to a base class pointer without a runtime check.
42///
43/// A null pointer is always converted to a null pointer.
44/// Otherwise, the provided pointer must be valid and point to the object of the specified type.
45///
46/// It's generally safer to use `DynamicCast` instead because it performs a checked conversion.
47/// This trait should only be used if the type of the object is known.
48///
49/// It's recommended to perform the conversion by calling `static_downcast`
50/// method on pointer types (`CppBox`, `Ptr`, `Ref`)
51/// instead of importing the trait directly.
52///
53/// Provides access to C++ `static_cast` conversion from base class to derived class.
54/// The conversion in opposite direction can be done with `StaticUpcast`.
55///
56/// If `T1` class is derived (in C++) from `T2` class (directly or indirectly),
57/// `StaticDowncast<T1>` is implemented for `T2`.
58/// The implementation is generated by `ritual` automatically.
59///
60/// Note that Rust functions associated with this trait have runtime overhead.
61/// In C++, `static_cast` is usually a no-op if there is no multiple inheritance,
62/// and multiple inheritance requires pointer adjustment. However, Rust compiler
63/// and `ritual` do not have any information about these implementation details,
64/// so all calls of `static_cast` are wrapper in FFI functions.
65pub trait StaticDowncast<T>: Sized {
66    /// Convert type of a const pointer.
67    ///
68    /// ### Safety
69    ///
70    /// This operation is safe as long as `ptr` is either null or points to an object
71    /// of the `T` class or a class inherited by `T`.
72    unsafe fn static_downcast(ptr: Ptr<Self>) -> Ptr<T>;
73}
74
75/// Converts a class pointer to a base class pointer.
76///
77/// A null pointer is always converted to a null pointer.
78/// If the object can't be converted to the requested type, a null pointer is returned.
79///
80/// It's recommended to perform the conversion by calling `dynamic_cast`
81/// method on pointer types (`CppBox`, `Ptr`, `Ref`)
82/// instead of importing the trait directly.
83///
84/// Provides access to C++ `dynamic_cast` conversion from base class to derived class.
85/// The conversion in opposite direction can be done with `StaticUpcast`.
86///
87/// If `T1` class is derived (in C++) from `T2` class (directly or indirectly),
88/// `DynamicCast<T1>` is implemented for `T2`.
89/// The implementation is generated by `ritual` automatically.
90pub trait DynamicCast<T>: Sized {
91    /// Convert type of a const pointer.
92    ///
93    /// Returns a null pointer if the object doesn't have the requested type.
94    ///
95    /// ### Safety
96    ///
97    /// This operation is safe as long as `ptr` is either valid or null.
98    unsafe fn dynamic_cast(ptr: Ptr<Self>) -> Ptr<T>;
99}