#ifndef TOOLS_JSON_SCHEMA_COMPILER_MANIFEST_PARSE_UTIL_H_
#define TOOLS_JSON_SCHEMA_COMPILER_MANIFEST_PARSE_UTIL_H_
#include <string>
#include <vector>
#include "base/check.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_piece_forward.h"
#include "base/values.h"
#include "tools/json_schema_compiler/util.h"
namespace json_schema_compiler {
namespace manifest_parse_util {
void PopulateInvalidEnumValueError(
base::StringPiece key,
base::StringPiece value,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
std::u16string GetArrayParseError(size_t error_index,
const std::u16string& item_error);
void PopulateFinalError(std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
const base::Value* FindKeyOfType(
const base::Value::Dict& dict,
base::StringPiece key,
base::Value::Type expected_type,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
int& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
bool& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
double& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
std::string& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
std::vector<T>& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
std::unique_ptr<T>& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
absl::optional<T>& out_opt,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed);
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
T& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
return T::ParseFromDictionary(dict, key, out, error, error_path_reversed);
}
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
std::vector<T>& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
const base::Value* value = FindKeyOfType(dict, key, base::Value::Type::LIST,
error, error_path_reversed);
if (!value)
return false;
bool result = json_schema_compiler::util::PopulateArrayFromList(
value->GetList(), out, error);
if (!result) {
DCHECK(error_path_reversed.empty());
error_path_reversed.push_back(key);
}
return result;
}
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
std::unique_ptr<T>& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
if (!dict.Find(key))
return true;
auto result = std::make_unique<T>();
if (!ParseFromDictionary(dict, key, *result, error, error_path_reversed)) {
return false;
}
out = std::move(result);
return true;
}
template <typename T>
bool ParseFromDictionary(const base::Value::Dict& dict,
base::StringPiece key,
absl::optional<T>& out_opt,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
if (!dict.Find(key))
return true;
T result{};
if (!ParseFromDictionary(dict, key, result, error, error_path_reversed)) {
return false;
}
out_opt = std::move(result);
return true;
}
template <typename T>
using StringToEnumConverter = T (*)(base::StringPiece);
template <typename T>
bool ParseEnumFromDictionary(
const base::Value::Dict& dict,
base::StringPiece key,
StringToEnumConverter<T> converter,
bool is_optional_property,
T none_value,
T& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
DCHECK_EQ(none_value, out);
if (is_optional_property && !dict.Find(key))
return true;
const base::Value* value = FindKeyOfType(dict, key, base::Value::Type::STRING,
error, error_path_reversed);
if (!value)
return false;
const std::string& str = value->GetString();
T enum_value = converter(str);
if (enum_value == none_value) {
PopulateInvalidEnumValueError(key, str, error, error_path_reversed);
return false;
}
out = enum_value;
return true;
}
template <typename T>
bool ParseEnumArrayFromDictionary(
const base::Value::Dict& dict,
base::StringPiece key,
StringToEnumConverter<T> converter,
T none_value,
std::vector<T>& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
std::vector<std::string> str_array;
if (!ParseFromDictionary(dict, key, str_array, error, error_path_reversed)) {
return false;
}
std::vector<T> result;
result.reserve(str_array.size());
for (size_t i = 0; i < str_array.size(); ++i) {
T enum_value = converter(str_array[i]);
if (enum_value == none_value) {
std::u16string item_error;
PopulateInvalidEnumValueError(key, str_array[i], item_error,
error_path_reversed);
error = GetArrayParseError(i, item_error);
return false;
}
result.push_back(enum_value);
}
out = std::move(result);
return true;
}
template <typename T>
bool ParseEnumArrayFromDictionary(
const base::Value::Dict& dict,
base::StringPiece key,
StringToEnumConverter<T> converter,
T none_value,
absl::optional<std::vector<T>>& out,
std::u16string& error,
std::vector<base::StringPiece>& error_path_reversed) {
if (!dict.Find(key))
return true;
std::vector<T> result;
if (!ParseEnumArrayFromDictionary(dict, key, converter, none_value, result,
error, error_path_reversed)) {
return false;
}
out = std::move(result);
return true;
}
}
}
#endif