diff options
| author | 2018-01-19 01:00:00 +0000 | |
|---|---|---|
| committer | 2018-01-19 01:00:00 +0000 | |
| commit | 8f2fffd809690bbef2593fbf45bc3d86a9ceedab (patch) | |
| tree | 626897cd34a290d31286b4879683ae19ded07e7f | |
| parent | f5e25a3052070485fc520863e3e6162097466e39 (diff) | |
| parent | d06f1f38a9266f4674a89d69d33198abd12b0e78 (diff) | |
Merge "AAPT2: Store BinaryPrimatives in protos as oneofs"
| -rw-r--r-- | tools/aapt2/Resources.proto | 21 | ||||
| -rw-r--r-- | tools/aapt2/format/proto/ProtoDeserialize.cpp | 63 | ||||
| -rw-r--r-- | tools/aapt2/format/proto/ProtoSerialize.cpp | 47 | ||||
| -rw-r--r-- | tools/aapt2/format/proto/ProtoSerialize_test.cpp | 105 |
4 files changed, 229 insertions, 7 deletions
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 8552195d338d..069360e3d6f3 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -306,10 +306,25 @@ message FileReference { } // A value that represents a primitive data type (float, int, boolean, etc.). -// Corresponds to the fields (type/data) of the C struct android::Res_value. message Primitive { - uint32 type = 1; - uint32 data = 2; + message NullType { + } + message EmptyType { + } + oneof oneof_value { + NullType null_value = 1; + EmptyType empty_value = 2; + float float_value = 3; + float dimension_value = 4; + float fraction_value = 5; + int32 int_decimal_value = 6; + uint32 int_hexidecimal_value = 7; + bool boolean_value = 8; + uint32 color_argb8_value = 9; + uint32 color_rgb8_value = 10; + uint32 color_argb4_value = 11; + uint32 color_rgb4_value = 12; + } } // A value that represents an XML attribute and what values it accepts. diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index d8635a989bed..064878b5f83f 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -23,6 +23,7 @@ #include "Locale.h" #include "ResourceTable.h" #include "ResourceUtils.h" +#include "ResourceValues.h" #include "ValueVisitor.h" using ::android::ResStringPool; @@ -761,8 +762,66 @@ std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item, case pb::Item::kPrim: { const pb::Primitive& pb_prim = pb_item.prim(); - return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()), - pb_prim.data()); + android::Res_value val = {}; + switch (pb_prim.oneof_value_case()) { + case pb::Primitive::kNullValue: { + val.dataType = android::Res_value::TYPE_NULL; + val.data = android::Res_value::DATA_NULL_UNDEFINED; + } break; + case pb::Primitive::kEmptyValue: { + val.dataType = android::Res_value::TYPE_NULL; + val.data = android::Res_value::DATA_NULL_EMPTY; + } break; + case pb::Primitive::kFloatValue: { + val.dataType = android::Res_value::TYPE_FLOAT; + float float_val = pb_prim.float_value(); + val.data = *(uint32_t*)&float_val; + } break; + case pb::Primitive::kDimensionValue: { + val.dataType = android::Res_value::TYPE_DIMENSION; + float dimen_val = pb_prim.dimension_value(); + val.data = *(uint32_t*)&dimen_val; + } break; + case pb::Primitive::kFractionValue: { + val.dataType = android::Res_value::TYPE_FRACTION; + float fraction_val = pb_prim.fraction_value(); + val.data = *(uint32_t*)&fraction_val; + } break; + case pb::Primitive::kIntDecimalValue: { + val.dataType = android::Res_value::TYPE_INT_DEC; + val.data = static_cast<uint32_t>(pb_prim.int_decimal_value()); + } break; + case pb::Primitive::kIntHexidecimalValue: { + val.dataType = android::Res_value::TYPE_INT_HEX; + val.data = pb_prim.int_hexidecimal_value(); + } break; + case pb::Primitive::kBooleanValue: { + val.dataType = android::Res_value::TYPE_INT_BOOLEAN; + val.data = pb_prim.boolean_value() ? 0xFFFFFFFF : 0x0; + } break; + case pb::Primitive::kColorArgb8Value: { + val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB8; + val.data = pb_prim.color_argb8_value(); + } break; + case pb::Primitive::kColorRgb8Value: { + val.dataType = android::Res_value::TYPE_INT_COLOR_RGB8; + val.data = pb_prim.color_rgb8_value(); + } break; + case pb::Primitive::kColorArgb4Value: { + val.dataType = android::Res_value::TYPE_INT_COLOR_ARGB4; + val.data = pb_prim.color_argb4_value(); + } break; + case pb::Primitive::kColorRgb4Value: { + val.dataType = android::Res_value::TYPE_INT_COLOR_RGB4; + val.data = pb_prim.color_rgb4_value(); + } break; + default: { + LOG(FATAL) << "Unexpected Primitive type: " + << static_cast<uint32_t>(pb_prim.oneof_value_case()); + return {}; + } break; + } + return util::make_unique<BinaryPrimitive>(val); } break; case pb::Item::kId: { diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index 78f12814389d..e9622f54f6ae 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -436,8 +436,51 @@ class ValueSerializer : public ConstValueVisitor { prim->Flatten(&val); pb::Primitive* pb_prim = out_value_->mutable_item()->mutable_prim(); - pb_prim->set_type(val.dataType); - pb_prim->set_data(val.data); + + switch (val.dataType) { + case android::Res_value::TYPE_NULL: { + if (val.data == android::Res_value::DATA_NULL_UNDEFINED) { + pb_prim->set_allocated_null_value(new pb::Primitive_NullType()); + } else if (val.data == android::Res_value::DATA_NULL_EMPTY) { + pb_prim->set_allocated_empty_value(new pb::Primitive_EmptyType()); + } else { + LOG(FATAL) << "Unexpected data value for TYPE_NULL BinaryPrimitive: " << val.data; + } + } break; + case android::Res_value::TYPE_FLOAT: { + pb_prim->set_float_value(*(float*)&val.data); + } break; + case android::Res_value::TYPE_DIMENSION: { + pb_prim->set_dimension_value(*(float*)&val.data); + } break; + case android::Res_value::TYPE_FRACTION: { + pb_prim->set_fraction_value(*(float*)&val.data); + } break; + case android::Res_value::TYPE_INT_DEC: { + pb_prim->set_int_decimal_value(static_cast<int32_t>(val.data)); + } break; + case android::Res_value::TYPE_INT_HEX: { + pb_prim->set_int_hexidecimal_value(val.data); + } break; + case android::Res_value::TYPE_INT_BOOLEAN: { + pb_prim->set_boolean_value(static_cast<bool>(val.data)); + } break; + case android::Res_value::TYPE_INT_COLOR_ARGB8: { + pb_prim->set_color_argb8_value(val.data); + } break; + case android::Res_value::TYPE_INT_COLOR_RGB8: { + pb_prim->set_color_rgb8_value(val.data); + } break; + case android::Res_value::TYPE_INT_COLOR_ARGB4: { + pb_prim->set_color_argb4_value(val.data); + } break; + case android::Res_value::TYPE_INT_COLOR_RGB4: { + pb_prim->set_color_rgb4_value(val.data); + } break; + default: + LOG(FATAL) << "Unexpected BinaryPrimitive type: " << val.dataType; + break; + } } void Visit(const Attribute* attr) override { diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index ccba5c652822..9081ab6abd0a 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -254,6 +254,111 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeXml) { EXPECT_THAT(child_text->text, StrEq("woah there")); } +TEST(ProtoSerializeTest, SerializeAndDeserializePrimitives) { + std::unique_ptr<ResourceTable> table = + test::ResourceTableBuilder() + .AddValue("android:bool/boolean_true", + test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, true)) + .AddValue("android:bool/boolean_false", + test::BuildPrimitive(android::Res_value::TYPE_INT_BOOLEAN, false)) + .AddValue("android:color/color_rgb8", ResourceUtils::TryParseColor("#AABBCC")) + .AddValue("android:color/color_argb8", ResourceUtils::TryParseColor("#11223344")) + .AddValue("android:color/color_rgb4", ResourceUtils::TryParseColor("#DEF")) + .AddValue("android:color/color_argb4", ResourceUtils::TryParseColor("#5678")) + .AddValue("android:integer/integer_444", ResourceUtils::TryParseInt("444")) + .AddValue("android:integer/integer_neg_333", ResourceUtils::TryParseInt("-333")) + .AddValue("android:integer/hex_int_abcd", ResourceUtils::TryParseInt("0xABCD")) + .AddValue("android:dimen/dimen_1.39mm", ResourceUtils::TryParseFloat("1.39mm")) + .AddValue("android:fraction/fraction_27", ResourceUtils::TryParseFloat("27%")) + .AddValue("android:integer/null", ResourceUtils::MakeEmpty()) + .Build(); + + pb::ResourceTable pb_table; + SerializeTableToPb(*table, &pb_table); + + test::TestFile file_a("res/layout/main.xml"); + MockFileCollection files; + EXPECT_CALL(files, FindFile(Eq("res/layout/main.xml"))) + .WillRepeatedly(::testing::Return(&file_a)); + + ResourceTable new_table; + std::string error; + ASSERT_TRUE(DeserializeTableFromPb(pb_table, &files, &new_table, &error)); + EXPECT_THAT(error, IsEmpty()); + + BinaryPrimitive* bp = test::GetValueForConfigAndProduct<BinaryPrimitive>( + &new_table, "android:bool/boolean_true", ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("true")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:bool/boolean_false", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_BOOLEAN)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseBool("false")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb8", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB8)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#AABBCC")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb8", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB8)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#11223344")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_rgb4", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_RGB4)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#DEF")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:color/color_argb4", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_COLOR_ARGB4)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseColor("#5678")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/integer_444", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("444")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>( + &new_table, "android:integer/integer_neg_333", ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_DEC)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("-333")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>( + &new_table, "android:integer/hex_int_abcd", ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_INT_HEX)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseInt("0xABCD")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:dimen/dimen_1.39mm", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_DIMENSION)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("1.39mm")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>( + &new_table, "android:fraction/fraction_27", ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_FRACTION)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::TryParseFloat("27%")->value.data)); + + bp = test::GetValueForConfigAndProduct<BinaryPrimitive>(&new_table, "android:integer/null", + ConfigDescription::DefaultConfig(), ""); + ASSERT_THAT(bp, NotNull()); + EXPECT_THAT(bp->value.dataType, Eq(android::Res_value::TYPE_NULL)); + EXPECT_THAT(bp->value.data, Eq(ResourceUtils::MakeEmpty()->value.data)); +} + static void ExpectConfigSerializes(const StringPiece& config_str) { const ConfigDescription expected_config = test::ParseConfigOrDie(config_str); pb::Configuration pb_config; |