module Jsonifier
(
toByteString,
Json,
null,
bool,
intNumber,
wordNumber,
doubleNumber,
scientificNumber,
textString,
scientificString,
array,
object,
)
where
import Jsonifier.Prelude hiding (null, bool)
import PtrPoker.Poke (Poke)
import PtrPoker.Write (Write)
import qualified Jsonifier.Allocation as Allocation
import qualified Jsonifier.Poke as Poke
import qualified Jsonifier.Write as Write
import qualified PtrPoker.Poke as Poke
import qualified PtrPoker.Write as Write
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Internal as ByteString
{-# INLINE toByteString #-}
toByteString :: Json -> ByteString
toByteString =
Write.writeToByteString . coerce
newtype Json =
Json Write.Write
{-# INLINE write #-}
write :: Int -> Poke.Poke -> Json
write size poke =
Json (Write.Write size poke)
{-# INLINE null #-}
null :: Json
null =
write 4 Poke.null
{-# INLINE bool #-}
bool :: Bool -> Json
bool =
\ case
True ->
write 4 Poke.true
False ->
write 5 Poke.false
{-# INLINE intNumber #-}
intNumber :: Int -> Json
intNumber =
Json . Write.intAsciiDec
{-# INLINE wordNumber #-}
wordNumber :: Word -> Json
wordNumber =
Json . Write.wordAsciiDec
{-# INLINE doubleNumber #-}
doubleNumber :: Double -> Json
doubleNumber =
Json . Write.zeroNonRealDoubleAsciiDec
{-# INLINE scientificNumber #-}
scientificNumber :: Scientific -> Json
scientificNumber =
Json . Write.scientificAsciiDec
{-# INLINE textString #-}
textString :: Text -> Json
textString text =
let
allocation =
2 + Allocation.stringBody text
poke =
Poke.string text
in write allocation poke
{-# INLINE scientificString #-}
scientificString :: Scientific -> Json
scientificString =
Json . Write.scientificString
{-# INLINE array #-}
array :: Foldable f => f Json -> Json
array foldable =
write size poke
where
size =
foldr step finalize foldable 0 0
where
step (Json (Write.Write writeSize _)) next !count !size =
next (succ count) (writeSize + size)
finalize count size =
Allocation.array count size
poke =
Poke.Poke $
Poke.pokePtr Poke.openingSquareBracket >=>
foldr step finalize foldable True
where
step (Json (Write.Write _ poke)) next first =
if first
then
Poke.pokePtr poke >=>
next False
else
Poke.pokePtr Poke.comma >=>
Poke.pokePtr poke >=>
next False
finalize _ =
Poke.pokePtr Poke.closingSquareBracket
{-# INLINE object #-}
object :: Foldable f => f (Text, Json) -> Json
object f =
foldr step finalize f True 0 0 mempty
where
step (key, Json (Write.Write{..})) next first !size !allocation !poke =
if first
then
next False 1 rowAllocation rowPoke
else
next False (succ size) (allocation + rowAllocation)
(poke <> Poke.comma <> rowPoke)
where
rowAllocation =
Allocation.stringBody key +
writeSize
rowPoke =
Poke.objectRow key writePoke
finalize _ size contentsAllocation bodyPoke =
write allocation poke
where
allocation =
Allocation.object size contentsAllocation
poke =
Poke.openingCurlyBracket <> bodyPoke <> Poke.closingCurlyBracket