From 1bf6bbf88e15d1df3afef3e35e42328c316d3406 Mon Sep 17 00:00:00 2001 From: Beojan Stanislaus Date: Tue, 3 Feb 2026 09:05:40 -0800 Subject: [PATCH 1/2] JSON parsing changes from new product query Eliminates need for default constructor --- phlex/configuration.cpp | 56 ++++++++++++++++++++++++++++++++++-- phlex/configuration.hpp | 21 ++++++++++++++ phlex/core/product_query.cpp | 2 -- phlex/core/product_query.hpp | 3 -- 4 files changed, 74 insertions(+), 8 deletions(-) diff --git a/phlex/configuration.cpp b/phlex/configuration.cpp index 03cb6daa..bf6cfd01 100644 --- a/phlex/configuration.cpp +++ b/phlex/configuration.cpp @@ -1,8 +1,57 @@ #include "phlex/configuration.hpp" #include "phlex/core/product_query.hpp" +#include "phlex/model/product_specification.hpp" -#include +#include +#include #include +#include + +namespace { + [[maybe_unused]] std::optional value_if_exists(boost::json::object const& obj, // will be used later for new product_query + std::string_view parameter) + { + if (!obj.contains(parameter)) { + return std::nullopt; + } + auto const& val = obj.at(parameter); + if (!val.is_string()) { + std::string_view kind; + switch (val.kind()) { + case boost::json::kind::null: + // seems reasonable to interpret this as if the value were not provided + return std::nullopt; + break; + case boost::json::kind::bool_: + kind = "bool"; + break; + case boost::json::kind::int64: + kind = "std::int64_t"; + break; + case boost::json::kind::uint64: + kind = "std::uint64_t"; + break; + case boost::json::kind::double_: + kind = "double"; + break; + case boost::json::kind::array: + kind = "array"; + break; + case boost::json::kind::object: + kind = "object"; + break; + default: + // std::unreachable(); + break; + } + throw std::runtime_error( + fmt::format("Error retrieving parameter '{}'. Should be a string but is instead a {}", + parameter, + kind)); + } + return boost::json::value_to(val); + } +} namespace phlex { std::vector configuration::keys() const @@ -25,7 +74,8 @@ namespace phlex { { using detail::value_decorate_exception; auto query_object = jv.as_object(); - return product_query{{value_decorate_exception(query_object, "product")}, - value_decorate_exception(query_object, "layer")}; + auto product = value_decorate_exception(query_object, "product"); + auto layer = value_decorate_exception(query_object, "layer"); + return product_query{experimental::product_specification::create(product), layer}; } } diff --git a/phlex/configuration.hpp b/phlex/configuration.hpp index 1fa142b8..82ef7aa3 100644 --- a/phlex/configuration.hpp +++ b/phlex/configuration.hpp @@ -19,6 +19,14 @@ namespace phlex { } catch (std::exception const& e) { throw std::runtime_error("Error retrieving parameter '" + key + "':\n" + e.what()); } + + // helper for unpacking json array + template + std::array unpack_json_array(boost::json::array const& array, + std::index_sequence) + { + return std::array{boost::json::value_to(array.at(I))...}; + } } class configuration { @@ -81,6 +89,19 @@ namespace phlex { product_query tag_invoke(boost::json::value_to_tag const&, boost::json::value const& jv); + + template + std::array tag_invoke( + boost::json::value_to_tag> const&, boost::json::value const& jv) + { + auto const& array = jv.as_array(); + return detail::unpack_json_array(array, std::make_index_sequence()); + } } +// The below is a better long term fix but it requires a Boost JSON bug (#1140) to be fixed +// namespace boost::json { +// template +// struct is_sequence_like> : std::false_type {}; +// } #endif // PHLEX_CONFIGURATION_HPP diff --git a/phlex/core/product_query.cpp b/phlex/core/product_query.cpp index 5f442e70..01e08fc4 100644 --- a/phlex/core/product_query.cpp +++ b/phlex/core/product_query.cpp @@ -5,8 +5,6 @@ #include namespace phlex { - product_query::product_query() = default; - product_query::product_query(experimental::product_specification spec, std::string layer) : spec_{std::move(spec)}, layer_{std::move(layer)} { diff --git a/phlex/core/product_query.hpp b/phlex/core/product_query.hpp index 55cc3956..d11b9b69 100644 --- a/phlex/core/product_query.hpp +++ b/phlex/core/product_query.hpp @@ -10,9 +10,6 @@ namespace phlex { class product_query { public: - // FIXME: Boost JSON's parameter retrieval facilities require a default constructor - // whenever the type is (e.g.) std::array. - product_query(); product_query(experimental::product_specification spec, std::string layer); auto const& spec() const noexcept { return spec_; } From aaebf2f35f01dadbb762c5d8a1716598c9a5c059 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 3 Feb 2026 19:55:28 +0000 Subject: [PATCH 2/2] Apply clang-format fixes --- phlex/configuration.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/phlex/configuration.cpp b/phlex/configuration.cpp index bf6cfd01..3be6f390 100644 --- a/phlex/configuration.cpp +++ b/phlex/configuration.cpp @@ -8,8 +8,9 @@ #include namespace { - [[maybe_unused]] std::optional value_if_exists(boost::json::object const& obj, // will be used later for new product_query - std::string_view parameter) + [[maybe_unused]] std::optional value_if_exists( + boost::json::object const& obj, // will be used later for new product_query + std::string_view parameter) { if (!obj.contains(parameter)) { return std::nullopt;