Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 54 additions & 3 deletions phlex/configuration.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,58 @@
#include "phlex/configuration.hpp"
#include "phlex/core/product_query.hpp"
#include "phlex/model/product_specification.hpp"

#include <ranges>
#include <algorithm>
#include <array>
#include <string>
#include <string_view>

namespace {
[[maybe_unused]] std::optional<std::string> 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;

Check warning on line 16 in phlex/configuration.cpp

View check run for this annotation

Codecov / codecov/patch

phlex/configuration.cpp#L15-L16

Added lines #L15 - L16 were not covered by tests
}
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;

Check warning on line 46 in phlex/configuration.cpp

View check run for this annotation

Codecov / codecov/patch

phlex/configuration.cpp#L18-L46

Added lines #L18 - L46 were not covered by tests
}
throw std::runtime_error(
fmt::format("Error retrieving parameter '{}'. Should be a string but is instead a {}",
parameter,
kind));

Check warning on line 51 in phlex/configuration.cpp

View check run for this annotation

Codecov / codecov/patch

phlex/configuration.cpp#L48-L51

Added lines #L48 - L51 were not covered by tests
}
return boost::json::value_to<std::string>(val);

Check warning on line 53 in phlex/configuration.cpp

View check run for this annotation

Codecov / codecov/patch

phlex/configuration.cpp#L53

Added line #L53 was not covered by tests
}
}

namespace phlex {
std::vector<std::string> configuration::keys() const
Expand All @@ -25,7 +75,8 @@
{
using detail::value_decorate_exception;
auto query_object = jv.as_object();
return product_query{{value_decorate_exception<std::string>(query_object, "product")},
value_decorate_exception<std::string>(query_object, "layer")};
auto product = value_decorate_exception<std::string>(query_object, "product");
auto layer = value_decorate_exception<std::string>(query_object, "layer");
return product_query{experimental::product_specification::create(product), layer};
}
}
21 changes: 21 additions & 0 deletions phlex/configuration.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename T, std::size_t... I>
std::array<T, sizeof...(I)> unpack_json_array(boost::json::array const& array,
std::index_sequence<I...>)
{
return std::array<T, sizeof...(I)>{boost::json::value_to<T>(array.at(I))...};
}
}

class configuration {
Expand Down Expand Up @@ -81,6 +89,19 @@ namespace phlex {

product_query tag_invoke(boost::json::value_to_tag<product_query> const&,
boost::json::value const& jv);

template <std::size_t N>
std::array<product_query, N> tag_invoke(
boost::json::value_to_tag<std::array<product_query, N>> const&, boost::json::value const& jv)
{
auto const& array = jv.as_array();
return detail::unpack_json_array<product_query>(array, std::make_index_sequence<N>());
}
}

// The below is a better long term fix but it requires a Boost JSON bug (#1140) to be fixed
// namespace boost::json {
// template <std::size_t N>
// struct is_sequence_like<std::array<phlex::product_query, N>> : std::false_type {};
// }
#endif // PHLEX_CONFIGURATION_HPP
2 changes: 0 additions & 2 deletions phlex/core/product_query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
#include <stdexcept>

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)}
{
Expand Down
3 changes: 0 additions & 3 deletions phlex/core/product_query.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, N>.
product_query();
product_query(experimental::product_specification spec, std::string layer);

auto const& spec() const noexcept { return spec_; }
Expand Down
Loading