blob: 2dca7dbae6f384918c94bc92148b06758b55117d [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "src/lib/cmx/program.h"
#include <algorithm>
#include "rapidjson/document.h"
#include "src/lib/json_parser/json_parser.h"
namespace component {
constexpr char kBinary[] = "binary";
constexpr char kArgs[] = "args";
constexpr char kEnvVars[] = "env_vars";
constexpr char kData[] = "data";
void ProgramMetadata::Parse(const rapidjson::Value& program_value, json::JSONParser* json_parser) {
binary_.clear();
args_.clear();
data_.clear();
binary_null_ = true;
data_null_ = true;
unknown_attributes_ = {};
if (!program_value.IsObject()) {
json_parser->ReportError("Program is not an object.");
return;
}
const bool parsed_binary = ParseBinary(program_value, json_parser);
const bool parsed_data = ParseData(program_value, json_parser);
if (!parsed_binary && !parsed_data) {
json_parser->ReportError("Both 'binary' and 'data' in program are missing.");
return;
}
const auto args = program_value.FindMember(kArgs);
if (args != program_value.MemberEnd()) {
json_parser->CopyStringArray("args", args->value, &args_);
args_null_ = false;
}
for (const auto& member : program_value.GetObject()) {
if (IsWellKnownAttributeName(member.name.GetString())) {
continue;
}
if (!member.value.IsString()) {
json_parser->ReportError("Extra attributes in 'program' must have string values.");
return;
}
unknown_attributes_.push_back({member.name.GetString(), member.value.GetString()});
}
}
bool ProgramMetadata::ParseBinary(const rapidjson::Value& program_value,
json::JSONParser* json_parser) {
const auto binary = program_value.FindMember(kBinary);
if (binary == program_value.MemberEnd()) {
return false;
}
if (!binary->value.IsString()) {
json_parser->ReportError("'binary' in program is not a string.");
return false;
}
binary_ = binary->value.GetString();
binary_null_ = false;
const auto env_vars = program_value.FindMember(kEnvVars);
if (env_vars != program_value.MemberEnd()) {
json_parser->CopyStringArray("env_vars", env_vars->value, &env_vars_);
env_vars_null_ = false;
}
return !json_parser->HasError();
}
bool ProgramMetadata::ParseData(const rapidjson::Value& program_value,
json::JSONParser* json_parser) {
const auto data = program_value.FindMember(kData);
if (data == program_value.MemberEnd()) {
return false;
}
if (!data->value.IsString()) {
json_parser->ReportError("'data' in program is not a string.");
return false;
}
data_ = data->value.GetString();
data_null_ = false;
return true;
}
bool ProgramMetadata::IsWellKnownAttributeName(std::string_view name) const {
return name == kData || name == kBinary || name == kArgs || name == kEnvVars;
}
} // namespace component