blob: 4b5619235c06c04e143ae80e0715f86ea9593556 [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:
58 PackagePbDeserializer(const android::ResStringPool* valuePool,
59 const android::ResStringPool* sourcePool,
60 const android::ResStringPool* symbolPool,
61 const Source& source, IDiagnostics* diag)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070062 : value_pool_(valuePool),
63 source_pool_(sourcePool),
64 symbol_pool_(symbolPool),
65 source_(source),
66 diag_(diag) {}
Adam Lesinskib54ef102016-10-21 13:38:42 -070067
68 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070069 bool DeserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070070 Maybe<uint8_t> id;
71 if (pbPackage.has_package_id()) {
72 id = static_cast<uint8_t>(pbPackage.package_id());
Adam Lesinski59e04c62016-02-04 15:59:23 -080073 }
74
Adam Lesinskib54ef102016-10-21 13:38:42 -070075 std::map<ResourceId, ResourceNameRef> idIndex;
Adam Lesinski59e04c62016-02-04 15:59:23 -080076
Adam Lesinski4488f1c2017-05-26 17:33:38 -070077 ResourceTablePackage* pkg = table->CreatePackage(pbPackage.package_name(), id);
Adam Lesinskib54ef102016-10-21 13:38:42 -070078 for (const pb::Type& pbType : pbPackage.types()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070079 const ResourceType* resType = ParseResourceType(pbType.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070080 if (!resType) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -070081 diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -070082 return {};
83 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080084
Adam Lesinskice5e56e2016-10-21 17:56:45 -070085 ResourceTableType* type = pkg->FindOrCreateType(*resType);
Adam Lesinskib54ef102016-10-21 13:38:42 -070086
87 for (const pb::Entry& pbEntry : pbType.entries()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070088 ResourceEntry* entry = type->FindOrCreateEntry(pbEntry.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070089
90 // Deserialize the symbol status (public/private with source and
91 // comments).
92 if (pbEntry.has_symbol_status()) {
93 const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
94 if (pbStatus.has_source()) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -070095 DeserializeSourceFromPb(pbStatus.source(), *source_pool_, &entry->symbol_status.source);
Adam Lesinskib54ef102016-10-21 13:38:42 -070096 }
97
98 if (pbStatus.has_comment()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099 entry->symbol_status.comment = pbStatus.comment();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700100 }
101
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700102 entry->symbol_status.allow_new = pbStatus.allow_new();
103
104 SymbolState visibility = DeserializeVisibilityFromPb(pbStatus.visibility());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700105 entry->symbol_status.state = visibility;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700106
107 if (visibility == SymbolState::kPublic) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700108 // This is a public symbol, we must encode the ID now if there is one.
Adam Lesinskib54ef102016-10-21 13:38:42 -0700109 if (pbEntry.has_id()) {
110 entry->id = static_cast<uint16_t>(pbEntry.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800111 }
112
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700113 if (type->symbol_status.state != SymbolState::kPublic) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700114 // If the type has not been made public, do so now.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 type->symbol_status.state = SymbolState::kPublic;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700116 if (pbType.has_id()) {
117 type->id = static_cast<uint8_t>(pbType.id());
118 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800119 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700120 } else if (visibility == SymbolState::kPrivate) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700121 if (type->symbol_status.state == SymbolState::kUndefined) {
122 type->symbol_status.state = SymbolState::kPrivate;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700123 }
124 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800125 }
126
Adam Lesinskib54ef102016-10-21 13:38:42 -0700127 ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700128 if (resId.is_valid()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700129 idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
130 }
131
132 for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
133 const pb::ConfigDescription& pbConfig = pbConfigValue.config();
134
135 ConfigDescription config;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700136 if (!DeserializeConfigDescriptionFromPb(pbConfig, &config)) {
137 diag_->Error(DiagMessage(source_) << "invalid configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700138 return {};
139 }
140
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700141 ResourceConfigValue* configValue = entry->FindOrCreateValue(config, pbConfig.product());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700142 if (configValue->value) {
143 // Duplicate config.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700144 diag_->Error(DiagMessage(source_) << "duplicate configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700145 return {};
146 }
147
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700148 configValue->value =
149 DeserializeValueFromPb(pbConfigValue.value(), config, &table->string_pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700150 if (!configValue->value) {
151 return {};
152 }
153 }
154 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800155 }
156
Adam Lesinskib54ef102016-10-21 13:38:42 -0700157 ReferenceIdToNameVisitor visitor(&idIndex);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158 VisitAllValuesInPackage(pkg, &visitor);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700159 return true;
160 }
161
162 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700164 const ConfigDescription& config,
165 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700166 if (pb_item.has_ref()) {
167 const pb::Reference& pb_ref = pb_item.ref();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700168 std::unique_ptr<Reference> ref = util::make_unique<Reference>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700169 if (!DeserializeReferenceFromPb(pb_ref, ref.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700170 return {};
171 }
172 return std::move(ref);
173
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700174 } else if (pb_item.has_prim()) {
175 const pb::Primitive& pb_prim = pb_item.prim();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700176 android::Res_value prim = {};
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700177 prim.dataType = static_cast<uint8_t>(pb_prim.type());
178 prim.data = pb_prim.data();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700179 return util::make_unique<BinaryPrimitive>(prim);
180
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700181 } else if (pb_item.has_id()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700182 return util::make_unique<Id>();
183
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700184 } else if (pb_item.has_str()) {
185 const uint32_t idx = pb_item.str().idx();
186 const std::string str = util::GetString(*value_pool_, idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700187
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700188 const android::ResStringPool_span* spans = value_pool_->styleAt(idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700189 if (spans && spans->name.index != android::ResStringPool_span::END) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700190 StyleString style_str = {str};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700191 while (spans->name.index != android::ResStringPool_span::END) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700192 style_str.spans.push_back(
193 Span{util::GetString(*value_pool_, spans->name.index),
Adam Lesinskib54ef102016-10-21 13:38:42 -0700194 spans->firstChar, spans->lastChar});
195 spans++;
196 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197 return util::make_unique<StyledString>(pool->MakeRef(
198 style_str,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700199 StringPool::Context(StringPool::Context::kStylePriority, config)));
200 }
201 return util::make_unique<String>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700202 pool->MakeRef(str, StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700203
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700204 } else if (pb_item.has_raw_str()) {
205 const uint32_t idx = pb_item.raw_str().idx();
206 const std::string str = util::GetString(*value_pool_, idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700207 return util::make_unique<RawString>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 pool->MakeRef(str, StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700209
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700210 } else if (pb_item.has_file()) {
211 const uint32_t idx = pb_item.file().path_idx();
212 const std::string str = util::GetString(*value_pool_, idx);
213 return util::make_unique<FileReference>(pool->MakeRef(
Adam Lesinskib54ef102016-10-21 13:38:42 -0700214 str,
215 StringPool::Context(StringPool::Context::kHighPriority, config)));
216
217 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700218 diag_->Error(DiagMessage(source_) << "unknown item");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700219 }
220 return {};
221 }
222
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
Adam Lesinski59e04c62016-02-04 15:59:23 -0800224 const ConfigDescription& config,
225 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700226 const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800227
Adam Lesinskib54ef102016-10-21 13:38:42 -0700228 std::unique_ptr<Value> value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700229 if (pb_value.has_item()) {
230 value = DeserializeItemFromPb(pb_value.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700231 if (!value) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800232 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700233 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800234
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 } else if (pb_value.has_compound_value()) {
236 const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
237 if (pb_compound_value.has_attr()) {
238 const pb::Attribute& pb_attr = pb_compound_value.attr();
239 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);
240 attr->type_mask = pb_attr.format_flags();
241 attr->min_int = pb_attr.min_int();
242 attr->max_int = pb_attr.max_int();
243 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700244 Attribute::Symbol symbol;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700245 DeserializeItemCommon(pb_symbol, &symbol.symbol);
246 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800247 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700248 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 symbol.value = pb_symbol.value();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700250 attr->symbols.push_back(std::move(symbol));
251 }
252 value = std::move(attr);
253
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700254 } else if (pb_compound_value.has_style()) {
255 const pb::Style& pb_style = pb_compound_value.style();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700256 std::unique_ptr<Style> style = util::make_unique<Style>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700257 if (pb_style.has_parent()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700258 style->parent = Reference();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700259 if (!DeserializeReferenceFromPb(pb_style.parent(),
Adam Lesinskib54ef102016-10-21 13:38:42 -0700260 &style->parent.value())) {
261 return {};
262 }
263
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700264 if (pb_style.has_parent_source()) {
265 Source parent_source;
266 DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_,
267 &parent_source);
268 style->parent.value().SetSource(std::move(parent_source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700269 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800270 }
271
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700272 for (const pb::Style_Entry& pb_entry : pb_style.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700273 Style::Entry entry;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700274 DeserializeItemCommon(pb_entry, &entry.key);
275 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700276 return {};
277 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800278
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700279 entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700280 if (!entry.value) {
281 return {};
282 }
283
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700284 DeserializeItemCommon(pb_entry, entry.value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700285 style->entries.push_back(std::move(entry));
286 }
287 value = std::move(style);
288
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700289 } else if (pb_compound_value.has_styleable()) {
290 const pb::Styleable& pb_styleable = pb_compound_value.styleable();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700291 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700292 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) {
293 Reference attr_ref;
294 DeserializeItemCommon(pb_entry, &attr_ref);
295 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
296 styleable->entries.push_back(std::move(attr_ref));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700297 }
298 value = std::move(styleable);
299
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700300 } else if (pb_compound_value.has_array()) {
301 const pb::Array& pb_array = pb_compound_value.array();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700302 std::unique_ptr<Array> array = util::make_unique<Array>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700303 for (const pb::Array_Entry& pb_entry : pb_array.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700304 std::unique_ptr<Item> item =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700305 DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700306 if (!item) {
307 return {};
308 }
309
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700310 DeserializeItemCommon(pb_entry, item.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700311 array->items.push_back(std::move(item));
312 }
313 value = std::move(array);
314
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700315 } else if (pb_compound_value.has_plural()) {
316 const pb::Plural& pb_plural = pb_compound_value.plural();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700317 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700318 for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) {
319 size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700320 plural->values[pluralIdx] =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700321 DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700322 if (!plural->values[pluralIdx]) {
323 return {};
324 }
325
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700326 DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700327 }
328 value = std::move(plural);
329
330 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700331 diag_->Error(DiagMessage(source_) << "unknown compound value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700332 return {};
333 }
334 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700335 diag_->Error(DiagMessage(source_) << "unknown value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700336 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800337 }
338
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700339 CHECK(value) << "forgot to set value";
Adam Lesinski59e04c62016-02-04 15:59:23 -0800340
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700341 value->SetWeak(is_weak);
342 DeserializeItemCommon(pb_value, value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700343 return value;
344 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800345
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700346 bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700347 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
348 out_ref->private_reference = pb_ref.private_();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800349
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700350 if (pb_ref.has_id()) {
351 out_ref->id = ResourceId(pb_ref.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800352 }
353
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700354 if (pb_ref.has_symbol_idx()) {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700355 const std::string str_symbol = util::GetString(*symbol_pool_, pb_ref.symbol_idx());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700356 ResourceNameRef name_ref;
357 if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700358 diag_->Error(DiagMessage(source_) << "invalid reference name '" << str_symbol << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700359 return false;
360 }
361
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700362 out_ref->name = name_ref.ToResourceName();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700363 }
364 return true;
365 }
366
367 template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700368 void DeserializeItemCommon(const T& pb_item, Value* out_value) {
369 if (pb_item.has_source()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700370 Source source;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700371 DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
372 out_value->SetSource(std::move(source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700373 }
374
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700375 if (pb_item.has_comment()) {
376 out_value->SetComment(pb_item.comment());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700377 }
378 }
379
380 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700381 const android::ResStringPool* value_pool_;
382 const android::ResStringPool* source_pool_;
383 const android::ResStringPool* symbol_pool_;
384 const Source source_;
385 IDiagnostics* diag_;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800386};
387
Adam Lesinskib54ef102016-10-21 13:38:42 -0700388} // namespace
Adam Lesinski59e04c62016-02-04 15:59:23 -0800389
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700390std::unique_ptr<ResourceTable> DeserializeTableFromPb(
391 const pb::ResourceTable& pb_table, const Source& source,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700392 IDiagnostics* diag) {
393 // We import the android namespace because on Windows NO_ERROR is a macro, not
394 // an enum, which
395 // causes errors when qualifying it with android::
396 using namespace android;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700397
Adam Lesinskib54ef102016-10-21 13:38:42 -0700398 std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800399
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700400 if (!pb_table.has_string_pool()) {
401 diag->Error(DiagMessage(source) << "no string pool found");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700402 return {};
403 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800404
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700405 ResStringPool value_pool;
406 status_t result = value_pool.setTo(pb_table.string_pool().data().data(),
407 pb_table.string_pool().data().size());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700408 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700409 diag->Error(DiagMessage(source) << "invalid string pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700410 return {};
411 }
412
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700413 ResStringPool source_pool;
414 if (pb_table.has_source_pool()) {
415 result = source_pool.setTo(pb_table.source_pool().data().data(),
416 pb_table.source_pool().data().size());
Adam Lesinski803c7c82016-04-06 16:09:43 -0700417 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700418 diag->Error(DiagMessage(source) << "invalid source pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700419 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800420 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700421 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800422
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700423 ResStringPool symbol_pool;
424 if (pb_table.has_symbol_pool()) {
425 result = symbol_pool.setTo(pb_table.symbol_pool().data().data(),
426 pb_table.symbol_pool().data().size());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700427 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700428 diag->Error(DiagMessage(source) << "invalid symbol pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700429 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800430 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700431 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800432
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700433 PackagePbDeserializer package_pb_deserializer(&value_pool, &source_pool,
434 &symbol_pool, source, diag);
435 for (const pb::Package& pb_package : pb_table.packages()) {
436 if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700437 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800438 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700439 }
440 return table;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800441}
442
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700443std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
444 const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700445 std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800446
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700447 ResourceNameRef name_ref;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800448
Adam Lesinskib54ef102016-10-21 13:38:42 -0700449 // Need to create an lvalue here so that nameRef can point to something real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700450 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
451 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700452 << "invalid resource name in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700453 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700454 return {};
455 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700456 file->name = name_ref.ToResourceName();
457 file->source.path = pb_file.source_path();
458 DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700459
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700460 for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700461 // Need to create an lvalue here so that nameRef can point to something
462 // real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700463 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(),
464 &name_ref)) {
465 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700466 << "invalid resource name for exported symbol in "
467 "compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700468 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700469 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800470 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700471 file->exported_symbols.push_back(
472 SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()});
Adam Lesinskib54ef102016-10-21 13:38:42 -0700473 }
474 return file;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800475}
476
Adam Lesinskib54ef102016-10-21 13:38:42 -0700477} // namespace aapt