Skip to content

Commit 187f7dd

Browse files
committed
leios-trace-hs: actually add the new module files
1 parent 030c0b2 commit 187f7dd

File tree

4 files changed

+928
-0
lines changed

4 files changed

+928
-0
lines changed

leios-trace-hs/src/JSONCompat.hs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
{-# LANGUAGE AllowAmbiguousTypes #-}
2+
{-# LANGUAGE DataKinds #-}
3+
{-# LANGUAGE DerivingStrategies #-}
4+
{-# LANGUAGE FlexibleContexts #-}
5+
{-# LANGUAGE FlexibleInstances #-}
6+
{-# LANGUAGE RankNTypes #-}
7+
{-# LANGUAGE TypeApplications #-}
8+
9+
module JSONCompat where
10+
11+
import Data.Aeson.Key (fromString)
12+
import Data.Aeson.Types (FromJSON (..), KeyValue ((.=)), Object, Parser, ToJSON (..), (.!=), (.:), (.:?))
13+
import Data.Char (isUpper, toLower, toUpper)
14+
import Data.Default (Default (..))
15+
import GHC.Records (HasField (..))
16+
import GHC.TypeLits (KnownSymbol (..), SSymbol, fromSSymbol)
17+
18+
kebabToCamel :: String -> String
19+
kebabToCamel = go False
20+
where
21+
go _ [] = []
22+
go _ ('-' : cs) = go True cs
23+
go b (c : cs) = (if b then toUpper c else c) : go False cs
24+
25+
camelToKebab :: String -> String
26+
camelToKebab = go . lowerFirst
27+
where
28+
lowerFirst [] = []
29+
lowerFirst (c : cs) = toLower c : cs
30+
go (c : cs)
31+
| isUpper c = '-' : toLower c : go cs
32+
| otherwise = c : go cs
33+
go [] = []
34+
35+
newtype Getter r = Getter {unGetter :: forall f v e kv. SSymbol f -> (HasField f r v, KeyValue e kv, ToJSON v, Eq v) => r -> Maybe kv}
36+
37+
get :: forall fld obj e kv a. (KnownSymbol fld, HasField fld obj a, KeyValue e kv, ToJSON a, Eq a) => Getter obj -> obj -> Maybe kv
38+
get (Getter getter) = getter (symbolSing @fld)
39+
40+
always :: Getter r
41+
always = Getter $ \(fld :: SSymbol fld) obj ->
42+
let key = fromString (camelToKebab (fromSSymbol fld))
43+
val = getField @fld obj
44+
in Just (key .= val)
45+
46+
omitDefault :: Default r => Getter r
47+
omitDefault = Getter $ \(fld :: SSymbol fld) obj ->
48+
let key = fromString (camelToKebab (fromSSymbol fld))
49+
getFld = getField @fld
50+
val = getFld obj
51+
in if val == getFld def then Nothing else Just (key .= val)
52+
53+
parseFieldOrDefault :: forall obj fld a. (HasField fld obj a, Default obj, KnownSymbol fld, FromJSON a) => Object -> Parser a
54+
parseFieldOrDefault obj =
55+
obj .:? fromString (camelToKebab (fromSSymbol (symbolSing @fld))) .!= getField @fld (def :: obj)
56+
57+
parseField :: forall obj fld a. (HasField fld obj a, KnownSymbol fld, FromJSON a) => Object -> Parser a
58+
parseField obj = obj .: fromString (camelToKebab (fromSSymbol (symbolSing @fld)))

0 commit comments

Comments
 (0)