virthttp  0.0
libvirt http interface
flagwork.hpp
Go to the documentation of this file.
1 #pragma once
2 #include <optional>
3 #include <string_view>
4 #include "../../detect.hpp"
5 #include "urlparser.hpp"
6 
15 #define SUBQ_LIFT(mem_fn) \
16  [&](auto&&... args) noexcept(noexcept(mem_fn(std::forward<decltype(args)>(args)...))) -> decltype( \
17  mem_fn(std::forward<decltype(args)>(args)...)) { \
18  return mem_fn(std::forward<decltype(args)>(args)...); \
19  }
20 
35 template <class F, class = std::enable_if_t<!std::is_same_v<F, Empty>>>
36 constexpr auto target_get_composable_flag(const TargetParser& target, std::string_view tag) noexcept -> std::optional<F> {
37  auto flags = F{};
38  if (auto csv = target[tag]; !csv.empty()) {
39  for (CSVIterator state_it{csv}; state_it != state_it.end(); ++state_it) {
40  const auto v = F::from_string(*state_it);
41  if (!v)
42  return std::nullopt;
43  if constexpr (test_sfinae([](auto f, auto g) { return f | g; }, F{}, F{}))
44  flags |= *v;
45  else
46  return v;
47  }
48  }
49  return {flags};
50 }
51 
60 template <class... Fcns> constexpr auto parameterized_depends_scope(Fcns&&... depends) noexcept((std::is_nothrow_move_constructible_v<Fcns> && ...)) {
61  using Arr = std::tuple<Fcns...>; // pray for vectorisation; wait for expansion statements
62  return [&](auto&&... args) -> DependsOutcome {
64  visit(Arr{std::forward<Fcns>(depends)...}, [&](auto&& f) {
65  if (ret != DependsOutcome::SKIPPED)
66  return;
67  if (const auto ao = std::forward<decltype(f)>(f)(args...); ao != DependsOutcome::SKIPPED) {
68  ret = ao;
69  }
70  });
71  return ret;
72  };
73 };
74 
78 namespace subq_impl {
79 
87 template <class T, class A> using ToJson = decltype(to_json(std::declval<T&&>(), std::declval<A&>()));
95 template <class T, class A> using GetToJson = decltype(get_to_json(std::declval<T&&>(), std::declval<A&>()));
96 
107 template <class T, class A> constexpr decltype(auto) auto_serialize(T&& v, A& al) {
108  using Value = std::remove_reference_t<T>;
109  using Alloc = std::remove_reference_t<A>;
110  if constexpr (nstd::is_detected_v<ToJson, Value, Alloc>)
111  return to_json(std::move(v), al);
112  else if constexpr (nstd::is_detected_v<GetToJson, Value, Alloc>)
113  return get_to_json(std::move(v), al);
114  else
115  static_assert(std::is_void_v<Value>, "T is not auto-serializable");
116  UNREACHABLE;
117 }
118 
135 template <class TI, class F, class VC, class TJ>
136 auto subquery(std::string_view name, std::string_view opt_tag, [[maybe_unused]] TI ti, F&& lifted, VC&& valid_check, TJ&& to_json) noexcept(
137  std::is_nothrow_move_constructible_v<F>&& std::is_nothrow_move_constructible_v<VC>&& std::is_nothrow_move_constructible_v<TJ>) {
138  return [name, opt_tag, lifted = std::forward<F>(lifted), valid_check = std::forward<VC>(valid_check), to_json = std::forward<TJ>(to_json)](
139  int sq_lev, const TargetParser& target, auto& res_val, auto& allocator, auto&& error) -> DependsOutcome {
140  if (target.getPathParts()[sq_lev] == name) {
141  using Flag = typename TI::type;
142  Flag flag{};
143  if constexpr (std::is_same_v<Flag, std::string_view> || std::is_same_v<Flag, std::string>)
144  flag = target[opt_tag];
145  else {
146  const auto opt_flags = target_get_composable_flag<Flag>(target, opt_tag);
147  if (!opt_flags)
148  return error(301), DependsOutcome::FAILURE;
149  flag = *opt_flags;
150  }
151  auto&& res = lifted(std::move(flag));
152  return valid_check(res) ? (res_val = std::move(to_json(std::move(res), allocator)), DependsOutcome::SUCCESS) : DependsOutcome::FAILURE;
153  }
155  };
156 }
157 
172 template <class F, class VC, class TI>
173 auto subquery(std::string_view name, std::string_view opt_tag, TI ti, F&& lifted,
174  VC&& valid_check) noexcept(std::is_nothrow_move_constructible_v<F>&& std::is_nothrow_move_constructible_v<VC>) -> decltype(auto) {
175  return subquery(name, opt_tag, ti, std::forward<F>(lifted), std::forward<VC>(valid_check),
176  [](auto&&... args) -> decltype(subq_impl::auto_serialize(args...)) { return subq_impl::auto_serialize(args...); });
177 }
178 
193 template <class F, class VC, class TJ, class = std::enable_if_t<!std::is_same_v<F, std::string_view>>>
194 auto subquery(std::string_view name, F&& lifted, VC&& valid_check, TJ&& to_json) noexcept(
195  std::is_nothrow_move_constructible_v<F>&& std::is_nothrow_move_constructible_v<VC>&& std::is_nothrow_move_constructible_v<TJ>) {
196  return [&, name, lifted = std::forward<F>(lifted), valid_check = std::forward<VC>(valid_check), to_json = std::forward<TJ>(to_json)](
197  int sq_lev, const TargetParser& target, auto& res_val, auto& allocator, auto&& error) -> DependsOutcome {
198  if (target.getPathParts()[sq_lev] == name) {
199  auto&& res = lifted();
200  return valid_check(res) ? (res_val = std::move(to_json(std::move(res), allocator)), DependsOutcome::SUCCESS) : DependsOutcome::FAILURE;
201  }
203  };
204 }
205 
218 template <class F, class VC, class = std::enable_if_t<!std::is_same_v<F, std::string_view>>>
219 auto subquery(std::string_view name, F&& lifted,
220  VC&& valid_check) noexcept(std::is_nothrow_move_constructible_v<F>&& std::is_nothrow_move_constructible_v<VC>) -> decltype(auto) {
221  return subquery(name, std::forward<F>(lifted), std::forward<VC>(valid_check),
222  [](auto&&... args) -> decltype(subq_impl::auto_serialize(args...)) { return subq_impl::auto_serialize(args...); });
223 }
224 
225 } // namespace subq_impl
226 
242 constexpr auto subquery = [](auto&&... args) noexcept(noexcept(subq_impl::subquery(std::forward<decltype(args)>(args)...)))
243  -> decltype(subq_impl::subquery(std::forward<decltype(args)>(args)...)) { return subq_impl::subquery(std::forward<decltype(args)>(args)...); };
constexpr auto target_get_composable_flag(const TargetParser &target, std::string_view tag) noexcept-> std::optional< F >
Extracts a flag from the HTTP target.
Definition: flagwork.hpp:36
DependsOutcome
Definition: depends.hpp:11
#define UNREACHABLE
Definition: utility.hpp:19
auto to_json(const virt::TypedParams &tp, JAllocator &&jalloc) noexcept-> rapidjson::Value
Definition: virt2json.hpp:6
Definition: flagwork.hpp:78
STL namespace.
Definition: urlparser.hpp:164
auto subquery(std::string_view name, std::string_view opt_tag, [[maybe_unused]] TI ti, F &&lifted, VC &&valid_check, TJ &&to_json) noexcept(std::is_nothrow_move_constructible_v< F > &&std::is_nothrow_move_constructible_v< VC > &&std::is_nothrow_move_constructible_v< TJ >)
subquery overload for functions taking a single flag and without automatically deduced JSON serializa...
Definition: flagwork.hpp:136
auto get_to_json(std::optional< T > opt, JAllocator &&jalloc) -> rapidjson::Value
Definition: virt2json.hpp:83
constexpr auto test_sfinae(Lambda lambda, Ts &&...) -> decltype(lambda(std::declval< Ts >()...), bool
Definition: utility.hpp:37
decltype(get_to_json(std::declval< T && >(), std::declval< A & >())) GetToJson
Definition: flagwork.hpp:95
constexpr auto ti
Definition: utils.hpp:23
decltype(auto) constexpr auto_serialize(T &&v, A &al)
Definition: flagwork.hpp:107
constexpr auto parameterized_depends_scope(Fcns &&...depends) noexcept((std::is_nothrow_move_constructible_v< Fcns > &&...))
Definition: flagwork.hpp:60
constexpr const std::vector< std::string_view > & getPathParts() const noexcept
Definition: urlparser.hpp:83
decltype(to_json(std::declval< T && >(), std::declval< A & >())) ToJson
Definition: flagwork.hpp:87
Definition: urlparser.hpp:36
constexpr CSVIterator end() const noexcept
Definition: urlparser.hpp:181
void visit(T &&t, V &&v)
Definition: utility.hpp:44