Array and map members for unions.
BUG=
R=yzshen@chromium.org
Review URL: https://codereview.chromium.org/1065653006
diff --git a/mojo/public/cpp/bindings/tests/union_unittest.cc b/mojo/public/cpp/bindings/tests/union_unittest.cc
index 6124d27..5017d97 100644
--- a/mojo/public/cpp/bindings/tests/union_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/union_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/lib/array_internal.h"
#include "mojo/public/cpp/bindings/lib/array_serialization.h"
@@ -637,6 +638,7 @@
static_cast<uint32_t>(size), 0);
EXPECT_TRUE(
internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
+ free(raw_buf);
}
TEST(UnionTest, StructInUnionValidationNonNullable) {
@@ -657,6 +659,7 @@
static_cast<uint32_t>(size), 0);
EXPECT_FALSE(
internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
+ free(raw_buf);
}
TEST(UnionTest, StructInUnionValidationNullable) {
@@ -677,6 +680,144 @@
static_cast<uint32_t>(size), 0);
EXPECT_TRUE(
internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
+ free(raw_buf);
+}
+
+TEST(UnionTest, ArrayInUnionGetterSetter) {
+ Environment environment;
+
+ Array<int8_t> array(2);
+ array[0] = 8;
+ array[1] = 9;
+
+ ObjectUnionPtr obj(ObjectUnion::New());
+ obj->set_f_array_int8(array.Pass());
+
+ EXPECT_EQ(8, obj->get_f_array_int8()[0]);
+ EXPECT_EQ(9, obj->get_f_array_int8()[1]);
+}
+
+TEST(UnionTest, ArrayInUnionSerialization) {
+ Environment environment;
+
+ Array<int8_t> array(2);
+ array[0] = 8;
+ array[1] = 9;
+
+ ObjectUnionPtr obj(ObjectUnion::New());
+ obj->set_f_array_int8(array.Pass());
+
+ size_t size = GetSerializedSize_(obj, false);
+ EXPECT_EQ(32U, size);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = nullptr;
+ SerializeUnion_(obj.Pass(), &buf, &data, false);
+
+ std::vector<Handle> handles;
+ data->EncodePointersAndHandles(&handles);
+ data->DecodePointersAndHandles(&handles);
+
+ ObjectUnionPtr obj2;
+ Deserialize_(data, &obj2);
+
+ EXPECT_EQ(8, obj2->get_f_array_int8()[0]);
+ EXPECT_EQ(9, obj2->get_f_array_int8()[1]);
+}
+
+TEST(UnionTest, ArrayInUnionValidation) {
+ Environment environment;
+
+ Array<int8_t> array(2);
+ array[0] = 8;
+ array[1] = 9;
+
+ ObjectUnionPtr obj(ObjectUnion::New());
+ obj->set_f_array_int8(array.Pass());
+
+ size_t size = GetSerializedSize_(obj, false);
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = nullptr;
+ SerializeUnion_(obj.Pass(), &buf, &data, false);
+
+ std::vector<Handle> handles;
+ data->EncodePointersAndHandles(&handles);
+
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
+
+ EXPECT_TRUE(
+ internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
+ free(raw_buf);
+}
+
+TEST(UnionTest, MapInUnionGetterSetter) {
+ Environment environment;
+ Map<String, int8_t> map;
+ map.insert("one", 1);
+ map.insert("two", 2);
+
+ ObjectUnionPtr obj(ObjectUnion::New());
+ obj->set_f_map_int8(map.Pass());
+
+ EXPECT_EQ(1, obj->get_f_map_int8()["one"]);
+ EXPECT_EQ(2, obj->get_f_map_int8()["two"]);
+}
+
+TEST(UnionTest, MapInUnionSerialization) {
+ Environment environment;
+ Map<String, int8_t> map;
+ map.insert("one", 1);
+ map.insert("two", 2);
+
+ ObjectUnionPtr obj(ObjectUnion::New());
+ obj->set_f_map_int8(map.Pass());
+
+ size_t size = GetSerializedSize_(obj, false);
+ EXPECT_EQ(112U, size);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = nullptr;
+ SerializeUnion_(obj.Pass(), &buf, &data, false);
+
+ std::vector<Handle> handles;
+ data->EncodePointersAndHandles(&handles);
+ data->DecodePointersAndHandles(&handles);
+
+ ObjectUnionPtr obj2;
+ Deserialize_(data, &obj2);
+
+ EXPECT_EQ(1, obj2->get_f_map_int8()["one"]);
+ EXPECT_EQ(2, obj2->get_f_map_int8()["two"]);
+}
+
+TEST(UnionTest, MapInUnionValidation) {
+ Environment environment;
+ Map<String, int8_t> map;
+ map.insert("one", 1);
+ map.insert("two", 2);
+
+ ObjectUnionPtr obj(ObjectUnion::New());
+ obj->set_f_map_int8(map.Pass());
+
+ size_t size = GetSerializedSize_(obj, false);
+ EXPECT_EQ(112U, size);
+
+ mojo::internal::FixedBuffer buf(size);
+ internal::ObjectUnion_Data* data = nullptr;
+ SerializeUnion_(obj.Pass(), &buf, &data, false);
+
+ std::vector<Handle> handles;
+ data->EncodePointersAndHandles(&handles);
+
+ void* raw_buf = buf.Leak();
+ mojo::internal::BoundsChecker bounds_checker(data,
+ static_cast<uint32_t>(size), 0);
+
+ EXPECT_TRUE(
+ internal::ObjectUnion_Data::Validate(raw_buf, &bounds_checker, false));
+ free(raw_buf);
}
} // namespace test
diff --git a/mojo/public/interfaces/bindings/tests/test_unions.mojom b/mojo/public/interfaces/bindings/tests/test_unions.mojom
index ffc8922..cda5be4 100644
--- a/mojo/public/interfaces/bindings/tests/test_unions.mojom
+++ b/mojo/public/interfaces/bindings/tests/test_unions.mojom
@@ -24,6 +24,8 @@
string f_string;
DummyStruct f_dummy;
DummyStruct? f_nullable;
+ array<int8> f_array_int8;
+ map<string, int8> f_map_int8;
};
struct DummyStruct {
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
index f29ea2d..f84f60a 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_declaration.tmpl
@@ -32,7 +32,7 @@
// a struct." - Section 9.5.2 ISO/IEC 14882:2011 (The C++ Spec)
union MOJO_ALIGNAS(8) Union_ {
{%- for field in union.fields %}
-{%- if field.kind|is_string_kind or field.kind|is_struct_kind %}
+{%- if field.kind|is_object_kind %}
uint64_t f_{{field.name}};
{%- elif field.kind.spec == 'b' %}
uint8_t f_{{field.name}} : 1;
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
index 3e6b0ad..9ddcc51 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_definition.tmpl
@@ -57,10 +57,36 @@
void {{class_name}}::EncodePointersAndHandles(
std::vector<mojo::Handle>* handles) {
- // TODO(azani): Implement pointers and handles.
+ switch (tag) {
+{%- for field in union.fields %}
+ case {{enum_name}}::{{field.name|upper}}: {
+{%- if field.kind|is_object_kind and not field.kind|is_union_kind %}
+ mojo::internal::Encode(
+ reinterpret_cast<{{field.kind|cpp_field_type}}*>(&data.f_{{field.name}}),
+ handles);
+{%- elif field.kind|is_any_handle_kind %}
+ mojo::internal::EncodeHandle(&data.f_{{field.name}}, handles);
+{%- endif %}
+ return;
+ }
+{%- endfor %}
+ }
}
void {{class_name}}::DecodePointersAndHandles(
std::vector<mojo::Handle>* handles) {
- // TODO(azani): Implement pointers and handles.
+ switch (tag) {
+{%- for field in union.fields %}
+ case {{enum_name}}::{{field.name|upper}}: {
+{%- if field.kind|is_object_kind and not field.kind|is_union_kind %}
+ mojo::internal::Decode(
+ reinterpret_cast<{{field.kind|cpp_field_type}}*>(&data.f_{{field.name}}),
+ handles);
+{%- elif field.kind|is_any_handle_kind %}
+ mojo::internal::DecodeHandle(&data.f_{{field.name}}, handles);
+{%- endif %}
+ return;
+ }
+{%- endfor %}
+ }
}
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
index f1dd0aa..7df17c1 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/union_serialization_definition.tmpl
@@ -43,6 +43,18 @@
Serialize_(*(input_acc.data()->{{field.name}}), buf, &{{field.name}}_ptr->ptr);
{% elif field.kind|is_struct_kind %}
Serialize_(mojo::internal::Forward(*(input_acc.data()->{{field.name}})), buf, &{{field.name}}_ptr->ptr);
+{% elif field.kind|is_array_kind %}
+ const mojo::internal::ArrayValidateParams {{field.name}}_validate_params =
+ {{field.kind|get_array_validate_params|indent(16)}};
+ SerializeArray_(
+ mojo::internal::Forward(*(input_acc.data()->{{field.name}})),
+ buf, &{{field.name}}_ptr->ptr, &{{field.name}}_validate_params);
+{% elif field.kind|is_map_kind %}
+ const mojo::internal::ArrayValidateParams {{field.name}}_validate_params =
+ {{field.kind.value_kind|get_map_validate_params|indent(16)}};
+ SerializeMap_(
+ mojo::internal::Forward(*(input_acc.data()->{{field.name}})),
+ buf, &{{field.name}}_ptr->ptr, &{{field.name}}_validate_params);
{%- endif %}
{% else %}
result->data.f_{{field.name}} = input_acc.data()->{{field.name}};
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
index 46931bc..4355f41 100644
--- a/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
+++ b/mojo/public/tools/bindings/generators/cpp_templates/wrapper_union_class_definition.tmpl
@@ -23,7 +23,7 @@
case Tag::{{field.name|upper}}:
{% if field.kind|is_string_kind %}
rv->set_{{field.name}}(*(data_.{{field.name}}));
-{% elif field.kind|is_struct_kind %}
+{% elif field.kind|is_object_kind %}
rv->set_{{field.name}}(data_.{{field.name}}->Clone());
{%- else %}
rv->set_{{field.name}}(data_.{{field.name}});
@@ -72,7 +72,7 @@
SwitchActive(Tag::{{field.name|upper}});
{% if field.kind|is_string_kind %}
*(data_.{{field.name}}) = {{field.name}};
-{% elif field.kind|is_struct_kind %}
+{% elif field.kind|is_object_kind %}
*(data_.{{field.name}}) = {{field.name}}.Pass();
{%- else %}
data_.{{field.name}} = {{field.name}};
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
index 35dec21..dbe977d 100644
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
@@ -228,7 +228,8 @@
return _kind_to_cpp_type[kind]
def GetUnionGetterReturnType(kind):
- if mojom.IsStructKind(kind):
+ if (mojom.IsStructKind(kind) or mojom.IsArrayKind(kind) or
+ mojom.IsMapKind(kind)):
return "%s&" % GetCppWrapperType(kind)
return GetCppResultWrapperType(kind)