on master help sign in
WIP: Abstract some usages of raw Builder
commit9f487ced441dd427ab6209401e0abd84dbc63f6b authorOleg Grenrus <oleg.grenrus@iki.fi> dateThu 2 Jun 2016, 19:55 (10 years ago) parentf2f73cc
13 files changed+301−292
Data/Aeson/Encode/Builder.hs+8−14 Data/Aeson/Encode/Functions.hs+3−51 Data/Aeson/Encoding.hs+128 Data/Aeson/TH.hs+2−1 Data/Aeson/Types.hs+1−6 Data/Aeson/Types/Class.hs+15−8 Data/Aeson/Types/Generic.hs+4−3 Data/Aeson/Types/Instances.hs+13−22 Data/Aeson/Types/Instances/Tuple.hs+121−133 Data/Aeson/Types/Internal.hs−50 aeson.cabal+1 benchmarks/aeson-benchmarks.cabal+1 tuple-instances.hs+4−4
Data/Aeson/Encode/Builder.hs+8−14
@@ -36,7 +36,7 @@ module Data.Aeson.Encode.Builder
3636 ) where
3737
3838import Data.Aeson.Internal.Time
39−import Data.Aeson.Types.Internal (Encoding(..), Value(..))
39+import Data.Aeson.Types.Internal (Value (..))
4040import Data.ByteString.Builder as B
4141import Data.ByteString.Builder.Prim as BP
4242import Data.ByteString.Builder.Scientific (scientificBuilder)
@@ -76,7 +76,7 @@ bool = BP.primBounded (BP.condB id (ascii4 ('t',('r',('u','e'))))
7676-- | Encode a JSON array.
7777array :: V.Vector Value -> Builder
7878array v
79− | V.null v = emptyArray__
79+ | V.null v = emptyArray_
8080 | otherwise = B.char8 '[' <>
8181 encodeToBuilder (V.unsafeHead v) <>
8282 V.foldr withComma (B.char8 ']') (V.unsafeTail v)
@@ -87,7 +87,7 @@ array v
8787object :: HMS.HashMap T.Text Value -> Builder
8888object m = case HMS.toList m of
8989 (x:xs) -> B.char8 '{' <> one x <> foldr withComma (B.char8 '}') xs
90− _ -> emptyObject__
90+ _ -> emptyObject_
9191 where
9292 withComma a z = B.char8 ',' <> one a <> z
9393 one (k,v) = text k <> B.char8 ':' <> encodeToBuilder v
@@ -98,7 +98,7 @@ text t = B.char8 '"' <> unquoted t <> B.char8 '"'
9898
9999-- | Encode a JSON string, without enclosing quotes.
100100unquoted :: T.Text -> Builder
101−unquoted t = TE.encodeUtf8BuilderEscaped escapeAscii t
101+unquoted = TE.encodeUtf8BuilderEscaped escapeAscii
102102
103103-- | Add quotes surrounding a builder
104104quote :: Builder -> Builder
@@ -135,17 +135,11 @@ number s
135135 where
136136 e = base10Exponent s
137137
138−emptyArray_ :: Encoding
139−emptyArray_ = Encoding emptyArray__
138+emptyArray_ :: Builder
139+emptyArray_ = BP.primBounded (ascii2 ('[',']')) ()
140140
141−emptyArray__ :: Builder
142−emptyArray__ = BP.primBounded (ascii2 ('[',']')) ()
143−
144−emptyObject_ :: Encoding
145−emptyObject_ = Encoding emptyObject__
146−
147−emptyObject__ :: Builder
148−emptyObject__ = BP.primBounded (ascii2 ('{','}')) ()
141+emptyObject_ :: Builder
142+emptyObject_ = BP.primBounded (ascii2 ('{','}')) ()
149143
150144ascii2 :: (Char, Char) -> BP.BoundedPrim a
151145ascii2 cs = BP.liftFixedToBounded $ (const cs) BP.>$< BP.char7 >*< BP.char7
Data/Aeson/Encode/Functions.hs+3−51
@@ -2,22 +2,14 @@
22
33module Data.Aeson.Encode.Functions
44 (
5− brackets
6− , builder
7− , builder'
8− , char7
5+ builder
6+ , char7 -- TODO: used by TH module
97 , encode
10− , list
11− , encodeMap
12− , encodeWithKey
138 ) where
149
15−import Data.Aeson.Encode.Builder
10+import Data.Aeson.Encoding
1611import Data.Aeson.Types.Class
17−import Data.Aeson.Types.Internal
1812import Data.ByteString.Builder (Builder, char7)
19−import Data.ByteString.Builder.Prim (primBounded)
20−import Data.Foldable (toList)
2113import Data.Monoid ((<>))
2214import qualified Data.ByteString.Builder as B
2315import qualified Data.ByteString.Lazy as L
@@ -27,53 +19,13 @@ import Data.Foldable (Foldable, foldMap)
2719import Data.Monoid (mempty)
2820#endif
2921
30−list :: (a -> Encoding) -> [a] -> Encoding
31−list = listEncoding
32−
3322builder :: ToJSON a => a -> Builder
3423builder = fromEncoding . toEncoding
3524{-# INLINE builder #-}
3625
37−builder' :: (a -> Encoding) -> a -> Builder
38−builder' f = fromEncoding . f
39−{-# INLINE builder' #-}
40−
4126-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
4227--
4328-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.
4429encode :: ToJSON a => a -> L.ByteString
4530encode = B.toLazyByteString . builder
4631{-# INLINE encode #-}
47−
48−brackets :: Char -> Char -> Series -> Encoding
49−brackets begin end (Value v) = Encoding $
50− char7 begin <> fromEncoding v <> char7 end
51−brackets begin end Empty = Encoding (primBounded (ascii2 (begin,end)) ())
52−
53−
54−
55−encodeMap :: (k -> Encoding)
56− -> (v -> Encoding)
57− -> (m -> Maybe ((k,v), m))
58− -> ((k -> v -> B.Builder -> B.Builder) -> B.Builder -> m -> B.Builder)
59− -> m -> Encoding
60−encodeMap encodeKey encodeVal minViewWithKey foldrWithKey xs =
61− case minViewWithKey xs of
62− Nothing -> Encoding $ primBounded (ascii2 ('{', '}')) ()
63− Just ((k,v),ys) -> Encoding $
64− B.char7 '{' <> encodeKV encodeKey encodeVal k v <>
65− foldrWithKey go (B.char7 '}') ys
66− where go k v b = B.char7 ',' <> encodeKV encodeKey encodeVal k v <> b
67−{-# INLINE encodeMap #-}
68−
69−encodeWithKey :: (k -> Encoding)
70− -> (v -> Encoding)
71− -> ((k -> v -> Series -> Series) -> Series -> m -> Series)
72− -> m -> Encoding
73−encodeWithKey encodeKey encodeVal foldrWithKey = brackets '{' '}' . foldrWithKey go mempty
74− where go k v c = Value (Encoding $ encodeKV encodeKey encodeVal k v) <> c
75−{-# INLINE encodeWithKey #-}
76−
77−encodeKV :: (k -> Encoding) -> (v -> Encoding) -> k -> v -> B.Builder
78−encodeKV encodeKey encodeVal k v = fromEncoding (encodeKey k) <> B.char7 ':' <> builder' encodeVal v
79−{-# INLINE encodeKV #-}
Data/Aeson/Encoding.hsnew file+128
@@ -0,0 +1,128 @@
1+{-# LANGUAGE GeneralizedNewtypeDeriving, DeriveDataTypeable, RankNTypes #-}
2+module Data.Aeson.Encoding
3+ (
4+ -- * Encoding
5+ Encoding (..) -- TODO: export fromEncoding for now
6+ , fromEncoding
7+ , unsafeToEncoding
8+ , Series (..) -- TODO: don't export constructor
9+ , pairs
10+ -- * Encoding constructors
11+ , emptyArray_
12+ , emptyObject_
13+ , list
14+ , dict
15+ , tuple
16+ , (>*<)
17+ ) where
18+
19+import Data.ByteString.Builder (Builder, char7, toLazyByteString)
20+import Data.Semigroup (Semigroup((<>)))
21+import Data.ByteString.Builder.Prim (primBounded)
22+import Data.Typeable (Typeable)
23+
24+import qualified Data.Aeson.Encode.Builder as B
25+
26+-- | An encoding of a JSON value.
27+newtype Encoding = Encoding {
28+ fromEncoding :: Builder
29+ -- ^ Acquire the underlying bytestring builder.
30+ } deriving (Semigroup,Monoid,Typeable)
31+
32+-- | Make Encoding from Builder.
33+--
34+-- Use with care! You have to make sure that the passed Builder
35+-- is a valid JSON Encoding!
36+unsafeToEncoding :: Builder -> Encoding
37+unsafeToEncoding = Encoding
38+
39+-------------------------------------------------------------------------------
40+-- Encoding instances
41+-------------------------------------------------------------------------------
42+
43+instance Show Encoding where
44+ show (Encoding e) = show (toLazyByteString e)
45+
46+instance Eq Encoding where
47+ Encoding a == Encoding b = toLazyByteString a == toLazyByteString b
48+
49+instance Ord Encoding where
50+ compare (Encoding a) (Encoding b) =
51+ compare (toLazyByteString a) (toLazyByteString b)
52+
53+-- | A series of values that, when encoded, should be separated by
54+-- commas. Since 0.11.0.0, the '.=' operator is overloaded to create
55+-- either @(Text, Value)@ or 'Series'. You can use Series when
56+-- encoding directly to a bytestring builder as in the following
57+-- example:
58+--
59+-- > toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)
60+data Series = Empty
61+ | Value Encoding
62+ deriving (Typeable)
63+
64+instance Semigroup Series where
65+ Empty <> a = a
66+ Value a <> b =
67+ Value $
68+ a <> case b of
69+ Empty -> mempty
70+ Value c -> Encoding (char7 ',') <> c
71+
72+instance Monoid Series where
73+ mempty = Empty
74+ mappend = (<>)
75+
76+emptyArray_ :: Encoding
77+emptyArray_ = Encoding B.emptyArray_
78+
79+emptyObject_ :: Encoding
80+emptyObject_ = Encoding B.emptyObject_
81+
82+-- | Encode a series of key/value pairs, separated by commas.
83+pairs :: Series -> Encoding
84+pairs = brackets '{' '}'
85+{-# INLINE pairs #-}
86+
87+brackets :: Char -> Char -> Series -> Encoding
88+brackets begin end (Value v) = Encoding $
89+ char7 begin <> fromEncoding v <> char7 end
90+brackets begin end Empty = Encoding (primBounded (B.ascii2 (begin,end)) ())
91+
92+list :: (a -> Encoding) -> [a] -> Encoding
93+list _ [] = emptyArray_
94+list to' (x:xs) = Encoding $
95+ char7 '[' <> fromEncoding (to' x) <> commas xs <> char7 ']'
96+ where
97+ commas = foldr (\v vs -> char7 ',' <> fromEncoding (to' v) <> vs) mempty
98+{-# INLINE list #-}
99+
100+-- | Encode as JSON object
101+dict
102+ :: (k -> Encoding) -- ^ key encoding
103+ -> (v -> Encoding) -- ^ value encoding
104+ -> (forall a. (k -> v -> a -> a) -> a -> m -> a) -- ^ @foldrWithKey@ - indexed fold
105+ -> m -- ^ container
106+ -> Encoding
107+dict encodeKey encodeVal foldrWithKey = brackets '{' '}' . foldrWithKey go mempty
108+ where
109+ go k v c = Value (encodeKV k v) <> c
110+ encodeKV k v = encodeKey k <> Encoding (char7 ':') <> encodeVal v
111+{-# INLINE dict #-}
112+
113+infixr 6 >*<
114+-- | See 'tuple'.
115+(>*<) :: Encoding -> Encoding -> Encoding
116+Encoding a >*< Encoding b = Encoding $ a <> char7 ',' <> b
117+{-# INLINE (>*<) #-}
118+
119+-- | Encode as a tuple.
120+--
121+-- @
122+-- toEncoding (X a b c) = tuple $
123+-- toEncoding a >*<
124+-- toEncoding b >*<
125+-- toEncoding c
126+tuple :: Encoding -> Encoding
127+tuple b = Encoding (char7 '[' <> fromEncoding b <> char7 ']')
128+{-# INLINE tuple #-}
Data/Aeson/TH.hs+2−1
@@ -107,7 +107,8 @@ import Data.Aeson.Types ( Value(..), Parser
107107 , defaultOptions
108108 , defaultTaggedObject
109109 )
110−import Data.Aeson.Types.Internal (Encoding(..), (<?>), JSONPathElement(Key))
110+import Data.Aeson.Types.Internal ((<?>), JSONPathElement(Key))
111+import Data.Aeson.Encoding ( Encoding(..) )
111112import Control.Monad ( liftM2, return, mapM, fail )
112113import Data.Bool ( Bool(False, True), otherwise, (&&), not )
113114import Data.Either ( Either(Left, Right) )
Data/Aeson/Types.hs+1−6
@@ -97,16 +97,11 @@ module Data.Aeson.Types
9797import Data.Aeson.Types.Generic ()
9898import Data.Aeson.Types.Instances
9999import Data.Aeson.Types.Internal
100+import Data.Aeson.Encoding (Encoding, unsafeToEncoding, fromEncoding, Series, pairs)
100101
101102import Data.Foldable (Foldable, toList)
102−import Data.Aeson.Encode.Functions (brackets)
103103
104104-- | Encode a 'Foldable' as a JSON array.
105105foldable :: (Foldable t, ToJSON a) => t a -> Encoding
106106foldable = toEncoding . toList
107107{-# INLINE foldable #-}
108−
109−-- | Encode a series of key/value pairs, separated by commas.
110−pairs :: Series -> Encoding
111−pairs = brackets '{' '}'
112−{-# INLINE pairs #-}
Data/Aeson/Types/Class.hs+15−8
@@ -1,5 +1,5 @@
1−{-# LANGUAGE CPP, GADTs, DefaultSignatures, FlexibleContexts, DeriveFunctor,
2− ScopedTypeVariables #-}
1+{-# LANGUAGE CPP, GADTs, DefaultSignatures, FlexibleInstances, FlexibleContexts, DeriveFunctor,
2+ ScopedTypeVariables, TypeSynonymInstances #-}
33
44-- |
55-- Module: Data.Aeson.Types.Class
@@ -58,7 +58,7 @@ import Data.Aeson.Types.Internal
5858import Data.Monoid ((<>))
5959import Data.Text (Text)
6060import GHC.Generics (Generic, Rep, from, to)
61−import Data.Aeson.Encode.Builder (emptyArray_)
61+import Data.Aeson.Encoding (Encoding (..), Series (..), emptyArray_, list)
6262import qualified Data.ByteString.Builder as B
6363import qualified Data.Aeson.Encode.Builder as E
6464import qualified Data.Vector as V
@@ -325,6 +325,17 @@ class KeyValue kv where
325325 (.=) :: ToJSON v => Text -> v -> kv
326326 infixr 8 .=
327327
328+instance KeyValue Series where
329+ name .= value = Value . Encoding $
330+ E.text name <> B.char7 ':' <> builder value
331+ where
332+ builder = fromEncoding . toEncoding
333+ {-# INLINE (.=) #-}
334+
335+instance KeyValue Pair where
336+ name .= value = (name, toJSON value)
337+ {-# INLINE (.=) #-}
338+
328339-------------------------------------------------------------------------------
329340-- Classes and types for map keys
330341-------------------------------------------------------------------------------
@@ -525,11 +536,7 @@ toEncoding2 = liftToEncoding2 toEncoding toEncodingList toEncoding toEncodingLis
525536-------------------------------------------------------------------------------
526537
527538listEncoding :: (a -> Encoding) -> [a] -> Encoding
528−listEncoding _ [] = emptyArray_
529−listEncoding to' (x:xs) = Encoding $
530− B.char7 '[' <> fromEncoding (to' x) <> commas xs <> B.char7 ']'
531− where commas = foldr (\v vs -> B.char7 ',' <> fromEncoding (to' v) <> vs) mempty
532−{-# INLINE listEncoding #-}
539+listEncoding = list
533540
534541listValue :: (a -> Value) -> [a] -> Value
535542listValue f = Array . V.fromList . map f
Data/Aeson/Types/Generic.hs+4−3
@@ -24,9 +24,10 @@ module Data.Aeson.Types.Generic ( ) where
2424import Control.Applicative ((<|>))
2525import Control.Monad ((<=<))
2626import Control.Monad.ST (ST)
27−import Data.Aeson.Encode.Builder (emptyArray_)
27+import Data.Aeson.Encoding (Encoding (..), emptyArray_)
2828import Data.Aeson.Encode.Functions (builder)
2929import Data.Aeson.Types.Instances
30+import Data.Aeson.Encoding ((>*<), tuple)
3031import Data.Aeson.Types.Internal
3132import Data.Bits (unsafeShiftR)
3233import Data.ByteString.Builder as B
@@ -299,8 +300,8 @@ instance (TwoElemArrayEnc a, TwoElemArrayEnc b) => TwoElemArrayEnc (a :+: b) whe
299300instance ( GToEncoding a, ConsToEncoding a
300301 , Constructor c ) => TwoElemArrayEnc (C1 c a) where
301302 twoElemArrayEnc opts x = fromEncoding . tuple $
302− builder (constructorTagModifier opts (conName (undefined :: t c a p))) >*<
303− gbuilder opts x
303+ toEncoding (constructorTagModifier opts (conName (undefined :: t c a p))) >*<
304+ gToEncoding opts x
304305
305306--------------------------------------------------------------------------------
306307
Data/Aeson/Types/Instances.hs+13−22
@@ -78,8 +78,6 @@ module Data.Aeson.Types.Instances
7878 , (.:?)
7979 , (.:!)
8080 , (.!=)
81− , tuple
82− , (>*<)
8381 , typeMismatch
8482
8583 , listEncoding
@@ -87,10 +85,12 @@ module Data.Aeson.Types.Instances
8785 , listParser
8886 ) where
8987
90−import Data.Aeson.Types.Instances.Tuple (tuple, (>*<))
88+import Data.Aeson.Types.Instances.Tuple ()
89+
90+import Data.Aeson.Encoding (Encoding (..), emptyArray_, dict, tuple, (>*<))
9191
9292import Control.Applicative (Const(..))
93−import Data.Aeson.Encode.Functions (builder, builder', encode, list, encodeWithKey, encodeMap)
93+import Data.Aeson.Encode.Functions (builder, encode)
9494import Data.Aeson.Functions (mapHashKeyVal, mapKey, mapKeyVal)
9595import Data.Aeson.Types.Class
9696import Data.Aeson.Types.Internal
@@ -398,7 +398,7 @@ instance ToJSON () where
398398 toJSON _ = emptyArray
399399 {-# INLINE toJSON #-}
400400
401− toEncoding _ = E.emptyArray_
401+ toEncoding _ = emptyArray_
402402 {-# INLINE toEncoding #-}
403403
404404instance FromJSON () where
@@ -823,11 +823,11 @@ instance ToJSONKey k => ToJSON1 (M.Map k) where
823823
824824 -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> M.Map k a -> Encoding
825825 liftToEncoding g _ = case toJSONKey of
826− ToJSONKeyText (_,f) -> encodeMap f g M.minViewWithKey M.foldrWithKey
827− ToJSONKeyValue (_,f) -> list (pairEncoding f) . M.toList
826+ ToJSONKeyText (_,f) -> dict f g M.foldrWithKey
827+ ToJSONKeyValue (_,f) -> listEncoding (pairEncoding f) . M.toList
828828 where
829829 -- pairEncoding :: (k -> Encoding) -> (k, a) -> Encoding
830− pairEncoding f (a, b) = tuple $ fromEncoding (f a) >*< builder' g b
830+ pairEncoding f (a, b) = tuple $ f a >*< g b
831831 {-# INLINE liftToEncoding #-}
832832
833833instance (FromJSONKey k, Ord k) => FromJSON1 (M.Map k) where
@@ -902,7 +902,7 @@ instance ToJSON1 Vector where
902902 {-# INLINE liftToJSON #-}
903903
904904 liftToEncoding to _ xs
905− | V.null xs = E.emptyArray_
905+ | V.null xs = emptyArray_
906906 | otherwise = Encoding $
907907 B.char7 '[' <> fromEncoding (to (V.unsafeHead xs)) <>
908908 V.foldr go (B.char7 ']') (V.unsafeTail xs)
@@ -919,7 +919,7 @@ instance (ToJSON a) => ToJSON (Vector a) where
919919
920920encodeVector :: (ToJSON a, VG.Vector v a) => v a -> Encoding
921921encodeVector xs
922− | VG.null xs = E.emptyArray_
922+ | VG.null xs = emptyArray_
923923 | otherwise = Encoding $
924924 B.char7 '[' <> builder (VG.unsafeHead xs) <>
925925 VG.foldr go (B.char7 ']') (VG.unsafeTail xs)
@@ -1006,11 +1006,11 @@ instance ToJSONKey k => ToJSON1 (H.HashMap k) where
10061006
10071007 -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> H.HashMap k a -> Encoding
10081008 liftToEncoding g _ = case toJSONKey of
1009− ToJSONKeyText (_,f) -> encodeWithKey f g H.foldrWithKey
1010− ToJSONKeyValue (_,f) -> list (pairEncoding f) . H.toList
1009+ ToJSONKeyText (_,f) -> dict f g H.foldrWithKey
1010+ ToJSONKeyValue (_,f) -> listEncoding (pairEncoding f) . H.toList
10111011 where
10121012 -- pairEncoding :: (k -> Encoding) -> (k, a) -> Encoding
1013− pairEncoding f (a, b) = tuple $ fromEncoding (f a) >*< builder' g b
1013+ pairEncoding f (a, b) = tuple $ f a >*< g b
10141014 {-# INLINE liftToEncoding #-}
10151015
10161016instance (ToJSON v, ToJSONKey k) => ToJSON (H.HashMap k v) where
@@ -1367,15 +1367,6 @@ withBool _ f (Bool arr) = f arr
13671367withBool expected _ v = typeMismatch expected v
13681368{-# INLINE withBool #-}
13691369
1370−instance KeyValue Pair where
1371− name .= value = (name, toJSON value)
1372− {-# INLINE (.=) #-}
1373−
1374−instance KeyValue Series where
1375− name .= value = Value . Encoding $
1376− E.text name <> B.char7 ':' <> builder value
1377− {-# INLINE (.=) #-}
1378−
13791370-- | Convert a value from JSON, failing if the types do not match.
13801371fromJSON :: (FromJSON a) => Value -> Result a
13811372fromJSON = parse parseJSON
Data/Aeson/Types/Instances/Tuple.hs+121−133
@@ -10,16 +10,15 @@
1010-- Portability: portable
1111--
1212-- Tuple instances
13−module Data.Aeson.Types.Instances.Tuple (tuple, (>*<)) where
13+module Data.Aeson.Types.Instances.Tuple () where
1414
15−import Data.Aeson.Encode.Functions (builder)
15+import Data.Aeson.Encoding (tuple, (>*<))
1616import Data.Aeson.Types.Class
1717import Data.Aeson.Types.Internal
1818import Data.Monoid ((<>))
1919
2020import qualified Data.Vector as V
2121import qualified Data.Vector.Mutable as VM (unsafeNew, unsafeWrite)
22−import qualified Data.ByteString.Builder as B
2322
2423#if MIN_VERSION_base(4,8,0)
2524#else
@@ -29,15 +28,6 @@ import Control.Applicative ((<$>), (<*>))
2928parseJSONElemAtIndex :: (Value -> Parser a) -> Int -> V.Vector Value -> Parser a
3029parseJSONElemAtIndex p idx ary = p (V.unsafeIndex ary idx) <?> Index idx
3130
32−(>*<) :: B.Builder -> B.Builder -> B.Builder
33−a >*< b = a <> B.char7 ',' <> b
34−{-# INLINE (>*<) #-}
35−infixr 6 >*<
36−
37−tuple :: B.Builder -> Encoding
38−tuple b = Encoding (B.char7 '[' <> b <> B.char7 ']')
39−{-# INLINE tuple #-}
40−
4131-- Local copy of withArray
4232withArray :: String -> (Array -> Parser a) -> Value -> Parser a
4333withArray _ f (Array arr) = f arr
@@ -57,8 +47,8 @@ instance ToJSON2 ((,) ) where
5747 {-# INLINE liftToJSON2 #-}
5848
5949 liftToEncoding2 toA _ toB _ (a, b) = tuple $
60− fromEncoding (toA a) >*<
61− fromEncoding (toB b)
50+ toA a >*<
51+ toB b
6252 {-# INLINE liftToEncoding2 #-}
6353
6454instance (ToJSON a) => ToJSON1 ((,) a) where
@@ -102,9 +92,9 @@ instance (ToJSON a) => ToJSON2 ((,,) a) where
10292 {-# INLINE liftToJSON2 #-}
10393
10494 liftToEncoding2 toB _ toC _ (a, b, c) = tuple $
105− builder a >*<
106− fromEncoding (toB b) >*<
107− fromEncoding (toC c)
95+ toEncoding a >*<
96+ toB b >*<
97+ toC c
10898 {-# INLINE liftToEncoding2 #-}
10999
110100instance (ToJSON a, ToJSON b) => ToJSON1 ((,,) a b) where
@@ -150,10 +140,10 @@ instance (ToJSON a, ToJSON b) => ToJSON2 ((,,,) a b) where
150140 {-# INLINE liftToJSON2 #-}
151141
152142 liftToEncoding2 toC _ toD _ (a, b, c, d) = tuple $
153− builder a >*<
154− builder b >*<
155− fromEncoding (toC c) >*<
156− fromEncoding (toD d)
143+ toEncoding a >*<
144+ toEncoding b >*<
145+ toC c >*<
146+ toD d
157147 {-# INLINE liftToEncoding2 #-}
158148
159149instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON1 ((,,,) a b c) where
@@ -201,11 +191,11 @@ instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON2 ((,,,,) a b c) where
201191 {-# INLINE liftToJSON2 #-}
202192
203193 liftToEncoding2 toD _ toE _ (a, b, c, d, e) = tuple $
204− builder a >*<
205− builder b >*<
206− builder c >*<
207− fromEncoding (toD d) >*<
208− fromEncoding (toE e)
194+ toEncoding a >*<
195+ toEncoding b >*<
196+ toEncoding c >*<
197+ toD d >*<
198+ toE e
209199 {-# INLINE liftToEncoding2 #-}
210200
211201instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON1 ((,,,,) a b c d) where
@@ -255,12 +245,12 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON2 ((,,,,,) a b c d) w
255245 {-# INLINE liftToJSON2 #-}
256246
257247 liftToEncoding2 toE _ toF _ (a, b, c, d, e, f) = tuple $
258− builder a >*<
259− builder b >*<
260− builder c >*<
261− builder d >*<
262− fromEncoding (toE e) >*<
263− fromEncoding (toF f)
248+ toEncoding a >*<
249+ toEncoding b >*<
250+ toEncoding c >*<
251+ toEncoding d >*<
252+ toE e >*<
253+ toF f
264254 {-# INLINE liftToEncoding2 #-}
265255
266256instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON1 ((,,,,,) a b c d e) where
@@ -312,13 +302,13 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON2 ((,,,,,,)
312302 {-# INLINE liftToJSON2 #-}
313303
314304 liftToEncoding2 toF _ toG _ (a, b, c, d, e, f, g) = tuple $
315− builder a >*<
316− builder b >*<
317− builder c >*<
318− builder d >*<
319− builder e >*<
320− fromEncoding (toF f) >*<
321− fromEncoding (toG g)
305+ toEncoding a >*<
306+ toEncoding b >*<
307+ toEncoding c >*<
308+ toEncoding d >*<
309+ toEncoding e >*<
310+ toF f >*<
311+ toG g
322312 {-# INLINE liftToEncoding2 #-}
323313
324314instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON1 ((,,,,,,) a b c d e f) where
@@ -372,14 +362,14 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON2
372362 {-# INLINE liftToJSON2 #-}
373363
374364 liftToEncoding2 toG _ toH _ (a, b, c, d, e, f, g, h) = tuple $
375− builder a >*<
376− builder b >*<
377− builder c >*<
378− builder d >*<
379− builder e >*<
380− builder f >*<
381− fromEncoding (toG g) >*<
382− fromEncoding (toH h)
365+ toEncoding a >*<
366+ toEncoding b >*<
367+ toEncoding c >*<
368+ toEncoding d >*<
369+ toEncoding e >*<
370+ toEncoding f >*<
371+ toG g >*<
372+ toH h
383373 {-# INLINE liftToEncoding2 #-}
384374
385375instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON1 ((,,,,,,,) a b c d e f g) where
@@ -435,15 +425,15 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g)
435425 {-# INLINE liftToJSON2 #-}
436426
437427 liftToEncoding2 toH _ toI _ (a, b, c, d, e, f, g, h, i) = tuple $
438− builder a >*<
439− builder b >*<
440− builder c >*<
441− builder d >*<
442− builder e >*<
443− builder f >*<
444− builder g >*<
445− fromEncoding (toH h) >*<
446− fromEncoding (toI i)
428+ toEncoding a >*<
429+ toEncoding b >*<
430+ toEncoding c >*<
431+ toEncoding d >*<
432+ toEncoding e >*<
433+ toEncoding f >*<
434+ toEncoding g >*<
435+ toH h >*<
436+ toI i
447437 {-# INLINE liftToEncoding2 #-}
448438
449439instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h) => ToJSON1 ((,,,,,,,,) a b c d e f g h) where
@@ -501,16 +491,16 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
501491 {-# INLINE liftToJSON2 #-}
502492
503493 liftToEncoding2 toI _ toJ _ (a, b, c, d, e, f, g, h, i, j) = tuple $
504− builder a >*<
505− builder b >*<
506− builder c >*<
507− builder d >*<
508− builder e >*<
509− builder f >*<
510− builder g >*<
511− builder h >*<
512− fromEncoding (toI i) >*<
513− fromEncoding (toJ j)
494+ toEncoding a >*<
495+ toEncoding b >*<
496+ toEncoding c >*<
497+ toEncoding d >*<
498+ toEncoding e >*<
499+ toEncoding f >*<
500+ toEncoding g >*<
501+ toEncoding h >*<
502+ toI i >*<
503+ toJ j
514504 {-# INLINE liftToEncoding2 #-}
515505
516506instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i) => ToJSON1 ((,,,,,,,,,) a b c d e f g h i) where
@@ -570,17 +560,17 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
570560 {-# INLINE liftToJSON2 #-}
571561
572562 liftToEncoding2 toJ _ toK _ (a, b, c, d, e, f, g, h, i, j, k) = tuple $
573− builder a >*<
574− builder b >*<
575− builder c >*<
576− builder d >*<
577− builder e >*<
578− builder f >*<
579− builder g >*<
580− builder h >*<
581− builder i >*<
582− fromEncoding (toJ j) >*<
583− fromEncoding (toK k)
563+ toEncoding a >*<
564+ toEncoding b >*<
565+ toEncoding c >*<
566+ toEncoding d >*<
567+ toEncoding e >*<
568+ toEncoding f >*<
569+ toEncoding g >*<
570+ toEncoding h >*<
571+ toEncoding i >*<
572+ toJ j >*<
573+ toK k
584574 {-# INLINE liftToEncoding2 #-}
585575
586576instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j) => ToJSON1 ((,,,,,,,,,,) a b c d e f g h i j) where
@@ -642,18 +632,18 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
642632 {-# INLINE liftToJSON2 #-}
643633
644634 liftToEncoding2 toK _ toL _ (a, b, c, d, e, f, g, h, i, j, k, l) = tuple $
645− builder a >*<
646− builder b >*<
647− builder c >*<
648− builder d >*<
649− builder e >*<
650− builder f >*<
651− builder g >*<
652− builder h >*<
653− builder i >*<
654− builder j >*<
655− fromEncoding (toK k) >*<
656− fromEncoding (toL l)
635+ toEncoding a >*<
636+ toEncoding b >*<
637+ toEncoding c >*<
638+ toEncoding d >*<
639+ toEncoding e >*<
640+ toEncoding f >*<
641+ toEncoding g >*<
642+ toEncoding h >*<
643+ toEncoding i >*<
644+ toEncoding j >*<
645+ toK k >*<
646+ toL l
657647 {-# INLINE liftToEncoding2 #-}
658648
659649instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k) => ToJSON1 ((,,,,,,,,,,,) a b c d e f g h i j k) where
@@ -717,19 +707,19 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
717707 {-# INLINE liftToJSON2 #-}
718708
719709 liftToEncoding2 toL _ toM _ (a, b, c, d, e, f, g, h, i, j, k, l, m) = tuple $
720− builder a >*<
721− builder b >*<
722− builder c >*<
723− builder d >*<
724− builder e >*<
725− builder f >*<
726− builder g >*<
727− builder h >*<
728− builder i >*<
729− builder j >*<
730− builder k >*<
731− fromEncoding (toL l) >*<
732− fromEncoding (toM m)
710+ toEncoding a >*<
711+ toEncoding b >*<
712+ toEncoding c >*<
713+ toEncoding d >*<
714+ toEncoding e >*<
715+ toEncoding f >*<
716+ toEncoding g >*<
717+ toEncoding h >*<
718+ toEncoding i >*<
719+ toEncoding j >*<
720+ toEncoding k >*<
721+ toL l >*<
722+ toM m
733723 {-# INLINE liftToEncoding2 #-}
734724
735725instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l) => ToJSON1 ((,,,,,,,,,,,,) a b c d e f g h i j k l) where
@@ -795,20 +785,20 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
795785 {-# INLINE liftToJSON2 #-}
796786
797787 liftToEncoding2 toM _ toN _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = tuple $
798− builder a >*<
799− builder b >*<
800− builder c >*<
801− builder d >*<
802− builder e >*<
803− builder f >*<
804− builder g >*<
805− builder h >*<
806− builder i >*<
807− builder j >*<
808− builder k >*<
809− builder l >*<
810− fromEncoding (toM m) >*<
811− fromEncoding (toN n)
788+ toEncoding a >*<
789+ toEncoding b >*<
790+ toEncoding c >*<
791+ toEncoding d >*<
792+ toEncoding e >*<
793+ toEncoding f >*<
794+ toEncoding g >*<
795+ toEncoding h >*<
796+ toEncoding i >*<
797+ toEncoding j >*<
798+ toEncoding k >*<
799+ toEncoding l >*<
800+ toM m >*<
801+ toN n
812802 {-# INLINE liftToEncoding2 #-}
813803
814804instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m) => ToJSON1 ((,,,,,,,,,,,,,) a b c d e f g h i j k l m) where
@@ -876,21 +866,21 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
876866 {-# INLINE liftToJSON2 #-}
877867
878868 liftToEncoding2 toN _ toO _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = tuple $
879− builder a >*<
880− builder b >*<
881− builder c >*<
882− builder d >*<
883− builder e >*<
884− builder f >*<
885− builder g >*<
886− builder h >*<
887− builder i >*<
888− builder j >*<
889− builder k >*<
890− builder l >*<
891− builder m >*<
892− fromEncoding (toN n) >*<
893− fromEncoding (toO o)
869+ toEncoding a >*<
870+ toEncoding b >*<
871+ toEncoding c >*<
872+ toEncoding d >*<
873+ toEncoding e >*<
874+ toEncoding f >*<
875+ toEncoding g >*<
876+ toEncoding h >*<
877+ toEncoding i >*<
878+ toEncoding j >*<
879+ toEncoding k >*<
880+ toEncoding l >*<
881+ toEncoding m >*<
882+ toN n >*<
883+ toO o
894884 {-# INLINE liftToEncoding2 #-}
895885
896886instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g, ToJSON h, ToJSON i, ToJSON j, ToJSON k, ToJSON l, ToJSON m, ToJSON n) => ToJSON1 ((,,,,,,,,,,,,,,) a b c d e f g h i j k l m n) where
@@ -935,5 +925,3 @@ instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f
935925instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d, FromJSON e, FromJSON f, FromJSON g, FromJSON h, FromJSON i, FromJSON j, FromJSON k, FromJSON l, FromJSON m, FromJSON n, FromJSON o) => FromJSON (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) where
936926 parseJSON = parseJSON2
937927 {-# INLINE parseJSON #-}
938−
939−
Data/Aeson/Types/Internal.hs−50
@@ -24,9 +24,6 @@ module Data.Aeson.Types.Internal
2424 (
2525 -- * Core JSON types
2626 Value(..)
27− , Encoding(..)
28− , unsafeToEncoding
29− , Series(..)
3027 , Array
3128 , emptyArray, isEmptyArray
3229 , Pair
@@ -67,7 +64,6 @@ import Control.Applicative
6764import Control.DeepSeq (NFData(..))
6865import Control.Monad (MonadPlus(..), ap)
6966import qualified Control.Monad.Fail as Fail
70−import Data.ByteString.Builder (Builder, char7, toLazyByteString)
7167import Data.Char (isLower, isUpper, toLower, isAlpha, isAlphaNum)
7268import Data.Data (Data)
7369import Data.Foldable (foldl')
@@ -338,52 +334,6 @@ data Value = Object !Object
338334 | Null
339335 deriving (Eq, Read, Show, Typeable, Data)
340336
341−-- | An encoding of a JSON value.
342−newtype Encoding = Encoding {
343− fromEncoding :: Builder
344− -- ^ Acquire the underlying bytestring builder.
345− } deriving (Semigroup,Monoid)
346−
347−-- | Make Encoding from Builder.
348−--
349−-- Use with care! You have to make sure that the passed Builder
350−-- is a valid JSON Encoding!
351−unsafeToEncoding :: Builder -> Encoding
352−unsafeToEncoding = Encoding
353−
354−instance Show Encoding where
355− show (Encoding e) = show (toLazyByteString e)
356−
357−instance Eq Encoding where
358− Encoding a == Encoding b = toLazyByteString a == toLazyByteString b
359−
360−instance Ord Encoding where
361− compare (Encoding a) (Encoding b) =
362− compare (toLazyByteString a) (toLazyByteString b)
363−
364−-- | A series of values that, when encoded, should be separated by
365−-- commas. Since 0.11.0.0, the '.=' operator is overloaded to create
366−-- either @(Text, Value)@ or 'Series'. You can use Series when
367−-- encoding directly to a bytestring builder as in the following
368−-- example:
369−--
370−-- > toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)
371−data Series = Empty
372− | Value Encoding
373− deriving (Typeable)
374−
375−instance Semigroup Series where
376− Empty <> a = a
377− Value a <> b =
378− Value $
379− a <> case b of
380− Empty -> mempty
381− Value c -> Encoding (char7 ',') <> c
382−
383−instance Monoid Series where
384− mempty = Empty
385− mappend = (<>)
386−
387337-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
388338-- serialization format as Microsoft .NET, whose
389339-- <https://msdn.microsoft.com/en-us/library/system.datetime(v=vs.110).aspx System.DateTime>
aeson.cabal+1
@@ -70,6 +70,7 @@ library
7070 exposed-modules:
7171 Data.Aeson
7272 Data.Aeson.Encode
73+ Data.Aeson.Encoding
7374 Data.Aeson.Internal
7475 Data.Aeson.Internal.Time
7576 Data.Aeson.Parser
benchmarks/aeson-benchmarks.cabal+1
@@ -15,6 +15,7 @@ library
1515
1616 exposed-modules:
1717 Data.Aeson
18+ Data.Aeson.Encoding
1819 Data.Aeson.Encode
1920 Data.Aeson.Encode.Builder
2021 Data.Aeson.Encode.Functions
tuple-instances.hs+4−4
@@ -1,5 +1,5 @@
11#!/usr/bin/env stack
2−{- stack --resolver=lts-5.9 runghc
2+{- stack --resolver=lts-6.0 runghc
33 --package mtl
44 --package dlist
55-}
@@ -45,9 +45,9 @@ tuple n = fold $ flip execState DList.empty $ do
4545 t [" liftToEncoding2 ", toPrev, " _ ", toLast, " _ ", vs', " = tuple $" ]
4646 forM_ (zip [0..] vs) $ \(i, v) -> t . (" " :) $ case i of
4747
48− _ | i == n - 1 -> [ "fromEncoding (", toLast, " ", v, ")" ]
49− _ | i == n - 2 -> [ "fromEncoding (", toPrev, " ", v, ") >*<" ]
50− _ | otherwise -> [ "builder ", v, " >*<" ]
48+ _ | i == n - 1 -> [ toLast, " ", v ]
49+ _ | i == n - 2 -> [ toPrev, " ", v, " >*<" ]
50+ _ | otherwise -> [ "toEncoding ", v, " >*<" ]
5151 t [" {-# INLINE liftToEncoding2 #-}" ]
5252 t []
5353