#[class_unsafe]Expand description
Generates class and appropriate helper types and traits.
Usage:
#[class_unsafe(inherits_ParentClass)]
struct Class {
field: FieldType,
#[non_virt]
non_virtual_method: fn(args: ArgsType) -> ResultType,
#[virt]
virtual_method: fn(args: ArgsType) -> ResultType,
#[over]
parent_virtual_method: (),
}
impl Class {
fn non_virtual_method_impl(this: Rc<dyn IsClass>, args: ArgsType) -> ResultType {
...
}
fn virtual_method_impl(this: Rc<dyn IsClass>, args: ArgsType) -> ResultType {
...
}
fn parent_virtual_method_impl(this: Rc<dyn IsParentClass>, args: ArgsType) -> ResultType {
let base_result = ParentClass::parent_virtual_method_impl(this, args);
...
}
}For a more detailed overview, please refer to the crate documentation.
§Safety
This macro may produce unsound code if the argument to the macro differs
from inherits_Obj/inherits_Obj_sync imported from the obj module
and another inherits_... generated by this macro for a direct or indirect inheritor of Obj.
In other words, it is safe to use this macro as long as you don’t try to manually create something that this macro will accept as a valid argument.
It must also be guaranteed that the generated class cannot be constructed with an invalid vtable, that is, any vtable other than the one generated by this macro for this class or its direct or indirect inheritor.
This is usually achieved by providing two constructors: a safe one that creates a class with a precisely known, guaranteed safe table, and an unsafe one for inheritors that enforces the specified requirement. For example:
#[class_unsafe(inherits_SomeBaseClass)]
pub struct SomeClass { }
impl SomeClass {
pub fn new(param: ParamType) -> Rc<dyn IsSomeClass> {
Rc::new(unsafe { Self::new_raw(param, SOME_CLASS_VTABLE.as_ptr()) })
}
pub unsafe fn new_raw(param: ParamType, vtable: Vtable) -> Self {
SomeClass { some_base_class: unsafe { SomeBaseClass::new_raw(param, vtable) } }
}
}