@@ -40,7 +40,6 @@ import Foreign.Object.ST as FOST
40
40
import Prim.Row as Row
41
41
import Record as Record
42
42
import Type.Proxy (Proxy (..))
43
- import Unsafe.Coerce (unsafeCoerce )
44
43
45
44
-- | A helper for defining JSON codecs for "enum" sum types, where every
46
45
-- | constructor is nullary, and the type will be encoded as a string.
@@ -109,6 +108,8 @@ data Encoding
109
108
, omitEmptyArguments ∷ Boolean
110
109
, unwrapSingleArguments ∷ Boolean
111
110
}
111
+ | EncodeUntagged
112
+ { unwrapSingleArguments ∷ Boolean }
112
113
113
114
defaultEncoding ∷ Encoding
114
115
defaultEncoding = EncodeTagValue
@@ -149,7 +150,7 @@ instance gCasesConstructorNoArgs ∷
149
150
let
150
151
name = reflectSymbol @name Proxy ∷ String
151
152
in
152
- encodeCase encoding name []
153
+ encodeSumCase encoding name []
153
154
154
155
gCasesDecode ∷ Encoding → Record r → Json → Either JsonDecodeError (Constructor name NoArguments )
155
156
gCasesDecode encoding _ json = do
@@ -169,7 +170,7 @@ else instance gCasesConstructorSingleArg ∷
169
170
codec = Record .get (Proxy @name) r ∷ JsonCodec a
170
171
name = reflectSymbol @name Proxy ∷ String
171
172
in
172
- encodeCase encoding name [ CA .encode codec x ]
173
+ encodeSumCase encoding name [ CA .encode codec x ]
173
174
174
175
gCasesDecode ∷ Encoding → Record r → Json → Either JsonDecodeError (Constructor name (Argument a ))
175
176
gCasesDecode encoding r json = do
@@ -193,7 +194,7 @@ else instance gCasesConstructorManyArgs ∷
193
194
name = reflectSymbol @name Proxy ∷ String
194
195
jsons = gFieldsEncode encoding codecs rep ∷ Array Json
195
196
in
196
- encodeCase encoding name jsons
197
+ encodeSumCase encoding name jsons
197
198
198
199
gCasesDecode ∷ Encoding → Record r → Json → Either JsonDecodeError (Constructor name args )
199
200
gCasesDecode encoding r json = do
@@ -292,9 +293,53 @@ checkTag tagKey obj expectedTag = do
292
293
$ throwError
293
294
$ TypeMismatch (" Expecting tag `" <> expectedTag <> " `, got `" <> tag <> " `" )
294
295
296
+ parseNoFields ∷ Encoding → Json → String → Either JsonDecodeError Unit
297
+ parseNoFields encoding json expectedTag =
298
+ case encoding of
299
+ EncodeCtorAsTag {} → do
300
+ obj ← CA .decode jobject json
301
+ val ←
302
+ ( Obj .lookup expectedTag obj # note (TypeMismatch (" Expecting a property `" <> expectedTag <> " `" ))
303
+ ) ∷ _ Json
304
+ fields ← CA .decode CA .jarray val ∷ _ (Array Json )
305
+ when (fields /= [] )
306
+ $ throwError
307
+ $ TypeMismatch " Expecting an empty array"
308
+
309
+ EncodeTagValue { tagKey, valuesKey, omitEmptyArguments } → do
310
+ obj ← CA .decode jobject json
311
+ checkTag tagKey obj expectedTag
312
+ when (not omitEmptyArguments) do
313
+ val ←
314
+ ( Obj .lookup valuesKey obj
315
+ # note (TypeMismatch (" Expecting a value property `" <> valuesKey <> " `" ))
316
+ ) ∷ _ Json
317
+ fields ← CA .decode CA .jarray val ∷ _ (Array Json )
318
+ when (fields /= [] )
319
+ $ throwError
320
+ $ TypeMismatch " Expecting an empty array"
321
+
322
+ EncodeUntagged {} → do
323
+ fields ← CA .decode CA .jarray json ∷ _ (Array Json )
324
+ when (fields /= [] )
325
+ $ throwError
326
+ $ TypeMismatch " Expecting an empty array"
327
+
295
328
parseSingleField ∷ Encoding → Json → String → Either JsonDecodeError Json
296
329
parseSingleField encoding json expectedTag = case encoding of
297
- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
330
+ EncodeCtorAsTag { unwrapSingleArguments } → do
331
+ obj ← CA .decode jobject json
332
+ val ←
333
+ ( Obj .lookup expectedTag obj # note (TypeMismatch (" Expecting a property `" <> expectedTag <> " `" ))
334
+ ) ∷ _ Json
335
+ if unwrapSingleArguments then
336
+ pure val
337
+ else do
338
+ fields ← CA .decode CA .jarray val
339
+ case fields of
340
+ [ head ] → pure head
341
+ _ → throwError $ TypeMismatch " Expecting exactly one element"
342
+
298
343
EncodeTagValue { tagKey, valuesKey, unwrapSingleArguments } → do
299
344
obj ← CA .decode jobject json
300
345
checkTag tagKey obj expectedTag
@@ -310,28 +355,25 @@ parseSingleField encoding json expectedTag = case encoding of
310
355
[ head ] → pure head
311
356
_ → throwError $ TypeMismatch " Expecting exactly one element"
312
357
313
- parseNoFields ∷ Encoding → Json → String → Either JsonDecodeError Unit
314
- parseNoFields encoding json expectedTag =
315
- case encoding of
316
- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
317
- EncodeTagValue { tagKey, valuesKey, omitEmptyArguments } →
318
- do
319
- obj ← CA .decode jobject json
320
- checkTag tagKey obj expectedTag
321
- when (not omitEmptyArguments) do
322
- val ←
323
- ( Obj .lookup valuesKey obj
324
- # note (TypeMismatch (" Expecting a value property `" <> valuesKey <> " `" ))
325
- ) ∷ _ Json
326
- fields ← CA .decode CA .jarray val ∷ _ (Array Json )
327
- when (fields /= [] )
328
- $ throwError
329
- $ TypeMismatch " Expecting an empty array"
358
+ EncodeUntagged { unwrapSingleArguments } → do
359
+ if unwrapSingleArguments then
360
+ pure json
361
+ else do
362
+ fields ← CA .decode CA .jarray json
363
+ case fields of
364
+ [ head ] → pure head
365
+ _ → throwError $ TypeMismatch " Expecting exactly one element"
330
366
331
367
parseManyFields ∷ Encoding → Json → String → Either JsonDecodeError (Array Json )
332
368
parseManyFields encoding json expectedTag =
333
369
case encoding of
334
- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
370
+ EncodeCtorAsTag {} → do
371
+ obj ← CA .decode jobject json
372
+ val ←
373
+ ( Obj .lookup expectedTag obj # note (TypeMismatch (" Expecting a property `" <> expectedTag <> " `" ))
374
+ ) ∷ _ Json
375
+ CA .decode CA .jarray val
376
+
335
377
EncodeTagValue { tagKey, valuesKey } → do
336
378
obj ← CA .decode jobject json
337
379
checkTag tagKey obj expectedTag
@@ -341,10 +383,23 @@ parseManyFields encoding json expectedTag =
341
383
) ∷ _ Json
342
384
CA .decode CA .jarray val
343
385
344
- encodeCase ∷ Encoding → String → Array Json → Json
345
- encodeCase encoding tag jsons =
386
+ EncodeUntagged {} →
387
+ CA .decode CA .jarray json
388
+
389
+ encodeSumCase ∷ Encoding → String → Array Json → Json
390
+ encodeSumCase encoding tag jsons =
346
391
case encoding of
347
- EncodeCtorAsTag { unwrapSingleArguments } → unsafeCoerce " todo"
392
+ EncodeCtorAsTag { unwrapSingleArguments } →
393
+ let
394
+ val = case jsons of
395
+ [] → CA .encode CA .jarray []
396
+ [ json ] | unwrapSingleArguments → json
397
+ manyJsons → CA .encode CA .jarray manyJsons
398
+ in
399
+ encode jobject $ Obj .fromFoldable
400
+ [ tag /\ val
401
+ ]
402
+
348
403
EncodeTagValue { tagKey, valuesKey, unwrapSingleArguments, omitEmptyArguments } →
349
404
let
350
405
tagEntry =
@@ -356,4 +411,10 @@ encodeCase encoding tag jsons =
356
411
manyJsons → Just (valuesKey /\ CA .encode CA .jarray manyJsons)
357
412
in
358
413
encode jobject $ Obj .fromFoldable $ catMaybes
359
- [ tagEntry, valEntry ]
414
+ [ tagEntry, valEntry ]
415
+
416
+ EncodeUntagged { unwrapSingleArguments } →
417
+ case jsons of
418
+ [] → CA .encode CA .jarray []
419
+ [ json ] | unwrapSingleArguments → json
420
+ manyJsons → CA .encode CA .jarray manyJsons
0 commit comments