json-syntax 0.1.1.0 → 0.1.2.0
raw patch · 4 files changed
+115/−28 lines, 4 filesdep ~array-chunksdep ~bytebuildPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: array-chunks, bytebuild
API changes (from Hackage documentation)
+ Json: object1 :: Member -> Value
+ Json: object2 :: Member -> Member -> Value
+ Json: object3 :: Member -> Member -> Member -> Value
+ Json: object4 :: Member -> Member -> Member -> Member -> Value
+ Json: object5 :: Member -> Member -> Member -> Member -> Member -> Value
+ Json: object6 :: Member -> Member -> Member -> Member -> Member -> Member -> Value
+ Json: object7 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
+ Json: object8 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
+ Json: pattern (:->) :: ShortText -> Value -> Member
Files
- CHANGELOG.md +5/−0
- bench/Main.hs +33/−12
- json-syntax.cabal +3/−2
- src/Json.hs +74/−14
CHANGELOG.md view
@@ -1,5 +1,10 @@ # Revision history for json-syntax +## 0.1.2.0 -- 2020-11-18++* Add infix pattern synonym for `Member`.+* Add `object(1|2|3|4|5|6|7|8)` as convenience helpers for construction.+ ## 0.1.1.0 -- 2020-05-01 * Add `encode`.
bench/Main.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE BangPatterns #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} import Gauge.Main (defaultMain,bgroup,bench,whnf)@@ -6,22 +7,42 @@ import Twitter100 (encodedTwitter100,byteStringTwitter100) import qualified Data.Bytes as Bytes+import qualified Data.Bytes.Builder as BLDR+import qualified Data.Bytes.Chunks as Chunks+import qualified Data.ByteString.Lazy as LBS import qualified Json as J import qualified Data.Aeson as Aeson main :: IO ()-main = defaultMain- [ bgroup "json"- [ bgroup "twitter"- [ bench "100" $ whnf- (\b -> J.decode (Bytes.fromByteArray b))- encodedTwitter100+main = do+ valueTwitter100 <- case J.decode (Bytes.fromByteArray encodedTwitter100) of+ Left _ -> fail "json-syntax failed to decode twitter-100"+ Right v -> pure v+ aesonValueTwitter100 <- case Aeson.decodeStrict' byteStringTwitter100 of+ Nothing -> fail "aeson failed to decode twitter-100"+ Just (v :: Aeson.Value) -> pure v+ defaultMain+ [ bgroup "json"+ [ bgroup "twitter"+ [ bgroup "100"+ [ bench "decode" $ whnf+ (\b -> J.decode (Bytes.fromByteArray b))+ encodedTwitter100+ , bench "encode" $ whnf+ (\v -> Chunks.length (BLDR.run 128 (J.encode v)))+ valueTwitter100+ ]+ ] ]- ]- , bgroup "aeson"- [ bgroup "twitter"- [ bench "100"- (whnf (Aeson.decodeStrict' @Aeson.Value) byteStringTwitter100)+ , bgroup "aeson"+ [ bgroup "twitter"+ [ bgroup "100"+ [ bench "decode"+ (whnf (Aeson.decodeStrict' @Aeson.Value) byteStringTwitter100)+ , bench "encode" $ whnf+ (\v -> LBS.length (Aeson.encode v))+ aesonValueTwitter100+ ]+ ] ] ]- ]
json-syntax.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: json-syntax-version: 0.1.1.0+version: 0.1.2.0 synopsis: High-performance JSON parser and encoder description: This library parses JSON into a @Value@ type that is consistent with the@@ -29,7 +29,7 @@ exposed-modules: Json build-depends: , array-builder >=0.1 && <0.2- , array-chunks >=0.1.1 && <0.2+ , array-chunks >=0.1.2 && <0.2 , base >=4.12 && <5 , bytebuild >=0.3.4 && <0.4 , byteslice >=0.1.3 && <0.3@@ -74,6 +74,7 @@ build-depends: , aeson , base+ , bytebuild , byteslice , bytestring , gauge
src/Json.hs view
@@ -6,7 +6,9 @@ {-# language LambdaCase #-} {-# language MagicHash #-} {-# language NamedFieldPuns #-}+{-# language PatternSynonyms #-} {-# language TypeApplications #-}+{-# language UnboxedSums #-} {-# language UnboxedTuples #-} module Json@@ -17,6 +19,17 @@ -- * Functions , decode , encode+ -- * Infix Synonyms + , pattern (:->)+ -- * Construction+ , object1+ , object2+ , object3+ , object4+ , object5+ , object6+ , object7+ , object8 ) where import Prelude hiding (Bool(True,False))@@ -32,13 +45,15 @@ import Data.Number.Scientific (Scientific) import Data.Primitive (ByteArray,MutableByteArray) import Data.Text.Short (ShortText)-import GHC.Exts (Char(C#),Int(I#),gtWord#,ltWord#,word2Int#,chr#)+import GHC.Exts (SmallArray#,Char(C#),Int(I#),gtWord#,ltWord#,word2Int#,chr#)+import GHC.Exts (sizeofSmallArray#,indexSmallArray#) import GHC.Word (Word8(W8#),Word16(W16#)) import qualified Prelude import qualified Data.Builder.ST as B import qualified Data.Bytes.Builder as BLDR import qualified Data.Bytes.Parser as P+import qualified Data.Chunks as Chunks import qualified Data.Text.Short.Unsafe as TS import qualified Data.Number.Scientific as SCI import qualified Data.Primitive as PM@@ -127,6 +142,7 @@ P.endOfInput UnexpectedLeftovers pure result +-- | Encode a JSON syntax tree. encode :: Value -> BLDR.Builder encode = \case True -> BLDR.ascii4 't' 'r' 'u' 'e'@@ -135,11 +151,11 @@ String s -> BLDR.shortTextJsonString s Number n -> SCI.builderUtf8 n Array ys -> case unconsNonempty ys of- Nothing -> BLDR.ascii2 '[' ']'- Just (x,xs) ->+ (# (# #) | #) -> BLDR.ascii2 '[' ']'+ (# | (# x, xs #) #) -> BLDR.ascii '[' <>- encode (PM.indexSmallArray x 0)+ encode (case indexSmallArray# x 0# of {(# z #) -> z}) <> foldrTail ( \v b -> BLDR.ascii ',' <> encode v <> b@@ -148,13 +164,13 @@ ( \v b -> BLDR.ascii ',' <> encode v <> b ) (BLDR.ascii ']') xs )- x+ (PM.SmallArray x) Object ys -> case unconsNonempty ys of- Nothing -> BLDR.ascii2 '{' '}'- Just (x,xs) ->+ (# (# #) | #) -> BLDR.ascii2 '{' '}'+ (# | (# x,xs #) #) -> BLDR.ascii '{' <>- encodeMember (PM.indexSmallArray x 0)+ encodeMember (case indexSmallArray# x 0# of {(# z #) -> z}) <> foldrTail ( \mbr b -> BLDR.ascii ',' <> encodeMember mbr <> b@@ -163,7 +179,7 @@ ( \mbr b -> BLDR.ascii ',' <> encodeMember mbr <> b ) (BLDR.ascii '}') xs )- x+ (PM.SmallArray x) encodeMember :: Member -> BLDR.Builder encodeMember Member{key,value} =@@ -183,13 +199,13 @@ = f x (go (i+1)) -- Get the first non-empty SmallArray from the Chunks.-unconsNonempty :: Chunks a -> Maybe (PM.SmallArray a, Chunks a)+unconsNonempty :: Chunks a -> (# (# #) | (# SmallArray# a, Chunks a #) #) {-# inline unconsNonempty #-} unconsNonempty = go where- go ChunksNil = Nothing- go (ChunksCons x xs) = case PM.sizeofSmallArray x of- 0 -> go xs- _ -> Just (x,xs)+ go ChunksNil = (# (# #) | #)+ go (ChunksCons (PM.SmallArray x) xs) = case sizeofSmallArray# x of+ 0# -> go xs+ _ -> (# | (# x, xs #) #) -- Precondition: skip over all space before calling this. -- It will not skip leading space for you. It does@@ -410,3 +426,47 @@ -- Precondition: Not in the range [U+D800 .. U+DFFF] w16ToChar :: Word16 -> Char w16ToChar (W16# w) = C# (chr# (word2Int# w))++-- | Infix pattern synonym for 'Member'.+pattern (:->) :: ShortText -> Value -> Member+pattern key :-> value = Member{key,value}++-- | Construct a JSON object with one member.+object1 :: Member -> Value+{-# inline object1 #-}+object1 a = Object (Chunks.singleton a)++-- | Construct a JSON object with two members.+object2 :: Member -> Member -> Value+{-# inline object2 #-}+object2 a b = Object (Chunks.doubleton a b)++-- | Construct a JSON object with three members.+object3 :: Member -> Member -> Member -> Value+{-# inline object3 #-}+object3 a b c = Object (Chunks.tripleton a b c)++-- | Construct a JSON object with four members.+object4 :: Member -> Member -> Member -> Member -> Value+{-# inline object4 #-}+object4 a b c d = Object (Chunks.quadrupleton a b c d)++-- | Construct a JSON object with five members.+object5 :: Member -> Member -> Member -> Member -> Member -> Value+{-# inline object5 #-}+object5 a b c d e = Object (Chunks.quintupleton a b c d e)++-- | Construct a JSON object with six members.+object6 :: Member -> Member -> Member -> Member -> Member -> Member -> Value+{-# inline object6 #-}+object6 a b c d e f = Object (Chunks.sextupleton a b c d e f)++-- | Construct a JSON object with seven members.+object7 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value+{-# inline object7 #-}+object7 a b c d e f g = Object (Chunks.septupleton a b c d e f g)++-- | Construct a JSON object with eight members.+object8 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value+{-# inline object8 #-}+object8 a b c d e f g h = Object (Chunks.octupleton a b c d e f g h)