27 T default_parse_raw(
const hegel::internal::json::json_raw_ref& result) {
28 if constexpr (std::is_same_v<T, std::string>) {
29 return result.get_string();
30 }
else if constexpr (std::is_same_v<std::remove_cvref_t<T>,
bool>) {
31 return result.get_bool();
32 }
else if constexpr (std::is_floating_point_v<T>) {
33 return static_cast<T
>(result.get_double());
34 }
else if constexpr (std::is_unsigned_v<T>) {
35 return static_cast<T
>(result.get_uint64_t());
36 }
else if constexpr (std::is_integral_v<T>) {
37 return static_cast<T
>(result.get_int64_t());
39 auto parse_result = internal::read_nlohmann<T>(result);
40 if (!parse_result.has_value()) {
41 throw std::runtime_error(
42 "Failed to parse server response into requested type");
44 return parse_result.value();
54 std::function<T(
const hegel::internal::json::json_raw_ref&)>;
56 hegel::internal::json::json schema;
59 T parse_raw(
const hegel::internal::json::json_raw_ref& raw)
const {
63 T do_draw(
const TestCase& tc)
const {
64 hegel::internal::json::json response =
65 internal::communicate_with_core(schema, tc);
66 if (!response.contains(
"result")) {
67 throw std::runtime_error(
68 "Server response missing 'result' field");
70 return parse(response[
"result"]);
73 template <
typename F,
typename U = std::invoke_result_t<F, T>>
74 BasicGenerator<U> map(F f)
const {
75 Parse old_parse = parse;
76 hegel::internal::json::json sch = schema;
77 return BasicGenerator<U>{
79 [old_parse = std::move(old_parse), f = std::move(f)](
80 const hegel::internal::json::json_raw_ref& raw) -> U {
81 return f(old_parse(raw));
94 template <
typename T>
struct IGenerator {
96 virtual ~IGenerator() =
default;
106 virtual std::optional<BasicGenerator<T>> as_basic()
const {
113 virtual std::optional<hegel::internal::json::json> schema()
const {
115 return b ? std::optional{b->schema} : std::nullopt;
121 virtual T do_draw(
const TestCase& tc)
const {
122 if (
auto b = as_basic())
123 return b->do_draw(tc);
124 throw std::logic_error(
125 "IGenerator has no basic form and no do_draw override");
160 Generator(IGenerator<T>* p) : IGenerator<T>(), inner_(p) {}
161 Generator(std::shared_ptr<IGenerator<T>> p)
162 : IGenerator<T>(), inner_(std::move(p)) {}
164 T do_draw(
const TestCase& tc)
const override {
165 return inner_->do_draw(tc);
168 std::optional<hegel::internal::json::json> schema()
const override {
169 return inner_->schema();
172 std::optional<BasicGenerator<T>> as_basic()
const override {
173 return inner_->as_basic();
200 template <
typename F>
202 using ResultType = std::invoke_result_t<F, T>;
228 template <
typename F> std::invoke_result_t<F, T>
flat_map(F&& f)
const {
235 decltype(std::declval<std::invoke_result_t<F, T>>().do_draw(
236 std::declval<const TestCase&>()));
238 return compose([inner, f = std::forward<F>(f)](
240 return f(inner->do_draw(tc)).do_draw(tc);
272 for (
int i = 0; i < 3; ++i) {
273 T value = inner->do_draw(tc);
280 throw internal::HegelReject();
285 std::shared_ptr<IGenerator<T>> inner_;
292 template <
typename T>
class CompositeGenerator :
public IGenerator<T> {
294 explicit CompositeGenerator(std::function<T(
const TestCase&)> fn)
295 : gen_fn_(std::move(fn)) {}
297 T do_draw(
const TestCase& tc)
const override {
return gen_fn_(tc); }
300 std::function<T(
const TestCase&)> gen_fn_;
312 template <
typename T,
typename U>
315 MappedGenerator(std::shared_ptr<IGenerator<T>> source,
316 std::function<U(T)> f)
317 : source_(std::move(source)), f_(std::move(f)) {}
319 std::optional<BasicGenerator<U>> as_basic()
const override {
320 auto basic = source_->as_basic();
323 return basic->map(f_);
326 U do_draw(
const TestCase& tc)
const override {
327 if (
auto basic = as_basic()) {
328 return basic->do_draw(tc);
330 return f_(source_->do_draw(tc));
334 std::shared_ptr<IGenerator<T>> source_;
335 std::function<U(T)> f_;
361 using T = std::invoke_result_t<F, const TestCase&>;
363 std::function<T(
const TestCase&)>(std::forward<F>(fn))));