Skip to content

Commit 5face5e

Browse files
authored
Merge pull request #8 from natefaubion/variant-codec
Variant codec from record of codecs
2 parents 3e51d19 + 7482a18 commit 5face5e

File tree

3 files changed

+62
-2
lines changed

3 files changed

+62
-2
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
"purescript-argonaut-core": "^3.1.0",
2020
"purescript-codec": "^2.0.0",
2121
"purescript-generics-rep": "^5.1.0",
22-
"purescript-variant": "^1.1.0",
22+
"purescript-variant": "^3.2.0",
2323
"purescript-typelevel-prelude": "^2.4.0",
2424
"purescript-record": "^0.2.0",
2525
"purescript-type-equality": "^2.1.0"

src/Data/Codec/Argonaut/Variant.purs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ import Data.Codec.Argonaut (JsonCodec, JsonDecodeError(..), decode, encode, jobj
1010
import Data.Either (Either(..))
1111
import Data.Newtype (un)
1212
import Data.Profunctor.Star (Star(..))
13+
import Data.Record as Rec
1314
import Data.StrMap as SM
1415
import Data.StrMap.ST as SMST
15-
import Data.Symbol (class IsSymbol, reflectSymbol)
16+
import Data.Symbol (class IsSymbol, reflectSymbol, SProxy(..))
1617
import Data.Tuple (Tuple(..))
1718
import Data.Variant (SProxy, Variant, case_, inj, on)
19+
import Type.Equality as TE
20+
import Type.Row as R
1821
import Unsafe.Coerce (unsafeCoerce)
1922

2023
variant JsonCodec (Variant ())
@@ -57,3 +60,33 @@ variantCase proxy eacodec (GCodec dec enc) = GCodec dec' enc'
5760

5861
coerceR Variant r Variant r'
5962
coerceR = unsafeCoerce
63+
64+
class VariantCodec (rlR.RowList) (ri ∷ # Type) (ro ∷ # Type) | rl ri ro where
65+
variantCodec R.RLProxy rl Record ri JsonCodec (Variant ro)
66+
67+
instance variantCodecNilVariantCodec R.Nil () () where
68+
variantCodec _ _ = variant
69+
70+
instance variantCodecCons
71+
( VariantCodec rs ri' ro'
72+
, RowCons sym (Either a (JsonCodec a)) ri' ri
73+
, RowCons sym a ro' ro
74+
, IsSymbol sym
75+
, TE.TypeEquals co (Either a (JsonCodec a))
76+
) VariantCodec (R.Cons sym co rs) ri ro where
77+
variantCodec _ codecs =
78+
variantCase (SProxy SProxy sym) codec tail
79+
where
80+
codec Either a (JsonCodec a)
81+
codec = TE.from (Rec.get (SProxy SProxy sym) codecs)
82+
83+
tail JsonCodec (Variant ro')
84+
tail = variantCodec (R.RLProxy R.RLProxy rs) ((unsafeCoerce Record ri Record ri') codecs)
85+
86+
variantMatch
87+
rl ri ro
88+
. R.RowToList ri rl
89+
VariantCodec rl ri ro
90+
Record ri
91+
JsonCodec (Variant ro)
92+
variantMatch = variantCodec (R.RLProxy R.RLProxy rl)

test/Test/Variant.purs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ module Test.Variant where
33
import Prelude
44

55
import Control.Monad.Eff.Console (log)
6+
import Control.Monad.Gen (chooseBool, chooseInt)
67
import Control.Monad.Gen.Common as GenC
78
import Data.Codec.Argonaut.Common as JA
89
import Data.Codec.Argonaut.Variant as JAV
@@ -13,8 +14,15 @@ import Data.String.Gen (genAsciiString)
1314
import Data.Symbol (SProxy(..))
1415
import Data.Variant as V
1516
import Test.QuickCheck (QC, quickCheck)
17+
import Test.QuickCheck.Gen (Gen)
1618
import Test.Util (genInt, propCodec)
1719

20+
type TestVariant = V.Variant
21+
( a Int
22+
, b String
23+
, c Maybe Boolean
24+
)
25+
1826
main :: QC () Unit
1927
main = do
2028
log "Checking Maybe-variant codec"
@@ -29,6 +37,10 @@ main = do
2937
(GenC.genEither genAsciiString genInt)
3038
(codecEither JA.string JA.int)
3139

40+
log "Checking variant codec"
41+
quickCheck $
42+
propCodec genVariant codecVariant
43+
3244
codecMaybe a. JA.JsonCodec a JA.JsonCodec (Maybe a)
3345
codecMaybe codecA =
3446
dimap toVariant fromVariant
@@ -60,3 +72,18 @@ codecEither codecA codecB =
6072
# V.on _Right Right
6173
_Left = SProxy SProxy "left"
6274
_Right = SProxy SProxy "right"
75+
76+
genVariant Gen TestVariant
77+
genVariant = do
78+
tag ← chooseInt 1 3
79+
case tag of
80+
1V.inj (SProxy SProxy "a") <$> genInt
81+
2V.inj (SProxy SProxy "b") <$> genAsciiString
82+
_ → V.inj (SProxy SProxy "c") <$> GenC.genMaybe chooseBool
83+
84+
codecVariant JA.JsonCodec TestVariant
85+
codecVariant = JAV.variantMatch
86+
{ a: Right JA.int
87+
, b: Right JA.string
88+
, c: Right (JA.maybe JA.boolean)
89+
}

0 commit comments

Comments
 (0)