blob: d93d495b106feebeda9c2058e6af07d07c3a5211 [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 Lesinskib54ef102016-10-21 13:38:42 -070035 explicit ReferenceIdToNameVisitor(
36 const std::map<ResourceId, ResourceNameRef>* mapping)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070037 : mapping_(mapping) {
38 CHECK(mapping_ != nullptr);
Adam Lesinskib54ef102016-10-21 13:38:42 -070039 }
40
Adam Lesinskice5e56e2016-10-21 17:56:45 -070041 void Visit(Reference* reference) override {
42 if (!reference->id || !reference->id.value().is_valid()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070043 return;
Adam Lesinski59e04c62016-02-04 15:59:23 -080044 }
45
Adam Lesinskib54ef102016-10-21 13:38:42 -070046 ResourceId id = reference->id.value();
Adam Lesinskice5e56e2016-10-21 17:56:45 -070047 auto cache_iter = mapping_->find(id);
48 if (cache_iter != mapping_->end()) {
49 reference->name = cache_iter->second.ToResourceName();
Adam Lesinski59e04c62016-02-04 15:59:23 -080050 }
Adam Lesinskib54ef102016-10-21 13:38:42 -070051 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080052
Adam Lesinskib54ef102016-10-21 13:38:42 -070053 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070054 const std::map<ResourceId, ResourceNameRef>* mapping_;
Adam Lesinski59e04c62016-02-04 15:59:23 -080055};
56
57class PackagePbDeserializer {
Adam Lesinskib54ef102016-10-21 13:38:42 -070058 public:
59 PackagePbDeserializer(const android::ResStringPool* valuePool,
60 const android::ResStringPool* sourcePool,
61 const android::ResStringPool* symbolPool,
62 const Source& source, IDiagnostics* diag)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070063 : value_pool_(valuePool),
64 source_pool_(sourcePool),
65 symbol_pool_(symbolPool),
66 source_(source),
67 diag_(diag) {}
Adam Lesinskib54ef102016-10-21 13:38:42 -070068
69 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070070 bool DeserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070071 Maybe<uint8_t> id;
72 if (pbPackage.has_package_id()) {
73 id = static_cast<uint8_t>(pbPackage.package_id());
Adam Lesinski59e04c62016-02-04 15:59:23 -080074 }
75
Adam Lesinskib54ef102016-10-21 13:38:42 -070076 std::map<ResourceId, ResourceNameRef> idIndex;
Adam Lesinski59e04c62016-02-04 15:59:23 -080077
Adam Lesinskib54ef102016-10-21 13:38:42 -070078 ResourceTablePackage* pkg =
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079 table->CreatePackage(pbPackage.package_name(), id);
Adam Lesinskib54ef102016-10-21 13:38:42 -070080 for (const pb::Type& pbType : pbPackage.types()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070081 const ResourceType* resType = ParseResourceType(pbType.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070082 if (!resType) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070083 diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name()
Adam Lesinskib54ef102016-10-21 13:38:42 -070084 << "'");
85 return {};
86 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080087
Adam Lesinskice5e56e2016-10-21 17:56:45 -070088 ResourceTableType* type = pkg->FindOrCreateType(*resType);
Adam Lesinskib54ef102016-10-21 13:38:42 -070089
90 for (const pb::Entry& pbEntry : pbType.entries()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070091 ResourceEntry* entry = type->FindOrCreateEntry(pbEntry.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070092
93 // Deserialize the symbol status (public/private with source and
94 // comments).
95 if (pbEntry.has_symbol_status()) {
96 const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
97 if (pbStatus.has_source()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070098 DeserializeSourceFromPb(pbStatus.source(), *source_pool_,
99 &entry->symbol_status.source);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700100 }
101
102 if (pbStatus.has_comment()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700103 entry->symbol_status.comment = pbStatus.comment();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700104 }
105
106 SymbolState visibility =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 DeserializeVisibilityFromPb(pbStatus.visibility());
108 entry->symbol_status.state = visibility;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700109
110 if (visibility == SymbolState::kPublic) {
111 // This is a public symbol, we must encode the ID now if there is
112 // one.
113 if (pbEntry.has_id()) {
114 entry->id = static_cast<uint16_t>(pbEntry.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800115 }
116
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700117 if (type->symbol_status.state != SymbolState::kPublic) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700118 // If the type has not been made public, do so now.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700119 type->symbol_status.state = SymbolState::kPublic;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700120 if (pbType.has_id()) {
121 type->id = static_cast<uint8_t>(pbType.id());
122 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800123 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700124 } else if (visibility == SymbolState::kPrivate) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700125 if (type->symbol_status.state == SymbolState::kUndefined) {
126 type->symbol_status.state = SymbolState::kPrivate;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700127 }
128 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800129 }
130
Adam Lesinskib54ef102016-10-21 13:38:42 -0700131 ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700132 if (resId.is_valid()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700133 idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
134 }
135
136 for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
137 const pb::ConfigDescription& pbConfig = pbConfigValue.config();
138
139 ConfigDescription config;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700140 if (!DeserializeConfigDescriptionFromPb(pbConfig, &config)) {
141 diag_->Error(DiagMessage(source_) << "invalid configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700142 return {};
143 }
144
145 ResourceConfigValue* configValue =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700146 entry->FindOrCreateValue(config, pbConfig.product());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700147 if (configValue->value) {
148 // Duplicate config.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700149 diag_->Error(DiagMessage(source_) << "duplicate configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700150 return {};
151 }
152
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700153 configValue->value = DeserializeValueFromPb(
154 pbConfigValue.value(), config, &table->string_pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700155 if (!configValue->value) {
156 return {};
157 }
158 }
159 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800160 }
161
Adam Lesinskib54ef102016-10-21 13:38:42 -0700162 ReferenceIdToNameVisitor visitor(&idIndex);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 VisitAllValuesInPackage(pkg, &visitor);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700164 return true;
165 }
166
167 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700168 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700169 const ConfigDescription& config,
170 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700171 if (pb_item.has_ref()) {
172 const pb::Reference& pb_ref = pb_item.ref();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700173 std::unique_ptr<Reference> ref = util::make_unique<Reference>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174 if (!DeserializeReferenceFromPb(pb_ref, ref.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700175 return {};
176 }
177 return std::move(ref);
178
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700179 } else if (pb_item.has_prim()) {
180 const pb::Primitive& pb_prim = pb_item.prim();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700181 android::Res_value prim = {};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700182 prim.dataType = static_cast<uint8_t>(pb_prim.type());
183 prim.data = pb_prim.data();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700184 return util::make_unique<BinaryPrimitive>(prim);
185
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700186 } else if (pb_item.has_id()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700187 return util::make_unique<Id>();
188
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700189 } else if (pb_item.has_str()) {
190 const uint32_t idx = pb_item.str().idx();
191 const std::string str = util::GetString(*value_pool_, idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700192
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 const android::ResStringPool_span* spans = value_pool_->styleAt(idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700194 if (spans && spans->name.index != android::ResStringPool_span::END) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700195 StyleString style_str = {str};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700196 while (spans->name.index != android::ResStringPool_span::END) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197 style_str.spans.push_back(
198 Span{util::GetString(*value_pool_, spans->name.index),
Adam Lesinskib54ef102016-10-21 13:38:42 -0700199 spans->firstChar, spans->lastChar});
200 spans++;
201 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700202 return util::make_unique<StyledString>(pool->MakeRef(
203 style_str,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700204 StringPool::Context(StringPool::Context::kStylePriority, config)));
205 }
206 return util::make_unique<String>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700207 pool->MakeRef(str, StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700208
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700209 } else if (pb_item.has_raw_str()) {
210 const uint32_t idx = pb_item.raw_str().idx();
211 const std::string str = util::GetString(*value_pool_, idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700212 return util::make_unique<RawString>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700213 pool->MakeRef(str, StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700214
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700215 } else if (pb_item.has_file()) {
216 const uint32_t idx = pb_item.file().path_idx();
217 const std::string str = util::GetString(*value_pool_, idx);
218 return util::make_unique<FileReference>(pool->MakeRef(
Adam Lesinskib54ef102016-10-21 13:38:42 -0700219 str,
220 StringPool::Context(StringPool::Context::kHighPriority, config)));
221
222 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223 diag_->Error(DiagMessage(source_) << "unknown item");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700224 }
225 return {};
226 }
227
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
Adam Lesinski59e04c62016-02-04 15:59:23 -0800229 const ConfigDescription& config,
230 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700231 const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800232
Adam Lesinskib54ef102016-10-21 13:38:42 -0700233 std::unique_ptr<Value> value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700234 if (pb_value.has_item()) {
235 value = DeserializeItemFromPb(pb_value.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700236 if (!value) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800237 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700238 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800239
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700240 } else if (pb_value.has_compound_value()) {
241 const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
242 if (pb_compound_value.has_attr()) {
243 const pb::Attribute& pb_attr = pb_compound_value.attr();
244 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);
245 attr->type_mask = pb_attr.format_flags();
246 attr->min_int = pb_attr.min_int();
247 attr->max_int = pb_attr.max_int();
248 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700249 Attribute::Symbol symbol;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 DeserializeItemCommon(pb_symbol, &symbol.symbol);
251 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800252 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700253 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700254 symbol.value = pb_symbol.value();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700255 attr->symbols.push_back(std::move(symbol));
256 }
257 value = std::move(attr);
258
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700259 } else if (pb_compound_value.has_style()) {
260 const pb::Style& pb_style = pb_compound_value.style();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700261 std::unique_ptr<Style> style = util::make_unique<Style>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700262 if (pb_style.has_parent()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700263 style->parent = Reference();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700264 if (!DeserializeReferenceFromPb(pb_style.parent(),
Adam Lesinskib54ef102016-10-21 13:38:42 -0700265 &style->parent.value())) {
266 return {};
267 }
268
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700269 if (pb_style.has_parent_source()) {
270 Source parent_source;
271 DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_,
272 &parent_source);
273 style->parent.value().SetSource(std::move(parent_source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700274 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800275 }
276
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700277 for (const pb::Style_Entry& pb_entry : pb_style.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700278 Style::Entry entry;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 DeserializeItemCommon(pb_entry, &entry.key);
280 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700281 return {};
282 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800283
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700284 entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700285 if (!entry.value) {
286 return {};
287 }
288
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700289 DeserializeItemCommon(pb_entry, entry.value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700290 style->entries.push_back(std::move(entry));
291 }
292 value = std::move(style);
293
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700294 } else if (pb_compound_value.has_styleable()) {
295 const pb::Styleable& pb_styleable = pb_compound_value.styleable();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700296 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700297 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) {
298 Reference attr_ref;
299 DeserializeItemCommon(pb_entry, &attr_ref);
300 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
301 styleable->entries.push_back(std::move(attr_ref));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700302 }
303 value = std::move(styleable);
304
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700305 } else if (pb_compound_value.has_array()) {
306 const pb::Array& pb_array = pb_compound_value.array();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700307 std::unique_ptr<Array> array = util::make_unique<Array>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700308 for (const pb::Array_Entry& pb_entry : pb_array.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700309 std::unique_ptr<Item> item =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700310 DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700311 if (!item) {
312 return {};
313 }
314
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700315 DeserializeItemCommon(pb_entry, item.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700316 array->items.push_back(std::move(item));
317 }
318 value = std::move(array);
319
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700320 } else if (pb_compound_value.has_plural()) {
321 const pb::Plural& pb_plural = pb_compound_value.plural();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700322 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700323 for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) {
324 size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700325 plural->values[pluralIdx] =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700326 DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700327 if (!plural->values[pluralIdx]) {
328 return {};
329 }
330
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700331 DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700332 }
333 value = std::move(plural);
334
335 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700336 diag_->Error(DiagMessage(source_) << "unknown compound value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700337 return {};
338 }
339 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700340 diag_->Error(DiagMessage(source_) << "unknown value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700341 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800342 }
343
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700344 CHECK(value) << "forgot to set value";
Adam Lesinski59e04c62016-02-04 15:59:23 -0800345
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700346 value->SetWeak(is_weak);
347 DeserializeItemCommon(pb_value, value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700348 return value;
349 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800350
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700351 bool DeserializeReferenceFromPb(const pb::Reference& pb_ref,
352 Reference* out_ref) {
353 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
354 out_ref->private_reference = pb_ref.private_();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800355
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700356 if (!pb_ref.has_id() && !pb_ref.has_symbol_idx()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700357 return false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800358 }
359
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700360 if (pb_ref.has_id()) {
361 out_ref->id = ResourceId(pb_ref.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800362 }
363
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700364 if (pb_ref.has_symbol_idx()) {
365 const std::string str_symbol =
366 util::GetString(*symbol_pool_, pb_ref.symbol_idx());
367 ResourceNameRef name_ref;
368 if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
369 diag_->Error(DiagMessage(source_) << "invalid reference name '"
370 << str_symbol << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700371 return false;
372 }
373
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700374 out_ref->name = name_ref.ToResourceName();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700375 }
376 return true;
377 }
378
379 template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700380 void DeserializeItemCommon(const T& pb_item, Value* out_value) {
381 if (pb_item.has_source()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700382 Source source;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700383 DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
384 out_value->SetSource(std::move(source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700385 }
386
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700387 if (pb_item.has_comment()) {
388 out_value->SetComment(pb_item.comment());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700389 }
390 }
391
392 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700393 const android::ResStringPool* value_pool_;
394 const android::ResStringPool* source_pool_;
395 const android::ResStringPool* symbol_pool_;
396 const Source source_;
397 IDiagnostics* diag_;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800398};
399
Adam Lesinskib54ef102016-10-21 13:38:42 -0700400} // namespace
Adam Lesinski59e04c62016-02-04 15:59:23 -0800401
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700402std::unique_ptr<ResourceTable> DeserializeTableFromPb(
403 const pb::ResourceTable& pb_table, const Source& source,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700404 IDiagnostics* diag) {
405 // We import the android namespace because on Windows NO_ERROR is a macro, not
406 // an enum, which
407 // causes errors when qualifying it with android::
408 using namespace android;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700409
Adam Lesinskib54ef102016-10-21 13:38:42 -0700410 std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800411
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700412 if (!pb_table.has_string_pool()) {
413 diag->Error(DiagMessage(source) << "no string pool found");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700414 return {};
415 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800416
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700417 ResStringPool value_pool;
418 status_t result = value_pool.setTo(pb_table.string_pool().data().data(),
419 pb_table.string_pool().data().size());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700420 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700421 diag->Error(DiagMessage(source) << "invalid string pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700422 return {};
423 }
424
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700425 ResStringPool source_pool;
426 if (pb_table.has_source_pool()) {
427 result = source_pool.setTo(pb_table.source_pool().data().data(),
428 pb_table.source_pool().data().size());
Adam Lesinski803c7c82016-04-06 16:09:43 -0700429 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700430 diag->Error(DiagMessage(source) << "invalid source pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700431 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800432 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700433 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800434
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700435 ResStringPool symbol_pool;
436 if (pb_table.has_symbol_pool()) {
437 result = symbol_pool.setTo(pb_table.symbol_pool().data().data(),
438 pb_table.symbol_pool().data().size());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700439 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700440 diag->Error(DiagMessage(source) << "invalid symbol pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700441 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800442 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700443 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800444
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700445 PackagePbDeserializer package_pb_deserializer(&value_pool, &source_pool,
446 &symbol_pool, source, diag);
447 for (const pb::Package& pb_package : pb_table.packages()) {
448 if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700449 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800450 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700451 }
452 return table;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800453}
454
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700455std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
456 const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700457 std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800458
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700459 ResourceNameRef name_ref;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800460
Adam Lesinskib54ef102016-10-21 13:38:42 -0700461 // Need to create an lvalue here so that nameRef can point to something real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700462 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
463 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700464 << "invalid resource name in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700465 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700466 return {};
467 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700468 file->name = name_ref.ToResourceName();
469 file->source.path = pb_file.source_path();
470 DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700471
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700472 for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700473 // Need to create an lvalue here so that nameRef can point to something
474 // real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700475 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(),
476 &name_ref)) {
477 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700478 << "invalid resource name for exported symbol in "
479 "compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700480 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700481 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800482 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700483 file->exported_symbols.push_back(
484 SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()});
Adam Lesinskib54ef102016-10-21 13:38:42 -0700485 }
486 return file;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800487}
488
Adam Lesinskib54ef102016-10-21 13:38:42 -0700489} // namespace aapt