mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 22:54:36 +00:00
Minor doc fixes to the vtable crate
This commit is contained in:
parent
b80182ce00
commit
46911f60ee
2 changed files with 51 additions and 49 deletions
|
@ -54,13 +54,13 @@ fn is_pin<'a>(ty: &'a Type) -> Option<&'a Type> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
This macro need to be applied to a VTable structure
|
This macro needs to be applied to a VTable structure
|
||||||
|
|
||||||
The desing choice is that it is applied to a VTable and not to a trait so that cbindgen
|
The design choice is that it is applied to a VTable and not to a trait so that cbindgen
|
||||||
can see the actual vtable struct.
|
can see the actual vtable struct.
|
||||||
|
|
||||||
This macro need to be applied to a struct whose name ends with "VTable", and which
|
This macro needs to be applied to a struct whose name ends with "VTable", and which
|
||||||
contains member which are function pointers.
|
contains members which are function pointers.
|
||||||
|
|
||||||
For example, if it is applied to `struct MyTraitVTable`, it will create:
|
For example, if it is applied to `struct MyTraitVTable`, it will create:
|
||||||
- The `MyTrait` trait with all the functions.
|
- The `MyTrait` trait with all the functions.
|
||||||
|
@ -70,23 +70,23 @@ For example, if it is applied to `struct MyTraitVTable`, it will create:
|
||||||
It will also implement the `VTableMeta` and `VTableMetaDrop` traits so that VRef and so on can work,
|
It will also implement the `VTableMeta` and `VTableMetaDrop` traits so that VRef and so on can work,
|
||||||
allowing to access methods from the trait directly from VRef.
|
allowing to access methods from the trait directly from VRef.
|
||||||
|
|
||||||
This macro does the following transformation.
|
This macro does the following transformation:
|
||||||
|
|
||||||
For fields whose type is a function:
|
For function type fields:
|
||||||
- The ABI of each functions is changed to `extern "C"`
|
- The ABI of each functions is changed to `extern "C"`
|
||||||
- `unsafe` is added to the signature of each, since it is unsafe to call these function directly from
|
- `unsafe` is added to the signature, since it is unsafe to call these functions directly from
|
||||||
the vtable without having a valid pointer to the actual object. But if the original function was
|
the vtable without having a valid pointer to the actual object. But if the original function was
|
||||||
marked unsafe, the unsafety is forwared to the trait.
|
marked unsafe, the unsafety is forwarded to the trait.
|
||||||
- If a field is called `drop` it is understood that this is the destructor for a VBox
|
- If a field is called `drop`, then it is understood that this is the destructor for a VBox.
|
||||||
- If the first argument of the function is `VRef<MyVTable>` or `VRefMut<MyVTable>` this is
|
- If the first argument of the function is `VRef<MyVTable>` or `VRefMut<MyVTable>`, then it is
|
||||||
understood as a `&self` or `&mut self` argument in the trait.
|
understood as a `&self` or `&mut self` argument in the trait.
|
||||||
- Similarily, if it is a `Pin<VRef<MyVTable>>` or `Pin<VRefMut<MyVTable>>`, self is mapped
|
- Similarly, if it is a `Pin<VRef<MyVTable>>` or `Pin<VRefMut<MyVTable>>`, self is mapped
|
||||||
to `Pin<&Self>` or `Pin<&mut Self>`
|
to `Pin<&Self>` or `Pin<&mut Self>`
|
||||||
|
|
||||||
For the other fields
|
For the other fields:
|
||||||
- They are considered assotiated const of the MyTraitConsts
|
- They are considered associated constants of the MyTraitConsts trait.
|
||||||
- If they are annotated with the `#[field_offset(FieldType)]` attribute, the type of the field must be `usize`,
|
- If they are annotated with the `#[field_offset(FieldType)]` attribute, the type of the field must be `usize`,
|
||||||
and the associated const in the trait will be of type `FieldOffset<Self, FieldType>`, and accessor to
|
and the associated const in the trait will be of type `FieldOffset<Self, FieldType>`, and an accessor to
|
||||||
the field reference and reference mut will be added to the Target of VRef and VRefMut.
|
the field reference and reference mut will be added to the Target of VRef and VRefMut.
|
||||||
|
|
||||||
The VRef/VRefMut/VBox structure will dereference to a type which has the following associated items:
|
The VRef/VRefMut/VBox structure will dereference to a type which has the following associated items:
|
||||||
|
|
|
@ -9,16 +9,16 @@
|
||||||
|
|
||||||
LICENSE END */
|
LICENSE END */
|
||||||
/*!
|
/*!
|
||||||
This crate allow to create ffi-friendly virtual tables.
|
This crate allows you to create ffi-friendly virtual tables.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- A `#[vtable]` macro to annotate a VTable struct to generate the traits and structure
|
- A `#[vtable]` macro to annotate a VTable struct to generate the traits and structure
|
||||||
to safely work with it.
|
to safely work with it.
|
||||||
- `VRef`/`VRefMut`/`VBox` types which are fat reference/box which wrap a pointer to
|
- `VRef`/`VRefMut`/`VBox` types. They are fat reference/box types which wrap a pointer to
|
||||||
the vtable, and a pointer to the object
|
the vtable, and a pointer to the object.
|
||||||
- Ability to store constant in a vtable.
|
- Ability to store constants in a vtable.
|
||||||
- These constant can even be field offset
|
- These constants can even be a field offset.
|
||||||
|
|
||||||
## Example of use:
|
## Example of use:
|
||||||
|
|
||||||
|
@ -28,13 +28,13 @@ use vtable::*;
|
||||||
#[vtable]
|
#[vtable]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct AnimalVTable {
|
struct AnimalVTable {
|
||||||
/// pointer to a function that make a noise. The `VRef<AnimalVTable>` is the type of
|
/// pointer to a function that makes a noise. The `VRef<AnimalVTable>` is the type of
|
||||||
/// the self object.
|
/// the self object.
|
||||||
///
|
///
|
||||||
/// Note: the #[vtable] macro will automatically add `extern "C"` if that is missing
|
/// Note: the #[vtable] macro will automatically add `extern "C"` if that is missing.
|
||||||
make_noise: fn(VRef<AnimalVTable>, i32) -> i32,
|
make_noise: fn(VRef<AnimalVTable>, i32) -> i32,
|
||||||
|
|
||||||
/// if there is a 'drop' member, it is considered as the destrutor
|
/// if there is a 'drop' member, it is considered as the destructor.
|
||||||
drop: fn(VRefMut<AnimalVTable>),
|
drop: fn(VRefMut<AnimalVTable>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +74,12 @@ pub use vtable_macro::*;
|
||||||
|
|
||||||
/// Internal trait that is implemented by the `#[vtable]` macro.
|
/// Internal trait that is implemented by the `#[vtable]` macro.
|
||||||
///
|
///
|
||||||
/// Safety: The Target object need to be implemented correctly.
|
/// Safety: The Target object needs to be implemented correctly.
|
||||||
/// And there should be a VTable::VTable::new<T> funciton that returns a
|
/// And there should be a VTable::VTable::new<T> function that returns a
|
||||||
/// VTable suitable for the type T
|
/// VTable suitable for the type T.
|
||||||
pub unsafe trait VTableMeta {
|
pub unsafe trait VTableMeta {
|
||||||
/// That's the trait object that implements the functions
|
/// That's the trait object that implements the functions
|
||||||
|
///
|
||||||
/// NOTE: the size must be `2*size_of::<usize>`
|
/// NOTE: the size must be `2*size_of::<usize>`
|
||||||
/// and a `repr(C)` with `(vtable, ptr)` so it has the same layout as
|
/// and a `repr(C)` with `(vtable, ptr)` so it has the same layout as
|
||||||
/// the inner and VBox/VRef/VRefMut
|
/// the inner and VBox/VRef/VRefMut
|
||||||
|
@ -90,14 +91,14 @@ pub unsafe trait VTableMeta {
|
||||||
|
|
||||||
/// This trait is implemented by the `#[vtable]` macro.
|
/// This trait is implemented by the `#[vtable]` macro.
|
||||||
///
|
///
|
||||||
/// It is implemented if the macro has a "drop" function
|
/// It is implemented if the macro has a "drop" function.
|
||||||
pub trait VTableMetaDrop: VTableMeta {
|
pub trait VTableMetaDrop: VTableMeta {
|
||||||
/// Safety: the Target need to be pointing to a valid allocated pointer
|
/// Safety: the Target needs to be pointing to a valid allocated pointer
|
||||||
unsafe fn drop(ptr: *mut Self::Target);
|
unsafe fn drop(ptr: *mut Self::Target);
|
||||||
fn new_box<X: HasStaticVTable<Self>>(value: X) -> VBox<Self>;
|
fn new_box<X: HasStaticVTable<Self>>(value: X) -> VBox<Self>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Allow to associate a VTable to a type.
|
/// Allow to associate a VTable with a type.
|
||||||
///
|
///
|
||||||
/// Safety: the VTABLE and STATIC_VTABLE need to be a a valid virtual table
|
/// Safety: the VTABLE and STATIC_VTABLE need to be a a valid virtual table
|
||||||
/// corresponding to pointer to Self instance.
|
/// corresponding to pointer to Self instance.
|
||||||
|
@ -129,14 +130,14 @@ impl Inner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An equivalent of a Box that holds a pointer to a VTable and a pointer to an instance
|
/// An equivalent of a Box that holds a pointer to a VTable and a pointer to an instance.
|
||||||
/// which frees the instance when droped.
|
/// A VBox frees the instance when dropped.
|
||||||
///
|
///
|
||||||
/// The type parameter is supposed to be the VTable type.
|
/// The type parameter is supposed to be the VTable type.
|
||||||
///
|
///
|
||||||
/// The VBox implemtns Deref so one can access all the member of the vtable.
|
/// The VBox implements Deref so one can access all the members of the vtable.
|
||||||
///
|
///
|
||||||
/// This is only valid of the VTable has a `drop` type (so that the `#[vtable]` macro
|
/// This is only valid if the VTable has a `drop` type (so that the `#[vtable]` macro
|
||||||
/// implements the `VTableMetaDrop` trait for it)
|
/// implements the `VTableMetaDrop` trait for it)
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct VBox<T: ?Sized + VTableMetaDrop> {
|
pub struct VBox<T: ?Sized + VTableMetaDrop> {
|
||||||
|
@ -165,7 +166,7 @@ impl<T: ?Sized + VTableMetaDrop> Drop for VBox<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: ?Sized + VTableMetaDrop> VBox<T> {
|
impl<T: ?Sized + VTableMetaDrop> VBox<T> {
|
||||||
/// Create a new VBox from an instance of a type that can be assosiated with a VTable.
|
/// Create a new VBox from an instance of a type that can be associated with a VTable.
|
||||||
///
|
///
|
||||||
/// Will move the instance on the heap.
|
/// Will move the instance on the heap.
|
||||||
///
|
///
|
||||||
|
@ -203,7 +204,7 @@ impl<T: ?Sized + VTableMetaDrop> VBox<T> {
|
||||||
|
|
||||||
/// `VRef<'a MyTraitVTable>` can be thought as a `&'a dyn MyTrait`
|
/// `VRef<'a MyTraitVTable>` can be thought as a `&'a dyn MyTrait`
|
||||||
///
|
///
|
||||||
/// It will dereference to a structure that has the same member as MyTrait
|
/// It will dereference to a structure that has the same members as MyTrait.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct VRef<'a, T: ?Sized + VTableMeta> {
|
pub struct VRef<'a, T: ?Sized + VTableMeta> {
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
|
@ -227,7 +228,7 @@ impl<'a, T: ?Sized + VTableMeta> Deref for VRef<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
||||||
/// Create a new VRef from an reference of a type that can be assosiated with a VTable.
|
/// Create a new VRef from an reference of a type that can be associated with a VTable.
|
||||||
///
|
///
|
||||||
/// (the `HasStaticVTable` is implemented by the `“MyTrait”VTable_static!` macro generated by
|
/// (the `HasStaticVTable` is implemented by the `“MyTrait”VTable_static!` macro generated by
|
||||||
/// the #[vtable] macro)
|
/// the #[vtable] macro)
|
||||||
|
@ -241,7 +242,7 @@ impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a new Pin<VRef<_>> from a pinned reference. This is similar to `VRef::new`
|
/// Create a new Pin<VRef<_>> from a pinned reference. This is similar to `VRef::new`.
|
||||||
pub fn new_pin<X: HasStaticVTable<T>>(value: core::pin::Pin<&'a X>) -> Pin<Self> {
|
pub fn new_pin<X: HasStaticVTable<T>>(value: core::pin::Pin<&'a X>) -> Pin<Self> {
|
||||||
// Since Value is pinned, this means it is safe to construct a Pin
|
// Since Value is pinned, this means it is safe to construct a Pin
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -267,7 +268,7 @@ impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return to a reference of the given type if the type is actually matching
|
/// Return a reference of the given type if the type is matching.
|
||||||
pub fn downcast<X: HasStaticVTable<T>>(&self) -> Option<&X> {
|
pub fn downcast<X: HasStaticVTable<T>>(&self) -> Option<&X> {
|
||||||
if self.inner.vtable == X::static_vtable() as *const _ as *const u8 {
|
if self.inner.vtable == X::static_vtable() as *const _ as *const u8 {
|
||||||
// Safety: We just checked that the vtable fits
|
// Safety: We just checked that the vtable fits
|
||||||
|
@ -277,7 +278,7 @@ impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return to a reference of the given type if the type is actually matching
|
/// Return a reference of the given type if the type is matching
|
||||||
pub fn downcast_pin<X: HasStaticVTable<T>>(this: Pin<Self>) -> Option<Pin<&'a X>> {
|
pub fn downcast_pin<X: HasStaticVTable<T>>(this: Pin<Self>) -> Option<Pin<&'a X>> {
|
||||||
let inner = unsafe { Pin::into_inner_unchecked(this).inner };
|
let inner = unsafe { Pin::into_inner_unchecked(this).inner };
|
||||||
if inner.vtable == X::static_vtable() as *const _ as *const u8 {
|
if inner.vtable == X::static_vtable() as *const _ as *const u8 {
|
||||||
|
@ -291,7 +292,7 @@ impl<'a, T: ?Sized + VTableMeta> VRef<'a, T> {
|
||||||
|
|
||||||
/// `VRefMut<'a MyTraitVTable>` can be thought as a `&'a mut dyn MyTrait`
|
/// `VRefMut<'a MyTraitVTable>` can be thought as a `&'a mut dyn MyTrait`
|
||||||
///
|
///
|
||||||
/// It will dereference to a structure that has the same member as MyTrait
|
/// It will dereference to a structure that has the same members as MyTrait.
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct VRefMut<'a, T: ?Sized + VTableMeta> {
|
pub struct VRefMut<'a, T: ?Sized + VTableMeta> {
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
|
@ -312,7 +313,7 @@ impl<'a, T: ?Sized + VTableMeta> DerefMut for VRefMut<'a, T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> {
|
impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> {
|
||||||
/// Create a new VRef from a mutable reference of a type that can be assosiated with a VTable.
|
/// Create a new VRef from a mutable reference of a type that can be associated with a VTable.
|
||||||
///
|
///
|
||||||
/// (the `HasStaticVTable` is implemented by the `“MyTrait”VTable_static!` macro generated by
|
/// (the `HasStaticVTable` is implemented by the `“MyTrait”VTable_static!` macro generated by
|
||||||
/// the #[vtable] macro)
|
/// the #[vtable] macro)
|
||||||
|
@ -338,22 +339,22 @@ impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow this to obtain a VRef
|
/// Borrow this to obtain a VRef.
|
||||||
pub fn borrow<'b>(&'b self) -> VRef<'b, T> {
|
pub fn borrow<'b>(&'b self) -> VRef<'b, T> {
|
||||||
unsafe { VRef::from_inner(self.inner) }
|
unsafe { VRef::from_inner(self.inner) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Borrow this to obtain a new VRefMut
|
/// Borrow this to obtain a new VRefMut.
|
||||||
pub fn borrow_mut<'b>(&'b mut self) -> VRefMut<'b, T> {
|
pub fn borrow_mut<'b>(&'b mut self) -> VRefMut<'b, T> {
|
||||||
unsafe { VRefMut::from_inner(self.inner) }
|
unsafe { VRefMut::from_inner(self.inner) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a VRef with the same lifetime as the original lifetime
|
/// Create a VRef with the same lifetime as the original lifetime.
|
||||||
pub fn into_ref(self) -> VRef<'a, T> {
|
pub fn into_ref(self) -> VRef<'a, T> {
|
||||||
unsafe { VRef::from_inner(self.inner) }
|
unsafe { VRef::from_inner(self.inner) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return to a reference of the given type if the type is actually matching
|
/// Return a reference of the given type if the type is matching.
|
||||||
pub fn downcast<X: HasStaticVTable<T>>(&mut self) -> Option<&mut X> {
|
pub fn downcast<X: HasStaticVTable<T>>(&mut self) -> Option<&mut X> {
|
||||||
if self.inner.vtable == X::static_vtable() as *const _ as *const u8 {
|
if self.inner.vtable == X::static_vtable() as *const _ as *const u8 {
|
||||||
// Safety: We just checked that the vtable fits
|
// Safety: We just checked that the vtable fits
|
||||||
|
@ -364,11 +365,12 @@ impl<'a, T: ?Sized + VTableMeta> VRefMut<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Create a `VRef` or a `VRefMut` suitable for an instance that implements the trait
|
/** Creates a `VRef` or a `VRefMut` suitable for an instance that implements the trait
|
||||||
|
|
||||||
When possible, `VRef::new` or `VRefMut::new` should be preferred, as they use a static vtable.
|
When possible, `VRef::new` or `VRefMut::new` should be preferred, as they use a static vtable.
|
||||||
But when using the generated `XxxVTable_static!` macro is not possible, this can be used.
|
But when using the generated `XxxVTable_static!` macro that is not possible and this macro can be
|
||||||
Note that the `downcast` will not work with references created with this macro
|
used instead.
|
||||||
|
Note that the `downcast` will not work with references created with this macro.
|
||||||
|
|
||||||
```
|
```
|
||||||
use vtable::*;
|
use vtable::*;
|
||||||
|
@ -438,7 +440,7 @@ macro_rules! new_vref {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represent an offset to a field of type mathcing the vtable, within the Base container structure.
|
/// Represents an offset to a field of type matching the vtable, within the Base container structure.
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct VOffset<Base, T: ?Sized + VTableMeta, PinFlag = NotPinned> {
|
pub struct VOffset<Base, T: ?Sized + VTableMeta, PinFlag = NotPinned> {
|
||||||
vtable: &'static T::VTable,
|
vtable: &'static T::VTable,
|
||||||
|
@ -484,7 +486,7 @@ impl<Base, T: ?Sized + VTableMeta, Flag> VOffset<Base, T, Flag> {
|
||||||
|
|
||||||
/// Create a new VOffset from raw data
|
/// Create a new VOffset from raw data
|
||||||
///
|
///
|
||||||
/// Safety: there must be a field that matches the vtable at offset T in base
|
/// Safety: there must be a field that matches the vtable at offset T in base.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub unsafe fn from_raw(vtable: &'static T::VTable, offset: usize) -> Self {
|
pub unsafe fn from_raw(vtable: &'static T::VTable, offset: usize) -> Self {
|
||||||
Self { vtable, offset, phantom: PhantomData }
|
Self { vtable, offset, phantom: PhantomData }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue