Skip to content

Commit

Permalink
Add "maybe" operations to JSON. (#1520)
Browse files Browse the repository at this point in the history
Extracted from #1514
  • Loading branch information
BillyONeal authored Oct 23, 2024
1 parent 76ca355 commit 829b20e
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 79 deletions.
8 changes: 8 additions & 0 deletions include/vcpkg/base/json.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,23 @@ namespace vcpkg::Json
int64_t integer(LineInfo li) const noexcept;
double number(LineInfo li) const noexcept;
StringView string(LineInfo li) const noexcept;
std::string* maybe_string() noexcept;
const std::string* maybe_string() const noexcept;

const Array& array(LineInfo li) const& noexcept;
Array& array(LineInfo li) & noexcept;
Array&& array(LineInfo li) && noexcept;

Array* maybe_array() noexcept;
const Array* maybe_array() const noexcept;

const Object& object(LineInfo li) const& noexcept;
Object& object(LineInfo li) & noexcept;
Object&& object(LineInfo li) && noexcept;

Object* maybe_object() noexcept;
const Object* maybe_object() const noexcept;

static Value null(std::nullptr_t) noexcept;
static Value boolean(bool) noexcept;
static Value integer(int64_t i) noexcept;
Expand Down
64 changes: 62 additions & 2 deletions src/vcpkg/base/json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,26 @@ namespace vcpkg::Json
return underlying_->string;
}

std::string* Value::maybe_string() noexcept
{
if (underlying_ && underlying_->tag == VK::String)
{
return &underlying_->string;
}

return nullptr;
}

const std::string* Value::maybe_string() const noexcept
{
if (underlying_ && underlying_->tag == VK::String)
{
return &underlying_->string;
}

return nullptr;
}

const Array& Value::array(LineInfo li) const& noexcept
{
vcpkg::Checks::msg_check_exit(li, is_array(), msgJsonValueNotArray);
Expand All @@ -169,6 +189,26 @@ namespace vcpkg::Json
}
Array&& Value::array(LineInfo li) && noexcept { return std::move(this->array(li)); }

Array* Value::maybe_array() noexcept
{
if (underlying_ && underlying_->tag == VK::Array)
{
return &underlying_->array;
}

return nullptr;
}

const Array* Value::maybe_array() const noexcept
{
if (underlying_ && underlying_->tag == VK::Array)
{
return &underlying_->array;
}

return nullptr;
}

const Object& Value::object(LineInfo li) const& noexcept
{
vcpkg::Checks::msg_check_exit(li, is_object(), msgJsonValueNotObject);
Expand All @@ -181,6 +221,26 @@ namespace vcpkg::Json
}
Object&& Value::object(LineInfo li) && noexcept { return std::move(this->object(li)); }

Object* Value::maybe_object() noexcept
{
if (underlying_ && underlying_->tag == VK::Object)
{
return &underlying_->object;
}

return nullptr;
}

const Object* Value::maybe_object() const noexcept
{
if (underlying_ && underlying_->tag == VK::Object)
{
return &underlying_->object;
}

return nullptr;
}

