Merge "AAPT2: Store BinaryPrimatives in protos as oneofs"
This commit is contained in:
committed by
Android (Google) Code Review
commit
8f2fffd809
@@ -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.
|
||||
|
||||
@@ -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: {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user