blob: 4a88d61ef84cd972ff2c6003f1af82ff7b749633 [file] [log] [blame]
Adam Lesinski59e04c62016-02-04 15:59:23 -08001/*
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
Adam Lesinskice5e56e2016-10-21 17:56:45 -070017#include "proto/ProtoSerialize.h"
18
19#include "android-base/logging.h"
20#include "androidfw/ResourceTypes.h"
21
Adam Lesinski59e04c62016-02-04 15:59:23 -080022#include "ResourceTable.h"
23#include "ResourceUtils.h"
24#include "ValueVisitor.h"
25#include "proto/ProtoHelpers.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080026
27namespace aapt {
28
29namespace {
30
31class ReferenceIdToNameVisitor : public ValueVisitor {
Adam Lesinskib54ef102016-10-21 13:38:42 -070032 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033 using ValueVisitor::Visit;
Adam Lesinski59e04c62016-02-04 15:59:23 -080034
Adam Lesinski4488f1c2017-05-26 17:33:38 -070035 explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070036 : mapping_(mapping) {
37 CHECK(mapping_ != nullptr);
Adam Lesinskib54ef102016-10-21 13:38:42 -070038 }
39
Adam Lesinskice5e56e2016-10-21 17:56:45 -070040 void Visit(Reference* reference) override {
41 if (!reference->id || !reference->id.value().is_valid()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070042 return;
Adam Lesinski59e04c62016-02-04 15:59:23 -080043 }
44
Adam Lesinskib54ef102016-10-21 13:38:42 -070045 ResourceId id = reference->id.value();
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046 auto cache_iter = mapping_->find(id);
47 if (cache_iter != mapping_->end()) {
48 reference->name = cache_iter->second.ToResourceName();
Adam Lesinski59e04c62016-02-04 15:59:23 -080049 }
Adam Lesinskib54ef102016-10-21 13:38:42 -070050 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080051
Adam Lesinskib54ef102016-10-21 13:38:42 -070052 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 const std::map<ResourceId, ResourceNameRef>* mapping_;
Adam Lesinski59e04c62016-02-04 15:59:23 -080054};
55
56class PackagePbDeserializer {
Adam Lesinskib54ef102016-10-21 13:38:42 -070057 public:
Adam Lesinski08535002017-08-04 16:15:17 -070058 PackagePbDeserializer(const android::ResStringPool* sourcePool, const Source& source,
59 IDiagnostics* diag)
60 : source_pool_(sourcePool), source_(source), diag_(diag) {
61 }
Adam Lesinskib54ef102016-10-21 13:38:42 -070062
63 public:
Adam Lesinski4ffea042017-08-10 15:37:28 -070064 bool DeserializeFromPb(const pb::Package& pb_package, ResourceTable* table) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070065 Maybe<uint8_t> id;
Adam Lesinski4ffea042017-08-10 15:37:28 -070066 if (pb_package.has_package_id()) {
Adam Lesinski5bd44232017-09-07 09:39:07 -070067 id = static_cast<uint8_t>(pb_package.package_id().id());
Adam Lesinski59e04c62016-02-04 15:59:23 -080068 }
69
Adam Lesinski4ffea042017-08-10 15:37:28 -070070 std::map<ResourceId, ResourceNameRef> id_index;
Adam Lesinski59e04c62016-02-04 15:59:23 -080071
Adam Lesinski4ffea042017-08-10 15:37:28 -070072 ResourceTablePackage* pkg = table->CreatePackage(pb_package.package_name(), id);
73 for (const pb::Type& pb_type : pb_package.type()) {
74 const ResourceType* res_type = ParseResourceType(pb_type.name());
75 if (res_type == nullptr) {
76 diag_->Error(DiagMessage(source_) << "unknown type '" << pb_type.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -070077 return {};
78 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080079
Adam Lesinski4ffea042017-08-10 15:37:28 -070080 ResourceTableType* type = pkg->FindOrCreateType(*res_type);
Adam Lesinskib54ef102016-10-21 13:38:42 -070081
Adam Lesinski4ffea042017-08-10 15:37:28 -070082 for (const pb::Entry& pb_entry : pb_type.entry()) {
83 ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070084
Adam Lesinski08535002017-08-04 16:15:17 -070085 // Deserialize the symbol status (public/private with source and comments).
Adam Lesinski4ffea042017-08-10 15:37:28 -070086 if (pb_entry.has_symbol_status()) {
87 const pb::SymbolStatus& pb_status = pb_entry.symbol_status();
88 if (pb_status.has_source()) {
89 DeserializeSourceFromPb(pb_status.source(), *source_pool_,
90 &entry->symbol_status.source);
Adam Lesinskib54ef102016-10-21 13:38:42 -070091 }
92
Adam Lesinski5bd44232017-09-07 09:39:07 -070093 entry->symbol_status.comment = pb_status.comment();
Adam Lesinski4ffea042017-08-10 15:37:28 -070094 entry->symbol_status.allow_new = pb_status.allow_new();
Adam Lesinski4488f1c2017-05-26 17:33:38 -070095
Adam Lesinski4ffea042017-08-10 15:37:28 -070096 SymbolState visibility = DeserializeVisibilityFromPb(pb_status.visibility());
Adam Lesinskice5e56e2016-10-21 17:56:45 -070097 entry->symbol_status.state = visibility;
Adam Lesinskib54ef102016-10-21 13:38:42 -070098
99 if (visibility == SymbolState::kPublic) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700100 // This is a public symbol, we must encode the ID now if there is one.
Adam Lesinski5bd44232017-09-07 09:39:07 -0700101 if (pb_entry.has_entry_id()) {
102 entry->id = static_cast<uint16_t>(pb_entry.entry_id().id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800103 }
104
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700105 if (type->symbol_status.state != SymbolState::kPublic) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700106 // If the type has not been made public, do so now.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 type->symbol_status.state = SymbolState::kPublic;
Adam Lesinski5bd44232017-09-07 09:39:07 -0700108 if (pb_type.has_type_id()) {
109 type->id = static_cast<uint8_t>(pb_type.type_id().id());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700110 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800111 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700112 } else if (visibility == SymbolState::kPrivate) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700113 if (type->symbol_status.state == SymbolState::kUndefined) {
114 type->symbol_status.state = SymbolState::kPrivate;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700115 }
116 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800117 }
118
Adam Lesinski5bd44232017-09-07 09:39:07 -0700119 ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(),
120 pb_entry.entry_id().id());
Adam Lesinski4ffea042017-08-10 15:37:28 -0700121 if (resid.is_valid()) {
122 id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700123 }
124
Adam Lesinski4ffea042017-08-10 15:37:28 -0700125 for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
Adam Lesinskib58c3ef2017-09-12 17:39:52 -0700126 const pb::Configuration& pb_config = pb_config_value.config();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700127
128 ConfigDescription config;
Adam Lesinski4ffea042017-08-10 15:37:28 -0700129 if (!DeserializeConfigDescriptionFromPb(pb_config, &config)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 diag_->Error(DiagMessage(source_) << "invalid configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700131 return {};
132 }
133
Adam Lesinski4ffea042017-08-10 15:37:28 -0700134 ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product());
135 if (config_value->value) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700136 // Duplicate config.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700137 diag_->Error(DiagMessage(source_) << "duplicate configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700138 return {};
139 }
140
Adam Lesinski4ffea042017-08-10 15:37:28 -0700141 config_value->value =
142 DeserializeValueFromPb(pb_config_value.value(), config, &table->string_pool);
143 if (!config_value->value) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700144 return {};
145 }
146 }
147 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800148 }
149
Adam Lesinski4ffea042017-08-10 15:37:28 -0700150 ReferenceIdToNameVisitor visitor(&id_index);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700151 VisitAllValuesInPackage(pkg, &visitor);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700152 return true;
153 }
154
155 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700156 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
Adam Lesinski08535002017-08-04 16:15:17 -0700157 const ConfigDescription& config, StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158 if (pb_item.has_ref()) {
159 const pb::Reference& pb_ref = pb_item.ref();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700160 std::unique_ptr<Reference> ref = util::make_unique<Reference>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700161 if (!DeserializeReferenceFromPb(pb_ref, ref.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700162 return {};
163 }
164 return std::move(ref);
165
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 } else if (pb_item.has_prim()) {
167 const pb::Primitive& pb_prim = pb_item.prim();
Adam Lesinski08535002017-08-04 16:15:17 -0700168 return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
169 pb_prim.data());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700170
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700171 } else if (pb_item.has_id()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700172 return util::make_unique<Id>();
173
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174 } else if (pb_item.has_str()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700175 return util::make_unique<String>(
Adam Lesinski08535002017-08-04 16:15:17 -0700176 pool->MakeRef(pb_item.str().value(), StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700177
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700178 } else if (pb_item.has_raw_str()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700179 return util::make_unique<RawString>(
Adam Lesinski08535002017-08-04 16:15:17 -0700180 pool->MakeRef(pb_item.raw_str().value(), StringPool::Context(config)));
181
182 } else if (pb_item.has_styled_str()) {
183 const pb::StyledString& pb_str = pb_item.styled_str();
184 StyleString style_str{pb_str.value()};
185 for (const pb::StyledString::Span& pb_span : pb_str.span()) {
186 style_str.spans.push_back(Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()});
187 }
188 return util::make_unique<StyledString>(pool->MakeRef(
189 style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700190
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700191 } else if (pb_item.has_file()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700192 return util::make_unique<FileReference>(pool->MakeRef(
Adam Lesinski08535002017-08-04 16:15:17 -0700193 pb_item.file().path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700194
195 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700196 diag_->Error(DiagMessage(source_) << "unknown item");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700197 }
198 return {};
199 }
200
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700201 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
Adam Lesinski59e04c62016-02-04 15:59:23 -0800202 const ConfigDescription& config,
203 StringPool* pool) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700204 std::unique_ptr<Value> value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700205 if (pb_value.has_item()) {
206 value = DeserializeItemFromPb(pb_value.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700207 if (!value) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800208 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700209 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800210
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700211 } else if (pb_value.has_compound_value()) {
212 const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
213 if (pb_compound_value.has_attr()) {
214 const pb::Attribute& pb_attr = pb_compound_value.attr();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700215 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700216 attr->type_mask = pb_attr.format_flags();
217 attr->min_int = pb_attr.min_int();
218 attr->max_int = pb_attr.max_int();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700219 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700220 Attribute::Symbol symbol;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700221 DeserializeItemCommon(pb_symbol, &symbol.symbol);
222 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800223 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700224 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700225 symbol.value = pb_symbol.value();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700226 attr->symbols.push_back(std::move(symbol));
227 }
228 value = std::move(attr);
229
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700230 } else if (pb_compound_value.has_style()) {
231 const pb::Style& pb_style = pb_compound_value.style();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700232 std::unique_ptr<Style> style = util::make_unique<Style>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700233 if (pb_style.has_parent()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700234 style->parent = Reference();
Adam Lesinski08535002017-08-04 16:15:17 -0700235 if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700236 return {};
237 }
238
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700239 if (pb_style.has_parent_source()) {
240 Source parent_source;
Adam Lesinski08535002017-08-04 16:15:17 -0700241 DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_, &parent_source);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700242 style->parent.value().SetSource(std::move(parent_source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700243 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800244 }
245
Adam Lesinski4ffea042017-08-10 15:37:28 -0700246 for (const pb::Style_Entry& pb_entry : pb_style.entry()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700247 Style::Entry entry;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700248 DeserializeItemCommon(pb_entry, &entry.key);
249 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700250 return {};
251 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800252
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700253 entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700254 if (!entry.value) {
255 return {};
256 }
257
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 DeserializeItemCommon(pb_entry, entry.value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700259 style->entries.push_back(std::move(entry));
260 }
261 value = std::move(style);
262
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700263 } else if (pb_compound_value.has_styleable()) {
264 const pb::Styleable& pb_styleable = pb_compound_value.styleable();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700265 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700266 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700267 Reference attr_ref;
268 DeserializeItemCommon(pb_entry, &attr_ref);
269 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
270 styleable->entries.push_back(std::move(attr_ref));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700271 }
272 value = std::move(styleable);
273
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700274 } else if (pb_compound_value.has_array()) {
275 const pb::Array& pb_array = pb_compound_value.array();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700276 std::unique_ptr<Array> array = util::make_unique<Array>();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700277 for (const pb::Array_Element& pb_entry : pb_array.element()) {
Adam Lesinski08535002017-08-04 16:15:17 -0700278 std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700279 if (!item) {
280 return {};
281 }
282
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700283 DeserializeItemCommon(pb_entry, item.get());
Adam Lesinski4ffea042017-08-10 15:37:28 -0700284 array->elements.push_back(std::move(item));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700285 }
286 value = std::move(array);
287
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700288 } else if (pb_compound_value.has_plural()) {
289 const pb::Plural& pb_plural = pb_compound_value.plural();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700290 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700291 for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700292 size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
Adam Lesinski08535002017-08-04 16:15:17 -0700293 plural->values[pluralIdx] = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700294 if (!plural->values[pluralIdx]) {
295 return {};
296 }
297
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700298 DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700299 }
300 value = std::move(plural);
301
302 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700303 diag_->Error(DiagMessage(source_) << "unknown compound value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700304 return {};
305 }
306 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700307 diag_->Error(DiagMessage(source_) << "unknown value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700308 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800309 }
310
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700311 CHECK(value) << "forgot to set value";
Adam Lesinski59e04c62016-02-04 15:59:23 -0800312
Adam Lesinski4ffea042017-08-10 15:37:28 -0700313 value->SetWeak(pb_value.weak());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700314 DeserializeItemCommon(pb_value, value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700315 return value;
316 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800317
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700318 bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700319 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
320 out_ref->private_reference = pb_ref.private_();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800321
Adam Lesinski5bd44232017-09-07 09:39:07 -0700322 if (pb_ref.id() != 0) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700323 out_ref->id = ResourceId(pb_ref.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800324 }
325
Adam Lesinski5bd44232017-09-07 09:39:07 -0700326 if (!pb_ref.name().empty()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700327 ResourceNameRef name_ref;
Adam Lesinski08535002017-08-04 16:15:17 -0700328 if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) {
329 diag_->Error(DiagMessage(source_) << "invalid reference name '" << pb_ref.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700330 return false;
331 }
332
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700333 out_ref->name = name_ref.ToResourceName();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700334 }
335 return true;
336 }
337
338 template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700339 void DeserializeItemCommon(const T& pb_item, Value* out_value) {
340 if (pb_item.has_source()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700341 Source source;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700342 DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
343 out_value->SetSource(std::move(source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700344 }
Adam Lesinski5bd44232017-09-07 09:39:07 -0700345 out_value->SetComment(pb_item.comment());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700346 }
347
348 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700349 const android::ResStringPool* source_pool_;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 const Source source_;
351 IDiagnostics* diag_;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800352};
353
Adam Lesinskib54ef102016-10-21 13:38:42 -0700354} // namespace
Adam Lesinski59e04c62016-02-04 15:59:23 -0800355
Adam Lesinski08535002017-08-04 16:15:17 -0700356std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& pb_table,
357 const Source& source, IDiagnostics* diag) {
358 // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
Adam Lesinskib54ef102016-10-21 13:38:42 -0700359 // causes errors when qualifying it with android::
360 using namespace android;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700361
Adam Lesinskib54ef102016-10-21 13:38:42 -0700362 std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800363
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700364 ResStringPool source_pool;
365 if (pb_table.has_source_pool()) {
Adam Lesinski08535002017-08-04 16:15:17 -0700366 status_t result = source_pool.setTo(pb_table.source_pool().data().data(),
367 pb_table.source_pool().data().size());
Adam Lesinski803c7c82016-04-06 16:09:43 -0700368 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369 diag->Error(DiagMessage(source) << "invalid source pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700370 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800371 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700372 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800373
Adam Lesinski08535002017-08-04 16:15:17 -0700374 PackagePbDeserializer package_pb_deserializer(&source_pool, source, diag);
Adam Lesinski4ffea042017-08-10 15:37:28 -0700375 for (const pb::Package& pb_package : pb_table.package()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700376 if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700377 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800378 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700379 }
380 return table;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800381}
382
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700383std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
Adam Lesinski4ffea042017-08-10 15:37:28 -0700384 const pb::internal::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700385 std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800386
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700387 ResourceNameRef name_ref;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800388
Adam Lesinskib54ef102016-10-21 13:38:42 -0700389 // Need to create an lvalue here so that nameRef can point to something real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700390 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
391 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700392 << "invalid resource name in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700393 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700394 return {};
395 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700396 file->name = name_ref.ToResourceName();
397 file->source.path = pb_file.source_path();
Adam Lesinskib58c3ef2017-09-12 17:39:52 -0700398 if (!DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config)) {
399 diag->Error(DiagMessage(source) << "invalid resource configuration in compiled file header");
400 return {};
401 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700402
Adam Lesinski4ffea042017-08-10 15:37:28 -0700403 for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) {
404 // Need to create an lvalue here so that nameRef can point to something real.
405 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700406 diag->Error(DiagMessage(source)
Adam Lesinskib58c3ef2017-09-12 17:39:52 -0700407 << "invalid resource name for exported symbol in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700408 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700409 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800410 }
Adam Lesinski4ffea042017-08-10 15:37:28 -0700411 size_t line = 0u;
412 if (pb_symbol.has_source()) {
413 line = pb_symbol.source().line_number();
414 }
415 file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line});
Adam Lesinskib54ef102016-10-21 13:38:42 -0700416 }
417 return file;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800418}
419
Adam Lesinskib54ef102016-10-21 13:38:42 -0700420} // namespace aapt