@@ -40,17 +40,16 @@ import Prelude hiding (Bool(True,False))
4040
4141import Control.Exception (Exception )
4242import Control.Monad.ST (ST )
43+ import Control.Monad.ST.Run (runSmallArrayST )
4344import Data.Bits ((.&.) ,(.|.) ,unsafeShiftR )
4445import Data.Builder.ST (Builder )
4546import Data.Bytes.Parser (Parser )
4647import Data.Bytes.Types (Bytes (.. ))
4748import Data.Char (ord )
48- import Data.Chunks (Chunks (ChunksNil ,ChunksCons ))
4949import Data.Number.Scientific (Scientific )
50- import Data.Primitive (ByteArray ,MutableByteArray )
50+ import Data.Primitive (ByteArray ,MutableByteArray , SmallArray )
5151import Data.Text.Short (ShortText )
52- import GHC.Exts (SmallArray #,Char (C #),Int (I #),gtWord #,ltWord #,word2Int #,chr #)
53- import GHC.Exts (sizeofSmallArray #,indexSmallArray #)
52+ import GHC.Exts (Char (C #),Int (I #),gtWord #,ltWord #,word2Int #,chr #)
5453import GHC.Word (Word8 (W8 #),Word16 (W16 #))
5554
5655import qualified Prelude
@@ -82,8 +81,8 @@ import qualified Data.Bytes.Parser.Unsafe as Unsafe
8281-- there are functions in @Data.Chunks@ that efficently perform other
8382-- operations.
8483data Value
85- = Object ! (Chunks Member )
86- | Array ! (Chunks Value )
84+ = Object ! (SmallArray Member )
85+ | Array ! (SmallArray Value )
8786 | String {- # UNPACK #-} !ShortText
8887 | Number {- # UNPACK #-} !Scientific
8988 | Null
@@ -124,11 +123,11 @@ data Member = Member
124123
125124emptyArrayValue :: Value
126125{-# noinline emptyArrayValue #-}
127- emptyArrayValue = Array ChunksNil
126+ emptyArrayValue = Array mempty
128127
129128emptyObjectValue :: Value
130129{-# noinline emptyObjectValue #-}
131- emptyObjectValue = Object ChunksNil
130+ emptyObjectValue = Object mempty
132131
133132isSpace :: Word8 -> Prelude. Bool
134133{-# inline isSpace #-}
@@ -155,36 +154,28 @@ encode = \case
155154 Null -> BLDR. ascii4 ' n' ' u' ' l' ' l'
156155 String s -> BLDR. shortTextJsonString s
157156 Number n -> SCI. builderUtf8 n
158- Array ys -> case unconsNonempty ys of
159- (# (# # ) | # ) -> BLDR. ascii2 ' [' ' ]'
160- (# | (# x, xs # ) # ) ->
161- BLDR. ascii ' ['
162- <>
163- encode (case indexSmallArray# x 0 # of {(# z # ) -> z})
164- <>
165- foldrTail
166- ( \ v b -> BLDR. ascii ' ,' <> encode v <> b
167- )
168- ( foldr
169- ( \ v b -> BLDR. ascii ' ,' <> encode v <> b
170- ) (BLDR. ascii ' ]' ) xs
171- )
172- (PM. SmallArray x)
173- Object ys -> case unconsNonempty ys of
174- (# (# # ) | # ) -> BLDR. ascii2 ' {' ' }'
175- (# | (# x,xs # ) # ) ->
176- BLDR. ascii ' {'
177- <>
178- encodeMember (case indexSmallArray# x 0 # of {(# z # ) -> z})
179- <>
180- foldrTail
181- ( \ mbr b -> BLDR. ascii ' ,' <> encodeMember mbr <> b
182- )
183- ( foldr
184- ( \ mbr b -> BLDR. ascii ' ,' <> encodeMember mbr <> b
185- ) (BLDR. ascii ' }' ) xs
186- )
187- (PM. SmallArray x)
157+ Array ys -> case PM. sizeofSmallArray ys of
158+ 0 -> BLDR. ascii2 ' [' ' ]'
159+ _ ->
160+ let ! (# z # ) = PM. indexSmallArray## ys 0
161+ in BLDR. ascii ' ['
162+ <>
163+ encode z
164+ <>
165+ foldrTail
166+ ( \ v b -> BLDR. ascii ' ,' <> encode v <> b
167+ ) (BLDR. ascii ' ]' ) ys
168+ Object ys -> case PM. sizeofSmallArray ys of
169+ 0 -> BLDR. ascii2 ' {' ' }'
170+ _ ->
171+ let ! (# z # ) = PM. indexSmallArray## ys 0
172+ in BLDR. ascii ' {'
173+ <>
174+ encodeMember z
175+ <>
176+ foldrTail
177+ ( \ v b -> BLDR. ascii ' ,' <> encodeMember v <> b
178+ ) (BLDR. ascii ' }' ) ys
188179
189180encodeMember :: Member -> BLDR. Builder
190181encodeMember Member {key,value} =
@@ -203,15 +194,6 @@ foldrTail f z !ary = go 1 where
203194 | (# x # ) <- PM. indexSmallArray## ary i
204195 = f x (go (i+ 1 ))
205196
206- -- Get the first non-empty SmallArray from the Chunks.
207- unconsNonempty :: Chunks a -> (# (# # ) | (# SmallArray # a , Chunks a # ) # )
208- {-# inline unconsNonempty #-}
209- unconsNonempty = go where
210- go ChunksNil = (# (# # ) | # )
211- go (ChunksCons (PM. SmallArray x) xs) = case sizeofSmallArray# x of
212- 0 # -> go xs
213- _ -> (# | (# x, xs # ) # )
214-
215197-- Precondition: skip over all space before calling this.
216198-- It will not skip leading space for you. It does
217199parser :: Char -> Parser SyntaxException s Value
@@ -274,7 +256,8 @@ objectStep !b = do
274256 P. effect (B. push mbr b) >>= objectStep
275257 ' }' -> do
276258 ! r <- P. effect (B. freeze b)
277- pure (Object r)
259+ let ! arr = Chunks. concat r
260+ pure (Object arr)
278261 _ -> P. fail ExpectedCommaOrRightBracket
279262
280263-- This eats all the space at the front of the input. There
@@ -315,7 +298,8 @@ arrayStep !b = do
315298 P. effect (B. push val b) >>= arrayStep
316299 ' ]' -> do
317300 ! r <- P. effect (B. freeze b)
318- pure (Array r)
301+ let ! arr = Chunks. concat r
302+ pure (Array arr)
319303 _ -> P. fail ExpectedCommaOrRightBracket
320304
321305c2w :: Char -> Word8
@@ -441,63 +425,153 @@ pattern key :-> value = Member{key,value}
441425-- | Construct a JSON object with one member.
442426object1 :: Member -> Value
443427{-# inline object1 #-}
444- object1 a = Object (Chunks. singleton a)
428+ object1 a = Object $ runSmallArrayST $ do
429+ dst <- PM. newSmallArray 1 a
430+ PM. unsafeFreezeSmallArray dst
445431
446432-- | Construct a JSON object with two members.
447433object2 :: Member -> Member -> Value
448434{-# inline object2 #-}
449- object2 a b = Object (Chunks. doubleton a b)
435+ object2 a b = Object $ runSmallArrayST $ do
436+ dst <- PM. newSmallArray 2 a
437+ PM. writeSmallArray dst 1 b
438+ PM. unsafeFreezeSmallArray dst
450439
451440-- | Construct a JSON object with three members.
452441object3 :: Member -> Member -> Member -> Value
453442{-# inline object3 #-}
454- object3 a b c = Object (Chunks. tripleton a b c)
443+ object3 a b c = Object $ runSmallArrayST $ do
444+ dst <- PM. newSmallArray 3 a
445+ PM. writeSmallArray dst 1 b
446+ PM. writeSmallArray dst 2 c
447+ PM. unsafeFreezeSmallArray dst
455448
456449-- | Construct a JSON object with four members.
457450object4 :: Member -> Member -> Member -> Member -> Value
458451{-# inline object4 #-}
459- object4 a b c d = Object (Chunks. quadrupleton a b c d)
452+ object4 a b c d = Object $ runSmallArrayST $ do
453+ dst <- PM. newSmallArray 4 a
454+ PM. writeSmallArray dst 1 b
455+ PM. writeSmallArray dst 2 c
456+ PM. writeSmallArray dst 3 d
457+ PM. unsafeFreezeSmallArray dst
460458
461459-- | Construct a JSON object with five members.
462460object5 :: Member -> Member -> Member -> Member -> Member -> Value
463461{-# inline object5 #-}
464- object5 a b c d e = Object (Chunks. quintupleton a b c d e)
462+ object5 a b c d e = Object $ runSmallArrayST $ do
463+ dst <- PM. newSmallArray 5 a
464+ PM. writeSmallArray dst 1 b
465+ PM. writeSmallArray dst 2 c
466+ PM. writeSmallArray dst 3 d
467+ PM. writeSmallArray dst 4 e
468+ PM. unsafeFreezeSmallArray dst
465469
466470-- | Construct a JSON object with six members.
467471object6 :: Member -> Member -> Member -> Member -> Member -> Member -> Value
468472{-# inline object6 #-}
469- object6 a b c d e f = Object (Chunks. sextupleton a b c d e f)
473+ object6 a b c d e f = Object $ runSmallArrayST $ do
474+ dst <- PM. newSmallArray 6 a
475+ PM. writeSmallArray dst 1 b
476+ PM. writeSmallArray dst 2 c
477+ PM. writeSmallArray dst 3 d
478+ PM. writeSmallArray dst 4 e
479+ PM. writeSmallArray dst 5 f
480+ PM. unsafeFreezeSmallArray dst
470481
471482-- | Construct a JSON object with seven members.
472483object7 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
473484{-# inline object7 #-}
474- object7 a b c d e f g = Object (Chunks. septupleton a b c d e f g)
485+ object7 a b c d e f g = Object $ runSmallArrayST $ do
486+ dst <- PM. newSmallArray 7 a
487+ PM. writeSmallArray dst 1 b
488+ PM. writeSmallArray dst 2 c
489+ PM. writeSmallArray dst 3 d
490+ PM. writeSmallArray dst 4 e
491+ PM. writeSmallArray dst 5 f
492+ PM. writeSmallArray dst 6 g
493+ PM. unsafeFreezeSmallArray dst
475494
476495-- | Construct a JSON object with nine members.
477496object8 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Value
478497{-# inline object8 #-}
479- object8 a b c d e f g h = Object (Chunks. octupleton a b c d e f g h)
498+ object8 a b c d e f g h = Object $ runSmallArrayST $ do
499+ dst <- PM. newSmallArray 8 a
500+ PM. writeSmallArray dst 1 b
501+ PM. writeSmallArray dst 2 c
502+ PM. writeSmallArray dst 3 d
503+ PM. writeSmallArray dst 4 e
504+ PM. writeSmallArray dst 5 f
505+ PM. writeSmallArray dst 6 g
506+ PM. writeSmallArray dst 7 h
507+ PM. unsafeFreezeSmallArray dst
480508
481509-- | Construct a JSON object with nine members.
482510object9 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
483511 -> Value
484512{-# inline object9 #-}
485- object9 a b c d e f g h i = Object (Chunks. nonupleton a b c d e f g h i)
513+ object9 a b c d e f g h i = Object $ runSmallArrayST $ do
514+ dst <- PM. newSmallArray 9 a
515+ PM. writeSmallArray dst 1 b
516+ PM. writeSmallArray dst 2 c
517+ PM. writeSmallArray dst 3 d
518+ PM. writeSmallArray dst 4 e
519+ PM. writeSmallArray dst 5 f
520+ PM. writeSmallArray dst 6 g
521+ PM. writeSmallArray dst 7 h
522+ PM. writeSmallArray dst 8 i
523+ PM. unsafeFreezeSmallArray dst
486524
487525-- | Construct a JSON object with ten members.
488526object10 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
489527 -> Member -> Member -> Value
490528{-# inline object10 #-}
491- object10 a b c d e f g h i j = Object (Chunks. decupleton a b c d e f g h i j)
529+ object10 a b c d e f g h i j = Object $ runSmallArrayST $ do
530+ dst <- PM. newSmallArray 10 a
531+ PM. writeSmallArray dst 1 b
532+ PM. writeSmallArray dst 2 c
533+ PM. writeSmallArray dst 3 d
534+ PM. writeSmallArray dst 4 e
535+ PM. writeSmallArray dst 5 f
536+ PM. writeSmallArray dst 6 g
537+ PM. writeSmallArray dst 7 h
538+ PM. writeSmallArray dst 8 i
539+ PM. writeSmallArray dst 9 j
540+ PM. unsafeFreezeSmallArray dst
492541
493542-- | Construct a JSON object with eleven members.
494543object11 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
495544 -> Member -> Member -> Member -> Value
496545{-# inline object11 #-}
497- object11 a b c d e f g h i j k = Object (Chunks. undecupleton a b c d e f g h i j k)
546+ object11 a b c d e f g h i j k = Object $ runSmallArrayST $ do
547+ dst <- PM. newSmallArray 11 a
548+ PM. writeSmallArray dst 1 b
549+ PM. writeSmallArray dst 2 c
550+ PM. writeSmallArray dst 3 d
551+ PM. writeSmallArray dst 4 e
552+ PM. writeSmallArray dst 5 f
553+ PM. writeSmallArray dst 6 g
554+ PM. writeSmallArray dst 7 h
555+ PM. writeSmallArray dst 8 i
556+ PM. writeSmallArray dst 9 j
557+ PM. writeSmallArray dst 10 k
558+ PM. unsafeFreezeSmallArray dst
498559
499560-- | Construct a JSON object with eleven members.
500561object12 :: Member -> Member -> Member -> Member -> Member -> Member -> Member -> Member
501562 -> Member -> Member -> Member -> Member -> Value
502563{-# inline object12 #-}
503- object12 a b c d e f g h i j k l = Object (Chunks. duodecupleton a b c d e f g h i j k l)
564+ object12 a b c d e f g h i j k l = Object $ runSmallArrayST $ do
565+ dst <- PM. newSmallArray 12 a
566+ PM. writeSmallArray dst 1 b
567+ PM. writeSmallArray dst 2 c
568+ PM. writeSmallArray dst 3 d
569+ PM. writeSmallArray dst 4 e
570+ PM. writeSmallArray dst 5 f
571+ PM. writeSmallArray dst 6 g
572+ PM. writeSmallArray dst 7 h
573+ PM. writeSmallArray dst 8 i
574+ PM. writeSmallArray dst 9 j
575+ PM. writeSmallArray dst 10 k
576+ PM. writeSmallArray dst 11 l
577+ PM. unsafeFreezeSmallArray dst
0 commit comments