1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "format/proto/ProtoSerialize.h" 18 19 #include "ValueVisitor.h" 20 #include "util/BigBuffer.h" 21 22 namespace aapt { 23 24 void SerializeStringPoolToPb(const StringPool& pool, pb::StringPool* out_pb_pool, IDiagnostics* diag) { 25 BigBuffer buffer(1024); 26 StringPool::FlattenUtf8(&buffer, pool, diag); 27 28 std::string* data = out_pb_pool->mutable_data(); 29 data->reserve(buffer.size()); 30 31 size_t offset = 0; 32 for (const BigBuffer::Block& block : buffer) { 33 data->insert(data->begin() + offset, block.buffer.get(), block.buffer.get() + block.size); 34 offset += block.size; 35 } 36 } 37 38 void SerializeSourceToPb(const Source& source, StringPool* src_pool, pb::Source* out_pb_source) { 39 StringPool::Ref ref = src_pool->MakeRef(source.path); 40 out_pb_source->set_path_idx(static_cast<uint32_t>(ref.index())); 41 if (source.line) { 42 out_pb_source->mutable_position()->set_line_number(static_cast<uint32_t>(source.line.value())); 43 } 44 } 45 46 static pb::Visibility::Level SerializeVisibilityToPb(Visibility::Level state) { 47 switch (state) { 48 case Visibility::Level::kPrivate: 49 return pb::Visibility::PRIVATE; 50 case Visibility::Level::kPublic: 51 return pb::Visibility::PUBLIC; 52 default: 53 break; 54 } 55 return pb::Visibility::UNKNOWN; 56 } 57 58 void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_config) { 59 out_pb_config->set_mcc(config.mcc); 60 out_pb_config->set_mnc(config.mnc); 61 out_pb_config->set_locale(config.GetBcp47LanguageTag()); 62 63 switch (config.screenLayout & ConfigDescription::MASK_LAYOUTDIR) { 64 case ConfigDescription::LAYOUTDIR_LTR: 65 out_pb_config->set_layout_direction(pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_LTR); 66 break; 67 68 case ConfigDescription::LAYOUTDIR_RTL: 69 out_pb_config->set_layout_direction(pb::Configuration_LayoutDirection_LAYOUT_DIRECTION_RTL); 70 break; 71 } 72 73 out_pb_config->set_screen_width(config.screenWidth); 74 out_pb_config->set_screen_height(config.screenHeight); 75 out_pb_config->set_screen_width_dp(config.screenWidthDp); 76 out_pb_config->set_screen_height_dp(config.screenHeightDp); 77 out_pb_config->set_smallest_screen_width_dp(config.smallestScreenWidthDp); 78 79 switch (config.screenLayout & ConfigDescription::MASK_SCREENSIZE) { 80 case ConfigDescription::SCREENSIZE_SMALL: 81 out_pb_config->set_screen_layout_size( 82 pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_SMALL); 83 break; 84 85 case ConfigDescription::SCREENSIZE_NORMAL: 86 out_pb_config->set_screen_layout_size( 87 pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_NORMAL); 88 break; 89 90 case ConfigDescription::SCREENSIZE_LARGE: 91 out_pb_config->set_screen_layout_size( 92 pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_LARGE); 93 break; 94 95 case ConfigDescription::SCREENSIZE_XLARGE: 96 out_pb_config->set_screen_layout_size( 97 pb::Configuration_ScreenLayoutSize_SCREEN_LAYOUT_SIZE_XLARGE); 98 break; 99 } 100 101 switch (config.screenLayout & ConfigDescription::MASK_SCREENLONG) { 102 case ConfigDescription::SCREENLONG_YES: 103 out_pb_config->set_screen_layout_long( 104 pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_LONG); 105 break; 106 107 case ConfigDescription::SCREENLONG_NO: 108 out_pb_config->set_screen_layout_long( 109 pb::Configuration_ScreenLayoutLong_SCREEN_LAYOUT_LONG_NOTLONG); 110 break; 111 } 112 113 switch (config.screenLayout2 & ConfigDescription::MASK_SCREENROUND) { 114 case ConfigDescription::SCREENROUND_YES: 115 out_pb_config->set_screen_round(pb::Configuration_ScreenRound_SCREEN_ROUND_ROUND); 116 break; 117 118 case ConfigDescription::SCREENROUND_NO: 119 out_pb_config->set_screen_round(pb::Configuration_ScreenRound_SCREEN_ROUND_NOTROUND); 120 break; 121 } 122 123 switch (config.colorMode & ConfigDescription::MASK_WIDE_COLOR_GAMUT) { 124 case ConfigDescription::WIDE_COLOR_GAMUT_YES: 125 out_pb_config->set_wide_color_gamut(pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_WIDECG); 126 break; 127 128 case ConfigDescription::WIDE_COLOR_GAMUT_NO: 129 out_pb_config->set_wide_color_gamut( 130 pb::Configuration_WideColorGamut_WIDE_COLOR_GAMUT_NOWIDECG); 131 break; 132 } 133 134 switch (config.colorMode & ConfigDescription::MASK_HDR) { 135 case ConfigDescription::HDR_YES: 136 out_pb_config->set_hdr(pb::Configuration_Hdr_HDR_HIGHDR); 137 break; 138 139 case ConfigDescription::HDR_NO: 140 out_pb_config->set_hdr(pb::Configuration_Hdr_HDR_LOWDR); 141 break; 142 } 143 144 switch (config.orientation) { 145 case ConfigDescription::ORIENTATION_PORT: 146 out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_PORT); 147 break; 148 149 case ConfigDescription::ORIENTATION_LAND: 150 out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_LAND); 151 break; 152 153 case ConfigDescription::ORIENTATION_SQUARE: 154 out_pb_config->set_orientation(pb::Configuration_Orientation_ORIENTATION_SQUARE); 155 break; 156 } 157 158 switch (config.uiMode & ConfigDescription::MASK_UI_MODE_TYPE) { 159 case ConfigDescription::UI_MODE_TYPE_NORMAL: 160 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_NORMAL); 161 break; 162 163 case ConfigDescription::UI_MODE_TYPE_DESK: 164 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_DESK); 165 break; 166 167 case ConfigDescription::UI_MODE_TYPE_CAR: 168 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_CAR); 169 break; 170 171 case ConfigDescription::UI_MODE_TYPE_TELEVISION: 172 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_TELEVISION); 173 break; 174 175 case ConfigDescription::UI_MODE_TYPE_APPLIANCE: 176 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_APPLIANCE); 177 break; 178 179 case ConfigDescription::UI_MODE_TYPE_WATCH: 180 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_WATCH); 181 break; 182 183 case ConfigDescription::UI_MODE_TYPE_VR_HEADSET: 184 out_pb_config->set_ui_mode_type(pb::Configuration_UiModeType_UI_MODE_TYPE_VRHEADSET); 185 break; 186 } 187 188 switch (config.uiMode & ConfigDescription::MASK_UI_MODE_NIGHT) { 189 case ConfigDescription::UI_MODE_NIGHT_YES: 190 out_pb_config->set_ui_mode_night(pb::Configuration_UiModeNight_UI_MODE_NIGHT_NIGHT); 191 break; 192 193 case ConfigDescription::UI_MODE_NIGHT_NO: 194 out_pb_config->set_ui_mode_night(pb::Configuration_UiModeNight_UI_MODE_NIGHT_NOTNIGHT); 195 break; 196 } 197 198 out_pb_config->set_density(config.density); 199 200 switch (config.touchscreen) { 201 case ConfigDescription::TOUCHSCREEN_NOTOUCH: 202 out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_NOTOUCH); 203 break; 204 205 case ConfigDescription::TOUCHSCREEN_STYLUS: 206 out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_STYLUS); 207 break; 208 209 case ConfigDescription::TOUCHSCREEN_FINGER: 210 out_pb_config->set_touchscreen(pb::Configuration_Touchscreen_TOUCHSCREEN_FINGER); 211 break; 212 } 213 214 switch (config.inputFlags & ConfigDescription::MASK_KEYSHIDDEN) { 215 case ConfigDescription::KEYSHIDDEN_NO: 216 out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSEXPOSED); 217 break; 218 219 case ConfigDescription::KEYSHIDDEN_YES: 220 out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSHIDDEN); 221 break; 222 223 case ConfigDescription::KEYSHIDDEN_SOFT: 224 out_pb_config->set_keys_hidden(pb::Configuration_KeysHidden_KEYS_HIDDEN_KEYSSOFT); 225 break; 226 } 227 228 switch (config.keyboard) { 229 case ConfigDescription::KEYBOARD_NOKEYS: 230 out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_NOKEYS); 231 break; 232 233 case ConfigDescription::KEYBOARD_QWERTY: 234 out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_QWERTY); 235 break; 236 237 case ConfigDescription::KEYBOARD_12KEY: 238 out_pb_config->set_keyboard(pb::Configuration_Keyboard_KEYBOARD_TWELVEKEY); 239 break; 240 } 241 242 switch (config.inputFlags & ConfigDescription::MASK_NAVHIDDEN) { 243 case ConfigDescription::NAVHIDDEN_NO: 244 out_pb_config->set_nav_hidden(pb::Configuration_NavHidden_NAV_HIDDEN_NAVEXPOSED); 245 break; 246 247 case ConfigDescription::NAVHIDDEN_YES: 248 out_pb_config->set_nav_hidden(pb::Configuration_NavHidden_NAV_HIDDEN_NAVHIDDEN); 249 break; 250 } 251 252 switch (config.navigation) { 253 case ConfigDescription::NAVIGATION_NONAV: 254 out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_NONAV); 255 break; 256 257 case ConfigDescription::NAVIGATION_DPAD: 258 out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_DPAD); 259 break; 260 261 case ConfigDescription::NAVIGATION_TRACKBALL: 262 out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_TRACKBALL); 263 break; 264 265 case ConfigDescription::NAVIGATION_WHEEL: 266 out_pb_config->set_navigation(pb::Configuration_Navigation_NAVIGATION_WHEEL); 267 break; 268 } 269 270 out_pb_config->set_sdk_version(config.sdkVersion); 271 } 272 273 void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table, 274 IDiagnostics* diag) { 275 StringPool source_pool; 276 for (const std::unique_ptr<ResourceTablePackage>& package : table.packages) { 277 pb::Package* pb_package = out_table->add_package(); 278 if (package->id) { 279 pb_package->mutable_package_id()->set_id(package->id.value()); 280 } 281 pb_package->set_package_name(package->name); 282 283 for (const std::unique_ptr<ResourceTableType>& type : package->types) { 284 pb::Type* pb_type = pb_package->add_type(); 285 if (type->id) { 286 pb_type->mutable_type_id()->set_id(type->id.value()); 287 } 288 pb_type->set_name(to_string(type->type).to_string()); 289 290 for (const std::unique_ptr<ResourceEntry>& entry : type->entries) { 291 pb::Entry* pb_entry = pb_type->add_entry(); 292 if (entry->id) { 293 pb_entry->mutable_entry_id()->set_id(entry->id.value()); 294 } 295 pb_entry->set_name(entry->name); 296 297 // Write the Visibility struct. 298 pb::Visibility* pb_visibility = pb_entry->mutable_visibility(); 299 pb_visibility->set_level(SerializeVisibilityToPb(entry->visibility.level)); 300 SerializeSourceToPb(entry->visibility.source, &source_pool, 301 pb_visibility->mutable_source()); 302 pb_visibility->set_comment(entry->visibility.comment); 303 304 if (entry->allow_new) { 305 pb::AllowNew* pb_allow_new = pb_entry->mutable_allow_new(); 306 SerializeSourceToPb(entry->allow_new.value().source, &source_pool, 307 pb_allow_new->mutable_source()); 308 pb_allow_new->set_comment(entry->allow_new.value().comment); 309 } 310 311 if (entry->overlayable) { 312 pb::Overlayable* pb_overlayable = pb_entry->mutable_overlayable(); 313 SerializeSourceToPb(entry->overlayable.value().source, &source_pool, 314 pb_overlayable->mutable_source()); 315 pb_overlayable->set_comment(entry->overlayable.value().comment); 316 } 317 318 for (const std::unique_ptr<ResourceConfigValue>& config_value : entry->values) { 319 pb::ConfigValue* pb_config_value = pb_entry->add_config_value(); 320 SerializeConfig(config_value->config, pb_config_value->mutable_config()); 321 pb_config_value->mutable_config()->set_product(config_value->product); 322 SerializeValueToPb(*config_value->value, pb_config_value->mutable_value(), &source_pool); 323 } 324 } 325 } 326 } 327 SerializeStringPoolToPb(source_pool, out_table->mutable_source_pool(), diag); 328 } 329 330 static pb::Reference_Type SerializeReferenceTypeToPb(Reference::Type type) { 331 switch (type) { 332 case Reference::Type::kResource: 333 return pb::Reference_Type_REFERENCE; 334 case Reference::Type::kAttribute: 335 return pb::Reference_Type_ATTRIBUTE; 336 default: 337 break; 338 } 339 return pb::Reference_Type_REFERENCE; 340 } 341 342 static void SerializeReferenceToPb(const Reference& ref, pb::Reference* pb_ref) { 343 pb_ref->set_id(ref.id.value_or_default(ResourceId(0x0)).id); 344 345 if (ref.name) { 346 pb_ref->set_name(ref.name.value().to_string()); 347 } 348 349 pb_ref->set_private_(ref.private_reference); 350 pb_ref->set_type(SerializeReferenceTypeToPb(ref.reference_type)); 351 } 352 353 template <typename T> 354 static void SerializeItemMetaDataToPb(const Item& item, T* pb_item, StringPool* src_pool) { 355 if (src_pool != nullptr) { 356 SerializeSourceToPb(item.GetSource(), src_pool, pb_item->mutable_source()); 357 } 358 pb_item->set_comment(item.GetComment()); 359 } 360 361 static pb::Plural_Arity SerializePluralEnumToPb(size_t plural_idx) { 362 switch (plural_idx) { 363 case Plural::Zero: 364 return pb::Plural_Arity_ZERO; 365 case Plural::One: 366 return pb::Plural_Arity_ONE; 367 case Plural::Two: 368 return pb::Plural_Arity_TWO; 369 case Plural::Few: 370 return pb::Plural_Arity_FEW; 371 case Plural::Many: 372 return pb::Plural_Arity_MANY; 373 default: 374 break; 375 } 376 return pb::Plural_Arity_OTHER; 377 } 378 379 static pb::FileReference::Type SerializeFileReferenceTypeToPb(const ResourceFile::Type& type) { 380 switch (type) { 381 case ResourceFile::Type::kBinaryXml: 382 return pb::FileReference::BINARY_XML; 383 case ResourceFile::Type::kProtoXml: 384 return pb::FileReference::PROTO_XML; 385 case ResourceFile::Type::kPng: 386 return pb::FileReference::PNG; 387 default: 388 return pb::FileReference::UNKNOWN; 389 } 390 } 391 392 namespace { 393 394 class ValueSerializer : public ConstValueVisitor { 395 public: 396 using ConstValueVisitor::Visit; 397 398 ValueSerializer(pb::Value* out_value, StringPool* src_pool) 399 : out_value_(out_value), src_pool_(src_pool) { 400 } 401 402 void Visit(const Reference* ref) override { 403 SerializeReferenceToPb(*ref, out_value_->mutable_item()->mutable_ref()); 404 } 405 406 void Visit(const String* str) override { 407 out_value_->mutable_item()->mutable_str()->set_value(*str->value); 408 } 409 410 void Visit(const RawString* str) override { 411 out_value_->mutable_item()->mutable_raw_str()->set_value(*str->value); 412 } 413 414 void Visit(const StyledString* str) override { 415 pb::StyledString* pb_str = out_value_->mutable_item()->mutable_styled_str(); 416 pb_str->set_value(str->value->value); 417 for (const StringPool::Span& span : str->value->spans) { 418 pb::StyledString::Span* pb_span = pb_str->add_span(); 419 pb_span->set_tag(*span.name); 420 pb_span->set_first_char(span.first_char); 421 pb_span->set_last_char(span.last_char); 422 } 423 } 424 425 void Visit(const FileReference* file) override { 426 pb::FileReference* pb_file = out_value_->mutable_item()->mutable_file(); 427 pb_file->set_path(*file->path); 428 pb_file->set_type(SerializeFileReferenceTypeToPb(file->type)); 429 } 430 431 void Visit(const Id* /*id*/) override { 432 out_value_->mutable_item()->mutable_id(); 433 } 434 435 void Visit(const BinaryPrimitive* prim) override { 436 android::Res_value val = {}; 437 prim->Flatten(&val); 438 439 pb::Primitive* pb_prim = out_value_->mutable_item()->mutable_prim(); 440 441 switch (val.dataType) { 442 case android::Res_value::TYPE_NULL: { 443 if (val.data == android::Res_value::DATA_NULL_UNDEFINED) { 444 pb_prim->set_allocated_null_value(new pb::Primitive_NullType()); 445 } else if (val.data == android::Res_value::DATA_NULL_EMPTY) { 446 pb_prim->set_allocated_empty_value(new pb::Primitive_EmptyType()); 447 } else { 448 LOG(FATAL) << "Unexpected data value for TYPE_NULL BinaryPrimitive: " << val.data; 449 } 450 } break; 451 case android::Res_value::TYPE_FLOAT: { 452 pb_prim->set_float_value(*(float*)&val.data); 453 } break; 454 case android::Res_value::TYPE_DIMENSION: { 455 pb_prim->set_dimension_value(val.data); 456 } break; 457 case android::Res_value::TYPE_FRACTION: { 458 pb_prim->set_fraction_value(val.data); 459 } break; 460 case android::Res_value::TYPE_INT_DEC: { 461 pb_prim->set_int_decimal_value(static_cast<int32_t>(val.data)); 462 } break; 463 case android::Res_value::TYPE_INT_HEX: { 464 pb_prim->set_int_hexadecimal_value(val.data); 465 } break; 466 case android::Res_value::TYPE_INT_BOOLEAN: { 467 pb_prim->set_boolean_value(static_cast<bool>(val.data)); 468 } break; 469 case android::Res_value::TYPE_INT_COLOR_ARGB8: { 470 pb_prim->set_color_argb8_value(val.data); 471 } break; 472 case android::Res_value::TYPE_INT_COLOR_RGB8: { 473 pb_prim->set_color_rgb8_value(val.data); 474 } break; 475 case android::Res_value::TYPE_INT_COLOR_ARGB4: { 476 pb_prim->set_color_argb4_value(val.data); 477 } break; 478 case android::Res_value::TYPE_INT_COLOR_RGB4: { 479 pb_prim->set_color_rgb4_value(val.data); 480 } break; 481 default: 482 LOG(FATAL) << "Unexpected BinaryPrimitive type: " << val.dataType; 483 break; 484 } 485 } 486 487 void Visit(const Attribute* attr) override { 488 pb::Attribute* pb_attr = out_value_->mutable_compound_value()->mutable_attr(); 489 pb_attr->set_format_flags(attr->type_mask); 490 pb_attr->set_min_int(attr->min_int); 491 pb_attr->set_max_int(attr->max_int); 492 493 for (auto& symbol : attr->symbols) { 494 pb::Attribute_Symbol* pb_symbol = pb_attr->add_symbol(); 495 SerializeItemMetaDataToPb(symbol.symbol, pb_symbol, src_pool_); 496 SerializeReferenceToPb(symbol.symbol, pb_symbol->mutable_name()); 497 pb_symbol->set_value(symbol.value); 498 } 499 } 500 501 void Visit(const Style* style) override { 502 pb::Style* pb_style = out_value_->mutable_compound_value()->mutable_style(); 503 if (style->parent) { 504 const Reference& parent = style->parent.value(); 505 SerializeReferenceToPb(parent, pb_style->mutable_parent()); 506 if (src_pool_ != nullptr) { 507 SerializeSourceToPb(parent.GetSource(), src_pool_, pb_style->mutable_parent_source()); 508 } 509 } 510 511 for (const Style::Entry& entry : style->entries) { 512 pb::Style_Entry* pb_entry = pb_style->add_entry(); 513 SerializeReferenceToPb(entry.key, pb_entry->mutable_key()); 514 SerializeItemMetaDataToPb(entry.key, pb_entry, src_pool_); 515 SerializeItemToPb(*entry.value, pb_entry->mutable_item()); 516 } 517 } 518 519 void Visit(const Styleable* styleable) override { 520 pb::Styleable* pb_styleable = out_value_->mutable_compound_value()->mutable_styleable(); 521 for (const Reference& entry : styleable->entries) { 522 pb::Styleable_Entry* pb_entry = pb_styleable->add_entry(); 523 SerializeItemMetaDataToPb(entry, pb_entry, src_pool_); 524 SerializeReferenceToPb(entry, pb_entry->mutable_attr()); 525 } 526 } 527 528 void Visit(const Array* array) override { 529 pb::Array* pb_array = out_value_->mutable_compound_value()->mutable_array(); 530 for (const std::unique_ptr<Item>& element : array->elements) { 531 pb::Array_Element* pb_element = pb_array->add_element(); 532 SerializeItemMetaDataToPb(*element, pb_element, src_pool_); 533 SerializeItemToPb(*element, pb_element->mutable_item()); 534 } 535 } 536 537 void Visit(const Plural* plural) override { 538 pb::Plural* pb_plural = out_value_->mutable_compound_value()->mutable_plural(); 539 const size_t count = plural->values.size(); 540 for (size_t i = 0; i < count; i++) { 541 if (!plural->values[i]) { 542 // No plural value set here. 543 continue; 544 } 545 546 pb::Plural_Entry* pb_entry = pb_plural->add_entry(); 547 pb_entry->set_arity(SerializePluralEnumToPb(i)); 548 SerializeItemMetaDataToPb(*plural->values[i], pb_entry, src_pool_); 549 SerializeItemToPb(*plural->values[i], pb_entry->mutable_item()); 550 } 551 } 552 553 void VisitAny(const Value* unknown) override { 554 LOG(FATAL) << "unimplemented value: " << *unknown; 555 } 556 557 private: 558 pb::Value* out_value_; 559 StringPool* src_pool_; 560 }; 561 562 } // namespace 563 564 void SerializeValueToPb(const Value& value, pb::Value* out_value, StringPool* src_pool) { 565 ValueSerializer serializer(out_value, src_pool); 566 value.Accept(&serializer); 567 568 // Serialize the meta-data of the Value. 569 out_value->set_comment(value.GetComment()); 570 out_value->set_weak(value.IsWeak()); 571 if (src_pool != nullptr) { 572 SerializeSourceToPb(value.GetSource(), src_pool, out_value->mutable_source()); 573 } 574 } 575 576 void SerializeItemToPb(const Item& item, pb::Item* out_item) { 577 pb::Value value; 578 ValueSerializer serializer(&value, nullptr); 579 item.Accept(&serializer); 580 out_item->MergeFrom(value.item()); 581 } 582 583 void SerializeCompiledFileToPb(const ResourceFile& file, pb::internal::CompiledFile* out_file) { 584 out_file->set_resource_name(file.name.to_string()); 585 out_file->set_source_path(file.source.path); 586 out_file->set_type(SerializeFileReferenceTypeToPb(file.type)); 587 SerializeConfig(file.config, out_file->mutable_config()); 588 589 for (const SourcedResourceName& exported : file.exported_symbols) { 590 pb::internal::CompiledFile_Symbol* pb_symbol = out_file->add_exported_symbol(); 591 pb_symbol->set_resource_name(exported.name.to_string()); 592 pb_symbol->mutable_source()->set_line_number(exported.line); 593 } 594 } 595 596 static void SerializeXmlCommon(const xml::Node& node, pb::XmlNode* out_node) { 597 pb::SourcePosition* pb_src = out_node->mutable_source(); 598 pb_src->set_line_number(node.line_number); 599 pb_src->set_column_number(node.column_number); 600 } 601 602 void SerializeXmlToPb(const xml::Element& el, pb::XmlNode* out_node) { 603 SerializeXmlCommon(el, out_node); 604 605 pb::XmlElement* pb_element = out_node->mutable_element(); 606 pb_element->set_name(el.name); 607 pb_element->set_namespace_uri(el.namespace_uri); 608 609 for (const xml::NamespaceDecl& ns : el.namespace_decls) { 610 pb::XmlNamespace* pb_ns = pb_element->add_namespace_declaration(); 611 pb_ns->set_prefix(ns.prefix); 612 pb_ns->set_uri(ns.uri); 613 pb::SourcePosition* pb_src = pb_ns->mutable_source(); 614 pb_src->set_line_number(ns.line_number); 615 pb_src->set_column_number(ns.column_number); 616 } 617 618 for (const xml::Attribute& attr : el.attributes) { 619 pb::XmlAttribute* pb_attr = pb_element->add_attribute(); 620 pb_attr->set_name(attr.name); 621 pb_attr->set_namespace_uri(attr.namespace_uri); 622 pb_attr->set_value(attr.value); 623 if (attr.compiled_attribute) { 624 const ResourceId attr_id = attr.compiled_attribute.value().id.value_or_default({}); 625 pb_attr->set_resource_id(attr_id.id); 626 } 627 if (attr.compiled_value != nullptr) { 628 SerializeItemToPb(*attr.compiled_value, pb_attr->mutable_compiled_item()); 629 pb::SourcePosition* pb_src = pb_attr->mutable_source(); 630 pb_src->set_line_number(attr.compiled_value->GetSource().line.value_or_default(0)); 631 } 632 } 633 634 for (const std::unique_ptr<xml::Node>& child : el.children) { 635 if (const xml::Element* child_el = xml::NodeCast<xml::Element>(child.get())) { 636 SerializeXmlToPb(*child_el, pb_element->add_child()); 637 } else if (const xml::Text* text_el = xml::NodeCast<xml::Text>(child.get())) { 638 pb::XmlNode* pb_child_node = pb_element->add_child(); 639 SerializeXmlCommon(*text_el, pb_child_node); 640 pb_child_node->set_text(text_el->text); 641 } else { 642 LOG(FATAL) << "unhandled XmlNode type"; 643 } 644 } 645 } 646 647 void SerializeXmlResourceToPb(const xml::XmlResource& resource, pb::XmlNode* out_node) { 648 SerializeXmlToPb(*resource.root, out_node); 649 } 650 651 } // namespace aapt 652