Fix build of generated Rust code for path elements with the llr

* Move the C++ elements back into private_api (despite being generated), so that struct_name_to_tokens can generate the right name in re_exports
* When generating the llr_Expression::Struct for the path elements, make sure
  that all fields are filled out, to avoid an empty value expression in Expression::Struct
  in the Rust generator. Since we don't generate tuples but a named struct, we must provide all fields.
This commit is contained in:
Simon Hausmann 2022-01-10 17:21:51 +01:00 committed by Olivier Goffart
parent 35446e1c82
commit 44297bad24
5 changed files with 30 additions and 123 deletions

View file

@ -8,6 +8,9 @@
// The C++ code generator assumes that enums are in the cbindgen_private namespace
namespace sixtyfps::cbindgen_private {
using cbindgen_private::types::PathEvent;
}
namespace sixtyfps::private_api {
using cbindgen_private::types::PathArcTo;
using cbindgen_private::types::PathCubicTo;
using cbindgen_private::types::PathElement;
@ -16,11 +19,6 @@ using cbindgen_private::types::PathLineTo;
using cbindgen_private::types::PathMoveTo;
using cbindgen_private::types::PathQuadraticTo;
using cbindgen_private::types::Point;
}
namespace sixtyfps::private_api {
using cbindgen_private::types::PathElement;
using cbindgen_private::types::PathEvent;
using cbindgen_private::types::Point;
struct PathData
{

View file

@ -270,7 +270,7 @@ MoveTo := _ {
property <float> y;
//-rust_type_constructor:sixtyfps::re_exports::PathElement::MoveTo(PathMoveTo{{}})
//-cpp_type:sixtyfps::cbindgen_private::PathMoveTo
//-cpp_type:sixtyfps::private_api::PathMoveTo
//-is_non_item_type
}
@ -279,7 +279,7 @@ LineTo := _ {
property <float> y;
//-rust_type_constructor:sixtyfps::re_exports::PathElement::LineTo(PathLineTo{{}})
//-cpp_type:sixtyfps::cbindgen_private::PathLineTo
//-cpp_type:sixtyfps::private_api::PathLineTo
//-is_non_item_type
}
@ -293,7 +293,7 @@ ArcTo := _ {
property <bool> sweep;
//-rust_type_constructor:sixtyfps::re_exports::PathElement::ArcTo(PathArcTo{{}})
//-cpp_type:sixtyfps::cbindgen_private::PathArcTo
//-cpp_type:sixtyfps::private_api::PathArcTo
//-is_non_item_type
}
@ -306,7 +306,7 @@ CubicTo := _ {
property <float> y;
//-rust_type_constructor:sixtyfps::re_exports::PathElement::CubicTo(PathCubicTo{{}})
//-cpp_type:sixtyfps::cbindgen_private::PathCubicTo
//-cpp_type:sixtyfps::private_api::PathCubicTo
//-is_non_item_type
}
@ -317,7 +317,7 @@ QuadraticTo := _ {
property <float> y;
//-rust_type_constructor:sixtyfps::re_exports::PathElement::QuadraticTo(PathQuadraticTo{{}})
//-cpp_type:sixtyfps::cbindgen_private::PathQuadraticTo
//-cpp_type:sixtyfps::private_api::PathQuadraticTo
//-is_non_item_type
}

View file

@ -2731,14 +2731,14 @@ fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>)
})
.unwrap_or_default();
format!(
"sixtyfps::cbindgen_private::PathElement::{}({})",
"sixtyfps::private_api::PathElement::{}({})",
element.element_type.native_class.class_name, element_initializer
)
})
.collect();
format!(
r#"[&](){{
sixtyfps::cbindgen_private::PathElement elements[{}] = {{
sixtyfps::private_api::PathElement elements[{}] = {{
{}
}};
return sixtyfps::private_api::PathData(&elements[0], std::size(elements));
@ -2756,10 +2756,10 @@ fn compile_path(path: &crate::expression_tree::Path, component: &Rc<Component>)
format!(
r#"[&](){{
sixtyfps::cbindgen_private::PathEvent events[{}] = {{
sixtyfps::private_api::PathEvent events[{}] = {{
{}
}};
sixtyfps::cbindgen_private::Point coordinates[{}] = {{
sixtyfps::private_api::Point coordinates[{}] = {{
{}
}};
return sixtyfps::private_api::PathData(&events[0], std::size(events), &coordinates[0], std::size(coordinates));

View file

@ -1939,109 +1939,6 @@ fn box_layout_function(
} }
}
/*
fn compile_path_events(events: &[crate::expression_tree::PathEvent]) -> TokenStream {
use lyon_path::Event;
let mut coordinates = Vec::new();
let converted_events: Vec<proc_macro2::TokenStream> = events
.iter()
.map(|event| match event {
Event::Begin { at } => {
coordinates.push(at);
quote!(sixtyfps::re_exports::PathEvent::Begin)
}
Event::Line { from, to } => {
coordinates.push(from);
coordinates.push(to);
quote!(sixtyfps::re_exports::PathEvent::Line)
}
Event::Quadratic { from, ctrl, to } => {
coordinates.push(from);
coordinates.push(ctrl);
coordinates.push(to);
quote!(sixtyfps::re_exports::PathEvent::Quadratic)
}
Event::Cubic { from, ctrl1, ctrl2, to } => {
coordinates.push(from);
coordinates.push(ctrl1);
coordinates.push(ctrl2);
coordinates.push(to);
quote!(sixtyfps::re_exports::PathEvent::Cubic)
}
Event::End { close, .. } => {
if *close {
quote!(sixtyfps::re_exports::PathEvent::EndClosed)
} else {
quote!(sixtyfps::re_exports::PathEvent::EndOpen)
}
}
})
.collect();
let coordinates: Vec<TokenStream> = coordinates
.into_iter()
.map(|pt| {
let x = pt.x;
let y = pt.y;
quote!(sixtyfps::re_exports::Point::new(#x, #y))
})
.collect();
quote!(sixtyfps::re_exports::SharedVector::<sixtyfps::re_exports::PathEvent>::from_slice(&[#(#converted_events),*]),
sixtyfps::re_exports::SharedVector::<sixtyfps::re_exports::Point>::from_slice(&[#(#coordinates),*]))
}
fn compile_path(path: &Path, component: &Rc<Component>) -> TokenStream {
match path {
Path::Elements(elements) => {
let converted_elements: Vec<TokenStream> = elements
.iter()
.map(|element| {
let mut bindings = element
.bindings
.iter()
.map(|(property, expr)| {
let prop_ident = ident(property);
let binding_expr = compile_expression(&expr.borrow(), component);
quote!(#prop_ident: #binding_expr as _).to_string()
})
.collect::<Vec<String>>();
if bindings.len() < element.element_type.properties.len() {
bindings.push("..Default::default()".into())
}
let bindings = bindings.join(",");
let ctor_format_string = element
.element_type
.native_class.rust_type_constructor
.as_ref()
.expect(
"Unexpected error in type registry: path element is lacking rust type name",
);
ctor_format_string
.replace("{}", &bindings)
.parse()
.expect("Error parsing rust path element constructor")
})
.collect();
quote!(sixtyfps::re_exports::PathData::Elements(
sixtyfps::re_exports::SharedVector::<sixtyfps::re_exports::PathElement>::from_slice(&[#(#converted_elements),*])
))
}
Path::Events(events) => {
let events = compile_path_events(events);
quote!(sixtyfps::re_exports::PathData::Events(#events))
}
}
}
*/
// In Rust debug builds, accessing the member of the FIELD_OFFSETS ends up copying the
// entire FIELD_OFFSETS into a new stack allocation, which with large property
// binding initialization functions isn't re-used and with large generated inner

View file

@ -866,7 +866,7 @@ fn compile_path(
let converted_elements = elements
.iter()
.map(|element| {
let ty = Type::Struct {
let element_type = Type::Struct {
fields: element
.element_type
.properties
@ -878,14 +878,26 @@ fn compile_path(
};
llr_Expression::Struct {
ty,
ty: element_type,
values: element
.bindings
.element_type
.properties
.iter()
.map(|(property, expr)| {
.map(|(element_field_name, element_property)| {
(
property.clone(),
lower_expression(&expr.borrow().expression, ctx).unwrap(),
element_field_name.clone(),
element.bindings.get(element_field_name).map_or_else(
|| {
llr_Expression::default_value_for_type(
&element_property.ty,
)
.unwrap()
},
|expr| {
lower_expression(&expr.borrow().expression, ctx)
.unwrap()
},
),
)
})
.collect(),