blob: b9d5878f2f71503a0a6f8bcf625ecd02e0eefc74 [file] [log] [blame]
Adam Lesinski59e04c62016-02-04 15:59:23 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Adam Lesinskice5e56e2016-10-21 17:56:45 -070017#include "proto/ProtoSerialize.h"
18
19#include "android-base/logging.h"
20#include "androidfw/ResourceTypes.h"
21
Adam Lesinski59e04c62016-02-04 15:59:23 -080022#include "ResourceTable.h"
23#include "ResourceUtils.h"
24#include "ValueVisitor.h"
25#include "proto/ProtoHelpers.h"
Adam Lesinski59e04c62016-02-04 15:59:23 -080026
27namespace aapt {
28
29namespace {
30
31class ReferenceIdToNameVisitor : public ValueVisitor {
Adam Lesinskib54ef102016-10-21 13:38:42 -070032 public:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070033 using ValueVisitor::Visit;
Adam Lesinski59e04c62016-02-04 15:59:23 -080034
Adam Lesinski4488f1c2017-05-26 17:33:38 -070035 explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping)
Adam Lesinskice5e56e2016-10-21 17:56:45 -070036 : mapping_(mapping) {
37 CHECK(mapping_ != nullptr);
Adam Lesinskib54ef102016-10-21 13:38:42 -070038 }
39
Adam Lesinskice5e56e2016-10-21 17:56:45 -070040 void Visit(Reference* reference) override {
41 if (!reference->id || !reference->id.value().is_valid()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070042 return;
Adam Lesinski59e04c62016-02-04 15:59:23 -080043 }
44
Adam Lesinskib54ef102016-10-21 13:38:42 -070045 ResourceId id = reference->id.value();
Adam Lesinskice5e56e2016-10-21 17:56:45 -070046 auto cache_iter = mapping_->find(id);
47 if (cache_iter != mapping_->end()) {
48 reference->name = cache_iter->second.ToResourceName();
Adam Lesinski59e04c62016-02-04 15:59:23 -080049 }
Adam Lesinskib54ef102016-10-21 13:38:42 -070050 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080051
Adam Lesinskib54ef102016-10-21 13:38:42 -070052 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -070053 const std::map<ResourceId, ResourceNameRef>* mapping_;
Adam Lesinski59e04c62016-02-04 15:59:23 -080054};
55
56class PackagePbDeserializer {
Adam Lesinskib54ef102016-10-21 13:38:42 -070057 public:
Adam Lesinski08535002017-08-04 16:15:17 -070058 PackagePbDeserializer(const android::ResStringPool* sourcePool, const Source& source,
59 IDiagnostics* diag)
60 : source_pool_(sourcePool), source_(source), diag_(diag) {
61 }
Adam Lesinskib54ef102016-10-21 13:38:42 -070062
63 public:
Adam Lesinski4ffea042017-08-10 15:37:28 -070064 bool DeserializeFromPb(const pb::Package& pb_package, ResourceTable* table) {
Adam Lesinskib54ef102016-10-21 13:38:42 -070065 Maybe<uint8_t> id;
Adam Lesinski4ffea042017-08-10 15:37:28 -070066 if (pb_package.has_package_id()) {
67 id = static_cast<uint8_t>(pb_package.package_id());
Adam Lesinski59e04c62016-02-04 15:59:23 -080068 }
69
Adam Lesinski4ffea042017-08-10 15:37:28 -070070 std::map<ResourceId, ResourceNameRef> id_index;
Adam Lesinski59e04c62016-02-04 15:59:23 -080071
Adam Lesinski4ffea042017-08-10 15:37:28 -070072 ResourceTablePackage* pkg = table->CreatePackage(pb_package.package_name(), id);
73 for (const pb::Type& pb_type : pb_package.type()) {
74 const ResourceType* res_type = ParseResourceType(pb_type.name());
75 if (res_type == nullptr) {
76 diag_->Error(DiagMessage(source_) << "unknown type '" << pb_type.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -070077 return {};
78 }
Adam Lesinski59e04c62016-02-04 15:59:23 -080079
Adam Lesinski4ffea042017-08-10 15:37:28 -070080 ResourceTableType* type = pkg->FindOrCreateType(*res_type);
Adam Lesinskib54ef102016-10-21 13:38:42 -070081
Adam Lesinski4ffea042017-08-10 15:37:28 -070082 for (const pb::Entry& pb_entry : pb_type.entry()) {
83 ResourceEntry* entry = type->FindOrCreateEntry(pb_entry.name());
Adam Lesinskib54ef102016-10-21 13:38:42 -070084
Adam Lesinski08535002017-08-04 16:15:17 -070085 // Deserialize the symbol status (public/private with source and comments).
Adam Lesinski4ffea042017-08-10 15:37:28 -070086 if (pb_entry.has_symbol_status()) {
87 const pb::SymbolStatus& pb_status = pb_entry.symbol_status();
88 if (pb_status.has_source()) {
89 DeserializeSourceFromPb(pb_status.source(), *source_pool_,
90 &entry->symbol_status.source);
Adam Lesinskib54ef102016-10-21 13:38:42 -070091 }
92
Adam Lesinski4ffea042017-08-10 15:37:28 -070093 if (pb_status.has_comment()) {
94 entry->symbol_status.comment = pb_status.comment();
Adam Lesinskib54ef102016-10-21 13:38:42 -070095 }
96
Adam Lesinski4ffea042017-08-10 15:37:28 -070097 entry->symbol_status.allow_new = pb_status.allow_new();
Adam Lesinski4488f1c2017-05-26 17:33:38 -070098
Adam Lesinski4ffea042017-08-10 15:37:28 -070099 SymbolState visibility = DeserializeVisibilityFromPb(pb_status.visibility());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700100 entry->symbol_status.state = visibility;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700101
102 if (visibility == SymbolState::kPublic) {
Adam Lesinski4488f1c2017-05-26 17:33:38 -0700103 // This is a public symbol, we must encode the ID now if there is one.
Adam Lesinski4ffea042017-08-10 15:37:28 -0700104 if (pb_entry.has_id()) {
105 entry->id = static_cast<uint16_t>(pb_entry.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800106 }
107
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700108 if (type->symbol_status.state != SymbolState::kPublic) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700109 // If the type has not been made public, do so now.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700110 type->symbol_status.state = SymbolState::kPublic;
Adam Lesinski4ffea042017-08-10 15:37:28 -0700111 if (pb_type.has_id()) {
112 type->id = static_cast<uint8_t>(pb_type.id());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700113 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800114 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700115 } else if (visibility == SymbolState::kPrivate) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700116 if (type->symbol_status.state == SymbolState::kUndefined) {
117 type->symbol_status.state = SymbolState::kPrivate;
Adam Lesinskib54ef102016-10-21 13:38:42 -0700118 }
119 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800120 }
121
Adam Lesinski4ffea042017-08-10 15:37:28 -0700122 ResourceId resid(pb_package.package_id(), pb_type.id(), pb_entry.id());
123 if (resid.is_valid()) {
124 id_index[resid] = ResourceNameRef(pkg->name, type->type, entry->name);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700125 }
126
Adam Lesinski4ffea042017-08-10 15:37:28 -0700127 for (const pb::ConfigValue& pb_config_value : pb_entry.config_value()) {
128 const pb::ConfigDescription& pb_config = pb_config_value.config();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700129
130 ConfigDescription config;
Adam Lesinski4ffea042017-08-10 15:37:28 -0700131 if (!DeserializeConfigDescriptionFromPb(pb_config, &config)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700132 diag_->Error(DiagMessage(source_) << "invalid configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700133 return {};
134 }
135
Adam Lesinski4ffea042017-08-10 15:37:28 -0700136 ResourceConfigValue* config_value = entry->FindOrCreateValue(config, pb_config.product());
137 if (config_value->value) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700138 // Duplicate config.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700139 diag_->Error(DiagMessage(source_) << "duplicate configuration");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700140 return {};
141 }
142
Adam Lesinski4ffea042017-08-10 15:37:28 -0700143 config_value->value =
144 DeserializeValueFromPb(pb_config_value.value(), config, &table->string_pool);
145 if (!config_value->value) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700146 return {};
147 }
148 }
149 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800150 }
151
Adam Lesinski4ffea042017-08-10 15:37:28 -0700152 ReferenceIdToNameVisitor visitor(&id_index);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700153 VisitAllValuesInPackage(pkg, &visitor);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700154 return true;
155 }
156
157 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700158 std::unique_ptr<Item> DeserializeItemFromPb(const pb::Item& pb_item,
Adam Lesinski08535002017-08-04 16:15:17 -0700159 const ConfigDescription& config, StringPool* pool) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700160 if (pb_item.has_ref()) {
161 const pb::Reference& pb_ref = pb_item.ref();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700162 std::unique_ptr<Reference> ref = util::make_unique<Reference>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700163 if (!DeserializeReferenceFromPb(pb_ref, ref.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700164 return {};
165 }
166 return std::move(ref);
167
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700168 } else if (pb_item.has_prim()) {
169 const pb::Primitive& pb_prim = pb_item.prim();
Adam Lesinski08535002017-08-04 16:15:17 -0700170 return util::make_unique<BinaryPrimitive>(static_cast<uint8_t>(pb_prim.type()),
171 pb_prim.data());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700172
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700173 } else if (pb_item.has_id()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700174 return util::make_unique<Id>();
175
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700176 } else if (pb_item.has_str()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700177 return util::make_unique<String>(
Adam Lesinski08535002017-08-04 16:15:17 -0700178 pool->MakeRef(pb_item.str().value(), StringPool::Context(config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700179
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700180 } else if (pb_item.has_raw_str()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700181 return util::make_unique<RawString>(
Adam Lesinski08535002017-08-04 16:15:17 -0700182 pool->MakeRef(pb_item.raw_str().value(), StringPool::Context(config)));
183
184 } else if (pb_item.has_styled_str()) {
185 const pb::StyledString& pb_str = pb_item.styled_str();
186 StyleString style_str{pb_str.value()};
187 for (const pb::StyledString::Span& pb_span : pb_str.span()) {
188 style_str.spans.push_back(Span{pb_span.tag(), pb_span.first_char(), pb_span.last_char()});
189 }
190 return util::make_unique<StyledString>(pool->MakeRef(
191 style_str, StringPool::Context(StringPool::Context::kNormalPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700192
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700193 } else if (pb_item.has_file()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700194 return util::make_unique<FileReference>(pool->MakeRef(
Adam Lesinski08535002017-08-04 16:15:17 -0700195 pb_item.file().path(), StringPool::Context(StringPool::Context::kHighPriority, config)));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700196
197 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700198 diag_->Error(DiagMessage(source_) << "unknown item");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700199 }
200 return {};
201 }
202
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700203 std::unique_ptr<Value> DeserializeValueFromPb(const pb::Value& pb_value,
Adam Lesinski59e04c62016-02-04 15:59:23 -0800204 const ConfigDescription& config,
205 StringPool* pool) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700206 std::unique_ptr<Value> value;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700207 if (pb_value.has_item()) {
208 value = DeserializeItemFromPb(pb_value.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700209 if (!value) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800210 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700211 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800212
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700213 } else if (pb_value.has_compound_value()) {
214 const pb::CompoundValue& pb_compound_value = pb_value.compound_value();
215 if (pb_compound_value.has_attr()) {
216 const pb::Attribute& pb_attr = pb_compound_value.attr();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700217 std::unique_ptr<Attribute> attr = util::make_unique<Attribute>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700218 attr->type_mask = pb_attr.format_flags();
219 attr->min_int = pb_attr.min_int();
220 attr->max_int = pb_attr.max_int();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700221 for (const pb::Attribute_Symbol& pb_symbol : pb_attr.symbol()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700222 Attribute::Symbol symbol;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700223 DeserializeItemCommon(pb_symbol, &symbol.symbol);
224 if (!DeserializeReferenceFromPb(pb_symbol.name(), &symbol.symbol)) {
Adam Lesinski59e04c62016-02-04 15:59:23 -0800225 return {};
Adam Lesinskib54ef102016-10-21 13:38:42 -0700226 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700227 symbol.value = pb_symbol.value();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700228 attr->symbols.push_back(std::move(symbol));
229 }
230 value = std::move(attr);
231
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700232 } else if (pb_compound_value.has_style()) {
233 const pb::Style& pb_style = pb_compound_value.style();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700234 std::unique_ptr<Style> style = util::make_unique<Style>();
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700235 if (pb_style.has_parent()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700236 style->parent = Reference();
Adam Lesinski08535002017-08-04 16:15:17 -0700237 if (!DeserializeReferenceFromPb(pb_style.parent(), &style->parent.value())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700238 return {};
239 }
240
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700241 if (pb_style.has_parent_source()) {
242 Source parent_source;
Adam Lesinski08535002017-08-04 16:15:17 -0700243 DeserializeSourceFromPb(pb_style.parent_source(), *source_pool_, &parent_source);
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700244 style->parent.value().SetSource(std::move(parent_source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700245 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800246 }
247
Adam Lesinski4ffea042017-08-10 15:37:28 -0700248 for (const pb::Style_Entry& pb_entry : pb_style.entry()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700249 Style::Entry entry;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700250 DeserializeItemCommon(pb_entry, &entry.key);
251 if (!DeserializeReferenceFromPb(pb_entry.key(), &entry.key)) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700252 return {};
253 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800254
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700255 entry.value = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700256 if (!entry.value) {
257 return {};
258 }
259
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700260 DeserializeItemCommon(pb_entry, entry.value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700261 style->entries.push_back(std::move(entry));
262 }
263 value = std::move(style);
264
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700265 } else if (pb_compound_value.has_styleable()) {
266 const pb::Styleable& pb_styleable = pb_compound_value.styleable();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700267 std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700268 for (const pb::Styleable_Entry& pb_entry : pb_styleable.entry()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700269 Reference attr_ref;
270 DeserializeItemCommon(pb_entry, &attr_ref);
271 DeserializeReferenceFromPb(pb_entry.attr(), &attr_ref);
272 styleable->entries.push_back(std::move(attr_ref));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700273 }
274 value = std::move(styleable);
275
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700276 } else if (pb_compound_value.has_array()) {
277 const pb::Array& pb_array = pb_compound_value.array();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700278 std::unique_ptr<Array> array = util::make_unique<Array>();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700279 for (const pb::Array_Element& pb_entry : pb_array.element()) {
Adam Lesinski08535002017-08-04 16:15:17 -0700280 std::unique_ptr<Item> item = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700281 if (!item) {
282 return {};
283 }
284
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700285 DeserializeItemCommon(pb_entry, item.get());
Adam Lesinski4ffea042017-08-10 15:37:28 -0700286 array->elements.push_back(std::move(item));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700287 }
288 value = std::move(array);
289
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700290 } else if (pb_compound_value.has_plural()) {
291 const pb::Plural& pb_plural = pb_compound_value.plural();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700292 std::unique_ptr<Plural> plural = util::make_unique<Plural>();
Adam Lesinski4ffea042017-08-10 15:37:28 -0700293 for (const pb::Plural_Entry& pb_entry : pb_plural.entry()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700294 size_t pluralIdx = DeserializePluralEnumFromPb(pb_entry.arity());
Adam Lesinski08535002017-08-04 16:15:17 -0700295 plural->values[pluralIdx] = DeserializeItemFromPb(pb_entry.item(), config, pool);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700296 if (!plural->values[pluralIdx]) {
297 return {};
298 }
299
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700300 DeserializeItemCommon(pb_entry, plural->values[pluralIdx].get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700301 }
302 value = std::move(plural);
303
304 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700305 diag_->Error(DiagMessage(source_) << "unknown compound value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700306 return {};
307 }
308 } else {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700309 diag_->Error(DiagMessage(source_) << "unknown value");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700310 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800311 }
312
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700313 CHECK(value) << "forgot to set value";
Adam Lesinski59e04c62016-02-04 15:59:23 -0800314
Adam Lesinski4ffea042017-08-10 15:37:28 -0700315 value->SetWeak(pb_value.weak());
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700316 DeserializeItemCommon(pb_value, value.get());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700317 return value;
318 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800319
Adam Lesinskibab4ef52017-06-01 15:22:57 -0700320 bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700321 out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
322 out_ref->private_reference = pb_ref.private_();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800323
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700324 if (pb_ref.has_id()) {
325 out_ref->id = ResourceId(pb_ref.id());
Adam Lesinski59e04c62016-02-04 15:59:23 -0800326 }
327
Adam Lesinski08535002017-08-04 16:15:17 -0700328 if (pb_ref.has_name()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700329 ResourceNameRef name_ref;
Adam Lesinski08535002017-08-04 16:15:17 -0700330 if (!ResourceUtils::ParseResourceName(pb_ref.name(), &name_ref, nullptr)) {
331 diag_->Error(DiagMessage(source_) << "invalid reference name '" << pb_ref.name() << "'");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700332 return false;
333 }
334
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700335 out_ref->name = name_ref.ToResourceName();
Adam Lesinskib54ef102016-10-21 13:38:42 -0700336 }
337 return true;
338 }
339
340 template <typename T>
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700341 void DeserializeItemCommon(const T& pb_item, Value* out_value) {
342 if (pb_item.has_source()) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700343 Source source;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700344 DeserializeSourceFromPb(pb_item.source(), *source_pool_, &source);
345 out_value->SetSource(std::move(source));
Adam Lesinskib54ef102016-10-21 13:38:42 -0700346 }
347
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700348 if (pb_item.has_comment()) {
349 out_value->SetComment(pb_item.comment());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700350 }
351 }
352
353 private:
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700354 const android::ResStringPool* source_pool_;
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700355 const Source source_;
356 IDiagnostics* diag_;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800357};
358
Adam Lesinskib54ef102016-10-21 13:38:42 -0700359} // namespace
Adam Lesinski59e04c62016-02-04 15:59:23 -0800360
Adam Lesinski08535002017-08-04 16:15:17 -0700361std::unique_ptr<ResourceTable> DeserializeTableFromPb(const pb::ResourceTable& pb_table,
362 const Source& source, IDiagnostics* diag) {
363 // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
Adam Lesinskib54ef102016-10-21 13:38:42 -0700364 // causes errors when qualifying it with android::
365 using namespace android;
Adam Lesinski803c7c82016-04-06 16:09:43 -0700366
Adam Lesinskib54ef102016-10-21 13:38:42 -0700367 std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800368
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700369 ResStringPool source_pool;
370 if (pb_table.has_source_pool()) {
Adam Lesinski08535002017-08-04 16:15:17 -0700371 status_t result = source_pool.setTo(pb_table.source_pool().data().data(),
372 pb_table.source_pool().data().size());
Adam Lesinski803c7c82016-04-06 16:09:43 -0700373 if (result != NO_ERROR) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700374 diag->Error(DiagMessage(source) << "invalid source pool");
Adam Lesinskib54ef102016-10-21 13:38:42 -0700375 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800376 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700377 }
Adam Lesinski59e04c62016-02-04 15:59:23 -0800378
Adam Lesinski08535002017-08-04 16:15:17 -0700379 PackagePbDeserializer package_pb_deserializer(&source_pool, source, diag);
Adam Lesinski4ffea042017-08-10 15:37:28 -0700380 for (const pb::Package& pb_package : pb_table.package()) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700381 if (!package_pb_deserializer.DeserializeFromPb(pb_package, table.get())) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700382 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800383 }
Adam Lesinskib54ef102016-10-21 13:38:42 -0700384 }
385 return table;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800386}
387
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700388std::unique_ptr<ResourceFile> DeserializeCompiledFileFromPb(
Adam Lesinski4ffea042017-08-10 15:37:28 -0700389 const pb::internal::CompiledFile& pb_file, const Source& source, IDiagnostics* diag) {
Adam Lesinskib54ef102016-10-21 13:38:42 -0700390 std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
Adam Lesinski59e04c62016-02-04 15:59:23 -0800391
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700392 ResourceNameRef name_ref;
Adam Lesinski59e04c62016-02-04 15:59:23 -0800393
Adam Lesinskib54ef102016-10-21 13:38:42 -0700394 // Need to create an lvalue here so that nameRef can point to something real.
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700395 if (!ResourceUtils::ParseResourceName(pb_file.resource_name(), &name_ref)) {
396 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700397 << "invalid resource name in compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700398 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700399 return {};
400 }
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700401 file->name = name_ref.ToResourceName();
402 file->source.path = pb_file.source_path();
403 DeserializeConfigDescriptionFromPb(pb_file.config(), &file->config);
Adam Lesinskib54ef102016-10-21 13:38:42 -0700404
Adam Lesinski4ffea042017-08-10 15:37:28 -0700405 for (const pb::internal::CompiledFile_Symbol& pb_symbol : pb_file.exported_symbol()) {
406 // Need to create an lvalue here so that nameRef can point to something real.
407 if (!ResourceUtils::ParseResourceName(pb_symbol.resource_name(), &name_ref)) {
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700408 diag->Error(DiagMessage(source)
Adam Lesinskib54ef102016-10-21 13:38:42 -0700409 << "invalid resource name for exported symbol in "
410 "compiled file header: "
Adam Lesinskice5e56e2016-10-21 17:56:45 -0700411 << pb_file.resource_name());
Adam Lesinskib54ef102016-10-21 13:38:42 -0700412 return {};
Adam Lesinski59e04c62016-02-04 15:59:23 -0800413 }
Adam Lesinski4ffea042017-08-10 15:37:28 -0700414 size_t line = 0u;
415 if (pb_symbol.has_source()) {
416 line = pb_symbol.source().line_number();
417 }
418 file->exported_symbols.push_back(SourcedResourceName{name_ref.ToResourceName(), line});
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