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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
type vec = { off : int option; len : int option }
type 'a state = 'a Lole.state
type encoder = Lole.encoder
type bigstring = Lole.bigstring
type iovecs = Lole.IOVec.t list
type -'a t = { run : 'r. (encoder -> 'r state) -> encoder -> 'a -> 'r state }
type -'a s = {
sub :
'r. (encoder -> 'r state) -> encoder -> ?off:int -> ?len:int -> 'a ->
'r state;
}
let peek : 'a t -> 'b t -> ('a, 'b) Either.t t =
fun a b ->
{ run = (fun k e -> function L x -> a.run k e x | R y -> b.run k e y) }
let char : char t = { run = (fun k e v -> Lole.write_char v k e) }
let int8 : int t = { run = (fun k e v -> Lole.write_uint8 v k e) }
let beint16 : int t = { run = (fun k e v -> Lole.BE.write_uint16 v k e) }
let beint32 : int32 t = { run = (fun k e v -> Lole.BE.write_uint32 v k e) }
let beint64 : int64 t = { run = (fun k e v -> Lole.BE.write_uint64 v k e) }
let leint16 : int t = { run = (fun k e v -> Lole.LE.write_uint16 v k e) }
let leint32 : int32 t = { run = (fun k e v -> Lole.LE.write_uint32 v k e) }
let leint64 : int64 t = { run = (fun k e v -> Lole.LE.write_uint64 v k e) }
let bool : bool t =
{
run =
(fun k e -> function
| true -> char.run k e '1'
| false -> char.run k e '0');
}
let substring : string s =
{ sub = (fun k e ?off ?len v -> Lole.write_string ?off ?len v k e) }
let subbytes : bytes s =
{ sub = (fun k e ?off ?len v -> Lole.write_bytes ?off ?len v k e) }
let subbigstring : bigstring s =
{ sub = (fun k e ?off ?len v -> Lole.write_bigstring ?off ?len v k e) }
let blitter length blit : _ s =
{ sub = (fun k e ?off ?len v -> Lole.write k ~blit ~length ?off ?len v e) }
let whole (a : 'v s) : 'v t =
{ run = (fun k e v -> a.sub ?off:None ?len:None k e v) }
let sub (a : 'v s) : (vec * 'v) t =
{ run = (fun k e ({ off; len }, v) -> a.sub ?off ?len k e v) }
let string : string t = whole substring
let bytes : bytes t = whole subbytes
let bigstring : bigstring t = whole subbigstring
let list ?sep a : 'a list t =
let sep k e = match sep with None -> k e | Some a -> a.run k e () in
let rec run k e : _ list -> _ state = function
| [] -> k e
| [ x ] -> a.run k e x
| x :: r -> a.run (sep (fun e -> run k e r)) e x in
{ run }
let nop = { run = (fun k e _ -> k e) }
let option f : 'a option t =
{ run = (fun k e -> function Some v -> f.run k e v | None -> k e) }
exception Fail of string
let pure ~compare v =
{
run =
(fun k e v' ->
if compare v v' = 0
then k e
else raise (Fail "fail at the pure operator"));
}
let fail s = { run = (fun _k _e _v -> raise (Fail s)) }
let const s =
{
run =
(fun k e s' ->
if String.equal s s'
then Lole.write_string s' k e
else raise (Fail (Fmt.strf "const: %s <> %s" s s')));
}
let ( <|> ) pu pv =
{
run =
(fun k e v ->
try pu.run k e v with Fail _ | Bijection.Exn.Bijection -> pv.run k e v);
}
let ( <$> ) f p = { run = (fun k e v -> p.run k e (f v)) }
let ( <*> ) a b = { run = (fun k e (x, y) -> a.run (fun e -> b.run k e y) e x) }
let prefix p r = { run = (fun k e v -> p.run (fun e -> r.run k e v) e ()) }
let suffix s r = { run = (fun k e v -> r.run (fun e -> s.run k e ()) e v) }
exception Break
let for_all predicate s =
let l = String.length s in
try
for i = 0 to l - 1 do
if not (predicate (String.unsafe_get s i)) then raise Break
done ;
true
with Break -> false
let while0 predicate =
{
run =
(fun k e v ->
if for_all predicate v
then Lole.write_string v k e
else raise (Fail "while0"));
}
let while1 predicate =
{
run =
(fun k e v ->
if String.length v > 0 && for_all predicate v
then Lole.write_string v k e
else raise (Fail "while1"));
}
let for_all predicate b =
let l = Bigarray_compat.Array1.dim b in
try
for i = 0 to l - 1 do
if not (predicate b.{i}) then raise Break
done ;
true
with Break -> false
let bigstring_while0 predicate =
{
run =
(fun k e v ->
if for_all predicate v
then Lole.write_bigstring v k e
else raise (Fail "bigstring_while0"));
}
let bigstring_while1 predicate =
{
run =
(fun k e v ->
if Bigarray_compat.Array1.dim v > 0 && for_all predicate v
then Lole.write_bigstring v k e
else raise (Fail "bigstring_while1"));
}
let take n =
{
run =
(fun k e s ->
if String.length s = n then string.run k e s else raise (Fail "take"));
}
let buffer = string
let bigstring_buffer = bigstring
let ( <* ) r s = suffix s r
let ( *> ) p r = prefix p r
let fix f =
let rec p = lazy (f r)
and r = { run = (fun k e v -> Lazy.(force p).run k e v) } in
r
let commit = { run = (fun k e () -> Lole.flush k e) }
let keval :
'v 'r. (encoder -> 'r state) -> (iovecs -> int) -> encoder -> 'v t ->
'v -> 'r =
fun k w e t v ->
let rec go = function
| Lole.End v -> v
| Lole.Continue { continue; encoder } -> continue encoder |> go
| Lole.Flush { continue; iovecs } ->
let len = w iovecs in
continue len |> go in
t.run k e v |> go
let eval w e t v = keval (fun _e -> Lole.End ()) w e (t <* commit) v
let run t = t.run
module Make (S : sig
type a
val run : (encoder -> 'r state) -> encoder -> a -> 'r state
end) =
struct
let x = { run = S.run }
end
let to_string : type a. a t -> a -> string =
fun t v ->
let buf = Buffer.create 16 in
let writer l =
List.iter
(function
| { Lole.IOVec.buffer = Lole.Buffer.String s; off; len } ->
Buffer.add_substring buf s off len
| { Lole.IOVec.buffer = Lole.Buffer.Bytes s; off; len } ->
Buffer.add_subbytes buf s off len
| { Lole.IOVec.buffer = Lole.Buffer.Bigstring s; off; len } ->
for i = 0 to len - 1 do
Buffer.add_char buf s.{off + i}
done)
l ;
Lole.IOVec.lengthv l in
eval writer (Lole.create 0x100) t v ;
Buffer.contents buf