blob: e891954bc52358999900c5ad93990d4085f71102 [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 Lesinskice5e56e2016-10-21 17:56:45 -070064 bool DeserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070065 Maybe<uint8_t> id;
66 if (pbPackage.has_package_id()) {
67 id = static_cast<uint8_t>(pbPackage.package_id());
Adam Lesinski59e04c62016-02-04 15:59:23 -080068 }
69
Adam Lesinskib54ef102016-10-21 13:38:42 -070070 std::map<ResourceId, ResourceNameRef> idIndex;
Adam Lesinski59e04c62016-02-04 15:59:23 -080071
Adam Lesinski4488f1c2017-05-26 17:33:38 -070072 ResourceTablePackage* pkg = table->CreatePackage(pbPackage.package_name(), id);
Adam Lesinskib54ef102016-10-21 13:38:42 -070073 for (const pb::Type& pbType : pbPackage.types()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070074 const ResourceType* resType = ParseResourceType(pbType.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070075 if (!resType) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -070076 diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -070077 return {};
78 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080079
Adam Lesinskice5e56e2016-10-21 17:56:45 -070080 ResourceTableType* type = pkg->FindOrCreateType(*resType);
Adam Lesinskib54ef102016-10-21 13:38:42 -070081
82 for (const pb::Entry& pbEntry : pbType.entries()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070083 ResourceEntry* entry = type->FindOrCreateEntry(pbEntry.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 Lesinskib54ef102016-10-21 13:38:42 -070086 if (pbEntry.has_symbol_status()) {
87 const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
88 if (pbStatus.has_source()) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -070089 DeserializeSourceFromPb(pbStatus.source(), *source_pool_, &entry->symbol_status.source);
Adam Lesinskib54ef102016-10-21 13:38:42 -070090 }
91
92 if (pbStatus.has_comment()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -070093 entry->symbol_status.comment = pbStatus.comment();
Adam Lesinskib54ef102016-10-21 13:38:42 -070094 }
95
Adam Lesinski4488f1c2017-05-26 17:33:38 -070096 entry->symbol_status.allow_new = pbStatus.allow_new();
97
98 SymbolState visibility = DeserializeVisibilityFromPb(pbStatus.visibility());
Adam Lesinskice5e56e2016-10-21 17:56:45 -070099 entry->symbol_status.state = visibility;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700100
101 if (visibility == SymbolState::kPublic) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700102 // This is a public symbol, we must encode the ID now if there is one.
Adam Lesinskib54ef102016-10-21 13:38:42 -0700103 if (pbEntry.has_id()) {
104 entry->id = static_cast<uint16_t>(pbEntry.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800105 }
106
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700107 if (type->symbol_status.state != SymbolState::kPublic) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700108 // If the type has not been made public, do so now.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700109 type->symbol_status.state = SymbolState::kPublic;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700110 if (pbType.has_id()) {
111 type->id = static_cast<uint8_t>(pbType.id());
112 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800113 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700114 } else if (visibility == SymbolState::kPrivate) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700115 if (type->symbol_status.state == SymbolState::kUndefined) {
116 type->symbol_status.state = SymbolState::kPrivate;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700117 }
118 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800119 }
120
Adam Lesinskib54ef102016-10-21 13:38:42 -0700121 ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700122 if (resId.is_valid()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700123 idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
124 }
125
126 for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
127 const pb::ConfigDescription& pbConfig = pbConfigValue.config();
128
129 ConfigDescription config;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700130 if (!DeserializeConfigDescriptionFromPb(pbConfig, &config)) {
131 diag_->Error(DiagMessage(source_) << "invalid configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700132 return {};
133 }
134
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700135 ResourceConfigValue* configValue = entry->FindOrCreateValue(config, pbConfig.product());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700136 if (configValue->value) {
137 // Duplicate config.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700138 diag_->Error(DiagMessage(source_) << "duplicate configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700139 return {};
140 }
141
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700142 configValue->value =
143 DeserializeValueFromPb(pbConfigValue.value(), config, &table->string_pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700144 if (!configValue->value) {
145 return {};
146 }
147 }
148 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800149 }
150
Adam Lesinskib54ef102016-10-21 13:38:42 -0700151 ReferenceIdToNameVisitor visitor(&idIndex);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700152 VisitAllValuesInPackage(pkg, &visitor);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700153 return true;
154 }
155
156 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700157 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
Adam Lesinski08535002017-08-04 16:15:17 -0700158 const ConfigDescription& config, StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700159 if (pb_item.has_ref()) {
160 const pb::Reference& pb_ref = pb_item.ref();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700161 std::unique_ptr<Reference> ref = util::make_unique<Reference>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700162 if (!DeserializeReferenceFromPb(pb_ref, ref.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700163 return {};
164 }
165 return std::move(ref);
166
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700167 } else if (pb_item.has_prim()) {
168 const pb::Primitive& pb_prim = pb_item.prim();
Adam Lesinski08535002017-08-04 16:15:17 -0700169 return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
170 pb_prim.data());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700171
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700172 } else if (pb_item.has_id()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700173 return util::make_unique<Id>();
174
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700175 } else if (pb_item.has_str()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700176 return util::make_unique<String>(
Adam Lesinski08535002017-08-04 16:15:17 -0700177 pool->MakeRef(pb_item.str().value(), StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700178
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700179 } else if (pb_item.has_raw_str()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700180 return util::make_unique<RawString>(
Adam Lesinski08535002017-08-04 16:15:17 -0700181 pool->MakeRef(pb_item.raw_str().value(), StringPool::Context(config)));
182
183 } else if (pb_item.has_styled_str()) {
184 const pb::StyledString& pb_str = pb_item.styled_str();
185 StyleString style_str{pb_str.value()};
186 for (const pb::StyledString::Span& pb_span : pb_str.span()) {
187 style_str.spans.push_back(Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()});
188 }
189 return util::make_unique<StyledString>(pool->MakeRef(
190 style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700191
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700192 } else if (pb_item.has_file()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 return util::make_unique<FileReference>(pool->MakeRef(
Adam Lesinski08535002017-08-04 16:15:17 -0700194 pb_item.file().path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700195
196 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700197 diag_->Error(DiagMessage(source_) << "unknown item");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700198 }
199 return {};
200 }
201
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700202 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
Adam Lesinski59e04c62016-02-04 15:59:23 -0800203 const ConfigDescription& config,
204 StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700205 const bool is_weak = pb_value.has_weak() ? pb_value.weak() : false;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800206
Adam Lesinskib54ef102016-10-21 13:38:42 -0700207 std::unique_ptr<Value> value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700208 if (pb_value.has_item()) {
209 value = DeserializeItemFromPb(pb_value.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700210 if (!value) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800211 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700212 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800213
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700214 } else if (pb_value.has_compound_value()) {
215 const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
216 if (pb_compound_value.has_attr()) {
217 const pb::Attribute& pb_attr = pb_compound_value.attr();
218 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(is_weak);
219 attr->type_mask = pb_attr.format_flags();
220 attr->min_int = pb_attr.min_int();
221 attr->max_int = pb_attr.max_int();
222 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700223 Attribute::Symbol symbol;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700224 DeserializeItemCommon(pb_symbol, &symbol.symbol);
225 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800226 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700227 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700228 symbol.value = pb_symbol.value();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700229 attr->symbols.push_back(std::move(symbol));
230 }
231 value = std::move(attr);
232
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700233 } else if (pb_compound_value.has_style()) {
234 const pb::Style& pb_style = pb_compound_value.style();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700235 std::unique_ptr<Style> style = util::make_unique<Style>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700236 if (pb_style.has_parent()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700237 style->parent = Reference();
Adam Lesinski08535002017-08-04 16:15:17 -0700238 if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700239 return {};
240 }
241
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700242 if (pb_style.has_parent_source()) {
243 Source parent_source;
Adam Lesinski08535002017-08-04 16:15:17 -0700244 DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_, &parent_source);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700245 style->parent.value().SetSource(std::move(parent_source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700246 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800247 }
248
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700249 for (const pb::Style_Entry& pb_entry : pb_style.entries()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700250 Style::Entry entry;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700251 DeserializeItemCommon(pb_entry, &entry.key);
252 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700253 return {};
254 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800255
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700256 entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700257 if (!entry.value) {
258 return {};
259 }
260
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700261 DeserializeItemCommon(pb_entry, entry.value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700262 style->entries.push_back(std::move(entry));
263 }
264 value = std::move(style);
265
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700266 } else if (pb_compound_value.has_styleable()) {
267 const pb::Styleable& pb_styleable = pb_compound_value.styleable();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700268 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700269 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entries()) {
270 Reference attr_ref;
271 DeserializeItemCommon(pb_entry, &attr_ref);
272 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
273 styleable->entries.push_back(std::move(attr_ref));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700274 }
275 value = std::move(styleable);
276
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700277 } else if (pb_compound_value.has_array()) {
278 const pb::Array& pb_array = pb_compound_value.array();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700279 std::unique_ptr<Array> array = util::make_unique<Array>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700280 for (const pb::Array_Entry& pb_entry : pb_array.entries()) {
Adam Lesinski08535002017-08-04 16:15:17 -0700281 std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700282 if (!item) {
283 return {};
284 }
285
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700286 DeserializeItemCommon(pb_entry, item.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700287 array->items.push_back(std::move(item));
288 }
289 value = std::move(array);
290
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700291 } else if (pb_compound_value.has_plural()) {
292 const pb::Plural& pb_plural = pb_compound_value.plural();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700293 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700294 for (const pb::Plural_Entry& pb_entry : pb_plural.entries()) {
295 size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
Adam Lesinski08535002017-08-04 16:15:17 -0700296 plural->values[pluralIdx] = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700297 if (!plural->values[pluralIdx]) {
298 return {};
299 }
300
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700301 DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700302 }
303 value = std::move(plural);
304
305 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700306 diag_->Error(DiagMessage(source_) << "unknown compound value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700307 return {};
308 }
309 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700310 diag_->Error(DiagMessage(source_) << "unknown value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700311 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800312 }
313
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700314 CHECK(value) << "forgot to set value";
Adam Lesinski59e04c62016-02-04 15:59:23 -0800315
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700316 value->SetWeak(is_weak);
317 DeserializeItemCommon(pb_value, value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700318 return value;
319 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800320
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700321 bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700322 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
323 out_ref->private_reference = pb_ref.private_();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800324
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700325 if (pb_ref.has_id()) {
326 out_ref->id = ResourceId(pb_ref.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800327 }
328
Adam Lesinski08535002017-08-04 16:15:17 -0700329 if (pb_ref.has_name()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700330 ResourceNameRef name_ref;
Adam Lesinski08535002017-08-04 16:15:17 -0700331 if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) {
332 diag_->Error(DiagMessage(source_) << "invalid reference name '" << pb_ref.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700333 return false;
334 }
335
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700336 out_ref->name = name_ref.ToResourceName();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700337 }
338 return true;
339 }
340
341 template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700342 void DeserializeItemCommon(const T& pb_item, Value* out_value) {
343 if (pb_item.has_source()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700344 Source source;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700345 DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
346 out_value->SetSource(std::move(source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700347 }
348
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700349 if (pb_item.has_comment()) {
350 out_value->SetComment(pb_item.comment());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700351 }
352 }
353
354 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 const android::ResStringPool* source_pool_;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700356 const Source source_;
357 IDiagnostics* diag_;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800358};
359
Adam Lesinskib54ef102016-10-21 13:38:42 -0700360} // namespace
Adam Lesinski59e04c62016-02-04 15:59:23 -0800361
Adam Lesinski08535002017-08-04 16:15:17 -0700362std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& pb_table,
363 const Source& source, IDiagnostics* diag) {
364 // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
Adam Lesinskib54ef102016-10-21 13:38:42 -0700365 // causes errors when qualifying it with android::
366 using namespace android;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700367
Adam Lesinskib54ef102016-10-21 13:38:42 -0700368 std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800369
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700370 ResStringPool source_pool;
371 if (pb_table.has_source_pool()) {
Adam Lesinski08535002017-08-04 16:15:17 -0700372 status_t result = source_pool.setTo(pb_table.source_pool().data().data(),
373 pb_table.source_pool().data().size());
Adam Lesinski803c7c82016-04-06 16:09:43 -0700374 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700375 diag->Error(DiagMessage(source) << "invalid source pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700376 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800377 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700378 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800379
Adam Lesinski08535002017-08-04 16:15:17 -0700380 PackagePbDeserializer package_pb_deserializer(&source_pool, source, diag);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700381 for (const pb::Package& pb_package : pb_table.packages()) {
382 if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700383 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800384 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700385 }
386 return table;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800387}
388
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700389std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
390 const pb::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700391 std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800392
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700393 ResourceNameRef name_ref;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800394
Adam Lesinskib54ef102016-10-21 13:38:42 -0700395 // Need to create an lvalue here so that nameRef can point to something real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700396 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
397 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700398 << "invalid resource name in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700399 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700400 return {};
401 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700402 file->name = name_ref.ToResourceName();
403 file->source.path = pb_file.source_path();
404 DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700405
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700406 for (const pb::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbols()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700407 // Need to create an lvalue here so that nameRef can point to something
408 // real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700409 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(),
410 &name_ref)) {
411 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700412 << "invalid resource name for exported symbol in "
413 "compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700414 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700415 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800416 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700417 file->exported_symbols.push_back(
418 SourcedResourceName{name_ref.ToResourceName(), pb_symbol.line_no()});
Adam Lesinskib54ef102016-10-21 13:38:42 -0700419 }
420 return file;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800421}
422
Adam Lesinskib54ef102016-10-21 13:38:42 -0700423} // namespace aapt