-
-
Notifications
You must be signed in to change notification settings - Fork 36
/
Editor_Json.re
123 lines (111 loc) · 3.63 KB
/
Editor_Json.re
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
open Editor_Types;
module V1 = {
module JsonDecode = {
open Json.Decode;
let blockDataDecoder: Js.Json.t => Block.blockData =
json => {
let kind = json |> field("kind", string);
let value = json |> field("value", string);
switch (kind) {
| "code" =>
B_Code({bc_value: value, bc_firstLineNumber: 1, bc_widgets: [||]})
| "text" => B_Text(value)
| _ => raise(Invalid_argument("Unexpected block type: " ++ kind))
};
};
let blockDecoder: Js.Json.t => Block.block =
json => {
b_id: json |> field("id", string),
b_data: json |> field("data", blockDataDecoder),
b_deleted:
json
|> optional(field("deleted", bool))
|> (
fun
| None => false
| Some(bool) => bool
),
};
let langDecoder: Js.Json.t => lang =
json => json |> string |> stringToLang;
external jsonIdentity: Js.Json.t => Js.Json.t = "%identity";
let internalBlockDecoder: Js.Json.t => Link.internalLink =
json => {
revision_at: json |> field("timestamp", jsonIdentity),
sketch_id: json |> field("id", string),
name: json |> field("name", string),
lang: json |> field("lang", langDecoder),
code: json |> field("code", string),
};
let linkDecoder: Js.Json.t => Link.link =
json => {
let kind = json |> field("kind", string);
switch (kind) {
| "internal" =>
Internal(json |> field("value", internalBlockDecoder))
| _ => External()
};
};
let decode: Js.Json.t => (lang, array(Link.link), array(Block.block)) =
json => (
json
|> optional(field("lang", langDecoder))
|> (
fun
| None => RE
| Some(lang) => lang
),
json
|> optional(field("links", array(linkDecoder)))
|> (
fun
| None => [||]
| Some(links) => links
),
json |> field("blocks", array(blockDecoder)),
);
};
module JsonEncode = {
open Json.Encode;
let mapToJsonArray: (array('a), 'a => Js.Json.t) => Js.Json.t =
(entities, encoder) =>
entities
->(Belt.Array.mapU((. entitity) => entitity |> encoder))
->jsonArray;
let blockDataEncoder: Block.blockData => Js.Json.t =
fun
| B_Code({bc_value}) =>
object_([("kind", string("code")), ("value", string(bc_value))])
| B_Text(value) =>
object_([("kind", string("text")), ("value", string(value))]);
let blockEncoder: Block.block => Js.Json.t =
({b_id, b_data, b_deleted}) =>
object_([
("id", string(b_id)),
("data", blockDataEncoder(b_data)),
("deleted", bool(b_deleted)),
]);
let linkDecoder: Link.link => Js.Json.t =
link =>
switch (link) {
| Internal(internalLink) =>
object_([
("sketch_id", string(internalLink.sketch_id)),
("name", string(internalLink.name)),
("lang", internalLink.lang |> langToString |> string),
("timestamp", internalLink.revision_at),
("code", string(internalLink.code)),
])
| External () => object_([])
};
let encode: (lang, array(Link.link), array(Block.block)) => Js.Json.t =
(lang, links, blocks) =>
object_([
("lang", lang |> langToString |> string),
("links", links->mapToJsonArray(linkDecoder)),
("blocks", blocks->mapToJsonArray(blockEncoder)),
]);
};
let decode = JsonDecode.decode;
let encode = JsonEncode.encode;
};