json-bytes-builder 0.3 → 0.4
raw patch · 16 files changed
+353/−348 lines, 16 files
Files
- demo/Main.hs +1/−1
- json-bytes-builder.cabal +8/−7
- library/JSONBytesBuilder/Builder.hs +1/−137
- library/JSONBytesBuilder/ByteString/BoundedPrims.hs +0/−72
- library/JSONBytesBuilder/ByteString/Builder.hs +17/−0
- library/JSONBytesBuilder/ByteString/Builders.hs +0/−66
- library/JSONBytesBuilder/ByteString/ByteString.hs +18/−0
- library/JSONBytesBuilder/ByteString/LazyByteString.hs +19/−0
- library/JSONBytesBuilder/Interpreters/ByteString.hs +0/−18
- library/JSONBytesBuilder/Interpreters/ByteStringBuilder.hs +0/−17
- library/JSONBytesBuilder/Interpreters/LazyByteString.hs +0/−19
- library/JSONBytesBuilder/Prelude.hs +0/−11
- library/JSONBytesBuilder/Private/Builder.hs +140/−0
- library/JSONBytesBuilder/Private/ByteString/BoundedPrim.hs +72/−0
- library/JSONBytesBuilder/Private/ByteString/Builder.hs +66/−0
- library/JSONBytesBuilder/Private/Prelude.hs +11/−0
demo/Main.hs view
@@ -4,7 +4,7 @@ import Data.ByteString (ByteString) import Data.Text (Text) import qualified JSONBytesBuilder.Builder as A-import qualified JSONBytesBuilder.Interpreters.ByteString as B+import qualified JSONBytesBuilder.ByteString.ByteString as B import qualified Data.ByteString.Char8 as C
json-bytes-builder.cabal view
@@ -1,7 +1,7 @@ name: json-bytes-builder version:- 0.3+ 0.4 synopsis: Direct-to-bytes JSON Builder description:@@ -47,14 +47,15 @@ default-language: Haskell2010 other-modules:- JSONBytesBuilder.Prelude- JSONBytesBuilder.ByteString.BoundedPrims- JSONBytesBuilder.ByteString.Builders+ JSONBytesBuilder.Private.Prelude+ JSONBytesBuilder.Private.ByteString.BoundedPrim+ JSONBytesBuilder.Private.ByteString.Builder+ JSONBytesBuilder.Private.Builder exposed-modules: JSONBytesBuilder.Builder- JSONBytesBuilder.Interpreters.ByteStringBuilder- JSONBytesBuilder.Interpreters.ByteString- JSONBytesBuilder.Interpreters.LazyByteString+ JSONBytesBuilder.ByteString.Builder+ JSONBytesBuilder.ByteString.ByteString+ JSONBytesBuilder.ByteString.LazyByteString build-depends: scientific == 0.3.*, text == 1.*,
library/JSONBytesBuilder/Builder.hs view
@@ -22,140 +22,4 @@ ) where -import JSONBytesBuilder.Prelude hiding (null)-import qualified Data.ByteString.Builder as A-import qualified JSONBytesBuilder.ByteString.Builders as E----- |--- Builder of any JSON literal.-newtype Literal =- Literal A.Builder---- |--- Builder of JSON Object rows.-newtype Rows =- Rows (Maybe A.Builder)--instance Monoid Rows where- {-# INLINE mempty #-}- mempty =- Rows Nothing- {-# INLINE mappend #-}- mappend =- \case- Rows (Just left) ->- \case- Rows (Just right) ->- Rows (Just (left <> A.char8 ',' <> right))- _ ->- Rows (Just left)- Rows Nothing ->- id---- |--- Builder of JSON Array elements.-newtype Elements =- Elements (Maybe A.Builder)--instance Monoid Elements where- {-# INLINE mempty #-}- mempty =- Elements Nothing- {-# INLINE mappend #-}- mappend =- \case- Elements (Just left) ->- \case- Elements (Just right) ->- Elements (Just (left <> A.char8 ',' <> right))- _ ->- Elements (Just left)- Elements Nothing ->- id---- |--- JSON Null literal.-{-# INLINE null #-}-null :: Literal-null =- Literal (inline E.null)---- |--- JSON Boolean literal from 'Bool'.-{-# INLINE boolean #-}-boolean :: Bool -> Literal-boolean =- Literal . inline E.boolean---- |--- JSON Number literal from 'Int'.-{-# INLINE number_int #-}-number_int :: Int -> Literal-number_int =- Literal . inline A.intDec---- |--- JSON Number literal from 'Integer'.-{-# INLINE number_integer #-}-number_integer :: Integer -> Literal-number_integer =- Literal . inline A.integerDec---- |--- JSON Number literal from 'Double'.-{-# INLINE number_double #-}-number_double :: Double -> Literal-number_double =- Literal . inline A.doubleDec---- |--- JSON Number literal from 'Scientific'.-{-# INLINE number_scientific #-}-number_scientific :: Scientific -> Literal-number_scientific =- Literal . inline E.scientific---- |--- JSON String literal from 'Text'.-{-# INLINE string #-}-string :: Text -> Literal-string =- Literal . inline E.string---- |--- JSON Object literal from the 'Rows' builder.-{-# INLINE object #-}-object :: Rows -> Literal-object (Rows x) =- Literal (maybe E.emptyObject (inline E.inCurlies) x)---- |--- JSON Array literal from the 'Elements' builder.-{-# INLINE array #-}-array :: Elements -> Literal-array (Elements x) =- Literal (maybe E.emptyArray (inline E.inSquarelies) x)---- |--- Rows builder from a key-value pair,--- where value is an already encoded JSON literal.--- --- Use the 'Rows' 'Monoid' instance--- to construct multi-row objects.-{-# INLINE row #-}-row :: Text -> Literal -> Rows-row key (Literal literal) =- Rows (Just (inline E.row key literal))---- |--- Elements builder from an element,--- which is an already encoded JSON literal.--- --- Use the 'Elements' 'Monoid' instance--- to construct multi-element arrays.-{-# INLINE element #-}-element :: Literal -> Elements-element (Literal literal) =- Elements (Just literal)-+import JSONBytesBuilder.Private.Builder
− library/JSONBytesBuilder/ByteString/BoundedPrims.hs
@@ -1,72 +0,0 @@-module JSONBytesBuilder.ByteString.BoundedPrims-where--import JSONBytesBuilder.Prelude-import Data.ByteString.Builder.Prim---{-# INLINE null #-}-null :: BoundedPrim ()-null =- ascii4 ('n', ('u', ('l', 'l')))--{-# INLINE boolean #-}-boolean :: BoundedPrim Bool-boolean =- condB id (ascii4 ('t', ('r', ('u', 'e')))) (ascii5 ('f', ('a', ('l', ('s', 'e')))))--{-# INLINE emptyArray #-}-emptyArray :: BoundedPrim ()-emptyArray =- ascii2 ('[', ']')--{-# INLINE emptyObject #-}-emptyObject :: BoundedPrim ()-emptyObject =- ascii2 ('{', '}')--{-# INLINE stringEncodedByte #-}-stringEncodedByte :: BoundedPrim Word8-stringEncodedByte =- condB (== (fromIntegral . ord) '\\') (ascii2 ('\\', '\\')) $- condB (== (fromIntegral . ord) '\"') (ascii2 ('\\', '"')) $- condB (>= (fromIntegral . ord) '\x20') (liftFixedToBounded word8) $- condB (== (fromIntegral . ord) '\n') (ascii2 ('\\', 'n')) $- condB (== (fromIntegral . ord) '\r') (ascii2 ('\\', 'r')) $- condB (== (fromIntegral . ord) '\t') (ascii2 ('\\', 't')) $- hexEncodedByte--{-# INLINE hexEncodedByte #-}-hexEncodedByte :: BoundedPrim Word8-hexEncodedByte =- liftFixedToBounded ((\c -> ('\\', ('u', fromIntegral c))) >$< char8 >*< char8 >*< word16HexFixed)--{-# INLINE ascii2 #-}-ascii2 :: (Char, Char) -> BoundedPrim a-ascii2 cs =- liftFixedToBounded $- const cs >$< char8 >*< char8--{-# INLINE ascii4 #-}-ascii4 :: (Char, (Char, (Char, Char))) -> BoundedPrim a-ascii4 cs =- liftFixedToBounded $- const cs >$< char8 >*< char8 >*< char8 >*< char8--{-# INLINE ascii5 #-}-ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BoundedPrim a-ascii5 cs =- liftFixedToBounded $- const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8--{-# INLINE ascii6 #-}-ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BoundedPrim a-ascii6 cs =- liftFixedToBounded $ - const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8--{-# INLINE ascii8 #-}-ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char))))))) -> BoundedPrim a-ascii8 cs =- liftFixedToBounded $- const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8
+ library/JSONBytesBuilder/ByteString/Builder.hs view
@@ -0,0 +1,17 @@+module JSONBytesBuilder.ByteString.Builder+(+ jsonLiteral,+)+where++import JSONBytesBuilder.Private.Prelude hiding (length, null)+import JSONBytesBuilder.Private.Builder+import Data.ByteString.Builder+++-- |+-- Produce a JSON ByteString builder with compact syntax from a literal builder.+{-# INLINE jsonLiteral #-}+jsonLiteral :: Literal -> Builder+jsonLiteral (Literal builder) =+ builder
− library/JSONBytesBuilder/ByteString/Builders.hs
@@ -1,66 +0,0 @@-module JSONBytesBuilder.ByteString.Builders-where--import JSONBytesBuilder.Prelude hiding (length, null)-import Data.ByteString.Builder-import qualified JSONBytesBuilder.ByteString.BoundedPrims as A-import qualified Data.ByteString.Builder.Prim as A-import qualified Data.Text.Encoding as B-import qualified Data.Scientific as C-import qualified Data.ByteString.Builder.Scientific as D---{-# INLINABLE null #-}-null :: Builder-null =- A.primBounded A.null ()--{-# INLINABLE boolean #-}-boolean :: Bool -> Builder-boolean =- A.primBounded A.boolean--{-# INLINABLE string #-}-string :: Text -> Builder-string x =- char8 '"' <> B.encodeUtf8BuilderEscaped A.stringEncodedByte x <> char8 '"'--{-# INLINABLE scientific #-}-scientific :: Scientific -> Builder-scientific n =- if e < 0- then D.scientificBuilder n- else integerDec (C.coefficient n * 10 ^ e)- where- e =- C.base10Exponent n--{-# INLINABLE inCurlies #-}-inCurlies :: Builder -> Builder-inCurlies x =- char8 '{' <> x <> char8 '}'--{-# INLINABLE row #-}-row :: Text -> Builder -> Builder-row key value =- string key <> char8 ':' <> value--{-# INLINABLE inSquarelies #-}-inSquarelies :: Builder -> Builder-inSquarelies x =- char8 '[' <> x <> char8 ']'--{-# INLINABLE commaSeparated #-}-commaSeparated :: Builder -> Builder -> Builder-commaSeparated left right =- left <> char8 ',' <> right--{-# INLINABLE emptyObject #-}-emptyObject :: Builder-emptyObject =- A.primBounded A.emptyObject ()--{-# INLINABLE emptyArray #-}-emptyArray :: Builder-emptyArray =- A.primBounded A.emptyArray ()
+ library/JSONBytesBuilder/ByteString/ByteString.hs view
@@ -0,0 +1,18 @@+module JSONBytesBuilder.ByteString.ByteString+(+ jsonLiteral,+)+where++import JSONBytesBuilder.Private.Prelude hiding (length, null)+import JSONBytesBuilder.Builder+import qualified JSONBytesBuilder.ByteString.LazyByteString as A+import qualified Data.ByteString.Lazy as B+++-- |+-- Produce a strict JSON ByteString with compact syntax from a literal builder.+{-# INLINE jsonLiteral #-}+jsonLiteral :: Literal -> ByteString+jsonLiteral =+ B.toStrict . A.jsonLiteral
+ library/JSONBytesBuilder/ByteString/LazyByteString.hs view
@@ -0,0 +1,19 @@+module JSONBytesBuilder.ByteString.LazyByteString+(+ jsonLiteral,+)+where++import JSONBytesBuilder.Private.Prelude hiding (length, null)+import JSONBytesBuilder.Builder+import Data.ByteString.Builder+import qualified JSONBytesBuilder.ByteString.Builder as A+import qualified Data.ByteString.Lazy as B+++-- |+-- Produce a lazy JSON ByteString with compact syntax from a literal builder.+{-# INLINE jsonLiteral #-}+jsonLiteral :: Literal -> B.ByteString+jsonLiteral =+ toLazyByteString . A.jsonLiteral
− library/JSONBytesBuilder/Interpreters/ByteString.hs
@@ -1,18 +0,0 @@-module JSONBytesBuilder.Interpreters.ByteString-(- jsonLiteral,-)-where--import JSONBytesBuilder.Prelude hiding (length, null)-import JSONBytesBuilder.Builder-import qualified JSONBytesBuilder.Interpreters.LazyByteString as A-import qualified Data.ByteString.Lazy as B----- |--- Produce a strict JSON ByteString with compact syntax from a literal builder.-{-# INLINE jsonLiteral #-}-jsonLiteral :: Literal -> ByteString-jsonLiteral =- B.toStrict . A.jsonLiteral
− library/JSONBytesBuilder/Interpreters/ByteStringBuilder.hs
@@ -1,17 +0,0 @@-module JSONBytesBuilder.Interpreters.ByteStringBuilder-(- jsonLiteral,-)-where--import JSONBytesBuilder.Prelude hiding (length, null)-import JSONBytesBuilder.Builder-import Data.ByteString.Builder----- |--- Produce a JSON ByteString builder with compact syntax from a literal builder.-{-# INLINE jsonLiteral #-}-jsonLiteral :: Literal -> Builder-jsonLiteral =- unsafeCoerce
− library/JSONBytesBuilder/Interpreters/LazyByteString.hs
@@ -1,19 +0,0 @@-module JSONBytesBuilder.Interpreters.LazyByteString-(- jsonLiteral,-)-where--import JSONBytesBuilder.Prelude hiding (length, null)-import JSONBytesBuilder.Builder-import Data.ByteString.Builder-import qualified JSONBytesBuilder.Interpreters.ByteStringBuilder as A-import qualified Data.ByteString.Lazy as B----- |--- Produce a lazy JSON ByteString with compact syntax from a literal builder.-{-# INLINE jsonLiteral #-}-jsonLiteral :: Literal -> B.ByteString-jsonLiteral =- toLazyByteString . A.jsonLiteral
− library/JSONBytesBuilder/Prelude.hs
@@ -1,11 +0,0 @@-module JSONBytesBuilder.Prelude-(- module Exports,-)-where--import BasePrelude as Exports hiding ((<>))-import Data.Semigroup as Exports (Semigroup(..))-import Data.Text as Exports (Text)-import Data.ByteString as Exports (ByteString)-import Data.Scientific as Exports (Scientific)
+ library/JSONBytesBuilder/Private/Builder.hs view
@@ -0,0 +1,140 @@+module JSONBytesBuilder.Private.Builder+where++import JSONBytesBuilder.Private.Prelude hiding (null)+import qualified Data.ByteString.Builder as A+import qualified JSONBytesBuilder.Private.ByteString.Builder as E+++-- |+-- Builder of any JSON literal.+newtype Literal =+ Literal A.Builder++-- |+-- Builder of JSON Object rows.+newtype Rows =+ Rows (Maybe A.Builder)++instance Monoid Rows where+ {-# INLINE mempty #-}+ mempty =+ Rows Nothing+ {-# INLINE mappend #-}+ mappend =+ \case+ Rows (Just left) ->+ \case+ Rows (Just right) ->+ Rows (Just (left <> A.char8 ',' <> right))+ _ ->+ Rows (Just left)+ Rows Nothing ->+ id++-- |+-- Builder of JSON Array elements.+newtype Elements =+ Elements (Maybe A.Builder)++instance Monoid Elements where+ {-# INLINE mempty #-}+ mempty =+ Elements Nothing+ {-# INLINE mappend #-}+ mappend =+ \case+ Elements (Just left) ->+ \case+ Elements (Just right) ->+ Elements (Just (left <> A.char8 ',' <> right))+ _ ->+ Elements (Just left)+ Elements Nothing ->+ id++-- |+-- JSON Null literal.+{-# INLINE null #-}+null :: Literal+null =+ Literal (inline E.null)++-- |+-- JSON Boolean literal from 'Bool'.+{-# INLINE boolean #-}+boolean :: Bool -> Literal+boolean =+ Literal . inline E.boolean++-- |+-- JSON Number literal from 'Int'.+{-# INLINE number_int #-}+number_int :: Int -> Literal+number_int =+ Literal . inline A.intDec++-- |+-- JSON Number literal from 'Integer'.+{-# INLINE number_integer #-}+number_integer :: Integer -> Literal+number_integer =+ Literal . inline A.integerDec++-- |+-- JSON Number literal from 'Double'.+{-# INLINE number_double #-}+number_double :: Double -> Literal+number_double =+ Literal . inline A.doubleDec++-- |+-- JSON Number literal from 'Scientific'.+{-# INLINE number_scientific #-}+number_scientific :: Scientific -> Literal+number_scientific =+ Literal . inline E.scientific++-- |+-- JSON String literal from 'Text'.+{-# INLINE string #-}+string :: Text -> Literal+string =+ Literal . inline E.string++-- |+-- JSON Object literal from the 'Rows' builder.+{-# INLINE object #-}+object :: Rows -> Literal+object (Rows x) =+ Literal (maybe E.emptyObject (inline E.inCurlies) x)++-- |+-- JSON Array literal from the 'Elements' builder.+{-# INLINE array #-}+array :: Elements -> Literal+array (Elements x) =+ Literal (maybe E.emptyArray (inline E.inSquarelies) x)++-- |+-- Rows builder from a key-value pair,+-- where value is an already encoded JSON literal.+-- +-- Use the 'Rows' 'Monoid' instance+-- to construct multi-row objects.+{-# INLINE row #-}+row :: Text -> Literal -> Rows+row key (Literal literal) =+ Rows (Just (inline E.row key literal))++-- |+-- Elements builder from an element,+-- which is an already encoded JSON literal.+-- +-- Use the 'Elements' 'Monoid' instance+-- to construct multi-element arrays.+{-# INLINE element #-}+element :: Literal -> Elements+element (Literal literal) =+ Elements (Just literal)+
+ library/JSONBytesBuilder/Private/ByteString/BoundedPrim.hs view
@@ -0,0 +1,72 @@+module JSONBytesBuilder.Private.ByteString.BoundedPrim+where++import JSONBytesBuilder.Private.Prelude+import Data.ByteString.Builder.Prim+++{-# INLINE null #-}+null :: BoundedPrim ()+null =+ ascii4 ('n', ('u', ('l', 'l')))++{-# INLINE boolean #-}+boolean :: BoundedPrim Bool+boolean =+ condB id (ascii4 ('t', ('r', ('u', 'e')))) (ascii5 ('f', ('a', ('l', ('s', 'e')))))++{-# INLINE emptyArray #-}+emptyArray :: BoundedPrim ()+emptyArray =+ ascii2 ('[', ']')++{-# INLINE emptyObject #-}+emptyObject :: BoundedPrim ()+emptyObject =+ ascii2 ('{', '}')++{-# INLINE stringEncodedByte #-}+stringEncodedByte :: BoundedPrim Word8+stringEncodedByte =+ condB (== (fromIntegral . ord) '\\') (ascii2 ('\\', '\\')) $+ condB (== (fromIntegral . ord) '\"') (ascii2 ('\\', '"')) $+ condB (>= (fromIntegral . ord) '\x20') (liftFixedToBounded word8) $+ condB (== (fromIntegral . ord) '\n') (ascii2 ('\\', 'n')) $+ condB (== (fromIntegral . ord) '\r') (ascii2 ('\\', 'r')) $+ condB (== (fromIntegral . ord) '\t') (ascii2 ('\\', 't')) $+ hexEncodedByte++{-# INLINE hexEncodedByte #-}+hexEncodedByte :: BoundedPrim Word8+hexEncodedByte =+ liftFixedToBounded ((\c -> ('\\', ('u', fromIntegral c))) >$< char8 >*< char8 >*< word16HexFixed)++{-# INLINE ascii2 #-}+ascii2 :: (Char, Char) -> BoundedPrim a+ascii2 cs =+ liftFixedToBounded $+ const cs >$< char8 >*< char8++{-# INLINE ascii4 #-}+ascii4 :: (Char, (Char, (Char, Char))) -> BoundedPrim a+ascii4 cs =+ liftFixedToBounded $+ const cs >$< char8 >*< char8 >*< char8 >*< char8++{-# INLINE ascii5 #-}+ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BoundedPrim a+ascii5 cs =+ liftFixedToBounded $+ const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8++{-# INLINE ascii6 #-}+ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BoundedPrim a+ascii6 cs =+ liftFixedToBounded $ + const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8++{-# INLINE ascii8 #-}+ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char))))))) -> BoundedPrim a+ascii8 cs =+ liftFixedToBounded $+ const cs >$< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8 >*< char8
+ library/JSONBytesBuilder/Private/ByteString/Builder.hs view
@@ -0,0 +1,66 @@+module JSONBytesBuilder.Private.ByteString.Builder+where++import JSONBytesBuilder.Private.Prelude hiding (length, null)+import Data.ByteString.Builder+import qualified JSONBytesBuilder.Private.ByteString.BoundedPrim as A+import qualified Data.ByteString.Builder.Prim as A+import qualified Data.Text.Encoding as B+import qualified Data.Scientific as C+import qualified Data.ByteString.Builder.Scientific as D+++{-# INLINABLE null #-}+null :: Builder+null =+ A.primBounded A.null ()++{-# INLINABLE boolean #-}+boolean :: Bool -> Builder+boolean =+ A.primBounded A.boolean++{-# INLINABLE string #-}+string :: Text -> Builder+string x =+ char8 '"' <> B.encodeUtf8BuilderEscaped A.stringEncodedByte x <> char8 '"'++{-# INLINABLE scientific #-}+scientific :: Scientific -> Builder+scientific n =+ if e < 0+ then D.scientificBuilder n+ else integerDec (C.coefficient n * 10 ^ e)+ where+ e =+ C.base10Exponent n++{-# INLINABLE inCurlies #-}+inCurlies :: Builder -> Builder+inCurlies x =+ char8 '{' <> x <> char8 '}'++{-# INLINABLE row #-}+row :: Text -> Builder -> Builder+row key value =+ string key <> char8 ':' <> value++{-# INLINABLE inSquarelies #-}+inSquarelies :: Builder -> Builder+inSquarelies x =+ char8 '[' <> x <> char8 ']'++{-# INLINABLE commaSeparated #-}+commaSeparated :: Builder -> Builder -> Builder+commaSeparated left right =+ left <> char8 ',' <> right++{-# INLINABLE emptyObject #-}+emptyObject :: Builder+emptyObject =+ A.primBounded A.emptyObject ()++{-# INLINABLE emptyArray #-}+emptyArray :: Builder+emptyArray =+ A.primBounded A.emptyArray ()
+ library/JSONBytesBuilder/Private/Prelude.hs view
@@ -0,0 +1,11 @@+module JSONBytesBuilder.Private.Prelude+(+ module Exports,+)+where++import BasePrelude as Exports hiding ((<>))+import Data.Semigroup as Exports (Semigroup(..))+import Data.Text as Exports (Text)+import Data.ByteString as Exports (ByteString)+import Data.Scientific as Exports (Scientific)