-
Notifications
You must be signed in to change notification settings - Fork 2
/
ConvertJson.elm
300 lines (221 loc) · 7.65 KB
/
ConvertJson.elm
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
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
module ConvertJson where
import Json.Encode as Enc exposing (encode, object, string)
import Json.Decode as Dec exposing (..)
import Model exposing (..)
import Char exposing (toCode)
import String exposing (toList)
import List exposing (head)
import Woot exposing (wToString)
import Debug
import Result exposing (..)
wUpdateDecoder : Decoder WUpdate
wUpdateDecoder =
oneOf
[
siteIdDecoder
, insertDeleteDecoder
]
insertDeleteDecoder : Decoder WUpdate
insertDeleteDecoder =
object6 (\t id ch vis next prev ->
if t == "Insert" then
Insert (wCharMaker id ch vis next prev)
else
Delete (wCharMaker id ch vis next prev))
("type" := Dec.string)
decodeId
("ch" := Dec.string)
("vis" := Dec.int)
decNext
decPrev
wDeleteDecoder : Decoder WUpdate
wDeleteDecoder =
object5 (\id ch vis next prev -> Delete (wCharMaker id ch vis next prev))
decodeId
("ch" := Dec.string)
("vis" := Dec.int)
decNext
decPrev
siteIdDecoder : Decoder WUpdate
siteIdDecoder = object1 (\id -> SiteId id) ("siteId" := int)
wCharMaker : (Int, Int) -> String -> Int -> (Int, Int) -> (Int, Int) -> WChar
wCharMaker id strCh vis next prev =
{id = id, ch = toChar strCh, vis = vis, next = next, prev = prev}
jsonToWUpdates : String -> List WUpdate
jsonToWUpdates str =
case Dec.decodeString (Dec.list wUpdateDecoder) str of
Ok x -> x
Err err -> [NoUpdate]
jsonObjToWUpdate : String -> WUpdate
jsonObjToWUpdate str =
case Dec.decodeString ("type" := Dec.string) str of
Ok x -> decodeWUpdate x str
Err error -> NoUpdate
jsonToTUpdate : String -> TUpdate
jsonToTUpdate str =
case Dec.decodeString ("type" := Dec.string) str of
Ok x -> decodeTUpdate x str
Err error -> NoTUpdate
decodeId = ("id" := Dec.tuple2 (,) int int)
decVis = ("vis" := Dec.int)
decNext = ("next" := Dec.tuple2 (,) int int)
decPrev = ("prev" := Dec.tuple2 (,) int int)
decCh = ("ch" := Dec.string)
toChar : String -> Char
toChar str =
case head (toList str) of
Just l -> l
_ -> '$'
decodeTUpdate : String -> String -> TUpdate
decodeTUpdate typeStr str =
if typeStr == "Insert" then
case Dec.decodeString tInsertDecoder str of
Ok x -> x
Err error -> NoTUpdate
else if typeStr == "Delete" then
case Dec.decodeString tDeleteDecoder str of
Ok x -> x
Err error -> NoTUpdate
else if typeStr == "InsertString" then
case Dec.decodeString tInsertStringDecoder str of
Ok x -> x
Err error -> NoTUpdate
else if typeStr == "DeleteString" then
case Dec.decodeString tDeleteStringDecoder str of
Ok x -> x
Err error -> NoTUpdate
else if typeStr == "RequestWString" then
RequestWString
else NoTUpdate
tInsertStringDecoder : Decoder TUpdate
tInsertStringDecoder =
object2
(\str cp -> IS str cp )
("str" := Dec.string) decCP
tDeleteStringDecoder : Decoder TUpdate
tDeleteStringDecoder =
object2
(\str cp -> DS str cp )
("str" := Dec.string) decCP
tInsertDecoder : Decoder TUpdate
tInsertDecoder =
object3
(\ ch cp siteId -> I (toChar ch) cp siteId)
decCh decCP ("siteId" := Dec.int)
tDeleteDecoder : Decoder TUpdate
tDeleteDecoder =
object2 (\ ch cp -> D (toChar ch) cp) ("ch" := Dec.string) ("cp" := Dec.int)
decCP = ("cp" := Dec.int)
decodeWUpdate : String -> String -> WUpdate
decodeWUpdate typeStr str =
if typeStr == "Insert" then decodeWInsert str
else if typeStr == "Delete" then decodeWDelete str
else if typeStr == "SiteId" then decodeWSiteId str
else if typeStr == "CurrWString" then decodeCurrWString str
else NoUpdate
decodeWInsert : String -> WUpdate
decodeWInsert str =
case Dec.decodeString wCharDecoder str of
Ok wCh -> Insert wCh
Err e -> NoUpdate
decodeWDelete : String -> WUpdate
decodeWDelete str =
case Dec.decodeString wCharDecoder str of
Ok wCh -> Delete wCh
Err e -> NoUpdate
decodeWSiteId : String -> WUpdate
decodeWSiteId str =
case Dec.decodeString wSiteIdDecoder str of
Ok siteId -> SiteId siteId
Err e -> NoUpdate
decodeCurrWString : String -> WUpdate
decodeCurrWString str =
case Dec.decodeString wStringDecoder str of
Ok wString -> CurrWString wString (wToString wString)
Err e -> NoUpdate
wStringDecoder : Decoder WString
wStringDecoder =
Dec.list (wCharDecoder)
wCharDecoder : Decoder WChar
wCharDecoder =
Dec.object5
(\ id next prev vis chr -> WChar id next prev vis (toChar chr))
decodeId decNext decPrev decVis decCh
wSiteIdDecoder : Decoder Int
wSiteIdDecoder = "siteId" := int
-- - - - - - - - - - - - - --
tUpdatesToJson : List TUpdate -> String
tUpdatesToJson tUpdates =
let
tUpdateListValue = Enc.list (List.map encodeTUpdate tUpdates)
in
encode 2 tUpdateListValue
tUpdateToJson : TUpdate -> String
tUpdateToJson tUpd =
let
tUpValue = encodeTUpdate tUpd
in
encode 2 tUpValue
wUpdatesToJson : List WUpdate -> String
wUpdatesToJson wUpdates =
let
wUpdateListValue = Enc.list (List.map encodeWUpdate wUpdates)
in
encode 2 wUpdateListValue
wUpdateToJson : WUpdate -> String
wUpdateToJson wUpdate =
let
wUpValue = encodeWUpdate wUpdate
in
encode 2 wUpValue
stringUpdateToJson : String -> String
stringUpdateToJson str =
let
strValue = encodeStringUpdate str
in
encode 2 strValue
encodeWInsert wCh =
object [("id", Enc.string wCh.id)
, ("ch", Enc.string (String.fromChar wCh.ch))
, ("next", Enc.string wCh.next)
, ("prev", Enc.string wCh.prev)
, ("vis", Enc.int wCh.vis)]
encodeStringUpdate : String -> Value
encodeStringUpdate str =
object [("type", Enc.string "StringUpdate"), ("string", Enc.string str)]
encodeWUpdate : WUpdate -> Value
encodeWUpdate wUp =
case wUp of
Insert wCh -> object (("type", Enc.string "Insert") :: wCharToJsonList wCh)
Delete wCh -> object (("type", Enc.string "Delete") :: wCharToJsonList wCh)
CurrWString wString str -> object [("type", Enc.string "CurrWString")
, ("WString", Enc.list (List.map (\wCh -> object (wCharToJsonList wCh)) wString))
, ("String", Enc.string str)]
_ -> object [("type", Enc.string "NoUpdate")]
wCharToJsonList : WChar -> List (String, Value)
wCharToJsonList wCh =
[ ("id", Enc.list [Enc.int (fst wCh.id), Enc.int (snd wCh.id)])
, ("prev", Enc.list [Enc.int (fst wCh.prev), Enc.int (snd wCh.prev)])
, ("next", Enc.list [Enc.int (fst wCh.next), Enc.int (snd wCh.next)])
, ("vis", Enc.int wCh.vis)
, ("ch", Enc.string (String.fromChar wCh.ch))
]
tDelToJsonList : Char -> Int -> List (String, Value)
tDelToJsonList ch index =
[
("ch", Enc.string (String.fromChar ch))
, ("index", Enc.int index)
]
tInsertToJsonList : Char -> Int -> Int -> List (String, Value)
tInsertToJsonList ch index siteId =
[
("ch", Enc.string (String.fromChar ch))
, ("index", Enc.int index)
, ("siteId", Enc.int siteId)
]
encodeTUpdate : TUpdate -> Value
encodeTUpdate tUp =
case tUp of
I ch index siteId -> object (("type", Enc.string "typingInsert") :: tInsertToJsonList ch index siteId)
D ch index -> object (("type", Enc.string "typingDelete") :: tDelToJsonList ch index)
_ -> object [("type", Enc.string "typingNoUpdate")]