-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathrFC7159.ml
81 lines (75 loc) · 2.5 KB
/
rFC7159.ml
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
open Faraday
type json =
[ `Null
| `False
| `True
| `String of string
| `Number of float
| `Object of (string * json) list
| `Array of json list ]
let to_hex_digit i =
Char.unsafe_chr (if i < 10 then i + 48 else i + 87)
let serialize_string t s =
(* TODO: Implement proper unicode verification. *)
let flush ~off ~len =
if len <> 0 then write_string t ~off ~len s in
let rec go ~off ~len =
if String.length s = off + len
then flush ~off ~len
else
let i = off + len in
match String.get s i with
| c when c <= '\031' -> (* non-visible characters have to be escaped *)
let i = Char.code c in
flush ~off ~len;
write_string t "\\u00";
write_char t (to_hex_digit (i lsr 4));
write_char t (to_hex_digit (i land 0xf));
go ~off:(i+1) ~len:0
| '"' -> flush ~off ~len; write_string t "\\" ; go ~off:(i+1) ~len:0
| '/' -> flush ~off ~len; write_string t "\\/" ; go ~off:(i+1) ~len:0
| '\b' -> flush ~off ~len; write_string t "\\b" ; go ~off:(i+1) ~len:0
| '\012' -> flush ~off ~len; write_string t "\\f" ; go ~off:(i+1) ~len:0
| '\n' -> flush ~off ~len; write_string t "\\n" ; go ~off:(i+1) ~len:0
| '\r' -> flush ~off ~len; write_string t "\\r" ; go ~off:(i+1) ~len:0
| '\t' -> flush ~off ~len; write_string t "\\t" ; go ~off:(i+1) ~len:0
| '\\' -> flush ~off ~len; write_string t "\\\\"; go ~off:(i+1) ~len:0
| _ -> go ~off ~len:(len + 1)
in
write_char t '"';
go ~off:0 ~len:0;
write_char t '"'
let serialize_number t f =
let f = string_of_float f in
let len = String.length f in
let len = if String.get f (len - 1) = '.' then len - 1 else len in
write_string t ~len f
let rec serialize_json t json =
match json with
| `Null -> write_string t "null"
| `True -> write_string t "true"
| `False -> write_string t "false"
| `Number n -> serialize_number t n
| `String s -> serialize_string t s
| `Object [] -> write_string t "{}"
| `Object ((k, v)::kvs) ->
write_char t '{';
serialize_kv t k v;
List.iter (fun (k, v) ->
write_char t ',';
serialize_kv t k v)
kvs;
write_char t '}';
| `Array [] -> write_string t "[]"
| `Array (v::vs) ->
write_char t '[';
serialize_json t v;
List.iter (fun v ->
write_char t ',';
serialize_json t v)
vs;
write_char t ']'
and serialize_kv t k v =
serialize_string t k;
write_char t ':';
serialize_json t v