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,13 +449,16 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
#vis use #module_name::*;
#[macro_export]
/// Implements HasStaticVTable<XXXVTable> for the given type
macro_rules! #static_vtable_macro_name {
($ty:ty) => {
{
unsafe impl ::vtable::HasStaticVTable<#vtable_name> for $ty {
const VTABLE: #vtable_name = {
type T = $ty;
#vtable_name {
#(#vtable_ctor)*
}
};
}
}
}
@ -463,3 +466,46 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
// println!("{}", result);
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);
}
/// 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)]
/// The inner structure of VRef, VRefMut, and VBox.
///

View file

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

View file

@ -293,10 +293,5 @@ pub static QT_BUTTON_VTABLE: ItemVTable = ItemVTable {
};
*/
#[allow(non_upper_case_globals)]
#[no_mangle]
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);
ItemVTable_static!(crate::abi::primitives::Image);
ItemVTable_static!(crate::abi::primitives::Rectangle);

View file

@ -1,6 +1,9 @@
#![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
#[repr(C)]
@ -80,4 +83,8 @@ impl ItemConsts for Image {
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;