Merge "AAPT2: Store BinaryPrimatives in protos as oneofs"

This commit is contained in:
TreeHugger Robot
2018-01-19 01:00:00 +00:00
committed by Android (Google) Code Review
4 changed files with 229 additions and 7 deletions

View File

@@ -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.

View File

@@ -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: {

View File

@@ -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 {

View File

@@ -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;