C++ interpreter: Use std::span instead of the internal Slice in the public API

This commit is contained in:
Olivier Goffart 2022-01-24 12:12:50 +01:00
parent d0b3adeba9
commit 973c5960b7
5 changed files with 37 additions and 32 deletions

View file

@ -3,6 +3,16 @@ All notable changes to this project will be documented in this file.
## Unreleased ## Unreleased
### Changed
- Minimum rust version is now 1.56
- C++ compiler requires C++20
- In the C++ interpreter API `std::span` is used for callbacks arguments, instead of `sixtyfps::Slice`
### Added
### Fixed
## [0.1.6] - 2022-01-21 ## [0.1.6] - 2022-01-21
### Changed ### Changed

View file

@ -17,6 +17,7 @@
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#include <condition_variable> #include <condition_variable>
#include <span>
namespace sixtyfps::cbindgen_private { namespace sixtyfps::cbindgen_private {
// Workaround https://github.com/eqrion/cbindgen/issues/43 // Workaround https://github.com/eqrion/cbindgen/issues/43
@ -48,9 +49,6 @@ using cbindgen_private::ItemWeak;
using cbindgen_private::TraversalOrder; using cbindgen_private::TraversalOrder;
} }
// FIXME: this should not be public API
using cbindgen_private::Slice;
namespace private_api { namespace private_api {
using ItemTreeNode = cbindgen_private::ItemTreeNode<uint8_t>; using ItemTreeNode = cbindgen_private::ItemTreeNode<uint8_t>;
using cbindgen_private::KeyboardModifiers; using cbindgen_private::KeyboardModifiers;
@ -161,14 +159,14 @@ constexpr inline ItemTreeNode make_dyn_node(std::uintptr_t offset, std::uint32_t
parent_index } }; parent_index } };
} }
inline ItemRef get_item_ref(ComponentRef component, Slice<ItemTreeNode> item_tree, int index) inline ItemRef get_item_ref(ComponentRef component, cbindgen_private::Slice<ItemTreeNode> item_tree, int index)
{ {
const auto &item = item_tree.ptr[index].item.item; const auto &item = item_tree.ptr[index].item.item;
return ItemRef { item.vtable, reinterpret_cast<char *>(component.instance) + item.offset }; return ItemRef { item.vtable, reinterpret_cast<char *>(component.instance) + item.offset };
} }
inline ItemWeak parent_item(cbindgen_private::ComponentWeak component, inline ItemWeak parent_item(cbindgen_private::ComponentWeak component,
Slice<ItemTreeNode> item_tree, int index) cbindgen_private::Slice<ItemTreeNode> item_tree, int index)
{ {
const auto &node = item_tree.ptr[index]; const auto &node = item_tree.ptr[index];
if (node.tag == ItemTreeNode::Tag::Item) { if (node.tag == ItemTreeNode::Tag::Item) {
@ -412,10 +410,10 @@ inline bool operator!=(const LayoutInfo &a, const LayoutInfo &b)
namespace private_api { namespace private_api {
inline SharedVector<float> solve_box_layout(const cbindgen_private::BoxLayoutData &data, inline SharedVector<float> solve_box_layout(const cbindgen_private::BoxLayoutData &data,
Slice<int> repeater_indexes) cbindgen_private::Slice<int> repeater_indexes)
{ {
SharedVector<float> result; SharedVector<float> result;
Slice<uint32_t> ri { reinterpret_cast<uint32_t *>(repeater_indexes.ptr), repeater_indexes.len }; cbindgen_private::Slice<uint32_t> ri { reinterpret_cast<uint32_t *>(repeater_indexes.ptr), repeater_indexes.len };
cbindgen_private::sixtyfps_solve_box_layout(&data, ri, &result); cbindgen_private::sixtyfps_solve_box_layout(&data, ri, &result);
return result; return result;
} }
@ -428,14 +426,14 @@ inline SharedVector<float> solve_grid_layout(const cbindgen_private::GridLayoutD
} }
inline cbindgen_private::LayoutInfo inline cbindgen_private::LayoutInfo
grid_layout_info(Slice<cbindgen_private::GridLayoutCellData> cells, float spacing, grid_layout_info(cbindgen_private::Slice<cbindgen_private::GridLayoutCellData> cells, float spacing,
const cbindgen_private::Padding &padding) const cbindgen_private::Padding &padding)
{ {
return cbindgen_private::sixtyfps_grid_layout_info(cells, spacing, &padding); return cbindgen_private::sixtyfps_grid_layout_info(cells, spacing, &padding);
} }
inline cbindgen_private::LayoutInfo inline cbindgen_private::LayoutInfo
box_layout_info(Slice<cbindgen_private::BoxLayoutCellData> cells, float spacing, box_layout_info(cbindgen_private::Slice<cbindgen_private::BoxLayoutCellData> cells, float spacing,
const cbindgen_private::Padding &padding, const cbindgen_private::Padding &padding,
cbindgen_private::LayoutAlignment alignment) cbindgen_private::LayoutAlignment alignment)
{ {
@ -443,17 +441,17 @@ box_layout_info(Slice<cbindgen_private::BoxLayoutCellData> cells, float spacing,
} }
inline cbindgen_private::LayoutInfo inline cbindgen_private::LayoutInfo
box_layout_info_ortho(Slice<cbindgen_private::BoxLayoutCellData> cells, box_layout_info_ortho(cbindgen_private::Slice<cbindgen_private::BoxLayoutCellData> cells,
const cbindgen_private::Padding &padding) const cbindgen_private::Padding &padding)
{ {
return cbindgen_private::sixtyfps_box_layout_info_ortho(cells, &padding); return cbindgen_private::sixtyfps_box_layout_info_ortho(cells, &padding);
} }
inline SharedVector<float> solve_path_layout(const cbindgen_private::PathLayoutData &data, inline SharedVector<float> solve_path_layout(const cbindgen_private::PathLayoutData &data,
Slice<int> repeater_indexes) cbindgen_private::Slice<int> repeater_indexes)
{ {
SharedVector<float> result; SharedVector<float> result;
Slice<uint32_t> ri { reinterpret_cast<uint32_t *>(repeater_indexes.ptr), repeater_indexes.len }; cbindgen_private::Slice<uint32_t> ri { reinterpret_cast<uint32_t *>(repeater_indexes.ptr), repeater_indexes.len };
cbindgen_private::sixtyfps_solve_path_layout(&data, ri, &result); cbindgen_private::sixtyfps_solve_path_layout(&data, ri, &result);
return result; return result;
} }

View file

@ -612,7 +612,6 @@ public:
return {}; return {};
} }
} }
// FIXME! Slice in public API? Should be std::span (c++20) or we need to improve the Slice API
/// Invoke the specified callback declared in .60 with the given arguments /// Invoke the specified callback declared in .60 with the given arguments
/// ///
/// Example: imagine the .60 file contains the given callback declaration: /// Example: imagine the .60 file contains the given callback declaration:
@ -628,10 +627,10 @@ public:
/// Returns an null optional if the callback don't exist or if the argument don't match /// Returns an null optional if the callback don't exist or if the argument don't match
/// Otherwise return the returned value from the callback, which may be an empty Value if /// Otherwise return the returned value from the callback, which may be an empty Value if
/// the callback did not return a value. /// the callback did not return a value.
std::optional<Value> invoke_callback(std::string_view name, Slice<Value> args) const std::optional<Value> invoke_callback(std::string_view name, std::span<const Value> args) const
{ {
using namespace cbindgen_private; using namespace cbindgen_private;
Slice<ValueOpaque> args_view { reinterpret_cast<ValueOpaque *>(args.ptr), args.len }; Slice<ValueOpaque> args_view { const_cast<ValueOpaque *>(reinterpret_cast<const ValueOpaque *>(args.data())), args.size() };
ValueOpaque out; ValueOpaque out;
if (sixtyfps_interpreter_component_instance_invoke_callback( if (sixtyfps_interpreter_component_instance_invoke_callback(
inner(), sixtyfps::private_api::string_to_slice(name), args_view, &out)) { inner(), sixtyfps::private_api::string_to_slice(name), args_view, &out)) {
@ -666,8 +665,8 @@ public:
bool set_callback(std::string_view name, F callback) const bool set_callback(std::string_view name, F callback) const
{ {
using cbindgen_private::ValueOpaque; using cbindgen_private::ValueOpaque;
auto actual_cb = [](void *data, Slice<ValueOpaque> arg, ValueOpaque *ret) { auto actual_cb = [](void *data, cbindgen_private::Slice<ValueOpaque> arg, ValueOpaque *ret) {
Slice<Value> args_view { reinterpret_cast<Value *>(arg.ptr), arg.len }; std::span<const Value> args_view { reinterpret_cast<const Value *>(arg.ptr), arg.len };
Value r = (*reinterpret_cast<F *>(data))(args_view); Value r = (*reinterpret_cast<F *>(data))(args_view);
new (ret) Value(std::move(r)); new (ret) Value(std::move(r));
}; };
@ -730,8 +729,8 @@ public:
bool set_global_callback(std::string_view global, std::string_view name, F callback) const bool set_global_callback(std::string_view global, std::string_view name, F callback) const
{ {
using cbindgen_private::ValueOpaque; using cbindgen_private::ValueOpaque;
auto actual_cb = [](void *data, Slice<ValueOpaque> arg, ValueOpaque *ret) { auto actual_cb = [](void *data, cbindgen_private::Slice<ValueOpaque> arg, ValueOpaque *ret) {
Slice<Value> args_view { reinterpret_cast<Value *>(arg.ptr), arg.len }; std::span<const Value> args_view { reinterpret_cast<const Value *>(arg.ptr), arg.len };
Value r = (*reinterpret_cast<F *>(data))(args_view); Value r = (*reinterpret_cast<F *>(data))(args_view);
new (ret) Value(std::move(r)); new (ret) Value(std::move(r));
}; };
@ -741,14 +740,13 @@ public:
[](void *data) { delete reinterpret_cast<F *>(data); }); [](void *data) { delete reinterpret_cast<F *>(data); });
} }
// FIXME! Slice in public API? Should be std::span (c++20) or we need to improve the Slice API
/// Invoke the specified callback declared in an exported global singleton /// Invoke the specified callback declared in an exported global singleton
std::optional<Value> invoke_global_callback(std::string_view global, std::optional<Value> invoke_global_callback(std::string_view global,
std::string_view callback_name, std::string_view callback_name,
Slice<Value> args) const std::span<const Value> args) const
{ {
using namespace cbindgen_private; using namespace cbindgen_private;
Slice<ValueOpaque> args_view { reinterpret_cast<ValueOpaque *>(args.ptr), args.len }; Slice<ValueOpaque> args_view { const_cast<ValueOpaque *>(reinterpret_cast<const ValueOpaque *>(args.data())), args.size() };
ValueOpaque out; ValueOpaque out;
if (sixtyfps_interpreter_component_instance_invoke_global_callback( if (sixtyfps_interpreter_component_instance_invoke_global_callback(
inner(), sixtyfps::private_api::string_to_slice(global), inner(), sixtyfps::private_api::string_to_slice(global),

View file

@ -366,7 +366,7 @@ SCENARIO("Invoke callback")
return Value(SharedString(res)); return Value(SharedString(res));
})); }));
Value args[] = { SharedString("Hello"), 42. }; Value args[] = { SharedString("Hello"), 42. };
auto res = instance->invoke_callback("some_callback", Slice<Value> { args, 2 }); auto res = instance->invoke_callback("some_callback", args);
REQUIRE(res.has_value()); REQUIRE(res.has_value());
REQUIRE(*res->to_string() == SharedString("Hello:42")); REQUIRE(*res->to_string() == SharedString("Hello:42"));
} }
@ -379,7 +379,7 @@ SCENARIO("Invoke callback")
auto instance = result->create(); auto instance = result->create();
REQUIRE(!instance->set_callback("bar", [](auto) { return Value(); })); REQUIRE(!instance->set_callback("bar", [](auto) { return Value(); }));
Value args[] = { SharedString("Hello"), 42. }; Value args[] = { SharedString("Hello"), 42. };
auto res = instance->invoke_callback("bar", Slice<Value> { args, 2 }); auto res = instance->invoke_callback("bar", args);
REQUIRE(!res.has_value()); REQUIRE(!res.has_value());
} }
} }
@ -573,8 +573,7 @@ SCENARIO("Global properties")
REQUIRE(result->to_string().value() == "ABC"); REQUIRE(result->to_string().value() == "ABC");
Value args[] = { SharedString("Hello") }; Value args[] = { SharedString("Hello") };
auto res = instance->invoke_global_callback("The_Global", "to-uppercase", auto res = instance->invoke_global_callback("The_Global", "to-uppercase", args);
Slice<Value> { args, 1 });
REQUIRE(res.has_value()); REQUIRE(res.has_value());
REQUIRE(*res->to_string() == SharedString("HELLO")); REQUIRE(*res->to_string() == SharedString("HELLO"));
} }

View file

@ -934,7 +934,7 @@ fn generate_item_tree(
Access::Private, Access::Private,
Declaration::Function(Function { Declaration::Function(Function {
name: "item_tree".into(), name: "item_tree".into(),
signature: "() -> sixtyfps::Slice<sixtyfps::private_api::ItemTreeNode>".into(), signature: "() -> sixtyfps::cbindgen_private::Slice<sixtyfps::private_api::ItemTreeNode>".into(),
is_static: true, is_static: true,
statements: Some(vec![ statements: Some(vec![
"static const sixtyfps::private_api::ItemTreeNode children[] {".to_owned(), "static const sixtyfps::private_api::ItemTreeNode children[] {".to_owned(),
@ -1953,7 +1953,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => { crate::expression_tree::ImageReference::EmbeddedData { resource_id, extension } => {
let symbol = format!("sfps_embedded_resource_{}", resource_id); let symbol = format!("sfps_embedded_resource_{}", resource_id);
format!( format!(
r#"sixtyfps::Image(sixtyfps::cbindgen_private::types::ImageInner::EmbeddedData(sixtyfps::Slice<uint8_t>{{std::data({}), std::size({})}}, sixtyfps::Slice<uint8_t>{{const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(u8"{}")), {}}}))"#, r#"sixtyfps::Image(sixtyfps::cbindgen_private::types::ImageInner::EmbeddedData(sixtyfps::cbindgen_private::Slice<uint8_t>{{std::data({}), std::size({})}}, sixtyfps::cbindgen_private::Slice<uint8_t>{{const_cast<uint8_t *>(reinterpret_cast<const uint8_t *>(u8"{}")), {}}}))"#,
symbol, symbol, escape_string(extension), extension.as_bytes().len() symbol, symbol, escape_string(extension), extension.as_bytes().len()
) )
} }
@ -1986,7 +1986,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
) )
} else { } else {
format!( format!(
"sixtyfps::Slice<{ty}>{{ std::array<{ty}, {count}>{{ {val} }}.data(), {count} }}", "sixtyfps::cbindgen_private::Slice<{ty}>{{ std::array<{ty}, {count}>{{ {val} }}.data(), {count} }}",
count = values.len(), count = values.len(),
ty = ty, ty = ty,
val = val.join(", ") val = val.join(", ")
@ -2072,7 +2072,7 @@ fn compile_expression(expr: &llr::Expression, ctx: &EvaluationContext) -> String
}; };
format!("sixtyfps::cbindgen_private::GridLayoutCellData {cv}_array [] = {{ {c} }};\ format!("sixtyfps::cbindgen_private::GridLayoutCellData {cv}_array [] = {{ {c} }};\
sixtyfps::cbindgen_private::sixtyfps_reorder_dialog_button_layout({cv}_array, {r});\ sixtyfps::cbindgen_private::sixtyfps_reorder_dialog_button_layout({cv}_array, {r});\
sixtyfps::Slice<sixtyfps::cbindgen_private::GridLayoutCellData> {cv} {{ std::data({cv}_array), std::size({cv}_array) }}", sixtyfps::cbindgen_private::Slice<sixtyfps::cbindgen_private::GridLayoutCellData> {cv} {{ std::data({cv}_array), std::size({cv}_array) }}",
r = compile_expression(roles, ctx), r = compile_expression(roles, ctx),
cv = cells_variable, cv = cells_variable,
c = cells.join(", "), c = cells.join(", "),
@ -2271,13 +2271,13 @@ fn box_layout_function(
let ri = repeated_indices.as_ref().map_or(String::new(), |ri| { let ri = repeated_indices.as_ref().map_or(String::new(), |ri| {
push_code += &format!( push_code += &format!(
"sixtyfps::Slice<int> {ri}{{ {ri}_array.data(), {ri}_array.size() }};", "sixtyfps::cbindgen_private::Slice<int> {ri}{{ {ri}_array.data(), {ri}_array.size() }};",
ri = ri ri = ri
); );
format!("std::array<int, {}> {}_array;", 2 * repeater_idx, ri) format!("std::array<int, {}> {}_array;", 2 * repeater_idx, ri)
}); });
format!( format!(
"[&]{{ {} {} sixtyfps::Slice<sixtyfps::cbindgen_private::BoxLayoutCellData>{}{{cells_vector.data(), cells_vector.size()}}; return {}; }}()", "[&]{{ {} {} sixtyfps::cbindgen_private::Slice<sixtyfps::cbindgen_private::BoxLayoutCellData>{}{{cells_vector.data(), cells_vector.size()}}; return {}; }}()",
ri, ri,
push_code, push_code,
ident(cells_variable), ident(cells_variable),