Add a trait to get the vtable for a type

This commit is contained in:
Olivier Goffart 2020-05-16 08:39:10 +02:00
parent 4ca45ca4da
commit b745c616f7
5 changed files with 72 additions and 13 deletions

View file

@ -449,17 +449,63 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
#vis use #module_name::*; #vis use #module_name::*;
#[macro_export] #[macro_export]
/// Implements HasStaticVTable<XXXVTable> for the given type
macro_rules! #static_vtable_macro_name { macro_rules! #static_vtable_macro_name {
($ty:ty) => { ($ty:ty) => {
{ unsafe impl ::vtable::HasStaticVTable<#vtable_name> for $ty {
const VTABLE: #vtable_name = {
type T = $ty; type T = $ty;
#vtable_name { #vtable_name {
#(#vtable_ctor)* #(#vtable_ctor)*
} }
} };
} }
} }
}
); );
// println!("{}", result); // println!("{}", result);
result.into() result.into()
} }
/*
#[proc_macro_attribute]
pub fn static_vtable(attr: TokenStream, item: TokenStream) -> TokenStream {
let mut input = parse_macro_input!(item as ItemStatic);
let ty = parse_macro_input!(attr as Type);
let input_ty = &input.ty;
let vtable_type = if let Type::Path(pat) = &**input_ty {
if let Some(seg) = pat.path.segments.last() {
seg.ident.clone()
} else {
return Error::new(proc_macro2::Span::call_site(), "Could not find the VTableType")
.to_compile_error()
.into();
}
} else {
return Error::new(proc_macro2::Span::call_site(), "Could not find the VTableType")
.to_compile_error()
.into();
};
if !vtable_type.to_string().ends_with("VTable") {
return Error::new(input.ident.span(), "The type does not ends in 'VTable'")
.to_compile_error()
.into();
}
let mac = quote::format_ident!("{}_static", vtable_type);
input.expr =
Box::new(parse2(quote!(<#ty as ::vtable::HasStaticVTable<#input_ty>>::VTABLE)).unwrap());
quote!(
#input
unsafe impl ::vtable::HasStaticVTable<#input_ty> for #ty
{
const VTABLE : <#input_ty as ::vtable::VTableMeta>::VTable = #mac!(#ty);
}
)
.into()
}
*/

View file

@ -19,6 +19,16 @@ pub trait VTableMetaDrop: VTableMeta {
unsafe fn drop(ptr: *mut Self::Target); unsafe fn drop(ptr: *mut Self::Target);
} }
/// Allow to associate a VTable to a type.
pub unsafe trait HasStaticVTable<VT>
where
VT: ?Sized + VTableMeta,
VT::VTable: 'static,
{
/// Savety: must be a valid VTable for Self
const VTABLE: VT::VTable;
}
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
/// The inner structure of VRef, VRefMut, and VBox. /// The inner structure of VRef, VRefMut, and VBox.
/// ///

View file

@ -39,7 +39,8 @@ impl HelloConsts for SomeStruct {
const CONSTANT: usize = 88; const CONSTANT: usize = 88;
} }
static SOME_STRUCT_TYPE: HelloVTable = HelloVTable_static!(SomeStruct); HelloVTable_static!(SomeStruct);
static SOME_STRUCT_TYPE: HelloVTable = SomeStruct::VTABLE;
#[test] #[test]
fn test() { fn test() {

View file

@ -293,10 +293,5 @@ pub static QT_BUTTON_VTABLE: ItemVTable = ItemVTable {
}; };
*/ */
#[allow(non_upper_case_globals)] ItemVTable_static!(crate::abi::primitives::Image);
#[no_mangle] ItemVTable_static!(crate::abi::primitives::Rectangle);
pub static RectangleVTable: ItemVTable = ItemVTable_static!(crate::abi::primitives::Rectangle);
#[allow(non_upper_case_globals)]
#[no_mangle]
pub static ImageVTable: ItemVTable = ItemVTable_static!(crate::abi::primitives::Image);

View file

@ -1,6 +1,9 @@
#![allow(non_upper_case_globals)] #![allow(non_upper_case_globals)]
use super::datastructures::{CachedRenderingData, Item, ItemConsts, LayoutInfo, RenderingInfo}; use super::datastructures::{
CachedRenderingData, Item, ItemConsts, ItemVTable, LayoutInfo, RenderingInfo,
};
use vtable::HasStaticVTable;
/// FIXME: more properties /// FIXME: more properties
#[repr(C)] #[repr(C)]
@ -80,4 +83,8 @@ impl ItemConsts for Image {
Image::field_offsets().cached_rendering_data as isize; Image::field_offsets().cached_rendering_data as isize;
} }
pub use super::datastructures::{ImageVTable, RectangleVTable}; #[no_mangle]
pub static RectangleVTable: ItemVTable = Image::VTABLE;
#[no_mangle]
pub static ImageVTable: ItemVTable = Rectangle::VTABLE;