1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
open Core
module Custom = struct
type t =
{ type_id : int
; data : Bytes.t
}
[@@deriving compare, sexp]
end
module T = struct
type t =
| Nil
| Integer of int
| Int64 of Int64.t
| UInt64 of Int64.t
| Boolean of bool
| Floating of float
| Array of t list
| Map of (t * t) list
| String of string
| Binary of Bytes.t
| Extension of Custom.t
[@@deriving compare, sexp]
end
include T
include Comparable.Make (T)
let quickcheck_generator ~only_string_keys ~only_finite_floats =
let open Quickcheck in
let open Generator in
let open Generator.Let_syntax in
let int_gen =
let open Int.O in
let min_tested_int = 0 - (2 ** 16) in
let max_tested_int = (2 ** 16) - 1 in
Int.gen_uniform_incl min_tested_int max_tested_int
in
let int64_gen = Int64.gen_uniform_incl Int64.min_value Int64.max_value in
let int64_pos_gen = Int64.gen_uniform_incl Int64.min_value Int64.minus_one in
let float =
if only_finite_floats then Float.gen_finite else Float.quickcheck_generator
in
recursive_union
[ return Nil
; (let%map i = int_gen in
Integer i)
; (let%map i = int64_gen in
UInt64 i)
; (let%map i = int64_pos_gen in
Int64 i)
; (let%map b = bool in
Boolean b)
; (let%map f = float in
Floating f)
; (let%map s = String.gen' char_print in
String s)
; (let%map b = Bytes.gen' char in
Binary b)
; (let%bind type_id = Int.gen_uniform_incl (-128) 127 in
let%map data = Bytes.gen' char in
Extension { type_id; data })
]
~f:(fun self ->
[ (let%map vs = list self in
Array vs)
; (let%bind ks =
list
(match only_string_keys with
| false -> self
| true ->
let%map s = String.gen' char_print in
String s)
in
let ks_length = List.length ks in
let%map vs = list_with_length ks_length self in
Map (List.zip_exn ks vs))
])
;;