{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE QuasiQuotes #-}
module Json.Enc where
import Data.Aeson (Encoding, Value (..))
import Data.Aeson qualified as Json
import Data.Aeson.Encode.Pretty qualified as Aeson.Pretty
import Data.Aeson.Encoding qualified as AesonEnc
import Data.Aeson.Encoding qualified as Json.Enc
import Data.Aeson.Encoding qualified as Json.Encoding
import Data.Aeson.Key qualified as Key
import Data.Aeson.KeyMap (KeyMap)
import Data.Aeson.KeyMap qualified as KeyMap
import Data.ByteString.Base64 qualified as Base64
import Data.ByteString.Lazy qualified as LazyBytes
import Data.Containers.ListUtils (nubOrdOn)
import Data.Int (Int64)
import Data.List qualified as List
import Data.Map.Strict qualified as Map
import Data.Scientific
import Data.String (IsString (fromString))
import Data.Text.Lazy qualified as Lazy
import Data.Text.Lazy.Builder qualified as Text.Builder
import Data.Time qualified as Time
import Data.Time.Format.ISO8601 qualified as ISO8601
import GHC.TypeLits (KnownSymbol, Symbol, symbolVal)
import PossehlAnalyticsPrelude
newtype Enc = Enc {Enc -> Encoding
unEnc :: Encoding}
deriving (Integer -> Enc
Enc -> Enc
Enc -> Enc -> Enc
forall a.
(a -> a -> a)
-> (a -> a -> a)
-> (a -> a -> a)
-> (a -> a)
-> (a -> a)
-> (a -> a)
-> (Integer -> a)
-> Num a
fromInteger :: Integer -> Enc
$cfromInteger :: Integer -> Enc
signum :: Enc -> Enc
$csignum :: Enc -> Enc
abs :: Enc -> Enc
$cabs :: Enc -> Enc
negate :: Enc -> Enc
$cnegate :: Enc -> Enc
* :: Enc -> Enc -> Enc
$c* :: Enc -> Enc -> Enc
- :: Enc -> Enc -> Enc
$c- :: Enc -> Enc -> Enc
+ :: Enc -> Enc -> Enc
$c+ :: Enc -> Enc -> Enc
Num, Num Enc
Rational -> Enc
Enc -> Enc
Enc -> Enc -> Enc
forall a.
Num a
-> (a -> a -> a) -> (a -> a) -> (Rational -> a) -> Fractional a
fromRational :: Rational -> Enc
$cfromRational :: Rational -> Enc
recip :: Enc -> Enc
$crecip :: Enc -> Enc
/ :: Enc -> Enc -> Enc
$c/ :: Enc -> Enc -> Enc
Fractional) via (NumLiteralOnly "Enc" Enc)
instance Show Enc where
show :: Enc -> String
show Enc
e = Enc
e.unEnc forall a b. a -> (a -> b) -> b
& forall a. Encoding' a -> ByteString
Json.Encoding.encodingToLazyByteString forall a b. a -> (a -> b) -> b
& ByteString -> Text
bytesToTextUtf8UnsafeLazy forall a b. a -> (a -> b) -> b
& forall a. Show a => a -> String
show
instance IsString Enc where
fromString :: String -> Enc
fromString = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. String -> Encoding' a
AesonEnc.string
instance IntegerLiteral Enc where
integerLiteral :: Integer -> Enc
integerLiteral = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Encoding
AesonEnc.integer
instance RationalLiteral Enc where
rationalLiteral :: Rational -> Enc
rationalLiteral Rational
r = Encoding -> Enc
Enc forall a b. (a -> b) -> a -> b
$ Scientific -> Encoding
AesonEnc.scientific (Rational
r forall a b. a -> (a -> b) -> b
& forall a. Fractional a => Rational -> a
fromRational @Scientific)
encToBytesUtf8 :: Enc -> ByteString
encToBytesUtf8 :: Enc -> ByteString
encToBytesUtf8 Enc
enc = Enc
enc forall a b. a -> (a -> b) -> b
& Enc -> ByteString
encToBytesUtf8Lazy forall a b. a -> (a -> b) -> b
& ByteString -> ByteString
toStrictBytes
encToBytesUtf8Lazy :: Enc -> LazyBytes.ByteString
encToBytesUtf8Lazy :: Enc -> ByteString
encToBytesUtf8Lazy Enc
enc = Enc
enc.unEnc forall a b. a -> (a -> b) -> b
& forall a. Encoding' a -> ByteString
Json.Enc.encodingToLazyByteString
encToTextPretty :: Enc -> Text
encToTextPretty :: Enc -> Text
encToTextPretty Enc
enc =
Enc
enc
forall a b. a -> (a -> b) -> b
& Enc -> Text
encToTextPrettyLazy
forall a b. a -> (a -> b) -> b
& Text -> Text
toStrict
encToTextPrettyLazy :: Enc -> Lazy.Text
encToTextPrettyLazy :: Enc -> Text
encToTextPrettyLazy Enc
enc =
Enc
enc
forall a b. a -> (a -> b) -> b
& Enc -> ByteString
encToBytesUtf8Lazy
forall a b. a -> (a -> b) -> b
& forall a. FromJSON a => ByteString -> Maybe a
Json.decode @Json.Value
forall a b. a -> (a -> b) -> b
& forall err a. err -> Maybe a -> Either err a
annotate Error
"the json parser can’t parse json encodings??"
forall a b. a -> (a -> b) -> b
& forall a. HasCallStack => Either Error a -> a
unwrapError
forall a b. a -> (a -> b) -> b
& forall a. ToJSON a => a -> Builder
Aeson.Pretty.encodePrettyToTextBuilder
forall a b. a -> (a -> b) -> b
& Builder -> Text
Text.Builder.toLazyText
encoding :: Encoding -> Enc
encoding :: Encoding -> Enc
encoding = Encoding -> Enc
Enc
value :: Value -> Enc
value :: Value -> Enc
value = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Encoding
AesonEnc.value
emptyArray :: Enc
emptyArray :: Enc
emptyArray = Encoding -> Enc
Enc Encoding
AesonEnc.emptyArray_
emptyObject :: Enc
emptyObject :: Enc
emptyObject = Encoding -> Enc
Enc Encoding
AesonEnc.emptyObject_
text :: Text -> Enc
text :: Text -> Enc
text = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Text -> Encoding' a
AesonEnc.text
lazyText :: Lazy.Text -> Enc
lazyText :: Text -> Enc
lazyText = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Text -> Encoding' a
AesonEnc.lazyText
base64Bytes :: ByteString -> Enc
base64Bytes :: ByteString -> Enc
base64Bytes = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Text -> Encoding' a
AesonEnc.text forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
bytesToTextUtf8Unsafe forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base64.encode
base64 :: Text -> Enc
base64 :: Text -> Enc
base64 = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Text -> Encoding' a
AesonEnc.text forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> Text
bytesToTextUtf8Unsafe forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
Base64.encode forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
textToBytesUtf8
string :: String -> Enc
string :: String -> Enc
string = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. String -> Encoding' a
AesonEnc.string
nullOr :: (a -> Enc) -> Maybe a -> Enc
nullOr :: forall a. (a -> Enc) -> Maybe a -> Enc
nullOr a -> Enc
inner = \case
Maybe a
Nothing -> Encoding -> Enc
Enc Encoding
AesonEnc.null_
Just a
a -> a -> Enc
inner a
a
list :: (a -> Enc) -> [a] -> Enc
list :: forall a. (a -> Enc) -> [a] -> Enc
list a -> Enc
f = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> Encoding) -> [a] -> Encoding
AesonEnc.list (\a
a -> (a -> Enc
f a
a).unEnc)
nonEmpty :: (a -> Enc) -> NonEmpty a -> Enc
nonEmpty :: forall a. (a -> Enc) -> NonEmpty a -> Enc
nonEmpty a -> Enc
f = forall a. (a -> Enc) -> [a] -> Enc
list a -> Enc
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList
object :: Foldable t => t (Text, Enc) -> Enc
object :: forall (t :: Type -> Type). Foldable t => t (Text, Enc) -> Enc
object t (Text, Enc)
m =
Encoding -> Enc
Enc forall a b. (a -> b) -> a -> b
$
forall k v m.
(k -> Encoding' Key)
-> (v -> Encoding)
-> (forall a. (k -> v -> a -> a) -> a -> m -> a)
-> m
-> Encoding
AesonEnc.dict
forall a. Text -> Encoding' a
AesonEnc.text
(\Enc
recEnc -> Enc
recEnc.unEnc)
(\Text -> Enc -> a -> a
f -> forall (t :: Type -> Type) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
List.foldr (\(Text
k, Enc
v) -> Text -> Enc -> a -> a
f Text
k Enc
v))
(forall b a. Ord b => (a -> b) -> [a] -> [a]
nubOrdOn forall a b. (a, b) -> a
fst forall a b. (a -> b) -> a -> b
$ forall (t :: Type -> Type) a. Foldable t => t a -> [a]
toList t (Text, Enc)
m)
data Choice = Choice Text Enc
choice :: (from -> Choice) -> from -> Enc
choice :: forall from. (from -> Choice) -> from -> Enc
choice from -> Choice
f from
from = case from -> Choice
f from
from of
Choice Text
key Enc
encA -> Text -> Enc -> Enc
singleChoice Text
key Enc
encA
singleChoice :: Text -> Enc -> Enc
singleChoice :: Text -> Enc -> Enc
singleChoice Text
key Enc
encA =
Encoding -> Enc
Enc forall a b. (a -> b) -> a -> b
$
Series -> Encoding
AesonEnc.pairs forall a b. (a -> b) -> a -> b
$
forall a. Monoid a => [a] -> a
mconcat
[ Key -> Encoding -> Series
AesonEnc.pair Key
"tag" (forall a. Text -> Encoding' a
AesonEnc.text Text
key),
Key -> Encoding -> Series
AesonEnc.pair Key
"value" Enc
encA.unEnc
]
map :: forall k v. (Coercible k Text) => (v -> Enc) -> Map k v -> Enc
map :: forall k v. Coercible k Text => (v -> Enc) -> Map k v -> Enc
map v -> Enc
valEnc Map k v
m =
Encoding -> Enc
Enc forall a b. (a -> b) -> a -> b
$
forall k v m.
(k -> Encoding' Key)
-> (v -> Encoding)
-> (forall a. (k -> v -> a -> a) -> a -> m -> a)
-> m
-> Encoding
AesonEnc.dict
(forall a. Text -> Encoding' a
AesonEnc.text forall b c a. (b -> c) -> (a -> b) -> a -> c
. coerce :: forall a b. Coercible a b => a -> b
coerce @k @Text)
(\v
v -> (v -> Enc
valEnc v
v).unEnc)
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey
Map k v
m
keyMap :: (v -> Enc) -> KeyMap v -> Enc
keyMap :: forall v. (v -> Enc) -> KeyMap v -> Enc
keyMap v -> Enc
valEnc KeyMap v
m =
Encoding -> Enc
Enc forall a b. (a -> b) -> a -> b
$
forall k v m.
(k -> Encoding' Key)
-> (v -> Encoding)
-> (forall a. (k -> v -> a -> a) -> a -> m -> a)
-> m
-> Encoding
AesonEnc.dict
(forall a. Text -> Encoding' a
AesonEnc.text forall b c a. (b -> c) -> (a -> b) -> a -> c
. Key -> Text
Key.toText)
(\v
v -> (v -> Enc
valEnc v
v).unEnc)
forall v a. (Key -> v -> a -> a) -> a -> KeyMap v -> a
KeyMap.foldrWithKey
KeyMap v
m
null :: Enc
null :: Enc
null = Encoding -> Enc
Enc Encoding
AesonEnc.null_
bool :: Bool -> Enc
bool :: Bool -> Enc
bool = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Encoding
AesonEnc.bool
integer :: Integer -> Enc
integer :: Integer -> Enc
integer = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> Encoding
AesonEnc.integer
scientific :: Scientific -> Enc
scientific :: Scientific -> Enc
scientific = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Scientific -> Encoding
AesonEnc.scientific
natural :: Natural -> Enc
natural :: Natural -> Enc
natural = Integer -> Enc
integer forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Integral a => a -> Integer
toInteger @Natural
int :: Int -> Enc
int :: Int -> Enc
int = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Encoding
AesonEnc.int
int64 :: Int64 -> Enc
int64 :: Int64 -> Enc
int64 = Encoding -> Enc
Enc forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> Encoding
AesonEnc.int64
utcTime :: Time.UTCTime -> Enc
utcTime :: UTCTime -> Enc
utcTime =
Text -> Enc
text forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
stringToText forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall t. ISO8601 t => t -> String
ISO8601.iso8601Show @Time.UTCTime
class IntegerLiteral a where
integerLiteral :: Integer -> a
class RationalLiteral a where
rationalLiteral :: Rational -> a
newtype NumLiteralOnly (sym :: Symbol) num = NumLiteralOnly num
instance (IntegerLiteral num, KnownSymbol sym) => Num (NumLiteralOnly sym num) where
fromInteger :: Integer -> NumLiteralOnly sym num
fromInteger = forall (sym :: Symbol) num. num -> NumLiteralOnly sym num
NumLiteralOnly forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IntegerLiteral a => Integer -> a
integerLiteral
+ :: NumLiteralOnly sym num
-> NumLiteralOnly sym num -> NumLiteralOnly sym num
(+) = forall a. HasCallStack => String -> a
error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to add (+) (NumLiteralOnly)|]
* :: NumLiteralOnly sym num
-> NumLiteralOnly sym num -> NumLiteralOnly sym num
(*) = forall a. HasCallStack => String -> a
error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to multiply (*) (NumLiteralOnly)|]
(-) = forall a. HasCallStack => String -> a
error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to subtract (-) (NumLiteralOnly)|]
abs :: NumLiteralOnly sym num -> NumLiteralOnly sym num
abs = forall a. HasCallStack => String -> a
error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to use `abs` (NumLiteralOnly)|]
signum :: NumLiteralOnly sym num -> NumLiteralOnly sym num
signum = forall a. HasCallStack => String -> a
error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to use `signum` (NumLiteralOnly)|]
instance (IntegerLiteral num, RationalLiteral num, KnownSymbol sym) => Fractional (NumLiteralOnly sym num) where
fromRational :: Rational -> NumLiteralOnly sym num
fromRational = forall (sym :: Symbol) num. num -> NumLiteralOnly sym num
NumLiteralOnly forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. RationalLiteral a => Rational -> a
rationalLiteral
recip :: NumLiteralOnly sym num -> NumLiteralOnly sym num
recip = forall a. HasCallStack => String -> a
error [fmt|Only use as rational literal allowed for {symbolVal (Proxy @sym)}, you tried to use `recip` (NumLiteralOnly)|]
/ :: NumLiteralOnly sym num
-> NumLiteralOnly sym num -> NumLiteralOnly sym num
(/) = forall a. HasCallStack => String -> a
error [fmt|Only use as numeric literal allowed for {symbolVal (Proxy @sym)}, you tried to divide (/) (NumLiteralOnly)|]