1
0
mirror of https://github.com/hasura/graphql-engine.git synced 2024-12-17 20:41:49 +03:00
graphql-engine/server/src-lib/Hasura/EncJSON.hs
Vamshi Surabhi 24c0643a6d
Use ByteString to cache introspection response, closes ()
If we store it as EncJSON, we still need to render it to ByteString
for every request which will result in higher CPU usage
2019-04-18 17:45:07 +05:30

89 lines
2.3 KiB
Haskell

-- A module for representing encoded json
-- and efficient operations to construct them
module Hasura.EncJSON
( EncJSON
, encJFromBuilder
, encJToLBS
, encJToBS
, encJFromJValue
, encJFromChar
, encJFromText
, encJFromBS
, encJFromLBS
, encJFromList
, encJFromAssocList
) where
import Hasura.Prelude
import qualified Data.Aeson as J
import qualified Data.ByteString as B
import qualified Data.ByteString.Builder as BB
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text.Encoding as TE
import qualified Database.PG.Query as Q
-- encoded json
-- TODO: can be improved with gadts capturing bytestring, lazybytestring
-- and builder
newtype EncJSON
= EncJSON { unEncJSON :: BB.Builder }
deriving (Semigroup, Monoid, IsString)
instance Q.FromCol EncJSON where
fromCol = fmap encJFromBS . Q.fromCol
encJToLBS :: EncJSON -> BL.ByteString
encJToLBS = BB.toLazyByteString . unEncJSON
{-# INLINE encJToLBS #-}
encJToBS :: EncJSON -> B.ByteString
encJToBS = BL.toStrict . encJToLBS
{-# INLINE encJToBS #-}
encJFromBuilder :: BB.Builder -> EncJSON
encJFromBuilder = EncJSON
{-# INLINE encJFromBuilder #-}
encJFromBS :: B.ByteString -> EncJSON
encJFromBS = EncJSON . BB.byteString
{-# INLINE encJFromBS #-}
encJFromLBS :: BL.ByteString -> EncJSON
encJFromLBS = EncJSON . BB.lazyByteString
{-# INLINE encJFromLBS #-}
encJFromJValue :: J.ToJSON a => a -> EncJSON
encJFromJValue = encJFromBuilder . J.fromEncoding . J.toEncoding
{-# INLINE encJFromJValue #-}
encJFromChar :: Char -> EncJSON
encJFromChar = EncJSON . BB.charUtf8
{-# INLINE encJFromChar #-}
encJFromText :: Text -> EncJSON
encJFromText = encJFromBS . TE.encodeUtf8
{-# INLINE encJFromText #-}
encJFromList :: [EncJSON] -> EncJSON
encJFromList = \case
[] -> "[]"
x:xs -> encJFromChar '['
<> x
<> foldr go (encJFromChar ']') xs
where go v b = encJFromChar ',' <> v <> b
-- from association list
encJFromAssocList :: [(Text, EncJSON)] -> EncJSON
encJFromAssocList = \case
[] -> "{}"
x:xs -> encJFromChar '{'
<> builder' x
<> foldr go (encJFromChar '}') xs
where
go v b = encJFromChar ',' <> builder' v <> b
-- builds "key":value from (key,value)
builder' (t, v) =
encJFromChar '"' <> encJFromText t <> encJFromText "\":" <> v