Move field accessors from Value to Struct in C++

This commit is contained in:
Simon Hausmann 2021-03-18 13:33:50 +01:00
parent 3335ff8da5
commit c6740fe592
2 changed files with 64 additions and 22 deletions

View file

@ -73,6 +73,9 @@ public:
iterator end() const; iterator end() const;
#endif #endif
inline std::optional<Value> get_field(std::string_view name) const;
inline void set_field(std::string_view name, const Value &value);
// internal // internal
Struct(const sixtyfps::cbindgen_private::StructOpaque &other) Struct(const sixtyfps::cbindgen_private::StructOpaque &other)
{ {
@ -117,11 +120,6 @@ public:
using Type = cbindgen_private::ValueType; using Type = cbindgen_private::ValueType;
// only works on Type::Struct
std::optional<Value> get_field(std::string_view) const;
// only works on Type::Struct
bool set_field(std::string_view, Value); // returns false if Value is not a Struct
// optional<int> to_int() const; // optional<int> to_int() const;
// optional<float> to_float() const; // optional<float> to_float() const;
std::optional<double> to_number() const std::optional<double> to_number() const
@ -187,9 +185,13 @@ public:
Type type() const { return cbindgen_private::sixtyfps_interpreter_value_type(&inner); } Type type() const { return cbindgen_private::sixtyfps_interpreter_value_type(&inner); }
// internal
Value(const sixtyfps::cbindgen_private::ValueOpaque &inner) : inner(inner) { }
private: private:
using ValueOpaque = sixtyfps::cbindgen_private::ValueOpaque; using ValueOpaque = sixtyfps::cbindgen_private::ValueOpaque;
ValueOpaque inner; ValueOpaque inner;
friend class Struct;
}; };
inline Value::Value(const sixtyfps::SharedVector<Value> &array) inline Value::Value(const sixtyfps::SharedVector<Value> &array)
@ -206,17 +208,18 @@ inline std::optional<sixtyfps::SharedVector<Value>> Value::to_array() const
return {}; return {};
} }
} }
inline Value::Value(const std::shared_ptr<sixtyfps::Model<Value>> &model) { inline Value::Value(const std::shared_ptr<sixtyfps::Model<Value>> &model)
{
using cbindgen_private::ModelAdaptorVTable; using cbindgen_private::ModelAdaptorVTable;
using vtable::VRef; using vtable::VRef;
struct ModelWrapper : AbstractRepeaterView { struct ModelWrapper : AbstractRepeaterView
{
std::shared_ptr<sixtyfps::Model<Value>> model; std::shared_ptr<sixtyfps::Model<Value>> model;
cbindgen_private::ModelNotifyOpaque notify; cbindgen_private::ModelNotifyOpaque notify;
// This kind of mean that the rust code has ownership of "this" until the drop funciton is called // This kind of mean that the rust code has ownership of "this" until the drop funciton is
// called
std::shared_ptr<AbstractRepeaterView> self; std::shared_ptr<AbstractRepeaterView> self;
~ModelWrapper() { ~ModelWrapper() { cbindgen_private::sixtyfps_interpreter_model_notify_destructor(&notify); }
cbindgen_private::sixtyfps_interpreter_model_notify_destructor(&notify);
}
void row_added(int index, int count) override void row_added(int index, int count) override
{ {
@ -250,7 +253,8 @@ inline Value::Value(const std::shared_ptr<sixtyfps::Model<Value>> &model) {
Value v = *reinterpret_cast<const Value *>(value); Value v = *reinterpret_cast<const Value *>(value);
reinterpret_cast<ModelWrapper *>(self.instance)->model->set_row_data(row, v); reinterpret_cast<ModelWrapper *>(self.instance)->model->set_row_data(row, v);
}; };
auto get_notify = [](VRef<ModelAdaptorVTable> self) -> const cbindgen_private::ModelNotifyOpaque* { auto get_notify =
[](VRef<ModelAdaptorVTable> self) -> const cbindgen_private::ModelNotifyOpaque * {
return &reinterpret_cast<ModelWrapper *>(self.instance)->notify; return &reinterpret_cast<ModelWrapper *>(self.instance)->notify;
}; };
auto drop = [](vtable::VRefMut<ModelAdaptorVTable> self) { auto drop = [](vtable::VRefMut<ModelAdaptorVTable> self) {
@ -262,4 +266,25 @@ inline Value::Value(const std::shared_ptr<sixtyfps::Model<Value>> &model) {
cbindgen_private::sixtyfps_interpreter_value_new_model(wrap, &inner); cbindgen_private::sixtyfps_interpreter_value_new_model(wrap, &inner);
} }
inline std::optional<Value> Struct::get_field(std::string_view name) const
{
cbindgen_private::Slice<uint8_t> name_view {
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(name.data())),
name.size()
};
if (auto *value = cbindgen_private::sixtyfps_interpreter_struct_get_field(&inner, name_view)) {
return *value;
} else {
return {};
}
}
inline void Struct::set_field(std::string_view name, const Value &value)
{
cbindgen_private::Slice<uint8_t> name_view {
const_cast<unsigned char *>(reinterpret_cast<const unsigned char *>(name.data())),
name.size()
};
cbindgen_private::sixtyfps_interpreter_struct_set_field(&inner, name_view, &value.inner);
}
} }

View file

@ -128,10 +128,12 @@ SCENARIO("Value API")
SECTION("Construct a model") SECTION("Construct a model")
{ {
// And test that it is properly destroyed when the value is destroyed // And test that it is properly destroyed when the value is destroyed
struct M : sixtyfps::VectorModel<Value> { struct M : sixtyfps::VectorModel<Value>
{
bool *destroyed; bool *destroyed;
explicit M(bool *destroyed) : destroyed(destroyed) { } explicit M(bool *destroyed) : destroyed(destroyed) { }
void play() { void play()
{
this->push_back(Value(4.)); this->push_back(Value(4.));
this->set_row_data(0, Value(9.)); this->set_row_data(0, Value(9.));
} }
@ -155,3 +157,18 @@ SCENARIO("Value API")
} }
} }
SCENARIO("Struct API")
{
using namespace sixtyfps::interpreter;
Struct struc;
REQUIRE(!struc.get_field("not_there"));
struc.set_field("field_a", Value(true));
auto value_opt = struc.get_field("field_a");
REQUIRE(value_opt.has_value());
auto value = value_opt.value();
REQUIRE(value.to_bool().has_value());
REQUIRE(value.to_bool().value() == true);
}