mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-03 07:04:34 +00:00
vtable add support for field offset in the vtable
This commit is contained in:
parent
751a3fbe59
commit
5a9cbaae66
7 changed files with 100 additions and 46 deletions
|
@ -11,4 +11,4 @@ syn = { version = "1.0", features = ["full"] }
|
|||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
vtable-macro = { path="./macro" }
|
||||
|
||||
const-field-offset = { path="../const-field-offset" }
|
||||
|
|
|
@ -344,7 +344,6 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
});
|
||||
|
||||
vtable_ctor.push(quote!(#ident: {
|
||||
#[allow(unused_parens)]
|
||||
#sig_extern {
|
||||
// This is safe since the self must be a instance of our type
|
||||
#[allow(unused)]
|
||||
|
@ -364,7 +363,6 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
}
|
||||
} else {
|
||||
// associated constant
|
||||
let ty = &field.ty;
|
||||
|
||||
let generated_trait_assoc_const =
|
||||
generated_trait_assoc_const.get_or_insert_with(|| ItemTrait {
|
||||
|
@ -373,17 +371,79 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
items: vec![],
|
||||
..generated_trait.clone()
|
||||
});
|
||||
|
||||
let const_type = if let Some(o) = field
|
||||
.attrs
|
||||
.iter()
|
||||
.position(|a| a.path.get_ident().map(|a| a == "offset").unwrap_or(false))
|
||||
{
|
||||
let a = field.attrs.remove(o);
|
||||
let member_type = match parse2::<Type>(a.tokens) {
|
||||
Err(e) => return e.to_compile_error().into(),
|
||||
Ok(ty) => ty,
|
||||
};
|
||||
|
||||
match &field.ty {
|
||||
Type::Path(p) if p.path.get_ident().map(|i| i == "usize").unwrap_or(false) => {}
|
||||
ty @ _ => {
|
||||
return Error::new(
|
||||
ty.span(),
|
||||
"The type of an #[offset] member in the vtable must be 'usize'",
|
||||
)
|
||||
.to_compile_error()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
// add `: Sized` to the trait in case it does not have it
|
||||
if generated_trait_assoc_const.supertraits.is_empty() {
|
||||
generated_trait_assoc_const.colon_token = Some(Default::default());
|
||||
generated_trait_assoc_const.supertraits.push(parse2(quote!(Sized)).unwrap());
|
||||
}
|
||||
|
||||
let offset_type =
|
||||
parse2::<Type>(quote!(vtable::FieldOffset<Self, #member_type>)).unwrap();
|
||||
|
||||
vtable_ctor.push(quote!(#ident: T::#ident.get_byte_offset(),));
|
||||
|
||||
let vis = &field.vis;
|
||||
generated_to_fn_trait.push(
|
||||
parse2(quote! {
|
||||
#vis fn #ident(&self) -> &#member_type {
|
||||
unsafe {
|
||||
&*(self.ptr.as_ptr().add(self.vtable.as_ref().#ident) as *const #member_type)
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
let ident_mut = quote::format_ident!("{}_mut", ident);
|
||||
generated_to_fn_trait.push(
|
||||
parse2(quote! {
|
||||
#vis fn #ident_mut(&mut self) -> &mut #member_type {
|
||||
unsafe {
|
||||
&mut *(self.ptr.as_ptr().add(self.vtable.as_ref().#ident) as *mut #member_type)
|
||||
}
|
||||
}
|
||||
})
|
||||
.unwrap(),
|
||||
);
|
||||
|
||||
offset_type
|
||||
} else {
|
||||
vtable_ctor.push(quote!(#ident: T::#ident,));
|
||||
field.ty.clone()
|
||||
};
|
||||
|
||||
generated_trait_assoc_const.items.push(TraitItem::Const(TraitItemConst {
|
||||
attrs: field.attrs.clone(),
|
||||
const_token: Default::default(),
|
||||
ident: ident.clone(),
|
||||
colon_token: Default::default(),
|
||||
ty: ty.clone(),
|
||||
ty: const_type,
|
||||
default: None,
|
||||
semi_token: Default::default(),
|
||||
}));
|
||||
|
||||
vtable_ctor.push(quote!(#ident: T::#ident,));
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -400,6 +460,7 @@ pub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {
|
|||
#[macro_use]
|
||||
/// This private module is generated by the `vtable` macro
|
||||
mod #module_name {
|
||||
#![allow(unused_parens)]
|
||||
#[allow(unused)]
|
||||
use super::*;
|
||||
use ::vtable::*;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub use const_field_offset::FieldOffset;
|
||||
use core::marker::PhantomData;
|
||||
use core::ops::{Deref, DerefMut, Drop};
|
||||
use core::ptr::NonNull;
|
||||
|
|
|
@ -10,25 +10,28 @@ struct HelloVTable {
|
|||
drop: fn(VRefMut<'_, HelloVTable>),
|
||||
|
||||
CONSTANT: usize,
|
||||
|
||||
#[offset(u32)]
|
||||
SOME_OFFSET: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SomeStruct(u32);
|
||||
#[derive(Debug, const_field_offset::FieldOffsets)]
|
||||
#[repr(C)]
|
||||
struct SomeStruct {
|
||||
x: u32,
|
||||
}
|
||||
impl Hello for SomeStruct {
|
||||
fn foo(&self, xx: u32) -> u32 {
|
||||
println!("calling foo {} + {}", self.0, xx);
|
||||
self.0 + xx
|
||||
self.x + xx
|
||||
}
|
||||
|
||||
fn foo_mut(&mut self, xx: u32) -> u32 {
|
||||
println!("calling foo_mut {} + {}", self.0, xx);
|
||||
self.0 += xx;
|
||||
self.0
|
||||
self.x += xx;
|
||||
self.x
|
||||
}
|
||||
|
||||
fn construct(init: u32) -> Self {
|
||||
println!("calling Construct {}", init);
|
||||
Self(init)
|
||||
Self { x: init }
|
||||
}
|
||||
|
||||
fn assoc() -> isize {
|
||||
|
@ -37,6 +40,8 @@ impl Hello for SomeStruct {
|
|||
}
|
||||
impl HelloConsts for SomeStruct {
|
||||
const CONSTANT: usize = 88;
|
||||
const SOME_OFFSET: const_field_offset::FieldOffset<SomeStruct, u32> =
|
||||
SomeStruct::field_offsets().x;
|
||||
}
|
||||
|
||||
HelloVTable_static!(SomeStruct);
|
||||
|
@ -53,11 +58,12 @@ fn test() {
|
|||
assert_eq!(bx.foo(2), 97);
|
||||
assert_eq!(bx.get_vtable().CONSTANT, 88);
|
||||
|
||||
let bx2 = VBox::<HelloVTable>::new(SomeStruct(23));
|
||||
let bx2 = VBox::<HelloVTable>::new(SomeStruct { x: 23 });
|
||||
assert_eq!(bx2.foo(3), 26);
|
||||
assert_eq!(bx2.get_vtable().CONSTANT, 88);
|
||||
assert_eq!(*bx2.SOME_OFFSET(), 23);
|
||||
|
||||
let mut hello = SomeStruct(44);
|
||||
let mut hello = SomeStruct { x: 44 };
|
||||
{
|
||||
let xref = VRef::<HelloVTable>::new(&hello);
|
||||
assert_eq!(xref.foo(0), 44);
|
||||
|
@ -65,7 +71,9 @@ fn test() {
|
|||
{
|
||||
let mut xref = VRefMut::<HelloVTable>::new(&mut hello);
|
||||
assert_eq!(xref.foo_mut(2), 46);
|
||||
assert_eq!(*xref.SOME_OFFSET(), 46);
|
||||
*xref.SOME_OFFSET_mut() = 3;
|
||||
let xref2 = xref.borrow();
|
||||
assert_eq!(xref2.foo(1), 47);
|
||||
assert_eq!(xref2.foo(1), 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,7 +74,8 @@ pub struct ItemVTable {
|
|||
/// offset in bytes fromthe *const ItemImpl.
|
||||
/// isize::MAX means None
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub cached_rendering_data_offset: isize,
|
||||
#[offset(CachedRenderingData)]
|
||||
pub cached_rendering_data_offset: usize,
|
||||
|
||||
/// Return a rendering info
|
||||
pub rendering_info: extern "C" fn(VRef<'_, ItemVTable>) -> RenderingInfo,
|
||||
|
@ -112,27 +113,6 @@ pub type MouseEvent = ();
|
|||
|
||||
/* -- Safe wrappers*/
|
||||
|
||||
/*trait Item {
|
||||
fn geometry(&self) -> ();
|
||||
fn cached_rendering_data(&self) -> &CachedRenderingData;
|
||||
fn cached_rendering_data_mut(&mut self) -> &mut CachedRenderingData;
|
||||
fn rendering_info(&self) -> CachedRenderingData;
|
||||
}*/
|
||||
|
||||
pub fn cached_rendering_data(item: VRef<'_, ItemVTable>) -> &CachedRenderingData {
|
||||
unsafe {
|
||||
&*(item.as_ptr().offset(item.get_vtable().cached_rendering_data_offset)
|
||||
as *const CachedRenderingData)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cached_rendering_data_mut(item: VRefMut<'_, ItemVTable>) -> &mut CachedRenderingData {
|
||||
unsafe {
|
||||
&mut *(item.as_ptr().offset(item.get_vtable().cached_rendering_data_offset)
|
||||
as *mut CachedRenderingData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Visit each items recursively
|
||||
///
|
||||
/// The state parametter returned by the visitor is passed to each children.
|
||||
|
|
|
@ -32,8 +32,10 @@ impl Item for Rectangle {
|
|||
}
|
||||
|
||||
impl ItemConsts for Rectangle {
|
||||
const cached_rendering_data_offset: isize =
|
||||
Rectangle::field_offsets().cached_rendering_data.get_byte_offset() as isize;
|
||||
const cached_rendering_data_offset: const_field_offset::FieldOffset<
|
||||
Rectangle,
|
||||
CachedRenderingData,
|
||||
> = Rectangle::field_offsets().cached_rendering_data;
|
||||
}
|
||||
|
||||
// FIXME: remove (or use the libc one)
|
||||
|
@ -79,8 +81,10 @@ impl Item for Image {
|
|||
}
|
||||
|
||||
impl ItemConsts for Image {
|
||||
const cached_rendering_data_offset: isize =
|
||||
Image::field_offsets().cached_rendering_data.get_byte_offset() as isize;
|
||||
const cached_rendering_data_offset: const_field_offset::FieldOffset<
|
||||
Image,
|
||||
CachedRenderingData,
|
||||
> = Image::field_offsets().cached_rendering_data;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
|
|
@ -12,7 +12,7 @@ pub(crate) fn update_item_rendering_data<Backend: GraphicsBackend>(
|
|||
|
||||
println!("Caching ... {:?}", item_rendering_info);
|
||||
|
||||
let rendering_data = super::abi::datastructures::cached_rendering_data_mut(item.borrow_mut());
|
||||
let rendering_data = item.cached_rendering_data_offset_mut();
|
||||
|
||||
match item_rendering_info {
|
||||
RenderingInfo::Rectangle(_x, _y, width, height, color) => {
|
||||
|
@ -85,7 +85,7 @@ pub(crate) fn render_component_items<Backend: GraphicsBackend>(
|
|||
_ => {}
|
||||
}
|
||||
|
||||
let cached_rendering_data = super::abi::datastructures::cached_rendering_data(item);
|
||||
let cached_rendering_data = item.cached_rendering_data_offset();
|
||||
if cached_rendering_data.cache_ok {
|
||||
println!(
|
||||
"Rendering... {:?} from cache {}",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue