Add the boilerplate for Struct in C++

This commit is contained in:
Simon Hausmann 2021-03-18 12:12:48 +01:00
parent 533b7f05ce
commit 02c1150fa7
3 changed files with 118 additions and 11 deletions

View file

@ -17,6 +17,74 @@ LICENSE END */
namespace sixtyfps::interpreter { namespace sixtyfps::interpreter {
class Value;
struct Struct
{
public:
Struct() { cbindgen_private::sixtyfps_interpreter_struct_new(&inner); }
Struct(const Struct &other)
{
cbindgen_private::sixtyfps_interpreter_struct_clone(&other.inner, &inner);
}
Struct(Struct &&other)
{
inner = other.inner;
cbindgen_private::sixtyfps_interpreter_struct_new(&other.inner);
}
Struct &operator=(const Struct &other)
{
if (this == &other)
return *this;
cbindgen_private::sixtyfps_interpreter_struct_destructor(&inner);
sixtyfps_interpreter_struct_clone(&other.inner, &inner);
return *this;
}
Struct &operator=(Struct &&other)
{
if (this == &other)
return *this;
cbindgen_private::sixtyfps_interpreter_struct_destructor(&inner);
inner = other.inner;
cbindgen_private::sixtyfps_interpreter_struct_new(&other.inner);
return *this;
}
~Struct() { cbindgen_private::sixtyfps_interpreter_struct_destructor(&inner); }
#if 0
Struct(std::initializer_list<std::pair<std::string_view, Value>>) template<
typename InputIterator,
typename = std::enable_if<
std::is_same(decltype(*std::declval<InputIterator>())),
std::pair<std::string_view, Value>>> // InputIterator produces
// std::pair<std::string, Value>
Struct(InputIterator begin,
InputIterator end); // Creates
// Value::Struct
struct iterator
{
//... iterator API to key/value pairs
}
iterator
begin() const;
iterator end() const;
#endif
// internal
Struct(const sixtyfps::cbindgen_private::StructOpaque &other)
{
cbindgen_private::sixtyfps_interpreter_struct_clone(&other, &inner);
}
private:
using StructOpaque = sixtyfps::cbindgen_private::StructOpaque;
StructOpaque inner;
friend class Value;
};
class Value class Value
{ {
public: public:
@ -28,6 +96,14 @@ public:
inner = other.inner; inner = other.inner;
cbindgen_private::sixtyfps_interpreter_value_new(&other.inner); cbindgen_private::sixtyfps_interpreter_value_new(&other.inner);
} }
Value &operator=(const Value &other)
{
if (this == &other)
return *this;
cbindgen_private::sixtyfps_interpreter_value_destructor(&inner);
sixtyfps_interpreter_value_clone(&other.inner, &inner);
return *this;
}
Value &operator=(Value &&other) Value &operator=(Value &&other)
{ {
if (this == &other) if (this == &other)
@ -37,14 +113,6 @@ public:
cbindgen_private::sixtyfps_interpreter_value_new(&other.inner); cbindgen_private::sixtyfps_interpreter_value_new(&other.inner);
return *this; return *this;
} }
Value &operator=(const Value &other)
{
if (this == &other)
return *this;
cbindgen_private::sixtyfps_interpreter_value_destructor(&inner);
sixtyfps_interpreter_value_clone(&other.inner, &inner);
return *this;
}
~Value() { cbindgen_private::sixtyfps_interpreter_value_destructor(&inner); } ~Value() { cbindgen_private::sixtyfps_interpreter_value_destructor(&inner); }
using Type = cbindgen_private::ValueType; using Type = cbindgen_private::ValueType;
@ -90,7 +158,14 @@ public:
return {}; return {};
} }
} }
// std::optional<Struct> to_struct() const; std::optional<Struct> to_struct() const
{
if (auto *opaque_struct = cbindgen_private::sixtyfps_interpreter_value_to_struct(&inner)) {
return Struct(*opaque_struct);
} else {
return {};
}
}
// template<typename T> std::optional<T> get() const; // template<typename T> std::optional<T> get() const;
Value(double value) { cbindgen_private::sixtyfps_interpreter_value_new_double(value, &inner); } Value(double value) { cbindgen_private::sixtyfps_interpreter_value_new_double(value, &inner); }
@ -105,7 +180,10 @@ public:
{ {
cbindgen_private::sixtyfps_interpreter_value_new_brush(&brush, &inner); cbindgen_private::sixtyfps_interpreter_value_new_brush(&brush, &inner);
} }
// Value(const Struct &); Value(const Struct &struc)
{
cbindgen_private::sixtyfps_interpreter_value_new_struct(&struc.inner, &inner);
}
Type type() const { return cbindgen_private::sixtyfps_interpreter_value_type(&inner); } Type type() const { return cbindgen_private::sixtyfps_interpreter_value_type(&inner); }
@ -128,5 +206,4 @@ inline std::optional<sixtyfps::SharedVector<Value>> Value::to_array() const
return {}; return {};
} }
} }
} }

View file

@ -113,4 +113,15 @@ SCENARIO("Value API")
REQUIRE(brush_opt.has_value()); REQUIRE(brush_opt.has_value());
REQUIRE(brush_opt.value() == brush); REQUIRE(brush_opt.value() == brush);
} }
SECTION("Construct a struct")
{
REQUIRE(!value.to_struct().has_value());
sixtyfps::interpreter::Struct struc;
value = Value(struc);
REQUIRE(value.type() == Value::Type::Struct);
auto struct_opt = value.to_struct();
REQUIRE(struct_opt.has_value());
}
} }

View file

@ -832,6 +832,15 @@ pub(crate) mod ffi {
std::ptr::write(val as *mut Value, Value::Brush(brush.clone())) std::ptr::write(val as *mut Value, Value::Brush(brush.clone()))
} }
/// Construct a new Value in the given memory location as Struct
#[no_mangle]
pub unsafe extern "C" fn sixtyfps_interpreter_value_new_struct(
struc: &StructOpaque,
val: *mut ValueOpaque,
) {
std::ptr::write(val as *mut Value, Value::Struct(struc.as_struct().clone()))
}
#[repr(i8)] #[repr(i8)]
pub enum ValueType { pub enum ValueType {
Void, Void,
@ -907,6 +916,16 @@ pub(crate) mod ffi {
} }
} }
#[no_mangle]
pub extern "C" fn sixtyfps_interpreter_value_to_struct(
val: &ValueOpaque,
) -> Option<&StructOpaque> {
match val.as_value() {
Value::Struct(s) => Some(unsafe { std::mem::transmute::<&Struct, &StructOpaque>(s) }),
_ => None,
}
}
#[repr(C)] #[repr(C)]
pub struct StructOpaque([usize; 6]); pub struct StructOpaque([usize; 6]);
/// Asserts that StructOpaque is at least as large as Struct, otherwise this would overflow /// Asserts that StructOpaque is at least as large as Struct, otherwise this would overflow