blob: 37d5ed0cf59d95636f37e7c12df7504b86e2063e [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(
Adam Lesinski5b6ee112017-07-28 17:10:35 -0700198 style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700199 }
200 return util::make_unique<String>(
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700201 pool->MakeRef(str, StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700202
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700203 } else if (pb_item.has_raw_str()) {
204 const uint32_t idx = pb_item.raw_str().idx();
205 const std::string str = util::GetString(*value_pool_, idx);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700206 return util::make_unique<RawString>(
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_file()) {
210 const uint32_t idx = pb_item.file().path_idx();
211 const std::string str = util::GetString(*value_pool_, idx);
212 return util::make_unique<FileReference>(pool->MakeRef(
Adam Lesinskib54ef102016-10-21 13:38:42 -0700213 str,
214 StringPool::Context(StringPool::Context::kHighPriority, config)));
215
216 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700217 diag_->Error(DiagMessage(source_) << "unknown item");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700218 }
219 return {};
220 }
221
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700222 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
Adam Lesinski59e04c62016-02-04 15:59:23 -0800223 const ConfigDescription& config,
224 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700225 const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800226
Adam Lesinskib54ef102016-10-21 13:38:42 -0700227 std::unique_ptr<Value> value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 if (pb_value.has_item()) {
229 value = DeserializeItemFromPb(pb_value.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700230 if (!value) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800231 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700232 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800233
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700234 } else if (pb_value.has_compound_value()) {
235 const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
236 if (pb_compound_value.has_attr()) {
237 const pb::Attribute& pb_attr = pb_compound_value.attr();
238 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);
239 attr->type_mask = pb_attr.format_flags();
240 attr->min_int = pb_attr.min_int();
241 attr->max_int = pb_attr.max_int();
242 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700243 Attribute::Symbol symbol;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700244 DeserializeItemCommon(pb_symbol, &symbol.symbol);
245 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800246 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700247 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700248 symbol.value = pb_symbol.value();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700249 attr->symbols.push_back(std::move(symbol));
250 }
251 value = std::move(attr);
252
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700253 } else if (pb_compound_value.has_style()) {
254 const pb::Style& pb_style = pb_compound_value.style();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700255 std::unique_ptr<Style> style = util::make_unique<Style>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700256 if (pb_style.has_parent()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700257 style->parent = Reference();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700258 if (!DeserializeReferenceFromPb(pb_style.parent(),
Adam Lesinskib54ef102016-10-21 13:38:42 -0700259 &style->parent.value())) {
260 return {};
261 }
262
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700263 if (pb_style.has_parent_source()) {
264 Source parent_source;
265 DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_,
266 &parent_source);
267 style->parent.value().SetSource(std::move(parent_source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700268 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800269 }
270
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700271 for (const pb::Style_Entry& pb_entry : pb_style.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700272 Style::Entry entry;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700273 DeserializeItemCommon(pb_entry, &entry.key);
274 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700275 return {};
276 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800277
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700278 entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700279 if (!entry.value) {
280 return {};
281 }
282
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700283 DeserializeItemCommon(pb_entry, entry.value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700284 style->entries.push_back(std::move(entry));
285 }
286 value = std::move(style);
287
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700288 } else if (pb_compound_value.has_styleable()) {
289 const pb::Styleable& pb_styleable = pb_compound_value.styleable();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700290 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700291 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) {
292 Reference attr_ref;
293 DeserializeItemCommon(pb_entry, &attr_ref);
294 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
295 styleable->entries.push_back(std::move(attr_ref));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700296 }
297 value = std::move(styleable);
298
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700299 } else if (pb_compound_value.has_array()) {
300 const pb::Array& pb_array = pb_compound_value.array();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700301 std::unique_ptr<Array> array = util::make_unique<Array>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700302 for (const pb::Array_Entry& pb_entry : pb_array.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700303 std::unique_ptr<Item> item =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700304 DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700305 if (!item) {
306 return {};
307 }
308
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700309 DeserializeItemCommon(pb_entry, item.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700310 array->items.push_back(std::move(item));
311 }
312 value = std::move(array);
313
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700314 } else if (pb_compound_value.has_plural()) {
315 const pb::Plural& pb_plural = pb_compound_value.plural();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700316 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700317 for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) {
318 size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700319 plural->values[pluralIdx] =
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700320 DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700321 if (!plural->values[pluralIdx]) {
322 return {};
323 }
324
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700325 DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700326 }
327 value = std::move(plural);
328
329 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 diag_->Error(DiagMessage(source_) << "unknown compound value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700331 return {};
332 }
333 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700334 diag_->Error(DiagMessage(source_) << "unknown value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700335 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800336 }
337
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700338 CHECK(value) << "forgot to set value";
Adam Lesinski59e04c62016-02-04 15:59:23 -0800339
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700340 value->SetWeak(is_weak);
341 DeserializeItemCommon(pb_value, value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700342 return value;
343 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800344
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700345 bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700346 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
347 out_ref->private_reference = pb_ref.private_();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800348
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700349 if (pb_ref.has_id()) {
350 out_ref->id = ResourceId(pb_ref.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800351 }
352
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700353 if (pb_ref.has_symbol_idx()) {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700354 const std::string str_symbol = util::GetString(*symbol_pool_, pb_ref.symbol_idx());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 ResourceNameRef name_ref;
356 if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700357 diag_->Error(DiagMessage(source_) << "invalid reference name '" << str_symbol << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700358 return false;
359 }
360
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700361 out_ref->name = name_ref.ToResourceName();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700362 }
363 return true;
364 }
365
366 template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700367 void DeserializeItemCommon(const T& pb_item, Value* out_value) {
368 if (pb_item.has_source()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700369 Source source;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700370 DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
371 out_value->SetSource(std::move(source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700372 }
373
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700374 if (pb_item.has_comment()) {
375 out_value->SetComment(pb_item.comment());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700376 }
377 }
378
379 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700380 const android::ResStringPool* value_pool_;
381 const android::ResStringPool* source_pool_;
382 const android::ResStringPool* symbol_pool_;
383 const Source source_;
384 IDiagnostics* diag_;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800385};
386
Adam Lesinskib54ef102016-10-21 13:38:42 -0700387} // namespace
Adam Lesinski59e04c62016-02-04 15:59:23 -0800388
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700389std::unique_ptr<ResourceTable> DeserializeTableFromPb(
390 const pb::ResourceTable& pb_table, const Source& source,
Adam Lesinskib54ef102016-10-21 13:38:42 -0700391 IDiagnostics* diag) {
392 // We import the android namespace because on Windows NO_ERROR is a macro, not
393 // an enum, which
394 // causes errors when qualifying it with android::
395 using namespace android;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700396
Adam Lesinskib54ef102016-10-21 13:38:42 -0700397 std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800398
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700399 if (!pb_table.has_string_pool()) {
400 diag->Error(DiagMessage(source) << "no string pool found");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700401 return {};
402 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800403
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700404 ResStringPool value_pool;
405 status_t result = value_pool.setTo(pb_table.string_pool().data().data(),
406 pb_table.string_pool().data().size());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700407 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700408 diag->Error(DiagMessage(source) << "invalid string pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700409 return {};
410 }
411
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700412 ResStringPool source_pool;
413 if (pb_table.has_source_pool()) {
414 result = source_pool.setTo(pb_table.source_pool().data().data(),
415 pb_table.source_pool().data().size());
Adam Lesinski803c7c82016-04-06 16:09:43 -0700416 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700417 diag->Error(DiagMessage(source) << "invalid source pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700418 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800419 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700420 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800421
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700422 ResStringPool symbol_pool;
423 if (pb_table.has_symbol_pool()) {
424 result = symbol_pool.setTo(pb_table.symbol_pool().data().data(),
425 pb_table.symbol_pool().data().size());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700426 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700427 diag->Error(DiagMessage(source) << "invalid symbol pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700428 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800429 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700430 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800431
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700432 PackagePbDeserializer package_pb_deserializer(&value_pool, &source_pool,
433 &symbol_pool, source, diag);
434 for (const pb::Package& pb_package : pb_table.packages()) {
435 if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700436 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800437 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700438 }
439 return table;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800440}
441
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700442std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
443 const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700444 std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800445
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700446 ResourceNameRef name_ref;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800447
Adam Lesinskib54ef102016-10-21 13:38:42 -0700448 // Need to create an lvalue here so that nameRef can point to something real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700449 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
450 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700451 << "invalid resource name in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700452 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700453 return {};
454 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700455 file->name = name_ref.ToResourceName();
456 file->source.path = pb_file.source_path();
457 DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700458
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700459 for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700460 // Need to create an lvalue here so that nameRef can point to something
461 // real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700462 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(),
463 &name_ref)) {
464 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700465 << "invalid resource name for exported symbol in "
466 "compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700467 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700468 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800469 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700470 file->exported_symbols.push_back(
471 SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()});
Adam Lesinskib54ef102016-10-21 13:38:42 -0700472 }
473 return file;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800474}
475
Adam Lesinskib54ef102016-10-21 13:38:42 -0700476} // namespace aapt