Add C++ Value Array construction/extraction

This commit is contained in:
Simon Hausmann 2021-03-17 16:52:30 +01:00
parent e20dd384f5
commit 79612d7354
3 changed files with 61 additions and 7 deletions

View file

@ -77,7 +77,7 @@ public:
return {}; return {};
} }
} }
std::optional<sixtyfps::SharedVector<Value>> to_array() const; inline std::optional<sixtyfps::SharedVector<Value>> to_array() const;
std::optional<std::shared_ptr<sixtyfps::Model<Value>>> to_model() const; std::optional<std::shared_ptr<sixtyfps::Model<Value>>> to_model() const;
std::optional<sixtyfps::Brush> to_brush() const; std::optional<sixtyfps::Brush> to_brush() const;
// std::optional<Struct> to_struct() const; // std::optional<Struct> to_struct() const;
@ -89,7 +89,7 @@ public:
cbindgen_private::sixtyfps_interpreter_value_new_string(&str, &inner); cbindgen_private::sixtyfps_interpreter_value_new_string(&str, &inner);
} }
Value(bool b) { cbindgen_private::sixtyfps_interpreter_value_new_bool(b, &inner); } Value(bool b) { cbindgen_private::sixtyfps_interpreter_value_new_bool(b, &inner); }
Value(const SharedVector<Value> &); inline Value(const SharedVector<Value> &);
Value(const std::shared_ptr<sixtyfps::Model<Value>> &); Value(const std::shared_ptr<sixtyfps::Model<Value>> &);
Value(const sixtyfps::Brush &); Value(const sixtyfps::Brush &);
// Value(const Struct &); // Value(const Struct &);
@ -98,7 +98,23 @@ public:
Type type() const { return cbindgen_private::sixtyfps_interpreter_value_type(&inner); } Type type() const { return cbindgen_private::sixtyfps_interpreter_value_type(&inner); }
private: private:
sixtyfps::cbindgen_private::ValueOpaque inner; using ValueOpaque = sixtyfps::cbindgen_private::ValueOpaque;
ValueOpaque inner;
}; };
inline Value::Value(const sixtyfps::SharedVector<Value> &array)
{
cbindgen_private::sixtyfps_interpreter_value_new_array(
&reinterpret_cast<const sixtyfps::SharedVector<ValueOpaque> &>(array), &inner);
}
inline std::optional<sixtyfps::SharedVector<Value>> Value::to_array() const
{
if (auto *array = cbindgen_private::sixtyfps_interpreter_value_to_array(&inner)) {
return *reinterpret_cast<const sixtyfps::SharedVector<Value> *>(array);
} else {
return {};
}
}
} }

View file

@ -85,4 +85,20 @@ SCENARIO("Value API")
REQUIRE(bool_opt.has_value()); REQUIRE(bool_opt.has_value());
REQUIRE(bool_opt.value() == true); REQUIRE(bool_opt.value() == true);
} }
SECTION("Construct an array")
{
REQUIRE(!value.to_array().has_value());
sixtyfps::SharedVector<Value> array { Value(42.0), Value(true) };
value = Value(array);
REQUIRE(value.type() == Value::Type::Array);
auto array_opt = value.to_array();
REQUIRE(array_opt.has_value());
auto extracted_array = array_opt.value();
REQUIRE(extracted_array.size() == 2);
REQUIRE(extracted_array[0].to_number().value() == 42);
REQUIRE(extracted_array[1].to_bool().value());
}
} }

View file

@ -750,6 +750,7 @@ pub(crate) mod ffi {
pub struct ValueOpaque([usize; 7]); pub struct ValueOpaque([usize; 7]);
/// Asserts that ValueOpaque is at least as large as Value, otherwise this would overflow /// Asserts that ValueOpaque is at least as large as Value, otherwise this would overflow
const _: usize = std::mem::size_of::<ValueOpaque>() - std::mem::size_of::<Value>(); const _: usize = std::mem::size_of::<ValueOpaque>() - std::mem::size_of::<Value>();
const _: [(); std::mem::align_of::<ValueOpaque>()] = [(); std::mem::align_of::<Value>()];
impl ValueOpaque { impl ValueOpaque {
fn as_value(&self) -> &Value { fn as_value(&self) -> &Value {
@ -788,7 +789,7 @@ pub(crate) mod ffi {
std::ptr::write(val as *mut Value, Value::String(str.clone())) std::ptr::write(val as *mut Value, Value::String(str.clone()))
} }
/// Construct a new Value in the given memory location as string /// Construct a new Value in the given memory location as double
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sixtyfps_interpreter_value_new_double( pub unsafe extern "C" fn sixtyfps_interpreter_value_new_double(
double: f64, double: f64,
@ -797,12 +798,30 @@ pub(crate) mod ffi {
std::ptr::write(val as *mut Value, Value::Number(double)) std::ptr::write(val as *mut Value, Value::Number(double))
} }
/// Construct a new Value in the given memory location as string /// Construct a new Value in the given memory location as bool
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn sixtyfps_interpreter_value_new_bool(b: bool, val: *mut ValueOpaque) { pub unsafe extern "C" fn sixtyfps_interpreter_value_new_bool(b: bool, val: *mut ValueOpaque) {
std::ptr::write(val as *mut Value, Value::Bool(b)) std::ptr::write(val as *mut Value, Value::Bool(b))
} }
/// Construct a new Value in the given memory location as array
#[no_mangle]
pub unsafe extern "C" fn sixtyfps_interpreter_value_new_array(
a: &SharedVector<ValueOpaque>,
val: *mut ValueOpaque,
) {
std::ptr::write(
val as *mut Value,
Value::Array(
{
// Safety: We assert that Value and ValueOpaque have the same size and alignment
std::mem::transmute::<&SharedVector<ValueOpaque>, &SharedVector<Value>>(a)
}
.clone(),
),
)
}
#[repr(i8)] #[repr(i8)]
pub enum ValueType { pub enum ValueType {
Void, Void,
@ -860,9 +879,12 @@ pub(crate) mod ffi {
#[no_mangle] #[no_mangle]
pub extern "C" fn sixtyfps_interpreter_value_to_array( pub extern "C" fn sixtyfps_interpreter_value_to_array(
val: &ValueOpaque, val: &ValueOpaque,
) -> Option<&SharedVector<Value>> { ) -> Option<&SharedVector<ValueOpaque>> {
match val.as_value() { match val.as_value() {
Value::Array(v) => Some(v), Value::Array(v) => Some(unsafe {
// Safety: We assert that Value and ValueOpaque have the same size and alignment
std::mem::transmute::<&SharedVector<Value>, &SharedVector<ValueOpaque>>(v)
}),
_ => None, _ => None,
} }
} }