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}