@@ -17,13 +17,15 @@ module Data.Aeson.Encode
1717 , encode
1818 ) where
1919
20−import Blaze.ByteString.Builder
21−import Blaze.ByteString.Builder.Char.Utf8
22−import Data.Attoparsec.Number (Number(..))
20+import Blaze.ByteString.Builder (Builder, fromByteString, toLazyByteString)
21+import Blaze.Text (double, integral)
2322import Data.Aeson.Types (ToJSON(..), Value(..))
23+import Data.Attoparsec.Number (Number(..))
2424import Data.Monoid (mappend)
25+import Data.Text.Encoding (encodeUtf8)
2526import Numeric (showHex)
26−import Blaze.Text (double, integral)
27+import qualified Blaze.ByteString.Builder.Char.Utf8 as Utf8
28+import qualified Blaze.ByteString.Builder.Char8 as Char8
2729import qualified Data.ByteString.Lazy.Char8 as L
2830import qualified Data.HashMap.Strict as H
2931import qualified Data.Text as T
@@ -31,27 +33,29 @@ import qualified Data.Vector as V
3133
3234-- | Encode a JSON value to a 'Builder'.
3335fromValue :: Value -> Builder
34−fromValue Null = fromByteString "null"
35−fromValue (Bool b) = fromByteString $ if b then "true" else "false"
36−fromValue (Number n) = fromNumber n
37−fromValue (String s) = string s
36+fromValue Null = {-# SCC "fromValue/Null" #-} fromByteString "null"
37+fromValue (Bool b) = {-# SCC "fromValue/Bool" #-}
38+ if b then fromByteString "true"
39+ else fromByteString "false"
40+fromValue (Number n) = {-# SCC "fromValue/Number" #-} fromNumber n
41+fromValue (String s) = {-# SCC "fromValue/String" #-} string s
3842fromValue (Array v)
39− | V.null v = fromByteString "[]"
40− | otherwise = fromChar '[' `mappend`
43+ | V.null v = {-# SCC "fromValue/Array" #-} fromByteString "[]"
44+ | otherwise = {-# SCC "fromValue/Array" #-}
45+ Char8.fromChar '[' `mappend`
4146 fromValue (V.unsafeHead v) `mappend`
42− V.foldr f (fromChar ']') (V.unsafeTail v)
43− where f a z = fromChar ',' `mappend` fromValue a `mappend` z
44−fromValue (Object m) =
47+ V.foldr f (Char8.fromChar ']') (V.unsafeTail v)
48+ where f a z = Char8.fromChar ',' `mappend` fromValue a `mappend` z
49+fromValue (Object m) = {-# SCC "fromValue/Object" #-}
4550 case H.toList m of
46− (x:xs) -> fromChar '{' `mappend`
47− one x `mappend`
48− foldr f (fromChar '}') xs
49− _ -> fromByteString "{}"
50− where f a z = fromChar ',' `mappend` one a `mappend` z
51− one (k,v) = string k `mappend` fromChar ':' `mappend` fromValue v
51+ (x:xs) -> Char8.fromChar '{' `mappend`
52+ one x `mappend` foldr f (Char8.fromChar '}') xs
53+ _ -> fromByteString "{}"
54+ where f a z = Char8.fromChar ',' `mappend` one a `mappend` z
55+ one (k,v) = string k `mappend` Char8.fromChar ':' `mappend` fromValue v
5256
5357string :: T.Text -> Builder
54−string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
58+string s = Char8.fromChar '"' `mappend` (quote s) `mappend` Char8.fromChar '"'
5559 where
5660 quote q = case T.uncons t of
5761 Just (c,t') -> fromText h `mappend` escape c `mappend` quote t'
@@ -64,10 +68,15 @@ string s = fromChar '"' `mappend` quote s `mappend` fromChar '"'
6468 escape '\r' = fromByteString "\\r"
6569 escape '\t' = fromByteString "\\t"
6670 escape c
67− | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
68− | otherwise = fromChar c
71+ | c < '\x20' = Char8.fromString $
72+ "\\u" ++ replicate (4 - length h) '0' ++ h
73+ | otherwise = Utf8.fromChar c
6974 where h = showHex (fromEnum c) ""
7075
76+-- The version in blaze-builder is way slower.
77+fromText :: T.Text -> Builder
78+fromText t = fromByteString (encodeUtf8 t)
79+
7180fromNumber :: Number -> Builder
7281fromNumber (I i) = integral i
7382fromNumber (D d)
@@ -76,5 +85,6 @@ fromNumber (D d)
7685
7786-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
7887encode :: ToJSON a => a -> L.ByteString
79−encode = toLazyByteString . fromValue . toJSON
88+encode = {-# SCC "encode" #-} toLazyByteString . fromValue .
89+ {-# SCC "toJSON" #-} toJSON
8090{-# INLINE encode #-}