Value::Value() noexcept = default;
Value::Value(Value&&) noexcept = default;
Value& Value::operator=(Value&&) noexcept = default;
Expand Down Expand Up @@ -1120,9 +1180,9 @@ namespace vcpkg::Json
{
return parse(text, origin).then([&](ParsedJson&& mabeValueIsh) -> ExpectedL<Json::Object> {
auto& asValue = mabeValueIsh.value;
if (asValue.is_object())
if (auto as_object = asValue.maybe_object())
{
return std::move(asValue).object(VCPKG_LINE_INFO);
return std::move(*as_object);
}

return msg::format(msgJsonErrorMustBeAnObject, msg::path = origin);
Expand Down
8 changes: 5 additions & 3 deletions src/vcpkg/binarycaching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -812,10 +812,12 @@ namespace
auto maybe_json = Json::parse_object(*p, m_url);
if (auto json = maybe_json.get())
{
auto archive_location = json->get(JsonIdArchiveCapitalLocation);
if (archive_location && archive_location->is_string())
if (auto archive_location = json->get(JsonIdArchiveCapitalLocation))
{
return archive_location->string(VCPKG_LINE_INFO).to_string();
if (auto archive_location_string = archive_location->maybe_string())
{
return *archive_location_string;
}
}
}
}
Expand Down
13 changes: 6 additions & 7 deletions src/vcpkg/bundlesettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,17 @@ namespace

bool parse_optional_json_string(const Json::Object& doc, StringLiteral field_name, Optional<std::string>& output)
{
auto value = doc.get(field_name);
if (!value)
if (auto value = doc.get(field_name))
{
return true;
}
if (auto value_string = value->maybe_string())
{
output = *value_string;
return true;
}

if (!value->is_string())
{
return false;
}

output = value->string(VCPKG_LINE_INFO).to_string();
return true;
}
}
Expand Down
42 changes: 23 additions & 19 deletions src/vcpkg/commands.set-installed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,27 @@ namespace vcpkg
Optional<Json::Object> create_dependency_graph_snapshot(const VcpkgCmdArguments& args,
const ActionPlan& action_plan)
{
if (args.github_ref.has_value() && args.github_sha.has_value() && args.github_job.has_value() &&
args.github_workflow.has_value() && args.github_run_id.has_value())
const auto github_ref = args.github_ref.get();
const auto github_sha = args.github_sha.get();
const auto github_job = args.github_job.get();
const auto github_workflow = args.github_workflow.get();
const auto github_run_id = args.github_run_id.get();
if (github_ref && github_sha && github_job && github_workflow && github_run_id)
{
Json::Object detector;
detector.insert(JsonIdName, Json::Value::string("vcpkg"));
detector.insert(JsonIdUrl, Json::Value::string("https://github.com/microsoft/vcpkg"));
detector.insert(JsonIdVersion, Json::Value::string("1.0.0"));

Json::Object job;
job.insert(JsonIdId, Json::Value::string(*args.github_run_id.get()));
job.insert(JsonIdCorrelator,
Json::Value::string(*args.github_workflow.get() + "-" + *args.github_job.get()));
job.insert(JsonIdId, Json::Value::string(*github_run_id));
job.insert(JsonIdCorrelator, Json::Value::string(fmt::format("{}-{}", *github_workflow, *github_run_id)));

Json::Object snapshot;
snapshot.insert(JsonIdJob, job);
snapshot.insert(JsonIdVersion, Json::Value::integer(0));
snapshot.insert(JsonIdSha, Json::Value::string(*args.github_sha.get()));
snapshot.insert(JsonIdRef, Json::Value::string(*args.github_ref.get()));
snapshot.insert(JsonIdSha, Json::Value::string(*github_sha));
snapshot.insert(JsonIdRef, Json::Value::string(*github_ref));
snapshot.insert(JsonIdScanned, Json::Value::string(CTime::now_string()));
snapshot.insert(JsonIdDetector, detector);

Expand All @@ -77,44 +80,45 @@ namespace vcpkg
std::unordered_map<std::string, std::string> map;
for (auto&& action : action_plan.install_actions)
{
if (!action.source_control_file_and_location.has_value())
const auto scfl = action.source_control_file_and_location.get();
if (!scfl)
{
return nullopt;
}
const auto& scf = *action.source_control_file_and_location.get();
auto version = scf.to_version().to_string();
auto s = action.spec.to_string();
auto pkg_url = Strings::concat("pkg:github/vcpkg/", s, "@", version);
map.insert({s, pkg_url});
auto spec = action.spec.to_string();
map.insert(
{spec, fmt::format("pkg:github/vcpkg/{}@{}", spec, scfl->source_control_file->to_version())});
}

Json::Object resolved;
for (auto&& action : action_plan.install_actions)
{
Json::Object resolved_item;
if (map.find(action.spec.to_string()) != map.end())
auto spec = action.spec.to_string();
const auto found = map.find(spec);
if (found != map.end())
{
auto pkg_url = map.at(action.spec.to_string());
const auto& pkg_url = found->second;
resolved_item.insert(JsonIdPackageUnderscoreUrl, pkg_url);
resolved_item.insert(JsonIdRelationship, Json::Value::string(JsonIdDirect));
Json::Array deps_list;
for (auto&& dep : action.package_dependencies)
{
if (map.find(dep.to_string()) != map.end())
const auto found_dep = map.find(dep.to_string());
if (found_dep != map.end())
{
auto dep_pkg_url = map.at(dep.to_string());
deps_list.push_back(dep_pkg_url);
deps_list.push_back(found_dep->second);
}
}
resolved_item.insert(JsonIdDependencies, deps_list);
resolved.insert(pkg_url, resolved_item);
}
}

manifest.insert(JsonIdResolved, resolved);
Json::Object manifests;
manifests.insert(JsonIdVcpkgDotJson, manifest);
snapshot.insert(JsonIdManifests, manifests);

Debug::print(Json::stringify(snapshot));
return snapshot;
}
Expand Down
30 changes: 16 additions & 14 deletions src/vcpkg/configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,20 +441,20 @@ namespace
continue;
}

if (!el.second.is_object())
auto maybe_demand_obj = el.second.maybe_object();
if (!maybe_demand_obj)
{
r.add_generic_error(type_name(), msg::format(msgJsonFieldNotObject, msg::json_field = key));
continue;
}

const auto& demand_obj = el.second.object(VCPKG_LINE_INFO);
if (demand_obj.contains(JsonIdDemands))
if (maybe_demand_obj->contains(JsonIdDemands))
{
r.add_generic_error(type_name(),
msg::format(msgConfigurationNestedDemands, msg::json_field = el.first));
}

auto maybe_demand = r.visit(demand_obj, CeMetadataDeserializer::instance);
auto maybe_demand = r.visit(*maybe_demand_obj, CeMetadataDeserializer::instance);
if (maybe_demand.has_value())
{
ret.insert_or_replace(key, maybe_demand.value_or_exit(VCPKG_LINE_INFO));
Expand Down Expand Up @@ -602,13 +602,14 @@ namespace
auto serialize_demands = [](const Json::Object& obj, Json::Object& put_into) {
if (auto demands = obj.get(JsonIdDemands))
{
if (!demands->is_object())
auto demands_obj = demands->maybe_object();
if (!demands_obj)
{
return;
}

Json::Object serialized_demands;
for (const auto& el : demands->object(VCPKG_LINE_INFO))
for (const auto& el : *demands_obj)
{
auto key = el.first;
if (Strings::starts_with(key, "$"))
Expand All @@ -617,10 +618,10 @@ namespace
continue;
}

if (el.second.is_object())
if (auto demand_obj = el.second.maybe_object())
{
auto& inserted = serialized_demands.insert_or_replace(key, Json::Object{});
serialize_ce_metadata(el.second.object(VCPKG_LINE_INFO), inserted);
serialize_ce_metadata(*demand_obj, inserted);
}
}
put_into.insert_or_replace(JsonIdDemands, serialized_demands);
Expand Down Expand Up @@ -667,12 +668,13 @@ namespace

if (el.first == JsonIdDemands)
{
if (!el.second.is_object())
auto maybe_demands_object = el.second.maybe_object();
if (!maybe_demands_object)
{
continue;
}

for (const auto& demand : el.second.object(VCPKG_LINE_INFO))
for (const auto& demand : *maybe_demands_object)
{
if (Strings::starts_with(demand.first, "$"))
{
Expand Down Expand Up @@ -840,13 +842,13 @@ namespace vcpkg
}

auto conf_value = std::move(conf).value(VCPKG_LINE_INFO).value;
if (!conf_value.is_object())
if (auto conf_value_object = conf_value.maybe_object())
{
messageSink.println(msgFailedToParseNoTopLevelObj, msg::path = origin);
return nullopt;
return parse_configuration(std::move(*conf_value_object), origin, messageSink);
}

return parse_configuration(std::move(conf_value).object(VCPKG_LINE_INFO), origin, messageSink);
messageSink.println(msgFailedToParseNoTopLevelObj, msg::path = origin);
return nullopt;
}

Optional<Configuration> parse_configuration(const Json::Object& obj, StringView origin, MessageSink& messageSink)
Expand Down
26 changes: 14 additions & 12 deletions src/vcpkg/configure-environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,32 @@ namespace
return;
}

auto acquired_artifacts = pparsed->get(JsonIdAcquiredArtifacts);
if (acquired_artifacts)
if (auto acquired_artifacts = pparsed->get(JsonIdAcquiredArtifacts))
{
if (acquired_artifacts->is_string())
if (auto maybe_acquired_string = acquired_artifacts->maybe_string())
{
get_global_metrics_collector().track_string(StringMetric::AcquiredArtifacts,
acquired_artifacts->string(VCPKG_LINE_INFO));
get_global_metrics_collector().track_string(StringMetric::AcquiredArtifacts, *maybe_acquired_string);
}
else
{
Debug::println("Acquired artifacts was not a string.");
}
Debug::println("Acquired artifacts was not a string.");
}
else
{
Debug::println("No artifacts acquired.");
}

auto activated_artifacts = pparsed->get(JsonIdActivatedArtifacts);
if (activated_artifacts)
if (auto activated_artifacts = pparsed->get(JsonIdActivatedArtifacts))
{
if (activated_artifacts->is_string())
if (auto maybe_activated_string = activated_artifacts->maybe_string())
{
get_global_metrics_collector().track_string(StringMetric::ActivatedArtifacts, *maybe_activated_string);
}
else
{
get_global_metrics_collector().track_string(StringMetric::ActivatedArtifacts,
activated_artifacts->string(VCPKG_LINE_INFO));
Debug::println("Activated artifacts was not a string.");
}
Debug::println("Activated artifacts was not a string.");
}
else
{
Expand Down
4 changes: 2 additions & 2 deletions src/vcpkg/sourceparagraph.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,9 +1194,9 @@ namespace vcpkg

if (auto configuration = obj.get(JsonIdVcpkgConfiguration))
{
if (configuration->is_object())
if (auto configuration_object = configuration->maybe_object())
{
spgh.vcpkg_configuration.emplace(configuration->object(VCPKG_LINE_INFO));
spgh.vcpkg_configuration.emplace(*configuration_object);
}
else
{
Expand Down
Loading

0 comments on commit 829b20e

Please sign in to comment.