on ae2dcc8 help sign in
.gitattributesdeleted−1
since splitsnapshots
unifiedsplit
@@ -1 +0,0 @@
1−tests/JSONTestSuite/* linguist-vendored
.gitignore−11
@@ -1,21 +1,10 @@
1dist
1dist
2−dist-newstyle
3−.ghc.environment.*
4.cabal-sandbox/
2.cabal-sandbox/
5cabal.sandbox.config
3cabal.sandbox.config
6−.stack-work/
7−.stack-work-bench/
8−*.yaml.lock
9
4
10*.o
5*.o
11*.hi
6*.hi
12*.nix
7*.nix
13−*.swp
14−.\#*
15−\#*
16−
17−# Emacs backup files
18−*~
19
8
20benchmarks/AesonEncode
9benchmarks/AesonEncode
21
10
.hlint.yamldeleted−11
@@ -1,11 +0,0 @@
1−# Ignore some builtin hints
2−- ignore:
3− name: "Reduce duplication"
4− within:
5− - Data.Aeson.Types.ToJSON
6−- ignore:
7− name: "Eta reduce"
8−- ignore:
9− name: "Use newtype instead of data"
10− within:
11− - Data.Aeson.Types.Internal
.travis.yml+16−43
@@ -12,58 +12,31 @@ cache:
12 - $HOME/.stack
12 - $HOME/.stack
13 - $HOME/.cabsnap
13 - $HOME/.cabsnap
14 - $HOME/.cabal/packages
14 - $HOME/.cabal/packages
15− - $HOME/.cabal/store
16
15
17before_cache:
16before_cache:
18 - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
17 - rm -fv $HOME/.cabal/packages/hackage.haskell.org/build-reports.log
19− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.*
18+ - rm -fv $HOME/.cabal/packages/hackage.haskell.org/00-index.tar
20− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/*.json
21− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.cache
22− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar
23− - rm -fv $HOME/.cabal/packages/hackage.haskell.org/01-index.tar.idx
24
19
25matrix:
20matrix:
26 include:
21 include:
27−
28− - env: BUILD=hlint CABALVER=2.2 GHCVER=8.4.4
29− compiler: ": #GHC 8.4.4"
30− addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.4], sources: [hvr-ghc]}}
31−
32− - env: BUILD=stack CABALVER=2.4 GHCVER=8.6.5 STACK_YAML=stack-bench.yaml
33− compiler: ": #GHC 8.6.5"
34− addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.5], sources: [hvr-ghc]}}
35−
36− - env: BUILD=stack CABALVER=2.2 GHCVER=8.6.5 STACK_YAML=stack-ffi-unescape.yaml
37− compiler: ": #GHC 8.6.5"
38− addons: {apt: {packages: [cabal-install-2.2,ghc-8.6.5], sources: [hvr-ghc]}}
39−
40− - env: BUILD=cabal2 CABALVER=3.0 GHCVER=8.8.1
41− compiler: ": #GHC 8.8.1"
42− addons: {apt: {packages: [cabal-install-3.0,ghc-8.8.1], sources: [hvr-ghc]}}
43−
44− - env: BUILD=cabal CABALVER=2.4 GHCVER=8.6.5
45− compiler: ": #GHC 8.6.5"
46− addons: {apt: {packages: [cabal-install-2.4,ghc-8.6.5], sources: [hvr-ghc]}}
47−
48− - env: BUILD=cabal CABALVER=2.2 GHCVER=8.4.4
22+ - env: BUILD=cabal CABALVER=1.16 GHCVER=7.4.2
49− compiler: ": #GHC 8.4.4"
23+ compiler: ": #GHC 7.4.2"
50− addons: {apt: {packages: [cabal-install-2.2,ghc-8.4.4], sources: [hvr-ghc]}}
24+ addons: {apt: {packages: [cabal-install-1.16,ghc-7.4.2], sources: [hvr-ghc]}}
51−
52− - env: BUILD=cabal CABALVER=2.0 GHCVER=8.2.2
53− compiler: ": #GHC 8.2.2"
54− addons: {apt: {packages: [cabal-install-2.0,ghc-8.2.2], sources: [hvr-ghc]}}
55−
56− - env: BUILD=cabal CABALVER=2.0 GHCVER=8.0.2
57− compiler: ": #GHC 8.0.2"
58− addons: {apt: {packages: [cabal-install-2.0,ghc-8.0.2], sources: [hvr-ghc]}}
59−
60− - env: BUILD=cabal CABALVER=1.22 GHCVER=7.10.3
25+ - env: BUILD=cabal CABALVER=1.16 GHCVER=7.6.3
61− compiler: ": #GHC 7.10.3"
26+ compiler: ": #GHC 7.6.3"
62− addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
27+ addons: {apt: {packages: [cabal-install-1.16,ghc-7.6.3], sources: [hvr-ghc]}}
63−
64 - env: BUILD=cabal CABALVER=1.18 GHCVER=7.8.4
28 - env: BUILD=cabal CABALVER=1.18 GHCVER=7.8.4
65 compiler: ": #GHC 7.8.4"
29 compiler: ": #GHC 7.8.4"
66 addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
30 addons: {apt: {packages: [cabal-install-1.18,ghc-7.8.4], sources: [hvr-ghc]}}
31+ - env: BUILD=cabal CABALVER=1.22 GHCVER=7.10.2
32+ compiler: ": #GHC 7.10.2"
33+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2], sources: [hvr-ghc]}}
34+ - env: BUILD=cabal CABALVER=1.24 GHCVER=8.0.1
35+ compiler: ": #GHC 8.0.1"
36+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.1], sources: [hvr-ghc]}}
37+ - env: BUILD=stack CABALVER=1.22 GHCVER=7.10.3
38+ compiler: ": #GHC 7.10.3"
39+ addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
67
40
68before_install:
41before_install:
69 - unset CC
42 - unset CC
CONTRIBUTING.mddeleted−98
@@ -1,98 +0,0 @@
1−# Documenting changes
2−
3−Changes that affect users of aeson should be mentioned in `changelog.md`. It should contain
4−* A description
5−* The level of change, see [PVP](https://wiki.haskell.org/Package_versioning_policy)
6−* Where applicable
7− * How to migrate existing code
8− * When it should be used
9− * What it supersedes
10−
11−Add this entry under an `## Upcoming` header above existing releases.
12−
13−The exact format of entries is not important as we'll go through everything before a release is made.
14−
15−# Style guide
16−
17−* 4 space indentation
18−
19−## Pragmas
20−
21−* One pragma on each line
22−* No alignment
23−* Sort lexicographically
24−
25−```haskell
26−{-# LANGUAGE BangPatterns #-}
27−{-# LANGUAGE CPP #-}
28−{-# LANGUAGE DataKinds #-}
29−```
30−
31−## Module declaration and exports
32−
33−* Opening paren on its own line
34−* Prefix with commas
35−* End with `) where`
36−
37−```haskell
38−module Data.Aeson.Types.ToJSON
39− (
40− -- * Core JSON classes
41− ToJSON(..)
42− -- * Liftings to unary and binary type constructors
43− , ToJSON1(..)
44− , toJSON1
45− ) where
46−```
47−
48−## Imports
49−
50−* No alignment of import lists or qualifications
51−* Sort lexicographically (qualified imports will be last)
52−* No space between types and constructor lists
53−* Sort identifiers in import lists lexicographically
54−
55−```haskell
56−import BarBar as B ((<>), foo)
57−import Foo as F
58−import Qux (Q(..), q)
59−import qualified A
60−```
61−
62−## Development Workflow (If you plan on using Stack)
63−
64−Here we outline a general workflow new contributors could adopt for a nice incremental development experience.
65−
66−The root folder consists of two stack-*.yaml config files.
67−
68−1. stack-nightly.yaml - Config file defines all the settings to build and test any changes.
69−2. stack-bench.yaml - Used to run benchmark tests.
70−3. stack-ffi-unescape.yaml - This is for replacing certain parts with a C-implementation.
71−
72−Therefore, a ghci development experience would be:
73−
74−1. `stack ghci --stack-yaml stack-nightly.yaml --test`
75−2. :r to recompile
76−3. `main` to run all tests, or `:main --pattern Foo` to run specific tests matched by pattern.
77−
78−Some discussion on this topic can also be found here [here](https://github.com/bos/aeson/issues/733)
79−
80−Of course before submitting a PR, the following steps are recommended:
81−
82−1. 'stack test --stack-yaml stack-nightly.yaml` - Run the entire suite of tests
83−2. `make hlint` - Run hlint on the source folders.
84−3. 'stack test --stack-yaml stack-bench.yaml` - Run the benchmark tests if you believe your changes could affect the benchmarks.
85−
86−## Development Workflow (If you plan on using Cabal)
87−
88−A ghci development experience would be:
89−
90−1. `cabal new-repl test:tests`
91−2. `:r` to recompile
92−3. `Main.main` to run all tests, or `:m Main; :main --pattern Foo` to run specific tests matched by pattern.
93−
94−Of course before submitting a PR, the following steps are recommended:
95−
96−1. `cabal new-test` - Run the entire suite of tests
97−2. `make hlint` - Run hlint on the source folders.
98−3. Uncomment the `benchmarks` line in `cabal.project` - Run the benchmark tests if you believe your changes could affect the benchmarks.
Data/Aeson.hs+15−94
@@ -1,4 +1,3 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2-- |
1-- |
3-- Module: Data.Aeson
2-- Module: Data.Aeson
4-- Copyright: (c) 2011-2016 Bryan O'Sullivan
3-- Copyright: (c) 2011-2016 Bryan O'Sullivan
@@ -39,16 +38,11 @@ module Data.Aeson
39 , eitherDecode
38 , eitherDecode
40 , eitherDecode'
39 , eitherDecode'
41 , encode
40 , encode
42− , encodeFile
43 -- ** Variants for strict bytestrings
41 -- ** Variants for strict bytestrings
44 , decodeStrict
42 , decodeStrict
45− , decodeFileStrict
46 , decodeStrict'
43 , decodeStrict'
47− , decodeFileStrict'
48 , eitherDecodeStrict
44 , eitherDecodeStrict
49− , eitherDecodeFileStrict
50 , eitherDecodeStrict'
45 , eitherDecodeStrict'
51− , eitherDecodeFileStrict'
52 -- * Core JSON types
46 -- * Core JSON types
53 , Value(..)
47 , Value(..)
54 , Encoding
48 , Encoding
@@ -63,18 +57,11 @@ module Data.Aeson
63 , fromJSON
57 , fromJSON
64 , ToJSON(..)
58 , ToJSON(..)
65 , KeyValue(..)
59 , KeyValue(..)
66− , (<?>)
67− , JSONPath
68 -- ** Keys for maps
60 -- ** Keys for maps
69 , ToJSONKey(..)
61 , ToJSONKey(..)
70 , ToJSONKeyFunction(..)
62 , ToJSONKeyFunction(..)
71 , FromJSONKey(..)
63 , FromJSONKey(..)
72 , FromJSONKeyFunction(..)
64 , FromJSONKeyFunction(..)
73− -- *** Generic keys
74− , GToJSONKey()
75− , genericToJSONKey
76− , GFromJSONKey()
77− , genericFromJSONKey
78 -- ** Liftings to unary and binary type constructors
65 -- ** Liftings to unary and binary type constructors
79 , FromJSON1(..)
66 , FromJSON1(..)
80 , parseJSON1
67 , parseJSON1
@@ -88,10 +75,8 @@ module Data.Aeson
88 , toEncoding2
75 , toEncoding2
89 -- ** Generic JSON classes and options
76 -- ** Generic JSON classes and options
90 , GFromJSON(..)
77 , GFromJSON(..)
91− , FromArgs(..)
92− , GToJSON
78+ , GToJSON(..)
93− , GToEncoding
79+ , GToEncoding(..)
94− , ToArgs(..)
95 , Zero
80 , Zero
96 , One
81 , One
97 , genericToJSON
82 , genericToJSON
@@ -100,34 +85,15 @@ module Data.Aeson
100 , genericLiftToEncoding
85 , genericLiftToEncoding
101 , genericParseJSON
86 , genericParseJSON
102 , genericLiftParseJSON
87 , genericLiftParseJSON
103− -- ** Generic and TH encoding configuration
104− , Options
105 , defaultOptions
88 , defaultOptions
106− -- *** Options fields
107− -- $optionsFields
108− , fieldLabelModifier
109− , constructorTagModifier
110− , allNullaryToStringTag
111− , omitNothingFields
112− , sumEncoding
113− , unwrapUnaryRecords
114− , tagSingleConstructors
115− -- *** Options utilities
116− , SumEncoding(..)
117− , camelTo2
118− , defaultTaggedObject
119− -- ** Options for object keys
120− , JSONKeyOptions
121− , keyModifier
122− , defaultJSONKeyOptions
123
89
124 -- * Inspecting @'Value's@
90 -- * Inspecting @'Value's@
125 , withObject
91 , withObject
126 , withText
92 , withText
127 , withArray
93 , withArray
94+ , withNumber
128 , withScientific
95 , withScientific
129 , withBool
96 , withBool
130− , withEmbeddedJSON
131 -- * Constructors and accessors
97 -- * Constructors and accessors
132 , Series
98 , Series
133 , pairs
99 , pairs
@@ -140,29 +106,18 @@ module Data.Aeson
140 -- * Parsing
106 -- * Parsing
141 , json
107 , json
142 , json'
108 , json'
143− , parseIndexedJSON
144 ) where
109 ) where
145
110
146−import Prelude.Compat
147−
148−import Data.Aeson.Types.FromJSON (ifromJSON, parseIndexedJSON)
111+import Data.Aeson.Types.FromJSON (ifromJSON)
149−import Data.Aeson.Encoding (encodingToLazyByteString)
112+import Data.Aeson.Encode (encode)
150−import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith, eitherDecodeWith, eitherDecodeStrictWith, jsonEOF, json, jsonEOF', json')
113+import Data.Aeson.Parser.Internal (decodeWith, decodeStrictWith,
114+ eitherDecodeWith, eitherDecodeStrictWith,
115+ jsonEOF, json, jsonEOF', json')
151import Data.Aeson.Types
116import Data.Aeson.Types
152−import Data.Aeson.Types.Internal (JSONPath, formatError, (<?>))
117+import Data.Aeson.Types.Internal (JSONPath, formatError)
153import qualified Data.ByteString as B
118import qualified Data.ByteString as B
154import qualified Data.ByteString.Lazy as L
119import qualified Data.ByteString.Lazy as L
155
120
156−-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
157−--
158−-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.
159−encode :: (ToJSON a) => a -> L.ByteString
160−encode = encodingToLazyByteString . toEncoding
161−
162−-- | Efficiently serialize a JSON value as a lazy 'L.ByteString' and write it to a file.
163−encodeFile :: (ToJSON a) => FilePath -> a -> IO ()
164−encodeFile fp = L.writeFile fp . encode
165−
166-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
121-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
167-- If this fails due to incomplete or invalid input, 'Nothing' is
122-- If this fails due to incomplete or invalid input, 'Nothing' is
168-- returned.
123-- returned.
@@ -189,18 +144,6 @@ decodeStrict :: (FromJSON a) => B.ByteString -> Maybe a
189decodeStrict = decodeStrictWith jsonEOF fromJSON
144decodeStrict = decodeStrictWith jsonEOF fromJSON
190{-# INLINE decodeStrict #-}
145{-# INLINE decodeStrict #-}
191
146
192−-- | Efficiently deserialize a JSON value from a file.
193−-- If this fails due to incomplete or invalid input, 'Nothing' is
194−-- returned.
195−--
196−-- The input file's content must consist solely of a JSON document,
197−-- with no trailing data except for whitespace.
198−--
199−-- This function parses immediately, but defers conversion. See
200−-- 'json' for details.
201−decodeFileStrict :: (FromJSON a) => FilePath -> IO (Maybe a)
202−decodeFileStrict = fmap decodeStrict . B.readFile
203−
204-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
147-- | Efficiently deserialize a JSON value from a lazy 'L.ByteString'.
205-- If this fails due to incomplete or invalid input, 'Nothing' is
148-- If this fails due to incomplete or invalid input, 'Nothing' is
206-- returned.
149-- returned.
@@ -227,18 +170,6 @@ decodeStrict' :: (FromJSON a) => B.ByteString -> Maybe a
227decodeStrict' = decodeStrictWith jsonEOF' fromJSON
170decodeStrict' = decodeStrictWith jsonEOF' fromJSON
228{-# INLINE decodeStrict' #-}
171{-# INLINE decodeStrict' #-}
229
172
230−-- | Efficiently deserialize a JSON value from a file.
231−-- If this fails due to incomplete or invalid input, 'Nothing' is
232−-- returned.
233−--
234−-- The input file's content must consist solely of a JSON document,
235−-- with no trailing data except for whitespace.
236−--
237−-- This function parses and performs conversion immediately. See
238−-- 'json'' for details.
239−decodeFileStrict' :: (FromJSON a) => FilePath -> IO (Maybe a)
240−decodeFileStrict' = fmap decodeStrict' . B.readFile
241−
242eitherFormatError :: Either (JSONPath, String) a -> Either String a
173eitherFormatError :: Either (JSONPath, String) a -> Either String a
243eitherFormatError = either (Left . uncurry formatError) Right
174eitherFormatError = either (Left . uncurry formatError) Right
244{-# INLINE eitherFormatError #-}
175{-# INLINE eitherFormatError #-}
@@ -254,12 +185,6 @@ eitherDecodeStrict =
254 eitherFormatError . eitherDecodeStrictWith jsonEOF ifromJSON
185 eitherFormatError . eitherDecodeStrictWith jsonEOF ifromJSON
255{-# INLINE eitherDecodeStrict #-}
186{-# INLINE eitherDecodeStrict #-}
256
187
257−-- | Like 'decodeFileStrict' but returns an error message when decoding fails.
258−eitherDecodeFileStrict :: (FromJSON a) => FilePath -> IO (Either String a)
259−eitherDecodeFileStrict =
260− fmap (eitherFormatError . eitherDecodeStrictWith jsonEOF ifromJSON) . B.readFile
261−{-# INLINE eitherDecodeFileStrict #-}
262−
263-- | Like 'decode'' but returns an error message when decoding fails.
188-- | Like 'decode'' but returns an error message when decoding fails.
264eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
189eitherDecode' :: (FromJSON a) => L.ByteString -> Either String a
265eitherDecode' = eitherFormatError . eitherDecodeWith jsonEOF' ifromJSON
190eitherDecode' = eitherFormatError . eitherDecodeWith jsonEOF' ifromJSON
@@ -271,12 +196,6 @@ eitherDecodeStrict' =
271 eitherFormatError . eitherDecodeStrictWith jsonEOF' ifromJSON
196 eitherFormatError . eitherDecodeStrictWith jsonEOF' ifromJSON
272{-# INLINE eitherDecodeStrict' #-}
197{-# INLINE eitherDecodeStrict' #-}
273
198
274−-- | Like 'decodeFileStrict'' but returns an error message when decoding fails.
275−eitherDecodeFileStrict' :: (FromJSON a) => FilePath -> IO (Either String a)
276−eitherDecodeFileStrict' =
277− fmap (eitherFormatError . eitherDecodeStrictWith jsonEOF' ifromJSON) . B.readFile
278−{-# INLINE eitherDecodeFileStrict' #-}
279−
280-- $use
199-- $use
281--
200--
282-- This section contains basic information on the different ways to
201-- This section contains basic information on the different ways to
@@ -346,9 +265,11 @@ eitherDecodeFileStrict' =
346-- > {-# LANGUAGE OverloadedStrings #-}
265-- > {-# LANGUAGE OverloadedStrings #-}
347-- >
266-- >
348-- > instance FromJSON Person where
267-- > instance FromJSON Person where
349−-- > parseJSON = withObject "Person" $ \v -> Person
268+-- > parseJSON (Object v) = Person <$>
350−-- > <$> v .: "name"
269+-- > v .: "name" <*>
351−-- > <*> v .: "age"
270+-- > v .: "age"
271+-- > -- A non-Object value is of the wrong type, so fail.
272+-- > parseJSON _ = empty
352--
273--
353-- We can now parse the JSON data like so:
274-- We can now parse the JSON data like so:
354--
275--
@@ -438,7 +359,7 @@ eitherDecodeFileStrict' =
438-- The 'Object' type contains JSON objects:
359-- The 'Object' type contains JSON objects:
439--
360--
440-- > λ> decode "{\"name\":\"Dave\",\"age\":2}" :: Maybe Object
361-- > λ> decode "{\"name\":\"Dave\",\"age\":2}" :: Maybe Object
441−-- > Just (fromList [("name",String "Dave"),("age",Number 2)])
362+-- > Just (fromList) [("name",String "Dave"),("age",Number 2)]
442--
363--
443-- You can extract values from it with a parser using 'parse',
364-- You can extract values from it with a parser using 'parse',
444-- 'parseEither' or, in this example, 'parseMaybe':
365-- 'parseEither' or, in this example, 'parseMaybe':
Data/Aeson/Encode.hs+94−15
@@ -1,4 +1,5 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2+
2-- |
3-- |
3-- Module: Data.Aeson.Encode
4-- Module: Data.Aeson.Encode
4-- Copyright: (c) 2012-2016 Bryan O'Sullivan
5-- Copyright: (c) 2012-2016 Bryan O'Sullivan
@@ -8,24 +9,102 @@
8-- Stability: experimental
9-- Stability: experimental
9-- Portability: portable
10-- Portability: portable
10--
11--
11−-- This module is left to supply limited backwards-compatibility.
12+-- Efficiently serialize a JSON value.
13+--
14+-- Most frequently, you'll probably want to encode straight to UTF-8
15+-- (the standard JSON encoding) using 'encode'.
16+--
17+-- You can use the conversions to 'Builder's when embedding JSON messages as
18+-- parts of a protocol.
19+module Data.Aeson.Encode
20+ ( encode
12
21
13−module Data.Aeson.Encode {-# DEPRECATED "Use Data.Aeson or Data.Aeson.Text instead" #-}
22+ -- * Encoding to Builders
14− (
23+ , encodeToBuilder
15− encode
16 , encodeToTextBuilder
24 , encodeToTextBuilder
25+
26+ -- * Deprecated
27+ , fromValue
17 ) where
28 ) where
18
29
30+import Data.Aeson.Encode.Builder (encodeToBuilder)
31+import Data.Aeson.Types (Value(..), ToJSON (..))
32+import Data.Aeson.Encoding (fromEncoding)
33+import Data.Monoid ((<>))
34+import Data.Scientific (FPFormat(..), Scientific, base10Exponent)
35+import Data.Text.Lazy.Builder
36+import Data.Text.Lazy.Builder.Scientific (formatScientificBuilder)
37+
38+import Numeric (showHex)
39+import qualified Data.ByteString.Builder as B
40+import qualified Data.HashMap.Strict as H
41+import qualified Data.Text as T
42+import qualified Data.Vector as V
43+import qualified Data.ByteString.Lazy as L
44+
45+-- | Efficiently serialize a JSON value as a lazy 'L.ByteString'.
46+--
47+-- This is implemented in terms of the 'ToJSON' class's 'toEncoding' method.
48+encode :: ToJSON a => a -> L.ByteString
49+encode = B.toLazyByteString . fromEncoding . toEncoding
50+{-# INLINE encode #-}
51+
52+-- | Encode a JSON 'Value' to a "Data.Text" 'Builder', which can be
53+-- embedded efficiently in a text-based protocol.
54+--
55+-- If you are going to immediately encode straight to a
56+-- 'L.ByteString', it is more efficient to use 'encodeToBuilder'
57+-- instead.
58+encodeToTextBuilder :: Value -> Builder
59+encodeToTextBuilder =
60+ go
61+ where
62+ go Null = {-# SCC "go/Null" #-} "null"
63+ go (Bool b) = {-# SCC "go/Bool" #-} if b then "true" else "false"
64+ go (Number s) = {-# SCC "go/Number" #-} fromScientific s
65+ go (String s) = {-# SCC "go/String" #-} string s
66+ go (Array v)
67+ | V.null v = {-# SCC "go/Array" #-} "[]"
68+ | otherwise = {-# SCC "go/Array" #-}
69+ singleton '[' <>
70+ go (V.unsafeHead v) <>
71+ V.foldr f (singleton ']') (V.unsafeTail v)
72+ where f a z = singleton ',' <> go a <> z
73+ go (Object m) = {-# SCC "go/Object" #-}
74+ case H.toList m of
75+ (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs
76+ _ -> "{}"
77+ where f a z = singleton ',' <> one a <> z
78+ one (k,v) = string k <> singleton ':' <> go v
79+
80+{-# DEPRECATED fromValue "Use 'encodeToTextBuilder' instead" #-}
81+fromValue :: Value -> Builder
82+fromValue = encodeToTextBuilder
19
83
20−import Data.ByteString.Lazy (ByteString)
84+string :: T.Text -> Builder
21−import Data.Text.Lazy.Builder (Builder)
85+string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'
22−import qualified Data.Aeson as A
86+ where
23−import qualified Data.Aeson.Text as A
87+ quote q = case T.uncons t of
88+ Nothing -> fromText h
89+ Just (!c,t') -> fromText h <> escape c <> quote t'
90+ where (h,t) = {-# SCC "break" #-} T.break isEscape q
91+ isEscape c = c == '\"' ||
92+ c == '\\' ||
93+ c < '\x20'
94+ escape '\"' = "\\\""
95+ escape '\\' = "\\\\"
96+ escape '\n' = "\\n"
97+ escape '\r' = "\\r"
98+ escape '\t' = "\\t"
24
99
25−encode :: A.ToJSON a => a -> ByteString
100+ escape c
26−encode = A.encode
101+ | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
27−{-# DEPRECATED encode "Use encode from Data.Aeson" #-}
102+ | otherwise = singleton c
103+ where h = showHex (fromEnum c) ""
28
104
29−encodeToTextBuilder :: A.Value -> Builder
105+fromScientific :: Scientific -> Builder
30−encodeToTextBuilder = A.encodeToTextBuilder
106+fromScientific s = formatScientificBuilder format prec s
31−{-# DEPRECATED encodeToTextBuilder "Use encodeTotextBuilder from Data.Aeson.Text" #-}
107+ where
108+ (format, prec)
109+ | base10Exponent s < 0 = (Generic, Nothing)
110+ | otherwise = (Fixed, Just 0)
Data/Aeson/Encoding/Builder.hs → Data/Aeson/Encode/Builder.hsrenamed+26−29
@@ -1,8 +1,7 @@
1−{-# LANGUAGE BangPatterns #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
2+
3−{-# LANGUAGE TupleSections #-}
4-- |
3-- |
5−-- Module: Data.Aeson.Encoding.Builder
4+-- Module: Data.Aeson.Encode.Builder
6-- Copyright: (c) 2011 MailRank, Inc.
5-- Copyright: (c) 2011 MailRank, Inc.
7-- (c) 2013 Simon Meier <iridcode@gmail.com>
6-- (c) 2013 Simon Meier <iridcode@gmail.com>
8-- License: BSD3
7-- License: BSD3
@@ -12,7 +11,7 @@
12--
11--
13-- Efficiently serialize a JSON value using the UTF-8 encoding.
12-- Efficiently serialize a JSON value using the UTF-8 encoding.
14
13
15−module Data.Aeson.Encoding.Builder
14+module Data.Aeson.Encode.Builder
16 (
15 (
17 encodeToBuilder
16 encodeToBuilder
18 , null_
17 , null_
@@ -25,7 +24,7 @@ module Data.Aeson.Encoding.Builder
25 , string
24 , string
26 , unquoted
25 , unquoted
27 , quote
26 , quote
28− , scientific
27+ , number
29 , day
28 , day
30 , localTime
29 , localTime
31 , utcTime
30 , utcTime
@@ -36,23 +35,21 @@ module Data.Aeson.Encoding.Builder
36 , ascii5
35 , ascii5
37 ) where
36 ) where
38
37
39−import Prelude.Compat
40−
41import Data.Aeson.Internal.Time
38import Data.Aeson.Internal.Time
42import Data.Aeson.Types.Internal (Value (..))
39import Data.Aeson.Types.Internal (Value (..))
43import Data.ByteString.Builder as B
40import Data.ByteString.Builder as B
44import Data.ByteString.Builder.Prim as BP
41import Data.ByteString.Builder.Prim as BP
45import Data.ByteString.Builder.Scientific (scientificBuilder)
42import Data.ByteString.Builder.Scientific (scientificBuilder)
46import Data.Char (chr, ord)
43import Data.Char (chr, ord)
47−import Data.Semigroup ((<>))
44+import Data.Monoid ((<>))
48import Data.Scientific (Scientific, base10Exponent, coefficient)
45import Data.Scientific (Scientific, base10Exponent, coefficient)
49−import Data.Text.Encoding (encodeUtf8BuilderEscaped)
50import Data.Time (UTCTime(..))
46import Data.Time (UTCTime(..))
51import Data.Time.Calendar (Day(..), toGregorian)
47import Data.Time.Calendar (Day(..), toGregorian)
52import Data.Time.LocalTime
48import Data.Time.LocalTime
53import Data.Word (Word8)
49import Data.Word (Word8)
54import qualified Data.HashMap.Strict as HMS
50import qualified Data.HashMap.Strict as HMS
55import qualified Data.Text as T
51import qualified Data.Text as T
52+import qualified Data.Text.Encoding as TE
56import qualified Data.Vector as V
53import qualified Data.Vector as V
57
54
58-- | Encode a JSON value to a "Data.ByteString" 'B.Builder'.
55-- | Encode a JSON value to a "Data.ByteString" 'B.Builder'.
@@ -62,7 +59,7 @@ import qualified Data.Vector as V
62encodeToBuilder :: Value -> Builder
59encodeToBuilder :: Value -> Builder
63encodeToBuilder Null = null_
60encodeToBuilder Null = null_
64encodeToBuilder (Bool b) = bool b
61encodeToBuilder (Bool b) = bool b
65−encodeToBuilder (Number n) = scientific n
62+encodeToBuilder (Number n) = number n
66encodeToBuilder (String s) = text s
63encodeToBuilder (String s) = text s
67encodeToBuilder (Array v) = array v
64encodeToBuilder (Array v) = array v
68encodeToBuilder (Object m) = object m
65encodeToBuilder (Object m) = object m
@@ -101,7 +98,7 @@ text t = B.char8 '"' <> unquoted t <> B.char8 '"'
101
98
102-- | Encode a JSON string, without enclosing quotes.
99-- | Encode a JSON string, without enclosing quotes.
103unquoted :: T.Text -> Builder
100unquoted :: T.Text -> Builder
104−unquoted = encodeUtf8BuilderEscaped escapeAscii
101+unquoted = TE.encodeUtf8BuilderEscaped escapeAscii
105
102
106-- | Add quotes surrounding a builder
103-- | Add quotes surrounding a builder
107quote :: Builder -> Builder
104quote :: Builder -> Builder
@@ -120,7 +117,7 @@ escapeAscii =
120 BP.condB (== c2w '\n' ) (ascii2 ('\\','n' )) $
117 BP.condB (== c2w '\n' ) (ascii2 ('\\','n' )) $
121 BP.condB (== c2w '\r' ) (ascii2 ('\\','r' )) $
118 BP.condB (== c2w '\r' ) (ascii2 ('\\','r' )) $
122 BP.condB (== c2w '\t' ) (ascii2 ('\\','t' )) $
119 BP.condB (== c2w '\t' ) (ascii2 ('\\','t' )) $
123− BP.liftFixedToBounded hexEscape -- fallback for chars < 0x20
120+ (BP.liftFixedToBounded hexEscape) -- fallback for chars < 0x20
124 where
121 where
125 hexEscape :: BP.FixedPrim Word8
122 hexEscape :: BP.FixedPrim Word8
126 hexEscape = (\c -> ('\\', ('u', fromIntegral c))) BP.>$<
123 hexEscape = (\c -> ('\\', ('u', fromIntegral c))) BP.>$<
@@ -131,9 +128,9 @@ c2w :: Char -> Word8
131c2w c = fromIntegral (ord c)
128c2w c = fromIntegral (ord c)
132
129
133-- | Encode a JSON number.
130-- | Encode a JSON number.
134−scientific :: Scientific -> Builder
131+number :: Scientific -> Builder
135−scientific s
132+number s
136− | e < 0 || e > 1024 = scientificBuilder s
133+ | e < 0 = scientificBuilder s
137 | otherwise = B.integerDec (coefficient s * 10 ^ e)
134 | otherwise = B.integerDec (coefficient s * 10 ^ e)
138 where
135 where
139 e = base10Exponent s
136 e = base10Exponent s
@@ -145,27 +142,27 @@ emptyObject_ :: Builder
145emptyObject_ = BP.primBounded (ascii2 ('{','}')) ()
142emptyObject_ = BP.primBounded (ascii2 ('{','}')) ()
146
143
147ascii2 :: (Char, Char) -> BP.BoundedPrim a
144ascii2 :: (Char, Char) -> BP.BoundedPrim a
148−ascii2 cs = BP.liftFixedToBounded $ const cs BP.>$< BP.char7 >*< BP.char7
145+ascii2 cs = BP.liftFixedToBounded $ (const cs) BP.>$< BP.char7 >*< BP.char7
149{-# INLINE ascii2 #-}
146{-# INLINE ascii2 #-}
150
147
151ascii4 :: (Char, (Char, (Char, Char))) -> BP.BoundedPrim a
148ascii4 :: (Char, (Char, (Char, Char))) -> BP.BoundedPrim a
152−ascii4 cs = BP.liftFixedToBounded $ const cs >$<
149+ascii4 cs = BP.liftFixedToBounded $ (const cs) >$<
153 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
150 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
154{-# INLINE ascii4 #-}
151{-# INLINE ascii4 #-}
155
152
156ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BP.BoundedPrim a
153ascii5 :: (Char, (Char, (Char, (Char, Char)))) -> BP.BoundedPrim a
157−ascii5 cs = BP.liftFixedToBounded $ const cs >$<
154+ascii5 cs = BP.liftFixedToBounded $ (const cs) >$<
158 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
155 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
159{-# INLINE ascii5 #-}
156{-# INLINE ascii5 #-}
160
157
161ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BP.BoundedPrim a
158ascii6 :: (Char, (Char, (Char, (Char, (Char, Char))))) -> BP.BoundedPrim a
162−ascii6 cs = BP.liftFixedToBounded $ const cs >$<
159+ascii6 cs = BP.liftFixedToBounded $ (const cs) >$<
163 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
160 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
164{-# INLINE ascii6 #-}
161{-# INLINE ascii6 #-}
165
162
166ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char)))))))
163ascii8 :: (Char, (Char, (Char, (Char, (Char, (Char, (Char, Char)))))))
167 -> BP.BoundedPrim a
164 -> BP.BoundedPrim a
168−ascii8 cs = BP.liftFixedToBounded $ const cs >$<
165+ascii8 cs = BP.liftFixedToBounded $ (const cs) >$<
169 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*<
166 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7 >*<
170 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
167 BP.char7 >*< BP.char7 >*< BP.char7 >*< BP.char7
171{-# INLINE ascii8 #-}
168{-# INLINE ascii8 #-}
@@ -178,13 +175,12 @@ day dd = encodeYear yr <>
178 !(T dh dl) = twoDigits d
175 !(T dh dl) = twoDigits d
179 encodeYear y
176 encodeYear y
180 | y >= 1000 = B.integerDec y
177 | y >= 1000 = B.integerDec y
181− | y >= 0 = BP.primBounded (ascii4 (padYear y)) ()
178+ | y > 0 =
182− | y >= -999 = BP.primBounded (ascii5 ('-',padYear (- y))) ()
183− | otherwise = B.integerDec y
184− padYear y =
185− let (ab,c) = fromIntegral y `quotRem` 10
179+ let (ab,c) = fromIntegral y `quotRem` 10
186− (a,b) = ab `quotRem` 10
180+ (a,b) = ab `quotRem` 10
187− in ('0',(digit a,(digit b,digit c)))
181+ in BP.primBounded (ascii4 ('0',(digit a,(digit b,digit c)))) ()
182+ | otherwise =
183+ error "Data.Aeson.Encode.Builder.day: years BCE not supported"
188{-# INLINE day #-}
184{-# INLINE day #-}
189
185
190timeOfDay :: TimeOfDay -> Builder
186timeOfDay :: TimeOfDay -> Builder
@@ -201,7 +197,7 @@ timeOfDay64 (TOD h m s)
201 !(T mh ml) = twoDigits m
197 !(T mh ml) = twoDigits m
202 !(T sh sl) = twoDigits (fromIntegral real)
198 !(T sh sl) = twoDigits (fromIntegral real)
203 (real,frac) = s `quotRem` pico
199 (real,frac) = s `quotRem` pico
204− showFrac = ('.',) >$< (BP.liftFixedToBounded BP.char7 >*< trunc12)
200+ showFrac = (\x -> ('.', x)) >$< (BP.liftFixedToBounded BP.char7 >*< trunc12)
205 trunc12 = (`quotRem` micro) >$<
201 trunc12 = (`quotRem` micro) >$<
206 BP.condB (\(_,y) -> y == 0) (fst >$< trunc6) (digits6 >*< trunc6)
202 BP.condB (\(_,y) -> y == 0) (fst >$< trunc6) (digits6 >*< trunc6)
207 digits6 = ((`quotRem` milli) . fromIntegral) >$< (digits3 >*< digits3)
203 digits6 = ((`quotRem` milli) . fromIntegral) >$< (digits3 >*< digits3)
@@ -219,6 +215,7 @@ timeOfDay64 (TOD h m s)
219 pico = 1000000000000 -- number of picoseconds in 1 second
215 pico = 1000000000000 -- number of picoseconds in 1 second
220 micro = 1000000 -- number of microseconds in 1 second
216 micro = 1000000 -- number of microseconds in 1 second
221 milli = 1000 -- number of milliseconds in 1 second
217 milli = 1000 -- number of milliseconds in 1 second
218+{-# INLINE timeOfDay64 #-}
222
219
223timeZone :: TimeZone -> Builder
220timeZone :: TimeZone -> Builder
224timeZone (TimeZone off _ _)
221timeZone (TimeZone off _ _)
Data/Aeson/Encode/Functions.hsnew file+14
@@ -0,0 +1,14 @@
1+{-# LANGUAGE CPP #-}
2+
3+module Data.Aeson.Encode.Functions
4+ (
5+ builder
6+ ) where
7+
8+import Data.Aeson.Encoding
9+import Data.Aeson.Types.Class
10+import Data.ByteString.Builder (Builder)
11+import Data.Monoid ((<>))
12+
13+
14+{-# INLINE builder #-}
Data/Aeson/Encoding.hs−36
@@ -1,55 +1,19 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−-- |
3−--
4−-- Functions in this module return well-formed 'Encoding''.
5−-- Polymorphic variants, which return @'Encoding' a@, return a textual JSON
6−-- value, so it can be used as both @'Encoding'' 'Text'@ and @'Encoding' = 'Encoding'' 'Value'@.
7−
8module Data.Aeson.Encoding
1module Data.Aeson.Encoding
9 (
2 (
10 -- * Encoding
3 -- * Encoding
11 Encoding
4 Encoding
12− , Encoding'
13− , encodingToLazyByteString
14 , fromEncoding
5 , fromEncoding
15 , unsafeToEncoding
6 , unsafeToEncoding
16 , Series
7 , Series
17 , pairs
8 , pairs
18− , pair
19− , pairStr
20− , pair'
21 -- * Predicates
9 -- * Predicates
22 , nullEncoding
10 , nullEncoding
23 -- * Encoding constructors
11 -- * Encoding constructors
24 , emptyArray_
12 , emptyArray_
25 , emptyObject_
13 , emptyObject_
26 , text
14 , text
27− , lazyText
28− , string
29 , list
15 , list
30 , dict
16 , dict
31− , null_
32− , bool
33− -- ** Decimal numbers
34− , int8, int16, int32, int64, int
35− , word8, word16, word32, word64, word
36− , integer, float, double, scientific
37−
38− -- ** Decimal numbers as Text
39− , int8Text, int16Text, int32Text, int64Text, intText
40− , word8Text, word16Text, word32Text, word64Text, wordText
41− , integerText, floatText, doubleText, scientificText
42−
43− -- ** Time
44− , day
45− , localTime
46− , utcTime
47− , timeOfDay
48− , zonedTime
49−
50− -- ** value
51− , value
52 ) where
17 ) where
53
18
54−
55import Data.Aeson.Encoding.Internal
19import Data.Aeson.Encoding.Internal
Data/Aeson/Encoding/Internal.hs+53−258
@@ -1,115 +1,65 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
1+{-# LANGUAGE CPP, GeneralizedNewtypeDeriving, DeriveDataTypeable, RankNTypes #-}
2−{-# LANGUAGE EmptyDataDecls #-}
3−{-# LANGUAGE NoImplicitPrelude #-}
4−{-# LANGUAGE OverloadedStrings #-}
5−{-# LANGUAGE RankNTypes #-}
6−
7module Data.Aeson.Encoding.Internal
2module Data.Aeson.Encoding.Internal
8 (
3 (
9 -- * Encoding
4 -- * Encoding
10− Encoding' (..)
5+ Encoding (..) -- TODO: export fromEncoding for now
11− , Encoding
6+ , fromEncoding
12− , encodingToLazyByteString
13 , unsafeToEncoding
7 , unsafeToEncoding
14− , retagEncoding
8+ , Series (..) -- TODO: don't export constructor
15− , Series (..)
16 , pairs
9 , pairs
17− , pair
18− , pairStr
19− , pair'
20 -- * Predicates
10 -- * Predicates
21 , nullEncoding
11 , nullEncoding
22 -- * Encoding constructors
12 -- * Encoding constructors
23 , emptyArray_
13 , emptyArray_
24 , emptyObject_
14 , emptyObject_
25− , wrapObject
26 , wrapArray
15 , wrapArray
27− , null_
16+ , wrapObject
28− , bool
29 , text
17 , text
30− , lazyText
31− , string
32 , list
18 , list
33 , dict
19 , dict
34 , tuple
20 , tuple
35 , (>*<)
21 , (>*<)
36− , InArray
22+ -- ** chars
37− , empty
38− , (><)
39− , econcat
40− -- ** Decimal numbers
41− , int8, int16, int32, int64, int
42− , word8, word16, word32, word64, word
43− , integer, float, double, scientific
44− -- ** Decimal numbers as Text
45− , int8Text, int16Text, int32Text, int64Text, intText
46− , word8Text, word16Text, word32Text, word64Text, wordText
47− , integerText, floatText, doubleText, scientificText
48− -- ** Time
49− , day
50− , localTime
51− , utcTime
52− , timeOfDay
53− , zonedTime
54− -- ** value
55− , value
56− -- ** JSON tokens
57 , comma, colon, openBracket, closeBracket, openCurly, closeCurly
23 , comma, colon, openBracket, closeBracket, openCurly, closeCurly
58 ) where
24 ) where
59
25
60−import Prelude.Compat
26+#if !MIN_VERSION_base(4,8,0)
27+import Data.Monoid (Monoid(..))
28+#endif
61
29
62−import Data.Aeson.Types.Internal (Value)
63−import Data.ByteString.Builder (Builder, char7, toLazyByteString)
64−import Data.Int
65−import Data.Scientific (Scientific)
66−import Data.Semigroup (Semigroup ((<>)))
67import Data.Text (Text)
30import Data.Text (Text)
68−import Data.Time (Day, LocalTime, TimeOfDay, UTCTime, ZonedTime)
31+import Data.ByteString.Builder (Builder, char7, toLazyByteString)
32+import Data.Semigroup (Semigroup((<>)))
33+import Data.ByteString.Builder.Prim (primBounded)
69import Data.Typeable (Typeable)
34import Data.Typeable (Typeable)
70−import Data.Word
35+
71−import qualified Data.Aeson.Encoding.Builder as EB
72−import qualified Data.ByteString.Builder as B
73import qualified Data.ByteString.Lazy as BSL
36import qualified Data.ByteString.Lazy as BSL
74−import qualified Data.Text.Lazy as LT
37+import qualified Data.Aeson.Encode.Builder as B
75
38
76-- | An encoding of a JSON value.
39-- | An encoding of a JSON value.
77−--
78−-- @tag@ represents which kind of JSON the Encoding is encoding to,
79−-- we reuse 'Text' and 'Value' as tags here.
80−newtype Encoding' tag = Encoding {
40+newtype Encoding = Encoding {
81 fromEncoding :: Builder
41 fromEncoding :: Builder
82 -- ^ Acquire the underlying bytestring builder.
42 -- ^ Acquire the underlying bytestring builder.
83− } deriving (Typeable)
43+ } deriving (Semigroup,Monoid,Typeable)
84−
85−-- | Often used synonym for 'Encoding''.
86−type Encoding = Encoding' Value
87
44
88-- | Make Encoding from Builder.
45-- | Make Encoding from Builder.
89--
46--
90-- Use with care! You have to make sure that the passed Builder
47-- Use with care! You have to make sure that the passed Builder
91-- is a valid JSON Encoding!
48-- is a valid JSON Encoding!
92−unsafeToEncoding :: Builder -> Encoding' a
49+unsafeToEncoding :: Builder -> Encoding
93unsafeToEncoding = Encoding
50unsafeToEncoding = Encoding
94
51
95−encodingToLazyByteString :: Encoding' a -> BSL.ByteString
96−encodingToLazyByteString = toLazyByteString . fromEncoding
97−{-# INLINE encodingToLazyByteString #-}
98−
99−retagEncoding :: Encoding' a -> Encoding' b
100−retagEncoding = Encoding . fromEncoding
101−
102-------------------------------------------------------------------------------
52-------------------------------------------------------------------------------
103-- Encoding instances
53-- Encoding instances
104-------------------------------------------------------------------------------
54-------------------------------------------------------------------------------
105
55
106−instance Show (Encoding' a) where
56+instance Show Encoding where
107 show (Encoding e) = show (toLazyByteString e)
57 show (Encoding e) = show (toLazyByteString e)
108
58
109−instance Eq (Encoding' a) where
59+instance Eq Encoding where
110 Encoding a == Encoding b = toLazyByteString a == toLazyByteString b
60 Encoding a == Encoding b = toLazyByteString a == toLazyByteString b
111
61
112−instance Ord (Encoding' a) where
62+instance Ord Encoding where
113 compare (Encoding a) (Encoding b) =
63 compare (Encoding a) (Encoding b) =
114 compare (toLazyByteString a) (toLazyByteString b)
64 compare (toLazyByteString a) (toLazyByteString b)
115
65
@@ -121,97 +71,73 @@ instance Ord (Encoding' a) where
121--
71--
122-- > toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)
72-- > toEncoding (Person name age) = pairs ("name" .= name <> "age" .= age)
123data Series = Empty
73data Series = Empty
124− | Value (Encoding' Series)
74+ | Value Encoding
125 deriving (Typeable)
75 deriving (Typeable)
126
76
127−pair :: Text -> Encoding -> Series
128−pair name val = pair' (text name) val
129−{-# INLINE pair #-}
130−
131−pairStr :: String -> Encoding -> Series
132−pairStr name val = pair' (string name) val
133−{-# INLINE pairStr #-}
134−
135−pair' :: Encoding' Text -> Encoding -> Series
136−pair' name val = Value $ retagEncoding $ retagEncoding name >< colon >< val
137−
138instance Semigroup Series where
77instance Semigroup Series where
139− Empty <> a = a
78+ Empty <> a = a
140− a <> Empty = a
79+ Value a <> b =
141− Value a <> Value b = Value (a >< comma >< b)
80+ Value $
81+ a <> case b of
82+ Empty -> mempty
83+ Value c -> Encoding (char7 ',') <> c
142
84
143instance Monoid Series where
85instance Monoid Series where
144 mempty = Empty
86 mempty = Empty
145 mappend = (<>)
87 mappend = (<>)
146
88
147−nullEncoding :: Encoding' a -> Bool
89+nullEncoding :: Encoding -> Bool
148nullEncoding = BSL.null . toLazyByteString . fromEncoding
90nullEncoding = BSL.null . toLazyByteString . fromEncoding
149
91
150emptyArray_ :: Encoding
92emptyArray_ :: Encoding
151−emptyArray_ = Encoding EB.emptyArray_
93+emptyArray_ = Encoding B.emptyArray_
152
94
153emptyObject_ :: Encoding
95emptyObject_ :: Encoding
154−emptyObject_ = Encoding EB.emptyObject_
96+emptyObject_ = Encoding B.emptyObject_
155
97
156−wrapArray :: Encoding' a -> Encoding
98+wrapArray :: Encoding -> Encoding
157−wrapArray e = retagEncoding $ openBracket >< e >< closeBracket
99+wrapArray e = openBracket <> e <> closeBracket
158
100
159−wrapObject :: Encoding' a -> Encoding
101+wrapObject :: Encoding -> Encoding
160−wrapObject e = retagEncoding $ openCurly >< e >< closeCurly
102+wrapObject e = openCurly <> e <> closeCurly
161−
162−null_ :: Encoding
163−null_ = Encoding EB.null_
164−
165−bool :: Bool -> Encoding
166−bool True = Encoding "true"
167−bool False = Encoding "false"
168
103
169-- | Encode a series of key/value pairs, separated by commas.
104-- | Encode a series of key/value pairs, separated by commas.
170pairs :: Series -> Encoding
105pairs :: Series -> Encoding
171−pairs (Value v) = openCurly >< retagEncoding v >< closeCurly
106+pairs = brackets '{' '}'
172−pairs Empty = emptyObject_
173{-# INLINE pairs #-}
107{-# INLINE pairs #-}
174
108
109+brackets :: Char -> Char -> Series -> Encoding
110+brackets begin end (Value v) = Encoding $
111+ char7 begin <> fromEncoding v <> char7 end
112+brackets begin end Empty = Encoding (primBounded (B.ascii2 (begin,end)) ())
113+
175list :: (a -> Encoding) -> [a] -> Encoding
114list :: (a -> Encoding) -> [a] -> Encoding
176list _ [] = emptyArray_
115list _ [] = emptyArray_
177−list to' (x:xs) = openBracket >< to' x >< commas xs >< closeBracket
116+list to' (x:xs) = Encoding $
117+ char7 '[' <> fromEncoding (to' x) <> commas xs <> char7 ']'
178 where
118 where
179− commas = foldr (\v vs -> comma >< to' v >< vs) empty
119+ commas = foldr (\v vs -> char7 ',' <> fromEncoding (to' v) <> vs) mempty
180{-# INLINE list #-}
120{-# INLINE list #-}
181
121
182-- | Encode as JSON object
122-- | Encode as JSON object
183dict
123dict
184− :: (k -> Encoding' Text) -- ^ key encoding
124+ :: (k -> Encoding) -- ^ key encoding
185 -> (v -> Encoding) -- ^ value encoding
125 -> (v -> Encoding) -- ^ value encoding
186 -> (forall a. (k -> v -> a -> a) -> a -> m -> a) -- ^ @foldrWithKey@ - indexed fold
126 -> (forall a. (k -> v -> a -> a) -> a -> m -> a) -- ^ @foldrWithKey@ - indexed fold
187 -> m -- ^ container
127 -> m -- ^ container
188 -> Encoding
128 -> Encoding
189−dict encodeKey encodeVal foldrWithKey = pairs . foldrWithKey go mempty
129+dict encodeKey encodeVal foldrWithKey = brackets '{' '}' . foldrWithKey go mempty
190 where
130 where
191 go k v c = Value (encodeKV k v) <> c
131 go k v c = Value (encodeKV k v) <> c
192− encodeKV k v = retagEncoding (encodeKey k) >< colon >< retagEncoding (encodeVal v)
132+ encodeKV k v = encodeKey k <> Encoding (char7 ':') <> encodeVal v
193{-# INLINE dict #-}
133{-# INLINE dict #-}
194
134
195−-- | Type tag for tuples contents, see 'tuple'.
196−data InArray
197−
198infixr 6 >*<
135infixr 6 >*<
199-- | See 'tuple'.
136-- | See 'tuple'.
200−(>*<) :: Encoding' a -> Encoding' b -> Encoding' InArray
137+(>*<) :: Encoding -> Encoding -> Encoding
201−a >*< b = retagEncoding a >< comma >< retagEncoding b
138+Encoding a >*< Encoding b = Encoding $ a <> char7 ',' <> b
202{-# INLINE (>*<) #-}
139{-# INLINE (>*<) #-}
203
140
204−empty :: Encoding' a
205−empty = Encoding mempty
206−
207−econcat :: [Encoding' a] -> Encoding' a
208−econcat = foldr (><) empty
209−
210−infixr 6 ><
211−(><) :: Encoding' a -> Encoding' a -> Encoding' a
212−Encoding a >< Encoding b = Encoding (a <> b)
213−{-# INLINE (><) #-}
214−
215-- | Encode as a tuple.
141-- | Encode as a tuple.
216--
142--
217-- @
143-- @
@@ -219,26 +145,18 @@ Encoding a >< Encoding b = Encoding (a <> b)
219-- toEncoding a >*<
145-- toEncoding a >*<
220-- toEncoding b >*<
146-- toEncoding b >*<
221-- toEncoding c
147-- toEncoding c
222−tuple :: Encoding' InArray -> Encoding
148+tuple :: Encoding -> Encoding
223−tuple b = retagEncoding $ openBracket >< b >< closeBracket
149+tuple b = Encoding (char7 '[' <> fromEncoding b <> char7 ']')
224{-# INLINE tuple #-}
150{-# INLINE tuple #-}
225
151
226−text :: Text -> Encoding' a
152+text :: Text -> Encoding
227−text = Encoding . EB.text
153+text = Encoding . B.text
228−
229−lazyText :: LT.Text -> Encoding' a
230−lazyText t = Encoding $
231− B.char7 '"' <>
232− LT.foldrChunks (\x xs -> EB.unquoted x <> xs) (B.char7 '"') t
233−
234−string :: String -> Encoding' a
235−string = Encoding . EB.string
236
154
237-------------------------------------------------------------------------------
155-------------------------------------------------------------------------------
238-- chars
156-- chars
239-------------------------------------------------------------------------------
157-------------------------------------------------------------------------------
240
158
241−comma, colon, openBracket, closeBracket, openCurly, closeCurly :: Encoding' a
159+comma, colon, openBracket, closeBracket, openCurly, closeCurly :: Encoding
242comma = Encoding $ char7 ','
160comma = Encoding $ char7 ','
243colon = Encoding $ char7 ':'
161colon = Encoding $ char7 ':'
244openBracket = Encoding $ char7 '['
162openBracket = Encoding $ char7 '['
@@ -246,126 +164,3 @@ closeBracket = Encoding $ char7 ']'
246openCurly = Encoding $ char7 '{'
164openCurly = Encoding $ char7 '{'
247closeCurly = Encoding $ char7 '}'
165closeCurly = Encoding $ char7 '}'
248
166
249−-------------------------------------------------------------------------------
250−-- Decimal numbers
251−-------------------------------------------------------------------------------
252−
253−int8 :: Int8 -> Encoding
254−int8 = Encoding . B.int8Dec
255−
256−int16 :: Int16 -> Encoding
257−int16 = Encoding . B.int16Dec
258−
259−int32 :: Int32 -> Encoding
260−int32 = Encoding . B.int32Dec
261−
262−int64 :: Int64 -> Encoding
263−int64 = Encoding . B.int64Dec
264−
265−int :: Int -> Encoding
266−int = Encoding . B.intDec
267−
268−word8 :: Word8 -> Encoding
269−word8 = Encoding . B.word8Dec
270−
271−word16 :: Word16 -> Encoding
272−word16 = Encoding . B.word16Dec
273−
274−word32 :: Word32 -> Encoding
275−word32 = Encoding . B.word32Dec
276−
277−word64 :: Word64 -> Encoding
278−word64 = Encoding . B.word64Dec
279−
280−word :: Word -> Encoding
281−word = Encoding . B.wordDec
282−
283−integer :: Integer -> Encoding
284−integer = Encoding . B.integerDec
285−
286−float :: Float -> Encoding
287−float = realFloatToEncoding $ Encoding . B.floatDec
288−
289−double :: Double -> Encoding
290−double = realFloatToEncoding $ Encoding . B.doubleDec
291−
292−scientific :: Scientific -> Encoding
293−scientific = Encoding . EB.scientific
294−
295−realFloatToEncoding :: RealFloat a => (a -> Encoding) -> a -> Encoding
296−realFloatToEncoding e d
297− | isNaN d || isInfinite d = null_
298− | otherwise = e d
299−{-# INLINE realFloatToEncoding #-}
300−
301−-------------------------------------------------------------------------------
302−-- Decimal numbers as Text
303−-------------------------------------------------------------------------------
304−
305−int8Text :: Int8 -> Encoding' a
306−int8Text = Encoding . EB.quote . B.int8Dec
307−
308−int16Text :: Int16 -> Encoding' a
309−int16Text = Encoding . EB.quote . B.int16Dec
310−
311−int32Text :: Int32 -> Encoding' a
312−int32Text = Encoding . EB.quote . B.int32Dec
313−
314−int64Text :: Int64 -> Encoding' a
315−int64Text = Encoding . EB.quote . B.int64Dec
316−
317−intText :: Int -> Encoding' a
318−intText = Encoding . EB.quote . B.intDec
319−
320−word8Text :: Word8 -> Encoding' a
321−word8Text = Encoding . EB.quote . B.word8Dec
322−
323−word16Text :: Word16 -> Encoding' a
324−word16Text = Encoding . EB.quote . B.word16Dec
325−
326−word32Text :: Word32 -> Encoding' a
327−word32Text = Encoding . EB.quote . B.word32Dec
328−
329−word64Text :: Word64 -> Encoding' a
330−word64Text = Encoding . EB.quote . B.word64Dec
331−
332−wordText :: Word -> Encoding' a
333−wordText = Encoding . EB.quote . B.wordDec
334−
335−integerText :: Integer -> Encoding' a
336−integerText = Encoding . EB.quote . B.integerDec
337−
338−floatText :: Float -> Encoding' a
339−floatText = Encoding . EB.quote . B.floatDec
340−
341−doubleText :: Double -> Encoding' a
342−doubleText = Encoding . EB.quote . B.doubleDec
343−
344−scientificText :: Scientific -> Encoding' a
345−scientificText = Encoding . EB.quote . EB.scientific
346−
347−-------------------------------------------------------------------------------
348−-- time
349−-------------------------------------------------------------------------------
350−
351−day :: Day -> Encoding' a
352−day = Encoding . EB.quote . EB.day
353−
354−localTime :: LocalTime -> Encoding' a
355−localTime = Encoding . EB.quote . EB.localTime
356−
357−utcTime :: UTCTime -> Encoding' a
358−utcTime = Encoding . EB.quote . EB.utcTime
359−
360−timeOfDay :: TimeOfDay -> Encoding' a
361−timeOfDay = Encoding . EB.quote . EB.timeOfDay
362−
363−zonedTime :: ZonedTime -> Encoding' a
364−zonedTime = Encoding . EB.quote . EB.zonedTime
365−
366−-------------------------------------------------------------------------------
367−-- Value
368−-------------------------------------------------------------------------------
369−
370−value :: Value -> Encoding
371−value = Encoding . EB.encodeToBuilder
Data/Aeson/Internal/Functions.hs → Data/Aeson/Functions.hsrenamed+9−6
@@ -1,4 +1,3 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2-- |
1-- |
3-- Module: Data.Aeson.Functions
2-- Module: Data.Aeson.Functions
4-- Copyright: (c) 2011-2016 Bryan O'Sullivan
3-- Copyright: (c) 2011-2016 Bryan O'Sullivan
@@ -8,15 +7,13 @@
8-- Stability: experimental
7-- Stability: experimental
9-- Portability: portable
8-- Portability: portable
10
9
11−module Data.Aeson.Internal.Functions
10+module Data.Aeson.Functions
12− (
13− mapHashKeyVal
11+ ( mapHashKeyVal
12+ , hashMapKey
14 , mapKeyVal
13 , mapKeyVal
15 , mapKey
14 , mapKey
16 ) where
15 ) where
17
16
18−import Prelude.Compat
19−
20import Data.Hashable (Hashable)
17import Data.Hashable (Hashable)
21import qualified Data.HashMap.Strict as H
18import qualified Data.HashMap.Strict as H
22import qualified Data.Map as M
19import qualified Data.Map as M
@@ -27,6 +24,12 @@ mapHashKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)
27mapHashKeyVal fk kv = M.foldrWithKey (\k v -> H.insert (fk k) (kv v)) H.empty
24mapHashKeyVal fk kv = M.foldrWithKey (\k v -> H.insert (fk k) (kv v)) H.empty
28{-# INLINE mapHashKeyVal #-}
25{-# INLINE mapHashKeyVal #-}
29
26
27+-- | Transform a 'M.Map' into a 'H.HashMap' while transforming the keys.
28+hashMapKey :: (Ord k2) => (k1 -> k2)
29+ -> H.HashMap k1 v -> M.Map k2 v
30+hashMapKey kv = H.foldrWithKey (M.insert . kv) M.empty
31+{-# INLINE hashMapKey #-}
32+
30-- | Transform the keys and values of a 'H.HashMap'.
33-- | Transform the keys and values of a 'H.HashMap'.
31mapKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)
34mapKeyVal :: (Eq k2, Hashable k2) => (k1 -> k2) -> (v1 -> v2)
32 -> H.HashMap k1 v1 -> H.HashMap k2 v2
35 -> H.HashMap k1 v1 -> H.HashMap k2 v2
Data/Aeson/Internal.hs−2
@@ -1,4 +1,3 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2-- |
1-- |
3-- Module: Data.Aeson.Internal
2-- Module: Data.Aeson.Internal
4-- Copyright: (c) 2015-2016 Bryan O'Sullivan
3-- Copyright: (c) 2015-2016 Bryan O'Sullivan
@@ -23,6 +22,5 @@ module Data.Aeson.Internal
23 , iparse
22 , iparse
24 ) where
23 ) where
25
24
26−
27import Data.Aeson.Types.Internal
25import Data.Aeson.Types.Internal
28import Data.Aeson.Types.FromJSON (ifromJSON)
26import Data.Aeson.Types.FromJSON (ifromJSON)
Data/Aeson/Internal/Time.hs+38−1
@@ -17,4 +17,41 @@ module Data.Aeson.Internal.Time
17 , toTimeOfDay64
17 , toTimeOfDay64
18 ) where
18 ) where
19
19
20−import Data.Attoparsec.Time.Internal
20+import Data.Fixed (Pico)
21+import Data.Int (Int64)
22+import Data.Time
23+import Unsafe.Coerce (unsafeCoerce)
24+
25+#if MIN_VERSION_base(4,7,0)
26+
27+import Data.Fixed (Fixed(MkFixed))
28+
29+toPico :: Integer -> Pico
30+toPico = MkFixed
31+
32+fromPico :: Pico -> Integer
33+fromPico (MkFixed i) = i
34+
35+#else
36+
37+toPico :: Integer -> Pico
38+toPico = unsafeCoerce
39+
40+fromPico :: Pico -> Integer
41+fromPico = unsafeCoerce
42+
43+#endif
44+
45+-- | Like TimeOfDay, but using a fixed-width integer for seconds.
46+data TimeOfDay64 = TOD {-# UNPACK #-} !Int
47+ {-# UNPACK #-} !Int
48+ {-# UNPACK #-} !Int64
49+
50+diffTimeOfDay64 :: DiffTime -> TimeOfDay64
51+diffTimeOfDay64 t = TOD (fromIntegral h) (fromIntegral m) s
52+ where (h,mp) = fromIntegral pico `quotRem` 3600000000000000
53+ (m,s) = mp `quotRem` 60000000000000
54+ pico = unsafeCoerce t :: Integer
55+
56+toTimeOfDay64 :: TimeOfDay -> TimeOfDay64
57+toTimeOfDay64 (TimeOfDay h m s) = TOD h m (fromIntegral (fromPico s))
Data/Aeson/Parser.hs+5−14
@@ -1,4 +1,5 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2+
2-- |
3-- |
3-- Module: Data.Aeson.Parser
4-- Module: Data.Aeson.Parser
4-- Copyright: (c) 2012-2016 Bryan O'Sullivan
5-- Copyright: (c) 2012-2016 Bryan O'Sullivan
@@ -34,21 +35,10 @@ module Data.Aeson.Parser
34 json
35 json
35 , value
36 , value
36 , jstring
37 , jstring
37− , scientific
38− -- ** Handling objects with duplicate keys
39− , jsonWith
40− , jsonLast
41− , jsonAccum
42− , jsonNoDup
43 -- * Strict parsers
38 -- * Strict parsers
44 -- $strict
39 -- $strict
45 , json'
40 , json'
46 , value'
41 , value'
47− -- ** Handling objects with duplicate keys
48− , jsonWith'
49− , jsonLast'
50− , jsonAccum'
51− , jsonNoDup'
52 -- * Decoding without FromJSON instances
42 -- * Decoding without FromJSON instances
53 , decodeWith
43 , decodeWith
54 , decodeStrictWith
44 , decodeStrictWith
@@ -56,8 +46,9 @@ module Data.Aeson.Parser
56 , eitherDecodeStrictWith
46 , eitherDecodeStrictWith
57 ) where
47 ) where
58
48
59−
60−import Data.Aeson.Parser.Internal
49+import Data.Aeson.Parser.Internal (decodeStrictWith, decodeWith,
50+ eitherDecodeStrictWith, eitherDecodeWith,
51+ json, json', jstring, value, value')
61
52
62-- $lazy
53-- $lazy
63--
54--
Data/Aeson/Parser/Internal.hs+198−325
@@ -1,14 +1,8 @@
1−{-# LANGUAGE BangPatterns #-}
1+{-# LANGUAGE BangPatterns, CPP, OverloadedStrings #-}
2−{-# LANGUAGE CPP #-}
3−{-# LANGUAGE NoImplicitPrelude #-}
4−{-# LANGUAGE OverloadedStrings #-}
5#if MIN_VERSION_ghc_prim(0,3,1)
2#if MIN_VERSION_ghc_prim(0,3,1)
6{-# LANGUAGE MagicHash #-}
3{-# LANGUAGE MagicHash #-}
7#endif
4#endif
8−#if __GLASGOW_HASKELL__ <= 710 && __GLASGOW_HASKELL__ >= 706
5+
9−-- Work around a compiler bug
10−{-# OPTIONS_GHC -fsimpl-tick-factor=200 #-}
11−#endif
12-- |
6-- |
13-- Module: Data.Aeson.Parser.Internal
7-- Module: Data.Aeson.Parser.Internal
14-- Copyright: (c) 2011-2016 Bryan O'Sullivan
8-- Copyright: (c) 2011-2016 Bryan O'Sullivan
@@ -25,56 +19,52 @@ module Data.Aeson.Parser.Internal
25 (
19 (
26 -- * Lazy parsers
20 -- * Lazy parsers
27 json, jsonEOF
21 json, jsonEOF
28− , jsonWith
29− , jsonLast
30− , jsonAccum
31− , jsonNoDup
32 , value
22 , value
33 , jstring
23 , jstring
34− , jstring_
35− , scientific
36 -- * Strict parsers
24 -- * Strict parsers
37 , json', jsonEOF'
25 , json', jsonEOF'
38− , jsonWith'
39− , jsonLast'
40− , jsonAccum'
41− , jsonNoDup'
42 , value'
26 , value'
43 -- * Helpers
27 -- * Helpers
44 , decodeWith
28 , decodeWith
45 , decodeStrictWith
29 , decodeStrictWith
46 , eitherDecodeWith
30 , eitherDecodeWith
47 , eitherDecodeStrictWith
31 , eitherDecodeStrictWith
48− -- ** Handling objects with duplicate keys
49− , fromListAccum
50− , parseListNoDup
51 ) where
32 ) where
52
33
53−import Prelude.Compat
54−
55−import Control.Applicative ((<|>))
56−import Control.Monad (void, when)
34+import Control.Monad.IO.Class (liftIO)
57−import Data.Aeson.Types.Internal (IResult(..), JSONPath, Object, Result(..), Value(..))
35+import Data.Aeson.Types.Internal (IResult(..), JSONPath, Result(..), Value(..))
58−import Data.Attoparsec.ByteString.Char8 (Parser, char, decimal, endOfInput, isDigit_w8, signed, string)
36+import Data.Attoparsec.ByteString.Char8 (Parser, char, endOfInput, scientific,
37+ skipSpace, string)
59−import Data.Function (fix)
38+import Data.Bits ((.|.), shiftL)
60−import Data.Functor.Compat (($>))
39+import Data.ByteString.Internal (ByteString(..))
61−import Data.Scientific (Scientific)
40+import Data.Char (chr)
62import Data.Text (Text)
41import Data.Text (Text)
63−import Data.Vector (Vector)
42+import Data.Text.Encoding (decodeUtf8')
43+import Data.Text.Internal.Encoding.Utf8 (ord2, ord3, ord4)
44+import Data.Text.Internal.Unsafe.Char (ord)
64−import qualified Data.Vector as Vector (empty, fromList, fromListN, reverse)
45+import Data.Vector as Vector (Vector, empty, fromList, reverse)
46+import Data.Word (Word8)
47+import Foreign.ForeignPtr (withForeignPtr)
48+import Foreign.Ptr (Ptr, plusPtr)
49+import Foreign.Ptr (minusPtr)
50+import Foreign.Storable (poke)
51+import System.IO.Unsafe (unsafePerformIO)
65import qualified Data.Attoparsec.ByteString as A
52import qualified Data.Attoparsec.ByteString as A
66import qualified Data.Attoparsec.Lazy as L
53import qualified Data.Attoparsec.Lazy as L
54+import qualified Data.Attoparsec.Zepto as Z
67import qualified Data.ByteString as B
55import qualified Data.ByteString as B
68−import qualified Data.ByteString.Unsafe as B
56+import qualified Data.ByteString.Internal as B
69import qualified Data.ByteString.Lazy as L
57import qualified Data.ByteString.Lazy as L
58+import qualified Data.ByteString.Unsafe as B
70import qualified Data.HashMap.Strict as H
59import qualified Data.HashMap.Strict as H
71−import qualified Data.Scientific as Sci
60+
72−import Data.Aeson.Parser.Unescape (unescapeText)
61+#if !MIN_VERSION_base(4,8,0)
62+import Control.Applicative ((*>), (<$>), (<*), pure)
63+#endif
73
64
74#if MIN_VERSION_ghc_prim(0,3,1)
65#if MIN_VERSION_ghc_prim(0,3,1)
75−import GHC.Base (Int#, (==#), isTrue#, word2Int#, orI#, andI#)
66+import GHC.Base (Int#, (==#), isTrue#, orI#, word2Int#)
76import GHC.Word (Word8(W8#))
67import GHC.Word (Word8(W8#))
77−import qualified Data.Text.Encoding as TE
78#endif
68#endif
79
69
80#define BACKSLASH 92
70#define BACKSLASH 92
@@ -93,7 +83,7 @@ import qualified Data.Text.Encoding as TE
93#define C_n 110
83#define C_n 110
94#define C_t 116
84#define C_t 116
95
85
96−-- | Parse any JSON value.
86+-- | Parse a top-level JSON value.
97--
87--
98-- The conversion of a parsed value to a Haskell value is deferred
88-- The conversion of a parsed value to a Haskell value is deferred
99-- until the Haskell value is needed. This may improve performance if
89-- until the Haskell value is needed. This may improve performance if
@@ -103,15 +93,10 @@ import qualified Data.Text.Encoding as TE
103-- This function is an alias for 'value'. In aeson 0.8 and earlier, it
93-- This function is an alias for 'value'. In aeson 0.8 and earlier, it
104-- parsed only object or array types, in conformance with the
94-- parsed only object or array types, in conformance with the
105-- now-obsolete RFC 4627.
95-- now-obsolete RFC 4627.
106−--
107−-- ==== Warning
108−--
109−-- If an object contains duplicate keys, only the first one will be kept.
110−-- For a more flexible alternative, see 'jsonWith'.
111json :: Parser Value
96json :: Parser Value
112json = value
97json = value
113
98
114−-- | Parse any JSON value.
99+-- | Parse a top-level JSON value.
115--
100--
116-- This is a strict version of 'json' which avoids building up thunks
101-- This is a strict version of 'json' which avoids building up thunks
117-- during parsing; it performs all conversions immediately. Prefer
102-- during parsing; it performs all conversions immediately. Prefer
@@ -120,64 +105,46 @@ json = value
120-- This function is an alias for 'value''. In aeson 0.8 and earlier, it
105-- This function is an alias for 'value''. In aeson 0.8 and earlier, it
121-- parsed only object or array types, in conformance with the
106-- parsed only object or array types, in conformance with the
122-- now-obsolete RFC 4627.
107-- now-obsolete RFC 4627.
123−--
124−-- ==== Warning
125−--
126−-- If an object contains duplicate keys, only the first one will be kept.
127−-- For a more flexible alternative, see 'jsonWith''.
128json' :: Parser Value
108json' :: Parser Value
129json' = value'
109json' = value'
130
110
131−-- Open recursion: object_, object_', array_, array_' are parameterized by the
132−-- toplevel Value parser to be called recursively, to keep the parameter
133−-- mkObject outside of the recursive loop for proper inlining.
134−
135−object_ :: ([(Text, Value)] -> Either String Object) -> Parser Value -> Parser Value
111+object_ :: Parser Value
136−object_ mkObject val = {-# SCC "object_" #-} Object <$> objectValues mkObject jstring val
112+object_ = {-# SCC "object_" #-} Object <$> objectValues jstring value
137−{-# INLINE object_ #-}
138
113
139−object_' :: ([(Text, Value)] -> Either String Object) -> Parser Value -> Parser Value
114+object_' :: Parser Value
140−object_' mkObject val' = {-# SCC "object_'" #-} do
115+object_' = {-# SCC "object_'" #-} do
141− !vals <- objectValues mkObject jstring' val'
116+ !vals <- objectValues jstring' value'
142 return (Object vals)
117 return (Object vals)
143 where
118 where
144 jstring' = do
119 jstring' = do
145 !s <- jstring
120 !s <- jstring
146 return s
121 return s
147−{-# INLINE object_' #-}
148
122
149−objectValues :: ([(Text, Value)] -> Either String Object)
150− -> Parser Text -> Parser Value -> Parser (H.HashMap Text Value)
123+objectValues :: Parser Text -> Parser Value -> Parser (H.HashMap Text Value)
151−objectValues mkObject str val = do
124+objectValues str val = do
152 skipSpace
125 skipSpace
153 w <- A.peekWord8'
126 w <- A.peekWord8'
154 if w == CLOSE_CURLY
127 if w == CLOSE_CURLY
155 then A.anyWord8 >> return H.empty
128 then A.anyWord8 >> return H.empty
156− else loop []
129+ else loop H.empty
157 where
130 where
158− -- Why use acc pattern here, you may ask? because 'H.fromList' use 'unsafeInsert'
159− -- and it's much faster because it's doing in place update to the 'HashMap'!
160− loop acc = do
131+ loop m0 = do
161− k <- (str A.<?> "object key") <* skipSpace <* (char ':' A.<?> "':'")
132+ k <- str <* skipSpace <* char ':'
162− v <- (val A.<?> "object value") <* skipSpace
133+ v <- val <* skipSpace
134+ let !m = H.insert k v m0
163− ch <- A.satisfy (\w -> w == COMMA || w == CLOSE_CURLY) A.<?> "',' or '}'"
135+ ch <- A.satisfy $ \w -> w == COMMA || w == CLOSE_CURLY
164− let acc' = (k, v) : acc
165 if ch == COMMA
136 if ch == COMMA
166− then skipSpace >> loop acc'
137+ then skipSpace >> loop m
167− else case mkObject acc' of
138+ else return m
168− Left err -> fail err
169− Right obj -> pure obj
170{-# INLINE objectValues #-}
139{-# INLINE objectValues #-}
171
140
172−array_ :: Parser Value -> Parser Value
141+array_ :: Parser Value
173−array_ val = {-# SCC "array_" #-} Array <$> arrayValues val
142+array_ = {-# SCC "array_" #-} Array <$> arrayValues value
174−{-# INLINE array_ #-}
175
143
176−array_' :: Parser Value -> Parser Value
144+array_' :: Parser Value
177−array_' val = {-# SCC "array_'" #-} do
145+array_' = {-# SCC "array_'" #-} do
178− !vals <- arrayValues val
146+ !vals <- arrayValues value'
179 return (Array vals)
147 return (Array vals)
180−{-# INLINE array_' #-}
181
148
182arrayValues :: Parser Value -> Parser (Vector Value)
149arrayValues :: Parser Value -> Parser (Vector Value)
183arrayValues val = do
150arrayValues val = do
@@ -185,136 +152,60 @@ arrayValues val = do
185 w <- A.peekWord8'
152 w <- A.peekWord8'
186 if w == CLOSE_SQUARE
153 if w == CLOSE_SQUARE
187 then A.anyWord8 >> return Vector.empty
154 then A.anyWord8 >> return Vector.empty
188− else loop [] 1
155+ else loop []
189 where
156 where
190− loop acc !len = do
157+ loop acc = do
191− v <- (val A.<?> "json list value") <* skipSpace
158+ v <- val <* skipSpace
192− ch <- A.satisfy (\w -> w == COMMA || w == CLOSE_SQUARE) A.<?> "',' or ']'"
159+ ch <- A.satisfy $ \w -> w == COMMA || w == CLOSE_SQUARE
193 if ch == COMMA
160 if ch == COMMA
194− then skipSpace >> loop (v:acc) (len+1)
161+ then skipSpace >> loop (v:acc)
195− else return (Vector.reverse (Vector.fromListN len (v:acc)))
162+ else return (Vector.reverse (Vector.fromList (v:acc)))
196{-# INLINE arrayValues #-}
163{-# INLINE arrayValues #-}
197
164
198−-- | Parse any JSON value. Synonym of 'json'.
165+-- | Parse any JSON value. You should usually 'json' in preference to
199−value :: Parser Value
166+-- this function, as this function relaxes the object-or-array
200−value = jsonWith (pure . H.fromList)
167+-- requirement of RFC 4627.
201−
202−-- | Parse any JSON value.
203−--
204−-- This parser is parameterized by a function to construct an 'Object'
205−-- from a raw list of key-value pairs, where duplicates are preserved.
206−-- The pairs appear in __reverse order__ from the source.
207−--
208−-- ==== __Examples__
209−--
210−-- 'json' keeps only the first occurence of each key, using 'HashMap.Lazy.fromList'.
211−--
212−-- @
213−-- 'json' = 'jsonWith' ('Right' '.' 'H.fromList')
214−-- @
215−--
216−-- 'jsonLast' keeps the last occurence of each key, using
217−-- @'HashMap.Lazy.fromListWith' ('const' 'id')@.
218−--
219−-- @
220−-- 'jsonLast' = 'jsonWith' ('Right' '.' 'HashMap.Lazy.fromListWith' ('const' 'id'))
221−-- @
222−--
223−-- 'jsonAccum' keeps wraps all values in arrays to keep duplicates, using
224−-- 'fromListAccum'.
225−--
226−-- @
227−-- 'jsonAccum' = 'jsonWith' ('Right' . 'fromListAccum')
228−-- @
229−--
230−-- 'jsonNoDup' fails if any object contains duplicate keys, using 'parseListNoDup'.
231--
168--
232−-- @
169+-- In particular, be careful in using this function if you think your
233−-- 'jsonNoDup' = 'jsonWith' 'parseListNoDup'
170+-- code might interoperate with Javascript. A na&#xef;ve Javascript
234−-- @
171+-- library that parses JSON data using @eval@ is vulnerable to attack
235−jsonWith :: ([(Text, Value)] -> Either String Object) -> Parser Value
172+-- unless the encoded data represents an object or an array. JSON
236−jsonWith mkObject = fix $ \value_ -> do
173+-- implementations in other languages conform to that same restriction
174+-- to preserve interoperability and security.
175+value :: Parser Value
176+value = do
237 skipSpace
177 skipSpace
238 w <- A.peekWord8'
178 w <- A.peekWord8'
239 case w of
179 case w of
240 DOUBLE_QUOTE -> A.anyWord8 *> (String <$> jstring_)
180 DOUBLE_QUOTE -> A.anyWord8 *> (String <$> jstring_)
241− OPEN_CURLY -> A.anyWord8 *> object_ mkObject value_
181+ OPEN_CURLY -> A.anyWord8 *> object_
242− OPEN_SQUARE -> A.anyWord8 *> array_ value_
182+ OPEN_SQUARE -> A.anyWord8 *> array_
243− C_f -> string "false" $> Bool False
183+ C_f -> string "false" *> pure (Bool False)
244− C_t -> string "true" $> Bool True
184+ C_t -> string "true" *> pure (Bool True)
245− C_n -> string "null" $> Null
185+ C_n -> string "null" *> pure Null
246 _ | w >= 48 && w <= 57 || w == 45
186 _ | w >= 48 && w <= 57 || w == 45
247 -> Number <$> scientific
187 -> Number <$> scientific
248 | otherwise -> fail "not a valid json value"
188 | otherwise -> fail "not a valid json value"
249−{-# INLINE jsonWith #-}
250−
251−-- | Variant of 'json' which keeps only the last occurence of every key.
252−jsonLast :: Parser Value
253−jsonLast = jsonWith (Right . H.fromListWith (const id))
254−
255−-- | Variant of 'json' wrapping all object mappings in 'Array' to preserve
256−-- key-value pairs with the same keys.
257−jsonAccum :: Parser Value
258−jsonAccum = jsonWith (Right . fromListAccum)
259−
260−-- | Variant of 'json' which fails if any object contains duplicate keys.
261−jsonNoDup :: Parser Value
262−jsonNoDup = jsonWith parseListNoDup
263−
264−-- | @'fromListAccum' kvs@ is an object mapping keys to arrays containing all
265−-- associated values from the original list @kvs@.
266−--
267−-- >>> fromListAccum [("apple", Bool True), ("apple", Bool False), ("orange", Bool False)]
268−-- fromList [("apple", [Bool False, Bool True]), ("orange", [Bool False])]
269−fromListAccum :: [(Text, Value)] -> Object
270−fromListAccum =
271− fmap (Array . Vector.fromList . ($ [])) . H.fromListWith (.) . (fmap . fmap) (:)
272−
273−-- | @'fromListNoDup' kvs@ fails if @kvs@ contains duplicate keys.
274−parseListNoDup :: [(Text, Value)] -> Either String Object
275−parseListNoDup =
276− H.traverseWithKey unwrap . H.fromListWith (\_ _ -> Nothing) . (fmap . fmap) Just
277− where
278− unwrap k Nothing = Left $ "found duplicate key: " ++ show k
279− unwrap _ (Just v) = Right v
280
189
281−-- | Strict version of 'value'. Synonym of 'json''.
190+-- | Strict version of 'value'. See also 'json''.
282value' :: Parser Value
191value' :: Parser Value
283−value' = jsonWith' (pure . H.fromList)
192+value' = do
284−
285−-- | Strict version of 'jsonWith'.
286−jsonWith' :: ([(Text, Value)] -> Either String Object) -> Parser Value
287−jsonWith' mkObject = fix $ \value_ -> do
288 skipSpace
193 skipSpace
289 w <- A.peekWord8'
194 w <- A.peekWord8'
290 case w of
195 case w of
291 DOUBLE_QUOTE -> do
196 DOUBLE_QUOTE -> do
292 !s <- A.anyWord8 *> jstring_
197 !s <- A.anyWord8 *> jstring_
293 return (String s)
198 return (String s)
294− OPEN_CURLY -> A.anyWord8 *> object_' mkObject value_
199+ OPEN_CURLY -> A.anyWord8 *> object_'
295− OPEN_SQUARE -> A.anyWord8 *> array_' value_
200+ OPEN_SQUARE -> A.anyWord8 *> array_'
296− C_f -> string "false" $> Bool False
201+ C_f -> string "false" *> pure (Bool False)
297− C_t -> string "true" $> Bool True
202+ C_t -> string "true" *> pure (Bool True)
298− C_n -> string "null" $> Null
203+ C_n -> string "null" *> pure Null
299 _ | w >= 48 && w <= 57 || w == 45
204 _ | w >= 48 && w <= 57 || w == 45
300 -> do
205 -> do
301 !n <- scientific
206 !n <- scientific
302 return (Number n)
207 return (Number n)
303 | otherwise -> fail "not a valid json value"
208 | otherwise -> fail "not a valid json value"
304−{-# INLINE jsonWith' #-}
305−
306−-- | Variant of 'json'' which keeps only the last occurence of every key.
307−jsonLast' :: Parser Value
308−jsonLast' = jsonWith' (pure . H.fromListWith (const id))
309−
310−-- | Variant of 'json'' wrapping all object mappings in 'Array' to preserve
311−-- key-value pairs with the same keys.
312−jsonAccum' :: Parser Value
313−jsonAccum' = jsonWith' (pure . fromListAccum)
314−
315−-- | Variant of 'json'' which fails if any object contains duplicate keys.
316−jsonNoDup' :: Parser Value
317−jsonNoDup' = jsonWith' parseListNoDup
318
209
319-- | Parse a quoted JSON string.
210-- | Parse a quoted JSON string.
320jstring :: Parser Text
211jstring :: Parser Text
@@ -324,48 +215,101 @@ jstring = A.word8 DOUBLE_QUOTE *> jstring_
324jstring_ :: Parser Text
215jstring_ :: Parser Text
325{-# INLINE jstring_ #-}
216{-# INLINE jstring_ #-}
326jstring_ = {-# SCC "jstring_" #-} do
217jstring_ = {-# SCC "jstring_" #-} do
327−#if MIN_VERSION_ghc_prim(0,3,1)
328− (s, S _ escaped) <- A.runScanner startState go <* A.anyWord8
218+ (s, fin) <- A.runScanner startState go
329− -- We escape only if there are
219+ _ <- A.anyWord8
330− -- non-ascii (over 7bit) characters or backslash present.
220+ s1 <- if isEscaped fin
331− --
332− -- Note: if/when text will have fast ascii -> text conversion
333− -- (e.g. uses utf8 encoding) we can have further speedup.
334− if isTrue# escaped
335− then case unescapeText s of
221+ then case unescape s of
336− Right r -> return r
222+ Right r -> return r
223+ Left err -> fail err
224+ else return s
225+ case decodeUtf8' s1 of
226+ Right r -> return r
337− Left err -> fail $ show err
227+ Left err -> fail $ show err
338− else return (TE.decodeUtf8 s)
339 where
228 where
229+#if MIN_VERSION_ghc_prim(0,3,1)
230+ isEscaped (S _ escaped) = isTrue# escaped
340 startState = S 0# 0#
231 startState = S 0# 0#
341− go (S skip escaped) (W8# c)
232+ go (S a b) (W8# c)
342− | isTrue# skip = Just (S 0# escaped')
233+ | isTrue# a = Just (S 0# b)
343− | isTrue# (w ==# 34#) = Nothing -- double quote
234+ | isTrue# (word2Int# c ==# 34#) = Nothing -- double quote
344− | otherwise = Just (S skip' escaped')
345− where
346− w = word2Int# c
347− skip' = w ==# 92# -- backslash
235+ | otherwise = let a' = word2Int# c ==# 92# -- backslash
348− escaped' = escaped
236+ in Just (S a' (orI# a' b))
349− `orI#` (w `andI#` 0x80# ==# 0x80#) -- c >= 0x80
350− `orI#` skip'
351− `orI#` (w `andI#` 0x1f# ==# w) -- c < 0x20
352
237
353data S = S Int# Int#
238data S = S Int# Int#
354#else
239#else
355− s <- A.scan startState go <* A.anyWord8
240+ isEscaped (S _ escaped) = escaped
356− case unescapeText s of
357− Right r -> return r
358− Left err -> fail $ show err
359− where
360− startState = False
241+ startState = S False False
361− go a c
242+ go (S a b) c
362− | a = Just False
243+ | a = Just (S False b)
363 | c == DOUBLE_QUOTE = Nothing
244 | c == DOUBLE_QUOTE = Nothing
364 | otherwise = let a' = c == backslash
245 | otherwise = let a' = c == backslash
365− in Just a'
246+ in Just (S a' (a' || b))
366 where backslash = BACKSLASH
247 where backslash = BACKSLASH
248+
249+data S = S !Bool !Bool
367#endif
250#endif
368
251
252+unescape :: ByteString -> Either String ByteString
253+unescape s = unsafePerformIO $ do
254+ let len = B.length s
255+ fp <- B.mallocByteString len
256+ -- We perform no bounds checking when writing to the destination
257+ -- string, as unescaping always makes it shorter than the source.
258+ withForeignPtr fp $ \ptr -> do
259+ ret <- Z.parseT (go ptr) s
260+ case ret of
261+ Left err -> return (Left err)
262+ Right p -> do
263+ let newlen = p `minusPtr` ptr
264+ slop = len - newlen
265+ Right <$> if slop >= 128 && slop >= len `quot` 4
266+ then B.create newlen $ \np -> B.memcpy np ptr newlen
267+ else return (PS fp 0 newlen)
268+ where
269+ go ptr = do
270+ h <- Z.takeWhile (/=BACKSLASH)
271+ let rest = do
272+ start <- Z.take 2
273+ let !slash = B.unsafeHead start
274+ !t = B.unsafeIndex start 1
275+ escape = case B.elemIndex t "\"\\/ntbrfu" of
276+ Just i -> i
277+ _ -> 255
278+ if slash /= BACKSLASH || escape == 255
279+ then fail "invalid JSON escape sequence"
280+ else
281+ if t /= 117 -- 'u'
282+ then copy h ptr >>= word8 (B.unsafeIndex mapping escape) >>= go
283+ else do
284+ a <- hexQuad
285+ if a < 0xd800 || a > 0xdfff
286+ then copy h ptr >>= charUtf8 (chr a) >>= go
287+ else do
288+ b <- Z.string "\\u" *> hexQuad
289+ if a <= 0xdbff && b >= 0xdc00 && b <= 0xdfff
290+ then let !c = ((a - 0xd800) `shiftL` 10) +
291+ (b - 0xdc00) + 0x10000
292+ in copy h ptr >>= charUtf8 (chr c) >>= go
293+ else fail "invalid UTF-16 surrogates"
294+ done <- Z.atEnd
295+ if done
296+ then copy h ptr
297+ else rest
298+ mapping = "\"\\/\n\t\b\r\f"
299+
300+hexQuad :: Z.ZeptoT IO Int
301+hexQuad = do
302+ s <- Z.take 4
303+ let hex n | w >= C_0 && w <= C_9 = w - C_0
304+ | w >= C_a && w <= C_f = w - 87
305+ | w >= C_A && w <= C_F = w - 55
306+ | otherwise = 255
307+ where w = fromIntegral $ B.unsafeIndex s n
308+ a = hex 0; b = hex 1; c = hex 2; d = hex 3
309+ if (a .|. b .|. c .|. d) /= 255
310+ then return $! d .|. (c `shiftL` 4) .|. (b `shiftL` 8) .|. (a `shiftL` 12)
311+ else fail "invalid hex escape"
312+
369decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
313decodeWith :: Parser Value -> (Value -> Result a) -> L.ByteString -> Maybe a
370decodeWith p to s =
314decodeWith p to s =
371 case L.parse p s of
315 case L.parse p s of
@@ -390,12 +334,7 @@ eitherDecodeWith p to s =
390 L.Done _ v -> case to v of
334 L.Done _ v -> case to v of
391 ISuccess a -> Right a
335 ISuccess a -> Right a
392 IError path msg -> Left (path, msg)
336 IError path msg -> Left (path, msg)
393− L.Fail _ ctx msg -> Left ([], buildMsg ctx msg)
337+ L.Fail _ _ msg -> Left ([], msg)
394− where
395− buildMsg :: [String] -> String -> String
396− buildMsg [] msg = msg
397− buildMsg (expectation:_) msg =
398− msg ++ ". Expecting " ++ expectation
399{-# INLINE eitherDecodeWith #-}
338{-# INLINE eitherDecodeWith #-}
400
339
401eitherDecodeStrictWith :: Parser Value -> (Value -> IResult a) -> B.ByteString
340eitherDecodeStrictWith :: Parser Value -> (Value -> IResult a) -> B.ByteString
@@ -435,103 +374,37 @@ jsonEOF = json <* skipSpace <* endOfInput
435jsonEOF' :: Parser Value
374jsonEOF' :: Parser Value
436jsonEOF' = json' <* skipSpace <* endOfInput
375jsonEOF' = json' <* skipSpace <* endOfInput
437
376
438−-- | The only valid whitespace in a JSON document is space, newline,
377+word8 :: Word8 -> Ptr Word8 -> Z.ZeptoT IO (Ptr Word8)
439−-- carriage return, and tab.
378+word8 w ptr = do
440−skipSpace :: Parser ()
379+ liftIO $ poke ptr w
441−skipSpace = A.skipWhile $ \w -> w == 0x20 || w == 0x0a || w == 0x0d || w == 0x09
380+ return $! ptr `plusPtr` 1
442−{-# INLINE skipSpace #-}
381+
443−
382+copy :: ByteString -> Ptr Word8 -> Z.ZeptoT IO (Ptr Word8)
444−------------------ Copy-pasted and adapted from attoparsec ------------------
383+copy (PS fp off len) ptr =
445−
384+ liftIO . withForeignPtr fp $ \src -> do
446−-- A strict pair
385+ B.memcpy ptr (src `plusPtr` off) len
447−data SP = SP !Integer {-# UNPACK #-}!Int
386+ return $! ptr `plusPtr` len
448−
387+
449−decimal0 :: Parser Integer
388+charUtf8 :: Char -> Ptr Word8 -> Z.ZeptoT IO (Ptr Word8)
450−decimal0 = do
389+charUtf8 ch ptr
451− let zero = 48
390+ | ch < '\x80' = liftIO $ do
452− digits <- A.takeWhile1 isDigit_w8
391+ poke ptr (fromIntegral (ord ch))
453− if B.length digits > 1 && B.unsafeHead digits == zero
392+ return $! ptr `plusPtr` 1
454− then fail "leading zero"
393+ | ch < '\x800' = liftIO $ do
455− else return (bsToInteger digits)
394+ let (a,b) = ord2 ch
456−
395+ poke ptr a
457−-- | Parse a JSON number.
396+ poke (ptr `plusPtr` 1) b
458−scientific :: Parser Scientific
397+ return $! ptr `plusPtr` 2
459−scientific = do
398+ | ch < '\xffff' = liftIO $ do
460− let minus = 45
399+ let (a,b,c) = ord3 ch
461− plus = 43
400+ poke ptr a
462− sign <- A.peekWord8'
401+ poke (ptr `plusPtr` 1) b
463− let !positive = sign == plus || sign /= minus
402+ poke (ptr `plusPtr` 2) c
464− when (sign == plus || sign == minus) $
403+ return $! ptr `plusPtr` 3
465− void A.anyWord8
404+ | otherwise = liftIO $ do
466−
405+ let (a,b,c,d) = ord4 ch
467− n <- decimal0
406+ poke ptr a
468−
407+ poke (ptr `plusPtr` 1) b
469− let f fracDigits = SP (B.foldl' step n fracDigits)
408+ poke (ptr `plusPtr` 2) c
470− (negate $ B.length fracDigits)
409+ poke (ptr `plusPtr` 3) d
471− step a w = a * 10 + fromIntegral (w - 48)
410+ return $! ptr `plusPtr` 4
472−
473− dotty <- A.peekWord8
474− -- '.' -> ascii 46
475− SP c e <- case dotty of
476− Just 46 -> A.anyWord8 *> (f <$> A.takeWhile1 isDigit_w8)
477− _ -> pure (SP n 0)
478−
479− let !signedCoeff | positive = c
480− | otherwise = -c
481−
482− let littleE = 101
483− bigE = 69
484− (A.satisfy (\ex -> ex == littleE || ex == bigE) *>
485− fmap (Sci.scientific signedCoeff . (e +)) (signed decimal)) <|>
486− return (Sci.scientific signedCoeff e)
487−{-# INLINE scientific #-}
488−
489−------------------ Copy-pasted and adapted from base ------------------------
490−
491−bsToInteger :: B.ByteString -> Integer
492−bsToInteger bs
493− | l > 40 = valInteger 10 l [ fromIntegral (w - 48) | w <- B.unpack bs ]
494− | otherwise = bsToIntegerSimple bs
495− where
496− l = B.length bs
497−
498−bsToIntegerSimple :: B.ByteString -> Integer
499−bsToIntegerSimple = B.foldl' step 0 where
500− step a b = a * 10 + fromIntegral (b - 48) -- 48 = '0'
501−
502−-- A sub-quadratic algorithm for Integer. Pairs of adjacent radix b
503−-- digits are combined into a single radix b^2 digit. This process is
504−-- repeated until we are left with a single digit. This algorithm
505−-- performs well only on large inputs, so we use the simple algorithm
506−-- for smaller inputs.
507−valInteger :: Integer -> Int -> [Integer] -> Integer
508−valInteger = go
509− where
510− go :: Integer -> Int -> [Integer] -> Integer
511− go _ _ [] = 0
512− go _ _ [d] = d
513− go b l ds
514− | l > 40 = b' `seq` go b' l' (combine b ds')
515− | otherwise = valSimple b ds
516− where
517− -- ensure that we have an even number of digits
518− -- before we call combine:
519− ds' = if even l then ds else 0 : ds
520− b' = b * b
521− l' = (l + 1) `quot` 2
522−
523− combine b (d1 : d2 : ds) = d `seq` (d : combine b ds)
524− where
525− d = d1 * b + d2
526− combine _ [] = []
527− combine _ [_] = errorWithoutStackTrace "this should not happen"
528−
529−-- The following algorithm is only linear for types whose Num operations
530−-- are in constant time.
531−valSimple :: Integer -> [Integer] -> Integer
532−valSimple base = go 0
533− where
534− go r [] = r
535− go r (d : ds) = r' `seq` go r' ds
536− where
537− r' = r * base + fromIntegral d
Data/Aeson/Parser/Time.hs+104−21
@@ -1,4 +1,14 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+{-# LANGUAGE BangPatterns, CPP, ScopedTypeVariables #-}
2+
3+-- |
4+-- Module: Data.Aeson.Parser.Time
5+-- Copyright: (c) 2015-2016 Bryan O'Sullivan
6+-- License: BSD3
7+-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
8+-- Stability: experimental
9+-- Portability: portable
10+--
11+-- Parsers for parsing dates and times.
2
12
3module Data.Aeson.Parser.Time
13module Data.Aeson.Parser.Time
4 (
14 (
@@ -11,51 +21,122 @@ module Data.Aeson.Parser.Time
11 , zonedTime
21 , zonedTime
12 ) where
22 ) where
13
23
14−import Prelude.Compat
24+import Control.Monad (when, void)
15−
25+import Data.Aeson.Internal.Time (toPico)
16−import Data.Attoparsec.Text (Parser)
26+import Data.Attoparsec.Text as A
27+import Data.Bits ((.&.))
28+import Data.Char (isDigit, ord)
29+import Data.Fixed (Pico)
30+import Data.Int (Int64)
31+import Data.Maybe (fromMaybe)
17import Data.Text (Text)
32import Data.Text (Text)
18−import Data.Time.Calendar (Day)
33+import Data.Time.Calendar (Day, fromGregorianValid)
19import Data.Time.Clock (UTCTime(..))
34import Data.Time.Clock (UTCTime(..))
20import qualified Data.Aeson.Types.Internal as Aeson
35import qualified Data.Aeson.Types.Internal as Aeson
21−import qualified Data.Attoparsec.Text as A
36+import qualified Data.Text as T
22−import qualified Data.Attoparsec.Time as T
23import qualified Data.Time.LocalTime as Local
37import qualified Data.Time.LocalTime as Local
24
38
39+#if !MIN_VERSION_base(4,8,0)
40+import Control.Applicative ((<$>), (<*>), (<*), (*>))
41+#endif
42+
25-- | Run an attoparsec parser as an aeson parser.
43-- | Run an attoparsec parser as an aeson parser.
26run :: Parser a -> Text -> Aeson.Parser a
44run :: Parser a -> Text -> Aeson.Parser a
27−run p t = case A.parseOnly (p <* A.endOfInput) t of
45+run p t = case A.parseOnly (p <* endOfInput) t of
28 Left err -> fail $ "could not parse date: " ++ err
46 Left err -> fail $ "could not parse date: " ++ err
29 Right r -> return r
47 Right r -> return r
30
48
31−-- | Parse a date of the form @[+,-]YYYY-MM-DD@.
49+-- | Parse a date of the form @YYYY-MM-DD@.
32day :: Parser Day
50day :: Parser Day
33−day = T.day
51+day = do
34−{-# INLINE day #-}
52+ y <- decimal <* char '-'
53+ m <- twoDigits <* char '-'
54+ d <- twoDigits
55+ maybe (fail "invalid date") return (fromGregorianValid y m d)
56+
57+-- | Parse a two-digit integer (e.g. day of month, hour).
58+twoDigits :: Parser Int
59+twoDigits = do
60+ a <- digit
61+ b <- digit
62+ let c2d c = ord c .&. 15
63+ return $! c2d a * 10 + c2d b
35
64
36-- | Parse a time of the form @HH:MM[:SS[.SSS]]@.
65-- | Parse a time of the form @HH:MM[:SS[.SSS]]@.
37timeOfDay :: Parser Local.TimeOfDay
66timeOfDay :: Parser Local.TimeOfDay
38−timeOfDay = T.timeOfDay
67+timeOfDay = do
39−{-# INLINE timeOfDay #-}
68+ h <- twoDigits
69+ m <- char ':' *> twoDigits
70+ s <- option 0 (char ':' *> seconds)
71+ if h < 24 && m < 60 && s < 61
72+ then return (Local.TimeOfDay h m s)
73+ else fail "invalid time"
74+
75+data T = T {-# UNPACK #-} !Int {-# UNPACK #-} !Int64
76+
77+-- | Parse a count of seconds, with the integer part being two digits
78+-- long.
79+seconds :: Parser Pico
80+seconds = do
81+ real <- twoDigits
82+ mc <- peekChar
83+ case mc of
84+ Just '.' -> do
85+ t <- anyChar *> takeWhile1 isDigit
86+ return $! parsePicos real t
87+ _ -> return $! fromIntegral real
88+ where
89+ parsePicos a0 t = toPico (fromIntegral (t' * 10^n))
90+ where T n t' = T.foldl' step (T 12 (fromIntegral a0)) t
91+ step ma@(T m a) c
92+ | m <= 0 = ma
93+ | otherwise = T (m-1) (10 * a + fromIntegral (ord c) .&. 15)
40
94
41-- | Parse a time zone, and return 'Nothing' if the offset from UTC is
95-- | Parse a time zone, and return 'Nothing' if the offset from UTC is
42-- zero. (This makes some speedups possible.)
96-- zero. (This makes some speedups possible.)
43timeZone :: Parser (Maybe Local.TimeZone)
97timeZone :: Parser (Maybe Local.TimeZone)
44−timeZone = T.timeZone
98+timeZone = do
45−{-# INLINE timeZone #-}
99+ let maybeSkip c = do ch <- peekChar'; when (ch == c) (void anyChar)
100+ maybeSkip ' '
101+ ch <- satisfy $ \c -> c == 'Z' || c == '+' || c == '-'
102+ if ch == 'Z'
103+ then return Nothing
104+ else do
105+ h <- twoDigits
106+ mm <- peekChar
107+ m <- case mm of
108+ Just ':' -> anyChar *> twoDigits
109+ Just d | isDigit d -> twoDigits
110+ _ -> return 0
111+ let off | ch == '-' = negate off0
112+ | otherwise = off0
113+ off0 = h * 60 + m
114+ case undefined of
115+ _ | off == 0 ->
116+ return Nothing
117+ | off < -720 || off > 840 || m > 59 ->
118+ fail "invalid time zone offset"
119+ | otherwise ->
120+ let !tz = Local.minutesToTimeZone off
121+ in return (Just tz)
46
122
47-- | Parse a date and time, of the form @YYYY-MM-DD HH:MM[:SS[.SSS]]@.
123-- | Parse a date and time, of the form @YYYY-MM-DD HH:MM[:SS[.SSS]]@.
48-- The space may be replaced with a @T@. The number of seconds is optional
124-- The space may be replaced with a @T@. The number of seconds is optional
49-- and may be followed by a fractional component.
125-- and may be followed by a fractional component.
50localTime :: Parser Local.LocalTime
126localTime :: Parser Local.LocalTime
51−localTime = T.localTime
127+localTime = Local.LocalTime <$> day <* daySep <*> timeOfDay
52−{-# INLINE localTime #-}
128+ where daySep = satisfy (\c -> c == 'T' || c == ' ')
53
129
54-- | Behaves as 'zonedTime', but converts any time zone offset into a
130-- | Behaves as 'zonedTime', but converts any time zone offset into a
55-- UTC time.
131-- UTC time.
56utcTime :: Parser UTCTime
132utcTime :: Parser UTCTime
57−utcTime = T.utcTime
133+utcTime = do
58−{-# INLINE utcTime #-}
134+ lt@(Local.LocalTime d t) <- localTime
135+ mtz <- timeZone
136+ case mtz of
137+ Nothing -> let !tt = Local.timeOfDayToTime t
138+ in return (UTCTime d tt)
139+ Just tz -> return $! Local.localTimeToUTC tz lt
59
140
60-- | Parse a date with time zone info. Acceptable formats:
141-- | Parse a date with time zone info. Acceptable formats:
61--
142--
@@ -69,5 +150,7 @@ utcTime = T.utcTime
69-- two digits are hours, the @:@ is optional and the second two digits
150-- two digits are hours, the @:@ is optional and the second two digits
70-- (also optional) are minutes.
151-- (also optional) are minutes.
71zonedTime :: Parser Local.ZonedTime
152zonedTime :: Parser Local.ZonedTime
72−zonedTime = T.zonedTime
153+zonedTime = Local.ZonedTime <$> localTime <*> (fromMaybe utc <$> timeZone)
73−{-# INLINE zonedTime #-}
154+
155+utc :: Local.TimeZone
156+utc = Local.TimeZone 0 False ""
Data/Aeson/Parser/Unescape.hsdeleted−11
@@ -1,11 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−module Data.Aeson.Parser.Unescape
3− (
4− unescapeText
5− ) where
6−
7−#ifdef CFFI
8−import Data.Aeson.Parser.UnescapeFFI (unescapeText)
9−#else
10−import Data.Aeson.Parser.UnescapePure (unescapeText)
11−#endif
Data/Aeson/QQ/Simple.hsdeleted−25
@@ -1,25 +0,0 @@
1−-- | Like "Data.Aeson.QQ" but without interpolation.
2−module Data.Aeson.QQ.Simple (aesonQQ) where
3−
4−import Data.Aeson
5−import qualified Data.Text as T
6−import qualified Data.Text.Encoding as TE
7−import Language.Haskell.TH
8−import Language.Haskell.TH.Quote
9−import Language.Haskell.TH.Syntax (Lift (..))
10−import Prelude ()
11−import Prelude.Compat
12−
13−aesonQQ :: QuasiQuoter
14−aesonQQ = QuasiQuoter
15− { quoteExp = aesonExp
16− , quotePat = const $ error "No quotePat defined for jsonQQ"
17− , quoteType = const $ error "No quoteType defined for jsonQQ"
18− , quoteDec = const $ error "No quoteDec defined for jsonQQ"
19− }
20−
21−aesonExp :: String -> ExpQ
22−aesonExp txt =
23− case eitherDecodeStrict $ TE.encodeUtf8 $ T.pack txt of
24− Left err -> error $ "Error in aesonExp: " ++ show err
25− Right val -> lift (val :: Value)
Data/Aeson/TH.hs+962−522
@@ -13,7 +13,6 @@
13{-# LANGUAGE TemplateHaskell #-}
13{-# LANGUAGE TemplateHaskell #-}
14#endif
14#endif
15
15
16−#include "incoherent-compat.h"
17#include "overlapping-compat.h"
16#include "overlapping-compat.h"
18
17
19{-|
18{-|
@@ -85,13 +84,10 @@ $('deriveJSON' 'defaultOptions' ''(,,,))
85@
84@
86
85
87-}
86-}
87+
88module Data.Aeson.TH
88module Data.Aeson.TH
89− (
90− -- * Encoding configuration
89+ ( -- * Encoding configuration
91− Options(..)
92− , SumEncoding(..)
93− , defaultOptions
94− , defaultTaggedObject
90+ Options(..), SumEncoding(..), defaultOptions, defaultTaggedObject
95
91
96 -- * FromJSON and ToJSON derivation
92 -- * FromJSON and ToJSON derivation
97 , deriveJSON
93 , deriveJSON
@@ -116,41 +112,73 @@ module Data.Aeson.TH
116 , mkLiftParseJSON2
112 , mkLiftParseJSON2
117 ) where
113 ) where
118
114
119−import Prelude.Compat
120−
121−import Control.Applicative ((<|>))
115+import Control.Applicative ( pure, (<$>), (<*>) )
122−import Data.Aeson (Object, (.:), FromJSON(..), FromJSON1(..), FromJSON2(..), ToJSON(..), ToJSON1(..), ToJSON2(..))
116+import Data.Aeson ( Object, (.=), (.:)
117+ , ToJSON(..), FromJSON(..)
118+ , ToJSON1(..), FromJSON1(..)
119+ , ToJSON2(..), FromJSON2(..)
120+ )
123−import Data.Aeson.Types (Options(..), Parser, SumEncoding(..), Value(..), defaultOptions, defaultTaggedObject)
121+import Data.Aeson.Types ( Value(..), Parser
122+ , Options(..)
123+ , SumEncoding(..)
124+ , defaultOptions
125+ , defaultTaggedObject
126+ )
124−import Data.Aeson.Types.Internal ((<?>), JSONPathElement(Key))
127+import Data.Aeson.Types.Internal (Pair, (<?>), JSONPathElement(Key))
125import Data.Aeson.Types.FromJSON (parseOptionalFieldWith)
128import Data.Aeson.Types.FromJSON (parseOptionalFieldWith)
126−import Data.Aeson.Types.ToJSON (fromPairs, pair)
127−import Control.Monad (liftM2, unless, when)
129+import Control.Monad ( fail, liftM2, mapM, return, unless, when )
130+import Data.Bool ( Bool(False, True), otherwise, (&&), not )
131+import Data.Either ( Either(Left, Right) )
132+import Data.Eq ( (==) )
128−import Data.Foldable (foldr')
133+import Data.Foldable ( concatMap, foldr' )
134+import Data.Function ( ($), (.), flip )
135+import Data.Functor ( fmap )
136+import Data.Int ( Int )
137+import Data.List ( (++), all, any, find, foldl, foldl'
138+ , genericLength , intercalate , intersperse, length, map
139+ , partition, union, zip, zip3
140+ )
141+import Data.List.NonEmpty ( NonEmpty((:|)), (<|) )
142+import Data.Map ( Map )
143+import Data.Maybe ( Maybe(Nothing, Just), catMaybes, fromMaybe, mapMaybe )
144+import Data.Monoid ( (<>), mconcat )
145+import Data.Set ( Set )
146+import Language.Haskell.TH
129−#if MIN_VERSION_template_haskell(2,8,0) && !MIN_VERSION_template_haskell(2,10,0)
147+#if MIN_VERSION_template_haskell(2,8,0)
130−import Data.List (nub)
148+ hiding ( Arity )
149+#endif
150+import Language.Haskell.TH.Syntax ( VarStrictType )
151+import Prelude ( Enum(..), Eq(..), Integer, Ord(..), String
152+ , concat, cycle, drop, elem, error, foldr1, fromIntegral
153+ , showChar, showParen, shows, showString, snd, splitAt
154+ , take, unzip, zipWith, (-), (||)
155+ )
156+#if MIN_VERSION_template_haskell(2,7,0) && !(MIN_VERSION_template_haskell(2,8,0))
157+import Language.Haskell.TH.Lib ( starK )
131#endif
158#endif
132−import Data.List (foldl', genericLength, intercalate, partition, union)
133−import Data.List.NonEmpty ((<|), NonEmpty((:|)))
134−import Data.Map (Map)
135−import Data.Maybe (catMaybes, fromMaybe, mapMaybe)
136−import qualified Data.Monoid as Monoid
137−import Data.Set (Set)
138−import Language.Haskell.TH hiding (Arity)
139−import Language.Haskell.TH.Datatype
140#if MIN_VERSION_template_haskell(2,8,0) && !(MIN_VERSION_template_haskell(2,10,0))
159#if MIN_VERSION_template_haskell(2,8,0) && !(MIN_VERSION_template_haskell(2,10,0))
160+import Data.List ( nub )
141−import Language.Haskell.TH.Syntax (mkNameG_tc)
161+import Language.Haskell.TH.Syntax ( mkNameG_tc )
162+import Prelude ( uncurry )
142#endif
163#endif
164+#if MIN_VERSION_template_haskell(2,11,0)
165+import Prelude ( head )
166+#endif
143−import Text.Printf (printf)
167+import Text.Printf ( printf )
168+import Text.Show ( show )
169+import qualified Data.Aeson as A
144import qualified Data.Aeson.Encoding.Internal as E
170import qualified Data.Aeson.Encoding.Internal as E
145−import qualified Data.Foldable as F (all)
171+import qualified Data.Foldable as F ( all )
146−import qualified Data.HashMap.Strict as H (difference, fromList, keys, lookup, toList)
172+import qualified Data.HashMap.Strict as H ( lookup, toList )
147−import qualified Data.List.NonEmpty as NE (length, reverse)
173+import qualified Data.List.NonEmpty as NE ( drop, length, reverse, splitAt )
148−import qualified Data.Map as M (fromList, keys, lookup , singleton, size)
174+import qualified Data.Map as M ( fromList, findWithDefault, keys, lookup
149−import qualified Data.Semigroup as Semigroup (Option(..))
175+ , singleton, size
176+ )
150−import qualified Data.Set as Set (empty, insert, member)
177+import qualified Data.Set as Set ( empty, insert, member )
151−import qualified Data.Text as T (Text, pack, unpack)
178+import qualified Data.Text as T ( Text, pack, unpack )
152−import qualified Data.Vector as V (unsafeIndex, null, length, create, empty)
179+import qualified Data.Vector as V ( unsafeIndex, null, length, create, fromList )
153−import qualified Data.Vector.Mutable as VM (unsafeNew, unsafeWrite)
180+import qualified Data.Vector.Mutable as VM ( unsafeNew, unsafeWrite )
181+
154
182
155--------------------------------------------------------------------------------
183--------------------------------------------------------------------------------
156-- Convenience
184-- Convenience
@@ -245,8 +273,8 @@ deriveToJSONCommon :: JSONClass
245 -> Name
273 -> Name
246 -- ^ Name of the type for which to generate an instance.
274 -- ^ Name of the type for which to generate an instance.
247 -> Q [Dec]
275 -> Q [Dec]
248−deriveToJSONCommon = deriveJSONClass [ (ToJSON, \jc _ -> consToValue Value jc)
276+deriveToJSONCommon = deriveJSONClass [ (ToJSON, \jc _ -> consToValue jc)
249− , (ToEncoding, \jc _ -> consToValue Encoding jc)
277+ , (ToEncoding, \jc _ -> consToEncoding jc)
250 ]
278 ]
251
279
252-- | Generates a lambda expression which encodes the given data type or
280-- | Generates a lambda expression which encodes the given data type or
@@ -276,7 +304,7 @@ mkToJSONCommon :: JSONClass -- ^ Which class's method is being derived.
276 -> Options -- ^ Encoding options.
304 -> Options -- ^ Encoding options.
277 -> Name -- ^ Name of the encoded type.
305 -> Name -- ^ Name of the encoded type.
278 -> Q Exp
306 -> Q Exp
279−mkToJSONCommon = mkFunCommon (\jc _ -> consToValue Value jc)
307+mkToJSONCommon = mkFunCommon (\jc _ -> consToValue jc)
280
308
281-- | Generates a lambda expression which encodes the given data type or
309-- | Generates a lambda expression which encodes the given data type or
282-- data family instance constructor as a JSON string.
310-- data family instance constructor as a JSON string.
@@ -305,272 +333,409 @@ mkToEncodingCommon :: JSONClass -- ^ Which class's method is being derived.
305 -> Options -- ^ Encoding options.
333 -> Options -- ^ Encoding options.
306 -> Name -- ^ Name of the encoded type.
334 -> Name -- ^ Name of the encoded type.
307 -> Q Exp
335 -> Q Exp
308−mkToEncodingCommon = mkFunCommon (\jc _ -> consToValue Encoding jc)
336+mkToEncodingCommon = mkFunCommon (\jc _ -> consToEncoding jc)
309
337
310-- | Helper function used by both 'deriveToJSON' and 'mkToJSON'. Generates
338-- | Helper function used by both 'deriveToJSON' and 'mkToJSON'. Generates
311−-- code to generate a 'Value' or 'Encoding' of a number of constructors. All
339+-- code to generate a 'Value' of a number of constructors. All constructors
312−-- constructors must be from the same type.
340+-- must be from the same type.
313−consToValue :: ToJSONFun
314− -- ^ The method ('toJSON' or 'toEncoding') being derived.
315− -> JSONClass
341+consToValue :: JSONClass
316 -- ^ The ToJSON variant being derived.
342 -- ^ The ToJSON variant being derived.
317 -> Options
343 -> Options
318 -- ^ Encoding options.
344 -- ^ Encoding options.
319− -> [Type]
345+ -> [Con]
320− -- ^ The types from the data type/data family instance declaration
321− -> [ConstructorInfo]
322 -- ^ Constructors for which to generate JSON generating code.
346 -- ^ Constructors for which to generate JSON generating code.
323 -> Q Exp
347 -> Q Exp
324
348
325−consToValue _ _ _ _ [] = error $ "Data.Aeson.TH.consToValue: "
349+consToValue _ _ [] = error $ "Data.Aeson.TH.consToValue: "
326− ++ "Not a single constructor given!"
350+ ++ "Not a single constructor given!"
327
351
328−consToValue target jc opts instTys cons = do
352+consToValue jc opts cons = do
329 value <- newName "value"
353 value <- newName "value"
330 tjs <- newNameList "_tj" $ arityInt jc
354 tjs <- newNameList "_tj" $ arityInt jc
331 tjls <- newNameList "_tjl" $ arityInt jc
355 tjls <- newNameList "_tjl" $ arityInt jc
332 let zippedTJs = zip tjs tjls
356 let zippedTJs = zip tjs tjls
333 interleavedTJs = interleave tjs tjls
357 interleavedTJs = interleave tjs tjls
334− lastTyVars = map varTToName $ drop (length instTys - arityInt jc) instTys
335− tvMap = M.fromList $ zip lastTyVars zippedTJs
336 lamE (map varP $ interleavedTJs ++ [value]) $
358 lamE (map varP $ interleavedTJs ++ [value]) $
337− caseE (varE value) (matches tvMap)
359+ caseE (varE value) (matches zippedTJs)
338 where
360 where
339− matches tvMap = case cons of
361+ matches tjs = case cons of
340 -- A single constructor is directly encoded. The constructor itself may be
362 -- A single constructor is directly encoded. The constructor itself may be
341 -- forgotten.
363 -- forgotten.
342− [con] | not (tagSingleConstructors opts) -> [argsToValue target jc tvMap opts False con]
364+ [con] -> [argsToValue jc tjs opts False con]
343 _ | allNullaryToStringTag opts && all isNullary cons ->
365 _ | allNullaryToStringTag opts && all isNullary cons ->
344− [ match (conP conName []) (normalB $ conStr target opts conName) []
366+ [ match (conP conName []) (normalB $ conStr opts conName) []
345 | con <- cons
367 | con <- cons
346− , let conName = constructorName con
368+ , let conName = getConName con
347 ]
369 ]
348− | otherwise -> [argsToValue target jc tvMap opts True con | con <- cons]
370+ | otherwise -> [argsToValue jc tjs opts True con | con <- cons]
349
371
350−-- | Name of the constructor as a quoted 'Value' or 'Encoding'.
351−conStr :: ToJSONFun -> Options -> Name -> Q Exp
372+conStr :: Options -> Name -> Q Exp
352−conStr Value opts = appE [|String|] . conTxt opts
373+conStr opts = appE [|String|] . conTxt opts
353−conStr Encoding opts = appE [|E.text|] . conTxt opts
354
374
355−-- | Name of the constructor as a quoted 'Text'.
356conTxt :: Options -> Name -> Q Exp
375conTxt :: Options -> Name -> Q Exp
357−conTxt opts = appE [|T.pack|] . stringE . conString opts
376+conTxt opts = appE [|T.pack|] . conStringE opts
377+
378+conStringE :: Options -> Name -> Q Exp
379+conStringE opts = stringE . constructorTagModifier opts . nameBase
380+
381+-- | Helper function used by both 'deriveToJSON' and 'mkToEncoding'. Generates
382+-- code to write out a value for a number of constructors. All constructors
383+-- must be from the same type.
384+consToEncoding :: JSONClass
385+ -- ^ The ToJSON variant being derived.
386+ -> Options
387+ -- ^ Encoding options.
388+ -> [Con]
389+ -- ^ Constructors for which to generate JSON generating code.
390+ -> Q Exp
391+
392+consToEncoding _ _ [] = error $ "Data.Aeson.TH.consToEncoding: "
393+ ++ "Not a single constructor given!"
394+
395+consToEncoding jc opts cons = do
396+ value <- newName "value"
397+ tes <- newNameList "_te" $ arityInt jc
398+ tels <- newNameList "_tel" $ arityInt jc
399+ let zippedTEs = zip tes tels
400+ interleavedTEs = interleave tes tels
401+ lamE (map varP $ interleavedTEs ++ [value]) $
402+ caseE (varE value) (matches zippedTEs)
403+ where
404+ matches tes = case cons of
405+ -- A single constructor is directly encoded. The constructor itself may be
406+ -- forgotten.
407+ [con] -> [argsToEncoding jc tes opts False con]
408+ -- Encode just the name of the constructor of a sum type iff all the
409+ -- constructors are nullary.
410+ _ | allNullaryToStringTag opts && all isNullary cons ->
411+ [ match (conP conName [])
412+ (normalB $ encStr opts conName) []
413+ | con <- cons
414+ , let conName = getConName con
415+ ]
416+ | otherwise -> [argsToEncoding jc tes opts True con | con <- cons]
358
417
359−-- | Name of the constructor.
360−conString :: Options -> Name -> String
418+encStr :: Options -> Name -> Q Exp
361−conString opts = constructorTagModifier opts . nameBase
419+encStr opts = appE [|E.text|] . conTxt opts
362
420
363-- | If constructor is nullary.
421-- | If constructor is nullary.
364−isNullary :: ConstructorInfo -> Bool
422+isNullary :: Con -> Bool
365−isNullary ConstructorInfo { constructorVariant = NormalConstructor
423+isNullary (NormalC _ []) = True
366− , constructorFields = tys } = null tys
367isNullary _ = False
424isNullary _ = False
368
425
369−-- | Wrap fields of a non-record constructor. See 'sumToValue'.
426+sumToValue :: Options -> Bool -> Name -> Q Exp -> Q Exp
370−opaqueSumToValue :: ToJSONFun -> Options -> Bool -> Bool -> Name -> ExpQ -> ExpQ
371−opaqueSumToValue target opts multiCons nullary conName value =
372− sumToValue target opts multiCons nullary conName
373− value
374− pairs
375− where
376− pairs contentsFieldName = pairE contentsFieldName value
377−
378−-- | Wrap fields of a record constructor. See 'sumToValue'.
379−recordSumToValue :: ToJSONFun -> Options -> Bool -> Bool -> Name -> ExpQ -> ExpQ
380−recordSumToValue target opts multiCons nullary conName pairs =
381− sumToValue target opts multiCons nullary conName
427+sumToValue opts multiCons conName exp
382− (fromPairsE pairs)
383− (const pairs)
384−
385−-- | Wrap fields of a constructor.
386−sumToValue
387− :: ToJSONFun
388− -- ^ The method being derived.
389− -> Options
390− -- ^ Deriving options.
391− -> Bool
392− -- ^ Does this type have multiple constructors.
393− -> Bool
394− -- ^ Is this constructor nullary.
395− -> Name
396− -- ^ Constructor name.
397− -> ExpQ
398− -- ^ Fields of the constructor as a 'Value' or 'Encoding'.
399− -> (String -> ExpQ)
400− -- ^ Representation of an 'Object' fragment used for the 'TaggedObject'
401− -- variant; of type @[(Text,Value)]@ or @[Encoding]@, depending on the method
402− -- being derived.
403− --
404− -- - For non-records, produces a pair @"contentsFieldName":value@,
405− -- given a @contentsFieldName@ as an argument. See 'opaqueSumToValue'.
406− -- - For records, produces the list of pairs corresponding to fields of the
407− -- encoded value (ignores the argument). See 'recordSumToValue'.
408− -> ExpQ
409−sumToValue target opts multiCons nullary conName value pairs
410 | multiCons =
428 | multiCons =
411 case sumEncoding opts of
429 case sumEncoding opts of
412 TwoElemArray ->
430 TwoElemArray ->
413− array target [conStr target opts conName, value]
431+ [|Array|] `appE` ([|V.fromList|] `appE` listE [conStr opts conName, exp])
414 TaggedObject{tagFieldName, contentsFieldName} ->
432 TaggedObject{tagFieldName, contentsFieldName} ->
415− -- TODO: Maybe throw an error in case
433+ [|A.object|] `appE` listE
416− -- tagFieldName overwrites a field in pairs.
434+ [ infixApp [|T.pack tagFieldName|] [|(.=)|] (conStr opts conName)
417− let tag = pairE tagFieldName (conStr target opts conName)
418− content = pairs contentsFieldName
435+ , infixApp [|T.pack contentsFieldName|] [|(.=)|] exp
419− in fromPairsE $
436+ ]
420− if nullary then tag else infixApp tag [|(Monoid.<>)|] content
421 ObjectWithSingleField ->
437 ObjectWithSingleField ->
422− objectE [(conString opts conName, value)]
438+ [|A.object|] `appE` listE
439+ [ infixApp (conTxt opts conName) [|(.=)|] exp
440+ ]
441+
442+ | otherwise = exp
443+
444+nullarySumToValue :: Options -> Bool -> Name -> Q Exp
445+nullarySumToValue opts multiCons conName =
446+ case sumEncoding opts of
447+ TaggedObject{tagFieldName} ->
448+ [|A.object|] `appE` listE
423− UntaggedValue | nullary -> conStr target opts conName
449+ [ infixApp [|T.pack tagFieldName|] [|(.=)|] (conStr opts conName)
424− UntaggedValue -> value
450+ ]
425− | otherwise = value
451+ _ -> sumToValue opts multiCons conName [e|toJSON ([] :: [()])|]
426
452
427-- | Generates code to generate the JSON encoding of a single constructor.
453-- | Generates code to generate the JSON encoding of a single constructor.
428−argsToValue :: ToJSONFun -> JSONClass -> TyVarMap -> Options -> Bool -> ConstructorInfo -> Q Match
454+argsToValue :: JSONClass -> [(Name, Name)] -> Options -> Bool -> Con -> Q Match
455+-- Nullary constructors. Generates code that explicitly matches against the
456+-- constructor even though it doesn't contain data. This is useful to prevent
457+-- type errors.
458+argsToValue jc tjs opts multiCons (NormalC conName []) = do
459+ ([], _) <- reifyConTys jc tjs conName
460+ match (conP conName [])
461+ (normalB (nullarySumToValue opts multiCons conName))
462+ []
429
463
430-- Polyadic constructors with special case for unary constructors.
464-- Polyadic constructors with special case for unary constructors.
431−argsToValue target jc tvMap opts multiCons
465+argsToValue jc tjs opts multiCons (NormalC conName ts) = do
432− ConstructorInfo { constructorName = conName
466+ (argTys, tvMap) <- reifyConTys jc tjs conName
433− , constructorVariant = NormalConstructor
434− , constructorFields = argTys } = do
435− argTys' <- mapM resolveTypeSynonyms argTys
436− let len = length argTys'
467+ let len = length ts
437 args <- newNameList "arg" len
468 args <- newNameList "arg" len
438− let js = case [ dispatchToJSON target jc conName tvMap argTy
469+ js <- case [ dispatchToJSON jc conName tvMap argTy
439− `appE` varE arg
470+ `appE` varE arg
440− | (arg, argTy) <- zip args argTys'
471+ | (arg, argTy) <- zip args argTys
441− ] of
472+ ] of
442− -- Single argument is directly converted.
473+ -- Single argument is directly converted.
443− [e] -> e
474+ [e] -> return e
444− -- Zero and multiple arguments are converted to a JSON array.
475+ -- Multiple arguments are converted to a JSON array.
445− es -> array target es
476+ es -> do
446−
477+ mv <- newName "mv"
478+ let newMV = bindS (varP mv)
479+ ([|VM.unsafeNew|] `appE`
480+ litE (integerL $ fromIntegral len))
481+ stmts = [ noBindS $
482+ [|VM.unsafeWrite|] `appE`
483+ (varE mv) `appE`
484+ litE (integerL ix) `appE`
485+ e
486+ | (ix, e) <- zip [(0::Integer)..] es
487+ ]
488+ ret = noBindS $ [|return|] `appE` varE mv
489+ return $ [|Array|] `appE`
490+ (varE 'V.create `appE`
491+ doE (newMV:stmts++[ret]))
447 match (conP conName $ map varP args)
492 match (conP conName $ map varP args)
448− (normalB $ opaqueSumToValue target opts multiCons (null argTys') conName js)
493+ (normalB $ sumToValue opts multiCons conName js)
449 []
494 []
450
495
451-- Records.
496-- Records.
452−argsToValue target jc tvMap opts multiCons
453− info@ConstructorInfo { constructorName = conName
454− , constructorVariant = RecordConstructor fields
455− , constructorFields = argTys } =
456− case (unwrapUnaryRecords opts, not multiCons, argTys) of
497+argsToValue jc tjs opts multiCons (RecC conName ts) = case (unwrapUnaryRecords opts, not multiCons, ts) of
457− (True,True,[_]) -> argsToValue target jc tvMap opts multiCons
498+ (True,True,[(_,st,ty)]) -> argsToValue jc tjs opts multiCons (NormalC conName [(st,ty)])
458− (info{constructorVariant = NormalConstructor})
459− _ -> do
499+ _ -> do
460− argTys' <- mapM resolveTypeSynonyms argTys
500+ (argTys, tvMap) <- reifyConTys jc tjs conName
461− args <- newNameList "arg" $ length argTys'
501+ args <- newNameList "arg" $ length ts
502+ let exp = [|A.object|] `appE` pairs
503+
462− let pairs | omitNothingFields opts = infixApp maybeFields
504+ pairs | omitNothingFields opts = infixApp maybeFields
463− [|(Monoid.<>)|]
505+ [|(++)|]
464− restFields
506+ restFields
465− | otherwise = mconcatE (map pureToPair argCons)
507+ | otherwise = listE $ map toPair argCons
466−
508+
467− argCons = zip3 (map varE args) argTys' fields
509+ argCons = zip3 args argTys ts
468−
510+
469− maybeFields = mconcatE (map maybeToPair maybes)
511+ maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)
470−
512+
471− restFields = mconcatE (map pureToPair rest)
513+ restFields = listE $ map toPair rest
472−
514+
473− (maybes0, rest0) = partition isMaybe argCons
515+ (maybes, rest) = partition isMaybe argCons
474− (options, rest) = partition isOption rest0
516+
475− maybes = maybes0 ++ map optionToMaybe options
517+ maybeToPair (arg, argTy, (field, _, _)) =
476−
518+ infixApp ([|keyValuePairWith|]
477− maybeToPair = toPairLifted True
519+ `appE` dispatchToJSON jc conName tvMap argTy
478− pureToPair = toPairLifted False
520+ `appE` toFieldName field)
479−
521+ [|(<$>)|]
522+ (varE arg)
523+
480− toPairLifted lifted (arg, argTy, field) =
524+ toPair (arg, argTy, (field, _, _)) =
525+ [|keyValuePairWith|]
481− let toValue = dispatchToJSON target jc conName tvMap argTy
526+ `appE` dispatchToJSON jc conName tvMap argTy
482− fieldName = fieldLabel opts field
527+ `appE` toFieldName field
483− e arg' = pairE fieldName (toValue `appE` arg')
528+ `appE` varE arg
484− in if lifted
529+
485− then do
530+ toFieldName field = [|T.pack|] `appE` fieldLabelExp opts field
486− x <- newName "x"
531+
487− [|maybe mempty|] `appE` lam1E (varP x) (e (varE x)) `appE` arg
488− else e arg
489−
490− match (conP conName $ map varP args)
532+ match (conP conName $ map varP args)
491− (normalB $ recordSumToValue target opts multiCons (null argTys) conName pairs)
533+ ( normalB
534+ $ if multiCons
535+ then case sumEncoding opts of
536+ TwoElemArray -> [|toJSON|] `appE` tupE [conStr opts conName, exp]
537+ TaggedObject{tagFieldName} ->
538+ [|A.object|] `appE`
539+ -- TODO: Maybe throw an error in case
540+ -- tagFieldName overwrites a field in pairs.
541+ infixApp (infixApp [|T.pack tagFieldName|]
542+ [|(.=)|]
543+ (conStr opts conName))
544+ [|(:)|]
545+ pairs
546+ ObjectWithSingleField ->
547+ [|A.object|] `appE` listE
548+ [ infixApp (conTxt opts conName) [|(.=)|] exp ]
549+ else exp
492− []
550+ ) []
493
551
494-- Infix constructors.
552-- Infix constructors.
495−argsToValue target jc tvMap opts multiCons
553+argsToValue jc tjs opts multiCons (InfixC _ conName _) = do
496− ConstructorInfo { constructorName = conName
554+ ([alTy, arTy], tvMap) <- reifyConTys jc tjs conName
497− , constructorVariant = InfixConstructor
498− , constructorFields = argTys } = do
499− [alTy, arTy] <- mapM resolveTypeSynonyms argTys
500 al <- newName "argL"
555 al <- newName "argL"
501 ar <- newName "argR"
556 ar <- newName "argR"
502 match (infixP (varP al) conName (varP ar))
557 match (infixP (varP al) conName (varP ar))
503 ( normalB
558 ( normalB
504− $ opaqueSumToValue target opts multiCons False conName
559+ $ sumToValue opts multiCons conName
505− $ array target
506− [ dispatchToJSON target jc conName tvMap aTy
560+ $ [|toJSON|] `appE` listE [ dispatchToJSON jc conName tvMap aTy
507− `appE` varE a
561+ `appE` varE a
508− | (a, aTy) <- [(al,alTy), (ar,arTy)]
562+ | (a, aTy) <- [(al,alTy), (ar,arTy)]
509− ]
563+ ]
510 )
564 )
511 []
565 []
566+-- Existentially quantified constructors.
567+argsToValue jc tjs opts multiCons (ForallC _ _ con) =
568+ argsToValue jc tjs opts multiCons con
512
569
513−isMaybe :: (a, Type, b) -> Bool
570+#if MIN_VERSION_template_haskell(2,11,0)
514−isMaybe (_, AppT (ConT t) _, _) = t == ''Maybe
571+-- GADTs.
515−isMaybe _ = False
572+argsToValue jc tjs opts multiCons (GadtC conNames ts _) =
573+ argsToValue jc tjs opts multiCons $ NormalC (head conNames) ts
516
574
517−isOption :: (a, Type, b) -> Bool
575+argsToValue jc tjs opts multiCons (RecGadtC conNames ts _) =
518−isOption (_, AppT (ConT t) _, _) = t == ''Semigroup.Option
576+ argsToValue jc tjs opts multiCons $ RecC (head conNames) ts
519−isOption _ = False
577+#endif
520
578
521−optionToMaybe :: (ExpQ, b, c) -> (ExpQ, b, c)
579+isMaybe :: (a, b, (c, d, Type)) -> Bool
522−optionToMaybe (a, b, c) = ([|Semigroup.getOption|] `appE` a, b, c)
580+isMaybe (_, _, (_, _, AppT (ConT t) _)) = t == ''Maybe
581+isMaybe _ = False
523
582
524(<^>) :: ExpQ -> ExpQ -> ExpQ
583(<^>) :: ExpQ -> ExpQ -> ExpQ
525−(<^>) a b = infixApp a [|(E.><)|] b
584+(<^>) a b = infixApp a [|(<>)|] b
526infixr 6 <^>
585infixr 6 <^>
527
586
587+(<:>) :: ExpQ -> ExpQ -> ExpQ
588+(<:>) a b = a <^> [|E.colon|] <^> b
589+infixr 5 <:>
590+
528(<%>) :: ExpQ -> ExpQ -> ExpQ
591(<%>) :: ExpQ -> ExpQ -> ExpQ
529(<%>) a b = a <^> [|E.comma|] <^> b
592(<%>) a b = a <^> [|E.comma|] <^> b
530infixr 4 <%>
593infixr 4 <%>
531
594
532−-- | Wrap a list of quoted 'Value's in a quoted 'Array' (of type 'Value').
533−array :: ToJSONFun -> [ExpQ] -> ExpQ
595+array :: ExpQ -> ExpQ
534−array Encoding [] = [|E.emptyArray_|]
535−array Value [] = [|Array V.empty|]
536−array Encoding es = [|E.wrapArray|] `appE` foldr1 (<%>) es
596+array exp = [|E.wrapArray|] `appE` exp
537−array Value es = do
538− mv <- newName "mv"
539− let newMV = bindS (varP mv)
540− ([|VM.unsafeNew|] `appE`
541− litE (integerL $ fromIntegral (length es)))
542− stmts = [ noBindS $
543− [|VM.unsafeWrite|] `appE`
544− varE mv `appE`
545− litE (integerL ix) `appE`
546− e
547− | (ix, e) <- zip [(0::Integer)..] es
548− ]
549− ret = noBindS $ [|return|] `appE` varE mv
550− [|Array|] `appE`
551− (varE 'V.create `appE`
552− doE (newMV:stmts++[ret]))
553
597
554−-- | Wrap an associative list of keys and quoted values in a quoted 'Object'.
555−objectE :: [(String, ExpQ)] -> ExpQ
598+object :: ExpQ -> ExpQ
556−objectE = fromPairsE . mconcatE . fmap (uncurry pairE)
599+object exp = [|E.wrapObject|] `appE` exp
557
600
558−-- | 'mconcat' a list of fixed length.
601+sumToEncoding :: Options -> Bool -> Name -> Q Exp -> Q Exp
559−--
602+sumToEncoding opts multiCons conName exp
560−-- > mconcatE [ [|x|], [|y|], [|z|] ] = [| x <> (y <> z) |]
603+ | multiCons =
561−mconcatE :: [ExpQ] -> ExpQ
604+ let fexp = exp in
562−mconcatE [] = [|Monoid.mempty|]
605+ case sumEncoding opts of
563−mconcatE [x] = x
606+ TwoElemArray ->
564−mconcatE (x : xs) = infixApp x [|(Monoid.<>)|] (mconcatE xs)
607+ array (encStr opts conName <%> fexp)
608+ TaggedObject{tagFieldName, contentsFieldName} ->
609+ object $
610+ ([|E.text (T.pack tagFieldName)|] <:> encStr opts conName) <%>
611+ ([|E.text (T.pack contentsFieldName)|] <:> fexp)
612+ ObjectWithSingleField ->
613+ object (encStr opts conName <:> fexp)
565
614
566−fromPairsE :: ExpQ -> ExpQ
615+ | otherwise = exp
567−fromPairsE = ([|fromPairs|] `appE`)
568
616
569−-- | Create (an encoding of) a key-value pair.
617+nullarySumToEncoding :: Options -> Bool -> Name -> Q Exp
570−--
618+nullarySumToEncoding opts multiCons conName =
571−-- > pairE "k" [|v|] = [|pair "k" v|]
619+ case sumEncoding opts of
572−pairE :: String -> ExpQ -> ExpQ
620+ TaggedObject{tagFieldName} ->
573−pairE k v = [|pair k|] `appE` v
621+ object $
622+ ([|E.text (T.pack tagFieldName)|] <:> encStr opts conName)
623+ _ -> sumToEncoding opts multiCons conName [e|toEncoding ([] :: [()])|]
624+
625+-- | Generates code to generate the JSON encoding of a single constructor.
626+argsToEncoding :: JSONClass -> [(Name, Name)] -> Options -> Bool -> Con -> Q Match
627+-- Nullary constructors. Generates code that explicitly matches against the
628+-- constructor even though it doesn't contain data. This is useful to prevent
629+-- type errors.
630+argsToEncoding jc tes opts multiCons (NormalC conName []) = do
631+ ([], _) <- reifyConTys jc tes conName
632+ match (conP conName [])
633+ (normalB (nullarySumToEncoding opts multiCons conName))
634+ []
635+
636+-- Polyadic constructors with special case for unary constructors.
637+argsToEncoding jc tes opts multiCons (NormalC conName ts) = do
638+ (argTys, tvMap) <- reifyConTys jc tes conName
639+ let len = length ts
640+ args <- newNameList "arg" len
641+ js <- case zip args argTys of
642+ -- Single argument is directly converted.
643+ [(e,eTy)] -> return (dispatchToEncoding jc conName tvMap eTy
644+ `appE` varE e)
645+ -- Multiple arguments are converted to a JSON array.
646+ es ->
647+ return (array (foldr1 (<%>) [ dispatchToEncoding jc conName tvMap xTy
648+ `appE` varE x
649+ | (x,xTy) <- es
650+ ]))
651+ match (conP conName $ map varP args)
652+ (normalB $ sumToEncoding opts multiCons conName js)
653+ []
654+
655+-- Records.
656+argsToEncoding jc tes opts multiCons (RecC conName ts) = case (unwrapUnaryRecords opts, not multiCons, ts) of
657+ (True,True,[(_,st,ty)]) -> argsToEncoding jc tes opts multiCons (NormalC conName [(st,ty)])
658+ _ -> do
659+ args <- newNameList "arg" $ length ts
660+ (argTys, tvMap) <- reifyConTys jc tes conName
661+ let exp = object objBody
662+
663+ objBody = [|mconcat|] `appE`
664+ ([|intersperse E.comma|] `appE` pairs)
665+ pairs | omitNothingFields opts = infixApp maybeFields
666+ [|(<>)|]
667+ restFields
668+ | otherwise = listE (map toPair argCons)
669+
670+ argCons = zip3 args argTys ts
671+
672+ maybeFields = [|catMaybes|] `appE` listE (map maybeToPair maybes)
673+
674+ restFields = listE (map toPair rest)
675+
676+ (maybes, rest) = partition isMaybe argCons
677+
678+ maybeToPair (arg, argTy, (field, _, _)) =
679+ infixApp
680+ (infixApp
681+ (infixE
682+ (Just $ toFieldName field <^> [|E.colon|])
683+ [|(<>)|]
684+ Nothing)
685+ [|(.)|]
686+ (dispatchToEncoding jc conName tvMap argTy))
687+ [|(<$>)|]
688+ (varE arg)
689+
690+ toPair (arg, argTy, (field, _, _)) =
691+ toFieldName field
692+ <:> dispatchToEncoding jc conName tvMap argTy
693+ `appE` varE arg
694+
695+ toFieldName field = [|E.text|] `appE`
696+ ([|T.pack|] `appE` fieldLabelExp opts field)
697+
698+ match (conP conName $ map varP args)
699+ ( normalB
700+ $ if multiCons
701+ then case sumEncoding opts of
702+ TwoElemArray -> array $
703+ encStr opts conName <%> exp
704+ TaggedObject{tagFieldName} -> object $
705+ ([|E.text (T.pack tagFieldName)|] <:>
706+ encStr opts conName) <%>
707+ objBody
708+ ObjectWithSingleField -> object $
709+ encStr opts conName <:> exp
710+ else exp
711+ ) []
712+
713+-- Infix constructors.
714+argsToEncoding jc tes opts multiCons (InfixC _ conName _) = do
715+ al <- newName "argL"
716+ ar <- newName "argR"
717+ ([alTy,arTy], tvMap) <- reifyConTys jc tes conName
718+ match (infixP (varP al) conName (varP ar))
719+ ( normalB
720+ $ sumToEncoding opts multiCons conName
721+ $ array (foldr1 (<%>) [ dispatchToEncoding jc conName tvMap aTy
722+ `appE` varE a
723+ | (a,aTy) <- [(al,alTy), (ar,arTy)]
724+ ])
725+ )
726+ []
727+-- Existentially quantified constructors.
728+argsToEncoding jc tes opts multiCons (ForallC _ _ con) =
729+ argsToEncoding jc tes opts multiCons con
730+
731+#if MIN_VERSION_template_haskell(2,11,0)
732+-- GADTs.
733+argsToEncoding jc tes opts multiCons (GadtC conNames ts _) =
734+ argsToEncoding jc tes opts multiCons $ NormalC (head conNames) ts
735+
736+argsToEncoding jc tes opts multiCons (RecGadtC conNames ts _) =
737+ argsToEncoding jc tes opts multiCons $ RecC (head conNames) ts
738+#endif
574
739
575--------------------------------------------------------------------------------
740--------------------------------------------------------------------------------
576-- FromJSON
741-- FromJSON
@@ -654,41 +819,28 @@ consFromJSON :: JSONClass
654 -- ^ Name of the type to which the constructors belong.
819 -- ^ Name of the type to which the constructors belong.
655 -> Options
820 -> Options
656 -- ^ Encoding options
821 -- ^ Encoding options
657− -> [Type]
822+ -> [Con]
658− -- ^ The types from the data type/data family instance declaration
659− -> [ConstructorInfo]
660 -- ^ Constructors for which to generate JSON parsing code.
823 -- ^ Constructors for which to generate JSON parsing code.
661 -> Q Exp
824 -> Q Exp
662
825
663−consFromJSON _ _ _ _ [] = error $ "Data.Aeson.TH.consFromJSON: "
826+consFromJSON _ _ _ [] = error $ "Data.Aeson.TH.consFromJSON: "
664− ++ "Not a single constructor given!"
827+ ++ "Not a single constructor given!"
665
828
666−consFromJSON jc tName opts instTys cons = do
829+consFromJSON jc tName opts cons = do
667 value <- newName "value"
830 value <- newName "value"
668 pjs <- newNameList "_pj" $ arityInt jc
831 pjs <- newNameList "_pj" $ arityInt jc
669 pjls <- newNameList "_pjl" $ arityInt jc
832 pjls <- newNameList "_pjl" $ arityInt jc
670 let zippedPJs = zip pjs pjls
833 let zippedPJs = zip pjs pjls
671 interleavedPJs = interleave pjs pjls
834 interleavedPJs = interleave pjs pjls
672− lastTyVars = map varTToName $ drop (length instTys - arityInt jc) instTys
673− tvMap = M.fromList $ zip lastTyVars zippedPJs
674− lamE (map varP $ interleavedPJs ++ [value]) $ lamExpr value tvMap
835+ lamE (map varP $ interleavedPJs ++ [value]) $ lamExpr value zippedPJs
675
836
676 where
837 where
677− checkExi tvMap con = checkExistentialContext jc tvMap
678− (constructorContext con)
679− (constructorName con)
680−
681− lamExpr value tvMap = case cons of
838+ lamExpr value pjs = case cons of
682− [con]
683− | not (tagSingleConstructors opts)
684− -> checkExi tvMap con $ parseArgs jc tvMap tName opts con (Right value)
839+ [con] -> parseArgs jc pjs tName opts con (Right value)
685− _ | sumEncoding opts == UntaggedValue
686− -> parseUntaggedValue tvMap cons value
687− | otherwise
688− -> caseE (varE value) $
840+ _ -> caseE (varE value) $
689 if allNullaryToStringTag opts && all isNullary cons
841 if allNullaryToStringTag opts && all isNullary cons
690 then allNullaryMatches
842 then allNullaryMatches
691− else mixedMatches tvMap
843+ else mixedMatches pjs
692
844
693 allNullaryMatches =
845 allNullaryMatches =
694 [ do txt <- newName "txt"
846 [ do txt <- newName "txt"
@@ -697,17 +849,18 @@ consFromJSON jc tName opts instTys cons = do
697 [ liftM2 (,) (normalG $
849 [ liftM2 (,) (normalG $
698 infixApp (varE txt)
850 infixApp (varE txt)
699 [|(==)|]
851 [|(==)|]
852+ ([|T.pack|] `appE`
700− (conTxt opts conName)
853+ conStringE opts conName)
701 )
854 )
702 ([|pure|] `appE` conE conName)
855 ([|pure|] `appE` conE conName)
703 | con <- cons
856 | con <- cons
704− , let conName = constructorName con
857+ , let conName = getConName con
705 ]
858 ]
706 ++
859 ++
707 [ liftM2 (,)
860 [ liftM2 (,)
708 (normalG [|otherwise|])
861 (normalG [|otherwise|])
709 ( [|noMatchFail|]
862 ( [|noMatchFail|]
710− `appE` litE (stringL $ show tName)
863+ `appE` (litE $ stringL $ show tName)
711 `appE` ([|T.unpack|] `appE` varE txt)
864 `appE` ([|T.unpack|] `appE` varE txt)
712 )
865 )
713 ]
866 ]
@@ -716,31 +869,30 @@ consFromJSON jc tName opts instTys cons = do
716 , do other <- newName "other"
869 , do other <- newName "other"
717 match (varP other)
870 match (varP other)
718 (normalB $ [|noStringFail|]
871 (normalB $ [|noStringFail|]
719− `appE` litE (stringL $ show tName)
872+ `appE` (litE $ stringL $ show tName)
720 `appE` ([|valueConName|] `appE` varE other)
873 `appE` ([|valueConName|] `appE` varE other)
721 )
874 )
722 []
875 []
723 ]
876 ]
724
877
725− mixedMatches tvMap =
878+ mixedMatches pjs =
726 case sumEncoding opts of
879 case sumEncoding opts of
727 TaggedObject {tagFieldName, contentsFieldName} ->
880 TaggedObject {tagFieldName, contentsFieldName} ->
728− parseObject $ parseTaggedObject tvMap tagFieldName contentsFieldName
881+ parseObject $ parseTaggedObject pjs tagFieldName contentsFieldName
729− UntaggedValue -> error "UntaggedValue: Should be handled already"
730 ObjectWithSingleField ->
882 ObjectWithSingleField ->
731− parseObject $ parseObjectWithSingleField tvMap
883+ parseObject $ parseObjectWithSingleField pjs
732 TwoElemArray ->
884 TwoElemArray ->
733 [ do arr <- newName "array"
885 [ do arr <- newName "array"
734 match (conP 'Array [varP arr])
886 match (conP 'Array [varP arr])
735− (guardedB
887+ (guardedB $
736 [ liftM2 (,) (normalG $ infixApp ([|V.length|] `appE` varE arr)
888 [ liftM2 (,) (normalG $ infixApp ([|V.length|] `appE` varE arr)
737 [|(==)|]
889 [|(==)|]
738 (litE $ integerL 2))
890 (litE $ integerL 2))
739− (parse2ElemArray tvMap arr)
891+ (parse2ElemArray pjs arr)
740 , liftM2 (,) (normalG [|otherwise|])
892 , liftM2 (,) (normalG [|otherwise|])
741− ([|not2ElemArray|]
893+ (([|not2ElemArray|]
742− `appE` litE (stringL $ show tName)
894+ `appE` (litE $ stringL $ show tName)
743− `appE` ([|V.length|] `appE` varE arr))
895+ `appE` ([|V.length|] `appE` varE arr)))
744 ]
896 ]
745 )
897 )
746 []
898 []
@@ -748,7 +900,7 @@ consFromJSON jc tName opts instTys cons = do
748 match (varP other)
900 match (varP other)
749 ( normalB
901 ( normalB
750 $ [|noArrayFail|]
902 $ [|noArrayFail|]
751− `appE` litE (stringL $ show tName)
903+ `appE` (litE $ stringL $ show tName)
752 `appE` ([|valueConName|] `appE` varE other)
904 `appE` ([|valueConName|] `appE` varE other)
753 )
905 )
754 []
906 []
@@ -761,47 +913,22 @@ consFromJSON jc tName opts instTys cons = do
761 match (varP other)
913 match (varP other)
762 ( normalB
914 ( normalB
763 $ [|noObjectFail|]
915 $ [|noObjectFail|]
764− `appE` litE (stringL $ show tName)
916+ `appE` (litE $ stringL $ show tName)
765 `appE` ([|valueConName|] `appE` varE other)
917 `appE` ([|valueConName|] `appE` varE other)
766 )
918 )
767 []
919 []
768 ]
920 ]
769
921
770− parseTaggedObject tvMap typFieldName valFieldName obj = do
922+ parseTaggedObject pjs typFieldName valFieldName obj = do
771 conKey <- newName "conKey"
923 conKey <- newName "conKey"
772 doE [ bindS (varP conKey)
924 doE [ bindS (varP conKey)
773 (infixApp (varE obj)
925 (infixApp (varE obj)
774 [|(.:)|]
926 [|(.:)|]
775 ([|T.pack|] `appE` stringE typFieldName))
927 ([|T.pack|] `appE` stringE typFieldName))
776− , noBindS $ parseContents tvMap conKey (Left (valFieldName, obj)) 'conNotFoundFailTaggedObject
928+ , noBindS $ parseContents pjs conKey (Left (valFieldName, obj)) 'conNotFoundFailTaggedObject
777 ]
929 ]
778
930
779− parseUntaggedValue tvMap cons' conVal =
780− foldr1 (\e e' -> infixApp e [|(<|>)|] e')
781− (map (\x -> parseValue tvMap x conVal) cons')
782−
783− parseValue _tvMap
784− ConstructorInfo { constructorName = conName
785− , constructorVariant = NormalConstructor
786− , constructorFields = [] }
787− conVal = do
788− str <- newName "str"
789− caseE (varE conVal)
790− [ match (conP 'String [varP str])
791− (guardedB
792− [ liftM2 (,) (normalG $ infixApp (varE str) [|(==)|] (conTxt opts conName)
793− )
794− ([|pure|] `appE` conE conName)
795− ]
796− )
797− []
798− , matchFailed tName conName "String"
799− ]
800− parseValue tvMap con conVal =
801− checkExi tvMap con $ parseArgs jc tvMap tName opts con (Right conVal)
802−
803−
804− parse2ElemArray tvMap arr = do
931+ parse2ElemArray pjs arr = do
805 conKey <- newName "conKey"
932 conKey <- newName "conKey"
806 conVal <- newName "conVal"
933 conVal <- newName "conVal"
807 let letIx n ix =
934 let letIx n ix =
@@ -816,7 +943,7 @@ consFromJSON jc tName opts instTys cons = do
816 (caseE (varE conKey)
943 (caseE (varE conKey)
817 [ do txt <- newName "txt"
944 [ do txt <- newName "txt"
818 match (conP 'String [varP txt])
945 match (conP 'String [varP txt])
819− (normalB $ parseContents tvMap
946+ (normalB $ parseContents pjs
820 txt
947 txt
821 (Right conVal)
948 (Right conVal)
822 'conNotFoundFail2ElemArray
949 'conNotFoundFail2ElemArray
@@ -826,30 +953,30 @@ consFromJSON jc tName opts instTys cons = do
826 match (varP other)
953 match (varP other)
827 ( normalB
954 ( normalB
828 $ [|firstElemNoStringFail|]
955 $ [|firstElemNoStringFail|]
829− `appE` litE (stringL $ show tName)
956+ `appE` (litE $ stringL $ show tName)
830 `appE` ([|valueConName|] `appE` varE other)
957 `appE` ([|valueConName|] `appE` varE other)
831 )
958 )
832 []
959 []
833 ]
960 ]
834 )
961 )
835
962
836− parseObjectWithSingleField tvMap obj = do
963+ parseObjectWithSingleField pjs obj = do
837 conKey <- newName "conKey"
964 conKey <- newName "conKey"
838 conVal <- newName "conVal"
965 conVal <- newName "conVal"
839 caseE ([e|H.toList|] `appE` varE obj)
966 caseE ([e|H.toList|] `appE` varE obj)
840 [ match (listP [tupP [varP conKey, varP conVal]])
967 [ match (listP [tupP [varP conKey, varP conVal]])
841− (normalB $ parseContents tvMap conKey (Right conVal) 'conNotFoundFailObjectSingleField)
968+ (normalB $ parseContents pjs conKey (Right conVal) 'conNotFoundFailObjectSingleField)
842 []
969 []
843 , do other <- newName "other"
970 , do other <- newName "other"
844 match (varP other)
971 match (varP other)
845 (normalB $ [|wrongPairCountFail|]
972 (normalB $ [|wrongPairCountFail|]
846− `appE` litE (stringL $ show tName)
973+ `appE` (litE $ stringL $ show tName)
847 `appE` ([|show . length|] `appE` varE other)
974 `appE` ([|show . length|] `appE` varE other)
848 )
975 )
849 []
976 []
850 ]
977 ]
851
978
852− parseContents tvMap conKey contents errorFun =
979+ parseContents pjs conKey contents errorFun =
853 caseE (varE conKey)
980 caseE (varE conKey)
854 [ match wildP
981 [ match wildP
855 ( guardedB $
982 ( guardedB $
@@ -857,8 +984,7 @@ consFromJSON jc tName opts instTys cons = do
857 [|(==)|]
984 [|(==)|]
858 ([|T.pack|] `appE`
985 ([|T.pack|] `appE`
859 conNameExp opts con)
986 conNameExp opts con)
860− e <- checkExi tvMap con $
861− parseArgs jc tvMap tName opts con contents
987+ e <- parseArgs jc pjs tName opts con contents
862 return (g, e)
988 return (g, e)
863 | con <- cons
989 | con <- cons
864 ]
990 ]
@@ -866,12 +992,12 @@ consFromJSON jc tName opts instTys cons = do
866 [ liftM2 (,)
992 [ liftM2 (,)
867 (normalG [e|otherwise|])
993 (normalG [e|otherwise|])
868 ( varE errorFun
994 ( varE errorFun
869− `appE` litE (stringL $ show tName)
995+ `appE` (litE $ stringL $ show tName)
870 `appE` listE (map ( litE
996 `appE` listE (map ( litE
871 . stringL
997 . stringL
872 . constructorTagModifier opts
998 . constructorTagModifier opts
873 . nameBase
999 . nameBase
874− . constructorName
1000+ . getConName
875 ) cons
1001 ) cons
876 )
1002 )
877 `appE` ([|T.unpack|] `appE` varE conKey)
1003 `appE` ([|T.unpack|] `appE` varE conKey)
@@ -885,13 +1011,13 @@ parseNullaryMatches :: Name -> Name -> [Q Match]
885parseNullaryMatches tName conName =
1011parseNullaryMatches tName conName =
886 [ do arr <- newName "arr"
1012 [ do arr <- newName "arr"
887 match (conP 'Array [varP arr])
1013 match (conP 'Array [varP arr])
888− (guardedB
1014+ (guardedB $
889 [ liftM2 (,) (normalG $ [|V.null|] `appE` varE arr)
1015 [ liftM2 (,) (normalG $ [|V.null|] `appE` varE arr)
890 ([|pure|] `appE` conE conName)
1016 ([|pure|] `appE` conE conName)
891 , liftM2 (,) (normalG [|otherwise|])
1017 , liftM2 (,) (normalG [|otherwise|])
892 (parseTypeMismatch tName conName
1018 (parseTypeMismatch tName conName
893 (litE $ stringL "an empty Array")
1019 (litE $ stringL "an empty Array")
894− (infixApp (litE $ stringL "Array of length ")
1020+ (infixApp (litE $ stringL $ "Array of length ")
895 [|(++)|]
1021 [|(++)|]
896 ([|show . V.length|] `appE` varE arr)
1022 ([|show . V.length|] `appE` varE arr)
897 )
1023 )
@@ -920,42 +1046,22 @@ parseRecord :: JSONClass
920 -> Options
1046 -> Options
921 -> Name
1047 -> Name
922 -> Name
1048 -> Name
923− -> [Name]
1049+ -> [VarStrictType]
924 -> Name
1050 -> Name
925− -> Bool
926 -> ExpQ
1051 -> ExpQ
927−parseRecord jc tvMap argTys opts tName conName fields obj inTaggedObject =
1052+parseRecord jc tvMap argTys opts tName conName ts obj =
928− (if rejectUnknownFields opts
929− then infixApp checkUnknownRecords [|(>>)|]
930− else id) $
931 foldl' (\a b -> infixApp a [|(<*>)|] b)
1053 foldl' (\a b -> infixApp a [|(<*>)|] b)
932 (infixApp (conE conName) [|(<$>)|] x)
1054 (infixApp (conE conName) [|(<$>)|] x)
933 xs
1055 xs
934 where
1056 where
935− tagFieldNameAppender =
936− if inTaggedObject then (tagFieldName (sumEncoding opts) :) else id
937− knownFields = appE [|H.fromList|] $ listE $
938− map (\knownName -> tupE [appE [|T.pack|] $ litE $ stringL knownName, [|()|]]) $
939− tagFieldNameAppender $ map nameBase fields
940− checkUnknownRecords =
941− caseE (appE [|H.keys|] $ infixApp (varE obj) [|H.difference|] knownFields)
942− [ match (listP []) (normalB [|return ()|]) []
943− , newName "unknownFields" >>=
944− \unknownFields -> match (varP unknownFields)
945− (normalB $ appE [|fail|] $ infixApp
946− (litE (stringL "Unknown fields: "))
947− [|(++)|]
948− (appE [|show|] (varE unknownFields)))
949− []
950− ]
951 x:xs = [ [|lookupField|]
1057 x:xs = [ [|lookupField|]
952 `appE` dispatchParseJSON jc conName tvMap argTy
1058 `appE` dispatchParseJSON jc conName tvMap argTy
953− `appE` litE (stringL $ show tName)
1059+ `appE` (litE $ stringL $ show tName)
954− `appE` litE (stringL $ constructorTagModifier opts $ nameBase conName)
1060+ `appE` (litE $ stringL $ constructorTagModifier opts $ nameBase conName)
955− `appE` varE obj
1061+ `appE` (varE obj)
956− `appE` ( [|T.pack|] `appE` stringE (fieldLabel opts field)
1062+ `appE` ( [|T.pack|] `appE` fieldLabelExp opts field
957 )
1063 )
958− | (field, argTy) <- zip fields argTys
1064+ | ((field, _, _), argTy) <- zip ts argTys
959 ]
1065 ]
960
1066
961getValField :: Name -> String -> [MatchQ] -> Q Exp
1067getValField :: Name -> String -> [MatchQ] -> Q Exp
@@ -964,7 +1070,7 @@ getValField obj valFieldName matches = do
964 doE [ bindS (varP val) $ infixApp (varE obj)
1070 doE [ bindS (varP val) $ infixApp (varE obj)
965 [|(.:)|]
1071 [|(.:)|]
966 ([|T.pack|] `appE`
1072 ([|T.pack|] `appE`
967− litE (stringL valFieldName))
1073+ (litE $ stringL valFieldName))
968 , noBindS $ caseE (varE val) matches
1074 , noBindS $ caseE (varE val) matches
969 ]
1075 ]
970
1076
@@ -974,82 +1080,67 @@ matchCases (Right valName) = caseE (varE valName)
974
1080
975-- | Generates code to parse the JSON encoding of a single constructor.
1081-- | Generates code to parse the JSON encoding of a single constructor.
976parseArgs :: JSONClass -- ^ The FromJSON variant being derived.
1082parseArgs :: JSONClass -- ^ The FromJSON variant being derived.
977− -> TyVarMap -- ^ Maps the last type variables to their decoding
978− -- function arguments.
1083+ -> [(Name, Name)] -- ^ The names of the encoding/decoding function arguments.
979 -> Name -- ^ Name of the type to which the constructor belongs.
1084 -> Name -- ^ Name of the type to which the constructor belongs.
980 -> Options -- ^ Encoding options.
1085 -> Options -- ^ Encoding options.
981− -> ConstructorInfo -- ^ Constructor for which to generate JSON parsing code.
1086+ -> Con -- ^ Constructor for which to generate JSON parsing code.
982 -> Either (String, Name) Name -- ^ Left (valFieldName, objName) or
1087 -> Either (String, Name) Name -- ^ Left (valFieldName, objName) or
983 -- Right valName
1088 -- Right valName
984 -> Q Exp
1089 -> Q Exp
985-- Nullary constructors.
1090-- Nullary constructors.
986−parseArgs _ _ _ _
1091+parseArgs jc pjs _ _ (NormalC conName []) (Left _) = do
987− ConstructorInfo { constructorName = conName
1092+ ([], _) <- reifyConTys jc pjs conName
988− , constructorVariant = NormalConstructor
989− , constructorFields = [] }
990− (Left _) =
991− [|pure|] `appE` conE conName
1093+ [|pure|] `appE` conE conName
992−parseArgs _ _ tName _
1094+parseArgs jc pjs tName _ (NormalC conName []) (Right valName) = do
993− ConstructorInfo { constructorName = conName
1095+ ([], _) <- reifyConTys jc pjs conName
994− , constructorVariant = NormalConstructor
995− , constructorFields = [] }
996− (Right valName) =
997− caseE (varE valName) $ parseNullaryMatches tName conName
1096+ caseE (varE valName) $ parseNullaryMatches tName conName
998
1097
999-- Unary constructors.
1098-- Unary constructors.
1000−parseArgs jc tvMap _ _
1099+parseArgs jc pjs _ _ (NormalC conName [_]) contents = do
1001− ConstructorInfo { constructorName = conName
1100+ ([argTy], tvMap) <- reifyConTys jc pjs conName
1002− , constructorVariant = NormalConstructor
1003− , constructorFields = [argTy] }
1004− contents = do
1005− argTy' <- resolveTypeSynonyms argTy
1006− matchCases contents $ parseUnaryMatches jc tvMap argTy' conName
1101+ matchCases contents $ parseUnaryMatches jc tvMap argTy conName
1007
1102
1008-- Polyadic constructors.
1103-- Polyadic constructors.
1009−parseArgs jc tvMap tName _
1104+parseArgs jc pjs tName _ (NormalC conName ts) contents = do
1010− ConstructorInfo { constructorName = conName
1105+ (argTys, tvMap) <- reifyConTys jc pjs conName
1011− , constructorVariant = NormalConstructor
1012− , constructorFields = argTys }
1013− contents = do
1014− argTys' <- mapM resolveTypeSynonyms argTys
1015− let len = genericLength argTys'
1106+ let len = genericLength ts
1016− matchCases contents $ parseProduct jc tvMap argTys' tName conName len
1107+ matchCases contents $ parseProduct jc tvMap argTys tName conName len
1017
1108
1018-- Records.
1109-- Records.
1019−parseArgs jc tvMap tName opts
1110+parseArgs jc pjs tName opts (RecC conName ts) (Left (_, obj)) = do
1020− ConstructorInfo { constructorName = conName
1111+ (argTys, tvMap) <- reifyConTys jc pjs conName
1021− , constructorVariant = RecordConstructor fields
1022− , constructorFields = argTys }
1023− (Left (_, obj)) = do
1024− argTys' <- mapM resolveTypeSynonyms argTys
1025− parseRecord jc tvMap argTys' opts tName conName fields obj True
1112+ parseRecord jc tvMap argTys opts tName conName ts obj
1026−parseArgs jc tvMap tName opts
1027− info@ConstructorInfo { constructorName = conName
1028− , constructorVariant = RecordConstructor fields
1029− , constructorFields = argTys }
1030− (Right valName) =
1031− case (unwrapUnaryRecords opts,argTys) of
1113+parseArgs jc pjs tName opts (RecC conName ts) (Right valName) = case (unwrapUnaryRecords opts,ts) of
1032− (True,[_])-> parseArgs jc tvMap tName opts
1114+ (True,[(_,st,ty)])-> parseArgs jc pjs tName opts (NormalC conName [(st,ty)]) (Right valName)
1033− (info{constructorVariant = NormalConstructor})
1034− (Right valName)
1035− _ -> do
1115+ _ -> do
1036− obj <- newName "recObj"
1116+ obj <- newName "recObj"
1037− argTys' <- mapM resolveTypeSynonyms argTys
1117+ (argTys, tvMap) <- reifyConTys jc pjs conName
1038− caseE (varE valName)
1118+ caseE (varE valName)
1039− [ match (conP 'Object [varP obj]) (normalB $
1119+ [ match (conP 'Object [varP obj]) (normalB $
1040− parseRecord jc tvMap argTys' opts tName conName fields obj False) []
1120+ parseRecord jc tvMap argTys opts tName conName ts obj) []
1041− , matchFailed tName conName "Object"
1121+ , matchFailed tName conName "Object"
1042− ]
1122+ ]
1043
1123
1044-- Infix constructors. Apart from syntax these are the same as
1124-- Infix constructors. Apart from syntax these are the same as
1045-- polyadic constructors.
1125-- polyadic constructors.
1046−parseArgs jc tvMap tName _
1126+parseArgs jc pjs tName _ (InfixC _ conName _) contents = do
1047− ConstructorInfo { constructorName = conName
1127+ (argTys, tvMap) <- reifyConTys jc pjs conName
1048− , constructorVariant = InfixConstructor
1049− , constructorFields = argTys }
1050− contents = do
1051− argTys' <- mapM resolveTypeSynonyms argTys
1052− matchCases contents $ parseProduct jc tvMap argTys' tName conName 2
1128+ matchCases contents $ parseProduct jc tvMap argTys tName conName 2
1129+
1130+-- Existentially quantified constructors. We ignore the quantifiers
1131+-- and proceed with the contained constructor.
1132+parseArgs jc pjs tName opts (ForallC _ _ con) contents =
1133+ parseArgs jc pjs tName opts con contents
1134+
1135+#if MIN_VERSION_template_haskell(2,11,0)
1136+-- GADTs. We ignore the refined return type and proceed as if it were a
1137+-- NormalC or RecC.
1138+parseArgs jc pjs tName opts (GadtC conNames ts _) contents =
1139+ parseArgs jc pjs tName opts (NormalC (head conNames) ts) contents
1140+
1141+parseArgs jc pjs tName opts (RecGadtC conNames ts _) contents =
1142+ parseArgs jc pjs tName opts (RecC (head conNames) ts) contents
1143+#endif
1053
1144
1054-- | Generates code to parse the JSON encoding of an n-ary
1145-- | Generates code to parse the JSON encoding of an n-ary
1055-- constructor.
1146-- constructor.
@@ -1082,7 +1173,7 @@ parseProduct jc tvMap argTys tName conName numArgs =
1082 )
1173 )
1083 ( parseTypeMismatch tName conName
1174 ( parseTypeMismatch tName conName
1084 (litE $ stringL $ "Array of length " ++ show numArgs)
1175 (litE $ stringL $ "Array of length " ++ show numArgs)
1085− ( infixApp (litE $ stringL "Array of length ")
1176+ ( infixApp (litE $ stringL $ "Array of length ")
1086 [|(++)|]
1177 [|(++)|]
1087 ([|show . V.length|] `appE` varE arr)
1178 ([|show . V.length|] `appE` varE arr)
1088 )
1179 )
@@ -1123,14 +1214,9 @@ class LookupField a where
1123instance OVERLAPPABLE_ LookupField a where
1214instance OVERLAPPABLE_ LookupField a where
1124 lookupField = lookupFieldWith
1215 lookupField = lookupFieldWith
1125
1216
1126−instance INCOHERENT_ LookupField (Maybe a) where
1217+instance LookupField (Maybe a) where
1127 lookupField pj _ _ = parseOptionalFieldWith pj
1218 lookupField pj _ _ = parseOptionalFieldWith pj
1128
1219
1129−instance INCOHERENT_ LookupField (Semigroup.Option a) where
1130− lookupField pj tName rec obj key =
1131− fmap Semigroup.Option
1132− (lookupField (fmap Semigroup.getOption . pj) tName rec obj key)
1133−
1134lookupFieldWith :: (Value -> Parser a) -> String -> String
1220lookupFieldWith :: (Value -> Parser a) -> String -> String
1135 -> Object -> T.Text -> Parser a
1221 -> Object -> T.Text -> Parser a
1136lookupFieldWith pj tName rec obj key =
1222lookupFieldWith pj tName rec obj key =
@@ -1138,6 +1224,9 @@ lookupFieldWith pj tName rec obj key =
1138 Nothing -> unknownFieldFail tName rec (T.unpack key)
1224 Nothing -> unknownFieldFail tName rec (T.unpack key)
1139 Just v -> pj v <?> Key key
1225 Just v -> pj v <?> Key key
1140
1226
1227+keyValuePairWith :: (v -> Value) -> T.Text -> v -> Pair
1228+keyValuePairWith tj name value = (name, tj value)
1229+
1141unknownFieldFail :: String -> String -> String -> Parser fail
1230unknownFieldFail :: String -> String -> String -> Parser fail
1142unknownFieldFail tName rec key =
1231unknownFieldFail tName rec key =
1143 fail $ printf "When parsing the record %s of type %s the key %s was not present."
1232 fail $ printf "When parsing the record %s of type %s the key %s was not present."
@@ -1206,8 +1295,7 @@ deriveJSONBoth dtj dfj opts name =
1206 liftM2 (++) (dtj opts name) (dfj opts name)
1295 liftM2 (++) (dtj opts name) (dfj opts name)
1207
1296
1208-- | Functionality common to @deriveToJSON(1)(2)@ and @deriveFromJSON(1)(2)@.
1297-- | Functionality common to @deriveToJSON(1)(2)@ and @deriveFromJSON(1)(2)@.
1209−deriveJSONClass :: [(JSONFun, JSONClass -> Name -> Options -> [Type]
1298+deriveJSONClass :: [(JSONFun, JSONClass -> Name -> Options -> [Con] -> Q Exp)]
1210− -> [ConstructorInfo] -> Q Exp)]
1211 -- ^ The class methods and the functions which derive them.
1299 -- ^ The class methods and the functions which derive them.
1212 -> JSONClass
1300 -> JSONClass
1213 -- ^ The class for which to generate an instance.
1301 -- ^ The class for which to generate an instance.
@@ -1217,34 +1305,27 @@ deriveJSONClass :: [(JSONFun, JSONClass -> Name -> Options -> [Type]
1217 -- ^ Name of the type for which to generate a class instance
1305 -- ^ Name of the type for which to generate a class instance
1218 -- declaration.
1306 -- declaration.
1219 -> Q [Dec]
1307 -> Q [Dec]
1220−deriveJSONClass consFuns jc opts name = do
1308+deriveJSONClass consFuns jc opts name =
1221− info <- reifyDatatype name
1309+ withType name $ \name' ctxt tvbs cons mbTys ->
1222− case info of
1310+ fmap (:[]) $ fromCons name' ctxt tvbs cons mbTys
1223− DatatypeInfo { datatypeContext = ctxt
1224− , datatypeName = parentName
1225−#if MIN_VERSION_th_abstraction(0,3,0)
1226− , datatypeInstTypes = instTys
1227−#else
1228− , datatypeVars = instTys
1229−#endif
1230− , datatypeVariant = variant
1231− , datatypeCons = cons
1232− } -> do
1233− (instanceCxt, instanceType)
1234− <- buildTypeInstance parentName jc ctxt instTys variant
1235− (:[]) <$> instanceD (return instanceCxt)
1236− (return instanceType)
1237− (methodDecs parentName instTys cons)
1238 where
1311 where
1239− methodDecs :: Name -> [Type] -> [ConstructorInfo] -> [Q Dec]
1312+ fromCons :: Name -> Cxt -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q Dec
1313+ fromCons name' ctxt tvbs cons mbTys = do
1314+ (instanceCxt, instanceType)
1315+ <- buildTypeInstance name' jc ctxt tvbs mbTys
1316+ instanceD (return instanceCxt)
1317+ (return instanceType)
1318+ (methodDecs name' cons)
1319+
1320+ methodDecs :: Name -> [Con] -> [Q Dec]
1240− methodDecs parentName instTys cons = flip map consFuns $ \(jf, jfMaker) ->
1321+ methodDecs name' cons = flip map consFuns $ \(jf, jfMaker) ->
1241 funD (jsonFunValName jf (arity jc))
1322 funD (jsonFunValName jf (arity jc))
1242 [ clause []
1323 [ clause []
1243− (normalB $ jfMaker jc parentName opts instTys cons)
1324+ (normalB $ jfMaker jc name' opts cons)
1244 []
1325 []
1245 ]
1326 ]
1246
1327
1247−mkFunCommon :: (JSONClass -> Name -> Options -> [Type] -> [ConstructorInfo] -> Q Exp)
1328+mkFunCommon :: (JSONClass -> Name -> Options -> [Con] -> Q Exp)
1248 -- ^ The function which derives the expression.
1329 -- ^ The function which derives the expression.
1249 -> JSONClass
1330 -> JSONClass
1250 -- ^ Which class's method is being derived.
1331 -- ^ Which class's method is being derived.
@@ -1253,24 +1334,15 @@ mkFunCommon :: (JSONClass -> Name -> Options -> [Type] -> [ConstructorInfo] -> Q
1253 -> Name
1334 -> Name
1254 -- ^ Name of the encoded type.
1335 -- ^ Name of the encoded type.
1255 -> Q Exp
1336 -> Q Exp
1256−mkFunCommon consFun jc opts name = do
1337+mkFunCommon consFun jc opts name = withType name fromCons
1257− info <- reifyDatatype name
1338+ where
1258− case info of
1339+ fromCons :: Name -> Cxt -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q Exp
1259− DatatypeInfo { datatypeContext = ctxt
1340+ fromCons name' ctxt tvbs cons mbTys = do
1260− , datatypeName = parentName
1261−#if MIN_VERSION_th_abstraction(0,3,0)
1262− , datatypeInstTypes = instTys
1263−#else
1264− , datatypeVars = instTys
1265−#endif
1266− , datatypeVariant = variant
1267− , datatypeCons = cons
1268− } -> do
1269− -- We force buildTypeInstance here since it performs some checks for whether
1341+ -- We force buildTypeInstance here since it performs some checks for whether
1270− -- or not the provided datatype's kind matches the derived method's
1342+ -- or not the provided datatype's kind matches the derived method's
1271− -- typeclass, and produces errors if it can't.
1343+ -- typeclass, and produces errors if it can't.
1272− !_ <- buildTypeInstance parentName jc ctxt instTys variant
1344+ !_ <- buildTypeInstance name' jc ctxt tvbs mbTys
1273− consFun jc parentName opts instTys cons
1345+ consFun jc name' opts cons
1274
1346
1275dispatchFunByType :: JSONClass
1347dispatchFunByType :: JSONClass
1276 -> JSONFun
1348 -> JSONFun
@@ -1308,44 +1380,205 @@ dispatchFunByType jc jf conName tvMap list ty = do
1308 if any (`mentionsName` tyVarNames) lhsArgs
1380 if any (`mentionsName` tyVarNames) lhsArgs
1309 || itf && any (`mentionsName` tyVarNames) tyArgs
1381 || itf && any (`mentionsName` tyVarNames) tyArgs
1310 then outOfPlaceTyVarError jc conName
1382 then outOfPlaceTyVarError jc conName
1311− else if any (`mentionsName` tyVarNames) rhsArgs
1312− then appsE $ varE (jsonFunValOrListName list jf $ toEnum numLastArgs)
1383+ else appsE $ [ varE . jsonFunValOrListName list jf $ toEnum numLastArgs]
1313− : zipWith (dispatchFunByType jc jf conName tvMap)
1384+ ++ zipWith (dispatchFunByType jc jf conName tvMap)
1314− (cycle [False,True])
1385+ (cycle [False,True])
1315− (interleave rhsArgs rhsArgs)
1386+ (interleave rhsArgs rhsArgs)
1316− else varE $ jsonFunValOrListName list jf Arity0
1387+
1317−
1318−dispatchToJSON
1319− :: ToJSONFun -> JSONClass -> Name -> TyVarMap -> Type -> Q Exp
1320−dispatchToJSON target jc n tvMap =
1321− dispatchFunByType jc (targetToJSONFun target) n tvMap False
1322−
1323−dispatchParseJSON
1388+dispatchToJSON, dispatchToEncoding, dispatchParseJSON
1324 :: JSONClass -> Name -> TyVarMap -> Type -> Q Exp
1389 :: JSONClass -> Name -> TyVarMap -> Type -> Q Exp
1390+dispatchToJSON jc n tvMap = dispatchFunByType jc ToJSON n tvMap False
1391+dispatchToEncoding jc n tvMap = dispatchFunByType jc ToEncoding n tvMap False
1325dispatchParseJSON jc n tvMap = dispatchFunByType jc ParseJSON n tvMap False
1392dispatchParseJSON jc n tvMap = dispatchFunByType jc ParseJSON n tvMap False
1326
1393
1327--------------------------------------------------------------------------------
1394--------------------------------------------------------------------------------
1328-- Utility functions
1395-- Utility functions
1329--------------------------------------------------------------------------------
1396--------------------------------------------------------------------------------
1330
1397
1331−-- For the given Types, generate an instance context and head.
1398+-- | Boilerplate for top level splices.
1399+--
1400+-- The given 'Name' must meet one of two criteria:
1401+--
1402+-- 1. It must be the name of a type constructor of a plain data type or newtype.
1403+-- 2. It must be the name of a data family instance or newtype instance constructor.
1404+
1405+-- Any other value will result in an exception.
1406+withType :: Name
1407+ -> (Name -> Cxt -> [TyVarBndr] -> [Con] -> Maybe [Type] -> Q a)
1408+ -- ^ Function that generates the actual code. Will be applied
1409+ -- to the datatype/data family 'Name', datatype context, type
1410+ -- variable binders and constructors extracted from the given
1411+ -- 'Name'. If the 'Name' is from a data family instance
1412+ -- constructor, it will also have its instantiated types;
1413+ -- otherwise, it will be 'Nothing'.
1414+ -> Q a
1415+ -- ^ Resulting value in the 'Q'uasi monad.
1416+withType name f = do
1417+ info <- reify name
1418+ case info of
1419+ TyConI dec ->
1420+ case dec of
1421+#if MIN_VERSION_template_haskell(2,11,0)
1422+ DataD ctxt _ tvbs _ cons _ -> f name ctxt tvbs cons Nothing
1423+ NewtypeD ctxt _ tvbs _ con _ -> f name ctxt tvbs [con] Nothing
1424+#else
1425+ DataD ctxt _ tvbs cons _ -> f name ctxt tvbs cons Nothing
1426+ NewtypeD ctxt _ tvbs con _ -> f name ctxt tvbs [con] Nothing
1427+#endif
1428+ other -> fail $ ns ++ "Unsupported type: " ++ show other
1429+#if MIN_VERSION_template_haskell(2,11,0)
1430+ DataConI _ _ parentName -> do
1431+#else
1432+ DataConI _ _ parentName _ -> do
1433+#endif
1434+ parentInfo <- reify parentName
1435+ case parentInfo of
1436+#if MIN_VERSION_template_haskell(2,11,0)
1437+ FamilyI (DataFamilyD _ tvbs _) decs ->
1438+#else
1439+ FamilyI (FamilyD DataFam _ tvbs _) decs ->
1440+#endif
1441+ let instDec = flip find decs $ \dec -> case dec of
1442+#if MIN_VERSION_template_haskell(2,11,0)
1443+ DataInstD _ _ _ _ cons _ -> any ((name ==) . getConName) cons
1444+ NewtypeInstD _ _ _ _ con _ -> name == getConName con
1445+#else
1446+ DataInstD _ _ _ cons _ -> any ((name ==) . getConName) cons
1447+ NewtypeInstD _ _ _ con _ -> name == getConName con
1448+#endif
1449+ _ -> error $ ns ++ "Must be a data or newtype instance."
1450+ in case instDec of
1451+#if MIN_VERSION_template_haskell(2,11,0)
1452+ Just (DataInstD ctxt _ instTys _ cons _) -> f parentName ctxt tvbs cons $ Just instTys
1453+ Just (NewtypeInstD ctxt _ instTys _ con _) -> f parentName ctxt tvbs [con] $ Just instTys
1454+#else
1455+ Just (DataInstD ctxt _ instTys cons _) -> f parentName ctxt tvbs cons $ Just instTys
1456+ Just (NewtypeInstD ctxt _ instTys con _) -> f parentName ctxt tvbs [con] $ Just instTys
1457+#endif
1458+ _ -> fail $ ns ++
1459+ "Could not find data or newtype instance constructor."
1460+ _ -> fail $ ns ++ "Data constructor " ++ show name ++
1461+ " is not from a data family instance constructor."
1462+#if MIN_VERSION_template_haskell(2,11,0)
1463+ FamilyI DataFamilyD{} _ ->
1464+#else
1465+ FamilyI (FamilyD DataFam _ _ _) _ ->
1466+#endif
1467+ fail $ ns ++
1468+ "Cannot use a data family name. Use a data family instance constructor instead."
1469+ _ -> fail $ ns ++ "I need the name of a plain data type constructor, "
1470+ ++ "or a data family instance constructor."
1471+ where
1472+ ns :: String
1473+ ns = "Data.Aeson.TH.withType: "
1474+
1475+-- | Infer the context and instance head needed for a FromJSON or ToJSON instance.
1332buildTypeInstance :: Name
1476buildTypeInstance :: Name
1333 -- ^ The type constructor or data family name
1477 -- ^ The type constructor or data family name
1334 -> JSONClass
1478 -> JSONClass
1335 -- ^ The typeclass to derive
1479 -- ^ The typeclass to derive
1336 -> Cxt
1480 -> Cxt
1337 -- ^ The datatype context
1481 -- ^ The datatype context
1482+ -> [TyVarBndr]
1483+ -- ^ The type variables from the data type/data family declaration
1338− -> [Type]
1484+ -> Maybe [Type]
1339− -- ^ The types to instantiate the instance with
1340− -> DatatypeVariant
1341− -- ^ Are we dealing with a data family instance or not
1485+ -- ^ 'Just' the types used to instantiate a data family instance,
1486+ -- or 'Nothing' if it's a plain data type
1342 -> Q (Cxt, Type)
1487 -> Q (Cxt, Type)
1488+ -- ^ The resulting 'Cxt' and 'Type' to use in a class instance
1489+-- Plain data type/newtype case
1343−buildTypeInstance tyConName jc dataCxt varTysOrig variant = do
1490+buildTypeInstance tyConName jc dataCxt tvbs Nothing =
1491+ let varTys :: [Type]
1492+ varTys = map tvbToType tvbs
1493+ in buildTypeInstanceFromTys tyConName jc dataCxt varTys False
1494+-- Data family instance case
1495+--
1496+-- The CPP is present to work around a couple of annoying old GHC bugs.
1497+-- See Note [Polykinded data families in Template Haskell]
1498+buildTypeInstance dataFamName jc dataCxt tvbs (Just instTysAndKinds) = do
1499+#if !(MIN_VERSION_template_haskell(2,8,0)) || MIN_VERSION_template_haskell(2,10,0)
1500+ let instTys :: [Type]
1501+ instTys = zipWith stealKindForType tvbs instTysAndKinds
1502+#else
1503+ let kindVarNames :: [Name]
1504+ kindVarNames = nub $ concatMap (tyVarNamesOfType . tvbKind) tvbs
1505+
1506+ numKindVars :: Int
1507+ numKindVars = length kindVarNames
1508+
1509+ givenKinds, givenKinds' :: [Kind]
1510+ givenTys :: [Type]
1511+ (givenKinds, givenTys) = splitAt numKindVars instTysAndKinds
1512+ givenKinds' = map sanitizeStars givenKinds
1513+
1514+ -- A GHC 7.6-specific bug requires us to replace all occurrences of
1515+ -- (ConT GHC.Prim.*) with StarT, or else Template Haskell will reject it.
1516+ -- Luckily, (ConT GHC.Prim.*) only seems to occur in this one spot.
1517+ sanitizeStars :: Kind -> Kind
1518+ sanitizeStars = go
1519+ where
1520+ go :: Kind -> Kind
1521+ go (AppT t1 t2) = AppT (go t1) (go t2)
1522+ go (SigT t k) = SigT (go t) (go k)
1523+ go (ConT n) | n == starKindName = StarT
1524+ go t = t
1525+
1526+ -- It's quite awkward to import * from GHC.Prim, so we'll just
1527+ -- hack our way around it.
1528+ starKindName :: Name
1529+ starKindName = mkNameG_tc "ghc-prim" "GHC.Prim" "*"
1530+
1531+ -- If we run this code with GHC 7.8, we might have to generate extra type
1532+ -- variables to compensate for any type variables that Template Haskell
1533+ -- eta-reduced away.
1534+ -- See Note [Polykinded data families in Template Haskell]
1535+ xTypeNames <- newNameList "tExtra" (length tvbs - length givenTys)
1536+
1537+ let xTys :: [Type]
1538+ xTys = map VarT xTypeNames
1539+ -- ^ Because these type variables were eta-reduced away, we can only
1540+ -- determine their kind by using stealKindForType. Therefore, we mark
1541+ -- them as VarT to ensure they will be given an explicit kind annotation
1542+ -- (and so the kind inference machinery has the right information).
1543+
1544+ substNamesWithKinds :: [(Name, Kind)] -> Type -> Type
1545+ substNamesWithKinds nks t = foldr' (uncurry substNameWithKind) t nks
1546+
1547+ -- The types from the data family instance might not have explicit kind
1548+ -- annotations, which the kind machinery needs to work correctly. To
1549+ -- compensate, we use stealKindForType to explicitly annotate any
1550+ -- types without kind annotations.
1551+ instTys :: [Type]
1552+ instTys = map (substNamesWithKinds (zip kindVarNames givenKinds'))
1553+ -- Note that due to a GHC 7.8-specific bug
1554+ -- (see Note [Polykinded data families in Template Haskell]),
1555+ -- there may be more kind variable names than there are kinds
1556+ -- to substitute. But this is OK! If a kind is eta-reduced, it
1557+ -- means that is was not instantiated to something more specific,
1558+ -- so we need not substitute it. Using stealKindForType will
1559+ -- grab the correct kind.
1560+ $ zipWith stealKindForType tvbs (givenTys ++ xTys)
1561+#endif
1562+ buildTypeInstanceFromTys dataFamName jc dataCxt instTys True
1563+
1564+-- For the given Types, generate an instance context and head.
1565+buildTypeInstanceFromTys :: Name
1566+ -- ^ The type constructor or data family name
1567+ -> JSONClass
1568+ -- ^ The typeclass to derive
1569+ -> Cxt
1570+ -- ^ The datatype context
1571+ -> [Type]
1572+ -- ^ The types to instantiate the instance with
1573+ -> Bool
1574+ -- ^ True if it's a data family, False otherwise
1575+ -> Q (Cxt, Type)
1576+buildTypeInstanceFromTys tyConName jc dataCxt varTysOrig isDataFamily = do
1344 -- Make sure to expand through type/kind synonyms! Otherwise, the
1577 -- Make sure to expand through type/kind synonyms! Otherwise, the
1345 -- eta-reduction check might get tripped up over type variables in a
1578 -- eta-reduction check might get tripped up over type variables in a
1346 -- synonym that are actually dropped.
1579 -- synonym that are actually dropped.
1347 -- (See GHC Trac #11416 for a scenario where this actually happened.)
1580 -- (See GHC Trac #11416 for a scenario where this actually happened.)
1348− varTysExp <- mapM resolveTypeSynonyms varTysOrig
1581+ varTysExp <- mapM expandSyn varTysOrig
1349
1582
1350 let remainingLength :: Int
1583 let remainingLength :: Int
1351 remainingLength = length varTysOrig - arityInt jc
1584 remainingLength = length varTysOrig - arityInt jc
@@ -1358,7 +1591,7 @@ buildTypeInstance tyConName jc dataCxt varTysOrig variant = do
1358
1591
1359 -- Check there are enough types to drop and that all of them are either of
1592 -- Check there are enough types to drop and that all of them are either of
1360 -- kind * or kind k (for some kind variable k). If not, throw an error.
1593 -- kind * or kind k (for some kind variable k). If not, throw an error.
1361− when (remainingLength < 0 || elem NotKindStar droppedStarKindStati) $
1594+ when (remainingLength < 0 || any (== NotKindStar) droppedStarKindStati) $
1362 derivingKindError jc tyConName
1595 derivingKindError jc tyConName
1363
1596
1364 let droppedKindVarNames :: [Name]
1597 let droppedKindVarNames :: [Name]
@@ -1375,7 +1608,7 @@ buildTypeInstance tyConName jc dataCxt varTysOrig variant = do
1375 -- All of the type variables mentioned in the dropped types
1608 -- All of the type variables mentioned in the dropped types
1376 -- (post-synonym expansion)
1609 -- (post-synonym expansion)
1377 droppedTyVarNames :: [Name]
1610 droppedTyVarNames :: [Name]
1378− droppedTyVarNames = freeVariables droppedTysExpSubst
1611+ droppedTyVarNames = concatMap tyVarNamesOfType droppedTysExpSubst
1379
1612
1380 -- If any of the dropped types were polykinded, ensure that they are of kind *
1613 -- If any of the dropped types were polykinded, ensure that they are of kind *
1381 -- after substituting * for the dropped kind variables. If not, throw an error.
1614 -- after substituting * for the dropped kind variables. If not, throw an error.
@@ -1413,16 +1646,9 @@ buildTypeInstance tyConName jc dataCxt varTysOrig variant = do
1413 -- instance C (Fam [Char])
1646 -- instance C (Fam [Char])
1414 remainingTysOrigSubst :: [Type]
1647 remainingTysOrigSubst :: [Type]
1415 remainingTysOrigSubst =
1648 remainingTysOrigSubst =
1416− map (substNamesWithKindStar (droppedKindVarNames `union` kvNames'))
1649+ map (substNamesWithKindStar (union droppedKindVarNames kvNames'))
1417 $ take remainingLength varTysOrig
1650 $ take remainingLength varTysOrig
1418
1651
1419− isDataFamily :: Bool
1420− isDataFamily = case variant of
1421− Datatype -> False
1422− Newtype -> False
1423− DataInstance -> True
1424− NewtypeInstance -> True
1425−
1426 remainingTysOrigSubst' :: [Type]
1652 remainingTysOrigSubst' :: [Type]
1427 -- See Note [Kind signatures in derived instances] for an explanation
1653 -- See Note [Kind signatures in derived instances] for an explanation
1428 -- of the isDataFamily check.
1654 -- of the isDataFamily check.
@@ -1476,6 +1702,55 @@ deriveConstraint jc t
1476 jcConstraint = jsonClassName . JSONClass (direction jc)
1702 jcConstraint = jsonClassName . JSONClass (direction jc)
1477
1703
1478{-
1704{-
1705+Note [Polykinded data families in Template Haskell]
1706+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1707+
1708+In order to come up with the correct instance context and head for an instance, e.g.,
1709+
1710+ instance C a => C (Data a) where ...
1711+
1712+We need to know the exact types and kinds used to instantiate the instance. For
1713+plain old datatypes, this is simple: every type must be a type variable, and
1714+Template Haskell reliably tells us the type variables and their kinds.
1715+
1716+Doing the same for data families proves to be much harder for three reasons:
1717+
1718+1. On any version of Template Haskell, it may not tell you what an instantiated
1719+ type's kind is. For instance, in the following data family instance:
1720+
1721+ data family Fam (f :: * -> *) (a :: *)
1722+ data instance Fam f a
1723+
1724+ Then if we use TH's reify function, it would tell us the TyVarBndrs of the
1725+ data family declaration are:
1726+
1727+ [KindedTV f (AppT (AppT ArrowT StarT) StarT),KindedTV a StarT]
1728+
1729+ and the instantiated types of the data family instance are:
1730+
1731+ [VarT f1,VarT a1]
1732+
1733+ We can't just pass [VarT f1,VarT a1] to buildTypeInstanceFromTys, since we
1734+ have no way of knowing their kinds. Luckily, the TyVarBndrs tell us what the
1735+ kind is in case an instantiated type isn't a SigT, so we use the stealKindForType
1736+ function to ensure all of the instantiated types are SigTs before passing them
1737+ to buildTypeInstanceFromTys.
1738+2. On GHC 7.6 and 7.8, a bug is present in which Template Haskell lists all of
1739+ the specified kinds of a data family instance efore any of the instantiated
1740+ types. Fortunately, this is easy to deal with: you simply count the number of
1741+ distinct kind variables in the data family declaration, take that many elements
1742+ from the front of the Types list of the data family instance, substitute the
1743+ kind variables with their respective instantiated kinds (which you took earlier),
1744+ and proceed as normal.
1745+3. On GHC 7.8, an even uglier bug is present (GHC Trac #9692) in which Template
1746+ Haskell might not even list all of the Types of a data family instance, since
1747+ they are eta-reduced away! And yes, kinds can be eta-reduced too.
1748+
1749+ The simplest workaround is to count how many instantiated types are missing from
1750+ the list and generate extra type variables to use in their place. Luckily, we
1751+ needn't worry much if its kind was eta-reduced away, since using stealKindForType
1752+ will get it back.
1753+
1479Note [Kind signatures in derived instances]
1754Note [Kind signatures in derived instances]
1480~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1755~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1481
1756
@@ -1553,14 +1828,50 @@ things we can do to make instance contexts that work for 80% of use cases:
1553 and perform kind substitution as in the other cases.
1828 and perform kind substitution as in the other cases.
1554-}
1829-}
1555
1830
1556−checkExistentialContext :: JSONClass -> TyVarMap -> Cxt -> Name
1831+-- Determines the types of a constructor's arguments as well as the last type
1557− -> Q a -> Q a
1832+-- parameters (mapped to their encoding/decoding functions), expanding through
1558−checkExistentialContext jc tvMap ctxt conName q =
1833+-- any type synonyms.
1834+--
1835+-- The type parameters are determined on a constructor-by-constructor basis since
1836+-- they may be refined to be particular types in a GADT.
1837+reifyConTys :: JSONClass
1838+ -> [(Name, Name)]
1839+ -> Name
1840+ -> Q ([Type], TyVarMap)
1841+reifyConTys jc tpjs conName = do
1842+ info <- reify conName
1843+ (ctxt, uncTy) <- case info of
1844+ DataConI _ ty _
1845+#if !(MIN_VERSION_template_haskell(2,11,0))
1846+ _
1847+#endif
1848+ -> fmap uncurryTy (expandSyn ty)
1849+ _ -> error "Must be a data constructor"
1850+ let (argTys, [resTy]) = NE.splitAt (NE.length uncTy - 1) uncTy
1851+ unapResTy = unapplyTy resTy
1852+ -- If one of the last type variables is refined to a particular type
1853+ -- (i.e., not truly polymorphic), we mark it with Nothing and filter
1854+ -- it out later, since we only apply encoding/decoding functions to
1855+ -- arguments of a type that it (1) one of the last type variables,
1856+ -- and (2) of a truly polymorphic type.
1857+ jArity = arityInt jc
1858+ mbTvNames = map varTToName_maybe $
1859+ NE.drop (NE.length unapResTy - jArity) unapResTy
1860+ -- We use M.fromList to ensure that if there are any duplicate type
1861+ -- variables (as can happen in a GADT), the rightmost type variable gets
1862+ -- associated with the show function.
1863+ --
1864+ -- See Note [Matching functions with GADT type variables]
1865+ tvMap = M.fromList
1866+ . catMaybes -- Drop refined types
1867+ $ zipWith (\mbTvName tpj ->
1868+ fmap (\tvName -> (tvName, tpj)) mbTvName)
1869+ mbTvNames tpjs
1559− if (any (`predMentionsName` M.keys tvMap) ctxt
1870+ if (any (`predMentionsName` M.keys tvMap) ctxt
1560− || M.size tvMap < arityInt jc)
1871+ || M.size tvMap < jArity)
1561− && not (allowExQuant jc)
1872+ && not (allowExQuant jc)
1562− then existentialContextError conName
1873+ then existentialContextError conName
1563− else q
1874+ else return (argTys, tvMap)
1564
1875
1565{-
1876{-
1566Note [Matching functions with GADT type variables]
1877Note [Matching functions with GADT type variables]
@@ -1600,22 +1911,69 @@ Both.
1600-- are the function arguments of types (b -> Value) and ([b] -> Value).
1911-- are the function arguments of types (b -> Value) and ([b] -> Value).
1601type TyVarMap = Map Name (Name, Name)
1912type TyVarMap = Map Name (Name, Name)
1602
1913
1914+-- | If a VarT is missing an explicit kind signature, steal it from a TyVarBndr.
1915+stealKindForType :: TyVarBndr -> Type -> Type
1916+stealKindForType tvb t@VarT{} = SigT t (tvbKind tvb)
1917+stealKindForType _ t = t
1918+
1919+-- | Extracts the kind from a type variable binder.
1920+tvbKind :: TyVarBndr -> Kind
1921+#if MIN_VERSION_template_haskell(2,8,0)
1922+tvbKind (PlainTV _ ) = StarT
1923+#else
1924+tvbKind (PlainTV _ ) = StarK
1925+#endif
1926+tvbKind (KindedTV _ k) = k
1927+
1928+tvbToType :: TyVarBndr -> Type
1929+tvbToType (PlainTV n) = VarT n
1930+tvbToType (KindedTV n k) = SigT (VarT n) k
1931+
1603-- | Returns True if a Type has kind *.
1932-- | Returns True if a Type has kind *.
1604hasKindStar :: Type -> Bool
1933hasKindStar :: Type -> Bool
1605hasKindStar VarT{} = True
1934hasKindStar VarT{} = True
1935+#if MIN_VERSION_template_haskell(2,8,0)
1606hasKindStar (SigT _ StarT) = True
1936hasKindStar (SigT _ StarT) = True
1937+#else
1938+hasKindStar (SigT _ StarK) = True
1939+#endif
1607hasKindStar _ = False
1940hasKindStar _ = False
1608
1941
1609-- Returns True is a kind is equal to *, or if it is a kind variable.
1942-- Returns True is a kind is equal to *, or if it is a kind variable.
1610isStarOrVar :: Kind -> Bool
1943isStarOrVar :: Kind -> Bool
1944+#if MIN_VERSION_template_haskell(2,8,0)
1611isStarOrVar StarT = True
1945isStarOrVar StarT = True
1612isStarOrVar VarT{} = True
1946isStarOrVar VarT{} = True
1947+#else
1948+isStarOrVar StarK = True
1949+#endif
1613isStarOrVar _ = False
1950isStarOrVar _ = False
1614
1951
1615-- Generate a list of fresh names with a common prefix, and numbered suffixes.
1952-- Generate a list of fresh names with a common prefix, and numbered suffixes.
1616newNameList :: String -> Int -> Q [Name]
1953newNameList :: String -> Int -> Q [Name]
1617newNameList prefix len = mapM newName [prefix ++ show n | n <- [1..len]]
1954newNameList prefix len = mapM newName [prefix ++ show n | n <- [1..len]]
1618
1955
1956+-- Gets all of the type/kind variable names mentioned somewhere in a Type.
1957+tyVarNamesOfType :: Type -> [Name]
1958+tyVarNamesOfType = go
1959+ where
1960+ go :: Type -> [Name]
1961+ go (AppT t1 t2) = go t1 ++ go t2
1962+ go (SigT t _k) = go t
1963+#if MIN_VERSION_template_haskell(2,8,0)
1964+ ++ go _k
1965+#endif
1966+ go (VarT n) = [n]
1967+ go _ = []
1968+
1969+-- | Gets all of the type/kind variable names mentioned somewhere in a Kind.
1970+tyVarNamesOfKind :: Kind -> [Name]
1971+#if MIN_VERSION_template_haskell(2,8,0)
1972+tyVarNamesOfKind = tyVarNamesOfType
1973+#else
1974+tyVarNamesOfKind _ = [] -- There are no kind variables
1975+#endif
1976+
1619-- | @hasKindVarChain n kind@ Checks if @kind@ is of the form
1977-- | @hasKindVarChain n kind@ Checks if @kind@ is of the form
1620-- k_0 -> k_1 -> ... -> k_(n-1), where k0, k1, ..., and k_(n-1) can be * or
1978-- k_0 -> k_1 -> ... -> k_(n-1), where k0, k1, ..., and k_(n-1) can be * or
1621-- kind variables.
1979-- kind variables.
@@ -1623,7 +1981,7 @@ hasKindVarChain :: Int -> Type -> Maybe [Name]
1623hasKindVarChain kindArrows t =
1981hasKindVarChain kindArrows t =
1624 let uk = uncurryKind (tyKind t)
1982 let uk = uncurryKind (tyKind t)
1625 in if (NE.length uk - 1 == kindArrows) && F.all isStarOrVar uk
1983 in if (NE.length uk - 1 == kindArrows) && F.all isStarOrVar uk
1626− then Just (concatMap freeVariables uk)
1984+ then Just (concatMap tyVarNamesOfKind uk)
1627 else Nothing
1985 else Nothing
1628
1986
1629-- | If a Type is a SigT, returns its kind signature. Otherwise, return *.
1987-- | If a Type is a SigT, returns its kind signature. Otherwise, return *.
@@ -1633,15 +1991,26 @@ tyKind _ = starK
1633
1991
1634-- | Extract Just the Name from a type variable. If the argument Type is not a
1992-- | Extract Just the Name from a type variable. If the argument Type is not a
1635-- type variable, return Nothing.
1993-- type variable, return Nothing.
1636−varTToNameMaybe :: Type -> Maybe Name
1994+varTToName_maybe :: Type -> Maybe Name
1637−varTToNameMaybe (VarT n) = Just n
1995+varTToName_maybe (VarT n) = Just n
1638−varTToNameMaybe (SigT t _) = varTToNameMaybe t
1996+varTToName_maybe (SigT t _) = varTToName_maybe t
1639−varTToNameMaybe _ = Nothing
1997+varTToName_maybe _ = Nothing
1640
1998
1641-- | Extract the Name from a type variable. If the argument Type is not a
1999-- | Extract the Name from a type variable. If the argument Type is not a
1642-- type variable, throw an error.
2000-- type variable, throw an error.
1643varTToName :: Type -> Name
2001varTToName :: Type -> Name
1644−varTToName = fromMaybe (error "Not a type variable!") . varTToNameMaybe
2002+varTToName = fromMaybe (error "Not a type variable!") . varTToName_maybe
2003+
2004+-- | Extracts the name from a constructor.
2005+getConName :: Con -> Name
2006+getConName (NormalC name _) = name
2007+getConName (RecC name _) = name
2008+getConName (InfixC _ name _) = name
2009+getConName (ForallC _ _ con) = getConName con
2010+#if MIN_VERSION_template_haskell(2,11,0)
2011+getConName (GadtC names _ _) = head names
2012+getConName (RecGadtC names _ _) = head names
2013+#endif
1645
2014
1646interleave :: [a] -> [a] -> [a]
2015interleave :: [a] -> [a] -> [a]
1647interleave (a1:a1s) (a2:a2s) = a1:a2:interleave a1s a2s
2016interleave (a1:a1s) (a2:a2s) = a1:a2:interleave a1s a2s
@@ -1667,7 +2036,9 @@ isTyFamily (ConT n) = do
1667#else
2036#else
1668 FamilyI (FamilyD TypeFam _ _ _) _ -> True
2037 FamilyI (FamilyD TypeFam _ _ _) _ -> True
1669#endif
2038#endif
2039+#if MIN_VERSION_template_haskell(2,9,0)
1670 FamilyI ClosedTypeFamilyD{} _ -> True
2040 FamilyI ClosedTypeFamilyD{} _ -> True
2041+#endif
1671 _ -> False
2042 _ -> False
1672isTyFamily _ = return False
2043isTyFamily _ = return False
1673
2044
@@ -1695,7 +2066,9 @@ mentionsName = go
1695 go :: Type -> [Name] -> Bool
2066 go :: Type -> [Name] -> Bool
1696 go (AppT t1 t2) names = go t1 names || go t2 names
2067 go (AppT t1 t2) names = go t1 names || go t2 names
1697 go (SigT t _k) names = go t names
2068 go (SigT t _k) names = go t names
2069+#if MIN_VERSION_template_haskell(2,8,0)
1698 || go _k names
2070 || go _k names
2071+#endif
1699 go (VarT n) names = n `elem` names
2072 go (VarT n) names = n `elem` names
1700 go _ _ = False
2073 go _ _ = False
1701
2074
@@ -1751,28 +2124,37 @@ uncurryTy t = ([], t :| [])
1751
2124
1752-- | Like uncurryType, except on a kind level.
2125-- | Like uncurryType, except on a kind level.
1753uncurryKind :: Kind -> NonEmpty Kind
2126uncurryKind :: Kind -> NonEmpty Kind
2127+#if MIN_VERSION_template_haskell(2,8,0)
1754uncurryKind = snd . uncurryTy
2128uncurryKind = snd . uncurryTy
2129+#else
2130+uncurryKind (ArrowK k1 k2) = k1 <| uncurryKind k2
2131+uncurryKind k = k :| []
2132+#endif
1755
2133
1756createKindChain :: Int -> Kind
2134createKindChain :: Int -> Kind
1757createKindChain = go starK
2135createKindChain = go starK
1758 where
2136 where
1759 go :: Kind -> Int -> Kind
2137 go :: Kind -> Int -> Kind
1760− go k 0 = k
2138+ go k !0 = k
2139+#if MIN_VERSION_template_haskell(2,8,0)
1761 go k !n = go (AppT (AppT ArrowT StarT) k) (n - 1)
2140 go k !n = go (AppT (AppT ArrowT StarT) k) (n - 1)
2141+#else
2142+ go k !n = go (ArrowK StarK k) (n - 1)
2143+#endif
1762
2144
1763-- | Makes a string literal expression from a constructor's name.
2145-- | Makes a string literal expression from a constructor's name.
1764−conNameExp :: Options -> ConstructorInfo -> Q Exp
2146+conNameExp :: Options -> Con -> Q Exp
1765conNameExp opts = litE
2147conNameExp opts = litE
1766 . stringL
2148 . stringL
1767 . constructorTagModifier opts
2149 . constructorTagModifier opts
1768 . nameBase
2150 . nameBase
1769− . constructorName
2151+ . getConName
1770
2152
1771−-- | Extracts a record field label.
2153+-- | Creates a string literal expression from a record field label.
1772−fieldLabel :: Options -- ^ Encoding options
2154+fieldLabelExp :: Options -- ^ Encoding options
1773− -> Name
2155+ -> Name
1774− -> String
2156+ -> Q Exp
1775−fieldLabel opts = fieldLabelModifier opts . nameBase
2157+fieldLabelExp opts = litE . stringL . fieldLabelModifier opts . nameBase
1776
2158
1777-- | The name of the outermost 'Value' constructor.
2159-- | The name of the outermost 'Value' constructor.
1778valueConName :: Value -> String
2160valueConName :: Value -> String
@@ -1811,14 +2193,76 @@ canEtaReduce remaining dropped =
1811-- Expanding type synonyms
2193-- Expanding type synonyms
1812-------------------------------------------------------------------------------
2194-------------------------------------------------------------------------------
1813
2195
1814−applySubstitutionKind :: Map Name Kind -> Type -> Type
2196+-- | Expands all type synonyms in a type. Written by Dan Rosén in the
1815−applySubstitutionKind = applySubstitution
2197+-- @genifunctors@ package (licensed under BSD3).
2198+expandSyn :: Type -> Q Type
2199+expandSyn (ForallT tvs ctx t) = fmap (ForallT tvs ctx) $ expandSyn t
2200+expandSyn t@AppT{} = expandSynApp t []
2201+expandSyn t@ConT{} = expandSynApp t []
2202+expandSyn (SigT t k) = do t' <- expandSyn t
2203+ k' <- expandSynKind k
2204+ return (SigT t' k')
2205+expandSyn t = return t
2206+
2207+expandSynKind :: Kind -> Q Kind
2208+#if MIN_VERSION_template_haskell(2,8,0)
2209+expandSynKind = expandSyn
2210+#else
2211+expandSynKind = return -- There are no kind synonyms to deal with
2212+#endif
2213+
2214+expandSynApp :: Type -> [Type] -> Q Type
2215+expandSynApp (AppT t1 t2) ts = do
2216+ t2' <- expandSyn t2
2217+ expandSynApp t1 (t2':ts)
2218+expandSynApp (ConT n) ts | nameBase n == "[]" = return $ foldl' AppT ListT ts
2219+expandSynApp t@(ConT n) ts = do
2220+ info <- reify n
2221+ case info of
2222+ TyConI (TySynD _ tvs rhs) ->
2223+ let (ts', ts'') = splitAt (length tvs) ts
2224+ subs = mkSubst tvs ts'
2225+ rhs' = substType subs rhs
2226+ in expandSynApp rhs' ts''
2227+ _ -> return $ foldl' AppT t ts
2228+expandSynApp t ts = do
2229+ t' <- expandSyn t
2230+ return $ foldl' AppT t' ts
2231+
2232+type TypeSubst = Map Name Type
2233+type KindSubst = Map Name Kind
2234+
2235+mkSubst :: [TyVarBndr] -> [Type] -> TypeSubst
2236+mkSubst vs ts =
2237+ let vs' = map un vs
2238+ un (PlainTV v) = v
2239+ un (KindedTV v _) = v
2240+ in M.fromList $ zip vs' ts
2241+
2242+substType :: TypeSubst -> Type -> Type
2243+substType subs (ForallT v c t) = ForallT v c $ substType subs t
2244+substType subs t@(VarT n) = M.findWithDefault t n subs
2245+substType subs (AppT t1 t2) = AppT (substType subs t1) (substType subs t2)
2246+substType subs (SigT t k) = SigT (substType subs t)
2247+#if MIN_VERSION_template_haskell(2,8,0)
2248+ (substType subs k)
2249+#else
2250+ k
2251+#endif
2252+substType _ t = t
2253+
2254+substKind :: KindSubst -> Type -> Type
2255+#if MIN_VERSION_template_haskell(2,8,0)
2256+substKind = substType
2257+#else
2258+substKind _ t = t -- There are no kind variables!
2259+#endif
1816
2260
1817substNameWithKind :: Name -> Kind -> Type -> Type
2261substNameWithKind :: Name -> Kind -> Type -> Type
1818−substNameWithKind n k = applySubstitutionKind (M.singleton n k)
2262+substNameWithKind n k = substKind (M.singleton n k)
1819
2263
1820substNamesWithKindStar :: [Name] -> Type -> Type
2264substNamesWithKindStar :: [Name] -> Type -> Type
1821−substNamesWithKindStar ns t = foldr' (`substNameWithKind` starK) t ns
2265+substNamesWithKindStar ns t = foldr' (flip substNameWithKind starK) t ns
1822
2266
1823-------------------------------------------------------------------------------
2267-------------------------------------------------------------------------------
1824-- Error messages
2268-- Error messages
@@ -1901,13 +2345,6 @@ data Direction = To | From
1901-- | A representation of which typeclass method is being spliced in.
2345-- | A representation of which typeclass method is being spliced in.
1902data JSONFun = ToJSON | ToEncoding | ParseJSON
2346data JSONFun = ToJSON | ToEncoding | ParseJSON
1903
2347
1904−-- | A refinement of JSONFun to [ToJSON, ToEncoding].
1905−data ToJSONFun = Value | Encoding
1906−
1907−targetToJSONFun :: ToJSONFun -> JSONFun
1908−targetToJSONFun Value = ToJSON
1909−targetToJSONFun Encoding = ToEncoding
1910−
1911-- | A representation of which typeclass is being derived.
2348-- | A representation of which typeclass is being derived.
1912data JSONClass = JSONClass { direction :: Direction, arity :: Arity }
2349data JSONClass = JSONClass { direction :: Direction, arity :: Arity }
1913
2350
@@ -1974,10 +2411,13 @@ data StarKindStatus = NotKindStar
1974
2411
1975-- | Does a Type have kind * or k (for some kind variable k)?
2412-- | Does a Type have kind * or k (for some kind variable k)?
1976canRealizeKindStar :: Type -> StarKindStatus
2413canRealizeKindStar :: Type -> StarKindStatus
1977−canRealizeKindStar t = case t of
2414+canRealizeKindStar t
1978− _ | hasKindStar t -> KindStar
2415+ | hasKindStar t = KindStar
2416+ | otherwise = case t of
2417+#if MIN_VERSION_template_haskell(2,8,0)
1979− SigT _ (VarT k) -> IsKindVar k
2418+ SigT _ (VarT k) -> IsKindVar k
2419+#endif
1980− _ -> NotKindStar
2420+ _ -> NotKindStar
1981
2421
1982-- | Returns 'Just' the kind variable 'Name' of a 'StarKindStatus' if it exists.
2422-- | Returns 'Just' the kind variable 'Name' of a 'StarKindStatus' if it exists.
1983-- Otherwise, returns 'Nothing'.
2423-- Otherwise, returns 'Nothing'.
Data/Aeson/Text.hsdeleted−102
@@ -1,102 +0,0 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−-- |
5−-- Module: Data.Aeson.Text
6−-- Copyright: (c) 2012-2016 Bryan O'Sullivan
7−-- (c) 2011 MailRank, Inc.
8−-- License: BSD3
9−-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
10−-- Stability: experimental
11−-- Portability: portable
12−--
13−-- Most frequently, you'll probably want to encode straight to UTF-8
14−-- (the standard JSON encoding) using 'encode'.
15−--
16−-- You can use the conversions to 'Builder's when embedding JSON messages as
17−-- parts of a protocol.
18−
19−module Data.Aeson.Text
20− (
21− encodeToLazyText
22− , encodeToTextBuilder
23− ) where
24−
25−import Prelude.Compat
26−
27−import Data.Aeson.Types (Value(..), ToJSON(..))
28−import Data.Aeson.Encoding (encodingToLazyByteString)
29−import Data.Semigroup ((<>))
30−import Data.Scientific (FPFormat(..), Scientific, base10Exponent)
31−import Data.Text.Lazy.Builder
32−import Data.Text.Lazy.Builder.Scientific (formatScientificBuilder)
33−import Numeric (showHex)
34−import qualified Data.HashMap.Strict as H
35−import qualified Data.Text as T
36−import qualified Data.Text.Lazy as LT
37−import qualified Data.Text.Lazy.Encoding as LT
38−import qualified Data.Vector as V
39−
40−-- | Encode a JSON 'Value' to a "Data.Text.Lazy"
41−--
42−-- /Note:/ uses 'toEncoding'
43−encodeToLazyText :: ToJSON a => a -> LT.Text
44−encodeToLazyText = LT.decodeUtf8 . encodingToLazyByteString . toEncoding
45−
46−-- | Encode a JSON 'Value' to a "Data.Text" 'Builder', which can be
47−-- embedded efficiently in a text-based protocol.
48−--
49−-- If you are going to immediately encode straight to a
50−-- 'L.ByteString', it is more efficient to use 'encode' (lazy ByteString)
51−-- or @'fromEncoding' . 'toEncoding'@ (ByteString.Builder) instead.
52−--
53−-- /Note:/ Uses 'toJSON'
54−encodeToTextBuilder :: ToJSON a => a -> Builder
55−encodeToTextBuilder =
56− go . toJSON
57− where
58− go Null = {-# SCC "go/Null" #-} "null"
59− go (Bool b) = {-# SCC "go/Bool" #-} if b then "true" else "false"
60− go (Number s) = {-# SCC "go/Number" #-} fromScientific s
61− go (String s) = {-# SCC "go/String" #-} string s
62− go (Array v)
63− | V.null v = {-# SCC "go/Array" #-} "[]"
64− | otherwise = {-# SCC "go/Array" #-}
65− singleton '[' <>
66− go (V.unsafeHead v) <>
67− V.foldr f (singleton ']') (V.unsafeTail v)
68− where f a z = singleton ',' <> go a <> z
69− go (Object m) = {-# SCC "go/Object" #-}
70− case H.toList m of
71− (x:xs) -> singleton '{' <> one x <> foldr f (singleton '}') xs
72− _ -> "{}"
73− where f a z = singleton ',' <> one a <> z
74− one (k,v) = string k <> singleton ':' <> go v
75−
76−string :: T.Text -> Builder
77−string s = {-# SCC "string" #-} singleton '"' <> quote s <> singleton '"'
78− where
79− quote q = case T.uncons t of
80− Nothing -> fromText h
81− Just (!c,t') -> fromText h <> escape c <> quote t'
82− where (h,t) = {-# SCC "break" #-} T.break isEscape q
83− isEscape c = c == '\"' ||
84− c == '\\' ||
85− c < '\x20'
86− escape '\"' = "\\\""
87− escape '\\' = "\\\\"
88− escape '\n' = "\\n"
89− escape '\r' = "\\r"
90− escape '\t' = "\\t"
91−
92− escape c
93− | c < '\x20' = fromString $ "\\u" ++ replicate (4 - length h) '0' ++ h
94− | otherwise = singleton c
95− where h = showHex (fromEnum c) ""
96−
97−fromScientific :: Scientific -> Builder
98−fromScientific s = formatScientificBuilder format prec s
99− where
100− (format, prec)
101− | base10Exponent s < 0 = (Generic, Nothing)
102− | otherwise = (Fixed, Just 0)
Data/Aeson/Types.hs+7−55
@@ -1,4 +1,3 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2-- |
1-- |
3-- Module: Data.Aeson.Types
2-- Module: Data.Aeson.Types
4-- Copyright: (c) 2011-2016 Bryan O'Sullivan
3-- Copyright: (c) 2011-2016 Bryan O'Sullivan
@@ -26,7 +25,6 @@ module Data.Aeson.Types
26 -- * Convenience types and functions
25 -- * Convenience types and functions
27 , DotNetTime(..)
26 , DotNetTime(..)
28 , typeMismatch
27 , typeMismatch
29− , unexpected
30 -- * Type conversion
28 -- * Type conversion
31 , Parser
29 , Parser
32 , Result(..)
30 , Result(..)
@@ -38,26 +36,14 @@ module Data.Aeson.Types
38 , ToJSON(..)
36 , ToJSON(..)
39 , KeyValue(..)
37 , KeyValue(..)
40 , modifyFailure
38 , modifyFailure
41− , prependFailure
42− , parserThrowError
43− , parserCatchError
44
39
45 -- ** Keys for maps
40 -- ** Keys for maps
46 , ToJSONKey(..)
41 , ToJSONKey(..)
47 , ToJSONKeyFunction(..)
42 , ToJSONKeyFunction(..)
48− , toJSONKeyText
49− , contramapToJSONKeyFunction
50 , FromJSONKey(..)
43 , FromJSONKey(..)
51 , FromJSONKeyFunction(..)
44 , FromJSONKeyFunction(..)
52 , fromJSONKeyCoerce
45 , fromJSONKeyCoerce
53 , coerceFromJSONKeyFunction
46 , coerceFromJSONKeyFunction
54− , mapFromJSONKeyFunction
55−
56− -- *** Generic keys
57− , GToJSONKey()
58− , genericToJSONKey
59− , GFromJSONKey()
60− , genericFromJSONKey
61
47
62 -- ** Liftings to unary and binary type constructors
48 -- ** Liftings to unary and binary type constructors
63 , FromJSON1(..)
49 , FromJSON1(..)
@@ -73,10 +59,8 @@ module Data.Aeson.Types
73
59
74 -- ** Generic JSON classes
60 -- ** Generic JSON classes
75 , GFromJSON(..)
61 , GFromJSON(..)
76− , FromArgs(..)
77− , GToJSON
62+ , GToJSON(..)
78− , GToEncoding
63+ , GToEncoding(..)
79− , ToArgs(..)
80 , Zero
64 , Zero
81 , One
65 , One
82 , genericToJSON
66 , genericToJSON
@@ -90,9 +74,9 @@ module Data.Aeson.Types
90 , withObject
74 , withObject
91 , withText
75 , withText
92 , withArray
76 , withArray
77+ , withNumber
93 , withScientific
78 , withScientific
94 , withBool
79 , withBool
95− , withEmbeddedJSON
96
80
97 , pairs
81 , pairs
98 , foldable
82 , foldable
@@ -101,62 +85,30 @@ module Data.Aeson.Types
101 , (.:!)
85 , (.:!)
102 , (.!=)
86 , (.!=)
103 , object
87 , object
104− , parseField
105− , parseFieldMaybe
106− , parseFieldMaybe'
107− , explicitParseField
108− , explicitParseFieldMaybe
109− , explicitParseFieldMaybe'
110
88
111 , listEncoding
89 , listEncoding
112 , listValue
90 , listValue
113 , listParser
91 , listParser
114
92
115 -- * Generic and TH encoding configuration
93 -- * Generic and TH encoding configuration
116− , Options
94+ , Options(..)
117−
118− -- ** Options fields
119− -- $optionsFields
120− , fieldLabelModifier
121− , constructorTagModifier
122− , allNullaryToStringTag
123− , omitNothingFields
124− , sumEncoding
125− , unwrapUnaryRecords
126− , tagSingleConstructors
127− , rejectUnknownFields
128−
129− -- ** Options utilities
130 , SumEncoding(..)
95 , SumEncoding(..)
131 , camelTo
96 , camelTo
132 , camelTo2
97 , camelTo2
133 , defaultOptions
98 , defaultOptions
134 , defaultTaggedObject
99 , defaultTaggedObject
135−
136− -- ** Options for object keys
137− , JSONKeyOptions
138− , keyModifier
139− , defaultJSONKeyOptions
140−
141− -- * Parsing context
142− , (<?>)
143− , JSONPath
144− , JSONPathElement(..)
145− , formatPath
146− , formatRelativePath
147 ) where
100 ) where
148
101
102+import Prelude ()
149import Prelude.Compat
103import Prelude.Compat
150
104
151−import Data.Aeson.Encoding (Encoding, unsafeToEncoding, fromEncoding, Series, pairs)
152import Data.Aeson.Types.Class
105import Data.Aeson.Types.Class
153import Data.Aeson.Types.Internal
106import Data.Aeson.Types.Internal
107+import Data.Aeson.Encoding (Encoding, unsafeToEncoding, fromEncoding, Series, pairs)
108+
154import Data.Foldable (toList)
109import Data.Foldable (toList)
155
110
156-- | Encode a 'Foldable' as a JSON array.
111-- | Encode a 'Foldable' as a JSON array.
157foldable :: (Foldable t, ToJSON a) => t a -> Encoding
112foldable :: (Foldable t, ToJSON a) => t a -> Encoding
158foldable = toEncoding . toList
113foldable = toEncoding . toList
159{-# INLINE foldable #-}
114{-# INLINE foldable #-}
160−
161−-- $optionsFields
162−-- The functions here are in fact record fields of the 'Options' type.
Data/Aeson/Types/Class.hs+9−30
@@ -1,11 +1,13 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2−{-# LANGUAGE ConstraintKinds #-}
2+{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE DeriveFunctor #-}
4+{-# LANGUAGE EmptyDataDecls #-}
3{-# LANGUAGE FlexibleContexts #-}
5{-# LANGUAGE FlexibleContexts #-}
4{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GADTs #-}
7{-# LANGUAGE GADTs #-}
6{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE MultiParamTypeClasses #-}
7−{-# LANGUAGE NoImplicitPrelude #-}
8{-# LANGUAGE ScopedTypeVariables #-}
9{-# LANGUAGE ScopedTypeVariables #-}
10+{-# LANGUAGE TypeSynonymInstances #-}
9
11
10-- |
12-- |
11-- Module: Data.Aeson.Types.Class
13-- Module: Data.Aeson.Types.Class
@@ -36,10 +38,8 @@ module Data.Aeson.Types.Class
36 , toEncoding2
38 , toEncoding2
37 -- * Generic JSON classes
39 -- * Generic JSON classes
38 , GFromJSON(..)
40 , GFromJSON(..)
39− , FromArgs(..)
40− , GToJSON
41+ , GToJSON(..)
41− , GToEncoding
42+ , GToEncoding(..)
42− , ToArgs(..)
43 , Zero
43 , Zero
44 , One
44 , One
45 , genericToJSON
45 , genericToJSON
@@ -51,18 +51,12 @@ module Data.Aeson.Types.Class
51 -- * Classes and types for map keys
51 -- * Classes and types for map keys
52 , ToJSONKey(..)
52 , ToJSONKey(..)
53 , ToJSONKeyFunction(..)
53 , ToJSONKeyFunction(..)
54− , toJSONKeyText
55 , contramapToJSONKeyFunction
54 , contramapToJSONKeyFunction
56 , FromJSONKey(..)
55 , FromJSONKey(..)
57 , FromJSONKeyFunction(..)
56 , FromJSONKeyFunction(..)
58 , fromJSONKeyCoerce
57 , fromJSONKeyCoerce
59 , coerceFromJSONKeyFunction
58 , coerceFromJSONKeyFunction
60 , mapFromJSONKeyFunction
59 , mapFromJSONKeyFunction
61− -- ** Generic keys
62− , GToJSONKey()
63− , genericToJSONKey
64− , GFromJSONKey()
65− , genericFromJSONKey
66 -- * Object key-value pairs
60 -- * Object key-value pairs
67 , KeyValue(..)
61 , KeyValue(..)
68
62
@@ -75,35 +69,20 @@ module Data.Aeson.Types.Class
75 , withObject
69 , withObject
76 , withText
70 , withText
77 , withArray
71 , withArray
72+ , withNumber
78 , withScientific
73 , withScientific
79 , withBool
74 , withBool
80− , withEmbeddedJSON
81
75
82 -- * Functions
76 -- * Functions
83 , fromJSON
77 , fromJSON
84 , ifromJSON
78 , ifromJSON
85− , typeMismatch
86− , unexpected
87− , parseField
88− , parseFieldMaybe
89− , parseFieldMaybe'
90− , explicitParseField
91− , explicitParseFieldMaybe
92− , explicitParseFieldMaybe'
93− -- ** Operators
94 , (.:)
79 , (.:)
95 , (.:?)
80 , (.:?)
96 , (.:!)
81 , (.:!)
97 , (.!=)
82 , (.!=)
83+ , typeMismatch
98 ) where
84 ) where
99
85
100−
101import Data.Aeson.Types.FromJSON
86import Data.Aeson.Types.FromJSON
87+import Data.Aeson.Types.ToJSON
102import Data.Aeson.Types.Generic (One, Zero)
88import Data.Aeson.Types.Generic (One, Zero)
103−import Data.Aeson.Types.ToJSON hiding (GToJSON)
104−import qualified Data.Aeson.Types.ToJSON as ToJSON
105−import Data.Aeson.Types.Internal (Value)
106−import Data.Aeson.Encoding (Encoding)
107−
108−type GToJSON = ToJSON.GToJSON Value
109−type GToEncoding = ToJSON.GToJSON Encoding
Data/Aeson/Types/FromJSON.hs+546−1433
@@ -1,28 +1,29 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE DefaultSignatures #-}
4−{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleContexts #-}
5−{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE GADTs #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
7{-# LANGUAGE MultiParamTypeClasses #-}
8−{-# LANGUAGE NoImplicitPrelude #-}
8+{-# LANGUAGE NamedFieldPuns #-}
9−{-# LANGUAGE OverloadedStrings #-}
9+{-# LANGUAGE OverloadedStrings #-}
10−{-# LANGUAGE PolyKinds #-}
11−{-# LANGUAGE RecordWildCards #-}
10+{-# LANGUAGE RecordWildCards #-}
12−{-# LANGUAGE ScopedTypeVariables #-}
11+{-# LANGUAGE ScopedTypeVariables #-}
13−{-# LANGUAGE TypeOperators #-}
12+{-# LANGUAGE TypeOperators #-}
14−{-# LANGUAGE TupleSections #-}
13+{-# LANGUAGE TypeSynonymInstances #-}
15−{-# LANGUAGE UndecidableInstances #-}
14+{-# LANGUAGE UndecidableInstances #-}
16−{-# LANGUAGE ViewPatterns #-}
15+{-# LANGUAGE ViewPatterns #-}
17−
16+
18−#include "incoherent-compat.h"
17+#if __GLASGOW_HASKELL__ >= 706
18+{-# LANGUAGE PolyKinds #-}
19+#endif
20+
19#include "overlapping-compat.h"
21#include "overlapping-compat.h"
20
22
21-- TODO: Drop this when we remove support for Data.Attoparsec.Number
23-- TODO: Drop this when we remove support for Data.Attoparsec.Number
22{-# OPTIONS_GHC -fno-warn-deprecations #-}
24{-# OPTIONS_GHC -fno-warn-deprecations #-}
23
25
24−module Data.Aeson.Types.FromJSON
26+module Data.Aeson.Types.FromJSON (
25− (
26 -- * Core JSON classes
27 -- * Core JSON classes
27 FromJSON(..)
28 FromJSON(..)
28 -- * Liftings to unary and binary type constructors
29 -- * Liftings to unary and binary type constructors
@@ -32,7 +33,6 @@ module Data.Aeson.Types.FromJSON
32 , parseJSON2
33 , parseJSON2
33 -- * Generic JSON classes
34 -- * Generic JSON classes
34 , GFromJSON(..)
35 , GFromJSON(..)
35− , FromArgs(..)
36 , genericParseJSON
36 , genericParseJSON
37 , genericLiftParseJSON
37 , genericLiftParseJSON
38 -- * Classes and types for map keys
38 -- * Classes and types for map keys
@@ -42,121 +42,101 @@ module Data.Aeson.Types.FromJSON
42 , coerceFromJSONKeyFunction
42 , coerceFromJSONKeyFunction
43 , mapFromJSONKeyFunction
43 , mapFromJSONKeyFunction
44
44
45− , GFromJSONKey()
46− , genericFromJSONKey
47−
48 -- * List functions
45 -- * List functions
49 , listParser
46 , listParser
50
47
51− -- * Inspecting @'Value's@
48+ -- * Inspecting @'Value's@
52 , withObject
49 , withObject
53 , withText
50 , withText
54 , withArray
51 , withArray
52+ , withNumber
55 , withScientific
53 , withScientific
56 , withBool
54 , withBool
57− , withEmbeddedJSON
58
55
59 -- * Functions
56 -- * Functions
60 , fromJSON
57 , fromJSON
61 , ifromJSON
58 , ifromJSON
62− , typeMismatch
63− , unexpected
64− , parseField
65− , parseFieldMaybe
66− , parseFieldMaybe'
67− , explicitParseField
68− , explicitParseFieldMaybe
69− , explicitParseFieldMaybe'
70− , parseIndexedJSON
71− -- ** Operators
72 , (.:)
59 , (.:)
73 , (.:?)
60 , (.:?)
74 , (.:!)
61 , (.:!)
75 , (.!=)
62 , (.!=)
63+ , typeMismatch
76
64
77 -- * Internal
65 -- * Internal
78 , parseOptionalFieldWith
66 , parseOptionalFieldWith
79 ) where
67 ) where
80
68
81−import Prelude.Compat
69+import Prelude ()
70+import Prelude.Compat hiding (foldr)
82
71
83−import Control.Applicative ((<|>), Const(..), liftA2)
84−import Control.Monad (zipWithM)
85−import Data.Aeson.Internal.Functions (mapKey)
72+import Data.Aeson.Functions (mapKey)
86−import Data.Aeson.Parser.Internal (eitherDecodeWith, jsonEOF)
87import Data.Aeson.Types.Generic
73import Data.Aeson.Types.Generic
88import Data.Aeson.Types.Internal
74import Data.Aeson.Types.Internal
75+
76+import qualified Data.Aeson.Parser.Time as Time
77+
78+import Control.Applicative (Const (..), (<|>))
79+import Control.Monad ((<=<))
80+import Data.Attoparsec.Number (Number (..))
89−import Data.Bits (unsafeShiftR)
81+import Data.Bits (unsafeShiftR)
90−import Data.Fixed (Fixed, HasResolution (resolution), Nano)
82+import Data.Fixed (Fixed, HasResolution)
91−import Data.Functor.Compose (Compose(..))
92−import Data.Functor.Identity (Identity(..))
83+import Data.Functor.Identity (Identity (..))
93−import Data.Functor.Product (Product(..))
94−import Data.Functor.Sum (Sum(..))
84+import Data.Hashable (Hashable (..))
95−import Data.Hashable (Hashable(..))
96−import Data.Int (Int16, Int32, Int64, Int8)
85+import Data.Int (Int16, Int32, Int64, Int8)
97−import Data.List.NonEmpty (NonEmpty(..))
86+import Data.List.NonEmpty (NonEmpty (..))
98−import Data.Maybe (fromMaybe)
87+import Data.Maybe (fromMaybe)
99−import Data.Semigroup ((<>))
88+import Data.Monoid (Dual (..), First (..), Last (..), (<>))
100−import Data.Proxy (Proxy(..))
89+import Data.Proxy (Proxy (..))
101−import Data.Ratio ((%), Ratio)
90+import Data.Ratio (Ratio, (%))
102−import Data.Scientific (Scientific, base10Exponent)
91+import Data.Scientific (Scientific)
103−import Data.Tagged (Tagged(..))
92+import Data.Tagged (Tagged (..))
104−import Data.Text (Text, pack, unpack)
93+import Data.Text (Text, pack, unpack)
105−import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)
94+import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay,
106−import Data.Time.Calendar.Compat (CalendarDiffDays (..), DayOfWeek (..))
95+ UTCTime, ZonedTime)
107−import Data.Time.LocalTime.Compat (CalendarDiffTime (..))
96+import Data.Time.Format (parseTime)
108−import Data.Time.Clock.System.Compat (SystemTime (..))
109−import Data.Time.Format.Compat (parseTimeM, defaultTimeLocale)
97+import Data.Time.Locale.Compat (defaultTimeLocale)
110−import Data.Traversable as Tr (sequence)
98+import Data.Traversable as Tr (sequence)
111−import Data.Vector (Vector)
99+import Data.Vector (Vector)
112−import Data.Version (Version, parseVersion)
100+import Data.Version (Version, parseVersion)
113−import Data.Void (Void)
114−import Data.Word (Word16, Word32, Word64, Word8)
101+import Data.Word (Word16, Word32, Word64, Word8)
115−import Foreign.Storable (Storable)
102+import Foreign.Storable (Storable)
116−import Foreign.C.Types (CTime (..))
117import GHC.Generics
103import GHC.Generics
118−import Numeric.Natural (Natural)
104+import Numeric.Natural (Natural)
119import Text.ParserCombinators.ReadP (readP_to_S)
105import Text.ParserCombinators.ReadP (readP_to_S)
120−import Unsafe.Coerce (unsafeCoerce)
106+
121−import qualified Data.Aeson.Parser.Time as Time
122−import qualified Data.Attoparsec.ByteString.Char8 as A (endOfInput, parseOnly, scientific)
123−import qualified Data.ByteString.Lazy as L
124−import qualified Data.DList as DList
125−import qualified Data.HashMap.Strict as H
107+import qualified Data.HashMap.Strict as H
126−import qualified Data.HashSet as HashSet
108+import qualified Data.HashSet as HashSet
127−import qualified Data.IntMap as IntMap
109+import qualified Data.IntMap as IntMap
128−import qualified Data.IntSet as IntSet
110+import qualified Data.IntSet as IntSet
129−import qualified Data.Map as M
111+import qualified Data.Map as M
130−import qualified Data.Monoid as Monoid
131−import qualified Data.Scientific as Scientific
112+import qualified Data.Scientific as Scientific
132−import qualified Data.Semigroup as Semigroup
133−import qualified Data.Sequence as Seq
113+import qualified Data.Sequence as Seq
134−import qualified Data.Set as Set
114+import qualified Data.Set as Set
135−import qualified Data.Text as T
115+import qualified Data.Text as T
136−import qualified Data.Text.Encoding as T
137−import qualified Data.Text.Lazy as LT
116+import qualified Data.Text.Lazy as LT
138−import qualified Data.Tree as Tree
117+import qualified Data.Text.Read as TR
139−import qualified Data.UUID.Types as UUID
118+import qualified Data.Tree as Tree
140−import qualified Data.Vector as V
119+import qualified Data.Vector as V
141−import qualified Data.Vector.Generic as VG
120+import qualified Data.Vector.Generic as VG
142import qualified Data.Vector.Primitive as VP
121import qualified Data.Vector.Primitive as VP
143−import qualified Data.Vector.Storable as VS
122+import qualified Data.Vector.Storable as VS
144−import qualified Data.Vector.Unboxed as VU
123+import qualified Data.Vector.Unboxed as VU
145
124
146−import qualified GHC.Exts as Exts
125+import Unsafe.Coerce (unsafeCoerce)
147−import qualified Data.Primitive.Array as PM
148−import qualified Data.Primitive.SmallArray as PM
149−import qualified Data.Primitive.Types as PM
150
126
151−#if MIN_VERSION_primitive(0,6,4)
127+-- Coercible derivations aren't as powerful on GHC 7.8, though supported.
152−#if !MIN_VERSION_primitive(0,7,0)
128+#ifndef HAS_COERCIBLE
153−import qualified Data.Primitive.UnliftedArray as PM
129+#define HAS_COERCIBLE (__GLASGOW_HASKELL__ >= 709)
154#endif
130#endif
155−import qualified Data.Primitive.PrimArray as PM
156−#endif
157−
158
131
132+#if HAS_COERCIBLE
159import Data.Coerce (Coercible, coerce)
133import Data.Coerce (Coercible, coerce)
134+coerce' :: Coercible a b => a -> b
135+coerce' = coerce
136+#else
137+coerce' :: a -> b
138+coerce' = unsafeCoerce
139+#endif
160
140
161parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
141parseIndexedJSON :: (Value -> Parser a) -> Int -> Value -> Parser a
162parseIndexedJSON p idx value = p value <?> Index idx
142parseIndexedJSON p idx value = p value <?> Index idx
@@ -165,7 +145,7 @@ parseIndexedJSON p idx value = p value <?> Index idx
165parseIndexedJSONPair :: (Value -> Parser a) -> (Value -> Parser b) -> Int -> Value -> Parser (a, b)
145parseIndexedJSONPair :: (Value -> Parser a) -> (Value -> Parser b) -> Int -> Value -> Parser (a, b)
166parseIndexedJSONPair keyParser valParser idx value = p value <?> Index idx
146parseIndexedJSONPair keyParser valParser idx value = p value <?> Index idx
167 where
147 where
168− p = withArray "(k, v)" $ \ab ->
148+ p = withArray "(k,v)" $ \ab ->
169 let n = V.length ab
149 let n = V.length ab
170 in if n == 2
150 in if n == 2
171 then (,) <$> parseJSONElemAtIndex keyParser 0 ab
151 then (,) <$> parseJSONElemAtIndex keyParser 0 ab
@@ -177,58 +157,25 @@ parseIndexedJSONPair keyParser valParser idx value = p value <?> Index idx
177parseJSONElemAtIndex :: (Value -> Parser a) -> Int -> V.Vector Value -> Parser a
157parseJSONElemAtIndex :: (Value -> Parser a) -> Int -> V.Vector Value -> Parser a
178parseJSONElemAtIndex p idx ary = p (V.unsafeIndex ary idx) <?> Index idx
158parseJSONElemAtIndex p idx ary = p (V.unsafeIndex ary idx) <?> Index idx
179
159
160+scientificToNumber :: Scientific -> Number
161+scientificToNumber s
162+ | e < 0 = D $ Scientific.toRealFloat s
163+ | otherwise = I $ c * 10 ^ e
164+ where
165+ e = Scientific.base10Exponent s
166+ c = Scientific.coefficient s
167+{-# INLINE scientificToNumber #-}
168+
180parseRealFloat :: RealFloat a => String -> Value -> Parser a
169parseRealFloat :: RealFloat a => String -> Value -> Parser a
181−parseRealFloat _ (Number s) = pure $ Scientific.toRealFloat s
170+parseRealFloat _ (Number s) = pure $ Scientific.toRealFloat s
182−parseRealFloat _ Null = pure (0/0)
171+parseRealFloat _ Null = pure (0/0)
183−parseRealFloat name v = prependContext name (unexpected v)
172+parseRealFloat expected v = typeMismatch expected v
184{-# INLINE parseRealFloat #-}
173{-# INLINE parseRealFloat #-}
185
174
186−parseIntegralFromScientific :: forall a. Integral a => Scientific -> Parser a
187−parseIntegralFromScientific s =
188− case Scientific.floatingOrInteger s :: Either Double a of
189− Right x -> pure x
190− Left _ -> fail $ "unexpected floating number " ++ show s
191−{-# INLINE parseIntegralFromScientific #-}
192−
193parseIntegral :: Integral a => String -> Value -> Parser a
175parseIntegral :: Integral a => String -> Value -> Parser a
194−parseIntegral name =
176+parseIntegral expected = withScientific expected $ pure . truncate
195− prependContext name . withBoundedScientific' parseIntegralFromScientific
196{-# INLINE parseIntegral #-}
177{-# INLINE parseIntegral #-}
197
178
198−parseBoundedIntegralFromScientific :: (Bounded a, Integral a) => Scientific -> Parser a
199−parseBoundedIntegralFromScientific s = maybe
200− (fail $ "value is either floating or will cause over or underflow " ++ show s)
201− pure
202− (Scientific.toBoundedInteger s)
203−{-# INLINE parseBoundedIntegralFromScientific #-}
204−
205−parseBoundedIntegral :: (Bounded a, Integral a) => String -> Value -> Parser a
206−parseBoundedIntegral name =
207− prependContext name . withScientific' parseBoundedIntegralFromScientific
208−{-# INLINE parseBoundedIntegral #-}
209−
210−parseScientificText :: Text -> Parser Scientific
211−parseScientificText
212− = either fail pure
213− . A.parseOnly (A.scientific <* A.endOfInput)
214− . T.encodeUtf8
215−
216−parseIntegralText :: Integral a => String -> Text -> Parser a
217−parseIntegralText name t =
218− prependContext name $
219− parseScientificText t
220− >>= rejectLargeExponent
221− >>= parseIntegralFromScientific
222− where
223− rejectLargeExponent :: Scientific -> Parser Scientific
224− rejectLargeExponent s = withBoundedScientific' pure (Number s)
225−{-# INLINE parseIntegralText #-}
226−
227−parseBoundedIntegralText :: (Bounded a, Integral a) => String -> Text -> Parser a
228−parseBoundedIntegralText name t =
229− prependContext name $
230− parseScientificText t >>= parseBoundedIntegralFromScientific
231−
232parseOptionalFieldWith :: (Value -> Parser (Maybe a))
179parseOptionalFieldWith :: (Value -> Parser (Maybe a))
233 -> Object -> Text -> Parser (Maybe a)
180 -> Object -> Text -> Parser (Maybe a)
234parseOptionalFieldWith pj obj key =
181parseOptionalFieldWith pj obj key =
@@ -246,21 +193,16 @@ class GFromJSON arity f where
246 -- | This method (applied to 'defaultOptions') is used as the
193 -- | This method (applied to 'defaultOptions') is used as the
247 -- default generic implementation of 'parseJSON' (if the @arity@ is 'Zero')
194 -- default generic implementation of 'parseJSON' (if the @arity@ is 'Zero')
248 -- or 'liftParseJSON' (if the @arity@ is 'One').
195 -- or 'liftParseJSON' (if the @arity@ is 'One').
249− gParseJSON :: Options -> FromArgs arity a -> Value -> Parser (f a)
196+ gParseJSON :: Options -> Proxy arity
250−
251−-- | A 'FromArgs' value either stores nothing (for 'FromJSON') or it stores the
252−-- two function arguments that decode occurrences of the type parameter (for
253−-- 'FromJSON1').
254−data FromArgs arity a where
255− NoFromArgs :: FromArgs Zero a
256− From1Args :: (Value -> Parser a) -> (Value -> Parser [a]) -> FromArgs One a
197+ -> (Value -> Parser a) -> (Value -> Parser [a])
198+ -> Value -> Parser (f a)
257
199
258-- | A configurable generic JSON decoder. This function applied to
200-- | A configurable generic JSON decoder. This function applied to
259-- 'defaultOptions' is used as the default for 'parseJSON' when the
201-- 'defaultOptions' is used as the default for 'parseJSON' when the
260-- type is an instance of 'Generic'.
202-- type is an instance of 'Generic'.
261genericParseJSON :: (Generic a, GFromJSON Zero (Rep a))
203genericParseJSON :: (Generic a, GFromJSON Zero (Rep a))
262 => Options -> Value -> Parser a
204 => Options -> Value -> Parser a
263−genericParseJSON opts = fmap to . gParseJSON opts NoFromArgs
205+genericParseJSON opts = fmap to . gParseJSON opts proxyZero undefined undefined
264
206
265-- | A configurable generic JSON decoder. This function applied to
207-- | A configurable generic JSON decoder. This function applied to
266-- 'defaultOptions' is used as the default for 'liftParseJSON' when the
208-- 'defaultOptions' is used as the default for 'liftParseJSON' when the
@@ -268,7 +210,7 @@ genericParseJSON opts = fmap to . gParseJSON opts NoFromArgs
268genericLiftParseJSON :: (Generic1 f, GFromJSON One (Rep1 f))
210genericLiftParseJSON :: (Generic1 f, GFromJSON One (Rep1 f))
269 => Options -> (Value -> Parser a) -> (Value -> Parser [a])
211 => Options -> (Value -> Parser a) -> (Value -> Parser [a])
270 -> Value -> Parser (f a)
212 -> Value -> Parser (f a)
271−genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
213+genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts proxyOne pj pjl
272
214
273-------------------------------------------------------------------------------
215-------------------------------------------------------------------------------
274-- Class
216-- Class
@@ -287,21 +229,14 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
287--
229--
288-- The basic ways to signal a failed conversion are as follows:
230-- The basic ways to signal a failed conversion are as follows:
289--
231--
290−-- * 'fail' yields a custom error message: it is the recommended way of
291−-- reporting a failure;
292−--
293−-- * 'Control.Applicative.empty' (or 'Control.Monad.mzero') is uninformative:
232+-- * 'empty' and 'mzero' work, but are terse and uninformative
294−-- use it when the error is meant to be caught by some @('<|>')@;
295--
233--
296−-- * 'typeMismatch' can be used to report a failure when the encountered value
234+-- * 'fail' yields a custom error message
297−-- is not of the expected JSON type; 'unexpected' is an appropriate alternative
298−-- when more than one type may be expected, or to keep the expected type
299−-- implicit.
300--
235--
301−-- 'prependFailure' (or 'modifyFailure') add more information to a parser's
236+-- * 'typeMismatch' produces an informative message for cases when the
302−-- error messages.
237+-- value encountered is not of the expected type
303--
238--
304−-- An example type and instance using 'typeMismatch' and 'prependFailure':
239+-- An example type and instance:
305--
240--
306-- @
241-- @
307-- \-- Allow ourselves to write 'Text' literals.
242-- \-- Allow ourselves to write 'Text' literals.
@@ -309,30 +244,15 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
309--
244--
310-- data Coord = Coord { x :: Double, y :: Double }
245-- data Coord = Coord { x :: Double, y :: Double }
311--
246--
312−-- instance 'FromJSON' Coord where
247+-- instance FromJSON Coord where
313−-- 'parseJSON' ('Object' v) = Coord
248+-- parseJSON ('Object' v) = Coord '<$>'
314−-- '<$>' v '.:' \"x\"
249+-- v '.:' \"x\" '<*>'
315−-- '<*>' v '.:' \"y\"
250+-- v '.:' \"y\"
316--
251--
317−-- \-- We do not expect a non-'Object' value here.
252+-- \-- We do not expect a non-'Object' value here.
318−-- \-- We could use 'Control.Applicative.empty' to fail, but 'typeMismatch'
253+-- \-- We could use 'mzero' to fail, but 'typeMismatch'
319−-- \-- gives a much more informative error message.
254+-- \-- gives a much more informative error message.
320−-- 'parseJSON' invalid =
255+-- parseJSON invalid = 'typeMismatch' \"Coord\" invalid
321−-- 'prependFailure' "parsing Coord failed, "
322−-- ('typeMismatch' \"Object\" invalid)
323−-- @
324−--
325−-- For this common case of only being concerned with a single
326−-- type of JSON value, the functions 'withObject', 'withScientific', etc.
327−-- are provided. Their use is to be preferred when possible, since
328−-- they are more terse. Using 'withObject', we can rewrite the above instance
329−-- (assuming the same language extension and data type) as:
330−--
331−-- @
332−-- instance 'FromJSON' Coord where
333−-- 'parseJSON' = 'withObject' \"Coord\" $ \\v -> Coord
334−-- '<$>' v '.:' \"x\"
335−-- '<*>' v '.:' \"y\"
336-- @
256-- @
337--
257--
338-- Instead of manually writing your 'FromJSON' instance, there are two options
258-- Instead of manually writing your 'FromJSON' instance, there are two options
@@ -340,7 +260,7 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
340--
260--
341-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
261-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
342-- instance at compile time. The generated instance is optimized for your type
262-- instance at compile time. The generated instance is optimized for your type
343−-- so it will probably be more efficient than the following option.
263+-- so will probably be more efficient than the following two options:
344--
264--
345-- * The compiler can provide a default generic implementation for
265-- * The compiler can provide a default generic implementation for
346-- 'parseJSON'.
266-- 'parseJSON'.
@@ -358,21 +278,18 @@ genericLiftParseJSON opts pj pjl = fmap to1 . gParseJSON opts (From1Args pj pjl)
358--
278--
359-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'
279-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'
360--
280--
361−-- instance 'FromJSON' Coord
281+-- instance FromJSON Coord
362-- @
282-- @
363--
283--
364−-- The default implementation will be equivalent to
284+-- If @DefaultSignatures@ doesn't give exactly the results you want,
365−-- @parseJSON = 'genericParseJSON' 'defaultOptions'@; if you need different
366−-- options, you can customize the generic decoding by defining:
285+-- you can customize the generic decoding with only a tiny amount of
286+-- effort, using 'genericParseJSON' with your preferred 'Options':
367--
287--
368-- @
288-- @
369−-- customOptions = 'defaultOptions'
370−-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
371−-- }
372−--
373−-- instance 'FromJSON' Coord where
289+-- instance FromJSON Coord where
374−-- 'parseJSON' = 'genericParseJSON' customOptions
290+-- parseJSON = 'genericParseJSON' 'defaultOptions'
375-- @
291-- @
292+
376class FromJSON a where
293class FromJSON a where
377 parseJSON :: Value -> Parser a
294 parseJSON :: Value -> Parser a
378
295
@@ -380,181 +297,111 @@ class FromJSON a where
380 parseJSON = genericParseJSON defaultOptions
297 parseJSON = genericParseJSON defaultOptions
381
298
382 parseJSONList :: Value -> Parser [a]
299 parseJSONList :: Value -> Parser [a]
383− parseJSONList = withArray "[]" $ \a ->
300+ parseJSONList (Array a)
301+ = sequence
384− zipWithM (parseIndexedJSON parseJSON) [0..]
302+ . zipWith (parseIndexedJSON parseJSON) [0..]
385 . V.toList
303 . V.toList
386 $ a
304 $ a
387
305
306+ parseJSONList v = typeMismatch "[a]" v
307+
388-------------------------------------------------------------------------------
308-------------------------------------------------------------------------------
389-- Classes and types for map keys
309-- Classes and types for map keys
390-------------------------------------------------------------------------------
310-------------------------------------------------------------------------------
391
311
392−-- | Read the docs for 'ToJSONKey' first. This class is a conversion
393−-- in the opposite direction. If you have a newtype wrapper around 'Text',
394−-- the recommended way to define instances is with generalized newtype deriving:
395−--
396−-- > newtype SomeId = SomeId { getSomeId :: Text }
397−-- > deriving (Eq,Ord,Hashable,FromJSONKey)
398−--
399−-- If you have a sum of nullary constructors, you may use the generic
400−-- implementation:
401−--
402−-- @
403−-- data Color = Red | Green | Blue
404−-- deriving Generic
405−--
406−-- instance 'FromJSONKey' Color where
407−-- 'fromJSONKey' = 'genericFromJSONKey' 'defaultJSONKeyOptions'
408−-- @
409class FromJSONKey a where
312class FromJSONKey a where
410− -- | Strategy for parsing the key of a map-like container.
411 fromJSONKey :: FromJSONKeyFunction a
313 fromJSONKey :: FromJSONKeyFunction a
412 default fromJSONKey :: FromJSON a => FromJSONKeyFunction a
314 default fromJSONKey :: FromJSON a => FromJSONKeyFunction a
413 fromJSONKey = FromJSONKeyValue parseJSON
315 fromJSONKey = FromJSONKeyValue parseJSON
414−
415− -- | This is similar in spirit to the 'readList' method of 'Read'.
416− -- It makes it possible to give 'String' keys special treatment
417− -- without using @OverlappingInstances@. End users should always
418− -- be able to use the default implementation of this method.
419 fromJSONKeyList :: FromJSONKeyFunction [a]
316 fromJSONKeyList :: FromJSONKeyFunction [a]
420 default fromJSONKeyList :: FromJSON a => FromJSONKeyFunction [a]
317 default fromJSONKeyList :: FromJSON a => FromJSONKeyFunction [a]
421 fromJSONKeyList = FromJSONKeyValue parseJSON
318 fromJSONKeyList = FromJSONKeyValue parseJSON
422
319
423−-- | With GHC 7.8+ we carry around @'Coercible' 'Text' a@ dictionary,
320+-- | With GHC 7.8 + we carry around 'Coercible Text a' dictionary,
424−-- to give us an assurance that the program will not segfault.
321+-- to have even some amount of safety net.
425−-- Unfortunately we cannot enforce that the 'Eq' instances or the
322+-- Unfortunately we cannot enforce that 'Hashable' instance agree on the type level
426−-- 'Hashable' instances for 'Text' and @a@ agree.
427--
323--
428−-- At the moment this type is intentionally not exported. 'FromJSONKeyFunction'
324+-- ATM this type is intentionally not exported. FromJSONKeyFunction can be inspected,
429−-- can be inspected, but cannot be constructed.
325+-- but cannot be constructed.
430data CoerceText a where
326data CoerceText a where
327+#if HAS_COERCIBLE
431 CoerceText :: Coercible Text a => CoerceText a
328 CoerceText :: Coercible Text a => CoerceText a
329+#else
330+ CoerceText :: CoerceText a
331+#endif
432
332
433−-- | This type is related to 'ToJSONKeyFunction'. If 'FromJSONKeyValue' is used in the
434−-- 'FromJSONKey' instance, then 'ToJSONKeyValue' should be used in the 'ToJSONKey'
435−-- instance. The other three data constructors for this type all correspond to
436−-- 'ToJSONKeyText'. Strictly speaking, 'FromJSONKeyTextParser' is more powerful than
437−-- 'FromJSONKeyText', which is in turn more powerful than 'FromJSONKeyCoerce'.
438−-- For performance reasons, these exist as three options instead of one.
439data FromJSONKeyFunction a
333data FromJSONKeyFunction a
440− = FromJSONKeyCoerce !(CoerceText a)
334+ = FromJSONKeyCoerce (CoerceText a)
441− -- ^ uses 'coerce' ('unsafeCoerce' in older GHCs)
442− | FromJSONKeyText !(Text -> a)
335+ | FromJSONKeyText (Text -> a)
443− -- ^ conversion from 'Text' that always succeeds
444− | FromJSONKeyTextParser !(Text -> Parser a)
336+ | FromJSONKeyTextParser (Text -> Parser a)
445− -- ^ conversion from 'Text' that may fail
446− | FromJSONKeyValue !(Value -> Parser a)
337+ | FromJSONKeyValue (Value -> Parser a)
447− -- ^ conversion for non-textual keys
338+
448−
449−-- | Only law abiding up to interpretation
450instance Functor FromJSONKeyFunction where
339instance Functor FromJSONKeyFunction where
451− fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce)
340+ fmap h (FromJSONKeyCoerce CoerceText) = FromJSONKeyText (h . coerce')
452 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
341 fmap h (FromJSONKeyText f) = FromJSONKeyText (h . f)
453 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
342 fmap h (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap h . f)
454 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
343 fmap h (FromJSONKeyValue f) = FromJSONKeyValue (fmap h . f)
455
344
456-- | Construct 'FromJSONKeyFunction' for types coercible from 'Text'. This
345-- | Construct 'FromJSONKeyFunction' for types coercible from 'Text'. This
457-- conversion is still unsafe, as 'Hashable' and 'Eq' instances of @a@ should be
346-- conversion is still unsafe, as 'Hashable' and 'Eq' instances of @a@ should be
458−-- compatible with 'Text' i.e. hash values should be equal for wrapped values as well.
459−-- This property will always be maintained if the 'Hashable' and 'Eq' instances
460−-- are derived with generalized newtype deriving.
461-- compatible with 'Text' i.e. hash values be equal for wrapped values as well.
347-- compatible with 'Text' i.e. hash values be equal for wrapped values as well.
462−--
463−-- On pre GHC 7.8 this is unconstrainted function.
464fromJSONKeyCoerce ::
348fromJSONKeyCoerce ::
349+#if HAS_COERCIBLE
465 Coercible Text a =>
350 Coercible Text a =>
351+#endif
466 FromJSONKeyFunction a
352 FromJSONKeyFunction a
467fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
353fromJSONKeyCoerce = FromJSONKeyCoerce CoerceText
468
354
469−-- | Semantically the same as @coerceFromJSONKeyFunction = fmap coerce = coerce@.
470−--
471−-- See note on 'fromJSONKeyCoerce'.
472coerceFromJSONKeyFunction ::
355coerceFromJSONKeyFunction ::
356+#if HAS_COERCIBLE
473 Coercible a b =>
357 Coercible a b =>
358+#endif
474 FromJSONKeyFunction a -> FromJSONKeyFunction b
359 FromJSONKeyFunction a -> FromJSONKeyFunction b
475−coerceFromJSONKeyFunction = coerce
360+coerceFromJSONKeyFunction (FromJSONKeyCoerce CoerceText) = FromJSONKeyCoerce CoerceText
361+coerceFromJSONKeyFunction (FromJSONKeyText f) = FromJSONKeyText (coerce' . f)
362+coerceFromJSONKeyFunction (FromJSONKeyTextParser f) = FromJSONKeyTextParser (fmap coerce' . f)
363+coerceFromJSONKeyFunction (FromJSONKeyValue f) = FromJSONKeyValue (fmap coerce' . f)
476
364
477{-# RULES
365{-# RULES
478 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
366 "FromJSONKeyCoerce: fmap id" forall (x :: FromJSONKeyFunction a).
479 fmap id x = x
367 fmap id x = x
480 #-}
368 #-}
369+#if HAS_COERCIBLE
481{-# RULES
370{-# RULES
482 "FromJSONKeyCoerce: fmap coerce" forall x .
371 "FromJSONKeyCoerce: fmap coerce" forall x .
483 fmap coerce x = coerceFromJSONKeyFunction x
372 fmap coerce x = coerceFromJSONKeyFunction x
484 #-}
373 #-}
374+#endif
485
375
486−-- | Same as 'fmap'. Provided for the consistency with 'ToJSONKeyFunction'.
487mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
376mapFromJSONKeyFunction :: (a -> b) -> FromJSONKeyFunction a -> FromJSONKeyFunction b
488mapFromJSONKeyFunction = fmap
377mapFromJSONKeyFunction = fmap
489
378
490−-- | 'fromJSONKey' for 'Generic' types.
491−-- These types must be sums of nullary constructors, whose names will be used
492−-- as keys for JSON objects.
493−--
494−-- See also 'genericToJSONKey'.
495−--
496−-- === __Example__
497−--
498−-- @
499−-- data Color = Red | Green | Blue
500−-- deriving 'Generic'
501−--
502−-- instance 'FromJSONKey' Color where
503−-- 'fromJSONKey' = 'genericFromJSONKey' 'defaultJSONKeyOptions'
504−-- @
505−genericFromJSONKey :: forall a. (Generic a, GFromJSONKey (Rep a))
506− => JSONKeyOptions
507− -> FromJSONKeyFunction a
508−genericFromJSONKey opts = FromJSONKeyTextParser $ \t ->
509− case parseSumFromString (keyModifier opts) t of
510− Nothing -> fail $
511− "invalid key " ++ show t ++ ", expected one of " ++ show cnames
512− Just k -> pure (to k)
513− where
514− cnames = unTagged2 (constructorTags (keyModifier opts) :: Tagged2 (Rep a) [String])
515−
516−class (ConstructorNames f, SumFromString f) => GFromJSONKey f where
517−instance (ConstructorNames f, SumFromString f) => GFromJSONKey f where
518−
519-------------------------------------------------------------------------------
379-------------------------------------------------------------------------------
520-- Functions needed for documentation
380-- Functions needed for documentation
521-------------------------------------------------------------------------------
381-------------------------------------------------------------------------------
522
382
523-- | Fail parsing due to a type mismatch, with a descriptive message.
383-- | Fail parsing due to a type mismatch, with a descriptive message.
524--
384--
525−-- The following wrappers should generally be prefered:
385+-- Example usage:
526−-- 'withObject', 'withArray', 'withText', 'withBool'.
527−--
528−-- ==== Error message example
529--
386--
530−-- > typeMismatch "Object" (String "oops")
387+-- @
531−-- > -- Error: "expected Object, but encountered String"
388+-- instance FromJSON Coord where
389+-- parseJSON ('Object' v) = {- type matches, life is good -}
390+-- parseJSON wat = 'typeMismatch' \"Coord\" wat
391+-- @
532−typeMismatch :: String -- ^ The name of the JSON type being parsed
392+typeMismatch :: String -- ^ The name of the type you are trying to parse.
533− -- (@\"Object\"@, @\"Array\"@, @\"String\"@, @\"Number\"@,
534− -- @\"Boolean\"@, or @\"Null\"@).
535 -> Value -- ^ The actual value encountered.
393 -> Value -- ^ The actual value encountered.
536 -> Parser a
394 -> Parser a
537typeMismatch expected actual =
395typeMismatch expected actual =
538− fail $ "expected " ++ expected ++ ", but encountered " ++ typeOf actual
396+ fail $ "expected " ++ expected ++ ", encountered " ++ name
539−
397+ where
540−-- | Fail parsing due to a type mismatch, when the expected types are implicit.
541−--
542−-- ==== Error message example
543−--
544−-- > unexpected (String "oops")
545−-- > -- Error: "unexpected String"
546−unexpected :: Value -> Parser a
547−unexpected actual = fail $ "unexpected " ++ typeOf actual
548−
549−-- | JSON type of a value, name of the head constructor.
550−typeOf :: Value -> String
551−typeOf v = case v of
398+ name = case actual of
552− Object _ -> "Object"
399+ Object _ -> "Object"
553− Array _ -> "Array"
400+ Array _ -> "Array"
554− String _ -> "String"
401+ String _ -> "String"
555− Number _ -> "Number"
402+ Number _ -> "Number"
556− Bool _ -> "Boolean"
403+ Bool _ -> "Boolean"
557− Null -> "Null"
404+ Null -> "Null"
558
405
559-------------------------------------------------------------------------------
406-------------------------------------------------------------------------------
560-- Lifings of FromJSON and ToJSON to unary and binary type constructors
407-- Lifings of FromJSON and ToJSON to unary and binary type constructors
@@ -567,7 +414,7 @@ typeOf v = case v of
567--
414--
568-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
415-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
569-- instance at compile time. The generated instance is optimized for your type
416-- instance at compile time. The generated instance is optimized for your type
570−-- so it will probably be more efficient than the following option.
417+-- so will probably be more efficient than the following two options:
571--
418--
572-- * The compiler can provide a default generic implementation for
419-- * The compiler can provide a default generic implementation for
573-- 'liftParseJSON'.
420-- 'liftParseJSON'.
@@ -585,20 +432,16 @@ typeOf v = case v of
585--
432--
586-- data Pair a b = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'
433-- data Pair a b = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'
587--
434--
588−-- instance 'FromJSON' a => 'FromJSON1' (Pair a)
435+-- instance FromJSON a => FromJSON1 (Pair a)
589-- @
436-- @
590--
437--
591−-- If the default implementation doesn't give exactly the results you want,
438+-- If @DefaultSignatures@ doesn't give exactly the results you want,
592-- you can customize the generic decoding with only a tiny amount of
439-- you can customize the generic decoding with only a tiny amount of
593-- effort, using 'genericLiftParseJSON' with your preferred 'Options':
440-- effort, using 'genericLiftParseJSON' with your preferred 'Options':
594--
441--
595-- @
442-- @
596−-- customOptions = 'defaultOptions'
597−-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
598−-- }
599−--
600−-- instance 'FromJSON' a => 'FromJSON1' (Pair a) where
443+-- instance FromJSON a => FromJSON1 (Pair a) where
601−-- 'liftParseJSON' = 'genericLiftParseJSON' customOptions
444+-- liftParseJSON = 'genericLiftParseJSON' 'defaultOptions'
602-- @
445-- @
603class FromJSON1 f where
446class FromJSON1 f where
604 liftParseJSON :: (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
447 liftParseJSON :: (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
@@ -635,8 +478,9 @@ class FromJSON2 f where
635 -> (Value -> Parser b)
478 -> (Value -> Parser b)
636 -> (Value -> Parser [b])
479 -> (Value -> Parser [b])
637 -> Value -> Parser [f a b]
480 -> Value -> Parser [f a b]
638− liftParseJSONList2 fa ga fb gb = withArray "[]" $ \vals ->
481+ liftParseJSONList2 fa ga fb gb v = case v of
639− fmap V.toList (V.mapM (liftParseJSON2 fa ga fb gb) vals)
482+ Array vals -> fmap V.toList (V.mapM (liftParseJSON2 fa ga fb gb) vals)
483+ _ -> typeMismatch "[a]" v
640
484
641-- | Lift the standard 'parseJSON' function through the type constructor.
485-- | Lift the standard 'parseJSON' function through the type constructor.
642parseJSON2 :: (FromJSON2 f, FromJSON a, FromJSON b) => Value -> Parser (f a b)
486parseJSON2 :: (FromJSON2 f, FromJSON a, FromJSON b) => Value -> Parser (f a b)
@@ -647,10 +491,9 @@ parseJSON2 = liftParseJSON2 parseJSON parseJSONList parseJSON parseJSONList
647-- List functions
491-- List functions
648-------------------------------------------------------------------------------
492-------------------------------------------------------------------------------
649
493
650−-- | Helper function to use with 'liftParseJSON'. See 'Data.Aeson.ToJSON.listEncoding'.
651listParser :: (Value -> Parser a) -> Value -> Parser [a]
494listParser :: (Value -> Parser a) -> Value -> Parser [a]
652listParser f (Array xs) = fmap V.toList (V.mapM f xs)
495listParser f (Array xs) = fmap V.toList (V.mapM f xs)
653−listParser _ v = typeMismatch "Array" v
496+listParser _ v = typeMismatch "[a]" v
654{-# INLINE listParser #-}
497{-# INLINE listParser #-}
655
498
656-------------------------------------------------------------------------------
499-------------------------------------------------------------------------------
@@ -668,139 +511,48 @@ instance (FromJSON a) => FromJSON [a] where
668-- Functions
511-- Functions
669-------------------------------------------------------------------------------
512-------------------------------------------------------------------------------
670
513
671−-- | Add context to a failure message, indicating the name of the structure
672−-- being parsed.
673−--
674−-- > prependContext "MyType" (fail "[error message]")
675−-- > -- Error: "parsing MyType failed, [error message]"
676−prependContext :: String -> Parser a -> Parser a
677−prependContext name = prependFailure ("parsing " ++ name ++ " failed, ")
678−
679−-- | @'withObject' name f value@ applies @f@ to the 'Object' when @value@
514+-- | @withObject expected f value@ applies @f@ to the 'Object' when @value@ is an @Object@
680−-- is an 'Data.Aeson.Object' and fails otherwise.
515+-- and fails using @'typeMismatch' expected@ otherwise.
681−--
682−-- ==== Error message example
683−--
684−-- > withObject "MyType" f (String "oops")
685−-- > -- Error: "parsing MyType failed, expected Object, but encountered String"
686withObject :: String -> (Object -> Parser a) -> Value -> Parser a
516withObject :: String -> (Object -> Parser a) -> Value -> Parser a
687−withObject _ f (Object obj) = f obj
517+withObject _ f (Object obj) = f obj
688−withObject name _ v = prependContext name (typeMismatch "Object" v)
518+withObject expected _ v = typeMismatch expected v
689{-# INLINE withObject #-}
519{-# INLINE withObject #-}
690
520
691−-- | @'withText' name f value@ applies @f@ to the 'Text' when @value@ is a
521+-- | @withText expected f value@ applies @f@ to the 'Text' when @value@ is a @String@
692−-- 'Data.Aeson.String' and fails otherwise.
522+-- and fails using @'typeMismatch' expected@ otherwise.
693−--
694−-- ==== Error message example
695−--
696−-- > withText "MyType" f Null
697−-- > -- Error: "parsing MyType failed, expected String, but encountered Null"
698withText :: String -> (Text -> Parser a) -> Value -> Parser a
523withText :: String -> (Text -> Parser a) -> Value -> Parser a
699−withText _ f (String txt) = f txt
524+withText _ f (String txt) = f txt
700−withText name _ v = prependContext name (typeMismatch "String" v)
525+withText expected _ v = typeMismatch expected v
701{-# INLINE withText #-}
526{-# INLINE withText #-}
702
527
703−-- | @'withArray' expected f value@ applies @f@ to the 'Array' when @value@ is
528+-- | @withArray expected f value@ applies @f@ to the 'Array' when @value@ is an @Array@
704−-- an 'Data.Aeson.Array' and fails otherwise.
529+-- and fails using @'typeMismatch' expected@ otherwise.
705−--
706−-- ==== Error message example
707−--
708−-- > withArray "MyType" f (String "oops")
709−-- > -- Error: "parsing MyType failed, expected Array, but encountered String"
710withArray :: String -> (Array -> Parser a) -> Value -> Parser a
530withArray :: String -> (Array -> Parser a) -> Value -> Parser a
711−withArray _ f (Array arr) = f arr
531+withArray _ f (Array arr) = f arr
712−withArray name _ v = prependContext name (typeMismatch "Array" v)
532+withArray expected _ v = typeMismatch expected v
713{-# INLINE withArray #-}
533{-# INLINE withArray #-}
714
534
535+-- | @withNumber expected f value@ applies @f@ to the 'Number' when @value@ is a 'Number'.
536+-- and fails using @'typeMismatch' expected@ otherwise.
537+withNumber :: String -> (Number -> Parser a) -> Value -> Parser a
538+withNumber expected f = withScientific expected (f . scientificToNumber)
539+{-# INLINE withNumber #-}
540+{-# DEPRECATED withNumber "Use withScientific instead" #-}
541+
715−-- | @'withScientific' name f value@ applies @f@ to the 'Scientific' number
542+-- | @withScientific expected f value@ applies @f@ to the 'Scientific' number when @value@ is a 'Number'.
716−-- when @value@ is a 'Data.Aeson.Number' and fails using 'typeMismatch'
543+-- and fails using @'typeMismatch' expected@ otherwise.
717−-- otherwise.
718−--
719−-- /Warning/: If you are converting from a scientific to an unbounded
720−-- type such as 'Integer' you may want to add a restriction on the
721−-- size of the exponent (see 'withBoundedScientific') to prevent
722−-- malicious input from filling up the memory of the target system.
723−--
724−-- ==== Error message example
725−--
726−-- > withScientific "MyType" f (String "oops")
727−-- > -- Error: "parsing MyType failed, expected Number, but encountered String"
728withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a
544withScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a
729−withScientific _ f (Number scientific) = f scientific
545+withScientific _ f (Number scientific) = f scientific
730−withScientific name _ v = prependContext name (typeMismatch "Number" v)
546+withScientific expected _ v = typeMismatch expected v
731{-# INLINE withScientific #-}
547{-# INLINE withScientific #-}
732
548
733−-- | A variant of 'withScientific' which doesn't use 'prependContext', so that
549+-- | @withBool expected f value@ applies @f@ to the 'Bool' when @value@ is a @Bool@
734−-- such context can be added separately in a way that also applies when the
735−-- continuation @f :: Scientific -> Parser a@ fails.
736−--
737−-- /Warning/: If you are converting from a scientific to an unbounded
738−-- type such as 'Integer' you may want to add a restriction on the
739−-- size of the exponent (see 'withBoundedScientific') to prevent
740−-- malicious input from filling up the memory of the target system.
741−--
742−-- ==== Error message examples
743−--
744−-- > withScientific' f (String "oops")
745−-- > -- Error: "unexpected String"
746−-- >
747−-- > prependContext "MyType" (withScientific' f (String "oops"))
748−-- > -- Error: "parsing MyType failed, unexpected String"
749−withScientific' :: (Scientific -> Parser a) -> Value -> Parser a
750−withScientific' f v = case v of
751− Number n -> f n
752− _ -> typeMismatch "Number" v
753−{-# INLINE withScientific' #-}
754−
755−-- | @'withBoundedScientific' name f value@ applies @f@ to the 'Scientific' number
756−-- when @value@ is a 'Number' with exponent less than or equal to 1024.
757−withBoundedScientific :: String -> (Scientific -> Parser a) -> Value -> Parser a
758−withBoundedScientific name f v = withBoundedScientific_ (prependContext name) f v
759−{-# INLINE withBoundedScientific #-}
760−
761−-- | A variant of 'withBoundedScientific' which doesn't use 'prependContext',
762−-- so that such context can be added separately in a way that also applies
763−-- when the continuation @f :: Scientific -> Parser a@ fails.
764−withBoundedScientific' :: (Scientific -> Parser a) -> Value -> Parser a
765−withBoundedScientific' f v = withBoundedScientific_ id f v
766−{-# INLINE withBoundedScientific' #-}
767−
768−-- | A variant of 'withBoundedScientific_' parameterized by a function to apply
769−-- to the 'Parser' in case of failure.
770−withBoundedScientific_ :: (Parser a -> Parser a) -> (Scientific -> Parser a) -> Value -> Parser a
771−withBoundedScientific_ whenFail f (Number scientific) =
772− if exp10 > 1024
773− then whenFail (fail msg)
774− else f scientific
775− where
776− exp10 = base10Exponent scientific
777− msg = "found a number with exponent " ++ show exp10 ++ ", but it must not be greater than 1024"
778−withBoundedScientific_ whenFail _ v =
779− whenFail (typeMismatch "Number" v)
780−{-# INLINE withBoundedScientific_ #-}
781−
782−-- | @'withBool' expected f value@ applies @f@ to the 'Bool' when @value@ is a
783−-- 'Boolean' and fails otherwise.
550+-- and fails using @'typeMismatch' expected@ otherwise.
784−--
785−-- ==== Error message example
786−--
787−-- > withBool "MyType" f (String "oops")
788−-- > -- Error: "parsing MyType failed, expected Boolean, but encountered String"
789withBool :: String -> (Bool -> Parser a) -> Value -> Parser a
551withBool :: String -> (Bool -> Parser a) -> Value -> Parser a
790−withBool _ f (Bool arr) = f arr
552+withBool _ f (Bool arr) = f arr
791−withBool name _ v = prependContext name (typeMismatch "Boolean" v)
553+withBool expected _ v = typeMismatch expected v
792{-# INLINE withBool #-}
554{-# INLINE withBool #-}
793
555
794−-- | Decode a nested JSON-encoded string.
795−withEmbeddedJSON :: String -> (Value -> Parser a) -> Value -> Parser a
796−withEmbeddedJSON _ innerParser (String txt) =
797− either fail innerParser $ eitherDecode (L.fromStrict $ T.encodeUtf8 txt)
798− where
799− eitherDecode = eitherFormatError . eitherDecodeWith jsonEOF ifromJSON
800− eitherFormatError = either (Left . uncurry formatError) Right
801−withEmbeddedJSON name _ v = prependContext name (typeMismatch "String" v)
802−{-# INLINE withEmbeddedJSON #-}
803−
804-- | Convert a value from JSON, failing if the types do not match.
556-- | Convert a value from JSON, failing if the types do not match.
805fromJSON :: (FromJSON a) => Value -> Result a
557fromJSON :: (FromJSON a) => Value -> Result a
806fromJSON = parse parseJSON
558fromJSON = parse parseJSON
@@ -819,68 +571,32 @@ ifromJSON = iparse parseJSON
819-- in an object for it to be valid. If the key and value are
571-- in an object for it to be valid. If the key and value are
820-- optional, use '.:?' instead.
572-- optional, use '.:?' instead.
821(.:) :: (FromJSON a) => Object -> Text -> Parser a
573(.:) :: (FromJSON a) => Object -> Text -> Parser a
822−(.:) = explicitParseField parseJSON
574+obj .: key = case H.lookup key obj of
575+ Nothing -> fail $ "key " ++ show key ++ " not present"
576+ Just v -> parseJSON v <?> Key key
823{-# INLINE (.:) #-}
577{-# INLINE (.:) #-}
824
578
825−-- | Retrieve the value associated with the given key of an 'Object'. The
579+-- | Retrieve the value associated with the given key of an 'Object'.
826−-- result is 'Nothing' if the key is not present or if its value is 'Null',
580+-- The result is 'Nothing' if the key is not present, or 'empty' if
827−-- or 'empty' if the value cannot be converted to the desired type.
581+-- the value cannot be converted to the desired type.
828--
582--
829-- This accessor is most useful if the key and value can be absent
583-- This accessor is most useful if the key and value can be absent
830-- from an object without affecting its validity. If the key and
584-- from an object without affecting its validity. If the key and
831-- value are mandatory, use '.:' instead.
585-- value are mandatory, use '.:' instead.
832(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
586(.:?) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
833−(.:?) = explicitParseFieldMaybe parseJSON
587+obj .:? key = case H.lookup key obj of
588+ Nothing -> pure Nothing
589+ Just v -> parseJSON v <?> Key key
834{-# INLINE (.:?) #-}
590{-# INLINE (.:?) #-}
835
591
836−-- | Retrieve the value associated with the given key of an 'Object'.
592+-- | Like '.:?', but the resulting parser will fail,
837−-- The result is 'Nothing' if the key is not present or 'empty' if the
593+-- if the key is present but is 'Null'.
838−-- value cannot be converted to the desired type.
839−--
840−-- This differs from '.:?' by attempting to parse 'Null' the same as any
841−-- other JSON value, instead of interpreting it as 'Nothing'.
842(.:!) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
594(.:!) :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
843−(.:!) = explicitParseFieldMaybe' parseJSON
595+obj .:! key = case H.lookup key obj of
596+ Nothing -> pure Nothing
597+ Just v -> Just <$> parseJSON v <?> Key key
844{-# INLINE (.:!) #-}
598{-# INLINE (.:!) #-}
845
599
846−-- | Function variant of '.:'.
847−parseField :: (FromJSON a) => Object -> Text -> Parser a
848−parseField = (.:)
849−{-# INLINE parseField #-}
850−
851−-- | Function variant of '.:?'.
852−parseFieldMaybe :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
853−parseFieldMaybe = (.:?)
854−{-# INLINE parseFieldMaybe #-}
855−
856−-- | Function variant of '.:!'.
857−parseFieldMaybe' :: (FromJSON a) => Object -> Text -> Parser (Maybe a)
858−parseFieldMaybe' = (.:!)
859−{-# INLINE parseFieldMaybe' #-}
860−
861−-- | Variant of '.:' with explicit parser function.
862−--
863−-- E.g. @'explicitParseField' 'parseJSON1' :: ('FromJSON1' f, 'FromJSON' a) -> 'Object' -> 'Text' -> 'Parser' (f a)@
864−explicitParseField :: (Value -> Parser a) -> Object -> Text -> Parser a
865−explicitParseField p obj key = case H.lookup key obj of
866− Nothing -> fail $ "key " ++ show key ++ " not found"
867− Just v -> p v <?> Key key
868−{-# INLINE explicitParseField #-}
869−
870−-- | Variant of '.:?' with explicit parser function.
871−explicitParseFieldMaybe :: (Value -> Parser a) -> Object -> Text -> Parser (Maybe a)
872−explicitParseFieldMaybe p obj key = case H.lookup key obj of
873− Nothing -> pure Nothing
874− Just v -> liftParseJSON p (listParser p) v <?> Key key -- listParser isn't used by maybe instance.
875−{-# INLINE explicitParseFieldMaybe #-}
876−
877−-- | Variant of '.:!' with explicit parser function.
878−explicitParseFieldMaybe' :: (Value -> Parser a) -> Object -> Text -> Parser (Maybe a)
879−explicitParseFieldMaybe' p obj key = case H.lookup key obj of
880− Nothing -> pure Nothing
881− Just v -> Just <$> p v <?> Key key
882−{-# INLINE explicitParseFieldMaybe' #-}
883−
884-- | Helper for use in combination with '.:?' to provide default
600-- | Helper for use in combination with '.:?' to provide default
885-- values for optional JSON object fields.
601-- values for optional JSON object fields.
886--
602--
@@ -903,554 +619,317 @@ pmval .!= val = fromMaybe val <$> pmval
903-- Generic parseJSON
619-- Generic parseJSON
904-------------------------------------------------------------------------------
620-------------------------------------------------------------------------------
905
621
906−instance GFromJSON arity V1 where
907− -- Whereof we cannot format, thereof we cannot parse:
908− gParseJSON _ _ _ = fail "Attempted to parse empty type"
909−
910−
911instance OVERLAPPABLE_ (GFromJSON arity a) => GFromJSON arity (M1 i c a) where
622instance OVERLAPPABLE_ (GFromJSON arity a) => GFromJSON arity (M1 i c a) where
912 -- Meta-information, which is not handled elsewhere, is just added to the
623 -- Meta-information, which is not handled elsewhere, is just added to the
913 -- parsed value:
624 -- parsed value:
914− gParseJSON opts fargs = fmap M1 . gParseJSON opts fargs
625+ gParseJSON opts pa pj pjl = fmap M1 . gParseJSON opts pa pj pjl
915−
916−-- Information for error messages
917−
918−type TypeName = String
919−type ConName = String
920−
921−-- | Add the name of the type being parsed to a parser's error messages.
922−contextType :: TypeName -> Parser a -> Parser a
923−contextType = prependContext
924−
925−-- | Add the tagKey that will be looked up while building an ADT
926−-- | Produce the error equivalent to
927−-- | Left "Error in $: parsing T failed, expected an object with keys "tag" and
928−-- | "contents", where "tag" i-- |s associated to one of ["Foo", "Bar"],
929−-- | The parser returned error was: could not find key "tag"
930−contextTag :: Text -> [String] -> Parser a -> Parser a
931−contextTag tagKey cnames = prependFailure
932− ("expected Object with key \"" ++ unpack tagKey ++ "\"" ++
933− " containing one of " ++ show cnames ++ ", ")
934−
935−-- | Add the name of the constructor being parsed to a parser's error messages.
936−contextCons :: ConName -> TypeName -> Parser a -> Parser a
937−contextCons cname tname = prependContext (showCons cname tname)
938−
939−-- | Render a constructor as @\"MyType(MyConstructor)\"@.
940−showCons :: ConName -> TypeName -> String
941−showCons cname tname = tname ++ "(" ++ cname ++ ")"
942−
943−--------------------------------------------------------------------------------
944−
945−-- Parsing single fields
946
626
947instance (FromJSON a) => GFromJSON arity (K1 i a) where
627instance (FromJSON a) => GFromJSON arity (K1 i a) where
948 -- Constant values are decoded using their FromJSON instance:
628 -- Constant values are decoded using their FromJSON instance:
949− gParseJSON _opts _ = fmap K1 . parseJSON
629+ gParseJSON _opts _ _ _ = fmap K1 . parseJSON
950
630
951instance GFromJSON One Par1 where
631instance GFromJSON One Par1 where
952 -- Direct occurrences of the last type parameter are decoded with the
632 -- Direct occurrences of the last type parameter are decoded with the
953 -- function passed in as an argument:
633 -- function passed in as an argument:
954− gParseJSON _opts (From1Args pj _) = fmap Par1 . pj
634+ gParseJSON _opts _ pj _ = fmap Par1 . pj
955
635
956instance (FromJSON1 f) => GFromJSON One (Rec1 f) where
636instance (FromJSON1 f) => GFromJSON One (Rec1 f) where
957 -- Recursive occurrences of the last type parameter are decoded using their
637 -- Recursive occurrences of the last type parameter are decoded using their
958 -- FromJSON1 instance:
638 -- FromJSON1 instance:
959− gParseJSON _opts (From1Args pj pjl) = fmap Rec1 . liftParseJSON pj pjl
639+ gParseJSON _opts _ pj pjl = fmap Rec1 . liftParseJSON pj pjl
640+
641+instance GFromJSON arity U1 where
642+ -- Empty constructors are expected to be encoded as an empty array:
643+ gParseJSON _opts _ _ _ v
644+ | isEmptyArray v = pure U1
645+ | otherwise = typeMismatch "unit constructor (U1)" v
646+
647+instance (ConsFromJSON arity a) => GFromJSON arity (C1 c a) where
648+ -- Constructors need to be decoded differently depending on whether they're
649+ -- a record or not. This distinction is made by consParseJSON:
650+ gParseJSON opts pa pj pjl = fmap M1 . consParseJSON opts pa pj pjl
651+
652+instance ( FromProduct arity a, FromProduct arity b
653+ , ProductSize a, ProductSize b
654+ ) => GFromJSON arity (a :*: b) where
655+ -- Products are expected to be encoded to an array. Here we check whether we
656+ -- got an array of the same size as the product, then parse each of the
657+ -- product's elements using parseProduct:
658+ gParseJSON opts pa pj pjl = withArray "product (:*:)" $ \arr ->
659+ let lenArray = V.length arr
660+ lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)
661+ productSize in
662+ if lenArray == lenProduct
663+ then parseProduct opts pa arr 0 lenProduct pj pjl
664+ else fail $ "When expecting a product of " ++ show lenProduct ++
665+ " values, encountered an Array of " ++ show lenArray ++
666+ " elements instead"
667+
668+instance ( AllNullary (a :+: b) allNullary
669+ , ParseSum arity (a :+: b) allNullary
670+ ) => GFromJSON arity (a :+: b) where
671+ -- If all constructors of a sum datatype are nullary and the
672+ -- 'allNullaryToStringTag' option is set they are expected to be
673+ -- encoded as strings. This distinction is made by 'parseSum':
674+ gParseJSON opts pa pj pjl =
675+ (unTagged :: Tagged allNullary (Parser ((a :+: b) d)) ->
676+ (Parser ((a :+: b) d)))
677+ . parseSum opts pa pj pjl
960
678
961instance (FromJSON1 f, GFromJSON One g) => GFromJSON One (f :.: g) where
679instance (FromJSON1 f, GFromJSON One g) => GFromJSON One (f :.: g) where
962 -- If an occurrence of the last type parameter is nested inside two
680 -- If an occurrence of the last type parameter is nested inside two
963 -- composed types, it is decoded by using the outermost type's FromJSON1
681 -- composed types, it is decoded by using the outermost type's FromJSON1
964 -- instance to generically decode the innermost type:
682 -- instance to generically decode the innermost type:
965− gParseJSON opts fargs =
683+ gParseJSON opts pa pj pjl =
966− let gpj = gParseJSON opts fargs in
684+ let gpj = gParseJSON opts pa pj pjl in
967− fmap Comp1 . liftParseJSON gpj (listParser gpj)
685+ fmap Comp1 . liftParseJSON gpj (listParser gpj)
968−
969−--------------------------------------------------------------------------------
970−
971−instance (GFromJSON' arity a, Datatype d) => GFromJSON arity (D1 d a) where
972− -- Meta-information, which is not handled elsewhere, is just added to the
973− -- parsed value:
974− gParseJSON opts fargs = fmap M1 . gParseJSON' (tname :* opts :* fargs)
975− where
976− tname = moduleName proxy ++ "." ++ datatypeName proxy
977− proxy = undefined :: M1 _i d _f _p
978−
979−-- | 'GFromJSON', after unwrapping the 'D1' constructor, now carrying the data
980−-- type's name.
981−class GFromJSON' arity f where
982− gParseJSON' :: TypeName :* Options :* FromArgs arity a
983− -> Value
984− -> Parser (f a)
985−
986−-- | Single constructor.
987−instance ( ConsFromJSON arity a
988− , AllNullary (C1 c a) allNullary
989− , ParseSum arity (C1 c a) allNullary
990− , Constructor c
991− ) => GFromJSON' arity (C1 c a) where
992− -- The option 'tagSingleConstructors' determines whether to wrap
993− -- a single-constructor type.
994− gParseJSON' p@(_ :* opts :* _)
995− | tagSingleConstructors opts
996− = (unTagged :: Tagged allNullary (Parser (C1 c a p)) -> Parser (C1 c a p))
997− . parseSum p
998− | otherwise = fmap M1 . consParseJSON (cname :* p)
999− where
1000− cname = conName (undefined :: M1 _i c _f _p)
1001−
1002−-- | Multiple constructors.
1003−instance ( AllNullary (a :+: b) allNullary
1004− , ParseSum arity (a :+: b) allNullary
1005− ) => GFromJSON' arity (a :+: b) where
1006− -- If all constructors of a sum datatype are nullary and the
1007− -- 'allNullaryToStringTag' option is set they are expected to be
1008− -- encoded as strings. This distinction is made by 'parseSum':
1009− gParseJSON' p =
1010− (unTagged :: Tagged allNullary (Parser ((a :+: b) _d)) ->
1011− Parser ((a :+: b) _d))
1012− . parseSum p
1013
686
1014--------------------------------------------------------------------------------
687--------------------------------------------------------------------------------
1015
688
1016class ParseSum arity f allNullary where
689class ParseSum arity f allNullary where
1017− parseSum :: TypeName :* Options :* FromArgs arity a
690+ parseSum :: Options -> Proxy arity
1018− -> Value
691+ -> (Value -> Parser a) -> (Value -> Parser [a])
1019− -> Tagged allNullary (Parser (f a))
692+ -> Value -> Tagged allNullary (Parser (f a))
1020−
693+
1021−instance ( ConstructorNames f
1022− , SumFromString f
694+instance ( SumFromString (a :+: b)
1023− , FromPair arity f
695+ , FromPair arity (a :+: b)
1024− , FromTaggedObject arity f
696+ , FromTaggedObject arity (a :+: b)
1025− , FromUntaggedValue arity f
1026− ) => ParseSum arity f True where
697+ ) => ParseSum arity (a :+: b) True where
1027− parseSum p@(tname :* opts :* _)
698+ parseSum opts pa pj pjl
1028− | allNullaryToStringTag opts = Tagged . parseAllNullarySum tname opts
699+ | allNullaryToStringTag opts = Tagged . parseAllNullarySum opts
1029− | otherwise = Tagged . parseNonAllNullarySum p
700+ | otherwise = Tagged . parseNonAllNullarySum opts pa pj pjl
1030−
701+
1031−instance ( ConstructorNames f
1032− , FromPair arity f
702+instance ( FromPair arity (a :+: b)
1033− , FromTaggedObject arity f
703+ , FromTaggedObject arity (a :+: b)
1034− , FromUntaggedValue arity f
1035− ) => ParseSum arity f False where
704+ ) => ParseSum arity (a :+: b) False where
1036− parseSum p = Tagged . parseNonAllNullarySum p
705+ parseSum opts pa pj pjl = Tagged . parseNonAllNullarySum opts pa pj pjl
1037
706
1038--------------------------------------------------------------------------------
707--------------------------------------------------------------------------------
1039
708
1040−parseAllNullarySum :: (SumFromString f, ConstructorNames f)
709+parseAllNullarySum :: SumFromString f => Options -> Value -> Parser (f a)
1041− => TypeName -> Options -> Value -> Parser (f a)
1042−parseAllNullarySum tname opts =
710+parseAllNullarySum opts = withText "Text" $ \key ->
1043− withText tname $ \tag ->
1044− maybe (badTag tag) return $
711+ maybe (notFound key) return $
1045− parseSumFromString modifier tag
712+ parseSumFromString opts key
1046− where
1047− badTag tag = failWithCTags tname modifier $ \cnames ->
1048− "expected one of the tags " ++ show cnames ++
1049− ", but found tag " ++ show tag
1050− modifier = constructorTagModifier opts
1051−
1052−-- | Fail with an informative error message about a mismatched tag.
1053−-- The error message is parameterized by the list of expected tags,
1054−-- to be inferred from the result type of the parser.
1055−failWithCTags
1056− :: forall f a t. ConstructorNames f
1057− => TypeName -> (String -> t) -> ([t] -> String) -> Parser (f a)
1058−failWithCTags tname modifier f =
1059− contextType tname . fail $ f cnames
1060− where
1061− cnames = unTagged2 (constructorTags modifier :: Tagged2 f [t])
1062
713
1063class SumFromString f where
714class SumFromString f where
1064− parseSumFromString :: (String -> String) -> Text -> Maybe (f a)
715+ parseSumFromString :: Options -> Text -> Maybe (f a)
1065
716
1066instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
717instance (SumFromString a, SumFromString b) => SumFromString (a :+: b) where
1067 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
718 parseSumFromString opts key = (L1 <$> parseSumFromString opts key) <|>
1068 (R1 <$> parseSumFromString opts key)
719 (R1 <$> parseSumFromString opts key)
1069
720
1070instance (Constructor c) => SumFromString (C1 c U1) where
721instance (Constructor c) => SumFromString (C1 c U1) where
1071− parseSumFromString modifier key
722+ parseSumFromString opts key | key == name = Just $ M1 U1
1072− | key == name = Just $ M1 U1
1073− | otherwise = Nothing
723+ | otherwise = Nothing
1074− where
724+ where
1075− name = pack $ modifier $ conName (undefined :: M1 _i c _f _p)
725+ name = pack $ constructorTagModifier opts $
1076−
1077−-- For genericFromJSONKey
1078−instance SumFromString a => SumFromString (D1 d a) where
1079− parseSumFromString modifier key = M1 <$> parseSumFromString modifier key
1080−
1081−-- | List of all constructor tags.
1082−constructorTags :: ConstructorNames a => (String -> t) -> Tagged2 a [t]
1083−constructorTags modifier =
1084− fmap DList.toList (constructorNames' modifier)
1085−
1086−-- | List of all constructor names of an ADT, after a given conversion
1087−-- function. (Better inlining.)
1088−class ConstructorNames a where
1089− constructorNames' :: (String -> t) -> Tagged2 a (DList.DList t)
1090−
1091−instance (ConstructorNames a, ConstructorNames b) => ConstructorNames (a :+: b) where
1092− constructorNames' = liftA2 append constructorNames' constructorNames'
1093− where
1094− append
1095− :: Tagged2 a (DList.DList t)
1096− -> Tagged2 b (DList.DList t)
1097− -> Tagged2 (a :+: b) (DList.DList t)
1098− append (Tagged2 xs) (Tagged2 ys) = Tagged2 (DList.append xs ys)
1099−
1100−instance Constructor c => ConstructorNames (C1 c a) where
1101− constructorNames' f = Tagged2 (pure (f cname))
1102− where
1103− cname = conName (undefined :: M1 _i c _f _p)
726+ conName (undefined :: t c U1 p)
1104−
1105−-- For genericFromJSONKey
1106−instance ConstructorNames a => ConstructorNames (D1 d a) where
1107− constructorNames' = retag . constructorNames'
1108− where
1109− retag :: Tagged2 a u -> Tagged2 (D1 d a) u
1110− retag (Tagged2 x) = Tagged2 x
1111
727
1112--------------------------------------------------------------------------------
728--------------------------------------------------------------------------------
729+
1113−parseNonAllNullarySum :: forall f c arity.
730+parseNonAllNullarySum :: ( FromPair arity (a :+: b)
1114− ( FromPair arity f
1115− , FromTaggedObject arity f
731+ , FromTaggedObject arity (a :+: b)
1116− , FromUntaggedValue arity f
1117− , ConstructorNames f
1118− ) => TypeName :* Options :* FromArgs arity c
732+ ) => Options -> Proxy arity
733+ -> (Value -> Parser c) -> (Value -> Parser [c])
1119− -> Value -> Parser (f c)
734+ -> Value -> Parser ((a :+: b) c)
1120−parseNonAllNullarySum p@(tname :* opts :* _) =
735+parseNonAllNullarySum opts pa pj pjl =
1121 case sumEncoding opts of
736 case sumEncoding opts of
1122 TaggedObject{..} ->
737 TaggedObject{..} ->
1123− withObject tname $ \obj -> do
738+ withObject "Object" $ \obj -> do
1124− tag <- contextType tname . contextTag tagKey cnames_ $ obj .: tagKey
1125− fromMaybe (badTag tag <?> Key tagKey) $
1126− parseFromTaggedObject (tag :* contentsFieldName :* p) obj
1127− where
1128− tagKey = pack tagFieldName
739+ tag <- obj .: pack tagFieldName
1129− badTag tag = failWith_ $ \cnames ->
740+ fromMaybe (notFound tag) $
1130− "expected tag field to be one of " ++ show cnames ++
741+ parseFromTaggedObject opts pa contentsFieldName obj pj pjl tag
1131− ", but found tag " ++ show tag
1132− cnames_ = unTagged2 (constructorTags (constructorTagModifier opts) :: Tagged2 f [String])
1133
742
1134 ObjectWithSingleField ->
743 ObjectWithSingleField ->
744+ withObject "Object" $ \obj ->
1135− withObject tname $ \obj -> case H.toList obj of
745+ case H.toList obj of
1136− [(tag, v)] -> maybe (badTag tag) (<?> Key tag) $
746+ [pair@(tag, _)] -> fromMaybe (notFound tag) $
1137− parsePair (tag :* p) v
747+ parsePair opts pa pj pjl pair
1138− _ -> contextType tname . fail $
748+ _ -> fail "Object doesn't have a single field"
1139− "expected an Object with a single pair, but found " ++
1140− show (H.size obj) ++ " pairs"
1141− where
1142− badTag tag = failWith_ $ \cnames ->
1143− "expected an Object with a single pair where the tag is one of " ++
1144− show cnames ++ ", but found tag " ++ show tag
1145
749
1146 TwoElemArray ->
750 TwoElemArray ->
1147− withArray tname $ \arr -> case V.length arr of
751+ withArray "Array" $ \arr ->
752+ if V.length arr == 2
1148− 2 | String tag <- V.unsafeIndex arr 0 ->
753+ then case V.unsafeIndex arr 0 of
1149− maybe (badTag tag <?> Index 0) (<?> Index 1) $
754+ String tag -> fromMaybe (notFound tag) $
1150− parsePair (tag :* p) (V.unsafeIndex arr 1)
755+ parsePair opts pa pj pjl (tag, V.unsafeIndex arr 1)
1151− | otherwise ->
1152− contextType tname $
1153− fail "tag element is not a String" <?> Index 0
756+ _ -> fail "First element is not a String"
1154− len -> contextType tname . fail $
757+ else fail "Array doesn't have 2 elements"
1155− "expected a 2-element Array, but encountered an Array of length " ++
1156− show len
1157− where
1158− badTag tag = failWith_ $ \cnames ->
1159− "expected tag of the 2-element Array to be one of " ++
1160− show cnames ++ ", but found tag " ++ show tag
1161−
1162− UntaggedValue -> parseUntaggedValue p
1163− where
1164− failWith_ = failWithCTags tname (constructorTagModifier opts)
1165
758
1166--------------------------------------------------------------------------------
759--------------------------------------------------------------------------------
1167
760
1168class FromTaggedObject arity f where
761class FromTaggedObject arity f where
1169− -- The first two components of the parameter tuple are: the constructor tag
1170− -- to match against, and the contents field name.
1171− parseFromTaggedObject
762+ parseFromTaggedObject :: Options -> Proxy arity
1172− :: Text :* String :* TypeName :* Options :* FromArgs arity a
1173− -> Object
763+ -> String -> Object
764+ -> (Value -> Parser a) -> (Value -> Parser [a])
1174− -> Maybe (Parser (f a))
765+ -> Text -> Maybe (Parser (f a))
1175
766
1176instance ( FromTaggedObject arity a, FromTaggedObject arity b) =>
767instance ( FromTaggedObject arity a, FromTaggedObject arity b) =>
1177 FromTaggedObject arity (a :+: b) where
768 FromTaggedObject arity (a :+: b) where
1178− parseFromTaggedObject p obj =
769+ parseFromTaggedObject opts pa contentsFieldName obj pj pjl tag =
1179− (fmap L1 <$> parseFromTaggedObject p obj) <|>
770+ (fmap L1 <$> parseFromTaggedObject opts pa contentsFieldName obj pj pjl tag) <|>
1180− (fmap R1 <$> parseFromTaggedObject p obj)
771+ (fmap R1 <$> parseFromTaggedObject opts pa contentsFieldName obj pj pjl tag)
1181
772
1182−instance ( IsRecord f isRecord
1183− , FromTaggedObject' arity f isRecord
773+instance ( FromTaggedObject' arity f
1184 , Constructor c
774 , Constructor c
1185 ) => FromTaggedObject arity (C1 c f) where
775 ) => FromTaggedObject arity (C1 c f) where
1186− parseFromTaggedObject (tag :* contentsFieldName :* p@(_ :* opts :* _))
776+ parseFromTaggedObject opts pa contentsFieldName obj pj pjl tag
1187− | tag == tag'
1188− = Just . fmap M1 .
1189− (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a)) .
1190− parseFromTaggedObject' (contentsFieldName :* cname :* p)
777+ | tag == name = Just $ M1 <$> parseFromTaggedObject'
778+ opts pa contentsFieldName pj pjl obj
1191− | otherwise = const Nothing
779+ | otherwise = Nothing
1192− where
780+ where
1193− tag' = pack $ constructorTagModifier opts cname
781+ name = pack $ constructorTagModifier opts $
1194− cname = conName (undefined :: M1 _i c _f _p)
782+ conName (undefined :: t c f p)
1195
783
1196--------------------------------------------------------------------------------
784--------------------------------------------------------------------------------
1197
785
1198−class FromTaggedObject' arity f isRecord where
786+class FromTaggedObject' arity f where
1199− -- The first component of the parameter tuple is the contents field name.
787+ parseFromTaggedObject' :: Options -> Proxy arity -> String
788+ -> (Value -> Parser a) -> (Value -> Parser [a])
789+ -> Object -> Parser (f a)
790+
791+class FromTaggedObject'' arity f isRecord where
1200− parseFromTaggedObject'
792+ parseFromTaggedObject'' :: Options -> Proxy arity -> String
1201− :: String :* ConName :* TypeName :* Options :* FromArgs arity a
793+ -> (Value -> Parser a) -> (Value -> Parser [a])
1202− -> Object -> Tagged isRecord (Parser (f a))
794+ -> Object -> Tagged isRecord (Parser (f a))
1203−
795+
796+instance ( IsRecord f isRecord
1204−instance (RecordFromJSON arity f, FieldNames f) => FromTaggedObject' arity f True where
797+ , FromTaggedObject'' arity f isRecord
1205− -- Records are unpacked in the tagged object
1206− parseFromTaggedObject' (_ :* p) = Tagged . recordParseJSON (True :* p)
1207−
1208−instance (ConsFromJSON arity f) => FromTaggedObject' arity f False where
798+ ) => FromTaggedObject' arity f where
1209− -- Nonnullary nonrecords are encoded in the contents field
1210− parseFromTaggedObject' p obj = Tagged $ do
799+ parseFromTaggedObject' opts pa contentsFieldName pj pjl =
1211− contents <- contextCons cname tname (obj .: key)
800+ (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a)) .
1212− consParseJSON p' contents <?> Key key
801+ parseFromTaggedObject'' opts pa contentsFieldName pj pjl
1213− where
1214− key = pack contentsFieldName
1215− contentsFieldName :* p'@(cname :* tname :* _) = p
1216
802
803+instance (FromRecord arity f) => FromTaggedObject'' arity f True where
804+ parseFromTaggedObject'' opts pa _ pj pjl =
805+ Tagged . parseRecord opts pa Nothing pj pjl
806+
807+instance (GFromJSON arity f) => FromTaggedObject'' arity f False where
808+ parseFromTaggedObject'' opts pa contentsFieldName pj pjl = Tagged .
809+ (gParseJSON opts pa pj pjl <=< (.: pack contentsFieldName))
810+
1217−instance OVERLAPPING_ FromTaggedObject' arity U1 False where
811+instance OVERLAPPING_ FromTaggedObject'' arity U1 False where
1218− -- Nullary constructors don't need a contents field
812+ parseFromTaggedObject'' _ _ _ _ _ _ = Tagged (pure U1)
1219− parseFromTaggedObject' _ _ = Tagged (pure U1)
1220
813
1221--------------------------------------------------------------------------------
814--------------------------------------------------------------------------------
1222
815
1223−-- | Constructors need to be decoded differently depending on whether they're
1224−-- a record or not. This distinction is made by 'ConsParseJSON'.
1225class ConsFromJSON arity f where
816class ConsFromJSON arity f where
1226− consParseJSON
817+ consParseJSON :: Options -> Proxy arity
1227− :: ConName :* TypeName :* Options :* FromArgs arity a
818+ -> (Value -> Parser a) -> (Value -> Parser [a])
1228− -> Value -> Parser (f a)
819+ -> Value -> Parser (f a)
1229
820
1230class ConsFromJSON' arity f isRecord where
821class ConsFromJSON' arity f isRecord where
1231− consParseJSON'
822+ consParseJSON' :: Options -> Proxy arity
1232− :: ConName :* TypeName :* Options :* FromArgs arity a
823+ -> (Maybe Text) -- ^ A dummy label
824+ -- (Nothing to use proper label)
825+ -> (Value -> Parser a) -> (Value -> Parser [a])
1233− -> Value -> Tagged isRecord (Parser (f a))
826+ -> Value -> Tagged isRecord (Parser (f a))
1234
827
1235instance ( IsRecord f isRecord
828instance ( IsRecord f isRecord
1236 , ConsFromJSON' arity f isRecord
829 , ConsFromJSON' arity f isRecord
1237 ) => ConsFromJSON arity f where
830 ) => ConsFromJSON arity f where
1238− consParseJSON p =
831+ consParseJSON opts pa pj pjl v = let
1239− (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a))
1240− . consParseJSON' p
1241−
1242−instance OVERLAPPING_
1243− ( GFromJSON arity a, RecordFromJSON arity (S1 s a)
1244− ) => ConsFromJSON' arity (S1 s a) True where
1245− consParseJSON' p@(cname :* tname :* opts :* fargs)
1246− | unwrapUnaryRecords opts = Tagged . fmap M1 . gParseJSON opts fargs
832+ (v2,lab) = case (unwrapUnaryRecords opts,isUnary (undefined :: f a)) of
1247− | otherwise = Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
833+ -- use a dummy object with a dummy label
1248−
834+ (True,True) -> ((object [(pack "dummy",v)]),Just $ pack "dummy")
1249−instance RecordFromJSON arity f => ConsFromJSON' arity f True where
835+ _ ->(v,Nothing)
1250− consParseJSON' p@(cname :* tname :* _) =
836+ in (unTagged :: Tagged isRecord (Parser (f a)) -> Parser (f a))
1251− Tagged . withObject (showCons cname tname) (recordParseJSON (False :* p))
837+ $ consParseJSON' opts pa lab pj pjl v2
1252−
1253−instance OVERLAPPING_
1254− ConsFromJSON' arity U1 False where
1255− -- Empty constructors are expected to be encoded as an empty array:
1256− consParseJSON' (cname :* tname :* _) v =
1257− Tagged . contextCons cname tname $ case v of
1258− Array a | V.null a -> pure U1
1259− | otherwise -> fail_ a
1260− _ -> typeMismatch "Array" v
1261− where
1262− fail_ a = fail $
1263− "expected an empty Array, but encountered an Array of length " ++
1264− show (V.length a)
1265−
1266−instance OVERLAPPING_
1267− GFromJSON arity f => ConsFromJSON' arity (S1 s f) False where
1268− consParseJSON' (_ :* _ :* opts :* fargs) =
1269− Tagged . fmap M1 . gParseJSON opts fargs
1270
838
1271−instance (ProductFromJSON arity f, ProductSize f
1272− ) => ConsFromJSON' arity f False where
1273− consParseJSON' p = Tagged . productParseJSON0 p
1274
839
1275−--------------------------------------------------------------------------------
840+instance (FromRecord arity f) => ConsFromJSON' arity f True where
841+ consParseJSON' opts pa mlab pj pjl = Tagged . (withObject "record (:*:)"
842+ $ parseRecord opts pa mlab pj pjl)
1276
843
1277−class FieldNames f where
844+instance (GFromJSON arity f) => ConsFromJSON' arity f False where
1278− fieldNames :: f a -> [Text] -> [Text]
845+ consParseJSON' opts pa _ pj pjl = Tagged . gParseJSON opts pa pj pjl
1279
846
1280−instance (FieldNames a, FieldNames b) => FieldNames (a :*: b) where
847+--------------------------------------------------------------------------------
1281− fieldNames _ =
1282− fieldNames (undefined :: a x) .
1283− fieldNames (undefined :: b y)
1284−
1285−instance (Selector s) => FieldNames (S1 s f) where
1286− fieldNames _ = (pack (selName (undefined :: M1 _i s _f _p)) :)
1287−
1288−class RecordFromJSON arity f where
1289− recordParseJSON
1290− :: Bool :* ConName :* TypeName :* Options :* FromArgs arity a
1291− -> Object -> Parser (f a)
1292
848
1293−instance ( FieldNames f
849+class FromRecord arity f where
1294− , RecordFromJSON' arity f
850+ parseRecord :: Options -> Proxy arity
1295− ) => RecordFromJSON arity f where
851+ -> (Maybe Text) -- ^ A dummy label
1296− recordParseJSON (fromTaggedSum :* p@(cname :* tname :* opts :* _)) =
852+ -- (Nothing to use proper label)
1297− \obj -> checkUnknown obj >> recordParseJSON' p obj
853+ -> (Value -> Parser a) -> (Value -> Parser [a])
854+ -> Object -> Parser (f a)
855+
856+instance ( FromRecord arity a
857+ , FromRecord arity b
858+ ) => FromRecord arity (a :*: b) where
859+ parseRecord opts pa _ pj pjl obj =
860+ (:*:) <$> parseRecord opts pa Nothing pj pjl obj
861+ <*> parseRecord opts pa Nothing pj pjl obj
862+
863+instance ( Selector s
864+ , GFromJSON arity a
865+ ) => FromRecord arity (S1 s a) where
866+ parseRecord opts pa lab pj pjl =
867+ (<?> Key label) . gParseJSON opts pa pj pjl <=< (.: label)
1298 where
868 where
1299− knownFields :: H.HashMap Text ()
869+ label = fromMaybe defLabel lab
1300− knownFields = H.fromList $ map (,()) $
1301− fieldNames (undefined :: f a)
1302− [pack (tagFieldName (sumEncoding opts)) | fromTaggedSum]
1303− checkUnknown =
1304− if not (rejectUnknownFields opts)
1305− then \_ -> return ()
1306− else \obj -> case H.keys (H.difference obj knownFields) of
1307− [] -> return ()
1308− unknownFields -> contextCons cname tname $
1309− fail ("unknown fields: " ++ show unknownFields)
1310−
1311−class RecordFromJSON' arity f where
1312− recordParseJSON'
1313− :: ConName :* TypeName :* Options :* FromArgs arity a
1314− -> Object -> Parser (f a)
1315−
1316−instance ( RecordFromJSON' arity a
1317− , RecordFromJSON' arity b
1318− ) => RecordFromJSON' arity (a :*: b) where
1319− recordParseJSON' p obj =
1320− (:*:) <$> recordParseJSON' p obj
1321− <*> recordParseJSON' p obj
1322−
1323−instance OVERLAPPABLE_ (Selector s, GFromJSON arity a) =>
1324− RecordFromJSON' arity (S1 s a) where
1325− recordParseJSON' (cname :* tname :* opts :* fargs) obj = do
1326− fv <- contextCons cname tname (obj .: label)
1327− M1 <$> gParseJSON opts fargs fv <?> Key label
1328− where
1329− label = pack $ fieldLabelModifier opts sname
870+ defLabel = pack . fieldLabelModifier opts $
1330− sname = selName (undefined :: M1 _i s _f _p)
871+ selName (undefined :: t s a p)
1331−
872+
1332−instance INCOHERENT_ (Selector s, FromJSON a) =>
873+instance OVERLAPPING_ (Selector s, FromJSON a) =>
1333− RecordFromJSON' arity (S1 s (K1 i (Maybe a))) where
874+ FromRecord arity (S1 s (K1 i (Maybe a))) where
1334− recordParseJSON' (_ :* _ :* opts :* _) obj = M1 . K1 <$> obj .:? pack label
875+ parseRecord _ _ (Just lab) _ _ obj = (M1 . K1) <$> obj .:? lab
1335− where
876+ parseRecord opts _ Nothing _ _ obj = (M1 . K1) <$> obj .:? pack label
1336− label = fieldLabelModifier opts sname
1337− sname = selName (undefined :: M1 _i s _f _p)
1338−
1339−-- Parse an Option like a Maybe.
1340−instance INCOHERENT_ (Selector s, FromJSON a) =>
1341− RecordFromJSON' arity (S1 s (K1 i (Semigroup.Option a))) where
1342− recordParseJSON' p obj = wrap <$> recordParseJSON' p obj
1343− where
877+ where
1344− wrap :: S1 s (K1 i (Maybe a)) p -> S1 s (K1 i (Semigroup.Option a)) p
878+ label = fieldLabelModifier opts $
1345− wrap (M1 (K1 a)) = M1 (K1 (Semigroup.Option a))
879+ selName (undefined :: t s (K1 i (Maybe a)) p)
1346
880
1347--------------------------------------------------------------------------------
881--------------------------------------------------------------------------------
1348
882
1349−productParseJSON0
1350− :: forall f arity a. (ProductFromJSON arity f, ProductSize f)
1351− => ConName :* TypeName :* Options :* FromArgs arity a
1352− -> Value -> Parser (f a)
1353− -- Products are expected to be encoded to an array. Here we check whether we
1354− -- got an array of the same size as the product, then parse each of the
1355− -- product's elements using productParseJSON:
1356−productParseJSON0 p@(cname :* tname :* _ :* _) =
1357− withArray (showCons cname tname) $ \arr ->
1358− let lenArray = V.length arr
1359− lenProduct = (unTagged2 :: Tagged2 f Int -> Int)
1360− productSize in
1361− if lenArray == lenProduct
1362− then productParseJSON p arr 0 lenProduct
1363− else contextCons cname tname $
1364− fail $ "expected an Array of length " ++ show lenProduct ++
1365− ", but encountered an Array of length " ++ show lenArray
1366−
1367−--
1368−
1369−class ProductFromJSON arity f where
883+class FromProduct arity f where
1370− productParseJSON :: ConName :* TypeName :* Options :* FromArgs arity a
884+ parseProduct :: Options -> Proxy arity
1371 -> Array -> Int -> Int
885 -> Array -> Int -> Int
886+ -> (Value -> Parser a) -> (Value -> Parser [a])
1372 -> Parser (f a)
887 -> Parser (f a)
1373
888
1374−instance ( ProductFromJSON arity a
889+instance ( FromProduct arity a
1375− , ProductFromJSON arity b
890+ , FromProduct arity b
1376− ) => ProductFromJSON arity (a :*: b) where
891+ ) => FromProduct arity (a :*: b) where
1377− productParseJSON p arr ix len =
892+ parseProduct opts pa arr ix len pj pjl =
1378− (:*:) <$> productParseJSON p arr ix lenL
893+ (:*:) <$> parseProduct opts pa arr ix lenL pj pjl
1379− <*> productParseJSON p arr ixR lenR
894+ <*> parseProduct opts pa arr ixR lenR pj pjl
1380 where
895 where
1381 lenL = len `unsafeShiftR` 1
896 lenL = len `unsafeShiftR` 1
1382 ixR = ix + lenL
897 ixR = ix + lenL
1383 lenR = len - lenL
898 lenR = len - lenL
1384
899
1385−instance (GFromJSON arity a) => ProductFromJSON arity (S1 s a) where
900+instance (GFromJSON arity a) => FromProduct arity (S1 s a) where
1386− productParseJSON (_ :* _ :* opts :* fargs) arr ix _ =
901+ parseProduct opts pa arr ix _ pj pjl =
1387− M1 <$> gParseJSON opts fargs (V.unsafeIndex arr ix) <?> Index ix
902+ gParseJSON opts pa pj pjl $ V.unsafeIndex arr ix
1388
903
1389--------------------------------------------------------------------------------
904--------------------------------------------------------------------------------
1390
905
1391class FromPair arity f where
906class FromPair arity f where
1392− -- The first component of the parameter tuple is the tag to match.
1393− parsePair :: Text :* TypeName :* Options :* FromArgs arity a
907+ parsePair :: Options -> Proxy arity
1394− -> Value
908+ -> (Value -> Parser a) -> (Value -> Parser [a])
1395− -> Maybe (Parser (f a))
909+ -> Pair -> Maybe (Parser (f a))
1396
910
1397instance ( FromPair arity a
911instance ( FromPair arity a
1398 , FromPair arity b
912 , FromPair arity b
1399 ) => FromPair arity (a :+: b) where
913 ) => FromPair arity (a :+: b) where
1400− parsePair p pair =
1401− (fmap L1 <$> parsePair p pair) <|>
914+ parsePair opts pa pj pjl pair = (fmap L1 <$> parsePair opts pa pj pjl pair) <|>
1402− (fmap R1 <$> parsePair p pair)
915+ (fmap R1 <$> parsePair opts pa pj pjl pair)
1403
916
1404instance ( Constructor c
917instance ( Constructor c
918+ , GFromJSON arity a
1405 , ConsFromJSON arity a
919 , ConsFromJSON arity a
1406 ) => FromPair arity (C1 c a) where
920 ) => FromPair arity (C1 c a) where
1407− parsePair (tag :* p@(_ :* opts :* _)) v
921+ parsePair opts pa pj pjl (tag, value)
1408− | tag == tag' = Just $ M1 <$> consParseJSON (cname :* p) v
922+ | tag == tag' = Just $ gParseJSON opts pa pj pjl value
1409 | otherwise = Nothing
923 | otherwise = Nothing
1410− where
924+ where
1411− tag' = pack $ constructorTagModifier opts cname
925+ tag' = pack $ constructorTagModifier opts $
1412− cname = conName (undefined :: M1 _i c _a _p)
926+ conName (undefined :: t c a p)
1413
927
1414--------------------------------------------------------------------------------
928--------------------------------------------------------------------------------
1415
929
1416−class FromUntaggedValue arity f where
1417− parseUntaggedValue :: TypeName :* Options :* FromArgs arity a
1418− -> Value
1419− -> Parser (f a)
930+notFound :: Text -> Parser a
1420−
931+notFound key = fail $ "The key \"" ++ unpack key ++ "\" was not found"
1421−instance
932+{-# INLINE notFound #-}
1422− ( FromUntaggedValue arity a
1423− , FromUntaggedValue arity b
1424− ) => FromUntaggedValue arity (a :+: b)
1425− where
1426− parseUntaggedValue p value =
1427− L1 <$> parseUntaggedValue p value <|>
1428− R1 <$> parseUntaggedValue p value
1429−
1430−instance OVERLAPPABLE_
1431− ( ConsFromJSON arity a
1432− , Constructor c
1433− ) => FromUntaggedValue arity (C1 c a)
1434− where
1435− parseUntaggedValue p = fmap M1 . consParseJSON (cname :* p)
1436− where
1437− cname = conName (undefined :: M1 _i c _f _p)
1438−
1439−instance OVERLAPPING_
1440− ( Constructor c )
1441− => FromUntaggedValue arity (C1 c U1)
1442− where
1443− parseUntaggedValue (tname :* opts :* _) v =
1444− contextCons cname tname $ case v of
1445− String tag
1446− | tag == tag' -> pure $ M1 U1
1447− | otherwise -> fail_ tag
1448− _ -> typeMismatch "String" v
1449− where
1450− tag' = pack $ constructorTagModifier opts cname
1451− cname = conName (undefined :: M1 _i c _f _p)
1452− fail_ tag = fail $
1453− "expected tag " ++ show tag' ++ ", but found tag " ++ show tag
1454
933
1455-------------------------------------------------------------------------------
934-------------------------------------------------------------------------------
1456-- Instances
935-- Instances
@@ -1460,6 +939,13 @@ instance OVERLAPPING_
1460-- base
939-- base
1461-------------------------------------------------------------------------------
940-------------------------------------------------------------------------------
1462
941
942+instance FromJSON1 Identity where
943+ liftParseJSON p _ a = Identity <$> p a
944+ {-# INLINE liftParseJSON #-}
945+
946+instance (FromJSON a) => FromJSON (Identity a) where
947+ parseJSON = parseJSON1
948+ {-# INLINE parseJSON #-}
1463
949
1464instance FromJSON2 Const where
950instance FromJSON2 Const where
1465 liftParseJSON2 p _ _ _ = fmap Const . p
951 liftParseJSON2 p _ _ _ = fmap Const . p
@@ -1489,10 +975,6 @@ instance FromJSON2 Either where
1489 liftParseJSON2 pA _ pB _ (Object (H.toList -> [(key, value)]))
975 liftParseJSON2 pA _ pB _ (Object (H.toList -> [(key, value)]))
1490 | key == left = Left <$> pA value <?> Key left
976 | key == left = Left <$> pA value <?> Key left
1491 | key == right = Right <$> pB value <?> Key right
977 | key == right = Right <$> pB value <?> Key right
1492− where
1493− left, right :: Text
1494− left = "Left"
1495− right = "Right"
1496
978
1497 liftParseJSON2 _ _ _ _ _ = fail $
979 liftParseJSON2 _ _ _ _ _ = fail $
1498 "expected an object with a single property " ++
980 "expected an object with a single property " ++
@@ -1508,241 +990,147 @@ instance (FromJSON a, FromJSON b) => FromJSON (Either a b) where
1508 parseJSON = parseJSON2
990 parseJSON = parseJSON2
1509 {-# INLINE parseJSON #-}
991 {-# INLINE parseJSON #-}
1510
992
1511−instance FromJSON Void where
993+left, right :: Text
1512− parseJSON _ = fail "Cannot parse Void"
994+left = "Left"
1513− {-# INLINE parseJSON #-}
995+right = "Right"
996+
1514
997
1515instance FromJSON Bool where
998instance FromJSON Bool where
1516− parseJSON (Bool b) = pure b
999+ parseJSON = withBool "Bool" pure
1517− parseJSON v = typeMismatch "Bool" v
1518 {-# INLINE parseJSON #-}
1000 {-# INLINE parseJSON #-}
1519
1001
1520−instance FromJSONKey Bool where
1521− fromJSONKey = FromJSONKeyTextParser $ \t -> case t of
1522− "true" -> pure True
1523− "false" -> pure False
1524− _ -> fail $ "cannot parse key " ++ show t ++ " into Bool"
1525−
1526instance FromJSON Ordering where
1002instance FromJSON Ordering where
1527 parseJSON = withText "Ordering" $ \s ->
1003 parseJSON = withText "Ordering" $ \s ->
1528 case s of
1004 case s of
1529 "LT" -> return LT
1005 "LT" -> return LT
1530 "EQ" -> return EQ
1006 "EQ" -> return EQ
1531 "GT" -> return GT
1007 "GT" -> return GT
1532− _ -> fail $ "parsing Ordering failed, unexpected " ++ show s ++
1533− " (expected \"LT\", \"EQ\", or \"GT\")"
1008+ _ -> fail "Parsing Ordering value failed: expected \"LT\", \"EQ\", or \"GT\""
1534
1009
1535instance FromJSON () where
1010instance FromJSON () where
1536 parseJSON = withArray "()" $ \v ->
1011 parseJSON = withArray "()" $ \v ->
1537 if V.null v
1012 if V.null v
1538 then pure ()
1013 then pure ()
1539− else prependContext "()" $ fail "expected an empty array"
1014+ else fail "Expected an empty array"
1540 {-# INLINE parseJSON #-}
1015 {-# INLINE parseJSON #-}
1541
1016
1542instance FromJSON Char where
1017instance FromJSON Char where
1543− parseJSON = withText "Char" parseChar
1018+ parseJSON = withText "Char" $ \t ->
1019+ if T.compareLength t 1 == EQ
1020+ then pure $ T.head t
1021+ else fail "Expected a string of length 1"
1544 {-# INLINE parseJSON #-}
1022 {-# INLINE parseJSON #-}
1545
1023
1546− parseJSONList (String s) = pure (T.unpack s)
1024+ parseJSONList = withText "String" $ pure . T.unpack
1547− parseJSONList v = typeMismatch "String" v
1548 {-# INLINE parseJSONList #-}
1025 {-# INLINE parseJSONList #-}
1549
1026
1550−parseChar :: Text -> Parser Char
1551−parseChar t =
1552− if T.compareLength t 1 == EQ
1553− then pure $ T.head t
1554− else prependContext "Char" $ fail "expected a string of length 1"
1555−
1556instance FromJSON Double where
1027instance FromJSON Double where
1557 parseJSON = parseRealFloat "Double"
1028 parseJSON = parseRealFloat "Double"
1558 {-# INLINE parseJSON #-}
1029 {-# INLINE parseJSON #-}
1559
1030
1560−instance FromJSONKey Double where
1031+instance FromJSON Number where
1561− fromJSONKey = FromJSONKeyTextParser $ \t -> case t of
1032+ parseJSON (Number s) = pure $ scientificToNumber s
1562− "NaN" -> pure (0/0)
1033+ parseJSON Null = pure (D (0/0))
1563− "Infinity" -> pure (1/0)
1034+ parseJSON v = typeMismatch "Number" v
1564− "-Infinity" -> pure (negate 1/0)
1035+ {-# INLINE parseJSON #-}
1565− _ -> Scientific.toRealFloat <$> parseScientificText t
1566
1036
1567instance FromJSON Float where
1037instance FromJSON Float where
1568 parseJSON = parseRealFloat "Float"
1038 parseJSON = parseRealFloat "Float"
1569 {-# INLINE parseJSON #-}
1039 {-# INLINE parseJSON #-}
1570
1040
1571−instance FromJSONKey Float where
1572− fromJSONKey = FromJSONKeyTextParser $ \t -> case t of
1573− "NaN" -> pure (0/0)
1574− "Infinity" -> pure (1/0)
1575− "-Infinity" -> pure (negate 1/0)
1576− _ -> Scientific.toRealFloat <$> parseScientificText t
1577−
1578−instance (FromJSON a, Integral a) => FromJSON (Ratio a) where
1041+instance FromJSON (Ratio Integer) where
1579− parseJSON (Number x)
1580− | exp10 <= 1024
1581− , exp10 >= -1024 = return $! realToFrac x
1582− | otherwise = prependContext "Ratio" $ fail msg
1583− where
1584− exp10 = base10Exponent x
1585− msg = "found a number with exponent " ++ show exp10
1586− ++ ", but it must not be greater than 1024 or less than -1024"
1587− parseJSON o = objParser o
1588− where
1589− objParser = withObject "Rational" $ \obj -> do
1042+ parseJSON = withObject "Rational" $ \obj ->
1590− numerator <- obj .: "numerator"
1043+ (%) <$> obj .: "numerator"
1591− denominator <- obj .: "denominator"
1592− if denominator == 0
1593− then fail "Ratio denominator was 0"
1594− else pure $ numerator % denominator
1044+ <*> obj .: "denominator"
1595 {-# INLINE parseJSON #-}
1045 {-# INLINE parseJSON #-}
1596
1046
1597−-- | This instance includes a bounds check to prevent maliciously
1047+-- | /WARNING:/ Only parse fixed-precision numbers from trusted input
1598−-- large inputs to fill up the memory of the target system. You can
1048+-- since an attacker could easily fill up the memory of the target
1599−-- newtype 'Scientific' and provide your own instance using
1049+-- system by specifying a scientific number with a big exponent like
1600−-- 'withScientific' if you want to allow larger inputs.
1050+-- @1e1000000000@.
1601instance HasResolution a => FromJSON (Fixed a) where
1051instance HasResolution a => FromJSON (Fixed a) where
1602− parseJSON = prependContext "Fixed" . withBoundedScientific' (pure . realToFrac)
1052+ parseJSON = withScientific "Fixed" $ pure . realToFrac
1603 {-# INLINE parseJSON #-}
1053 {-# INLINE parseJSON #-}
1604
1054
1605instance FromJSON Int where
1055instance FromJSON Int where
1606− parseJSON = parseBoundedIntegral "Int"
1056+ parseJSON = parseIntegral "Int"
1607 {-# INLINE parseJSON #-}
1057 {-# INLINE parseJSON #-}
1608
1058
1609−instance FromJSONKey Int where
1059+-- | /WARNING:/ Only parse Integers from trusted input since an
1610− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int"
1611−
1612−-- | This instance includes a bounds check to prevent maliciously
1613−-- large inputs to fill up the memory of the target system. You can
1060+-- attacker could easily fill up the memory of the target system by
1614−-- newtype 'Scientific' and provide your own instance using
1061+-- specifying a scientific number with a big exponent like
1615−-- 'withScientific' if you want to allow larger inputs.
1062+-- @1e1000000000@.
1616instance FromJSON Integer where
1063instance FromJSON Integer where
1617− parseJSON = parseIntegral "Integer"
1064+ parseJSON = withScientific "Integral" $ pure . truncate
1618 {-# INLINE parseJSON #-}
1065 {-# INLINE parseJSON #-}
1619
1066
1620−instance FromJSONKey Integer where
1621− fromJSONKey = FromJSONKeyTextParser $ parseIntegralText "Integer"
1622−
1623instance FromJSON Natural where
1067instance FromJSON Natural where
1624− parseJSON value = do
1068+ parseJSON = withScientific "Natural" $ \s ->
1625− integer <- parseIntegral "Natural" value
1069+ if Scientific.coefficient s < 0
1626− parseNatural integer
1627−
1628−instance FromJSONKey Natural where
1629− fromJSONKey = FromJSONKeyTextParser $ \text -> do
1630− integer <- parseIntegralText "Natural" text
1631− parseNatural integer
1632−
1633−parseNatural :: Integer -> Parser Natural
1634−parseNatural integer =
1635− if integer < 0 then
1636− fail $ "parsing Natural failed, unexpected negative number " <> show integer
1070+ then fail $ "Expected a Natural number but got the negative number: " <> show s
1637− else
1071+ else pure $ truncate s
1638− pure $ fromIntegral integer
1639
1072
1640instance FromJSON Int8 where
1073instance FromJSON Int8 where
1641− parseJSON = parseBoundedIntegral "Int8"
1074+ parseJSON = parseIntegral "Int8"
1642 {-# INLINE parseJSON #-}
1075 {-# INLINE parseJSON #-}
1643
1076
1644−instance FromJSONKey Int8 where
1645− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int8"
1646−
1647instance FromJSON Int16 where
1077instance FromJSON Int16 where
1648− parseJSON = parseBoundedIntegral "Int16"
1078+ parseJSON = parseIntegral "Int16"
1649 {-# INLINE parseJSON #-}
1079 {-# INLINE parseJSON #-}
1650
1080
1651−instance FromJSONKey Int16 where
1652− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int16"
1653−
1654instance FromJSON Int32 where
1081instance FromJSON Int32 where
1655− parseJSON = parseBoundedIntegral "Int32"
1082+ parseJSON = parseIntegral "Int32"
1656 {-# INLINE parseJSON #-}
1083 {-# INLINE parseJSON #-}
1657
1084
1658−instance FromJSONKey Int32 where
1659− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int32"
1660−
1661instance FromJSON Int64 where
1085instance FromJSON Int64 where
1662− parseJSON = parseBoundedIntegral "Int64"
1086+ parseJSON = parseIntegral "Int64"
1663 {-# INLINE parseJSON #-}
1087 {-# INLINE parseJSON #-}
1664
1088
1665−instance FromJSONKey Int64 where
1666− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Int64"
1667−
1668instance FromJSON Word where
1089instance FromJSON Word where
1669− parseJSON = parseBoundedIntegral "Word"
1090+ parseJSON = parseIntegral "Word"
1670 {-# INLINE parseJSON #-}
1091 {-# INLINE parseJSON #-}
1671
1092
1672−instance FromJSONKey Word where
1673− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word"
1674−
1675instance FromJSON Word8 where
1093instance FromJSON Word8 where
1676− parseJSON = parseBoundedIntegral "Word8"
1094+ parseJSON = parseIntegral "Word8"
1677 {-# INLINE parseJSON #-}
1095 {-# INLINE parseJSON #-}
1678
1096
1679−instance FromJSONKey Word8 where
1680− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word8"
1681−
1682instance FromJSON Word16 where
1097instance FromJSON Word16 where
1683− parseJSON = parseBoundedIntegral "Word16"
1098+ parseJSON = parseIntegral "Word16"
1684 {-# INLINE parseJSON #-}
1099 {-# INLINE parseJSON #-}
1685
1100
1686−instance FromJSONKey Word16 where
1687− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word16"
1688−
1689instance FromJSON Word32 where
1101instance FromJSON Word32 where
1690− parseJSON = parseBoundedIntegral "Word32"
1102+ parseJSON = parseIntegral "Word32"
1691 {-# INLINE parseJSON #-}
1103 {-# INLINE parseJSON #-}
1692
1104
1693−instance FromJSONKey Word32 where
1694− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word32"
1695−
1696instance FromJSON Word64 where
1105instance FromJSON Word64 where
1697− parseJSON = parseBoundedIntegral "Word64"
1106+ parseJSON = parseIntegral "Word64"
1698− {-# INLINE parseJSON #-}
1699−
1700−instance FromJSONKey Word64 where
1701− fromJSONKey = FromJSONKeyTextParser $ parseBoundedIntegralText "Word64"
1702−
1703−instance FromJSON CTime where
1704− parseJSON = fmap CTime . parseJSON
1705 {-# INLINE parseJSON #-}
1107 {-# INLINE parseJSON #-}
1706
1108
1707instance FromJSON Text where
1109instance FromJSON Text where
1708 parseJSON = withText "Text" pure
1110 parseJSON = withText "Text" pure
1709 {-# INLINE parseJSON #-}
1111 {-# INLINE parseJSON #-}
1710
1112
1711−instance FromJSONKey Text where
1712− fromJSONKey = fromJSONKeyCoerce
1713−
1714−
1715instance FromJSON LT.Text where
1113instance FromJSON LT.Text where
1716 parseJSON = withText "Lazy Text" $ pure . LT.fromStrict
1114 parseJSON = withText "Lazy Text" $ pure . LT.fromStrict
1717 {-# INLINE parseJSON #-}
1115 {-# INLINE parseJSON #-}
1718
1116
1719−instance FromJSONKey LT.Text where
1720− fromJSONKey = FromJSONKeyText LT.fromStrict
1721−
1722−
1723instance FromJSON Version where
1117instance FromJSON Version where
1724− parseJSON = withText "Version" parseVersionText
1725 {-# INLINE parseJSON #-}
1118 {-# INLINE parseJSON #-}
1726−
1727−instance FromJSONKey Version where
1728− fromJSONKey = FromJSONKeyTextParser parseVersionText
1729−
1730−parseVersionText :: Text -> Parser Version
1731−parseVersionText = go . readP_to_S parseVersion . unpack
1119+ parseJSON = withText "Version" $ go . readP_to_S parseVersion . unpack
1732− where
1120+ where
1733− go [(v,[])] = return v
1121+ go [(v,[])] = return v
1734− go (_ : xs) = go xs
1122+ go (_ : xs) = go xs
1735− go _ = fail "parsing Version failed"
1123+ go _ = fail $ "could not parse Version"
1736
1124
1737-------------------------------------------------------------------------------
1125-------------------------------------------------------------------------------
1738-- semigroups NonEmpty
1126-- semigroups NonEmpty
1739-------------------------------------------------------------------------------
1127-------------------------------------------------------------------------------
1740
1128
1741instance FromJSON1 NonEmpty where
1129instance FromJSON1 NonEmpty where
1742− liftParseJSON p _ = withArray "NonEmpty" $
1130+ liftParseJSON p _ = withArray "NonEmpty a" $
1743 (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1131 (>>= ne) . Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1744 where
1132 where
1745− ne [] = fail "parsing NonEmpty failed, unexpected empty list"
1133+ ne [] = fail "Expected a NonEmpty but got an empty list"
1746 ne (x:xs) = pure (x :| xs)
1134 ne (x:xs) = pure (x :| xs)
1747 {-# INLINE liftParseJSON #-}
1135 {-# INLINE liftParseJSON #-}
1748
1136
@@ -1758,103 +1146,12 @@ instance FromJSON Scientific where
1758 parseJSON = withScientific "Scientific" pure
1146 parseJSON = withScientific "Scientific" pure
1759 {-# INLINE parseJSON #-}
1147 {-# INLINE parseJSON #-}
1760
1148
1761−-------------------------------------------------------------------------------
1762−-- DList
1763−-------------------------------------------------------------------------------
1764−
1765−instance FromJSON1 DList.DList where
1766− liftParseJSON p _ = withArray "DList" $
1767− fmap DList.fromList .
1768− Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1769− {-# INLINE liftParseJSON #-}
1770−
1771−instance (FromJSON a) => FromJSON (DList.DList a) where
1772− parseJSON = parseJSON1
1773− {-# INLINE parseJSON #-}
1774−
1775−-------------------------------------------------------------------------------
1776−-- tranformers - Functors
1777−-------------------------------------------------------------------------------
1778−
1779−instance FromJSON1 Identity where
1780− liftParseJSON p _ a = Identity <$> p a
1781− {-# INLINE liftParseJSON #-}
1782−
1783− liftParseJSONList _ p a = fmap Identity <$> p a
1784− {-# INLINE liftParseJSONList #-}
1785−
1786−instance (FromJSON a) => FromJSON (Identity a) where
1787− parseJSON = parseJSON1
1788− {-# INLINE parseJSON #-}
1789−
1790− parseJSONList = liftParseJSONList parseJSON parseJSONList
1791− {-# INLINE parseJSONList #-}
1792−
1793−instance (FromJSONKey a) => FromJSONKey (Identity a) where
1794− fromJSONKey = coerceFromJSONKeyFunction (fromJSONKey :: FromJSONKeyFunction a)
1795− fromJSONKeyList = coerceFromJSONKeyFunction (fromJSONKeyList :: FromJSONKeyFunction [a])
1796−
1797−
1798−instance (FromJSON1 f, FromJSON1 g) => FromJSON1 (Compose f g) where
1799− liftParseJSON p pl a = Compose <$> liftParseJSON g gl a
1800− where
1801− g = liftParseJSON p pl
1802− gl = liftParseJSONList p pl
1803− {-# INLINE liftParseJSON #-}
1804−
1805− liftParseJSONList p pl a = map Compose <$> liftParseJSONList g gl a
1806− where
1807− g = liftParseJSON p pl
1808− gl = liftParseJSONList p pl
1809− {-# INLINE liftParseJSONList #-}
1810−
1811−instance (FromJSON1 f, FromJSON1 g, FromJSON a) => FromJSON (Compose f g a) where
1812− parseJSON = parseJSON1
1813− {-# INLINE parseJSON #-}
1814−
1815− parseJSONList = liftParseJSONList parseJSON parseJSONList
1816− {-# INLINE parseJSONList #-}
1817−
1818−
1819−instance (FromJSON1 f, FromJSON1 g) => FromJSON1 (Product f g) where
1820− liftParseJSON p pl a = uncurry Pair <$> liftParseJSON2 px pxl py pyl a
1821− where
1822− px = liftParseJSON p pl
1823− pxl = liftParseJSONList p pl
1824− py = liftParseJSON p pl
1825− pyl = liftParseJSONList p pl
1826− {-# INLINE liftParseJSON #-}
1827−
1828−instance (FromJSON1 f, FromJSON1 g, FromJSON a) => FromJSON (Product f g a) where
1829− parseJSON = parseJSON1
1830− {-# INLINE parseJSON #-}
1831−
1832−
1833−instance (FromJSON1 f, FromJSON1 g) => FromJSON1 (Sum f g) where
1834− liftParseJSON p pl (Object (H.toList -> [(key, value)]))
1835− | key == inl = InL <$> liftParseJSON p pl value <?> Key inl
1836− | key == inr = InR <$> liftParseJSON p pl value <?> Key inl
1837− where
1838− inl, inr :: Text
1839− inl = "InL"
1840− inr = "InR"
1841−
1842− liftParseJSON _ _ _ = fail $
1843− "parsing Sum failed, expected an object with a single property " ++
1844− "where the property key should be either " ++
1845− "\"InL\" or \"InR\""
1846− {-# INLINE liftParseJSON #-}
1847−
1848−instance (FromJSON1 f, FromJSON1 g, FromJSON a) => FromJSON (Sum f g a) where
1849− parseJSON = parseJSON1
1850− {-# INLINE parseJSON #-}
1851−
1852-------------------------------------------------------------------------------
1149-------------------------------------------------------------------------------
1853-- containers
1150-- containers
1854-------------------------------------------------------------------------------
1151-------------------------------------------------------------------------------
1855
1152
1856instance FromJSON1 Seq.Seq where
1153instance FromJSON1 Seq.Seq where
1857− liftParseJSON p _ = withArray "Seq" $
1154+ liftParseJSON p _ = withArray "Seq a" $
1858 fmap Seq.fromList .
1155 fmap Seq.fromList .
1859 Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1156 Tr.sequence . zipWith (parseIndexedJSON p) [0..] . V.toList
1860 {-# INLINE liftParseJSON #-}
1157 {-# INLINE liftParseJSON #-}
@@ -1888,15 +1185,15 @@ instance FromJSON a => FromJSON (IntMap.IntMap a) where
1888
1185
1889instance (FromJSONKey k, Ord k) => FromJSON1 (M.Map k) where
1186instance (FromJSONKey k, Ord k) => FromJSON1 (M.Map k) where
1890 liftParseJSON p _ = case fromJSONKey of
1187 liftParseJSON p _ = case fromJSONKey of
1891− FromJSONKeyCoerce _ -> withObject "Map" $
1188+ FromJSONKeyCoerce _-> withObject "Map k v" $
1892 fmap (H.foldrWithKey (M.insert . unsafeCoerce) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)
1189 fmap (H.foldrWithKey (M.insert . unsafeCoerce) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)
1893− FromJSONKeyText f -> withObject "Map" $
1190+ FromJSONKeyText f -> withObject "Map k v" $
1894 fmap (H.foldrWithKey (M.insert . f) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)
1191 fmap (H.foldrWithKey (M.insert . f) M.empty) . H.traverseWithKey (\k v -> p v <?> Key k)
1895− FromJSONKeyTextParser f -> withObject "Map" $
1192+ FromJSONKeyTextParser f -> withObject "Map k v" $
1896− H.foldrWithKey (\k v m -> M.insert <$> f k <?> Key k <*> p v <?> Key k <*> m) (pure M.empty)
1193+ H.foldrWithKey (\k v m -> M.insert <$> f k <*> (p v <?> Key k) <*> m) (pure M.empty)
1897− FromJSONKeyValue f -> withArray "Map" $ \arr ->
1194+ FromJSONKeyValue f -> withArray "Map k v" $ \arr ->
1898− fmap M.fromList . Tr.sequence .
1195+ M.fromList <$> (Tr.sequence .
1899− zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr
1196+ zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr)
1900 {-# INLINE liftParseJSON #-}
1197 {-# INLINE liftParseJSON #-}
1901
1198
1902instance (FromJSONKey k, Ord k, FromJSON v) => FromJSON (M.Map k v) where
1199instance (FromJSONKey k, Ord k, FromJSON v) => FromJSON (M.Map k v) where
@@ -1916,24 +1213,12 @@ instance (FromJSON v) => FromJSON (Tree.Tree v) where
1916 parseJSON = parseJSON1
1213 parseJSON = parseJSON1
1917 {-# INLINE parseJSON #-}
1214 {-# INLINE parseJSON #-}
1918
1215
1919−-------------------------------------------------------------------------------
1920−-- uuid
1921−-------------------------------------------------------------------------------
1922−
1923−instance FromJSON UUID.UUID where
1924− parseJSON = withText "UUID" $
1925− maybe (fail "invalid UUID") pure . UUID.fromText
1926−
1927−instance FromJSONKey UUID.UUID where
1928− fromJSONKey = FromJSONKeyTextParser $
1929− maybe (fail "invalid UUID") pure . UUID.fromText
1930−
1931-------------------------------------------------------------------------------
1216-------------------------------------------------------------------------------
1932-- vector
1217-- vector
1933-------------------------------------------------------------------------------
1218-------------------------------------------------------------------------------
1934
1219
1935instance FromJSON1 Vector where
1220instance FromJSON1 Vector where
1936− liftParseJSON p _ = withArray "Vector" $
1221+ liftParseJSON p _ = withArray "Vector a" $
1937 V.mapM (uncurry $ parseIndexedJSON p) . V.indexed
1222 V.mapM (uncurry $ parseIndexedJSON p) . V.indexed
1938 {-# INLINE liftParseJSON #-}
1223 {-# INLINE liftParseJSON #-}
1939
1224
@@ -1947,14 +1232,14 @@ vectorParseJSON s = withArray s $ fmap V.convert . V.mapM (uncurry $ parseIndexe
1947{-# INLINE vectorParseJSON #-}
1232{-# INLINE vectorParseJSON #-}
1948
1233
1949instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where
1234instance (Storable a, FromJSON a) => FromJSON (VS.Vector a) where
1950− parseJSON = vectorParseJSON "Data.Vector.Storable.Vector"
1235+ parseJSON = vectorParseJSON "Data.Vector.Storable.Vector a"
1951
1236
1952instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where
1237instance (VP.Prim a, FromJSON a) => FromJSON (VP.Vector a) where
1953− parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector"
1238+ parseJSON = vectorParseJSON "Data.Vector.Primitive.Vector a"
1954 {-# INLINE parseJSON #-}
1239 {-# INLINE parseJSON #-}
1955
1240
1956instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where
1241instance (VG.Vector VU.Vector a, FromJSON a) => FromJSON (VU.Vector a) where
1957− parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector"
1242+ parseJSON = vectorParseJSON "Data.Vector.Unboxed.Vector a"
1958 {-# INLINE parseJSON #-}
1243 {-# INLINE parseJSON #-}
1959
1244
1960-------------------------------------------------------------------------------
1245-------------------------------------------------------------------------------
@@ -1968,15 +1253,15 @@ instance (Eq a, Hashable a, FromJSON a) => FromJSON (HashSet.HashSet a) where
1968
1253
1969instance (FromJSONKey k, Eq k, Hashable k) => FromJSON1 (H.HashMap k) where
1254instance (FromJSONKey k, Eq k, Hashable k) => FromJSON1 (H.HashMap k) where
1970 liftParseJSON p _ = case fromJSONKey of
1255 liftParseJSON p _ = case fromJSONKey of
1971− FromJSONKeyCoerce _ -> withObject "HashMap ~Text" $
1256+ FromJSONKeyCoerce _ -> withObject "HashMap ~Text v" $
1972 uc . H.traverseWithKey (\k v -> p v <?> Key k)
1257 uc . H.traverseWithKey (\k v -> p v <?> Key k)
1973− FromJSONKeyText f -> withObject "HashMap" $
1258+ FromJSONKeyText f -> withObject "HashMap k v" $
1974 fmap (mapKey f) . H.traverseWithKey (\k v -> p v <?> Key k)
1259 fmap (mapKey f) . H.traverseWithKey (\k v -> p v <?> Key k)
1975− FromJSONKeyTextParser f -> withObject "HashMap" $
1260+ FromJSONKeyTextParser f -> withObject "HashMap k v" $
1976− H.foldrWithKey (\k v m -> H.insert <$> f k <?> Key k <*> p v <?> Key k <*> m) (pure H.empty)
1261+ H.foldrWithKey (\k v m -> H.insert <$> f k <*> (p v <?> Key k) <*> m) (pure H.empty)
1977− FromJSONKeyValue f -> withArray "Map" $ \arr ->
1262+ FromJSONKeyValue f -> withArray "Map k v" $ \arr ->
1978− fmap H.fromList . Tr.sequence .
1263+ H.fromList <$> (Tr.sequence .
1979− zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr
1264+ zipWith (parseIndexedJSONPair f p) [0..] . V.toList $ arr)
1980 where
1265 where
1981 uc :: Parser (H.HashMap Text v) -> Parser (H.HashMap k v)
1266 uc :: Parser (H.HashMap Text v) -> Parser (H.HashMap k v)
1982 uc = unsafeCoerce
1267 uc = unsafeCoerce
@@ -1997,33 +1282,11 @@ instance FromJSON DotNetTime where
1997 parseJSON = withText "DotNetTime" $ \t ->
1282 parseJSON = withText "DotNetTime" $ \t ->
1998 let (s,m) = T.splitAt (T.length t - 5) t
1283 let (s,m) = T.splitAt (T.length t - 5) t
1999 t' = T.concat [s,".",m]
1284 t' = T.concat [s,".",m]
2000− in case parseTimeM True defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
1285+ in case parseTime defaultTimeLocale "/Date(%s%Q)/" (unpack t') of
2001 Just d -> pure (DotNetTime d)
1286 Just d -> pure (DotNetTime d)
2002 _ -> fail "could not parse .NET time"
1287 _ -> fail "could not parse .NET time"
2003 {-# INLINE parseJSON #-}
1288 {-# INLINE parseJSON #-}
2004
1289
2005−-------------------------------------------------------------------------------
2006−-- primitive
2007−-------------------------------------------------------------------------------
2008−
2009−instance FromJSON a => FromJSON (PM.Array a) where
2010− -- note: we could do better than this if vector exposed the data
2011− -- constructor in Data.Vector.
2012− parseJSON = fmap Exts.fromList . parseJSON
2013−
2014−instance FromJSON a => FromJSON (PM.SmallArray a) where
2015− parseJSON = fmap Exts.fromList . parseJSON
2016−
2017−#if MIN_VERSION_primitive(0,6,4)
2018−instance (PM.Prim a,FromJSON a) => FromJSON (PM.PrimArray a) where
2019− parseJSON = fmap Exts.fromList . parseJSON
2020−
2021−#if !MIN_VERSION_primitive(0,7,0)
2022−instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
2023− parseJSON = fmap Exts.fromList . parseJSON
2024−#endif
2025−#endif
2026−
2027-------------------------------------------------------------------------------
1290-------------------------------------------------------------------------------
2028-- time
1291-- time
2029-------------------------------------------------------------------------------
1292-------------------------------------------------------------------------------
@@ -2031,211 +1294,53 @@ instance (PM.PrimUnlifted a,FromJSON a) => FromJSON (PM.UnliftedArray a) where
2031instance FromJSON Day where
1294instance FromJSON Day where
2032 parseJSON = withText "Day" (Time.run Time.day)
1295 parseJSON = withText "Day" (Time.run Time.day)
2033
1296
2034−instance FromJSONKey Day where
2035− fromJSONKey = FromJSONKeyTextParser (Time.run Time.day)
2036−
2037−
2038instance FromJSON TimeOfDay where
1297instance FromJSON TimeOfDay where
2039 parseJSON = withText "TimeOfDay" (Time.run Time.timeOfDay)
1298 parseJSON = withText "TimeOfDay" (Time.run Time.timeOfDay)
2040
1299
2041−instance FromJSONKey TimeOfDay where
2042− fromJSONKey = FromJSONKeyTextParser (Time.run Time.timeOfDay)
2043−
2044−
2045instance FromJSON LocalTime where
1300instance FromJSON LocalTime where
2046 parseJSON = withText "LocalTime" (Time.run Time.localTime)
1301 parseJSON = withText "LocalTime" (Time.run Time.localTime)
2047
1302
2048−instance FromJSONKey LocalTime where
2049− fromJSONKey = FromJSONKeyTextParser (Time.run Time.localTime)
2050−
2051−
2052−-- | Supported string formats:
2053−--
2054−-- @YYYY-MM-DD HH:MM Z@
2055−-- @YYYY-MM-DD HH:MM:SS Z@
2056−-- @YYYY-MM-DD HH:MM:SS.SSS Z@
2057−--
2058−-- The first space may instead be a @T@, and the second space is
2059−-- optional. The @Z@ represents UTC. The @Z@ may be replaced with a
2060−-- time zone offset of the form @+0000@ or @-08:00@, where the first
2061−-- two digits are hours, the @:@ is optional and the second two digits
2062−-- (also optional) are minutes.
2063instance FromJSON ZonedTime where
1303instance FromJSON ZonedTime where
2064 parseJSON = withText "ZonedTime" (Time.run Time.zonedTime)
1304 parseJSON = withText "ZonedTime" (Time.run Time.zonedTime)
2065
1305
2066−instance FromJSONKey ZonedTime where
2067− fromJSONKey = FromJSONKeyTextParser (Time.run Time.zonedTime)
2068−
2069−
2070instance FromJSON UTCTime where
1306instance FromJSON UTCTime where
2071 parseJSON = withText "UTCTime" (Time.run Time.utcTime)
1307 parseJSON = withText "UTCTime" (Time.run Time.utcTime)
2072
1308
2073−instance FromJSONKey UTCTime where
1309+-- | /WARNING:/ Only parse lengths of time from trusted input
2074− fromJSONKey = FromJSONKeyTextParser (Time.run Time.utcTime)
2075−
2076−
2077−-- | This instance includes a bounds check to prevent maliciously
2078−-- large inputs to fill up the memory of the target system. You can
1310+-- since an attacker could easily fill up the memory of the target
2079−-- newtype 'Scientific' and provide your own instance using
1311+-- system by specifying a scientific number with a big exponent like
2080−-- 'withScientific' if you want to allow larger inputs.
1312+-- @1e1000000000@.
2081instance FromJSON NominalDiffTime where
1313instance FromJSON NominalDiffTime where
2082− parseJSON = withBoundedScientific "NominalDiffTime" $ pure . realToFrac
1314+ parseJSON = withScientific "NominalDiffTime" $ pure . realToFrac
2083− {-# INLINE parseJSON #-}
2084−
2085−
2086−-- | This instance includes a bounds check to prevent maliciously
2087−-- large inputs to fill up the memory of the target system. You can
2088−-- newtype 'Scientific' and provide your own instance using
2089−-- 'withScientific' if you want to allow larger inputs.
2090−instance FromJSON DiffTime where
2091− parseJSON = withBoundedScientific "DiffTime" $ pure . realToFrac
2092 {-# INLINE parseJSON #-}
1315 {-# INLINE parseJSON #-}
2093
1316
2094−instance FromJSON SystemTime where
2095− parseJSON v = prependContext "SystemTime" $ do
2096− n <- parseJSON v
2097− let n' = floor (n * fromInteger (resolution n) :: Nano)
2098− let (secs, nano) = n' `divMod` resolution n
2099− return (MkSystemTime (fromInteger secs) (fromInteger nano))
2100−
2101−instance FromJSON CalendarDiffTime where
2102− parseJSON = withObject "CalendarDiffTime" $ \obj -> CalendarDiffTime
2103− <$> obj .: "months"
2104− <*> obj .: "time"
2105−
2106−instance FromJSON CalendarDiffDays where
2107− parseJSON = withObject "CalendarDiffDays" $ \obj -> CalendarDiffDays
2108− <$> obj .: "months"
2109− <*> obj .: "days"
2110−
2111−instance FromJSON DayOfWeek where
2112− parseJSON = withText "DaysOfWeek" parseDayOfWeek
2113−
2114−parseDayOfWeek :: T.Text -> Parser DayOfWeek
2115−parseDayOfWeek t = case T.toLower t of
2116− "monday" -> return Monday
2117− "tuesday" -> return Tuesday
2118− "wednesday" -> return Wednesday
2119− "thursday" -> return Thursday
2120− "friday" -> return Friday
2121− "saturday" -> return Saturday
2122− "sunday" -> return Sunday
2123− _ -> fail "Invalid week day"
2124−
2125−instance FromJSONKey DayOfWeek where
2126− fromJSONKey = FromJSONKeyTextParser parseDayOfWeek
2127−
2128-------------------------------------------------------------------------------
1317-------------------------------------------------------------------------------
2129-- base Monoid/Semigroup
1318-- base Monoid/Semigroup
2130-------------------------------------------------------------------------------
1319-------------------------------------------------------------------------------
2131
1320
2132−instance FromJSON1 Monoid.Dual where
1321+instance FromJSON1 Dual where
2133− liftParseJSON p _ = fmap Monoid.Dual . p
1322+ liftParseJSON p _ = fmap Dual . p
2134− {-# INLINE liftParseJSON #-}
2135−
2136−instance FromJSON a => FromJSON (Monoid.Dual a) where
2137− parseJSON = parseJSON1
2138− {-# INLINE parseJSON #-}
2139−
2140−
2141−instance FromJSON1 Monoid.First where
2142− liftParseJSON p p' = fmap Monoid.First . liftParseJSON p p'
2143− {-# INLINE liftParseJSON #-}
2144−
2145−instance FromJSON a => FromJSON (Monoid.First a) where
2146− parseJSON = parseJSON1
2147− {-# INLINE parseJSON #-}
2148−
2149−
2150−instance FromJSON1 Monoid.Last where
2151− liftParseJSON p p' = fmap Monoid.Last . liftParseJSON p p'
2152− {-# INLINE liftParseJSON #-}
2153−
2154−instance FromJSON a => FromJSON (Monoid.Last a) where
2155− parseJSON = parseJSON1
2156− {-# INLINE parseJSON #-}
2157−
2158−
2159−instance FromJSON1 Semigroup.Min where
2160− liftParseJSON p _ a = Semigroup.Min <$> p a
2161− {-# INLINE liftParseJSON #-}
2162−
2163− liftParseJSONList _ p a = fmap Semigroup.Min <$> p a
2164− {-# INLINE liftParseJSONList #-}
2165−
2166−instance (FromJSON a) => FromJSON (Semigroup.Min a) where
2167− parseJSON = parseJSON1
2168− {-# INLINE parseJSON #-}
2169−
2170− parseJSONList = liftParseJSONList parseJSON parseJSONList
2171− {-# INLINE parseJSONList #-}
2172−
2173−
2174−instance FromJSON1 Semigroup.Max where
2175− liftParseJSON p _ a = Semigroup.Max <$> p a
2176− {-# INLINE liftParseJSON #-}
2177−
2178− liftParseJSONList _ p a = fmap Semigroup.Max <$> p a
2179− {-# INLINE liftParseJSONList #-}
2180−
2181−instance (FromJSON a) => FromJSON (Semigroup.Max a) where
2182− parseJSON = parseJSON1
2183− {-# INLINE parseJSON #-}
2184−
2185− parseJSONList = liftParseJSONList parseJSON parseJSONList
2186− {-# INLINE parseJSONList #-}
2187−
2188−
2189−instance FromJSON1 Semigroup.First where
2190− liftParseJSON p _ a = Semigroup.First <$> p a
2191− {-# INLINE liftParseJSON #-}
2192−
2193− liftParseJSONList _ p a = fmap Semigroup.First <$> p a
2194− {-# INLINE liftParseJSONList #-}
2195−
2196−instance (FromJSON a) => FromJSON (Semigroup.First a) where
2197− parseJSON = parseJSON1
2198− {-# INLINE parseJSON #-}
2199−
2200− parseJSONList = liftParseJSONList parseJSON parseJSONList
2201− {-# INLINE parseJSONList #-}
2202−
2203−
2204−instance FromJSON1 Semigroup.Last where
2205− liftParseJSON p _ a = Semigroup.Last <$> p a
2206 {-# INLINE liftParseJSON #-}
1323 {-# INLINE liftParseJSON #-}
2207
1324
2208− liftParseJSONList _ p a = fmap Semigroup.Last <$> p a
2209− {-# INLINE liftParseJSONList #-}
2210−
2211−instance (FromJSON a) => FromJSON (Semigroup.Last a) where
1325+instance FromJSON a => FromJSON (Dual a) where
2212 parseJSON = parseJSON1
1326 parseJSON = parseJSON1
2213 {-# INLINE parseJSON #-}
1327 {-# INLINE parseJSON #-}
2214
1328
2215− parseJSONList = liftParseJSONList parseJSON parseJSONList
2216− {-# INLINE parseJSONList #-}
2217−
2218
1329
2219−instance FromJSON1 Semigroup.WrappedMonoid where
1330+instance FromJSON1 First where
2220− liftParseJSON p _ a = Semigroup.WrapMonoid <$> p a
1331+ liftParseJSON p p' = fmap First . liftParseJSON p p'
2221 {-# INLINE liftParseJSON #-}
1332 {-# INLINE liftParseJSON #-}
2222
1333
2223− liftParseJSONList _ p a = fmap Semigroup.WrapMonoid <$> p a
2224− {-# INLINE liftParseJSONList #-}
2225−
2226−instance (FromJSON a) => FromJSON (Semigroup.WrappedMonoid a) where
1334+instance FromJSON a => FromJSON (First a) where
2227 parseJSON = parseJSON1
1335 parseJSON = parseJSON1
2228 {-# INLINE parseJSON #-}
1336 {-# INLINE parseJSON #-}
2229
1337
2230− parseJSONList = liftParseJSONList parseJSON parseJSONList
2231− {-# INLINE parseJSONList #-}
2232−
2233
1338
2234−instance FromJSON1 Semigroup.Option where
1339+instance FromJSON1 Last where
2235− liftParseJSON p p' = fmap Semigroup.Option . liftParseJSON p p'
1340+ liftParseJSON p p' = fmap Last . liftParseJSON p p'
2236 {-# INLINE liftParseJSON #-}
1341 {-# INLINE liftParseJSON #-}
2237
1342
2238−instance FromJSON a => FromJSON (Semigroup.Option a) where
1343+instance FromJSON a => FromJSON (Last a) where
2239 parseJSON = parseJSON1
1344 parseJSON = parseJSON1
2240 {-# INLINE parseJSON #-}
1345 {-# INLINE parseJSON #-}
2241
1346
@@ -2243,21 +1348,11 @@ instance FromJSON a => FromJSON (Semigroup.Option a) where
2243-- tagged
1348-- tagged
2244-------------------------------------------------------------------------------
1349-------------------------------------------------------------------------------
2245
1350
2246−instance FromJSON1 Proxy where
2247− {-# INLINE liftParseJSON #-}
2248− liftParseJSON _ _ = fromNull "Proxy" Proxy
2249−
2250instance FromJSON (Proxy a) where
1351instance FromJSON (Proxy a) where
2251 {-# INLINE parseJSON #-}
1352 {-# INLINE parseJSON #-}
2252− parseJSON = fromNull "Proxy" Proxy
1353+ parseJSON Null = pure Proxy
1354+ parseJSON v = typeMismatch "Proxy" v
2253
1355
2254−fromNull :: String -> a -> Value -> Parser a
2255−fromNull _ a Null = pure a
2256−fromNull c _ v = prependContext c (typeMismatch "Null" v)
2257−
2258−instance FromJSON2 Tagged where
2259− liftParseJSON2 _ _ p _ = fmap Tagged . p
2260− {-# INLINE liftParseJSON2 #-}
2261
1356
2262instance FromJSON1 (Tagged a) where
1357instance FromJSON1 (Tagged a) where
2263 liftParseJSON p _ = fmap Tagged . p
1358 liftParseJSON p _ = fmap Tagged . p
@@ -2275,22 +1370,40 @@ instance FromJSONKey b => FromJSONKey (Tagged a b) where
2275-- Instances for converting from map keys
1370-- Instances for converting from map keys
2276-------------------------------------------------------------------------------
1371-------------------------------------------------------------------------------
2277
1372
1373+instance FromJSONKey Text where
1374+ fromJSONKey = fromJSONKeyCoerce
1375+
1376+instance FromJSONKey Int where
1377+ -- not sure if there if there is already a helper in
1378+ -- aeson for doing this.
1379+ fromJSONKey = FromJSONKeyTextParser $ \t -> case TR.decimal t of
1380+ Left err -> fail err
1381+ Right (v,t2) -> if T.null t2
1382+ then return v
1383+ else fail "Was not an integer, had extra stuff."
1384+
2278instance (FromJSON a, FromJSON b) => FromJSONKey (a,b)
1385instance (FromJSON a, FromJSON b) => FromJSONKey (a,b)
2279instance (FromJSON a, FromJSON b, FromJSON c) => FromJSONKey (a,b,c)
1386instance (FromJSON a, FromJSON b, FromJSON c) => FromJSONKey (a,b,c)
2280instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSONKey (a,b,c,d)
1387instance (FromJSON a, FromJSON b, FromJSON c, FromJSON d) => FromJSONKey (a,b,c,d)
2281
1388
2282instance FromJSONKey Char where
1389instance FromJSONKey Char where
2283− fromJSONKey = FromJSONKeyTextParser parseChar
1390+ fromJSONKey = FromJSONKeyTextParser $ \t ->
1391+ if T.length t == 1
1392+ then return (T.index t 0)
1393+ else typeMismatch "Expected Char but String didn't contain exactly one character" (String t)
2284 fromJSONKeyList = FromJSONKeyText T.unpack
1394 fromJSONKeyList = FromJSONKeyText T.unpack
2285
1395
2286instance (FromJSONKey a, FromJSON a) => FromJSONKey [a] where
1396instance (FromJSONKey a, FromJSON a) => FromJSONKey [a] where
2287 fromJSONKey = fromJSONKeyList
1397 fromJSONKey = fromJSONKeyList
2288
1398
1399+instance (FromJSONKey a, FromJSON a) => FromJSONKey (Identity a) where
1400+ fromJSONKey = mapFromJSONKeyFunction Identity fromJSONKey
1401+
2289-------------------------------------------------------------------------------
1402-------------------------------------------------------------------------------
2290-- Tuple instances, see tuple-instances-from.hs
1403-- Tuple instances, see tuple-instances-from.hs
2291-------------------------------------------------------------------------------
1404-------------------------------------------------------------------------------
2292
1405
2293−instance FromJSON2 (,) where
1406+instance FromJSON2 ((,) ) where
2294 liftParseJSON2 pA _ pB _ = withArray "(a, b)" $ \t ->
1407 liftParseJSON2 pA _ pB _ = withArray "(a, b)" $ \t ->
2295 let n = V.length t
1408 let n = V.length t
2296 in if n == 2
1409 in if n == 2
Data/Aeson/Types/Generic.hs+22−35
@@ -1,14 +1,13 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE DeriveFunctor #-}
4−{-# LANGUAGE EmptyDataDecls #-}
3+{-# LANGUAGE EmptyDataDecls #-}
5−{-# LANGUAGE FlexibleInstances #-}
4+{-# LANGUAGE FlexibleInstances #-}
6{-# LANGUAGE FunctionalDependencies #-}
5{-# LANGUAGE FunctionalDependencies #-}
7−{-# LANGUAGE KindSignatures #-}
6+{-# LANGUAGE KindSignatures #-}
8−{-# LANGUAGE NoImplicitPrelude #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
9−{-# LANGUAGE ScopedTypeVariables #-}
8+{-# LANGUAGE ScopedTypeVariables #-}
10−{-# LANGUAGE TypeOperators #-}
9+{-# LANGUAGE TypeOperators #-}
11−{-# LANGUAGE UndecidableInstances #-}
10+{-# LANGUAGE UndecidableInstances #-}
12
11
13#include "overlapping-compat.h"
12#include "overlapping-compat.h"
14
13
@@ -24,29 +23,20 @@
24--
23--
25-- Helpers for generic derivations.
24-- Helpers for generic derivations.
26
25
27−module Data.Aeson.Types.Generic
26+module Data.Aeson.Types.Generic where
28− (
29− IsRecord
30− , AllNullary
31− , Tagged2(..)
32− , True
33− , False
34− , And
35− , Zero
36− , One
37− , ProductSize(..)
38− , (:*)(..)
39− ) where
40−
41−import Prelude.Compat
42
27
43import GHC.Generics
28import GHC.Generics
29+import Data.Proxy (Proxy (..))
44
30
45--------------------------------------------------------------------------------
31--------------------------------------------------------------------------------
46
32
47class IsRecord (f :: * -> *) isRecord | f -> isRecord
33class IsRecord (f :: * -> *) isRecord | f -> isRecord
34+ where
35+ isUnary :: f a -> Bool
36+ isUnary = const True
48
37
49instance (IsRecord f isRecord) => IsRecord (f :*: g) isRecord
38instance (IsRecord f isRecord) => IsRecord (f :*: g) isRecord
39+ where isUnary = const False
50#if MIN_VERSION_base(4,9,0)
40#if MIN_VERSION_base(4,9,0)
51instance OVERLAPPING_ IsRecord (M1 S ('MetaSel 'Nothing u ss ds) f) False
41instance OVERLAPPING_ IsRecord (M1 S ('MetaSel 'Nothing u ss ds) f) False
52#else
42#else
@@ -55,9 +45,9 @@ instance OVERLAPPING_ IsRecord (M1 S NoSelector f) False
55instance (IsRecord f isRecord) => IsRecord (M1 S c f) isRecord
45instance (IsRecord f isRecord) => IsRecord (M1 S c f) isRecord
56instance IsRecord (K1 i c) True
46instance IsRecord (K1 i c) True
57instance IsRecord Par1 True
47instance IsRecord Par1 True
58−instance IsRecord (Rec1 f) True
59instance IsRecord (f :.: g) True
48instance IsRecord (f :.: g) True
60instance IsRecord U1 False
49instance IsRecord U1 False
50+ where isUnary = const False
61
51
62--------------------------------------------------------------------------------
52--------------------------------------------------------------------------------
63
53
@@ -72,11 +62,9 @@ instance AllNullary (a :*: b) False
72instance AllNullary (a :.: b) False
62instance AllNullary (a :.: b) False
73instance AllNullary (K1 i c) False
63instance AllNullary (K1 i c) False
74instance AllNullary Par1 False
64instance AllNullary Par1 False
75−instance AllNullary (Rec1 f) False
76instance AllNullary U1 True
65instance AllNullary U1 True
77
66
78newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}
67newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}
79− deriving Functor
80
68
81--------------------------------------------------------------------------------
69--------------------------------------------------------------------------------
82
70
@@ -98,6 +86,12 @@ data Zero
98-- | A type-level indicator that 'ToJSON1' or 'FromJSON1' is being derived generically.
86-- | A type-level indicator that 'ToJSON1' or 'FromJSON1' is being derived generically.
99data One
87data One
100
88
89+proxyZero :: Proxy Zero
90+proxyZero = Proxy
91+
92+proxyOne :: Proxy One
93+proxyOne = Proxy
94+
101--------------------------------------------------------------------------------
95--------------------------------------------------------------------------------
102
96
103class ProductSize f where
97class ProductSize f where
@@ -109,10 +103,3 @@ instance (ProductSize a, ProductSize b) => ProductSize (a :*: b) where
109
103
110instance ProductSize (S1 s a) where
104instance ProductSize (S1 s a) where
111 productSize = Tagged2 1
105 productSize = Tagged2 1
112−
113−--------------------------------------------------------------------------------
114−
115−-- | Simple extensible tuple type to simplify passing around many parameters.
116−data a :* b = a :* b
117−
118−infixr 1 :*
Data/Aeson/Types/Internal.hs+32−195
@@ -1,9 +1,5 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE DeriveDataTypeable #-}
3−{-# LANGUAGE DeriveGeneric #-}
4−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1+{-# LANGUAGE CPP, DeriveDataTypeable, GeneralizedNewtypeDeriving, Rank2Types,
5−{-# LANGUAGE NoImplicitPrelude #-}
2+ RecordWildCards #-}
6−{-# LANGUAGE Rank2Types #-}
7#if __GLASGOW_HASKELL__ >= 800
3#if __GLASGOW_HASKELL__ >= 800
8-- a) THQ works on cross-compilers and unregisterised GHCs
4-- a) THQ works on cross-compilers and unregisterised GHCs
9-- b) may make compilation faster as no dynamic loading is ever needed (not sure about this)
5-- b) may make compilation faster as no dynamic loading is ever needed (not sure about this)
@@ -45,33 +41,16 @@ module Data.Aeson.Types.Internal
45 , parseEither
41 , parseEither
46 , parseMaybe
42 , parseMaybe
47 , modifyFailure
43 , modifyFailure
48− , prependFailure
49− , parserThrowError
50− , parserCatchError
51 , formatError
44 , formatError
52− , formatPath
53− , formatRelativePath
54 , (<?>)
45 , (<?>)
55 -- * Constructors and accessors
46 -- * Constructors and accessors
56 , object
47 , object
57
48
58 -- * Generic and TH encoding configuration
49 -- * Generic and TH encoding configuration
59− , Options(
50+ , Options(..)
60− fieldLabelModifier
61− , constructorTagModifier
62− , allNullaryToStringTag
63− , omitNothingFields
64− , sumEncoding
65− , unwrapUnaryRecords
66− , tagSingleConstructors
67− , rejectUnknownFields
68− )
69−
70 , SumEncoding(..)
51 , SumEncoding(..)
71− , JSONKeyOptions(keyModifier)
72 , defaultOptions
52 , defaultOptions
73 , defaultTaggedObject
53 , defaultTaggedObject
74− , defaultJSONKeyOptions
75
54
76 -- * Used for changing CamelCase names into something else.
55 -- * Used for changing CamelCase names into something else.
77 , camelTo
56 , camelTo
@@ -81,34 +60,35 @@ module Data.Aeson.Types.Internal
81 , DotNetTime(..)
60 , DotNetTime(..)
82 ) where
61 ) where
83
62
84−import Prelude.Compat
85−
86−import Control.Applicative (Alternative(..))
87import Control.Arrow (first)
63import Control.Arrow (first)
64+import Control.Applicative
88import Control.DeepSeq (NFData(..))
65import Control.DeepSeq (NFData(..))
89import Control.Monad (MonadPlus(..), ap)
66import Control.Monad (MonadPlus(..), ap)
67+import qualified Control.Monad.Fail as Fail
90import Data.Char (isLower, isUpper, toLower, isAlpha, isAlphaNum)
68import Data.Char (isLower, isUpper, toLower, isAlpha, isAlphaNum)
91import Data.Data (Data)
69import Data.Data (Data)
92import Data.Foldable (foldl')
70import Data.Foldable (foldl')
93import Data.HashMap.Strict (HashMap)
71import Data.HashMap.Strict (HashMap)
94import Data.Hashable (Hashable(..))
72import Data.Hashable (Hashable(..))
95−import Data.List (intercalate)
96−import Data.Scientific (Scientific)
97import Data.Semigroup (Semigroup((<>)))
73import Data.Semigroup (Semigroup((<>)))
74+import Data.Scientific (Scientific)
98import Data.String (IsString(..))
75import Data.String (IsString(..))
99import Data.Text (Text, pack, unpack)
76import Data.Text (Text, pack, unpack)
100import Data.Time (UTCTime)
77import Data.Time (UTCTime)
101import Data.Time.Format (FormatTime)
78import Data.Time.Format (FormatTime)
102import Data.Typeable (Typeable)
79import Data.Typeable (Typeable)
103import Data.Vector (Vector)
80import Data.Vector (Vector)
104−import GHC.Generics (Generic)
105−import qualified Control.Monad as Monad
106−import qualified Control.Monad.Fail as Fail
107import qualified Data.HashMap.Strict as H
81import qualified Data.HashMap.Strict as H
108import qualified Data.Scientific as S
82import qualified Data.Scientific as S
109import qualified Data.Vector as V
83import qualified Data.Vector as V
110import qualified Language.Haskell.TH.Syntax as TH
84import qualified Language.Haskell.TH.Syntax as TH
111
85
86+#if !MIN_VERSION_base(4,8,0)
87+import Data.Foldable (Foldable(..))
88+import Data.Monoid (Monoid(..))
89+import Data.Traversable (Traversable(..))
90+#endif
91+
112#if !MIN_VERSION_unordered_containers(0,2,6)
92#if !MIN_VERSION_unordered_containers(0,2,6)
113import Data.List (sort)
93import Data.List (sort)
114#endif
94#endif
@@ -121,7 +101,7 @@ data JSONPathElement = Key Text
121 | Index {-# UNPACK #-} !Int
101 | Index {-# UNPACK #-} !Int
122 -- ^ JSON path element of an index into an
102 -- ^ JSON path element of an index into an
123 -- array, \"array[index]\".
103 -- array, \"array[index]\".
124− deriving (Eq, Show, Typeable, Ord)
104+ deriving (Eq, Show, Typeable)
125type JSONPath = [JSONPathElement]
105type JSONPath = [JSONPathElement]
126
106
127-- | The internal result of running a 'Parser'.
107-- | The internal result of running a 'Parser'.
@@ -156,7 +136,7 @@ instance Functor Result where
156 fmap _ (Error err) = Error err
136 fmap _ (Error err) = Error err
157 {-# INLINE fmap #-}
137 {-# INLINE fmap #-}
158
138
159−instance Monad.Monad IResult where
139+instance Monad IResult where
160 return = pure
140 return = pure
161 {-# INLINE return #-}
141 {-# INLINE return #-}
162
142
@@ -164,16 +144,14 @@ instance Monad.Monad IResult where
164 IError path err >>= _ = IError path err
144 IError path err >>= _ = IError path err
165 {-# INLINE (>>=) #-}
145 {-# INLINE (>>=) #-}
166
146
167−#if !(MIN_VERSION_base(4,13,0))
168 fail = Fail.fail
147 fail = Fail.fail
169 {-# INLINE fail #-}
148 {-# INLINE fail #-}
170−#endif
171
149
172instance Fail.MonadFail IResult where
150instance Fail.MonadFail IResult where
173 fail err = IError [] err
151 fail err = IError [] err
174 {-# INLINE fail #-}
152 {-# INLINE fail #-}
175
153
176−instance Monad.Monad Result where
154+instance Monad Result where
177 return = pure
155 return = pure
178 {-# INLINE return #-}
156 {-# INLINE return #-}
179
157
@@ -181,10 +159,8 @@ instance Monad.Monad Result where
181 Error err >>= _ = Error err
159 Error err >>= _ = Error err
182 {-# INLINE (>>=) #-}
160 {-# INLINE (>>=) #-}
183
161
184−#if !(MIN_VERSION_base(4,13,0))
185 fail = Fail.fail
162 fail = Fail.fail
186 {-# INLINE fail #-}
163 {-# INLINE fail #-}
187−#endif
188
164
189instance Fail.MonadFail Result where
165instance Fail.MonadFail Result where
190 fail err = Error err
166 fail err = Error err
@@ -281,9 +257,7 @@ type Failure f r = JSONPath -> String -> f r
281-- | Success continuation.
257-- | Success continuation.
282type Success a f r = a -> f r
258type Success a f r = a -> f r
283
259
284−-- | A JSON parser. N.B. This might not fit your usual understanding of
260+-- | A JSON parser.
285−-- "parser". Instead you might like to think of 'Parser' as a "parse result",
286−-- i.e. a parser to which the input has already been applied.
287newtype Parser a = Parser {
261newtype Parser a = Parser {
288 runParser :: forall f r.
262 runParser :: forall f r.
289 JSONPath
263 JSONPath
@@ -292,17 +266,14 @@ newtype Parser a = Parser {
292 -> f r
266 -> f r
293 }
267 }
294
268
295−instance Monad.Monad Parser where
269+instance Monad Parser where
296 m >>= g = Parser $ \path kf ks -> let ks' a = runParser (g a) path kf ks
270 m >>= g = Parser $ \path kf ks -> let ks' a = runParser (g a) path kf ks
297 in runParser m path kf ks'
271 in runParser m path kf ks'
298 {-# INLINE (>>=) #-}
272 {-# INLINE (>>=) #-}
299 return = pure
273 return = pure
300 {-# INLINE return #-}
274 {-# INLINE return #-}
301−
302−#if !(MIN_VERSION_base(4,13,0))
303 fail = Fail.fail
275 fail = Fail.fail
304 {-# INLINE fail #-}
276 {-# INLINE fail #-}
305−#endif
306
277
307instance Fail.MonadFail Parser where
278instance Fail.MonadFail Parser where
308 fail msg = Parser $ \path kf _ks -> kf (reverse path) msg
279 fail msg = Parser $ \path kf _ks -> kf (reverse path) msg
@@ -345,7 +316,8 @@ instance Monoid (Parser a) where
345apP :: Parser (a -> b) -> Parser a -> Parser b
316apP :: Parser (a -> b) -> Parser a -> Parser b
346apP d e = do
317apP d e = do
347 b <- d
318 b <- d
348− b <$> e
319+ a <- e
320+ return (b a)
349{-# INLINE apP #-}
321{-# INLINE apP #-}
350
322
351-- | A JSON \"object\" (key\/value map).
323-- | A JSON \"object\" (key\/value map).
@@ -361,7 +333,7 @@ data Value = Object !Object
361 | Number !Scientific
333 | Number !Scientific
362 | Bool !Bool
334 | Bool !Bool
363 | Null
335 | Null
364− deriving (Eq, Read, Show, Typeable, Data, Generic)
336+ deriving (Eq, Read, Show, Typeable, Data)
365
337
366-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
338-- | A newtype wrapper for 'UTCTime' that uses the same non-standard
367-- serialization format as Microsoft .NET, whose
339-- serialization format as Microsoft .NET, whose
@@ -461,17 +433,7 @@ parseEither m v = runParser (m v) [] onError Right
461-- | Annotate an error message with a
433-- | Annotate an error message with a
462-- <http://goessner.net/articles/JsonPath/ JSONPath> error location.
434-- <http://goessner.net/articles/JsonPath/ JSONPath> error location.
463formatError :: JSONPath -> String -> String
435formatError :: JSONPath -> String -> String
464−formatError path msg = "Error in " ++ formatPath path ++ ": " ++ msg
436+formatError path msg = "Error in " ++ (format "$" path) ++ ": " ++ msg
465−
466−-- | Format a <http://goessner.net/articles/JsonPath/ JSONPath> as a 'String',
467−-- representing the root object as @$@.
468−formatPath :: JSONPath -> String
469−formatPath path = "$" ++ formatRelativePath path
470−
471−-- | Format a <http://goessner.net/articles/JsonPath/ JSONPath> as a 'String'
472−-- which represents the path relative to some root object.
473−formatRelativePath :: JSONPath -> String
474−formatRelativePath path = format "" path
475 where
437 where
476 format :: String -> JSONPath -> String
438 format :: String -> JSONPath -> String
477 format pfx [] = pfx
439 format pfx [] = pfx
@@ -534,40 +496,13 @@ p <?> pathElem = Parser $ \path kf ks -> runParser p (pathElem:path) kf ks
534--
496--
535-- Since 0.6.2.0
497-- Since 0.6.2.0
536modifyFailure :: (String -> String) -> Parser a -> Parser a
498modifyFailure :: (String -> String) -> Parser a -> Parser a
537−modifyFailure f (Parser p) = Parser $ \path kf ks ->
499+modifyFailure f (Parser p) = Parser $ \path kf ks -> p path (\p' m -> kf p' (f m)) ks
538− p path (\p' m -> kf p' (f m)) ks
539−
540−-- | If the inner 'Parser' failed, prepend the given string to the failure
541−-- message.
542−--
543−-- @
544−-- 'prependFailure' s = 'modifyFailure' (s '++')
545−-- @
546−prependFailure :: String -> Parser a -> Parser a
547−prependFailure = modifyFailure . (++)
548−
549−-- | Throw a parser error with an additional path.
550−--
551−-- @since 1.2.1.0
552−parserThrowError :: JSONPath -> String -> Parser a
553−parserThrowError path' msg = Parser $ \path kf _ks ->
554− kf (reverse path ++ path') msg
555−
556−-- | A handler function to handle previous errors and return to normal execution.
557−--
558−-- @since 1.2.1.0
559−parserCatchError :: Parser a -> (JSONPath -> String -> Parser a) -> Parser a
560−parserCatchError (Parser p) handler = Parser $ \path kf ks ->
561− p path (\e msg -> runParser (handler e msg) path kf ks) ks
562
500
563--------------------------------------------------------------------------------
501--------------------------------------------------------------------------------
564-- Generic and TH encoding configuration
502-- Generic and TH encoding configuration
565--------------------------------------------------------------------------------
503--------------------------------------------------------------------------------
566
504
567-- | Options that specify how to encode\/decode your datatype to\/from JSON.
505-- | Options that specify how to encode\/decode your datatype to\/from JSON.
568−--
569−-- Options can be set using record syntax on 'defaultOptions' with the fields
570−-- below.
571data Options = Options
506data Options = Options
572 { fieldLabelModifier :: String -> String
507 { fieldLabelModifier :: String -> String
573 -- ^ Function applied to field labels.
508 -- ^ Function applied to field labels.
@@ -584,67 +519,24 @@ data Options = Options
584 -- ^ If 'True' record fields with a 'Nothing' value will be
519 -- ^ If 'True' record fields with a 'Nothing' value will be
585 -- omitted from the resulting object. If 'False' the resulting
520 -- omitted from the resulting object. If 'False' the resulting
586 -- object will include those fields mapping to @null@.
521 -- object will include those fields mapping to @null@.
587− --
588− -- === Note
589− --
590− -- Setting 'omitNothingFields' to 'True' only affects fields which are of
591− -- type 'Maybe' /uniformly/ in the 'ToJSON' or 'FromJSON' instance. In
592− -- particular, if the type of a field is declared as a type variable, it
593− -- will not be omitted from the JSON object, unless the field is
594− -- specialized upfront in the instance.
595− --
596− -- ==== __Example__
597− --
598− -- The generic instance for the following type @Fruit@ depends on whether
599− -- the instance head is @Fruit a@ or @Fruit (Maybe a)@.
600− --
601− -- @
602− -- data Fruit a =
603− -- { apples :: a -- A field whose type is a type variable.
604− -- , oranges :: 'Maybe' Int
605− -- }
606− --
607− -- options :: 'Options'
608− -- options = 'defaultOptions' { 'omitNothingFields' = 'True' }
609− --
610− -- -- apples required, oranges optional
611− -- -- Even if 'Data.Aeson.fromJSON' is then specialized to (Fruit ('Maybe' a)).
612− -- instance 'Data.Aeson.FromJSON' a => 'Data.Aeson.FromJSON' (Fruit a) where
613− -- 'Data.Aeson.fromJSON' = 'Data.Aeson.genericFromJSON' options
614− --
615− -- -- apples optional, oranges optional
616− -- -- In this instance, the field apples is uniformly of type ('Maybe' a).
617− -- instance 'Data.Aeson.FromJSON' a => 'Data.Aeson.FromJSON' (Fruit ('Maybe' a)) where
618− -- 'Data.Aeson.fromJSON' = 'Data.Aeson.genericFromJSON' options
619− -- @
620 , sumEncoding :: SumEncoding
522 , sumEncoding :: SumEncoding
621 -- ^ Specifies how to encode constructors of a sum datatype.
523 -- ^ Specifies how to encode constructors of a sum datatype.
622 , unwrapUnaryRecords :: Bool
524 , unwrapUnaryRecords :: Bool
623 -- ^ Hide the field name when a record constructor has only one
525 -- ^ Hide the field name when a record constructor has only one
624 -- field, like a newtype.
526 -- field, like a newtype.
625− , tagSingleConstructors :: Bool
626− -- ^ Encode types with a single constructor as sums,
627− -- so that `allNullaryToStringTag` and `sumEncoding` apply.
628− , rejectUnknownFields :: Bool
629− -- ^ Applies only to 'Data.Aeson.FromJSON' instances. If a field appears in
630− -- the parsed object map, but does not appear in the target object, parsing
631− -- will fail, with an error message indicating which fields were unknown.
632 }
527 }
633
528
634instance Show Options where
529instance Show Options where
635− show (Options f c a o s u t r) =
530+ show Options{..} = "Options {" ++
636− "Options {"
637− ++ intercalate ", "
638− [ "fieldLabelModifier =~ " ++ show (f "exampleField")
531+ "fieldLabelModifier =~ " ++
532+ show (fieldLabelModifier "exampleField") ++ ", " ++
639− , "constructorTagModifier =~ " ++ show (c "ExampleConstructor")
533+ "constructorTagModifier =~ " ++
534+ show (constructorTagModifier "ExampleConstructor") ++ ", " ++
640− , "allNullaryToStringTag = " ++ show a
535+ "allNullaryToStringTag = " ++ show allNullaryToStringTag ++ ", " ++
641− , "omitNothingFields = " ++ show o
536+ "omitNothingFields = " ++ show omitNothingFields ++ ", " ++
642− , "sumEncoding = " ++ show s
537+ "sumEncoding = " ++ show sumEncoding ++ ", " ++
643− , "unwrapUnaryRecords = " ++ show u
538+ "unwrapUnaryRecords = " ++ show unwrapUnaryRecords ++
644− , "tagSingleConstructors = " ++ show t
645− , "rejectUnknownFields = " ++ show r
646− ]
647− ++ "}"
539+ "}"
648
540
649-- | Specifies how to encode constructors of a sum datatype.
541-- | Specifies how to encode constructors of a sum datatype.
650data SumEncoding =
542data SumEncoding =
@@ -660,20 +552,6 @@ data SumEncoding =
660 -- by the encoded value of that field! If the constructor is not a
552 -- by the encoded value of that field! If the constructor is not a
661 -- record the encoded constructor contents will be stored under
553 -- record the encoded constructor contents will be stored under
662 -- the 'contentsFieldName' field.
554 -- the 'contentsFieldName' field.
663− | UntaggedValue
664− -- ^ Constructor names won't be encoded. Instead only the contents of the
665− -- constructor will be encoded as if the type had a single constructor. JSON
666− -- encodings have to be disjoint for decoding to work properly.
667− --
668− -- When decoding, constructors are tried in the order of definition. If some
669− -- encodings overlap, the first one defined will succeed.
670− --
671− -- /Note:/ Nullary constructors are encoded as strings (using
672− -- 'constructorTagModifier'). Having a nullary constructor alongside a
673− -- single field constructor that encodes to a string leads to ambiguity.
674− --
675− -- /Note:/ Only the last error is kept when decoding, so in the case of
676− -- malformed JSON, only an error for the last constructor will be reported.
677 | ObjectWithSingleField
555 | ObjectWithSingleField
678 -- ^ A constructor will be encoded to an object with a single
556 -- ^ A constructor will be encoded to an object with a single
679 -- field named after the constructor tag (modified by the
557 -- field named after the constructor tag (modified by the
@@ -686,33 +564,6 @@ data SumEncoding =
686 -- contents of the constructor.
564 -- contents of the constructor.
687 deriving (Eq, Show)
565 deriving (Eq, Show)
688
566
689−-- | Options for encoding keys with 'Data.Aeson.Types.genericFromJSONKey' and
690−-- 'Data.Aeson.Types.genericToJSONKey'.
691−data JSONKeyOptions = JSONKeyOptions
692− { keyModifier :: String -> String
693− -- ^ Function applied to keys. Its result is what goes into the encoded
694− -- 'Value'.
695− --
696− -- === __Example__
697− --
698− -- The following instances encode the constructor @Bar@ to lower-case keys
699− -- @\"bar\"@.
700− --
701− -- @
702− -- data Foo = Bar
703− -- deriving 'Generic'
704− --
705− -- opts :: 'JSONKeyOptions'
706− -- opts = 'defaultJSONKeyOptions' { 'keyModifier' = 'toLower' }
707− --
708− -- instance 'ToJSONKey' Foo where
709− -- 'toJSONKey' = 'genericToJSONKey' opts
710− --
711− -- instance 'FromJSONKey' Foo where
712− -- 'fromJSONKey' = 'genericFromJSONKey' opts
713− -- @
714− }
715−
716-- | Default encoding 'Options':
567-- | Default encoding 'Options':
717--
568--
718-- @
569-- @
@@ -723,8 +574,6 @@ data JSONKeyOptions = JSONKeyOptions
723-- , 'omitNothingFields' = False
574-- , 'omitNothingFields' = False
724-- , 'sumEncoding' = 'defaultTaggedObject'
575-- , 'sumEncoding' = 'defaultTaggedObject'
725-- , 'unwrapUnaryRecords' = False
576-- , 'unwrapUnaryRecords' = False
726−-- , 'tagSingleConstructors' = False
727−-- , 'rejectUnknownFields' = False
728-- }
577-- }
729-- @
578-- @
730defaultOptions :: Options
579defaultOptions :: Options
@@ -735,8 +584,6 @@ defaultOptions = Options
735 , omitNothingFields = False
584 , omitNothingFields = False
736 , sumEncoding = defaultTaggedObject
585 , sumEncoding = defaultTaggedObject
737 , unwrapUnaryRecords = False
586 , unwrapUnaryRecords = False
738− , tagSingleConstructors = False
739− , rejectUnknownFields = False
740 }
587 }
741
588
742-- | Default 'TaggedObject' 'SumEncoding' options:
589-- | Default 'TaggedObject' 'SumEncoding' options:
@@ -753,16 +600,6 @@ defaultTaggedObject = TaggedObject
753 , contentsFieldName = "contents"
600 , contentsFieldName = "contents"
754 }
601 }
755
602
756−-- | Default 'JSONKeyOptions':
757−--
758−-- @
759−-- defaultJSONKeyOptions = 'JSONKeyOptions'
760−-- { 'keyModifier' = 'id'
761−-- }
762−-- @
763−defaultJSONKeyOptions :: JSONKeyOptions
764−defaultJSONKeyOptions = JSONKeyOptions id
765−
766-- | Converts from CamelCase to another lower case, interspersing
603-- | Converts from CamelCase to another lower case, interspersing
767-- the character between all capital letters and their previous
604-- the character between all capital letters and their previous
768-- entries, except those capital letters that appear together,
605-- entries, except those capital letters that appear together,
Data/Aeson/Types/ToJSON.hs+879−1362
@@ -1,27 +1,29 @@
1−{-# LANGUAGE CPP #-}
1+{-# LANGUAGE CPP #-}
2+{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DefaultSignatures #-}
3+{-# LANGUAGE DefaultSignatures #-}
3−{-# LANGUAGE EmptyDataDecls #-}
4−{-# LANGUAGE FlexibleContexts #-}
4+{-# LANGUAGE FlexibleContexts #-}
5−{-# LANGUAGE FlexibleInstances #-}
5+{-# LANGUAGE FlexibleInstances #-}
6−{-# LANGUAGE FunctionalDependencies #-}
7−{-# LANGUAGE GADTs #-}
6+{-# LANGUAGE GADTs #-}
8−{-# LANGUAGE NoImplicitPrelude #-}
7+{-# LANGUAGE MultiParamTypeClasses #-}
8+{-# LANGUAGE NamedFieldPuns #-}
9−{-# LANGUAGE OverloadedStrings #-}
9+{-# LANGUAGE OverloadedStrings #-}
10−{-# LANGUAGE PatternGuards #-}
10+{-# LANGUAGE PatternGuards #-}
11−{-# LANGUAGE PolyKinds #-}
12−{-# LANGUAGE RecordWildCards #-}
11+{-# LANGUAGE RecordWildCards #-}
13−{-# LANGUAGE ScopedTypeVariables #-}
12+{-# LANGUAGE ScopedTypeVariables #-}
14−{-# LANGUAGE TypeOperators #-}
13+{-# LANGUAGE TypeOperators #-}
14+{-# LANGUAGE TypeSynonymInstances #-}
15−{-# LANGUAGE UndecidableInstances #-}
15+{-# LANGUAGE UndecidableInstances #-}
16+
17+#if __GLASGOW_HASKELL__ >= 706
18+{-# LANGUAGE PolyKinds #-}
19+#endif
16
20
17#include "overlapping-compat.h"
21#include "overlapping-compat.h"
18−#include "incoherent-compat.h"
19
22
20-- TODO: Drop this when we remove support for Data.Attoparsec.Number
23-- TODO: Drop this when we remove support for Data.Attoparsec.Number
21{-# OPTIONS_GHC -fno-warn-deprecations #-}
24{-# OPTIONS_GHC -fno-warn-deprecations #-}
22
25
23−module Data.Aeson.Types.ToJSON
26+module Data.Aeson.Types.ToJSON (
24− (
25 -- * Core JSON classes
27 -- * Core JSON classes
26 ToJSON(..)
28 ToJSON(..)
27 -- * Liftings to unary and binary type constructors
29 -- * Liftings to unary and binary type constructors
@@ -33,7 +35,7 @@ module Data.Aeson.Types.ToJSON
33 , toEncoding2
35 , toEncoding2
34 -- * Generic JSON classes
36 -- * Generic JSON classes
35 , GToJSON(..)
37 , GToJSON(..)
36− , ToArgs(..)
38+ , GToEncoding(..)
37 , genericToJSON
39 , genericToJSON
38 , genericToEncoding
40 , genericToEncoding
39 , genericLiftToJSON
41 , genericLiftToJSON
@@ -41,107 +43,89 @@ module Data.Aeson.Types.ToJSON
41 -- * Classes and types for map keys
43 -- * Classes and types for map keys
42 , ToJSONKey(..)
44 , ToJSONKey(..)
43 , ToJSONKeyFunction(..)
45 , ToJSONKeyFunction(..)
44− , toJSONKeyText
45 , contramapToJSONKeyFunction
46 , contramapToJSONKeyFunction
46−
47− , GToJSONKey()
48− , genericToJSONKey
49−
50 -- * Object key-value pairs
47 -- * Object key-value pairs
51 , KeyValue(..)
48 , KeyValue(..)
52− , KeyValuePair(..)
53− , FromPairs(..)
54 -- * Functions needed for documentation
49 -- * Functions needed for documentation
55 -- * Encoding functions
50 -- * Encoding functions
56 , listEncoding
51 , listEncoding
57 , listValue
52 , listValue
58 ) where
53 ) where
59
54
55+import Prelude ()
60import Prelude.Compat
56import Prelude.Compat
61
57
62−import Control.Applicative (Const(..))
63−import Control.Monad.ST (ST)
64−import Data.Aeson.Encoding (Encoding, Encoding', Series, dict, emptyArray_)
58+import Data.Aeson.Encoding.Internal (Encoding (..), Series, dict, emptyArray_,
65−import Data.Aeson.Encoding.Internal ((>*<))
59+ tuple, (>*<))
66−import Data.Aeson.Internal.Functions (mapHashKeyVal, mapKeyVal)
60+import Data.Aeson.Functions (mapHashKeyVal, mapKeyVal)
67−import Data.Aeson.Types.Generic (AllNullary, False, IsRecord, One, ProductSize, Tagged2(..), True, Zero, productSize)
61+import Data.Aeson.Types.Generic
68import Data.Aeson.Types.Internal
62import Data.Aeson.Types.Internal
63+
64+import qualified Data.Aeson.Encode.Builder as EB
65+import qualified Data.Aeson.Encoding.Internal as E
66+
67+import Control.Applicative (Const (..))
68+import Control.Monad.ST (ST)
69−import Data.Attoparsec.Number (Number(..))
69+import Data.Attoparsec.Number (Number (..))
70−import Data.Bits (unsafeShiftR)
70+import Data.Bits (unsafeShiftR)
71−import Data.DList (DList)
71+import Data.DList (DList)
72−import Data.Fixed (Fixed, HasResolution, Nano)
72+import Data.Fixed (Fixed, HasResolution)
73−import Data.Foldable (toList)
73+import Data.Foldable (toList)
74−import Data.Functor.Compose (Compose(..))
74+import Data.Functor.Identity (Identity (..))
75−import Data.Functor.Contravariant (Contravariant (..))
76−import Data.Functor.Identity (Identity(..))
77−import Data.Functor.Product (Product(..))
78−import Data.Functor.Sum (Sum(..))
79−import Data.Int (Int16, Int32, Int64, Int8)
75+import Data.Int (Int16, Int32, Int64, Int8)
80−import Data.List (intersperse)
76+import Data.List (intersperse)
81−import Data.List.NonEmpty (NonEmpty(..))
77+import Data.List.NonEmpty (NonEmpty (..))
82−import Data.Semigroup ((<>))
78+import Data.Monoid (Dual (..), First (..), Last (..), (<>))
83−import Data.Proxy (Proxy(..))
79+import Data.Proxy (Proxy (..))
84−import Data.Ratio (Ratio, denominator, numerator)
80+import Data.Ratio (Ratio, denominator, numerator)
85−import Data.Scientific (Scientific)
81+import Data.Scientific (Scientific)
86−import Data.Tagged (Tagged(..))
82+import Data.Tagged (Tagged (..))
87−import Data.Text (Text, pack)
83+import Data.Text (Text, pack)
88−import Data.Time (Day, DiffTime, LocalTime, NominalDiffTime, TimeOfDay, UTCTime, ZonedTime)
84+import Data.Time (Day, LocalTime, NominalDiffTime, TimeOfDay,
89−import Data.Time.Calendar.Compat (CalendarDiffDays (..), DayOfWeek (..))
85+ UTCTime, ZonedTime)
90−import Data.Time.LocalTime.Compat (CalendarDiffTime (..))
91−import Data.Time.Clock.System.Compat (SystemTime (..))
92−import Data.Time.Format.Compat (FormatTime, formatTime, defaultTimeLocale)
86+import Data.Time.Format (FormatTime, formatTime)
87+import Data.Time.Locale.Compat (defaultTimeLocale)
93−import Data.Vector (Vector)
88+import Data.Vector (Vector)
94−import Data.Version (Version, showVersion)
89+import Data.Version (Version, showVersion)
95−import Data.Void (Void, absurd)
96−import Data.Word (Word16, Word32, Word64, Word8)
90+import Data.Word (Word16, Word32, Word64, Word8)
97−import Foreign.Storable (Storable)
91+import Foreign.Storable (Storable)
98−import Foreign.C.Types (CTime (..))
99import GHC.Generics
92import GHC.Generics
100−import Numeric.Natural (Natural)
93+import Numeric.Natural (Natural)
101−import qualified Data.Aeson.Encoding as E
94+
102−import qualified Data.Aeson.Encoding.Internal as E (InArray, comma, econcat, retagEncoding)
95+import qualified Data.ByteString.Builder as B
103−import qualified Data.ByteString.Lazy as L
96+import qualified Data.ByteString.Lazy as L
104−import qualified Data.DList as DList
97+import qualified Data.DList as DList
105−import qualified Data.HashMap.Strict as H
98+import qualified Data.HashMap.Strict as H
106−import qualified Data.HashSet as HashSet
99+import qualified Data.HashSet as HashSet
107−import qualified Data.IntMap as IntMap
100+import qualified Data.IntMap as IntMap
108−import qualified Data.IntSet as IntSet
101+import qualified Data.IntSet as IntSet
109−import qualified Data.List.NonEmpty as NE
102+import qualified Data.List.NonEmpty as NE
110−import qualified Data.Map as M
103+import qualified Data.Map as M
111−import qualified Data.Monoid as Monoid
112−import qualified Data.Scientific as Scientific
104+import qualified Data.Scientific as Scientific
113−import qualified Data.Semigroup as Semigroup
114−import qualified Data.Sequence as Seq
105+import qualified Data.Sequence as Seq
115−import qualified Data.Set as Set
106+import qualified Data.Set as Set
116−import qualified Data.Text as T
107+import qualified Data.Text as T
117−import qualified Data.Text.Encoding as T
108+import qualified Data.Text.Encoding as T
118−import qualified Data.Text.Lazy as LT
109+import qualified Data.Text.Lazy as LT
119−import qualified Data.Tree as Tree
110+import qualified Data.Text.Lazy.Builder as LTB
120−import qualified Data.UUID.Types as UUID
111+import qualified Data.Text.Lazy.Builder.Int as LTBI
121−import qualified Data.Vector as V
112+import qualified Data.Tree as Tree
113+import qualified Data.Vector as V
122−import qualified Data.Vector.Generic as VG
114+import qualified Data.Vector.Generic as VG
123−import qualified Data.Vector.Mutable as VM
115+import qualified Data.Vector.Mutable as VM
124−import qualified Data.Vector.Primitive as VP
116+import qualified Data.Vector.Primitive as VP
125−import qualified Data.Vector.Storable as VS
117+import qualified Data.Vector.Storable as VS
126−import qualified Data.Vector.Unboxed as VU
118+import qualified Data.Vector.Unboxed as VU
127−
119+
128−import qualified Data.Aeson.Encoding.Builder as EB
120+builder :: ToJSON a => a -> B.Builder
129−import qualified Data.ByteString.Builder as B
121+builder = fromEncoding . toEncoding
130−
131−import qualified GHC.Exts as Exts
132−import qualified Data.Primitive.Array as PM
133−import qualified Data.Primitive.SmallArray as PM
134−import qualified Data.Primitive.Types as PM
135−
136−#if MIN_VERSION_primitive(0,6,4)
137−#if !MIN_VERSION_primitive(0,7,0)
138−import qualified Data.Primitive.UnliftedArray as PM
139−#endif
140−import qualified Data.Primitive.PrimArray as PM
141−#endif
142
122
143toJSONPair :: (a -> Value) -> (b -> Value) -> (a, b) -> Value
123toJSONPair :: (a -> Value) -> (b -> Value) -> (a, b) -> Value
144−toJSONPair a b = liftToJSON2 a (listValue a) b (listValue b)
124+toJSONPair keySerialiser valSerializer (a, b) = Array $ V.create $ do
125+ mv <- VM.unsafeNew 2
126+ VM.unsafeWrite mv 0 (keySerialiser a)
127+ VM.unsafeWrite mv 1 (valSerializer b)
128+ return mv
145{-# INLINE toJSONPair #-}
129{-# INLINE toJSONPair #-}
146
130
147realFloatToJSON :: RealFloat a => a -> Value
131realFloatToJSON :: RealFloat a => a -> Value
@@ -150,59 +134,63 @@ realFloatToJSON d
150 | otherwise = Number $ Scientific.fromFloatDigits d
134 | otherwise = Number $ Scientific.fromFloatDigits d
151{-# INLINE realFloatToJSON #-}
135{-# INLINE realFloatToJSON #-}
152
136
137+realFloatToEncoding :: RealFloat a => a -> Encoding
138+realFloatToEncoding d
139+ | isNaN d || isInfinite d = Encoding EB.null_
140+ | otherwise = toEncoding (Scientific.fromFloatDigits d)
141+{-# INLINE realFloatToEncoding #-}
142+
153-------------------------------------------------------------------------------
143-------------------------------------------------------------------------------
154-- Generics
144-- Generics
155-------------------------------------------------------------------------------
145-------------------------------------------------------------------------------
156
146
157-- | Class of generic representation types that can be converted to
147-- | Class of generic representation types that can be converted to
158-- JSON.
148-- JSON.
159−class GToJSON enc arity f where
149+class GToJSON arity f where
160 -- | This method (applied to 'defaultOptions') is used as the
150 -- | This method (applied to 'defaultOptions') is used as the
161− -- default generic implementation of 'toJSON'
151+ -- default generic implementation of 'toJSON' (if the @arity@ is 'Zero')
162− -- (with @enc ~ 'Value'@ and @arity ~ 'Zero'@)
163− -- and 'liftToJSON' (if the @arity@ is 'One').
152+ -- or 'liftToJSON' (if the @arity@ is 'One').
164− --
165− -- It also provides a generic implementation of 'toEncoding'
166− -- (with @enc ~ 'Encoding'@ and @arity ~ 'Zero'@)
167− -- and 'liftToEncoding' (if the @arity@ is 'One').
168− gToJSON :: Options -> ToArgs enc arity a -> f a -> enc
153+ gToJSON :: Options -> Proxy arity
169−
154+ -> (a -> Value) -> ([a] -> Value) -> f a -> Value
170−-- | A 'ToArgs' value either stores nothing (for 'ToJSON') or it stores the two
155+
171−-- function arguments that encode occurrences of the type parameter (for
156+-- | Class of generic representation types that can be converted to
172−-- 'ToJSON1').
157+-- a JSON 'Encoding'.
173−data ToArgs res arity a where
158+class GToEncoding arity f where
174− NoToArgs :: ToArgs res Zero a
159+ -- | This method (applied to 'defaultOptions') can be used as the
175− To1Args :: (a -> res) -> ([a] -> res) -> ToArgs res One a
160+ -- default generic implementation of 'toEncoding' (if the @arity@ is 'Zero')
161+ -- or 'liftToEncoding' (if the @arity@ is 'One').
162+ gToEncoding :: Options -> Proxy arity
163+ -> (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
176
164
177-- | A configurable generic JSON creator. This function applied to
165-- | A configurable generic JSON creator. This function applied to
178-- 'defaultOptions' is used as the default for 'toJSON' when the type
166-- 'defaultOptions' is used as the default for 'toJSON' when the type
179-- is an instance of 'Generic'.
167-- is an instance of 'Generic'.
180−genericToJSON :: (Generic a, GToJSON Value Zero (Rep a))
168+genericToJSON :: (Generic a, GToJSON Zero (Rep a))
181 => Options -> a -> Value
169 => Options -> a -> Value
182−genericToJSON opts = gToJSON opts NoToArgs . from
170+genericToJSON opts = gToJSON opts proxyZero undefined undefined . from
183
171
184-- | A configurable generic JSON creator. This function applied to
172-- | A configurable generic JSON creator. This function applied to
185-- 'defaultOptions' is used as the default for 'liftToJSON' when the type
173-- 'defaultOptions' is used as the default for 'liftToJSON' when the type
186-- is an instance of 'Generic1'.
174-- is an instance of 'Generic1'.
187−genericLiftToJSON :: (Generic1 f, GToJSON Value One (Rep1 f))
175+genericLiftToJSON :: (Generic1 f, GToJSON One (Rep1 f))
188 => Options -> (a -> Value) -> ([a] -> Value)
176 => Options -> (a -> Value) -> ([a] -> Value)
189 -> f a -> Value
177 -> f a -> Value
190−genericLiftToJSON opts tj tjl = gToJSON opts (To1Args tj tjl) . from1
178+genericLiftToJSON opts tj tjl = gToJSON opts proxyOne tj tjl . from1
191
179
192-- | A configurable generic JSON encoder. This function applied to
180-- | A configurable generic JSON encoder. This function applied to
193-- 'defaultOptions' is used as the default for 'toEncoding' when the type
181-- 'defaultOptions' is used as the default for 'toEncoding' when the type
194-- is an instance of 'Generic'.
182-- is an instance of 'Generic'.
195−genericToEncoding :: (Generic a, GToJSON Encoding Zero (Rep a))
183+genericToEncoding :: (Generic a, GToEncoding Zero (Rep a))
196 => Options -> a -> Encoding
184 => Options -> a -> Encoding
197−genericToEncoding opts = gToJSON opts NoToArgs . from
185+genericToEncoding opts = gToEncoding opts proxyZero undefined undefined . from
198
186
199-- | A configurable generic JSON encoder. This function applied to
187-- | A configurable generic JSON encoder. This function applied to
200-- 'defaultOptions' is used as the default for 'liftToEncoding' when the type
188-- 'defaultOptions' is used as the default for 'liftToEncoding' when the type
201-- is an instance of 'Generic1'.
189-- is an instance of 'Generic1'.
202−genericLiftToEncoding :: (Generic1 f, GToJSON Encoding One (Rep1 f))
190+genericLiftToEncoding :: (Generic1 f, GToEncoding One (Rep1 f))
203 => Options -> (a -> Encoding) -> ([a] -> Encoding)
191 => Options -> (a -> Encoding) -> ([a] -> Encoding)
204 -> f a -> Encoding
192 -> f a -> Encoding
205−genericLiftToEncoding opts te tel = gToJSON opts (To1Args te tel) . from1
193+genericLiftToEncoding opts te tel = gToEncoding opts proxyOne te tel . from1
206
194
207-------------------------------------------------------------------------------
195-------------------------------------------------------------------------------
208-- Class
196-- Class
@@ -210,9 +198,6 @@ genericLiftToEncoding opts te tel = gToJSON opts (To1Args te tel) . from1
210
198
211-- | A type that can be converted to JSON.
199-- | A type that can be converted to JSON.
212--
200--
213−-- Instances in general /must/ specify 'toJSON' and /should/ (but don't need
214−-- to) specify 'toEncoding'.
215−--
216-- An example type and instance:
201-- An example type and instance:
217--
202--
218-- @
203-- @
@@ -221,10 +206,10 @@ genericLiftToEncoding opts te tel = gToJSON opts (To1Args te tel) . from1
221--
206--
222-- data Coord = Coord { x :: Double, y :: Double }
207-- data Coord = Coord { x :: Double, y :: Double }
223--
208--
224−-- instance 'ToJSON' Coord where
209+-- instance ToJSON Coord where
225−-- 'toJSON' (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]
210+-- toJSON (Coord x y) = 'object' [\"x\" '.=' x, \"y\" '.=' y]
226--
211--
227−-- 'toEncoding' (Coord x y) = 'pairs' (\"x\" '.=' x '<>' \"y\" '.=' y)
212+-- toEncoding (Coord x y) = 'pairs' (\"x\" '.=' x '<>' \"y\" '.=' y)
228-- @
213-- @
229--
214--
230-- Instead of manually writing your 'ToJSON' instance, there are two options
215-- Instead of manually writing your 'ToJSON' instance, there are two options
@@ -232,15 +217,17 @@ genericLiftToEncoding opts te tel = gToJSON opts (To1Args te tel) . from1
232--
217--
233-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
218-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
234-- instance at compile time. The generated instance is optimized for your type
219-- instance at compile time. The generated instance is optimized for your type
235−-- so it will probably be more efficient than the following option.
220+-- so will probably be more efficient than the following two options:
236--
221--
237-- * The compiler can provide a default generic implementation for
222-- * The compiler can provide a default generic implementation for
238-- 'toJSON'.
223-- 'toJSON'.
239--
224--
240-- To use the second, simply add a @deriving 'Generic'@ clause to your
225-- To use the second, simply add a @deriving 'Generic'@ clause to your
241−-- datatype and declare a 'ToJSON' instance. If you require nothing other than
226+-- datatype and declare a 'ToJSON' instance for your datatype without giving
242−-- 'defaultOptions', it is sufficient to write (and this is the only
227+-- definitions for 'toJSON' or 'toEncoding'.
243−-- alternative where the default 'toJSON' implementation is sufficient):
228+--
229+-- For example, the previous example can be simplified to a more
230+-- minimal instance:
244--
231--
245-- @
232-- @
246-- {-\# LANGUAGE DeriveGeneric \#-}
233-- {-\# LANGUAGE DeriveGeneric \#-}
@@ -249,46 +236,35 @@ genericLiftToEncoding opts te tel = gToJSON opts (To1Args te tel) . from1
249--
236--
250-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'
237-- data Coord = Coord { x :: Double, y :: Double } deriving 'Generic'
251--
238--
252−-- instance 'ToJSON' Coord where
239+-- instance ToJSON Coord where
253−-- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
240+-- toEncoding = 'genericToEncoding' 'defaultOptions'
254-- @
241-- @
255--
242--
256−-- If on the other hand you wish to customize the generic decoding, you have
243+-- Why do we provide an implementation for 'toEncoding' here? The
257−-- to implement both methods:
244+-- 'toEncoding' function is a relatively new addition to this class.
245+-- To allow users of older versions of this library to upgrade without
246+-- having to edit all of their instances or encounter surprising
247+-- incompatibilities, the default implementation of 'toEncoding' uses
248+-- 'toJSON'. This produces correct results, but since it performs an
249+-- intermediate conversion to a 'Value', it will be less efficient
250+-- than directly emitting an 'Encoding'. Our one-liner definition of
251+-- 'toEncoding' above bypasses the intermediate 'Value'.
252+--
253+-- If @DefaultSignatures@ doesn't give exactly the results you want,
254+-- you can customize the generic encoding with only a tiny amount of
255+-- effort, using 'genericToJSON' and 'genericToEncoding' with your
256+-- preferred 'Options':
258--
257--
259-- @
258-- @
260−-- customOptions = 'defaultOptions'
261−-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
262−-- }
263−--
264−-- instance 'ToJSON' Coord where
259+-- instance ToJSON Coord where
265−-- 'toJSON' = 'genericToJSON' customOptions
260+-- toJSON = 'genericToJSON' 'defaultOptions'
266−-- 'toEncoding' = 'genericToEncoding' customOptions
261+-- toEncoding = 'genericToEncoding' 'defaultOptions'
267-- @
262-- @
268−--
269−-- Previous versions of this library only had the 'toJSON' method. Adding
270−-- 'toEncoding' had two reasons:
271−--
272−-- 1. toEncoding is more efficient for the common case that the output of
273−-- 'toJSON' is directly serialized to a @ByteString@.
274−-- Further, expressing either method in terms of the other would be
275−-- non-optimal.
276−--
277−-- 2. The choice of defaults allows a smooth transition for existing users:
278−-- Existing instances that do not define 'toEncoding' still
279−-- compile and have the correct semantics. This is ensured by making
280−-- the default implementation of 'toEncoding' use 'toJSON'. This produces
281−-- correct results, but since it performs an intermediate conversion to a
282−-- 'Value', it will be less efficient than directly emitting an 'Encoding'.
283−-- (this also means that specifying nothing more than
284−-- @instance ToJSON Coord@ would be sufficient as a generically decoding
285−-- instance, but there probably exists no good reason to not specify
286−-- 'toEncoding' in new instances.)
287class ToJSON a where
263class ToJSON a where
288 -- | Convert a Haskell value to a JSON-friendly intermediate type.
264 -- | Convert a Haskell value to a JSON-friendly intermediate type.
289 toJSON :: a -> Value
265 toJSON :: a -> Value
290
266
291− default toJSON :: (Generic a, GToJSON Value Zero (Rep a)) => a -> Value
267+ default toJSON :: (Generic a, GToJSON Zero (Rep a)) => a -> Value
292 toJSON = genericToJSON defaultOptions
268 toJSON = genericToJSON defaultOptions
293
269
294 -- | Encode a Haskell value as JSON.
270 -- | Encode a Haskell value as JSON.
@@ -305,12 +281,12 @@ class ToJSON a where
305 -- extension, and then have GHC generate a method body as follows.
281 -- extension, and then have GHC generate a method body as follows.
306 --
282 --
307 -- @
283 -- @
308− -- instance 'ToJSON' Coord where
284+ -- instance ToJSON Coord where
309− -- 'toEncoding' = 'genericToEncoding' 'defaultOptions'
285+ -- toEncoding = 'genericToEncoding' 'defaultOptions'
310 -- @
286 -- @
311
287
312 toEncoding :: a -> Encoding
288 toEncoding :: a -> Encoding
313− toEncoding = E.value . toJSON
289+ toEncoding = E.Encoding . EB.encodeToBuilder . toJSON
314 {-# INLINE toEncoding #-}
290 {-# INLINE toEncoding #-}
315
291
316 toJSONList :: [a] -> Value
292 toJSONList :: [a] -> Value
@@ -331,27 +307,20 @@ class KeyValue kv where
331 infixr 8 .=
307 infixr 8 .=
332
308
333instance KeyValue Series where
309instance KeyValue Series where
334− name .= value = E.pair name (toEncoding value)
310+ name .= value = E.Value $ E.text name <> E.colon <> toEncoding value
335 {-# INLINE (.=) #-}
311 {-# INLINE (.=) #-}
336
312
337instance KeyValue Pair where
313instance KeyValue Pair where
338 name .= value = (name, toJSON value)
314 name .= value = (name, toJSON value)
339 {-# INLINE (.=) #-}
315 {-# INLINE (.=) #-}
340
316
341−-- | Constructs a singleton 'H.HashMap'. For calling functions that
342−-- demand an 'Object' for constructing objects. To be used in
343−-- conjunction with 'mconcat'. Prefer to use 'object' where possible.
344−instance KeyValue Object where
345− name .= value = H.singleton name (toJSON value)
346− {-# INLINE (.=) #-}
347−
348-------------------------------------------------------------------------------
317-------------------------------------------------------------------------------
349-- Classes and types for map keys
318-- Classes and types for map keys
350-------------------------------------------------------------------------------
319-------------------------------------------------------------------------------
351
320
352-- | Typeclass for types that can be used as the key of a map-like container
321-- | Typeclass for types that can be used as the key of a map-like container
353-- (like 'Map' or 'HashMap'). For example, since 'Text' has a 'ToJSONKey'
322-- (like 'Map' or 'HashMap'). For example, since 'Text' has a 'ToJSONKey'
354−-- instance and 'Char' has a 'ToJSON' instance, we can encode a value of
323+-- instance and 'Char' has a 'ToJSON' instance, we can encode a value of
355-- type 'Map' 'Text' 'Char':
324-- type 'Map' 'Text' 'Char':
356--
325--
357-- >>> LBC8.putStrLn $ encode $ Map.fromList [("foo" :: Text, 'a')]
326-- >>> LBC8.putStrLn $ encode $ Map.fromList [("foo" :: Text, 'a')]
@@ -397,147 +366,59 @@ instance KeyValue Object where
397-- >>> let m = Map.fromList [(Foo 4 "bar",'a'),(Foo 6 "arg",'b')]
366-- >>> let m = Map.fromList [(Foo 4 "bar",'a'),(Foo 6 "arg",'b')]
398-- >>> LBC8.putStrLn $ encode m
367-- >>> LBC8.putStrLn $ encode m
399-- [[{"fooName":"bar","fooAge":4},"a"],[{"fooName":"arg","fooAge":6},"b"]]
368-- [[{"fooName":"bar","fooAge":4},"a"],[{"fooName":"arg","fooAge":6},"b"]]
400−--
369+--
401-- The next case to consider is if we have a type that is a
370-- The next case to consider is if we have a type that is a
402-- newtype wrapper around 'Text'. The recommended approach is to use
371-- newtype wrapper around 'Text'. The recommended approach is to use
403-- generalized newtype deriving:
372-- generalized newtype deriving:
404--
373--
405−-- > newtype RecordId = RecordId { getRecordId :: Text }
374+-- > newtype RecordId = RecordId { getRecordId :: Text}
406-- > deriving (Eq,Ord,ToJSONKey)
375-- > deriving (Eq,Ord,ToJSONKey)
407−--
376+--
408-- Then we may write:
377-- Then we may write:
409−--
378+--
410-- >>> LBC8.putStrLn $ encode $ Map.fromList [(RecordId "abc",'a')]
379-- >>> LBC8.putStrLn $ encode $ Map.fromList [(RecordId "abc",'a')]
411-- {"abc":"a"}
380-- {"abc":"a"}
412--
381--
413-- Simple sum types are a final case worth considering. Suppose we have:
382-- Simple sum types are a final case worth considering. Suppose we have:
414--
383--
415−-- > data Color = Red | Green | Blue
384+-- > data Color = Red | Green | Blue | Black
416-- > deriving (Show,Read,Eq,Ord)
385-- > deriving (Show,Read,Eq,Ord)
417--
386--
418-- It is possible to get the 'ToJSONKey' instance for free as we did
387-- It is possible to get the 'ToJSONKey' instance for free as we did
419-- with 'Foo'. However, in this case, we have a natural way to go to
388-- with 'Foo'. However, in this case, we have a natural way to go to
420−-- and from 'Text' that does not require any escape sequences. So
389+-- and from 'Text' that does not require any escape sequences. So, in
421−-- 'ToJSONKeyText' can be used instead of 'ToJSONKeyValue' to encode maps
390+-- this example, 'ToJSONKeyText' will be used instead of 'ToJSONKeyValue'.
422−-- as objects instead of arrays of pairs. This instance may be
391+-- At the moment, there are no conveniences for this situation. The
423−-- implemented using generics as follows:
424−--
425−-- @
426−-- instance 'ToJSONKey' Color where
427−-- 'toJSONKey' = 'genericToJSONKey' 'defaultJSONKeyOptions'
428−-- @
429−--
430−-- === __Low-level implementations__
431−--
432−-- The 'Show' instance can be used to help write 'ToJSONKey':
392+-- 'Show' instance can be used to help write 'ToJSONKey', but this will
393+-- be inefficient since it uses 'String' as an intermediate step:
433--
394--
434-- > instance ToJSONKey Color where
395-- > instance ToJSONKey Color where
435-- > toJSONKey = ToJSONKeyText f g
396-- > toJSONKey = ToJSONKeyText f g
436-- > where f = Text.pack . show
397-- > where f = Text.pack . show
437−-- > g = text . Text.pack . show
398+-- > g = text . Text.pack . show
438−-- > -- text function is from Data.Aeson.Encoding
439−--
440−-- The situation of needing to turning function @a -> Text@ into
441−-- a 'ToJSONKeyFunction' is common enough that a special combinator
442−-- is provided for it. The above instance can be rewritten as:
443−--
444−-- > instance ToJSONKey Color where
445−-- > toJSONKey = toJSONKeyText (Text.pack . show)
446−--
447−-- The performance of the above instance can be improved by
448−-- not using 'String' as an intermediate step when converting to
449−-- 'Text'. One option for improving performance would be to use
450−-- template haskell machinery from the @text-show@ package. However,
451−-- even with the approach, the 'Encoding' (a wrapper around a bytestring
452−-- builder) is generated by encoding the 'Text' to a 'ByteString',
453−-- an intermediate step that could be avoided. The fastest possible
454−-- implementation would be:
455−--
456−-- > -- Assuming that OverloadedStrings is enabled
457−-- > instance ToJSONKey Color where
458−-- > toJSONKey = ToJSONKeyText f g
459−-- > where f x = case x of {Red -> "Red";Green ->"Green";Blue -> "Blue"}
460−-- > g x = case x of {Red -> text "Red";Green -> text "Green";Blue -> text "Blue"}
461-- > -- text function is from Data.Aeson.Encoding
399-- > -- text function is from Data.Aeson.Encoding
462--
400--
463−-- This works because GHC can lift the encoded values out of the case
464−-- statements, which means that they are only evaluated once. This
465−-- approach should only be used when there is a serious need to
466−-- maximize performance.
467−
468class ToJSONKey a where
401class ToJSONKey a where
469− -- | Strategy for rendering the key for a map-like container.
402+ -- | Provides a way to use a data type as the key for a map-like
403+ -- container.
470 toJSONKey :: ToJSONKeyFunction a
404 toJSONKey :: ToJSONKeyFunction a
471 default toJSONKey :: ToJSON a => ToJSONKeyFunction a
405 default toJSONKey :: ToJSON a => ToJSONKeyFunction a
472− toJSONKey = ToJSONKeyValue toJSON toEncoding
406+ toJSONKey = ToJSONKeyValue (toJSON, toEncoding)
473−
474 -- | This is similar in spirit to the 'showsList' method of 'Show'.
407 -- | This is similar in spirit to the 'showsList' method of 'Show'.
475 -- It makes it possible to give 'String' keys special treatment
408 -- It makes it possible to give 'String' keys special treatment
476− -- without using @OverlappingInstances@. End users should always
409+ -- without using @OverlappingInstances@.
477− -- be able to use the default implementation of this method.
478 toJSONKeyList :: ToJSONKeyFunction [a]
410 toJSONKeyList :: ToJSONKeyFunction [a]
479 default toJSONKeyList :: ToJSON a => ToJSONKeyFunction [a]
411 default toJSONKeyList :: ToJSON a => ToJSONKeyFunction [a]
480− toJSONKeyList = ToJSONKeyValue toJSON toEncoding
412+ toJSONKeyList = ToJSONKeyValue (toJSON, toEncoding)
481
413
482data ToJSONKeyFunction a
414data ToJSONKeyFunction a
483− = ToJSONKeyText !(a -> Text) !(a -> Encoding' Text)
484− -- ^ key is encoded to string, produces object
415+ = ToJSONKeyText (a -> Text, a -> Encoding) -- ^ key is encoded to string, produces object
485− | ToJSONKeyValue !(a -> Value) !(a -> Encoding)
486− -- ^ key is encoded to value, produces array
416+ | ToJSONKeyValue (a -> Value, a -> Encoding) -- ^ key is encoded to value, produces array
487
417
488−-- | Helper for creating textual keys.
489−--
490−-- @
491−-- instance 'ToJSONKey' MyKey where
492−-- 'toJSONKey' = 'toJSONKeyText' myKeyToText
493−-- where
494−-- myKeyToText = Text.pack . show -- or showt from text-show
495−-- @
496−toJSONKeyText :: (a -> Text) -> ToJSONKeyFunction a
497−toJSONKeyText f = ToJSONKeyText f (E.text . f)
498−
499−-- | TODO: should this be exported?
500−toJSONKeyTextEnc :: (a -> Encoding' Text) -> ToJSONKeyFunction a
501−toJSONKeyTextEnc e = ToJSONKeyText tot e
502− where
503− -- TODO: dropAround is also used in stringEncoding, which is unfortunate atm
504− tot = T.dropAround (== '"')
505− . T.decodeLatin1
506− . L.toStrict
507− . E.encodingToLazyByteString
508− . e
509−
510−instance Contravariant ToJSONKeyFunction where
511− contramap = contramapToJSONKeyFunction
512−
513−-- | Contravariant map, as 'ToJSONKeyFunction' is a contravariant functor.
514contramapToJSONKeyFunction :: (b -> a) -> ToJSONKeyFunction a -> ToJSONKeyFunction b
418contramapToJSONKeyFunction :: (b -> a) -> ToJSONKeyFunction a -> ToJSONKeyFunction b
515contramapToJSONKeyFunction h x = case x of
419contramapToJSONKeyFunction h x = case x of
516− ToJSONKeyText f g -> ToJSONKeyText (f . h) (g . h)
420+ ToJSONKeyText (f,g) -> ToJSONKeyText (f . h, g . h)
517− ToJSONKeyValue f g -> ToJSONKeyValue (f . h) (g . h)
421+ ToJSONKeyValue (f,g) -> ToJSONKeyValue (f . h, g . h)
518−
519−-- 'toJSONKey' for 'Generic' types.
520−-- Deriving is supported for enumeration types, i.e. the sums of nullary
521−-- constructors. The names of constructors will be used as keys for JSON
522−-- objects.
523−--
524−-- See also 'genericFromJSONKey'.
525−--
526−-- === __Example__
527−--
528−-- @
529−-- data Color = Red | Green | Blue
530−-- deriving 'Generic'
531−--
532−-- instance 'ToJSONKey' Color where
533−-- 'toJSONKey' = 'genericToJSONKey' 'defaultJSONKeyOptions'
534−-- @
535−genericToJSONKey :: (Generic a, GToJSONKey (Rep a))
536− => JSONKeyOptions -> ToJSONKeyFunction a
537−genericToJSONKey opts = toJSONKeyText (pack . keyModifier opts . getConName . from)
538−
539−class GetConName f => GToJSONKey f
540−instance GetConName f => GToJSONKey f
541
422
542-------------------------------------------------------------------------------
423-------------------------------------------------------------------------------
543-- Lifings of FromJSON and ToJSON to unary and binary type constructors
424-- Lifings of FromJSON and ToJSON to unary and binary type constructors
@@ -551,7 +432,7 @@ instance GetConName f => GToJSONKey f
551--
432--
552-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
433-- * "Data.Aeson.TH" provides Template Haskell functions which will derive an
553-- instance at compile time. The generated instance is optimized for your type
434-- instance at compile time. The generated instance is optimized for your type
554−-- so it will probably be more efficient than the following option.
435+-- so will probably be more efficient than the following two options:
555--
436--
556-- * The compiler can provide a default generic implementation for
437-- * The compiler can provide a default generic implementation for
557-- 'toJSON1'.
438-- 'toJSON1'.
@@ -569,29 +450,23 @@ instance GetConName f => GToJSONKey f
569--
450--
570-- data Pair = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'
451-- data Pair = Pair { pairFst :: a, pairSnd :: b } deriving 'Generic1'
571--
452--
572−-- instance 'ToJSON' a => 'ToJSON1' (Pair a)
453+-- instance ToJSON a => ToJSON1 (Pair a)
573-- @
454-- @
574--
455--
575−-- If the default implementation doesn't give exactly the results you want,
456+-- If @DefaultSignatures@ doesn't give exactly the results you want,
576-- you can customize the generic encoding with only a tiny amount of
457-- you can customize the generic encoding with only a tiny amount of
577-- effort, using 'genericLiftToJSON' and 'genericLiftToEncoding' with
458-- effort, using 'genericLiftToJSON' and 'genericLiftToEncoding' with
578-- your preferred 'Options':
459-- your preferred 'Options':
579--
460--
580-- @
461-- @
581−-- customOptions = 'defaultOptions'
582−-- { 'fieldLabelModifier' = 'map' 'Data.Char.toUpper'
583−-- }
584−--
585−-- instance 'ToJSON' a => 'ToJSON1' (Pair a) where
462+-- instance ToJSON a => ToJSON1 (Pair a) where
586−-- 'liftToJSON' = 'genericLiftToJSON' customOptions
463+-- liftToJSON = 'genericLiftToJSON' 'defaultOptions'
587−-- 'liftToEncoding' = 'genericLiftToEncoding' customOptions
464+-- liftToEncoding = 'genericLiftToEncoding' 'defaultOptions'
588-- @
465-- @
589−--
590−-- See also 'ToJSON'.
591class ToJSON1 f where
466class ToJSON1 f where
592 liftToJSON :: (a -> Value) -> ([a] -> Value) -> f a -> Value
467 liftToJSON :: (a -> Value) -> ([a] -> Value) -> f a -> Value
593
468
594− default liftToJSON :: (Generic1 f, GToJSON Value One (Rep1 f))
469+ default liftToJSON :: (Generic1 f, GToJSON One (Rep1 f))
595 => (a -> Value) -> ([a] -> Value) -> f a -> Value
470 => (a -> Value) -> ([a] -> Value) -> f a -> Value
596 liftToJSON = genericLiftToJSON defaultOptions
471 liftToJSON = genericLiftToJSON defaultOptions
597
472
@@ -600,7 +475,7 @@ class ToJSON1 f where
600
475
601 liftToEncoding :: (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
476 liftToEncoding :: (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
602
477
603− default liftToEncoding :: (Generic1 f, GToJSON Encoding One (Rep1 f))
478+ default liftToEncoding :: (Generic1 f, GToEncoding One (Rep1 f))
604 => (a -> Encoding) -> ([a] -> Encoding)
479 => (a -> Encoding) -> ([a] -> Encoding)
605 -> f a -> Encoding
480 -> f a -> Encoding
606 liftToEncoding = genericLiftToEncoding defaultOptions
481 liftToEncoding = genericLiftToEncoding defaultOptions
@@ -648,25 +523,9 @@ toEncoding2 = liftToEncoding2 toEncoding toEncodingList toEncoding toEncodingLis
648-- Encoding functions
523-- Encoding functions
649-------------------------------------------------------------------------------
524-------------------------------------------------------------------------------
650
525
651−-- | Helper function to use with 'liftToEncoding'.
652−-- Useful when writing own 'ToJSON1' instances.
653−--
654−-- @
655−-- newtype F a = F [a]
656−--
657−-- -- This instance encodes 'String' as an array of chars
658−-- instance 'ToJSON1' F where
659−-- 'liftToJSON' tj _ (F xs) = 'liftToJSON' tj ('listValue' tj) xs
660−-- 'liftToEncoding' te _ (F xs) = 'liftToEncoding' te ('listEncoding' te) xs
661−--
662−-- instance 'Data.Aeson.FromJSON.FromJSON1' F where
663−-- 'Data.Aeson.FromJSON.liftParseJSON' p _ v = F \<$\> 'Data.Aeson.FromJSON.liftParseJSON' p ('Data.Aeson.FromJSON.listParser' p) v
664−-- @
665listEncoding :: (a -> Encoding) -> [a] -> Encoding
526listEncoding :: (a -> Encoding) -> [a] -> Encoding
666listEncoding = E.list
527listEncoding = E.list
667−{-# INLINE listEncoding #-}
668
528
669−-- | Helper function to use with 'liftToJSON', see 'listEncoding'.
670listValue :: (a -> Value) -> [a] -> Value
529listValue :: (a -> Value) -> [a] -> Value
671listValue f = Array . V.fromList . map f
530listValue f = Array . V.fromList . map f
672{-# INLINE listValue #-}
531{-# INLINE listValue #-}
@@ -685,11 +544,6 @@ instance ToJSON1 [] where
685 {-# INLINE liftToEncoding #-}
544 {-# INLINE liftToEncoding #-}
686
545
687instance (ToJSON a) => ToJSON [a] where
546instance (ToJSON a) => ToJSON [a] where
688− {-# SPECIALIZE instance ToJSON String #-}
689− {-# SPECIALIZE instance ToJSON [String] #-}
690− {-# SPECIALIZE instance ToJSON [Array] #-}
691− {-# SPECIALIZE instance ToJSON [Object] #-}
692−
693 toJSON = toJSON1
547 toJSON = toJSON1
694 {-# INLINE toJSON #-}
548 {-# INLINE toJSON #-}
695
549
@@ -700,260 +554,283 @@ instance (ToJSON a) => ToJSON [a] where
700-- Generic toJSON / toEncoding
554-- Generic toJSON / toEncoding
701-------------------------------------------------------------------------------
555-------------------------------------------------------------------------------
702
556
703−instance OVERLAPPABLE_ (GToJSON enc arity a) => GToJSON enc arity (M1 i c a) where
704− -- Meta-information, which is not handled elsewhere, is ignored:
705− gToJSON opts targs = gToJSON opts targs . unM1
706− {-# INLINE gToJSON #-}
707−
708−instance GToJSON enc One Par1 where
709− -- Direct occurrences of the last type parameter are encoded with the
710− -- function passed in as an argument:
711− gToJSON _opts (To1Args tj _) = tj . unPar1
712− {-# INLINE gToJSON #-}
713−
714−instance ( ConsToJSON enc arity a
715− , AllNullary (C1 c a) allNullary
716− , SumToJSON enc arity (C1 c a) allNullary
717− ) => GToJSON enc arity (D1 d (C1 c a)) where
718− -- The option 'tagSingleConstructors' determines whether to wrap
719− -- a single-constructor type.
720− gToJSON opts targs
721− | tagSingleConstructors opts = (unTagged :: Tagged allNullary enc -> enc)
722− . sumToJSON opts targs
723− . unM1
724− | otherwise = consToJSON opts targs . unM1 . unM1
725− {-# INLINE gToJSON #-}
726−
727−instance (ConsToJSON enc arity a) => GToJSON enc arity (C1 c a) where
728− -- Constructors need to be encoded differently depending on whether they're
729− -- a record or not. This distinction is made by 'consToJSON':
730− gToJSON opts targs = consToJSON opts targs . unM1
731− {-# INLINE gToJSON #-}
732−
733−instance ( AllNullary (a :+: b) allNullary
734− , SumToJSON enc arity (a :+: b) allNullary
735− ) => GToJSON enc arity (a :+: b)
736− where
737− -- If all constructors of a sum datatype are nullary and the
738− -- 'allNullaryToStringTag' option is set they are encoded to
739− -- strings. This distinction is made by 'sumToJSON':
740− gToJSON opts targs = (unTagged :: Tagged allNullary enc -> enc)
741− . sumToJSON opts targs
742− {-# INLINE gToJSON #-}
743−
744--------------------------------------------------------------------------------
557--------------------------------------------------------------------------------
745-- Generic toJSON
558-- Generic toJSON
746
559
747−-- Note: Refactoring 'ToJSON a' to 'ToJSON enc a' (and 'ToJSON1' similarly) is
748−-- possible but makes error messages a bit harder to understand for missing
749−-- instances.
750−
751−instance GToJSON Value arity V1 where
560+instance OVERLAPPABLE_ (GToJSON arity a) => GToJSON arity (M1 i c a) where
752− -- Empty values do not exist, which makes the job of formatting them
561+ -- Meta-information, which is not handled elsewhere, is ignored:
753− -- rather easy:
562+ gToJSON opts pa tj tjl = gToJSON opts pa tj tjl . unM1
754− gToJSON _ _ x = x `seq` error "case: V1"
755− {-# INLINE gToJSON #-}
756
563
757−instance ToJSON a => GToJSON Value arity (K1 i a) where
564+instance (ToJSON a) => GToJSON arity (K1 i a) where
758 -- Constant values are encoded using their ToJSON instance:
565 -- Constant values are encoded using their ToJSON instance:
759− gToJSON _opts _ = toJSON . unK1
566+ gToJSON _opts _ _ _ = toJSON . unK1
760− {-# INLINE gToJSON #-}
761
567
568+instance GToJSON One Par1 where
569+ -- Direct occurrences of the last type parameter are encoded with the
570+ -- function passed in as an argument:
571+ gToJSON _opts _ tj _ = tj . unPar1
572+
762−instance ToJSON1 f => GToJSON Value One (Rec1 f) where
573+instance (ToJSON1 f) => GToJSON One (Rec1 f) where
763 -- Recursive occurrences of the last type parameter are encoded using their
574 -- Recursive occurrences of the last type parameter are encoded using their
764 -- ToJSON1 instance:
575 -- ToJSON1 instance:
765− gToJSON _opts (To1Args tj tjl) = liftToJSON tj tjl . unRec1
576+ gToJSON _opts _ tj tjl = liftToJSON tj tjl . unRec1
766− {-# INLINE gToJSON #-}
767
577
768−instance GToJSON Value arity U1 where
578+instance GToJSON arity U1 where
769 -- Empty constructors are encoded to an empty array:
579 -- Empty constructors are encoded to an empty array:
770− gToJSON _opts _ _ = emptyArray
580+ gToJSON _opts _ _ _ _ = emptyArray
771− {-# INLINE gToJSON #-}
581+
582+instance (ConsToJSON arity a) => GToJSON arity (C1 c a) where
583+ -- Constructors need to be encoded differently depending on whether they're
584+ -- a record or not. This distinction is made by 'consToJSON':
585+ gToJSON opts pa tj tjl = consToJSON opts pa tj tjl . unM1
772
586
773instance ( WriteProduct arity a, WriteProduct arity b
587instance ( WriteProduct arity a, WriteProduct arity b
774 , ProductSize a, ProductSize b
588 , ProductSize a, ProductSize b
775− ) => GToJSON Value arity (a :*: b)
589+ ) => GToJSON arity (a :*: b) where
776− where
777 -- Products are encoded to an array. Here we allocate a mutable vector of
590 -- Products are encoded to an array. Here we allocate a mutable vector of
778 -- the same size as the product and write the product's elements to it using
591 -- the same size as the product and write the product's elements to it using
779 -- 'writeProduct':
592 -- 'writeProduct':
780− gToJSON opts targs p =
593+ gToJSON opts pa tj tjl p =
781 Array $ V.create $ do
594 Array $ V.create $ do
782 mv <- VM.unsafeNew lenProduct
595 mv <- VM.unsafeNew lenProduct
783− writeProduct opts targs mv 0 lenProduct p
596+ writeProduct opts pa mv 0 lenProduct tj tjl p
784 return mv
597 return mv
785 where
598 where
786 lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)
599 lenProduct = (unTagged2 :: Tagged2 (a :*: b) Int -> Int)
787 productSize
600 productSize
788− {-# INLINE gToJSON #-}
789
601
790−instance ( ToJSON1 f
602+instance ( AllNullary (a :+: b) allNullary
791− , GToJSON Value One g
603+ , SumToJSON arity (a :+: b) allNullary
792− ) => GToJSON Value One (f :.: g)
604+ ) => GToJSON arity (a :+: b) where
793− where
605+ -- If all constructors of a sum datatype are nullary and the
606+ -- 'allNullaryToStringTag' option is set they are encoded to
607+ -- strings. This distinction is made by 'sumToJSON':
608+ gToJSON opts pa tj tjl = (unTagged :: Tagged allNullary Value -> Value)
609+ . sumToJSON opts pa tj tjl
610+
611+instance (ToJSON1 f, GToJSON One g) => GToJSON One (f :.: g) where
794 -- If an occurrence of the last type parameter is nested inside two
612 -- If an occurrence of the last type parameter is nested inside two
795 -- composed types, it is encoded by using the outermost type's ToJSON1
613 -- composed types, it is encoded by using the outermost type's ToJSON1
796 -- instance to generically encode the innermost type:
614 -- instance to generically encode the innermost type:
797− gToJSON opts targs =
615+ gToJSON opts pa tj tjl =
798− let gtj = gToJSON opts targs in
616+ let gtj = gToJSON opts pa tj tjl in
799 liftToJSON gtj (listValue gtj) . unComp1
617 liftToJSON gtj (listValue gtj) . unComp1
800− {-# INLINE gToJSON #-}
801
618
802--------------------------------------------------------------------------------
619--------------------------------------------------------------------------------
803-- Generic toEncoding
620-- Generic toEncoding
804
621
622+instance OVERLAPPABLE_ (GToEncoding arity a) => GToEncoding arity (M1 i c a) where
623+ -- Meta-information, which is not handled elsewhere, is ignored:
624+ gToEncoding opts pa te tel = gToEncoding opts pa te tel . unM1
625+
805−instance ToJSON a => GToJSON Encoding arity (K1 i a) where
626+instance (ToJSON a) => GToEncoding arity (K1 i a) where
806 -- Constant values are encoded using their ToJSON instance:
627 -- Constant values are encoded using their ToJSON instance:
807− gToJSON _opts _ = toEncoding . unK1
628+ gToEncoding _opts _ _ _ = toEncoding . unK1
808− {-# INLINE gToJSON #-}
809
629
630+instance GToEncoding One Par1 where
631+ -- Direct occurrences of the last type parameter are encoded with the
632+ -- function passed in as an argument:
633+ gToEncoding _opts _ te _ = te . unPar1
634+
810−instance ToJSON1 f => GToJSON Encoding One (Rec1 f) where
635+instance (ToJSON1 f) => GToEncoding One (Rec1 f) where
811 -- Recursive occurrences of the last type parameter are encoded using their
636 -- Recursive occurrences of the last type parameter are encoded using their
812 -- ToEncoding1 instance:
637 -- ToEncoding1 instance:
813− gToJSON _opts (To1Args te tel) = liftToEncoding te tel . unRec1
638+ gToEncoding _opts _ te tel = liftToEncoding te tel . unRec1
814− {-# INLINE gToJSON #-}
815
639
816−instance GToJSON Encoding arity U1 where
640+instance GToEncoding arity U1 where
817 -- Empty constructors are encoded to an empty array:
641 -- Empty constructors are encoded to an empty array:
818− gToJSON _opts _ _ = E.emptyArray_
642+ gToEncoding _opts _ _ _ _ = E.emptyArray_
819− {-# INLINE gToJSON #-}
643+
644+instance (ConsToEncoding arity a) => GToEncoding arity (C1 c a) where
645+ -- Constructors need to be encoded differently depending on whether they're
646+ -- a record or not. This distinction is made by 'consToEncoding':
647+ gToEncoding opts pa te tel = consToEncoding opts pa te tel . unM1
820
648
821instance ( EncodeProduct arity a
649instance ( EncodeProduct arity a
822 , EncodeProduct arity b
650 , EncodeProduct arity b
823− ) => GToJSON Encoding arity (a :*: b)
651+ ) => GToEncoding arity (a :*: b) where
824− where
825 -- Products are encoded to an array. Here we allocate a mutable vector of
652 -- Products are encoded to an array. Here we allocate a mutable vector of
826 -- the same size as the product and write the product's elements to it using
653 -- the same size as the product and write the product's elements to it using
827 -- 'encodeProduct':
654 -- 'encodeProduct':
828− gToJSON opts targs p = E.list E.retagEncoding [encodeProduct opts targs p]
655+ gToEncoding opts pa te tel p = E.tuple $ encodeProduct opts pa te tel p
829− {-# INLINE gToJSON #-}
830
656
831−instance ( ToJSON1 f
657+instance ( AllNullary (a :+: b) allNullary
832− , GToJSON Encoding One g
658+ , SumToEncoding arity (a :+: b) allNullary
833− ) => GToJSON Encoding One (f :.: g)
659+ ) => GToEncoding arity (a :+: b) where
834− where
660+ -- If all constructors of a sum datatype are nullary and the
661+ -- 'allNullaryToStringTag' option is set they are encoded to
662+ -- strings. This distinction is made by 'sumToEncoding':
663+ gToEncoding opts pa te tel
664+ = (unTagged :: Tagged allNullary Encoding -> Encoding)
665+ . sumToEncoding opts pa te tel
666+
667+instance (ToJSON1 f, GToEncoding One g) => GToEncoding One (f :.: g) where
835 -- If an occurrence of the last type parameter is nested inside two
668 -- If an occurrence of the last type parameter is nested inside two
836 -- composed types, it is encoded by using the outermost type's ToJSON1
669 -- composed types, it is encoded by using the outermost type's ToJSON1
837 -- instance to generically encode the innermost type:
670 -- instance to generically encode the innermost type:
838− gToJSON opts targs =
671+ gToEncoding opts pa te tel =
839− let gte = gToJSON opts targs in
672+ let gte = gToEncoding opts pa te tel in
840 liftToEncoding gte (listEncoding gte) . unComp1
673 liftToEncoding gte (listEncoding gte) . unComp1
841− {-# INLINE gToJSON #-}
842
674
843--------------------------------------------------------------------------------
675--------------------------------------------------------------------------------
844
676
845−class SumToJSON enc arity f allNullary where
677+class SumToJSON arity f allNullary where
846− sumToJSON :: Options -> ToArgs enc arity a
678+ sumToJSON :: Options -> Proxy arity
679+ -> (a -> Value) -> ([a] -> Value)
847− -> f a -> Tagged allNullary enc
680+ -> f a -> Tagged allNullary Value
848−
681+
849−instance ( GetConName f
682+instance ( GetConName f
850− , FromString enc
683+ , TaggedObjectPairs arity f
851− , TaggedObject enc arity f
684+ , ObjectWithSingleFieldObj arity f
852− , SumToJSON' ObjectWithSingleField enc arity f
685+ , TwoElemArrayObj arity f
853− , SumToJSON' TwoElemArray enc arity f
854− , SumToJSON' UntaggedValue enc arity f
855− ) => SumToJSON enc arity f True
686+ ) => SumToJSON arity f True where
856− where
857− sumToJSON opts targs
687+ sumToJSON opts pa tj tjl
858− | allNullaryToStringTag opts = Tagged . fromString
688+ | allNullaryToStringTag opts = Tagged . String . pack
859 . constructorTagModifier opts . getConName
689 . constructorTagModifier opts . getConName
860− | otherwise = Tagged . nonAllNullarySumToJSON opts targs
690+ | otherwise = Tagged . nonAllNullarySumToJSON opts pa tj tjl
861−
691+
862−instance ( TaggedObject enc arity f
692+instance ( TwoElemArrayObj arity f
863− , SumToJSON' ObjectWithSingleField enc arity f
693+ , TaggedObjectPairs arity f
864− , SumToJSON' TwoElemArray enc arity f
694+ , ObjectWithSingleFieldObj arity f
865− , SumToJSON' UntaggedValue enc arity f
866− ) => SumToJSON enc arity f False
695+ ) => SumToJSON arity f False where
867− where
868− sumToJSON opts targs = Tagged . nonAllNullarySumToJSON opts targs
696+ sumToJSON opts pa tj tjl = Tagged . nonAllNullarySumToJSON opts pa tj tjl
869−
697+
870−nonAllNullarySumToJSON :: ( TaggedObject enc arity f
698+nonAllNullarySumToJSON :: ( TwoElemArrayObj arity f
871− , SumToJSON' ObjectWithSingleField enc arity f
699+ , TaggedObjectPairs arity f
872− , SumToJSON' TwoElemArray enc arity f
700+ , ObjectWithSingleFieldObj arity f
873− , SumToJSON' UntaggedValue enc arity f
874− ) => Options -> ToArgs enc arity a
701+ ) => Options -> Proxy arity
875− -> f a -> enc
702+ -> (a -> Value) -> ([a] -> Value)
703+ -> f a -> Value
876−nonAllNullarySumToJSON opts targs =
704+nonAllNullarySumToJSON opts pa tj tjl =
877 case sumEncoding opts of
705 case sumEncoding opts of
878−
879 TaggedObject{..} ->
706 TaggedObject{..} ->
880− taggedObject opts targs tagFieldName contentsFieldName
707+ object . taggedObjectPairs opts pa tagFieldName contentsFieldName tj tjl
708+ ObjectWithSingleField -> Object . objectWithSingleFieldObj opts pa tj tjl
709+ TwoElemArray -> Array . twoElemArrayObj opts pa tj tjl
881
710
882− ObjectWithSingleField ->
711+--------------------------------------------------------------------------------
883− (unTagged :: Tagged ObjectWithSingleField enc -> enc)
884− . sumToJSON' opts targs
885−
886− TwoElemArray ->
887− (unTagged :: Tagged TwoElemArray enc -> enc)
888− . sumToJSON' opts targs
889
712
890− UntaggedValue ->
713+class SumToEncoding arity f allNullary where
891− (unTagged :: Tagged UntaggedValue enc -> enc)
714+ sumToEncoding :: Options -> Proxy arity
892− . sumToJSON' opts targs
715+ -> (a -> Encoding) -> ([a] -> Encoding)
716+ -> f a -> Tagged allNullary Encoding
717+
718+instance ( GetConName f
719+ , TaggedObjectEnc arity f
720+ , ObjectWithSingleFieldEnc arity f
721+ , TwoElemArrayEnc arity f
722+ ) => SumToEncoding arity f True where
723+ sumToEncoding opts pa te tel
724+ | allNullaryToStringTag opts = Tagged . toEncoding .
725+ constructorTagModifier opts . getConName
726+ | otherwise = Tagged . nonAllNullarySumToEncoding opts pa te tel
727+
728+instance ( TwoElemArrayEnc arity f
729+ , TaggedObjectEnc arity f
730+ , ObjectWithSingleFieldEnc arity f
731+ ) => SumToEncoding arity f False where
732+ sumToEncoding opts pa te tel = Tagged . nonAllNullarySumToEncoding opts pa te tel
733+
734+nonAllNullarySumToEncoding :: ( TwoElemArrayEnc arity f
735+ , TaggedObjectEnc arity f
736+ , ObjectWithSingleFieldEnc arity f
737+ ) => Options -> Proxy arity
738+ -> (a -> Encoding) -> ([a] -> Encoding)
739+ -> f a -> Encoding
740+nonAllNullarySumToEncoding opts pa te tel =
741+ case sumEncoding opts of
742+ TaggedObject{..} ->
743+ taggedObjectEnc opts pa tagFieldName contentsFieldName te tel
744+ ObjectWithSingleField -> objectWithSingleFieldEnc opts pa te tel
745+ TwoElemArray -> twoElemArrayEnc opts pa te tel
893
746
894--------------------------------------------------------------------------------
747--------------------------------------------------------------------------------
895
748
896−class FromString enc where
749+class TaggedObjectPairs arity f where
897− fromString :: String -> enc
750+ taggedObjectPairs :: Options -> Proxy arity
751+ -> String -> String
752+ -> (a -> Value) -> ([a] -> Value)
753+ -> f a -> [Pair]
754+
755+instance ( TaggedObjectPairs arity a
756+ , TaggedObjectPairs arity b
757+ ) => TaggedObjectPairs arity (a :+: b) where
758+ taggedObjectPairs opts pa tagFieldName contentsFieldName tj tjl (L1 x) =
759+ taggedObjectPairs opts pa tagFieldName contentsFieldName tj tjl x
760+ taggedObjectPairs opts pa tagFieldName contentsFieldName tj tjl (R1 x) =
761+ taggedObjectPairs opts pa tagFieldName contentsFieldName tj tjl x
762+
763+instance ( IsRecord a isRecord
764+ , TaggedObjectPairs' arity a isRecord
765+ , Constructor c
766+ ) => TaggedObjectPairs arity (C1 c a) where
767+ taggedObjectPairs opts pa tagFieldName contentsFieldName tj tjl =
768+ (pack tagFieldName .= constructorTagModifier opts
769+ (conName (undefined :: t c a p)) :) .
770+ (unTagged :: Tagged isRecord [Pair] -> [Pair]) .
771+ taggedObjectPairs' opts pa contentsFieldName tj tjl . unM1
772+
773+class TaggedObjectPairs' arity f isRecord where
774+ taggedObjectPairs' :: Options -> Proxy arity
775+ -> String -> (a -> Value) -> ([a] -> Value)
776+ -> f a -> Tagged isRecord [Pair]
777+
778+instance OVERLAPPING_ TaggedObjectPairs' arity U1 False where
779+ taggedObjectPairs' _ _ _ _ _ _ = Tagged []
898
780
899−instance FromString Encoding where
781+instance (RecordToPairs arity f) => TaggedObjectPairs' arity f True where
900− fromString = toEncoding
782+ taggedObjectPairs' opts pa _ tj tjl =
783+ Tagged . toList . recordToPairs opts pa tj tjl
901
784
902−instance FromString Value where
785+instance (GToJSON arity f) => TaggedObjectPairs' arity f False where
903− fromString = String . pack
786+ taggedObjectPairs' opts pa contentsFieldName tj tjl =
787+ Tagged . (:[]) . (pack contentsFieldName .=) . gToJSON opts pa tj tjl
904
788
905--------------------------------------------------------------------------------
789--------------------------------------------------------------------------------
906
790
907−class TaggedObject enc arity f where
791+class TaggedObjectEnc arity f where
908− taggedObject :: Options -> ToArgs enc arity a
792+ taggedObjectEnc :: Options -> Proxy arity
909− -> String -> String
793+ -> String -> String
910− -> f a -> enc
794+ -> (a -> Encoding) -> ([a] -> Encoding)
911−
795+ -> f a -> Encoding
796+
912−instance ( TaggedObject enc arity a
797+instance ( TaggedObjectEnc arity a
913− , TaggedObject enc arity b
798+ , TaggedObjectEnc arity b
914− ) => TaggedObject enc arity (a :+: b)
799+ ) => TaggedObjectEnc arity (a :+: b) where
915− where
916− taggedObject opts targs tagFieldName contentsFieldName (L1 x) =
800+ taggedObjectEnc opts pa tagFieldName contentsFieldName te tel (L1 x) =
917− taggedObject opts targs tagFieldName contentsFieldName x
801+ taggedObjectEnc opts pa tagFieldName contentsFieldName te tel x
918− taggedObject opts targs tagFieldName contentsFieldName (R1 x) =
802+ taggedObjectEnc opts pa tagFieldName contentsFieldName te tel (R1 x) =
919− taggedObject opts targs tagFieldName contentsFieldName x
803+ taggedObjectEnc opts pa tagFieldName contentsFieldName te tel x
920−
804+
921−instance ( IsRecord a isRecord
805+instance ( IsRecord a isRecord
922− , TaggedObject' enc pairs arity a isRecord
806+ , TaggedObjectEnc' arity a isRecord
923− , FromPairs enc pairs
924− , FromString enc
925− , KeyValuePair enc pairs
926 , Constructor c
807 , Constructor c
927− ) => TaggedObject enc arity (C1 c a)
808+ ) => TaggedObjectEnc arity (C1 c a) where
928− where
929− taggedObject opts targs tagFieldName contentsFieldName =
809+ taggedObjectEnc opts pa tagFieldName contentsFieldName te tel v =
930− fromPairs . mappend tag . contents
810+ E.openCurly <>
931− where
811+ (toEncoding tagFieldName <>
932− tag = tagFieldName `pair`
812+ E.colon <>
933− (fromString (constructorTagModifier opts (conName (undefined :: t c a p)))
813+ toEncoding (constructorTagModifier opts (conName (undefined :: t c a p)))) <>
934− :: enc)
935− contents =
936− (unTagged :: Tagged isRecord pairs -> pairs) .
814+ ((unTagged :: Tagged isRecord Encoding -> Encoding) .
937− taggedObject' opts targs contentsFieldName . unM1
815+ taggedObjectEnc' opts pa contentsFieldName te tel . unM1 $ v) <>
938−
816+ E.closeCurly
817+
939−class TaggedObject' enc pairs arity f isRecord where
818+class TaggedObjectEnc' arity f isRecord where
940− taggedObject' :: Options -> ToArgs enc arity a
819+ taggedObjectEnc' :: Options -> Proxy arity
941− -> String -> f a -> Tagged isRecord pairs
820+ -> String -> (a -> Encoding) -> ([a] -> Encoding)
942−
821+ -> f a -> Tagged isRecord Encoding
943−instance ( GToJSON enc arity f
822+
944− , KeyValuePair enc pairs
945− ) => TaggedObject' enc pairs arity f False
946− where
947− taggedObject' opts targs contentsFieldName =
948− Tagged . (contentsFieldName `pair`) . gToJSON opts targs
949−
950−instance OVERLAPPING_ Monoid pairs => TaggedObject' enc pairs arity U1 False where
823+instance OVERLAPPING_ TaggedObjectEnc' arity U1 False where
951− taggedObject' _ _ _ _ = Tagged mempty
824+ taggedObjectEnc' _ _ _ _ _ _ = Tagged mempty
952−
825+
953−instance ( RecordToPairs enc pairs arity f
826+instance (RecordToEncoding arity f) => TaggedObjectEnc' arity f True where
954− ) => TaggedObject' enc pairs arity f True
827+ taggedObjectEnc' opts pa _ te tel = Tagged . (E.comma <>) . fst
955− where
828+ . recordToEncoding opts pa te tel
956− taggedObject' opts targs _ = Tagged . recordToPairs opts targs
829+
830+instance (GToEncoding arity f) => TaggedObjectEnc' arity f False where
831+ taggedObjectEnc' opts pa contentsFieldName te tel =
832+ Tagged . (\z -> E.comma <> toEncoding contentsFieldName <> E.colon <> z) .
833+ gToEncoding opts pa te tel
957
834
958--------------------------------------------------------------------------------
835--------------------------------------------------------------------------------
959
836
@@ -968,242 +845,283 @@ instance (GetConName a, GetConName b) => GetConName (a :+: b) where
968instance (Constructor c) => GetConName (C1 c a) where
845instance (Constructor c) => GetConName (C1 c a) where
969 getConName = conName
846 getConName = conName
970
847
971−-- For genericToJSONKey
972−instance GetConName a => GetConName (D1 d a) where
973− getConName (M1 x) = getConName x
974−
975−--------------------------------------------------------------------------------
976−
977−-- Reflection of SumEncoding variants
978−
979−data ObjectWithSingleField
980−data TwoElemArray
981−data UntaggedValue
982−
983--------------------------------------------------------------------------------
848--------------------------------------------------------------------------------
984
849
985−class SumToJSON' s enc arity f where
850+class TwoElemArrayObj arity f where
986− sumToJSON' :: Options -> ToArgs enc arity a
851+ twoElemArrayObj :: Options -> Proxy arity
987− -> f a -> Tagged s enc
852+ -> (a -> Value) -> ([a] -> Value)
988−
853+ -> f a -> V.Vector Value
989−instance ( SumToJSON' s enc arity a
990− , SumToJSON' s enc arity b
991− ) => SumToJSON' s enc arity (a :+: b)
992− where
993− sumToJSON' opts targs (L1 x) = sumToJSON' opts targs x
994− sumToJSON' opts targs (R1 x) = sumToJSON' opts targs x
995
854
996−--------------------------------------------------------------------------------
855+instance ( TwoElemArrayObj arity a
856+ , TwoElemArrayObj arity b
857+ ) => TwoElemArrayObj arity (a :+: b) where
858+ twoElemArrayObj opts pa tj tjl (L1 x) = twoElemArrayObj opts pa tj tjl x
859+ twoElemArrayObj opts pa tj tjl (R1 x) = twoElemArrayObj opts pa tj tjl x
997
860
998−instance ( GToJSON Value arity a
861+instance ( GToJSON arity a
999− , ConsToJSON Value arity a
862+ , ConsToJSON arity a
1000 , Constructor c
863 , Constructor c
1001− ) => SumToJSON' TwoElemArray Value arity (C1 c a) where
864+ ) => TwoElemArrayObj arity (C1 c a) where
1002− sumToJSON' opts targs x = Tagged $ Array $ V.create $ do
865+ twoElemArrayObj opts pa tj tjl x = V.create $ do
1003 mv <- VM.unsafeNew 2
866 mv <- VM.unsafeNew 2
1004 VM.unsafeWrite mv 0 $ String $ pack $ constructorTagModifier opts
867 VM.unsafeWrite mv 0 $ String $ pack $ constructorTagModifier opts
1005 $ conName (undefined :: t c a p)
868 $ conName (undefined :: t c a p)
1006− VM.unsafeWrite mv 1 $ gToJSON opts targs x
869+ VM.unsafeWrite mv 1 $ gToJSON opts pa tj tjl x
1007 return mv
870 return mv
1008
871
1009--------------------------------------------------------------------------------
872--------------------------------------------------------------------------------
1010
873
1011−instance ( GToJSON Encoding arity a
874+class TwoElemArrayEnc arity f where
1012− , ConsToJSON Encoding arity a
875+ twoElemArrayEnc :: Options -> Proxy arity
876+ -> (a -> Encoding) -> ([a] -> Encoding)
877+ -> f a -> Encoding
878+
879+instance ( TwoElemArrayEnc arity a
880+ , TwoElemArrayEnc arity b
881+ ) => TwoElemArrayEnc arity (a :+: b) where
882+ twoElemArrayEnc opts pa te tel (L1 x) = twoElemArrayEnc opts pa te tel x
883+ twoElemArrayEnc opts pa te tel (R1 x) = twoElemArrayEnc opts pa te tel x
884+
885+instance ( GToEncoding arity a
886+ , ConsToEncoding arity a
1013 , Constructor c
887 , Constructor c
1014− ) => SumToJSON' TwoElemArray Encoding arity (C1 c a)
888+ ) => TwoElemArrayEnc arity (C1 c a) where
1015− where
889+ twoElemArrayEnc opts pa te tel x = E.tuple $
1016− sumToJSON' opts targs x = Tagged $ E.list id
1017− [ toEncoding (constructorTagModifier opts (conName (undefined :: t c a p)))
890+ toEncoding (constructorTagModifier opts (conName (undefined :: t c a p))) >*<
1018− , gToJSON opts targs x
891+ gToEncoding opts pa te tel x
1019− ]
892+
893+--------------------------------------------------------------------------------
894+
895+class ConsToJSON arity f where
896+ consToJSON :: Options -> Proxy arity
897+ -> (a -> Value) -> ([a] -> Value)
898+ -> f a -> Value
899+
900+class ConsToJSON' arity f isRecord where
901+ consToJSON' :: Options -> Proxy arity
902+ -> Bool -- ^ Are we a record with one field?
903+ -> (a -> Value) -> ([a] -> Value)
904+ -> f a -> Tagged isRecord Value
905+
906+instance ( IsRecord f isRecord
907+ , ConsToJSON' arity f isRecord
908+ ) => ConsToJSON arity f where
909+ consToJSON opts pa tj tjl =
910+ (unTagged :: Tagged isRecord Value -> Value)
911+ . consToJSON' opts pa (isUnary (undefined :: f a)) tj tjl
912+
913+instance (RecordToPairs arity f) => ConsToJSON' arity f True where
914+ consToJSON' opts pa isUn tj tjl f = let
915+ vals = toList $ recordToPairs opts pa tj tjl f
916+ in case (unwrapUnaryRecords opts,isUn,vals) of
917+ (True,True,[(_,val)]) -> Tagged val
918+ _ -> Tagged $ object vals
919+
920+instance GToJSON arity f => ConsToJSON' arity f False where
921+ consToJSON' opts pa _ tj tjl = Tagged . gToJSON opts pa tj tjl
1020
922
1021--------------------------------------------------------------------------------
923--------------------------------------------------------------------------------
1022
924
1023−class ConsToJSON enc arity f where
925+class ConsToEncoding arity f where
1024− consToJSON :: Options -> ToArgs enc arity a
926+ consToEncoding :: Options -> Proxy arity
1025− -> f a -> enc
927+ -> (a -> Encoding) -> ([a] -> Encoding)
928+ -> f a -> Encoding
1026
929
1027−class ConsToJSON' enc arity f isRecord where
930+class ConsToEncoding' arity f isRecord where
1028− consToJSON' :: Options -> ToArgs enc arity a
931+ consToEncoding' :: Options -> Proxy arity
932+ -> Bool -- ^ Are we a record with one field?
933+ -> (a -> Encoding) -> ([a] -> Encoding)
1029− -> f a -> Tagged isRecord enc
934+ -> f a -> Tagged isRecord Encoding
1030
935
1031instance ( IsRecord f isRecord
936instance ( IsRecord f isRecord
1032− , ConsToJSON' enc arity f isRecord
937+ , ConsToEncoding' arity f isRecord
1033− ) => ConsToJSON enc arity f
938+ ) => ConsToEncoding arity f where
1034− where
939+ consToEncoding opts pa te tel =
1035− consToJSON opts targs =
940+ (unTagged :: Tagged isRecord Encoding -> Encoding)
1036− (unTagged :: Tagged isRecord enc -> enc)
941+ . consToEncoding' opts pa (isUnary (undefined :: f a)) te tel
1037− . consToJSON' opts targs
942+
1038− {-# INLINE consToJSON #-}
943+instance (RecordToEncoding arity f) => ConsToEncoding' arity f True where
1039−
944+ consToEncoding' opts pa isUn te tel x =
1040−instance OVERLAPPING_
945+ let (enc, mbVal) = recordToEncoding opts pa te tel x
1041− ( RecordToPairs enc pairs arity (S1 s f)
946+ in case (unwrapUnaryRecords opts, isUn, mbVal) of
1042− , FromPairs enc pairs
947+ (True, True, Just val) -> Tagged val
1043− , GToJSON enc arity f
948+ _ -> Tagged $ E.wrapObject enc
1044− ) => ConsToJSON' enc arity (S1 s f) True
949+
1045− where
950+instance GToEncoding arity f => ConsToEncoding' arity f False where
1046− consToJSON' opts targs
951+ consToEncoding' opts pa _ te tel = Tagged . gToEncoding opts pa te tel
1047− | unwrapUnaryRecords opts = Tagged . gToJSON opts targs
1048− | otherwise = Tagged . fromPairs . recordToPairs opts targs
1049− {-# INLINE consToJSON' #-}
1050−
1051−instance ( RecordToPairs enc pairs arity f
1052− , FromPairs enc pairs
1053− ) => ConsToJSON' enc arity f True
1054− where
1055− consToJSON' opts targs = Tagged . fromPairs . recordToPairs opts targs
1056− {-# INLINE consToJSON' #-}
1057−
1058−instance GToJSON enc arity f => ConsToJSON' enc arity f False where
1059− consToJSON' opts targs = Tagged . gToJSON opts targs
1060− {-# INLINE consToJSON' #-}
1061
952
1062--------------------------------------------------------------------------------
953--------------------------------------------------------------------------------
1063
954
1064−class RecordToPairs enc pairs arity f where
955+class RecordToPairs arity f where
956+ recordToPairs :: Options -> Proxy arity
957+ -> (a -> Value) -> ([a] -> Value)
958+ -> f a -> DList Pair
959+
960+instance ( RecordToPairs arity a
961+ , RecordToPairs arity b
962+ ) => RecordToPairs arity (a :*: b) where
963+ recordToPairs opts pa tj tjl (a :*: b) = recordToPairs opts pa tj tjl a <>
964+ recordToPairs opts pa tj tjl b
965+
966+instance (Selector s, GToJSON arity a) => RecordToPairs arity (S1 s a) where
967+ recordToPairs = fieldToPair
968+
969+instance OVERLAPPING_ (Selector s, ToJSON a) =>
970+ RecordToPairs arity (S1 s (K1 i (Maybe a))) where
971+ recordToPairs opts _ _ _ (M1 k1) | omitNothingFields opts
972+ , K1 Nothing <- k1 = DList.empty
973+ recordToPairs opts pa tj tjl m1 = fieldToPair opts pa tj tjl m1
974+
975+fieldToPair :: (Selector s, GToJSON arity a)
976+ => Options -> Proxy arity
977+ -> (p -> Value) -> ([p] -> Value)
978+ -> S1 s a p -> DList Pair
979+fieldToPair opts pa tj tjl m1 = pure ( pack $ fieldLabelModifier opts $ selName m1
980+ , gToJSON opts pa tj tjl (unM1 m1)
981+ )
982+
983+--------------------------------------------------------------------------------
984+
985+class RecordToEncoding arity f where
1065 -- 1st element: whole thing
986 -- 1st element: whole thing
1066 -- 2nd element: in case the record has only 1 field, just the value
987 -- 2nd element: in case the record has only 1 field, just the value
1067 -- of the field (without the key); 'Nothing' otherwise
988 -- of the field (without the key); 'Nothing' otherwise
1068− recordToPairs :: Options -> ToArgs enc arity a
989+ recordToEncoding :: Options -> Proxy arity
1069− -> f a -> pairs
990+ -> (a -> Encoding) -> ([a] -> Encoding)
1070−
991+ -> f a -> (Encoding, Maybe Encoding)
1071−instance ( Monoid pairs
992+
1072− , RecordToPairs enc pairs arity a
993+instance ( RecordToEncoding arity a
1073− , RecordToPairs enc pairs arity b
994+ , RecordToEncoding arity b
1074− ) => RecordToPairs enc pairs arity (a :*: b)
995+ ) => RecordToEncoding arity (a :*: b) where
1075− where
996+ recordToEncoding opts pa te tel (a :*: b) | omitNothingFields opts =
1076− recordToPairs opts (targs :: ToArgs enc arity p) (a :*: b) =
997+ (mconcat $ intersperse E.comma $
1077− pairsOf a `mappend` pairsOf b
998+ filter (not . E.nullEncoding)
1078− where
999+ [ fst (recordToEncoding opts pa te tel a)
1079− pairsOf :: (RecordToPairs enc pairs arity f) => f p -> pairs
1000+ , fst (recordToEncoding opts pa te tel b) ]
1080− pairsOf = recordToPairs opts targs
1001+ , Nothing)
1081− {-# INLINE recordToPairs #-}
1002+ recordToEncoding opts pa te tel (a :*: b) =
1082−
1003+ (fst (recordToEncoding opts pa te tel a) <> E.comma <>
1083−instance ( Selector s
1004+ fst (recordToEncoding opts pa te tel b),
1084− , GToJSON enc arity a
1005+ Nothing)
1085− , KeyValuePair enc pairs
1006+
1086− ) => RecordToPairs enc pairs arity (S1 s a)
1007+instance (Selector s, GToEncoding arity a) => RecordToEncoding arity (S1 s a) where
1087− where
1008+ recordToEncoding = fieldToEncoding
1088− recordToPairs = fieldToPair
1009+
1089− {-# INLINE recordToPairs #-}
1010+instance OVERLAPPING_ (Selector s, ToJSON a) =>
1090−
1011+ RecordToEncoding arity (S1 s (K1 i (Maybe a))) where
1091−instance INCOHERENT_
1012+ recordToEncoding opts _ _ _ (M1 k1) | omitNothingFields opts
1092− ( Selector s
1013+ , K1 Nothing <- k1 = (mempty, Nothing)
1093− , GToJSON enc arity (K1 i (Maybe a))
1014+ recordToEncoding opts pa te tel m1 = fieldToEncoding opts pa te tel m1
1094− , KeyValuePair enc pairs
1015+
1095− , Monoid pairs
1016+fieldToEncoding :: (Selector s, GToEncoding arity a)
1096− ) => RecordToPairs enc pairs arity (S1 s (K1 i (Maybe a)))
1017+ => Options -> Proxy arity
1097− where
1018+ -> (p -> Encoding) -> ([p] -> Encoding)
1098− recordToPairs opts _ (M1 k1) | omitNothingFields opts
1019+ -> S1 s a p -> (Encoding, Maybe Encoding)
1099− , K1 Nothing <- k1 = mempty
1020+fieldToEncoding opts pa te tel m1 =
1100− recordToPairs opts targs m1 = fieldToPair opts targs m1
1021+ let keyBuilder = toEncoding (fieldLabelModifier opts $ selName m1)
1101− {-# INLINE recordToPairs #-}
1022+ valueBuilder = gToEncoding opts pa te tel (unM1 m1)
1102−
1023+ in (keyBuilder <> E.colon <> valueBuilder, Just valueBuilder)
1103−instance INCOHERENT_
1104− ( Selector s
1105− , GToJSON enc arity (K1 i (Maybe a))
1106− , KeyValuePair enc pairs
1107− , Monoid pairs
1108− ) => RecordToPairs enc pairs arity (S1 s (K1 i (Semigroup.Option a)))
1109− where
1110− recordToPairs opts targs = recordToPairs opts targs . unwrap
1111− where
1112− unwrap :: S1 s (K1 i (Semigroup.Option a)) p -> S1 s (K1 i (Maybe a)) p
1113− unwrap (M1 (K1 (Semigroup.Option a))) = M1 (K1 a)
1114− {-# INLINE recordToPairs #-}
1115−
1116−fieldToPair :: (Selector s
1117− , GToJSON enc arity a
1118− , KeyValuePair enc pairs)
1119− => Options -> ToArgs enc arity p
1120− -> S1 s a p -> pairs
1121−fieldToPair opts targs m1 =
1122− let key = fieldLabelModifier opts (selName m1)
1123− value = gToJSON opts targs (unM1 m1)
1124− in key `pair` value
1125−{-# INLINE fieldToPair #-}
1126
1024
1127--------------------------------------------------------------------------------
1025--------------------------------------------------------------------------------
1128
1026
1129class WriteProduct arity f where
1027class WriteProduct arity f where
1130 writeProduct :: Options
1028 writeProduct :: Options
1131− -> ToArgs Value arity a
1029+ -> Proxy arity
1132 -> VM.MVector s Value
1030 -> VM.MVector s Value
1133 -> Int -- ^ index
1031 -> Int -- ^ index
1134 -> Int -- ^ length
1032 -> Int -- ^ length
1033+ -> (a -> Value)
1034+ -> ([a] -> Value)
1135 -> f a
1035 -> f a
1136 -> ST s ()
1036 -> ST s ()
1137
1037
1138instance ( WriteProduct arity a
1038instance ( WriteProduct arity a
1139 , WriteProduct arity b
1039 , WriteProduct arity b
1140 ) => WriteProduct arity (a :*: b) where
1040 ) => WriteProduct arity (a :*: b) where
1141− writeProduct opts targs mv ix len (a :*: b) = do
1041+ writeProduct opts pa mv ix len tj tjl (a :*: b) = do
1142− writeProduct opts targs mv ix lenL a
1042+ writeProduct opts pa mv ix lenL tj tjl a
1143− writeProduct opts targs mv ixR lenR b
1043+ writeProduct opts pa mv ixR lenR tj tjl b
1144 where
1044 where
1145 lenL = len `unsafeShiftR` 1
1045 lenL = len `unsafeShiftR` 1
1146 lenR = len - lenL
1046 lenR = len - lenL
1147 ixR = ix + lenL
1047 ixR = ix + lenL
1148− {-# INLINE writeProduct #-}
1149
1048
1150−instance OVERLAPPABLE_ (GToJSON Value arity a) => WriteProduct arity a where
1049+instance OVERLAPPABLE_ (GToJSON arity a) => WriteProduct arity a where
1151− writeProduct opts targs mv ix _ =
1050+ writeProduct opts pa mv ix _ tj tjl =
1152− VM.unsafeWrite mv ix . gToJSON opts targs
1051+ VM.unsafeWrite mv ix . gToJSON opts pa tj tjl
1153− {-# INLINE writeProduct #-}
1154
1052
1155--------------------------------------------------------------------------------
1053--------------------------------------------------------------------------------
1156
1054
1157class EncodeProduct arity f where
1055class EncodeProduct arity f where
1158− encodeProduct :: Options -> ToArgs Encoding arity a
1056+ encodeProduct :: Options -> Proxy arity
1159− -> f a -> Encoding' E.InArray
1057+ -> (a -> Encoding) -> ([a] -> Encoding)
1058+ -> f a -> Encoding
1160
1059
1161instance ( EncodeProduct arity a
1060instance ( EncodeProduct arity a
1162 , EncodeProduct arity b
1061 , EncodeProduct arity b
1163 ) => EncodeProduct arity (a :*: b) where
1062 ) => EncodeProduct arity (a :*: b) where
1164− encodeProduct opts targs (a :*: b) | omitNothingFields opts =
1063+ encodeProduct opts pa te tel (a :*: b) | omitNothingFields opts =
1165− E.econcat $ intersperse E.comma $
1064+ mconcat $ intersperse E.comma $
1166 filter (not . E.nullEncoding)
1065 filter (not . E.nullEncoding)
1167− [encodeProduct opts targs a, encodeProduct opts targs b]
1066+ [encodeProduct opts pa te tel a, encodeProduct opts pa te tel b]
1168− encodeProduct opts targs (a :*: b) =
1067+ encodeProduct opts pa te tel (a :*: b) = encodeProduct opts pa te tel a <>
1169− encodeProduct opts targs a >*<
1068+ E.comma <>
1170− encodeProduct opts targs b
1069+ encodeProduct opts pa te tel b
1171− {-# INLINE encodeProduct #-}
1172
1070
1173−instance OVERLAPPABLE_ (GToJSON Encoding arity a) => EncodeProduct arity a where
1071+instance OVERLAPPABLE_ (GToEncoding arity a) => EncodeProduct arity a where
1174− encodeProduct opts targs a = E.retagEncoding $ gToJSON opts targs a
1072+ encodeProduct opts = gToEncoding opts
1175− {-# INLINE encodeProduct #-}
1176
1073
1177--------------------------------------------------------------------------------
1074--------------------------------------------------------------------------------
1178
1075
1179−instance ( GToJSON enc arity a
1076+class ObjectWithSingleFieldObj arity f where
1180− , ConsToJSON enc arity a
1077+ objectWithSingleFieldObj :: Options -> Proxy arity
1181− , FromPairs enc pairs
1078+ -> (a -> Value) -> ([a] -> Value)
1182− , KeyValuePair enc pairs
1079+ -> f a -> Object
1080+
1081+instance ( ObjectWithSingleFieldObj arity a
1082+ , ObjectWithSingleFieldObj arity b
1083+ ) => ObjectWithSingleFieldObj arity (a :+: b) where
1084+ objectWithSingleFieldObj opts pa tj tjl (L1 x) =
1085+ objectWithSingleFieldObj opts pa tj tjl x
1086+ objectWithSingleFieldObj opts pa tj tjl (R1 x) =
1087+ objectWithSingleFieldObj opts pa tj tjl x
1088+
1089+instance ( GToJSON arity a
1090+ , ConsToJSON arity a
1183 , Constructor c
1091 , Constructor c
1184− ) => SumToJSON' ObjectWithSingleField enc arity (C1 c a)
1092+ ) => ObjectWithSingleFieldObj arity (C1 c a) where
1185− where
1093+ objectWithSingleFieldObj opts pa tj tjl = H.singleton typ . gToJSON opts pa tj tjl
1186− sumToJSON' opts targs =
1187− Tagged . fromPairs . (typ `pair`) . gToJSON opts targs
1188 where
1094 where
1189− typ = constructorTagModifier opts $
1095+ typ = pack $ constructorTagModifier opts $
1190 conName (undefined :: t c a p)
1096 conName (undefined :: t c a p)
1191
1097
1192--------------------------------------------------------------------------------
1098--------------------------------------------------------------------------------
1193
1099
1194−instance OVERLAPPABLE_
1100+class ObjectWithSingleFieldEnc arity f where
1195− ( ConsToJSON enc arity a
1101+ objectWithSingleFieldEnc :: Options -> Proxy arity
1196− ) => SumToJSON' UntaggedValue enc arity (C1 c a)
1102+ -> (a -> Encoding) -> ([a] -> Encoding)
1197− where
1103+ -> f a -> Encoding
1198− sumToJSON' opts targs = Tagged . gToJSON opts targs
1104+
1199−
1105+instance ( ObjectWithSingleFieldEnc arity a
1200−instance OVERLAPPING_
1106+ , ObjectWithSingleFieldEnc arity b
1201− ( Constructor c
1107+ ) => ObjectWithSingleFieldEnc arity (a :+: b) where
1202− , FromString enc
1108+ objectWithSingleFieldEnc opts pa te tel (L1 x) =
1203− ) => SumToJSON' UntaggedValue enc arity (C1 c U1)
1109+ objectWithSingleFieldEnc opts pa te tel x
1204− where
1110+ objectWithSingleFieldEnc opts pa te tel (R1 x) =
1205− sumToJSON' opts _ _ = Tagged . fromString $
1111+ objectWithSingleFieldEnc opts pa te tel x
1206− constructorTagModifier opts $ conName (undefined :: t c U1 p)
1112+
1113+instance ( GToEncoding arity a
1114+ , ConsToEncoding arity a
1115+ , Constructor c
1116+ ) => ObjectWithSingleFieldEnc arity (C1 c a) where
1117+ objectWithSingleFieldEnc opts pa te tel v =
1118+ E.openCurly <>
1119+ toEncoding
1120+ (constructorTagModifier opts
1121+ (conName (undefined :: t c a p))) <>
1122+ E.colon <>
1123+ gToEncoding opts pa te tel v <>
1124+ E.closeCurly
1207
1125
1208-------------------------------------------------------------------------------
1126-------------------------------------------------------------------------------
1209-- Instances
1127-- Instances
@@ -1213,6 +1131,21 @@ instance OVERLAPPING_
1213-- base
1131-- base
1214-------------------------------------------------------------------------------
1132-------------------------------------------------------------------------------
1215
1133
1134+instance ToJSON1 Identity where
1135+ liftToJSON t _ (Identity a) = t a
1136+ {-# INLINE liftToJSON #-}
1137+
1138+ liftToEncoding t _ (Identity a) = t a
1139+ {-# INLINE liftToEncoding #-}
1140+
1141+instance (ToJSON a) => ToJSON (Identity a) where
1142+ toJSON = toJSON1
1143+ {-# INLINE toJSON #-}
1144+
1145+ toEncoding = toEncoding1
1146+ {-# INLINE toEncoding #-}
1147+
1148+
1216instance ToJSON2 Const where
1149instance ToJSON2 Const where
1217 liftToJSON2 t _ _ _ (Const x) = t x
1150 liftToJSON2 t _ _ _ (Const x) = t x
1218 {-# INLINE liftToJSON2 #-}
1151 {-# INLINE liftToJSON2 #-}
@@ -1241,7 +1174,7 @@ instance ToJSON1 Maybe where
1241 {-# INLINE liftToJSON #-}
1174 {-# INLINE liftToJSON #-}
1242
1175
1243 liftToEncoding t _ (Just a) = t a
1176 liftToEncoding t _ (Just a) = t a
1244− liftToEncoding _ _ Nothing = E.null_
1177+ liftToEncoding _ _ Nothing = Encoding EB.null_
1245 {-# INLINE liftToEncoding #-}
1178 {-# INLINE liftToEncoding #-}
1246
1179
1247instance (ToJSON a) => ToJSON (Maybe a) where
1180instance (ToJSON a) => ToJSON (Maybe a) where
@@ -1253,13 +1186,19 @@ instance (ToJSON a) => ToJSON (Maybe a) where
1253
1186
1254
1187
1255instance ToJSON2 Either where
1188instance ToJSON2 Either where
1256− liftToJSON2 toA _ _toB _ (Left a) = Object $ H.singleton "Left" (toA a)
1189+ liftToJSON2 toA _ _toB _ (Left a) = Object $ H.singleton left (toA a)
1257− liftToJSON2 _toA _ toB _ (Right b) = Object $ H.singleton "Right" (toB b)
1190+ liftToJSON2 _toA _ toB _ (Right b) = Object $ H.singleton right (toB b)
1258 {-# INLINE liftToJSON2 #-}
1191 {-# INLINE liftToJSON2 #-}
1259
1192
1260− liftToEncoding2 toA _ _toB _ (Left a) = E.pairs $ E.pair "Left" $ toA a
1193+ liftToEncoding2 toA _ _toB _ (Left a) =
1194+ Encoding (B.shortByteString "{\"Left\":")
1195+ <> toA a
1196+ <> Encoding (B.char7 '}')
1261
1197
1262− liftToEncoding2 _toA _ toB _ (Right b) = E.pairs $ E.pair "Right" $ toB b
1198+ liftToEncoding2 _toA _ toB _ (Right b) =
1199+ Encoding (B.shortByteString "{\"Right\":")
1200+ <> toB b
1201+ <> Encoding (B.char7 '}')
1263 {-# INLINE liftToEncoding2 #-}
1202 {-# INLINE liftToEncoding2 #-}
1264
1203
1265instance (ToJSON a) => ToJSON1 (Either a) where
1204instance (ToJSON a) => ToJSON1 (Either a) where
@@ -1276,24 +1215,18 @@ instance (ToJSON a, ToJSON b) => ToJSON (Either a b) where
1276 toEncoding = toEncoding2
1215 toEncoding = toEncoding2
1277 {-# INLINE toEncoding #-}
1216 {-# INLINE toEncoding #-}
1278
1217
1279−instance ToJSON Void where
1218+left, right :: Text
1280− toJSON = absurd
1219+left = "Left"
1281− {-# INLINE toJSON #-}
1220+right = "Right"
1282−
1283− toEncoding = absurd
1284− {-# INLINE toEncoding #-}
1285
1221
1286
1222
1287instance ToJSON Bool where
1223instance ToJSON Bool where
1288 toJSON = Bool
1224 toJSON = Bool
1289 {-# INLINE toJSON #-}
1225 {-# INLINE toJSON #-}
1290
1226
1291− toEncoding = E.bool
1227+ toEncoding = Encoding . EB.bool
1292 {-# INLINE toEncoding #-}
1228 {-# INLINE toEncoding #-}
1293
1229
1294−instance ToJSONKey Bool where
1295− toJSONKey = toJSONKeyText $ \x -> if x then "true" else "false"
1296−
1297
1230
1298instance ToJSON Ordering where
1231instance ToJSON Ordering where
1299 toJSON = toJSON . orderingToText
1232 toJSON = toJSON . orderingToText
@@ -1320,10 +1253,10 @@ instance ToJSON Char where
1320 toJSONList = String . T.pack
1253 toJSONList = String . T.pack
1321 {-# INLINE toJSONList #-}
1254 {-# INLINE toJSONList #-}
1322
1255
1323− toEncoding = E.string . (:[])
1256+ toEncoding = Encoding . EB.string . (:[])
1324 {-# INLINE toEncoding #-}
1257 {-# INLINE toEncoding #-}
1325
1258
1326− toEncodingList = E.string
1259+ toEncodingList = Encoding . EB.string
1327 {-# INLINE toEncodingList #-}
1260 {-# INLINE toEncodingList #-}
1328
1261
1329
1262
@@ -1331,13 +1264,9 @@ instance ToJSON Double where
1331 toJSON = realFloatToJSON
1264 toJSON = realFloatToJSON
1332 {-# INLINE toJSON #-}
1265 {-# INLINE toJSON #-}
1333
1266
1334− toEncoding = E.double
1267+ toEncoding = realFloatToEncoding
1335 {-# INLINE toEncoding #-}
1268 {-# INLINE toEncoding #-}
1336
1269
1337−instance ToJSONKey Double where
1338− toJSONKey = toJSONKeyTextEnc E.doubleText
1339− {-# INLINE toJSONKey #-}
1340−
1341
1270
1342instance ToJSON Number where
1271instance ToJSON Number where
1343 toJSON (D d) = toJSON d
1272 toJSON (D d) = toJSON d
@@ -1353,23 +1282,20 @@ instance ToJSON Float where
1353 toJSON = realFloatToJSON
1282 toJSON = realFloatToJSON
1354 {-# INLINE toJSON #-}
1283 {-# INLINE toJSON #-}
1355
1284
1356− toEncoding = E.float
1285+ toEncoding = realFloatToEncoding
1357 {-# INLINE toEncoding #-}
1286 {-# INLINE toEncoding #-}
1358
1287
1359−instance ToJSONKey Float where
1360− toJSONKey = toJSONKeyTextEnc E.floatText
1361− {-# INLINE toJSONKey #-}
1362
1288
1363−
1289+instance ToJSON (Ratio Integer) where
1364−instance (ToJSON a, Integral a) => ToJSON (Ratio a) where
1365 toJSON r = object [ "numerator" .= numerator r
1290 toJSON r = object [ "numerator" .= numerator r
1366 , "denominator" .= denominator r
1291 , "denominator" .= denominator r
1367 ]
1292 ]
1368 {-# INLINE toJSON #-}
1293 {-# INLINE toJSON #-}
1369
1294
1370− toEncoding r = E.pairs $
1295+ toEncoding r = Encoding $
1371− "numerator" .= numerator r <>
1296+ B.shortByteString "{\"numerator\":" <> builder (numerator r) <>
1372− "denominator" .= denominator r
1297+ B.shortByteString ",\"denominator\":" <> builder (denominator r) <>
1298+ B.char7 '}'
1373 {-# INLINE toEncoding #-}
1299 {-# INLINE toEncoding #-}
1374
1300
1375
1301
@@ -1377,37 +1303,24 @@ instance HasResolution a => ToJSON (Fixed a) where
1377 toJSON = Number . realToFrac
1303 toJSON = Number . realToFrac
1378 {-# INLINE toJSON #-}
1304 {-# INLINE toJSON #-}
1379
1305
1380− toEncoding = E.scientific . realToFrac
1306+ toEncoding = Encoding . EB.number . realToFrac
1381 {-# INLINE toEncoding #-}
1307 {-# INLINE toEncoding #-}
1382
1308
1383−instance HasResolution a => ToJSONKey (Fixed a) where
1384− toJSONKey = toJSONKeyTextEnc (E.scientificText . realToFrac)
1385− {-# INLINE toJSONKey #-}
1386−
1387
1309
1388instance ToJSON Int where
1310instance ToJSON Int where
1389 toJSON = Number . fromIntegral
1311 toJSON = Number . fromIntegral
1390 {-# INLINE toJSON #-}
1312 {-# INLINE toJSON #-}
1391
1313
1392− toEncoding = E.int
1314+ toEncoding = Encoding . B.intDec
1393 {-# INLINE toEncoding #-}
1315 {-# INLINE toEncoding #-}
1394
1316
1395−instance ToJSONKey Int where
1396− toJSONKey = toJSONKeyTextEnc E.intText
1397− {-# INLINE toJSONKey #-}
1398−
1399−
1400instance ToJSON Integer where
1317instance ToJSON Integer where
1401 toJSON = Number . fromInteger
1318 toJSON = Number . fromInteger
1402 {-# INLINE toJSON #-}
1319 {-# INLINE toJSON #-}
1403
1320
1404− toEncoding = E.integer
1321+ toEncoding = Encoding . B.integerDec
1405 {-# INLINE toEncoding #-}
1322 {-# INLINE toEncoding #-}
1406
1323
1407−instance ToJSONKey Integer where
1408− toJSONKey = toJSONKeyTextEnc E.integerText
1409− {-# INLINE toJSONKey #-}
1410−
1411
1324
1412instance ToJSON Natural where
1325instance ToJSON Natural where
1413 toJSON = toJSON . toInteger
1326 toJSON = toJSON . toInteger
@@ -1416,147 +1329,93 @@ instance ToJSON Natural where
1416 toEncoding = toEncoding . toInteger
1329 toEncoding = toEncoding . toInteger
1417 {-# INLINE toEncoding #-}
1330 {-# INLINE toEncoding #-}
1418
1331
1419−instance ToJSONKey Natural where
1420− toJSONKey = toJSONKeyTextEnc (E.integerText . toInteger)
1421− {-# INLINE toJSONKey #-}
1422−
1423
1332
1424instance ToJSON Int8 where
1333instance ToJSON Int8 where
1425 toJSON = Number . fromIntegral
1334 toJSON = Number . fromIntegral
1426 {-# INLINE toJSON #-}
1335 {-# INLINE toJSON #-}
1427
1336
1428− toEncoding = E.int8
1337+ toEncoding = Encoding . B.int8Dec
1429 {-# INLINE toEncoding #-}
1338 {-# INLINE toEncoding #-}
1430
1339
1431−instance ToJSONKey Int8 where
1432− toJSONKey = toJSONKeyTextEnc E.int8Text
1433− {-# INLINE toJSONKey #-}
1434−
1435
1340
1436instance ToJSON Int16 where
1341instance ToJSON Int16 where
1437 toJSON = Number . fromIntegral
1342 toJSON = Number . fromIntegral
1438 {-# INLINE toJSON #-}
1343 {-# INLINE toJSON #-}
1439
1344
1440− toEncoding = E.int16
1345+ toEncoding = Encoding . B.int16Dec
1441 {-# INLINE toEncoding #-}
1346 {-# INLINE toEncoding #-}
1442
1347
1443−instance ToJSONKey Int16 where
1444− toJSONKey = toJSONKeyTextEnc E.int16Text
1445− {-# INLINE toJSONKey #-}
1446−
1447
1348
1448instance ToJSON Int32 where
1349instance ToJSON Int32 where
1449 toJSON = Number . fromIntegral
1350 toJSON = Number . fromIntegral
1450 {-# INLINE toJSON #-}
1351 {-# INLINE toJSON #-}
1451
1352
1452− toEncoding = E.int32
1353+ toEncoding = Encoding . B.int32Dec
1453 {-# INLINE toEncoding #-}
1354 {-# INLINE toEncoding #-}
1454
1355
1455−instance ToJSONKey Int32 where
1456− toJSONKey = toJSONKeyTextEnc E.int32Text
1457− {-# INLINE toJSONKey #-}
1458−
1459
1356
1460instance ToJSON Int64 where
1357instance ToJSON Int64 where
1461 toJSON = Number . fromIntegral
1358 toJSON = Number . fromIntegral
1462 {-# INLINE toJSON #-}
1359 {-# INLINE toJSON #-}
1463
1360
1464− toEncoding = E.int64
1361+ toEncoding = Encoding . B.int64Dec
1465 {-# INLINE toEncoding #-}
1362 {-# INLINE toEncoding #-}
1466
1363
1467−instance ToJSONKey Int64 where
1468− toJSONKey = toJSONKeyTextEnc E.int64Text
1469− {-# INLINE toJSONKey #-}
1470
1364
1471instance ToJSON Word where
1365instance ToJSON Word where
1472 toJSON = Number . fromIntegral
1366 toJSON = Number . fromIntegral
1473 {-# INLINE toJSON #-}
1367 {-# INLINE toJSON #-}
1474
1368
1475− toEncoding = E.word
1369+ toEncoding = Encoding . B.wordDec
1476 {-# INLINE toEncoding #-}
1370 {-# INLINE toEncoding #-}
1477
1371
1478−instance ToJSONKey Word where
1479− toJSONKey = toJSONKeyTextEnc E.wordText
1480− {-# INLINE toJSONKey #-}
1481−
1482
1372
1483instance ToJSON Word8 where
1373instance ToJSON Word8 where
1484 toJSON = Number . fromIntegral
1374 toJSON = Number . fromIntegral
1485 {-# INLINE toJSON #-}
1375 {-# INLINE toJSON #-}
1486
1376
1487− toEncoding = E.word8
1377+ toEncoding = Encoding . B.word8Dec
1488 {-# INLINE toEncoding #-}
1378 {-# INLINE toEncoding #-}
1489
1379
1490−instance ToJSONKey Word8 where
1491− toJSONKey = toJSONKeyTextEnc E.word8Text
1492− {-# INLINE toJSONKey #-}
1493−
1494
1380
1495instance ToJSON Word16 where
1381instance ToJSON Word16 where
1496 toJSON = Number . fromIntegral
1382 toJSON = Number . fromIntegral
1497 {-# INLINE toJSON #-}
1383 {-# INLINE toJSON #-}
1498
1384
1499− toEncoding = E.word16
1385+ toEncoding = Encoding . B.word16Dec
1500 {-# INLINE toEncoding #-}
1386 {-# INLINE toEncoding #-}
1501
1387
1502−instance ToJSONKey Word16 where
1503− toJSONKey = toJSONKeyTextEnc E.word16Text
1504− {-# INLINE toJSONKey #-}
1505−
1506
1388
1507instance ToJSON Word32 where
1389instance ToJSON Word32 where
1508 toJSON = Number . fromIntegral
1390 toJSON = Number . fromIntegral
1509 {-# INLINE toJSON #-}
1391 {-# INLINE toJSON #-}
1510
1392
1511− toEncoding = E.word32
1393+ toEncoding = Encoding . B.word32Dec
1512 {-# INLINE toEncoding #-}
1394 {-# INLINE toEncoding #-}
1513
1395
1514−instance ToJSONKey Word32 where
1515− toJSONKey = toJSONKeyTextEnc E.word32Text
1516− {-# INLINE toJSONKey #-}
1517−
1518−
1519instance ToJSON Word64 where
1396instance ToJSON Word64 where
1520 toJSON = Number . fromIntegral
1397 toJSON = Number . fromIntegral
1521 {-# INLINE toJSON #-}
1398 {-# INLINE toJSON #-}
1522
1399
1523− toEncoding = E.word64
1400+ toEncoding = Encoding . B.word64Dec
1524− {-# INLINE toEncoding #-}
1525−
1526−instance ToJSONKey Word64 where
1527− toJSONKey = toJSONKeyTextEnc E.word64Text
1528− {-# INLINE toJSONKey #-}
1529−
1530−instance ToJSON CTime where
1531− toJSON (CTime i) = toJSON i
1532− {-# INLINE toJSON #-}
1533−
1534− toEncoding (CTime i) = toEncoding i
1535 {-# INLINE toEncoding #-}
1401 {-# INLINE toEncoding #-}
1536
1402
1537instance ToJSON Text where
1403instance ToJSON Text where
1538 toJSON = String
1404 toJSON = String
1539 {-# INLINE toJSON #-}
1405 {-# INLINE toJSON #-}
1540
1406
1541− toEncoding = E.text
1407+ toEncoding = Encoding . EB.text
1542 {-# INLINE toEncoding #-}
1408 {-# INLINE toEncoding #-}
1543
1409
1544−instance ToJSONKey Text where
1545− toJSONKey = toJSONKeyText id
1546− {-# INLINE toJSONKey #-}
1547−
1548−
1549instance ToJSON LT.Text where
1410instance ToJSON LT.Text where
1550 toJSON = String . LT.toStrict
1411 toJSON = String . LT.toStrict
1551 {-# INLINE toJSON #-}
1412 {-# INLINE toJSON #-}
1552
1413
1553− toEncoding = E.lazyText
1414+ toEncoding t = Encoding $
1415+ B.char7 '"' <>
1416+ LT.foldrChunks (\x xs -> EB.unquoted x <> xs) (B.char7 '"') t
1554 {-# INLINE toEncoding #-}
1417 {-# INLINE toEncoding #-}
1555
1418
1556−instance ToJSONKey LT.Text where
1557− toJSONKey = toJSONKeyText LT.toStrict
1558−
1559−
1560instance ToJSON Version where
1419instance ToJSON Version where
1561 toJSON = toJSON . showVersion
1420 toJSON = toJSON . showVersion
1562 {-# INLINE toJSON #-}
1421 {-# INLINE toJSON #-}
@@ -1564,8 +1423,6 @@ instance ToJSON Version where
1564 toEncoding = toEncoding . showVersion
1423 toEncoding = toEncoding . showVersion
1565 {-# INLINE toEncoding #-}
1424 {-# INLINE toEncoding #-}
1566
1425
1567−instance ToJSONKey Version where
1568− toJSONKey = toJSONKeyText (T.pack . showVersion)
1569
1426
1570-------------------------------------------------------------------------------
1427-------------------------------------------------------------------------------
1571-- semigroups NonEmpty
1428-- semigroups NonEmpty
@@ -1593,138 +1450,7 @@ instance ToJSON Scientific where
1593 toJSON = Number
1450 toJSON = Number
1594 {-# INLINE toJSON #-}
1451 {-# INLINE toJSON #-}
1595
1452
1596− toEncoding = E.scientific
1453+ toEncoding = Encoding . EB.number
1597− {-# INLINE toEncoding #-}
1598−
1599−instance ToJSONKey Scientific where
1600− toJSONKey = toJSONKeyTextEnc E.scientificText
1601−
1602−-------------------------------------------------------------------------------
1603−-- DList
1604−-------------------------------------------------------------------------------
1605−
1606−instance ToJSON1 DList.DList where
1607− liftToJSON t _ = listValue t . toList
1608− {-# INLINE liftToJSON #-}
1609−
1610− liftToEncoding t _ = listEncoding t . toList
1611− {-# INLINE liftToEncoding #-}
1612−
1613−instance (ToJSON a) => ToJSON (DList.DList a) where
1614− toJSON = toJSON1
1615− {-# INLINE toJSON #-}
1616−
1617− toEncoding = toEncoding1
1618− {-# INLINE toEncoding #-}
1619−
1620−-------------------------------------------------------------------------------
1621−-- transformers - Functors
1622−-------------------------------------------------------------------------------
1623−
1624−instance ToJSON1 Identity where
1625− liftToJSON t _ (Identity a) = t a
1626− {-# INLINE liftToJSON #-}
1627−
1628− liftToJSONList _ tl xs = tl (map runIdentity xs)
1629− {-# INLINE liftToJSONList #-}
1630−
1631− liftToEncoding t _ (Identity a) = t a
1632− {-# INLINE liftToEncoding #-}
1633−
1634− liftToEncodingList _ tl xs = tl (map runIdentity xs)
1635− {-# INLINE liftToEncodingList #-}
1636−
1637−instance (ToJSON a) => ToJSON (Identity a) where
1638− toJSON = toJSON1
1639− {-# INLINE toJSON #-}
1640−
1641− toJSONList = liftToJSONList toJSON toJSONList
1642− {-# INLINE toJSONList #-}
1643−
1644− toEncoding = toEncoding1
1645− {-# INLINE toEncoding #-}
1646−
1647− toEncodingList = liftToEncodingList toEncoding toEncodingList
1648− {-# INLINE toEncodingList #-}
1649−
1650−instance (ToJSONKey a) => ToJSONKey (Identity a) where
1651− toJSONKey = contramapToJSONKeyFunction runIdentity toJSONKey
1652− toJSONKeyList = contramapToJSONKeyFunction (map runIdentity) toJSONKeyList
1653−
1654−
1655−instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Compose f g) where
1656− liftToJSON tv tvl (Compose x) = liftToJSON g gl x
1657− where
1658− g = liftToJSON tv tvl
1659− gl = liftToJSONList tv tvl
1660− {-# INLINE liftToJSON #-}
1661−
1662− liftToJSONList te tel xs = liftToJSONList g gl (map getCompose xs)
1663− where
1664− g = liftToJSON te tel
1665− gl = liftToJSONList te tel
1666− {-# INLINE liftToJSONList #-}
1667−
1668− liftToEncoding te tel (Compose x) = liftToEncoding g gl x
1669− where
1670− g = liftToEncoding te tel
1671− gl = liftToEncodingList te tel
1672− {-# INLINE liftToEncoding #-}
1673−
1674− liftToEncodingList te tel xs = liftToEncodingList g gl (map getCompose xs)
1675− where
1676− g = liftToEncoding te tel
1677− gl = liftToEncodingList te tel
1678− {-# INLINE liftToEncodingList #-}
1679−
1680−instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Compose f g a) where
1681− toJSON = toJSON1
1682− {-# INLINE toJSON #-}
1683−
1684− toJSONList = liftToJSONList toJSON toJSONList
1685− {-# INLINE toJSONList #-}
1686−
1687− toEncoding = toEncoding1
1688− {-# INLINE toEncoding #-}
1689−
1690− toEncodingList = liftToEncodingList toEncoding toEncodingList
1691− {-# INLINE toEncodingList #-}
1692−
1693−
1694−instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Product f g) where
1695− liftToJSON tv tvl (Pair x y) = liftToJSON2 tx txl ty tyl (x, y)
1696− where
1697− tx = liftToJSON tv tvl
1698− txl = liftToJSONList tv tvl
1699− ty = liftToJSON tv tvl
1700− tyl = liftToJSONList tv tvl
1701−
1702− liftToEncoding te tel (Pair x y) = liftToEncoding2 tx txl ty tyl (x, y)
1703− where
1704− tx = liftToEncoding te tel
1705− txl = liftToEncodingList te tel
1706− ty = liftToEncoding te tel
1707− tyl = liftToEncodingList te tel
1708−
1709−instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Product f g a) where
1710− toJSON = toJSON1
1711− {-# INLINE toJSON #-}
1712−
1713− toEncoding = toEncoding1
1714− {-# INLINE toEncoding #-}
1715−
1716−instance (ToJSON1 f, ToJSON1 g) => ToJSON1 (Sum f g) where
1717− liftToJSON tv tvl (InL x) = Object $ H.singleton "InL" (liftToJSON tv tvl x)
1718− liftToJSON tv tvl (InR y) = Object $ H.singleton "InR" (liftToJSON tv tvl y)
1719−
1720− liftToEncoding te tel (InL x) = E.pairs $ E.pair "InL" $ liftToEncoding te tel x
1721− liftToEncoding te tel (InR y) = E.pairs $ E.pair "InR" $ liftToEncoding te tel y
1722−
1723−instance (ToJSON1 f, ToJSON1 g, ToJSON a) => ToJSON (Sum f g a) where
1724− toJSON = toJSON1
1725− {-# INLINE toJSON #-}
1726−
1727− toEncoding = toEncoding1
1728 {-# INLINE toEncoding #-}
1454 {-# INLINE toEncoding #-}
1729
1455
1730-------------------------------------------------------------------------------
1456-------------------------------------------------------------------------------
@@ -1792,15 +1518,17 @@ instance ToJSON a => ToJSON (IntMap.IntMap a) where
1792
1518
1793instance ToJSONKey k => ToJSON1 (M.Map k) where
1519instance ToJSONKey k => ToJSON1 (M.Map k) where
1794 liftToJSON g _ = case toJSONKey of
1520 liftToJSON g _ = case toJSONKey of
1795− ToJSONKeyText f _ -> Object . mapHashKeyVal f g
1521+ ToJSONKeyText (f,_) -> Object . mapHashKeyVal f g
1796− ToJSONKeyValue f _ -> Array . V.fromList . map (toJSONPair f g) . M.toList
1522+ ToJSONKeyValue (f,_) -> Array . V.fromList . map (toJSONPair f g) . M.toList
1797 {-# INLINE liftToJSON #-}
1523 {-# INLINE liftToJSON #-}
1798
1524
1525+ -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> M.Map k a -> Encoding
1799 liftToEncoding g _ = case toJSONKey of
1526 liftToEncoding g _ = case toJSONKey of
1800− ToJSONKeyText _ f -> dict f g M.foldrWithKey
1527+ ToJSONKeyText (_,f) -> dict f g M.foldrWithKey
1801− ToJSONKeyValue _ f -> listEncoding (pairEncoding f) . M.toList
1528+ ToJSONKeyValue (_,f) -> listEncoding (pairEncoding f) . M.toList
1802 where
1529 where
1803− pairEncoding f (a, b) = E.list id [f a, g b]
1530+ -- pairEncoding :: (k -> Encoding) -> (k, a) -> Encoding
1531+ pairEncoding f (a, b) = tuple $ f a >*< g b
1804 {-# INLINE liftToEncoding #-}
1532 {-# INLINE liftToEncoding #-}
1805
1533
1806
1534
@@ -1838,17 +1566,6 @@ instance (ToJSON v) => ToJSON (Tree.Tree v) where
1838 toEncoding = toEncoding1
1566 toEncoding = toEncoding1
1839 {-# INLINE toEncoding #-}
1567 {-# INLINE toEncoding #-}
1840
1568
1841−-------------------------------------------------------------------------------
1842−-- uuid
1843−-------------------------------------------------------------------------------
1844−
1845−instance ToJSON UUID.UUID where
1846− toJSON = toJSON . UUID.toText
1847− toEncoding = E.unsafeToEncoding . EB.quote . B.byteString . UUID.toASCIIBytes
1848−
1849−instance ToJSONKey UUID.UUID where
1850− toJSONKey = ToJSONKeyText UUID.toText $
1851− E.unsafeToEncoding . EB.quote . B.byteString . UUID.toASCIIBytes
1852
1569
1853-------------------------------------------------------------------------------
1570-------------------------------------------------------------------------------
1854-- vector
1571-- vector
@@ -1858,20 +1575,29 @@ instance ToJSON1 Vector where
1858 liftToJSON t _ = Array . V.map t
1575 liftToJSON t _ = Array . V.map t
1859 {-# INLINE liftToJSON #-}
1576 {-# INLINE liftToJSON #-}
1860
1577
1861− liftToEncoding t _ = listEncoding t . V.toList
1578+ liftToEncoding t _ xs
1579+ | V.null xs = emptyArray_
1580+ | otherwise = Encoding $
1581+ B.char7 '[' <> fromEncoding (t (V.unsafeHead xs)) <>
1582+ V.foldr go (B.char7 ']') (V.unsafeTail xs)
1583+ where
1584+ go v b = B.char7 ',' <> fromEncoding (t v) <> b
1862 {-# INLINE liftToEncoding #-}
1585 {-# INLINE liftToEncoding #-}
1863
1586
1864instance (ToJSON a) => ToJSON (Vector a) where
1587instance (ToJSON a) => ToJSON (Vector a) where
1865− {-# SPECIALIZE instance ToJSON Array #-}
1588+ toJSON = Array . V.map toJSON
1866−
1867− toJSON = toJSON1
1868 {-# INLINE toJSON #-}
1589 {-# INLINE toJSON #-}
1869
1590
1870− toEncoding = toEncoding1
1591+ toEncoding = encodeVector
1871 {-# INLINE toEncoding #-}
1592 {-# INLINE toEncoding #-}
1872
1593
1873encodeVector :: (ToJSON a, VG.Vector v a) => v a -> Encoding
1594encodeVector :: (ToJSON a, VG.Vector v a) => v a -> Encoding
1874−encodeVector = listEncoding toEncoding . VG.toList
1595+encodeVector xs
1596+ | VG.null xs = emptyArray_
1597+ | otherwise = Encoding $
1598+ B.char7 '[' <> builder (VG.unsafeHead xs) <>
1599+ VG.foldr go (B.char7 ']') (VG.unsafeTail xs)
1600+ where go v b = B.char7 ',' <> builder v <> b
1875{-# INLINE encodeVector #-}
1601{-# INLINE encodeVector #-}
1876
1602
1877vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value
1603vectorToJSON :: (VG.Vector v a, ToJSON a) => v a -> Value
@@ -1922,21 +1648,20 @@ instance (ToJSON a) => ToJSON (HashSet.HashSet a) where
1922
1648
1923instance ToJSONKey k => ToJSON1 (H.HashMap k) where
1649instance ToJSONKey k => ToJSON1 (H.HashMap k) where
1924 liftToJSON g _ = case toJSONKey of
1650 liftToJSON g _ = case toJSONKey of
1925− ToJSONKeyText f _ -> Object . mapKeyVal f g
1651+ ToJSONKeyText (f,_) -> Object . mapKeyVal f g
1926− ToJSONKeyValue f _ -> Array . V.fromList . map (toJSONPair f g) . H.toList
1652+ ToJSONKeyValue (f,_) -> Array . V.fromList . map (toJSONPair f g) . H.toList
1927 {-# INLINE liftToJSON #-}
1653 {-# INLINE liftToJSON #-}
1928
1654
1929 -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> H.HashMap k a -> Encoding
1655 -- liftToEncoding :: forall a. (a -> Encoding) -> ([a] -> Encoding) -> H.HashMap k a -> Encoding
1930 liftToEncoding g _ = case toJSONKey of
1656 liftToEncoding g _ = case toJSONKey of
1931− ToJSONKeyText _ f -> dict f g H.foldrWithKey
1657+ ToJSONKeyText (_,f) -> dict f g H.foldrWithKey
1932− ToJSONKeyValue _ f -> listEncoding (pairEncoding f) . H.toList
1658+ ToJSONKeyValue (_,f) -> listEncoding (pairEncoding f) . H.toList
1933 where
1659 where
1934− pairEncoding f (a, b) = E.list id [f a, g b]
1660+ -- pairEncoding :: (k -> Encoding) -> (k, a) -> Encoding
1661+ pairEncoding f (a, b) = tuple $ f a >*< g b
1935 {-# INLINE liftToEncoding #-}
1662 {-# INLINE liftToEncoding #-}
1936
1663
1937instance (ToJSON v, ToJSONKey k) => ToJSON (H.HashMap k v) where
1664instance (ToJSON v, ToJSONKey k) => ToJSON (H.HashMap k v) where
1938− {-# SPECIALIZE instance ToJSON Object #-}
1939−
1940 toJSON = toJSON1
1665 toJSON = toJSON1
1941 {-# INLINE toJSON #-}
1666 {-# INLINE toJSON #-}
1942
1667
@@ -1951,7 +1676,7 @@ instance ToJSON Value where
1951 toJSON a = a
1676 toJSON a = a
1952 {-# INLINE toJSON #-}
1677 {-# INLINE toJSON #-}
1953
1678
1954− toEncoding = E.value
1679+ toEncoding = Encoding . EB.encodeToBuilder
1955 {-# INLINE toEncoding #-}
1680 {-# INLINE toEncoding #-}
1956
1681
1957instance ToJSON DotNetTime where
1682instance ToJSON DotNetTime where
@@ -1963,189 +1688,69 @@ dotNetTime :: DotNetTime -> String
1963dotNetTime (DotNetTime t) = secs ++ formatMillis t ++ ")/"
1688dotNetTime (DotNetTime t) = secs ++ formatMillis t ++ ")/"
1964 where secs = formatTime defaultTimeLocale "/Date(%s" t
1689 where secs = formatTime defaultTimeLocale "/Date(%s" t
1965
1690
1966−formatMillis :: (FormatTime t) => t -> String
1967−formatMillis = take 3 . formatTime defaultTimeLocale "%q"
1968−
1969−-------------------------------------------------------------------------------
1970−-- primitive
1971−-------------------------------------------------------------------------------
1972−
1973−instance ToJSON a => ToJSON (PM.Array a) where
1974− -- note: we could do better than this if vector exposed the data
1975− -- constructor in Data.Vector.
1976− toJSON = toJSON . Exts.toList
1977− toEncoding = toEncoding . Exts.toList
1978−
1979−instance ToJSON a => ToJSON (PM.SmallArray a) where
1980− toJSON = toJSON . Exts.toList
1981− toEncoding = toEncoding . Exts.toList
1982−
1983−#if (MIN_VERSION_primitive(0,6,4))
1984−instance (PM.Prim a,ToJSON a) => ToJSON (PM.PrimArray a) where
1985− toJSON = toJSON . Exts.toList
1986− toEncoding = toEncoding . Exts.toList
1987−
1988−#if !MIN_VERSION_primitive(0,7,0)
1989−instance (PM.PrimUnlifted a,ToJSON a) => ToJSON (PM.UnliftedArray a) where
1990− toJSON = toJSON . Exts.toList
1991− toEncoding = toEncoding . Exts.toList
1992−#endif
1993−#endif
1994−
1995-------------------------------------------------------------------------------
1691-------------------------------------------------------------------------------
1996-- time
1692-- time
1997-------------------------------------------------------------------------------
1693-------------------------------------------------------------------------------
1998
1694
1999instance ToJSON Day where
1695instance ToJSON Day where
2000− toJSON = stringEncoding . E.day
1696+ toJSON = stringEncoding
2001− toEncoding = E.day
1697+ toEncoding z = Encoding (EB.quote $ EB.day z)
2002−
2003−instance ToJSONKey Day where
2004− toJSONKey = toJSONKeyTextEnc E.day
2005
1698
2006
1699
2007instance ToJSON TimeOfDay where
1700instance ToJSON TimeOfDay where
2008− toJSON = stringEncoding . E.timeOfDay
1701+ toJSON = stringEncoding
2009− toEncoding = E.timeOfDay
1702+ toEncoding z = Encoding (EB.quote $ EB.timeOfDay z)
2010−
2011−instance ToJSONKey TimeOfDay where
2012− toJSONKey = toJSONKeyTextEnc E.timeOfDay
2013
1703
2014
1704
2015instance ToJSON LocalTime where
1705instance ToJSON LocalTime where
2016− toJSON = stringEncoding . E.localTime
1706+ toJSON = stringEncoding
2017− toEncoding = E.localTime
1707+ toEncoding z = Encoding (EB.quote $ EB.localTime z)
2018−
2019−instance ToJSONKey LocalTime where
2020− toJSONKey = toJSONKeyTextEnc E.localTime
2021−
2022
1708
2023instance ToJSON ZonedTime where
1709instance ToJSON ZonedTime where
2024− toJSON = stringEncoding . E.zonedTime
1710+ toJSON = stringEncoding
2025− toEncoding = E.zonedTime
2026
1711
2027−instance ToJSONKey ZonedTime where
1712+ toEncoding z = Encoding (EB.quote $ EB.zonedTime z)
2028− toJSONKey = toJSONKeyTextEnc E.zonedTime
2029
1713
1714+formatMillis :: (FormatTime t) => t -> String
1715+formatMillis = take 3 . formatTime defaultTimeLocale "%q"
2030
1716
2031instance ToJSON UTCTime where
1717instance ToJSON UTCTime where
2032− toJSON = stringEncoding . E.utcTime
1718+ toJSON = stringEncoding
2033− toEncoding = E.utcTime
2034
1719
2035−instance ToJSONKey UTCTime where
1720+ toEncoding t = Encoding (EB.quote $ EB.utcTime t)
2036− toJSONKey = toJSONKeyTextEnc E.utcTime
2037
1721
2038-- | Encode something t a JSON string.
1722-- | Encode something t a JSON string.
2039−stringEncoding :: Encoding' Text -> Value
1723+--
1724+-- TODO: remove me, this is a hack
1725+stringEncoding :: (ToJSON a) => a -> Value
2040stringEncoding = String
1726stringEncoding = String
2041 . T.dropAround (== '"')
1727 . T.dropAround (== '"')
2042 . T.decodeLatin1
1728 . T.decodeLatin1
2043 . L.toStrict
1729 . L.toStrict
2044− . E.encodingToLazyByteString
1730+ . B.toLazyByteString
1731+ . fromEncoding
1732+ . toEncoding
2045{-# INLINE stringEncoding #-}
1733{-# INLINE stringEncoding #-}
2046
1734
2047−
2048instance ToJSON NominalDiffTime where
1735instance ToJSON NominalDiffTime where
2049 toJSON = Number . realToFrac
1736 toJSON = Number . realToFrac
2050 {-# INLINE toJSON #-}
1737 {-# INLINE toJSON #-}
2051
1738
2052− toEncoding = E.scientific . realToFrac
1739+ toEncoding = Encoding . EB.number . realToFrac
2053 {-# INLINE toEncoding #-}
1740 {-# INLINE toEncoding #-}
2054
1741
2055−
2056−instance ToJSON DiffTime where
2057− toJSON = Number . realToFrac
2058− {-# INLINE toJSON #-}
2059−
2060− toEncoding = E.scientific . realToFrac
2061− {-# INLINE toEncoding #-}
2062−
2063−-- | Encoded as number
2064−instance ToJSON SystemTime where
2065− toJSON (MkSystemTime secs nsecs) =
2066− toJSON (fromIntegral secs + fromIntegral nsecs / 1000000000 :: Nano)
2067− toEncoding (MkSystemTime secs nsecs) =
2068− toEncoding (fromIntegral secs + fromIntegral nsecs / 1000000000 :: Nano)
2069−
2070−instance ToJSON CalendarDiffTime where
2071− toJSON (CalendarDiffTime m nt) = object
2072− [ "months" .= m
2073− , "time" .= nt
2074− ]
2075− toEncoding (CalendarDiffTime m nt) = E.pairs
2076− ("months" .= m <> "time" .= nt)
2077−
2078−instance ToJSON CalendarDiffDays where
2079− toJSON (CalendarDiffDays m d) = object
2080− [ "months" .= m
2081− , "days" .= d
2082− ]
2083− toEncoding (CalendarDiffDays m d) = E.pairs
2084− ("months" .= m <> "days" .= d)
2085−
2086−instance ToJSON DayOfWeek where
2087− toJSON Monday = "monday"
2088− toJSON Tuesday = "tuesday"
2089− toJSON Wednesday = "wednesday"
2090− toJSON Thursday = "thursday"
2091− toJSON Friday = "friday"
2092− toJSON Saturday = "saturday"
2093− toJSON Sunday = "sunday"
2094−
2095−toEncodingDayOfWeek :: DayOfWeek -> E.Encoding' Text
2096−toEncodingDayOfWeek Monday = E.unsafeToEncoding "\"monday\""
2097−toEncodingDayOfWeek Tuesday = E.unsafeToEncoding "\"tuesday\""
2098−toEncodingDayOfWeek Wednesday = E.unsafeToEncoding "\"wednesday\""
2099−toEncodingDayOfWeek Thursday = E.unsafeToEncoding "\"thursday\""
2100−toEncodingDayOfWeek Friday = E.unsafeToEncoding "\"friday\""
2101−toEncodingDayOfWeek Saturday = E.unsafeToEncoding "\"saturday\""
2102−toEncodingDayOfWeek Sunday = E.unsafeToEncoding "\"sunday\""
2103−
2104−instance ToJSONKey DayOfWeek where
2105− toJSONKey = toJSONKeyTextEnc toEncodingDayOfWeek
2106−
2107-------------------------------------------------------------------------------
1742-------------------------------------------------------------------------------
2108-- base Monoid/Semigroup
1743-- base Monoid/Semigroup
2109-------------------------------------------------------------------------------
1744-------------------------------------------------------------------------------
2110
1745
2111−instance ToJSON1 Monoid.Dual where
1746+instance ToJSON1 Dual where
2112− liftToJSON t _ = t . Monoid.getDual
1747+ liftToJSON t _ = t . getDual
2113− {-# INLINE liftToJSON #-}
2114−
2115− liftToEncoding t _ = t . Monoid.getDual
2116− {-# INLINE liftToEncoding #-}
2117−
2118−instance ToJSON a => ToJSON (Monoid.Dual a) where
2119− toJSON = toJSON1
2120− {-# INLINE toJSON #-}
2121−
2122− toEncoding = toEncoding1
2123− {-# INLINE toEncoding #-}
2124−
2125−
2126−instance ToJSON1 Monoid.First where
2127− liftToJSON t to' = liftToJSON t to' . Monoid.getFirst
2128− {-# INLINE liftToJSON #-}
2129−
2130− liftToEncoding t to' = liftToEncoding t to' . Monoid.getFirst
2131− {-# INLINE liftToEncoding #-}
2132−
2133−instance ToJSON a => ToJSON (Monoid.First a) where
2134− toJSON = toJSON1
2135− {-# INLINE toJSON #-}
2136−
2137− toEncoding = toEncoding1
2138− {-# INLINE toEncoding #-}
2139−
2140−
2141−instance ToJSON1 Monoid.Last where
2142− liftToJSON t to' = liftToJSON t to' . Monoid.getLast
2143 {-# INLINE liftToJSON #-}
1748 {-# INLINE liftToJSON #-}
2144
1749
2145− liftToEncoding t to' = liftToEncoding t to' . Monoid.getLast
1750+ liftToEncoding t _ = t . getDual
2146 {-# INLINE liftToEncoding #-}
1751 {-# INLINE liftToEncoding #-}
2147
1752
2148−instance ToJSON a => ToJSON (Monoid.Last a) where
1753+instance ToJSON a => ToJSON (Dual a) where
2149 toJSON = toJSON1
1754 toJSON = toJSON1
2150 {-# INLINE toJSON #-}
1755 {-# INLINE toJSON #-}
2151
1756
@@ -2153,14 +1758,14 @@ instance ToJSON a => ToJSON (Monoid.Last a) where
2153 {-# INLINE toEncoding #-}
1758 {-# INLINE toEncoding #-}
2154
1759
2155
1760
2156−instance ToJSON1 Semigroup.Min where
1761+instance ToJSON1 First where
2157− liftToJSON t _ (Semigroup.Min x) = t x
1762+ liftToJSON t to' = liftToJSON t to' . getFirst
2158 {-# INLINE liftToJSON #-}
1763 {-# INLINE liftToJSON #-}
2159
1764
2160− liftToEncoding t _ (Semigroup.Min x) = t x
1765+ liftToEncoding t to' = liftToEncoding t to' . getFirst
2161 {-# INLINE liftToEncoding #-}
1766 {-# INLINE liftToEncoding #-}
2162
1767
2163−instance ToJSON a => ToJSON (Semigroup.Min a) where
1768+instance ToJSON a => ToJSON (First a) where
2164 toJSON = toJSON1
1769 toJSON = toJSON1
2165 {-# INLINE toJSON #-}
1770 {-# INLINE toJSON #-}
2166
1771
@@ -2168,73 +1773,14 @@ instance ToJSON a => ToJSON (Semigroup.Min a) where
2168 {-# INLINE toEncoding #-}
1773 {-# INLINE toEncoding #-}
2169
1774
2170
1775
2171−instance ToJSON1 Semigroup.Max where
1776+instance ToJSON1 Last where
2172− liftToJSON t _ (Semigroup.Max x) = t x
1777+ liftToJSON t to' = liftToJSON t to' . getLast
2173 {-# INLINE liftToJSON #-}
1778 {-# INLINE liftToJSON #-}
2174
1779
2175− liftToEncoding t _ (Semigroup.Max x) = t x
1780+ liftToEncoding t to' = liftToEncoding t to' . getLast
2176 {-# INLINE liftToEncoding #-}
1781 {-# INLINE liftToEncoding #-}
2177
1782
2178−instance ToJSON a => ToJSON (Semigroup.Max a) where
1783+instance ToJSON a => ToJSON (Last a) where
2179− toJSON = toJSON1
2180− {-# INLINE toJSON #-}
2181−
2182− toEncoding = toEncoding1
2183− {-# INLINE toEncoding #-}
2184−
2185−instance ToJSON1 Semigroup.First where
2186− liftToJSON t _ (Semigroup.First x) = t x
2187− {-# INLINE liftToJSON #-}
2188−
2189− liftToEncoding t _ (Semigroup.First x) = t x
2190− {-# INLINE liftToEncoding #-}
2191−
2192−instance ToJSON a => ToJSON (Semigroup.First a) where
2193− toJSON = toJSON1
2194− {-# INLINE toJSON #-}
2195−
2196− toEncoding = toEncoding1
2197− {-# INLINE toEncoding #-}
2198−
2199−
2200−instance ToJSON1 Semigroup.Last where
2201− liftToJSON t _ (Semigroup.Last x) = t x
2202− {-# INLINE liftToJSON #-}
2203−
2204− liftToEncoding t _ (Semigroup.Last x) = t x
2205− {-# INLINE liftToEncoding #-}
2206−
2207−instance ToJSON a => ToJSON (Semigroup.Last a) where
2208− toJSON = toJSON1
2209− {-# INLINE toJSON #-}
2210−
2211− toEncoding = toEncoding1
2212− {-# INLINE toEncoding #-}
2213−
2214−
2215−instance ToJSON1 Semigroup.WrappedMonoid where
2216− liftToJSON t _ (Semigroup.WrapMonoid x) = t x
2217− {-# INLINE liftToJSON #-}
2218−
2219− liftToEncoding t _ (Semigroup.WrapMonoid x) = t x
2220− {-# INLINE liftToEncoding #-}
2221−
2222−instance ToJSON a => ToJSON (Semigroup.WrappedMonoid a) where
2223− toJSON = toJSON1
2224− {-# INLINE toJSON #-}
2225−
2226− toEncoding = toEncoding1
2227− {-# INLINE toEncoding #-}
2228−
2229−
2230−instance ToJSON1 Semigroup.Option where
2231− liftToJSON t to' = liftToJSON t to' . Semigroup.getOption
2232− {-# INLINE liftToJSON #-}
2233−
2234− liftToEncoding t to' = liftToEncoding t to' . Semigroup.getOption
2235− {-# INLINE liftToEncoding #-}
2236−
2237−instance ToJSON a => ToJSON (Semigroup.Option a) where
2238 toJSON = toJSON1
1784 toJSON = toJSON1
2239 {-# INLINE toJSON #-}
1785 {-# INLINE toJSON #-}
2240
1786
@@ -2245,28 +1791,14 @@ instance ToJSON a => ToJSON (Semigroup.Option a) where
2245-- tagged
1791-- tagged
2246-------------------------------------------------------------------------------
1792-------------------------------------------------------------------------------
2247
1793
2248−instance ToJSON1 Proxy where
2249− liftToJSON _ _ _ = Null
2250− {-# INLINE liftToJSON #-}
2251−
2252− liftToEncoding _ _ _ = E.null_
2253− {-# INLINE liftToEncoding #-}
2254−
2255instance ToJSON (Proxy a) where
1794instance ToJSON (Proxy a) where
2256 toJSON _ = Null
1795 toJSON _ = Null
2257 {-# INLINE toJSON #-}
1796 {-# INLINE toJSON #-}
2258
1797
2259− toEncoding _ = E.null_
1798+ toEncoding _ = Encoding EB.null_
2260 {-# INLINE toEncoding #-}
1799 {-# INLINE toEncoding #-}
2261
1800
2262
1801
2263−instance ToJSON2 Tagged where
2264− liftToJSON2 _ _ t _ (Tagged x) = t x
2265− {-# INLINE liftToJSON2 #-}
2266−
2267− liftToEncoding2 _ _ t _ (Tagged x) = t x
2268− {-# INLINE liftToEncoding2 #-}
2269−
2270instance ToJSON1 (Tagged a) where
1802instance ToJSON1 (Tagged a) where
2271 liftToJSON t _ (Tagged x) = t x
1803 liftToJSON t _ (Tagged x) = t x
2272 {-# INLINE liftToJSON #-}
1804 {-# INLINE liftToJSON #-}
@@ -2281,6 +1813,7 @@ instance ToJSON b => ToJSON (Tagged a b) where
2281 toEncoding = toEncoding1
1813 toEncoding = toEncoding1
2282 {-# INLINE toEncoding #-}
1814 {-# INLINE toEncoding #-}
2283
1815
1816+
2284instance ToJSONKey b => ToJSONKey (Tagged a b) where
1817instance ToJSONKey b => ToJSONKey (Tagged a b) where
2285 toJSONKey = contramapToJSONKeyFunction unTagged toJSONKey
1818 toJSONKey = contramapToJSONKeyFunction unTagged toJSONKey
2286 toJSONKeyList = contramapToJSONKeyFunction (fmap unTagged) toJSONKeyList
1819 toJSONKeyList = contramapToJSONKeyFunction (fmap unTagged) toJSONKeyList
@@ -2289,22 +1822,41 @@ instance ToJSONKey b => ToJSONKey (Tagged a b) where
2289-- Instances for converting t map keys
1822-- Instances for converting t map keys
2290-------------------------------------------------------------------------------
1823-------------------------------------------------------------------------------
2291
1824
1825+instance ToJSONKey Text where
1826+ toJSONKey = ToJSONKeyText (id,toEncoding)
1827+
1828+
1829+instance ToJSONKey Bool where
1830+ toJSONKey = ToJSONKeyText
1831+ ( (\x -> if x then "true" else "false")
1832+ , (\x -> Encoding $ if x then "\"true\"" else "\"false\"")
1833+ )
1834+
1835+instance ToJSONKey Int where
1836+ toJSONKey = ToJSONKeyText
1837+ ( LT.toStrict . LTB.toLazyText . LTBI.decimal
1838+ , \x -> Encoding $ B.char7 '"' <> fromEncoding (toEncoding x) <> B.char7 '"'
1839+ )
1840+
2292instance (ToJSON a, ToJSON b) => ToJSONKey (a,b)
1841instance (ToJSON a, ToJSON b) => ToJSONKey (a,b)
2293instance (ToJSON a, ToJSON b, ToJSON c) => ToJSONKey (a,b,c)
1842instance (ToJSON a, ToJSON b, ToJSON c) => ToJSONKey (a,b,c)
2294instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSONKey (a,b,c,d)
1843instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSONKey (a,b,c,d)
2295
1844
2296instance ToJSONKey Char where
1845instance ToJSONKey Char where
2297− toJSONKey = ToJSONKeyText T.singleton (E.string . (:[]))
1846+ toJSONKey = ToJSONKeyText (T.singleton, toEncoding)
2298− toJSONKeyList = toJSONKeyText T.pack
1847+ toJSONKeyList = ToJSONKeyText (T.pack, toEncoding . T.pack)
2299
1848
2300instance (ToJSONKey a, ToJSON a) => ToJSONKey [a] where
1849instance (ToJSONKey a, ToJSON a) => ToJSONKey [a] where
2301 toJSONKey = toJSONKeyList
1850 toJSONKey = toJSONKeyList
2302
1851
1852+instance (ToJSONKey a, ToJSON a) => ToJSONKey (Identity a) where
1853+ toJSONKey = contramapToJSONKeyFunction runIdentity toJSONKey
1854+
2303-------------------------------------------------------------------------------
1855-------------------------------------------------------------------------------
2304−-- Tuple instances
1856+-- Tuple instances, see tuple-instances-to.hs
2305-------------------------------------------------------------------------------
1857-------------------------------------------------------------------------------
2306
1858
2307−instance ToJSON2 (,) where
1859+instance ToJSON2 ((,) ) where
2308 liftToJSON2 toA _ toB _ (a, b) = Array $ V.create $ do
1860 liftToJSON2 toA _ toB _ (a, b) = Array $ V.create $ do
2309 mv <- VM.unsafeNew 2
1861 mv <- VM.unsafeNew 2
2310 VM.unsafeWrite mv 0 (toA a)
1862 VM.unsafeWrite mv 0 (toA a)
@@ -2312,7 +1864,9 @@ instance ToJSON2 (,) where
2312 return mv
1864 return mv
2313 {-# INLINE liftToJSON2 #-}
1865 {-# INLINE liftToJSON2 #-}
2314
1866
2315− liftToEncoding2 toA _ toB _ (a, b) = E.list id [toA a, toB b]
1867+ liftToEncoding2 toA _ toB _ (a, b) = tuple $
1868+ toA a >*<
1869+ toB b
2316 {-# INLINE liftToEncoding2 #-}
1870 {-# INLINE liftToEncoding2 #-}
2317
1871
2318instance (ToJSON a) => ToJSON1 ((,) a) where
1872instance (ToJSON a) => ToJSON1 ((,) a) where
@@ -2336,11 +1890,10 @@ instance (ToJSON a) => ToJSON2 ((,,) a) where
2336 return mv
1890 return mv
2337 {-# INLINE liftToJSON2 #-}
1891 {-# INLINE liftToJSON2 #-}
2338
1892
2339− liftToEncoding2 toB _ toC _ (a, b, c) = E.list id
1893+ liftToEncoding2 toB _ toC _ (a, b, c) = tuple $
2340− [ toEncoding a
1894+ toEncoding a >*<
2341− , toB b
1895+ toB b >*<
2342− , toC c
1896+ toC c
2343− ]
2344 {-# INLINE liftToEncoding2 #-}
1897 {-# INLINE liftToEncoding2 #-}
2345
1898
2346instance (ToJSON a, ToJSON b) => ToJSON1 ((,,) a b) where
1899instance (ToJSON a, ToJSON b) => ToJSON1 ((,,) a b) where
@@ -2365,12 +1918,11 @@ instance (ToJSON a, ToJSON b) => ToJSON2 ((,,,) a b) where
2365 return mv
1918 return mv
2366 {-# INLINE liftToJSON2 #-}
1919 {-# INLINE liftToJSON2 #-}
2367
1920
2368− liftToEncoding2 toC _ toD _ (a, b, c, d) = E.list id
1921+ liftToEncoding2 toC _ toD _ (a, b, c, d) = tuple $
2369− [ toEncoding a
1922+ toEncoding a >*<
2370− , toEncoding b
1923+ toEncoding b >*<
2371− , toC c
1924+ toC c >*<
2372− , toD d
1925+ toD d
2373− ]
2374 {-# INLINE liftToEncoding2 #-}
1926 {-# INLINE liftToEncoding2 #-}
2375
1927
2376instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON1 ((,,,) a b c) where
1928instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON1 ((,,,) a b c) where
@@ -2396,13 +1948,12 @@ instance (ToJSON a, ToJSON b, ToJSON c) => ToJSON2 ((,,,,) a b c) where
2396 return mv
1948 return mv
2397 {-# INLINE liftToJSON2 #-}
1949 {-# INLINE liftToJSON2 #-}
2398
1950
2399− liftToEncoding2 toD _ toE _ (a, b, c, d, e) = E.list id
1951+ liftToEncoding2 toD _ toE _ (a, b, c, d, e) = tuple $
2400− [ toEncoding a
1952+ toEncoding a >*<
2401− , toEncoding b
1953+ toEncoding b >*<
2402− , toEncoding c
1954+ toEncoding c >*<
2403− , toD d
1955+ toD d >*<
2404− , toE e
1956+ toE e
2405− ]
2406 {-# INLINE liftToEncoding2 #-}
1957 {-# INLINE liftToEncoding2 #-}
2407
1958
2408instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON1 ((,,,,) a b c d) where
1959instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON1 ((,,,,) a b c d) where
@@ -2429,14 +1980,13 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d) => ToJSON2 ((,,,,,) a b c d) w
2429 return mv
1980 return mv
2430 {-# INLINE liftToJSON2 #-}
1981 {-# INLINE liftToJSON2 #-}
2431
1982
2432− liftToEncoding2 toE _ toF _ (a, b, c, d, e, f) = E.list id
1983+ liftToEncoding2 toE _ toF _ (a, b, c, d, e, f) = tuple $
2433− [ toEncoding a
1984+ toEncoding a >*<
2434− , toEncoding b
1985+ toEncoding b >*<
2435− , toEncoding c
1986+ toEncoding c >*<
2436− , toEncoding d
1987+ toEncoding d >*<
2437− , toE e
1988+ toE e >*<
2438− , toF f
1989+ toF f
2439− ]
2440 {-# INLINE liftToEncoding2 #-}
1990 {-# INLINE liftToEncoding2 #-}
2441
1991
2442instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON1 ((,,,,,) a b c d e) where
1992instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON1 ((,,,,,) a b c d e) where
@@ -2464,15 +2014,14 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e) => ToJSON2 ((,,,,,,)
2464 return mv
2014 return mv
2465 {-# INLINE liftToJSON2 #-}
2015 {-# INLINE liftToJSON2 #-}
2466
2016
2467− liftToEncoding2 toF _ toG _ (a, b, c, d, e, f, g) = E.list id
2017+ liftToEncoding2 toF _ toG _ (a, b, c, d, e, f, g) = tuple $
2468− [ toEncoding a
2018+ toEncoding a >*<
2469− , toEncoding b
2019+ toEncoding b >*<
2470− , toEncoding c
2020+ toEncoding c >*<
2471− , toEncoding d
2021+ toEncoding d >*<
2472− , toEncoding e
2022+ toEncoding e >*<
2473− , toF f
2023+ toF f >*<
2474− , toG g
2024+ toG g
2475− ]
2476 {-# INLINE liftToEncoding2 #-}
2025 {-# INLINE liftToEncoding2 #-}
2477
2026
2478instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON1 ((,,,,,,) a b c d e f) where
2027instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON1 ((,,,,,,) a b c d e f) where
@@ -2501,16 +2050,15 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f) => ToJSON2
2501 return mv
2050 return mv
2502 {-# INLINE liftToJSON2 #-}
2051 {-# INLINE liftToJSON2 #-}
2503
2052
2504− liftToEncoding2 toG _ toH _ (a, b, c, d, e, f, g, h) = E.list id
2053+ liftToEncoding2 toG _ toH _ (a, b, c, d, e, f, g, h) = tuple $
2505− [ toEncoding a
2054+ toEncoding a >*<
2506− , toEncoding b
2055+ toEncoding b >*<
2507− , toEncoding c
2056+ toEncoding c >*<
2508− , toEncoding d
2057+ toEncoding d >*<
2509− , toEncoding e
2058+ toEncoding e >*<
2510− , toEncoding f
2059+ toEncoding f >*<
2511− , toG g
2060+ toG g >*<
2512− , toH h
2061+ toH h
2513− ]
2514 {-# INLINE liftToEncoding2 #-}
2062 {-# INLINE liftToEncoding2 #-}
2515
2063
2516instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON1 ((,,,,,,,) a b c d e f g) where
2064instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g) => ToJSON1 ((,,,,,,,) a b c d e f g) where
@@ -2540,17 +2088,16 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g)
2540 return mv
2088 return mv
2541 {-# INLINE liftToJSON2 #-}
2089 {-# INLINE liftToJSON2 #-}
2542
2090
2543− liftToEncoding2 toH _ toI _ (a, b, c, d, e, f, g, h, i) = E.list id
2091+ liftToEncoding2 toH _ toI _ (a, b, c, d, e, f, g, h, i) = tuple $
2544− [ toEncoding a
2092+ toEncoding a >*<
2545− , toEncoding b
2093+ toEncoding b >*<
2546− , toEncoding c
2094+ toEncoding c >*<
2547− , toEncoding d
2095+ toEncoding d >*<
2548− , toEncoding e
2096+ toEncoding e >*<
2549− , toEncoding f
2097+ toEncoding f >*<
2550− , toEncoding g
2098+ toEncoding g >*<
2551− , toH h
2099+ toH h >*<
2552− , toI i
2100+ toI i
2553− ]
2554 {-# INLINE liftToEncoding2 #-}
2101 {-# INLINE liftToEncoding2 #-}
2555
2102
2556instance (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
2103instance (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
@@ -2581,18 +2128,17 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2581 return mv
2128 return mv
2582 {-# INLINE liftToJSON2 #-}
2129 {-# INLINE liftToJSON2 #-}
2583
2130
2584− liftToEncoding2 toI _ toJ _ (a, b, c, d, e, f, g, h, i, j) = E.list id
2131+ liftToEncoding2 toI _ toJ _ (a, b, c, d, e, f, g, h, i, j) = tuple $
2585− [ toEncoding a
2132+ toEncoding a >*<
2586− , toEncoding b
2133+ toEncoding b >*<
2587− , toEncoding c
2134+ toEncoding c >*<
2588− , toEncoding d
2135+ toEncoding d >*<
2589− , toEncoding e
2136+ toEncoding e >*<
2590− , toEncoding f
2137+ toEncoding f >*<
2591− , toEncoding g
2138+ toEncoding g >*<
2592− , toEncoding h
2139+ toEncoding h >*<
2593− , toI i
2140+ toI i >*<
2594− , toJ j
2141+ toJ j
2595− ]
2596 {-# INLINE liftToEncoding2 #-}
2142 {-# INLINE liftToEncoding2 #-}
2597
2143
2598instance (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
2144instance (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
@@ -2624,19 +2170,18 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2624 return mv
2170 return mv
2625 {-# INLINE liftToJSON2 #-}
2171 {-# INLINE liftToJSON2 #-}
2626
2172
2627− liftToEncoding2 toJ _ toK _ (a, b, c, d, e, f, g, h, i, j, k) = E.list id
2173+ liftToEncoding2 toJ _ toK _ (a, b, c, d, e, f, g, h, i, j, k) = tuple $
2628− [ toEncoding a
2174+ toEncoding a >*<
2629− , toEncoding b
2175+ toEncoding b >*<
2630− , toEncoding c
2176+ toEncoding c >*<
2631− , toEncoding d
2177+ toEncoding d >*<
2632− , toEncoding e
2178+ toEncoding e >*<
2633− , toEncoding f
2179+ toEncoding f >*<
2634− , toEncoding g
2180+ toEncoding g >*<
2635− , toEncoding h
2181+ toEncoding h >*<
2636− , toEncoding i
2182+ toEncoding i >*<
2637− , toJ j
2183+ toJ j >*<
2638− , toK k
2184+ toK k
2639− ]
2640 {-# INLINE liftToEncoding2 #-}
2185 {-# INLINE liftToEncoding2 #-}
2641
2186
2642instance (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
2187instance (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
@@ -2669,20 +2214,19 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2669 return mv
2214 return mv
2670 {-# INLINE liftToJSON2 #-}
2215 {-# INLINE liftToJSON2 #-}
2671
2216
2672− liftToEncoding2 toK _ toL _ (a, b, c, d, e, f, g, h, i, j, k, l) = E.list id
2217+ liftToEncoding2 toK _ toL _ (a, b, c, d, e, f, g, h, i, j, k, l) = tuple $
2673− [ toEncoding a
2218+ toEncoding a >*<
2674− , toEncoding b
2219+ toEncoding b >*<
2675− , toEncoding c
2220+ toEncoding c >*<
2676− , toEncoding d
2221+ toEncoding d >*<
2677− , toEncoding e
2222+ toEncoding e >*<
2678− , toEncoding f
2223+ toEncoding f >*<
2679− , toEncoding g
2224+ toEncoding g >*<
2680− , toEncoding h
2225+ toEncoding h >*<
2681− , toEncoding i
2226+ toEncoding i >*<
2682− , toEncoding j
2227+ toEncoding j >*<
2683− , toK k
2228+ toK k >*<
2684− , toL l
2229+ toL l
2685− ]
2686 {-# INLINE liftToEncoding2 #-}
2230 {-# INLINE liftToEncoding2 #-}
2687
2231
2688instance (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
2232instance (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
@@ -2716,21 +2260,20 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2716 return mv
2260 return mv
2717 {-# INLINE liftToJSON2 #-}
2261 {-# INLINE liftToJSON2 #-}
2718
2262
2719− liftToEncoding2 toL _ toM _ (a, b, c, d, e, f, g, h, i, j, k, l, m) = E.list id
2263+ liftToEncoding2 toL _ toM _ (a, b, c, d, e, f, g, h, i, j, k, l, m) = tuple $
2720− [ toEncoding a
2264+ toEncoding a >*<
2721− , toEncoding b
2265+ toEncoding b >*<
2722− , toEncoding c
2266+ toEncoding c >*<
2723− , toEncoding d
2267+ toEncoding d >*<
2724− , toEncoding e
2268+ toEncoding e >*<
2725− , toEncoding f
2269+ toEncoding f >*<
2726− , toEncoding g
2270+ toEncoding g >*<
2727− , toEncoding h
2271+ toEncoding h >*<
2728− , toEncoding i
2272+ toEncoding i >*<
2729− , toEncoding j
2273+ toEncoding j >*<
2730− , toEncoding k
2274+ toEncoding k >*<
2731− , toL l
2275+ toL l >*<
2732− , toM m
2276+ toM m
2733− ]
2734 {-# INLINE liftToEncoding2 #-}
2277 {-# INLINE liftToEncoding2 #-}
2735
2278
2736instance (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
2279instance (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
@@ -2765,22 +2308,21 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2765 return mv
2308 return mv
2766 {-# INLINE liftToJSON2 #-}
2309 {-# INLINE liftToJSON2 #-}
2767
2310
2768− liftToEncoding2 toM _ toN _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = E.list id
2311+ liftToEncoding2 toM _ toN _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n) = tuple $
2769− [ toEncoding a
2312+ toEncoding a >*<
2770− , toEncoding b
2313+ toEncoding b >*<
2771− , toEncoding c
2314+ toEncoding c >*<
2772− , toEncoding d
2315+ toEncoding d >*<
2773− , toEncoding e
2316+ toEncoding e >*<
2774− , toEncoding f
2317+ toEncoding f >*<
2775− , toEncoding g
2318+ toEncoding g >*<
2776− , toEncoding h
2319+ toEncoding h >*<
2777− , toEncoding i
2320+ toEncoding i >*<
2778− , toEncoding j
2321+ toEncoding j >*<
2779− , toEncoding k
2322+ toEncoding k >*<
2780− , toEncoding l
2323+ toEncoding l >*<
2781− , toM m
2324+ toM m >*<
2782− , toN n
2325+ toN n
2783− ]
2784 {-# INLINE liftToEncoding2 #-}
2326 {-# INLINE liftToEncoding2 #-}
2785
2327
2786instance (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
2328instance (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
@@ -2816,23 +2358,22 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2816 return mv
2358 return mv
2817 {-# INLINE liftToJSON2 #-}
2359 {-# INLINE liftToJSON2 #-}
2818
2360
2819− liftToEncoding2 toN _ toO _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = E.list id
2361+ liftToEncoding2 toN _ toO _ (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) = tuple $
2820− [ toEncoding a
2362+ toEncoding a >*<
2821− , toEncoding b
2363+ toEncoding b >*<
2822− , toEncoding c
2364+ toEncoding c >*<
2823− , toEncoding d
2365+ toEncoding d >*<
2824− , toEncoding e
2366+ toEncoding e >*<
2825− , toEncoding f
2367+ toEncoding f >*<
2826− , toEncoding g
2368+ toEncoding g >*<
2827− , toEncoding h
2369+ toEncoding h >*<
2828− , toEncoding i
2370+ toEncoding i >*<
2829− , toEncoding j
2371+ toEncoding j >*<
2830− , toEncoding k
2372+ toEncoding k >*<
2831− , toEncoding l
2373+ toEncoding l >*<
2832− , toEncoding m
2374+ toEncoding m >*<
2833− , toN n
2375+ toN n >*<
2834− , toO o
2376+ toO o
2835− ]
2836 {-# INLINE liftToEncoding2 #-}
2377 {-# INLINE liftToEncoding2 #-}
2837
2378
2838instance (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
2379instance (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
@@ -2846,27 +2387,3 @@ instance (ToJSON a, ToJSON b, ToJSON c, ToJSON d, ToJSON e, ToJSON f, ToJSON g,
2846 {-# INLINE toJSON #-}
2387 {-# INLINE toJSON #-}
2847 toEncoding = toEncoding2
2388 toEncoding = toEncoding2
2848 {-# INLINE toEncoding #-}
2389 {-# INLINE toEncoding #-}
2849−
2850−--------------------------------------------------------------------------------
2851−
2852−-- | Wrap a list of pairs as an object.
2853−class Monoid pairs => FromPairs enc pairs | enc -> pairs where
2854− fromPairs :: pairs -> enc
2855−
2856−instance (a ~ Value) => FromPairs (Encoding' a) Series where
2857− fromPairs = E.pairs
2858−
2859−instance FromPairs Value (DList Pair) where
2860− fromPairs = object . toList
2861−
2862−-- | Like 'KeyValue' but the value is already converted to JSON
2863−-- ('Value' or 'Encoding'), and the result actually represents lists of pairs
2864−-- so it can be readily concatenated.
2865−class Monoid kv => KeyValuePair v kv where
2866− pair :: String -> v -> kv
2867−
2868−instance (v ~ Value) => KeyValuePair v (DList Pair) where
2869− pair k v = DList.singleton (pack k .= v)
2870−
2871−instance (e ~ Encoding) => KeyValuePair e Series where
2872− pair = E.pairStr
Makefiledeleted−2
@@ -1,2 +0,0 @@
1−lint:
2− ./run-hlint.sh --cpp-include include/ --cpp-file travis/cabal_macros.h Data/ attoparsec-iso8601/ benchmarks/ examples/ ffi/ pure/ tests/
README.markdown+4−3
@@ -15,13 +15,14 @@ Master [git repository](http://github.com/bos/aeson):
15
15
16* `git clone git://github.com/bos/aeson.git`
16* `git clone git://github.com/bos/aeson.git`
17
17
18−See what's changed in recent (and upcoming) releases:
18+There's also a [Mercurial mirror](http://bitbucket.org/bos/aeson):
19
19
20−* https://github.com/bos/aeson/blob/master/changelog.md
20+* `hg clone http://bitbucket.org/bos/aeson`
21
21
22(You can create and contribute changes using either git or Mercurial.)
22(You can create and contribute changes using either git or Mercurial.)
23
23
24
24
25# Authors
25# Authors
26
26
27−This library was originally written by Bryan O'Sullivan.
27+This library is written and maintained by Bryan O'Sullivan,
28+<bos@serpentine.com>.
aeson.cabal+67−152
@@ -1,12 +1,12 @@
1name: aeson
1name: aeson
2−version: 1.4.6.0
2+version: 0.12.0.0
3license: BSD3
3license: BSD3
4license-file: LICENSE
4license-file: LICENSE
5category: Text, Web, JSON
5category: Text, Web, JSON
6copyright: (c) 2011-2016 Bryan O'Sullivan
6copyright: (c) 2011-2016 Bryan O'Sullivan
7 (c) 2011 MailRank, Inc.
7 (c) 2011 MailRank, Inc.
8author: Bryan O'Sullivan <bos@serpentine.com>
8author: Bryan O'Sullivan <bos@serpentine.com>
9−maintainer: Adam Bergmark <adam@bergmark.nl>
9+maintainer: Bryan O'Sullivan <bos@serpentine.com>
10stability: experimental
10stability: experimental
11tested-with: GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1
11tested-with: GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.3, GHC == 8.0.1
12synopsis: Fast JSON parsing and encoding
12synopsis: Fast JSON parsing and encoding
@@ -21,10 +21,23 @@ description:
21 To get started, see the documentation for the @Data.Aeson@ module
21 To get started, see the documentation for the @Data.Aeson@ module
22 below.
22 below.
23 .
23 .
24+ Parsing performance on a late 2013 MacBook Pro (2.6GHz Core i7),
25+ running 64-bit GHC 7.10.1, for mostly-English tweets from Twitter's
26+ JSON search API:
27+ .
28+ * 6.4 KB payloads, English: 7570 msg\/sec (47.6 MB\/sec)
29+ .
30+ * 14.6 KB payloads, Japanese: 3261 msg\/sec (46.6 MB\/sec)
31+ .
32+ Encoding performance on the same machine and data:
33+ .
34+ * 6.4 KB payloads, English: 22738 msg\/sec (142.9 MB\/sec)
35+ .
36+ * 14.6 KB payloads, Japanese: 15911 msg\/sec (227.4 MB\/sec)
37+ .
24 (A note on naming: in Greek mythology, Aeson was the father of Jason.)
38 (A note on naming: in Greek mythology, Aeson was the father of Jason.)
25
39
26extra-source-files:
40extra-source-files:
27− *.yaml
28 README.markdown
41 README.markdown
29 benchmarks/*.cabal
42 benchmarks/*.cabal
30 benchmarks/*.hs
43 benchmarks/*.hs
@@ -33,234 +46,136 @@ extra-source-files:
33 benchmarks/Makefile
46 benchmarks/Makefile
34 benchmarks/Typed/*.hs
47 benchmarks/Typed/*.hs
35 benchmarks/json-data/*.json
48 benchmarks/json-data/*.json
36− cbits/*.c
49+ include/overlapping-compat.h
37 changelog.md
50 changelog.md
38 examples/*.cabal
51 examples/*.cabal
39 examples/*.hs
52 examples/*.hs
40 examples/Twitter/*.hs
53 examples/Twitter/*.hs
41− ffi/Data/Aeson/Parser/*.hs
42 include/*.h
54 include/*.h
43− tests/JSONTestSuite/test_parsing/*.json
44− tests/JSONTestSuite/test_transform/*.json
45− tests/golden/*.expected
46− pure/Data/Aeson/Parser/*.hs
47
55
48flag developer
56flag developer
49 description: operate in developer mode
57 description: operate in developer mode
50 default: False
58 default: False
51 manual: True
59 manual: True
52
60
53−flag fast
54− description: compile without optimizations
55− default: False
56− manual: True
57−
58−flag bytestring-builder
59− description: Depend on the bytestring-builder package for backwards compatibility.
60− default: False
61− manual: False
62−
63−flag cffi
64− description: Controls whether to include c-ffi bits or pure haskell. Default to False for security.
65− default: False
66− manual: True
67−
68library
61library
69 default-language: Haskell2010
62 default-language: Haskell2010
70− hs-source-dirs: . attoparsec-iso8601/
71
63
72 exposed-modules:
64 exposed-modules:
73 Data.Aeson
65 Data.Aeson
66+ Data.Aeson.Encode
74 Data.Aeson.Encoding
67 Data.Aeson.Encoding
75− Data.Aeson.Parser
76− Data.Aeson.Text
77− Data.Aeson.Types
78− Data.Aeson.TH
79− Data.Aeson.QQ.Simple
80−
81 Data.Aeson.Encoding.Internal
68 Data.Aeson.Encoding.Internal
82 Data.Aeson.Internal
69 Data.Aeson.Internal
83 Data.Aeson.Internal.Time
70 Data.Aeson.Internal.Time
84− Data.Aeson.Parser.Internal
71+ Data.Aeson.Parser
85−
72+ Data.Aeson.Types
86− -- Deprecated modules
73+ Data.Aeson.TH
87− exposed-modules:
88− Data.Aeson.Encode
89
74
90 other-modules:
75 other-modules:
91− Data.Aeson.Encoding.Builder
76+ Data.Aeson.Encode.Builder
92− Data.Aeson.Internal.Functions
77+ Data.Aeson.Functions
93− Data.Aeson.Parser.Unescape
78+ Data.Aeson.Parser.Internal
94 Data.Aeson.Parser.Time
79 Data.Aeson.Parser.Time
95 Data.Aeson.Types.FromJSON
80 Data.Aeson.Types.FromJSON
96 Data.Aeson.Types.Generic
81 Data.Aeson.Types.Generic
97 Data.Aeson.Types.ToJSON
82 Data.Aeson.Types.ToJSON
98 Data.Aeson.Types.Class
83 Data.Aeson.Types.Class
99 Data.Aeson.Types.Internal
84 Data.Aeson.Types.Internal
100− Data.Attoparsec.Time
101− Data.Attoparsec.Time.Internal
102−
103− -- GHC bundled libs
104− build-depends:
105− base >= 4.7.0.0 && < 5,
106− bytestring >= 0.10.4.0 && < 0.11,
107− containers >= 0.5.5.1 && < 0.7,
108− deepseq >= 1.3.0.0 && < 1.5,
109− ghc-prim >= 0.2 && < 0.6,
110− template-haskell >= 2.9.0.0 && < 2.16,
111− text >= 1.2.3.0 && < 1.3,
112− time >= 1.4 && < 1.10
113−
114− if impl(ghc >= 8.0)
115− build-depends: bytestring >= 0.10.8.1
116
85
117− -- Compat
118 build-depends:
86 build-depends:
119− base-compat >= 0.9.1 && < 0.12,
87+ attoparsec >= 0.13.0.1,
120− time-compat >= 1.9.2.2 && < 1.10
88+ base >= 4.5 && < 5,
121−
89+ base-compat >= 0.9.1 && < 0.10,
122− if !impl(ghc >= 8.6)
90+ bytestring >= 0.10.4.0,
123− build-depends:
91+ containers >= 0.2.4.1,
124− contravariant >=1.4.1 && <1.6
92+ deepseq >= 1.3,
93+ dlist >= 0.2,
94+ ghc-prim >= 0.2,
95+ hashable >= 1.1.2.0,
96+ scientific >= 0.3.1 && < 0.4,
97+ tagged >=0.8.3 && <0.9,
98+ template-haskell >= 2.7,
99+ text >= 1.1.1.0,
100+ time >= 1.1.1.4,
101+ time-locale-compat >= 0.1.1 && < 0.2,
102+ unordered-containers >= 0.2.5.0,
103+ vector >= 0.8
125
104
126 if !impl(ghc >= 8.0)
105 if !impl(ghc >= 8.0)
127 -- `Data.Semigroup` and `Control.Monad.Fail` and `Control.Monad.IO.Class` are available in base only since GHC 8.0 / base 4.9
106 -- `Data.Semigroup` and `Control.Monad.Fail` and `Control.Monad.IO.Class` are available in base only since GHC 8.0 / base 4.9
128 build-depends:
107 build-depends:
129− semigroups >= 0.18.5 && < 0.20,
108+ semigroups >= 0.16.1 && < 0.19,
130− transformers >= 0.3.0.0 && < 0.6,
109+ transformers >= 0.2.2.0,
131− transformers-compat >= 0.6.2 && < 0.7,
132 fail == 4.9.*
110 fail == 4.9.*
133
111
134 if !impl(ghc >= 7.10)
112 if !impl(ghc >= 7.10)
135 -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8
113 -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8
136− build-depends: nats >= 1.1.1 && < 1.2,
114+ build-depends: nats >= 1 && < 1.2
137− void >= 0.7.2 && < 0.8
138−
139− -- cannot use latest version
140− build-depends:
141− unordered-containers >= 0.2.8.0 && < 0.3,
142−
143− -- not in LTS-12.10
144− tagged >= 0.8.5 && < 0.9,
145− primitive >= 0.6.3.0 && < 0.8
146−
147− -- Other dependencies
148− build-depends:
149− attoparsec >= 0.13.2.2 && < 0.14,
150− dlist >= 0.8.0.4 && < 0.9,
151− hashable >= 1.2.7.0 && < 1.4,
152− scientific >= 0.3.6.2 && < 0.4,
153− th-abstraction >= 0.2.8.0 && < 0.4,
154− uuid-types >= 1.0.3 && < 1.1,
155− vector >= 0.12.0.1 && < 0.13
156−
157− ghc-options: -Wall
158
115
159 if flag(developer)
116 if flag(developer)
160 ghc-options: -Werror
117 ghc-options: -Werror
161 ghc-prof-options: -auto-all
118 ghc-prof-options: -auto-all
162
119
163− if flag(fast)
120+ ghc-options: -O2 -Wall
164− ghc-options: -O0
165− else
166− ghc-options: -O2
167
121
168 include-dirs: include
122 include-dirs: include
169− if impl(ghcjs) || !flag(cffi)
170− hs-source-dirs: pure
171− other-modules: Data.Aeson.Parser.UnescapePure
172− else
173− c-sources: cbits/unescape_string.c
174− cpp-options: -DCFFI
175− hs-source-dirs: ffi
176− other-modules: Data.Aeson.Parser.UnescapeFFI
177
123
178test-suite tests
124test-suite tests
179 default-language: Haskell2010
125 default-language: Haskell2010
180− type: exitcode-stdio-1.0
126+ type: exitcode-stdio-1.0
181− hs-source-dirs: tests ffi pure
127+ hs-source-dirs: tests
182− main-is: Tests.hs
128+ main-is: Tests.hs
183− c-sources: cbits/unescape_string.c
184− ghc-options: -Wall -threaded -rtsopts
185−
186 other-modules:
129 other-modules:
187− Data.Aeson.Parser.UnescapeFFI
188− Data.Aeson.Parser.UnescapePure
189 DataFamilies.Properties
130 DataFamilies.Properties
190 DataFamilies.Instances
131 DataFamilies.Instances
191 DataFamilies.Encoders
132 DataFamilies.Encoders
192 DataFamilies.Types
133 DataFamilies.Types
193 Encoders
134 Encoders
194− ErrorMessages
195 Functions
135 Functions
196 Instances
136 Instances
197 Options
137 Options
198− PropUtils
199 Properties
138 Properties
200− PropertyGeneric
201− PropertyKeys
202− PropertyRoundTrip
203− PropertyRTFunctors
204− PropertyTH
205− SerializationFormatSpec
206 Types
139 Types
207 UnitTests
140 UnitTests
208 UnitTests.NullaryConstructors
141 UnitTests.NullaryConstructors
209
142
143+ ghc-options: -Wall -threaded -rtsopts
144+
210 build-depends:
145 build-depends:
211− QuickCheck >= 2.10.0.1 && < 2.14,
146+ HUnit,
147+ QuickCheck >= 2.7 && <2.8.3,
212 aeson,
148 aeson,
213− integer-logarithms >= 1 && <1.1,
214 attoparsec,
149 attoparsec,
215 base,
150 base,
216− base-compat,
151+ base-orphans >= 0.5.3 && <0.6,
217− base-orphans >= 0.5.3 && <0.9,
152+ bytestring,
218− base16-bytestring,
219 containers,
153 containers,
220− directory,
154+ generic-deriving >= 1.10 && < 1.11,
221− dlist,
222− Diff >= 0.4 && < 0.5,
223− filepath,
224− generic-deriving >= 1.10 && < 1.14,
225 ghc-prim >= 0.2,
155 ghc-prim >= 0.2,
226− hashable >= 1.2.4.0,
156+ hashable >= 1.1.2.0,
227− scientific,
228 tagged,
157 tagged,
229 template-haskell,
158 template-haskell,
230− tasty,
159+ test-framework,
231− tasty-golden,
160+ test-framework-hunit,
232− tasty-hunit,
161+ test-framework-quickcheck2,
233− tasty-quickcheck,
234 text,
162 text,
235 time,
163 time,
236− time-compat,
164+ time-locale-compat,
237 unordered-containers,
165 unordered-containers,
238− uuid-types,
239 vector,
166 vector,
240− quickcheck-instances >= 0.3.21 && <0.4
167+ quickcheck-instances >=0.3.12
241−
242− if flag(bytestring-builder)
243− build-depends: bytestring >= 0.9 && < 0.10.4,
244− bytestring-builder >= 0.10.4 && < 1
245− else
246− build-depends: bytestring >= 0.10.4
247
168
248 if !impl(ghc >= 8.0)
169 if !impl(ghc >= 8.0)
249− build-depends:
170+ build-depends: semigroups >= 0.16.1 && < 0.19
250− semigroups >= 0.18.2 && < 0.20,
251− transformers >= 0.2.2.0,
252− transformers-compat >= 0.3
253
171
254 if !impl(ghc >= 7.10)
172 if !impl(ghc >= 7.10)
255− build-depends: nats >=1 && <1.2,
173+ build-depends: nats >=1 && <1.2
256− void >=0.7.2 && <0.8
257−
258− if impl(ghc >= 7.8)
259− build-depends: hashable-time >= 0.2 && <0.3
260−
261− if flag(fast)
262− ghc-options: -fno-enable-rewrite-rules
263
174
264source-repository head
175source-repository head
265 type: git
176 type: git
266 location: git://github.com/bos/aeson.git
177 location: git://github.com/bos/aeson.git
178+
179+source-repository head
180+ type: mercurial
181+ location: https://bitbucket.org/bos/aeson
attoparsec-iso8601/Data/Attoparsec/Time.hsdeleted−148
@@ -1,148 +0,0 @@
1−{-# LANGUAGE BangPatterns #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−-- |
5−-- Module: Data.Aeson.Parser.Time
6−-- Copyright: (c) 2015-2016 Bryan O'Sullivan
7−-- License: BSD3
8−-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
9−-- Stability: experimental
10−-- Portability: portable
11−--
12−-- Parsers for parsing dates and times.
13−
14−module Data.Attoparsec.Time
15− (
16− day
17− , localTime
18− , timeOfDay
19− , timeZone
20− , utcTime
21− , zonedTime
22− ) where
23−
24−import Prelude.Compat
25−
26−import Control.Applicative ((<|>))
27−import Control.Monad (void, when)
28−import Data.Attoparsec.Text as A
29−import Data.Attoparsec.Time.Internal (toPico)
30−import Data.Bits ((.&.))
31−import Data.Char (isDigit, ord)
32−import Data.Fixed (Pico)
33−import Data.Int (Int64)
34−import Data.Maybe (fromMaybe)
35−import Data.Time.Calendar (Day, fromGregorianValid)
36−import Data.Time.Clock (UTCTime(..))
37−import qualified Data.Text as T
38−import qualified Data.Time.LocalTime as Local
39−
40−-- | Parse a date of the form @[+,-]YYYY-MM-DD@.
41−day :: Parser Day
42−day = do
43− absOrNeg <- negate <$ char '-' <|> id <$ char '+' <|> pure id
44− y <- (decimal <* char '-') <|> fail "date must be of form [+,-]YYYY-MM-DD"
45− m <- (twoDigits <* char '-') <|> fail "date must be of form [+,-]YYYY-MM-DD"
46− d <- twoDigits <|> fail "date must be of form [+,-]YYYY-MM-DD"
47− maybe (fail "invalid date") return (fromGregorianValid (absOrNeg y) m d)
48−
49−-- | Parse a two-digit integer (e.g. day of month, hour).
50−twoDigits :: Parser Int
51−twoDigits = do
52− a <- digit
53− b <- digit
54− let c2d c = ord c .&. 15
55− return $! c2d a * 10 + c2d b
56−
57−-- | Parse a time of the form @HH:MM[:SS[.SSS]]@.
58−timeOfDay :: Parser Local.TimeOfDay
59−timeOfDay = do
60− h <- twoDigits
61− m <- char ':' *> twoDigits
62− s <- option 0 (char ':' *> seconds)
63− if h < 24 && m < 60 && s < 61
64− then return (Local.TimeOfDay h m s)
65− else fail "invalid time"
66−
67−data T = T {-# UNPACK #-} !Int {-# UNPACK #-} !Int64
68−
69−-- | Parse a count of seconds, with the integer part being two digits
70−-- long.
71−seconds :: Parser Pico
72−seconds = do
73− real <- twoDigits
74− mc <- peekChar
75− case mc of
76− Just '.' -> do
77− t <- anyChar *> takeWhile1 isDigit
78− return $! parsePicos real t
79− _ -> return $! fromIntegral real
80− where
81− parsePicos a0 t = toPico (fromIntegral (t' * 10^n))
82− where T n t' = T.foldl' step (T 12 (fromIntegral a0)) t
83− step ma@(T m a) c
84− | m <= 0 = ma
85− | otherwise = T (m-1) (10 * a + fromIntegral (ord c) .&. 15)
86−
87−-- | Parse a time zone, and return 'Nothing' if the offset from UTC is
88−-- zero. (This makes some speedups possible.)
89−timeZone :: Parser (Maybe Local.TimeZone)
90−timeZone = do
91− let maybeSkip c = do ch <- peekChar'; when (ch == c) (void anyChar)
92− maybeSkip ' '
93− ch <- satisfy $ \c -> c == 'Z' || c == '+' || c == '-'
94− if ch == 'Z'
95− then return Nothing
96− else do
97− h <- twoDigits
98− mm <- peekChar
99− m <- case mm of
100− Just ':' -> anyChar *> twoDigits
101− Just d | isDigit d -> twoDigits
102− _ -> return 0
103− let off | ch == '-' = negate off0
104− | otherwise = off0
105− off0 = h * 60 + m
106− case undefined of
107− _ | off == 0 ->
108− return Nothing
109− | off < -720 || off > 840 || m > 59 ->
110− fail "invalid time zone offset"
111− | otherwise ->
112− let !tz = Local.minutesToTimeZone off
113− in return (Just tz)
114−
115−-- | Parse a date and time, of the form @YYYY-MM-DD HH:MM[:SS[.SSS]]@.
116−-- The space may be replaced with a @T@. The number of seconds is optional
117−-- and may be followed by a fractional component.
118−localTime :: Parser Local.LocalTime
119−localTime = Local.LocalTime <$> day <* daySep <*> timeOfDay
120− where daySep = satisfy (\c -> c == 'T' || c == ' ')
121−
122−-- | Behaves as 'zonedTime', but converts any time zone offset into a
123−-- UTC time.
124−utcTime :: Parser UTCTime
125−utcTime = do
126− lt@(Local.LocalTime d t) <- localTime
127− mtz <- timeZone
128− case mtz of
129− Nothing -> let !tt = Local.timeOfDayToTime t
130− in return (UTCTime d tt)
131− Just tz -> return $! Local.localTimeToUTC tz lt
132−
133−-- | Parse a date with time zone info. Acceptable formats:
134−--
135−-- @YYYY-MM-DD HH:MM Z@
136−-- @YYYY-MM-DD HH:MM:SS Z@
137−-- @YYYY-MM-DD HH:MM:SS.SSS Z@
138−--
139−-- The first space may instead be a @T@, and the second space is
140−-- optional. The @Z@ represents UTC. The @Z@ may be replaced with a
141−-- time zone offset of the form @+0000@ or @-08:00@, where the first
142−-- two digits are hours, the @:@ is optional and the second two digits
143−-- (also optional) are minutes.
144−zonedTime :: Parser Local.ZonedTime
145−zonedTime = Local.ZonedTime <$> localTime <*> (fromMaybe utc <$> timeZone)
146−
147−utc :: Local.TimeZone
148−utc = Local.TimeZone 0 False ""
attoparsec-iso8601/Data/Attoparsec/Time/Internal.hsdeleted−64
@@ -1,64 +0,0 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−-- |
4−-- Module: Data.Aeson.Internal.Time
5−-- Copyright: (c) 2015-2016 Bryan O'Sullivan
6−-- License: BSD3
7−-- Maintainer: Bryan O'Sullivan <bos@serpentine.com>
8−-- Stability: experimental
9−-- Portability: portable
10−
11−module Data.Attoparsec.Time.Internal
12− (
13− TimeOfDay64(..)
14− , fromPico
15− , toPico
16− , diffTimeOfDay64
17− , toTimeOfDay64
18− ) where
19−
20−import Prelude.Compat
21−
22−import Data.Int (Int64)
23−import Data.Time
24−import Unsafe.Coerce (unsafeCoerce)
25−
26−#if MIN_VERSION_time(1,6,0)
27−
28−import Data.Time.Clock (diffTimeToPicoseconds)
29−
30−#endif
31−
32−import Data.Fixed (Pico, Fixed(MkFixed))
33−
34−#if !MIN_VERSION_time(1,6,0)
35−
36−diffTimeToPicoseconds :: DiffTime -> Integer
37−diffTimeToPicoseconds = unsafeCoerce
38−
39−#endif
40−
41−toPico :: Integer -> Pico
42−toPico = MkFixed
43−
44−fromPico :: Pico -> Integer
45−fromPico (MkFixed i) = i
46−
47−-- | Like TimeOfDay, but using a fixed-width integer for seconds.
48−data TimeOfDay64 = TOD {-# UNPACK #-} !Int
49− {-# UNPACK #-} !Int
50− {-# UNPACK #-} !Int64
51−
52−posixDayLength :: DiffTime
53−posixDayLength = 86400
54−
55−diffTimeOfDay64 :: DiffTime -> TimeOfDay64
56−diffTimeOfDay64 t
57− | t >= posixDayLength = TOD 23 59 (60000000000000 + pico (t - posixDayLength))
58− | otherwise = TOD (fromIntegral h) (fromIntegral m) s
59− where (h,mp) = pico t `quotRem` 3600000000000000
60− (m,s) = mp `quotRem` 60000000000000
61− pico = fromIntegral . diffTimeToPicoseconds
62−
63−toTimeOfDay64 :: TimeOfDay -> TimeOfDay64
64−toTimeOfDay64 (TimeOfDay h m s) = TOD h m (fromIntegral (fromPico s))
attoparsec-iso8601/LICENSEdeleted−30
@@ -1,30 +0,0 @@
1−Copyright (c) 2011, MailRank, Inc.
2−
3−All rights reserved.
4−
5−Redistribution and use in source and binary forms, with or without
6−modification, are permitted provided that the following conditions
7−are met:
8−
9−1. Redistributions of source code must retain the above copyright
10− notice, this list of conditions and the following disclaimer.
11−
12−2. Redistributions in binary form must reproduce the above copyright
13− notice, this list of conditions and the following disclaimer in the
14− documentation and/or other materials provided with the distribution.
15−
16−3. Neither the name of the author nor the names of his contributors
17− may be used to endorse or promote products derived from this software
18− without specific prior written permission.
19−
20−THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
21−OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22−WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23−DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
24−ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25−DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26−OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27−HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28−STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29−ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30−POSSIBILITY OF SUCH DAMAGE.
attoparsec-iso8601/README.mddeleted−19
@@ -1,19 +0,0 @@
1−Parsing of ISO 8601 dates.
2−
3−This package is used to parse dates in aeson. It is split into a
4−separate package to be shared by other projects that want to parse
5−dates like aeson does.
6−
7−For now, this project is located in the aeson repository and aeson
8−itself uses the source of this package without pulling in the package
9−as a dependency.
10−
11−## Stability
12−
13−Since aeson depends on this package we want to be very careful about
14−changing the format.
15−
16−There may be breaking changes if we find that the format is
17−incorrectly too lenient. We consider widening of the allowed input a
18−non-breaking addition since all previously valid input will still
19−parse correctly.
attoparsec-iso8601/attoparsec-iso8601.cabaldeleted−55
@@ -1,55 +0,0 @@
1−name: attoparsec-iso8601
2−version: 1.0.1.0
3−synopsis: Parsing of ISO 8601 dates, originally from aeson.
4−description: Parsing of ISO 8601 dates, originally from aeson.
5−license: BSD3
6−license-file: LICENSE
7−category: Parsing
8−copyright: (c) 2011-2016 Bryan O'Sullivan
9− (c) 2011 MailRank, Inc.
10−author: Bryan O'Sullivan <bos@serpentine.com>
11−maintainer: Adam Bergmark <adam@bergmark.nl>
12−stability: experimental
13−cabal-version: >=1.10
14−homepage: https://github.com/bos/aeson
15−bug-reports: https://github.com/bos/aeson/issues
16−build-type: Simple
17−extra-source-files:
18− README.md
19−
20−flag developer
21− description: operate in developer mode
22− default: False
23− manual: True
24−
25−flag fast
26− description: compile without optimizations
27− default: False
28− manual: True
29−
30−library
31− hs-source-dirs: .
32− default-language: Haskell2010
33− ghc-options: -Wall
34− exposed-modules:
35− Data.Attoparsec.Time.Internal
36− Data.Attoparsec.Time
37− build-depends:
38− attoparsec >= 0.13.0.1,
39− base >= 4.7 && < 5,
40− base-compat >= 0.9.1 && < 0.12,
41− text >= 1.1.1.0,
42− time >= 1.1.1.4
43−
44− if flag(fast)
45− ghc-options: -O0
46− else
47− ghc-options: -O2
48−
49− if flag(developer)
50− ghc-options: -Werror
51− ghc-prof-options: -auto-all
52−
53−source-repository head
54− type: git
55− location: git://github.com/bos/aeson.git
attoparsec-iso8601/changelog.mddeleted−5
@@ -1,5 +0,0 @@
1−For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/attoparsec-iso8601/changelog.md](https://github.com/bos/aeson/blob/master/attoparsec-iso8601/changelog.md).
2−
3−### 1.0.1.0
4−
5−* Fixes handling of `UTCTime` wrt. leap seconds , thanks to Adam Schønemann
benchmarks/AesonCompareAutoInstances.hsnew file+231
@@ -0,0 +1,231 @@
1+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, TemplateHaskell #-}
2+
3+module Main where
4+
5+--------------------------------------------------------------------------------
6+
7+import Criterion.Main hiding (defaultOptions)
8+
9+import Control.DeepSeq (NFData, rnf, deepseq)
10+
11+import Data.Typeable (Typeable)
12+import Data.Data (Data)
13+import GHC.Generics (Generic)
14+
15+import Data.Aeson.Types
16+import Data.Aeson.TH
17+import qualified Data.Aeson.Generic as G (fromJSON, toJSON)
18+
19+import Data.Aeson.Encode
20+
21+import Options
22+
23+--------------------------------------------------------------------------------
24+
25+data D a = Nullary
26+ | Unary Int
27+ | Product String Char a
28+ | Record { testOne :: Double
29+ , testTwo :: Bool
30+ , testThree :: D a
31+ }
32+ deriving (Show, Eq, Data, Typeable)
33+
34+deriveJSON opts ''D
35+
36+instance NFData a => NFData (D a) where
37+ rnf Nullary = ()
38+ rnf (Unary n) = rnf n
39+ rnf (Product s c x) = s `deepseq` c `deepseq` rnf x
40+ rnf (Record d b y) = d `deepseq` b `deepseq` rnf y
41+
42+type T = D (D (D ()))
43+
44+d :: T
45+d = Record
46+ { testOne = 1234.56789
47+ , testTwo = True
48+ , testThree = Product "Hello World!" 'a' $
49+ Record
50+ { testOne = 9876.54321
51+ , testTwo = False
52+ , testThree = Product "Yeehaa!!!" '\n' Nullary
53+ }
54+ }
55+
56+--------------------------------------------------------------------------------
57+
58+data D' a = Nullary'
59+ | Unary' Int
60+ | Product' String Char a
61+ | Record' { testOne' :: Double
62+ , testTwo' :: Bool
63+ , testThree' :: D' a
64+ }
65+ deriving (Show, Eq, Generic, Data, Typeable)
66+
67+instance ToJSON a => ToJSON (D' a) where
68+ toJSON = genericToJSON opts
69+
70+instance FromJSON a => FromJSON (D' a) where
71+ parseJSON = genericParseJSON opts
72+
73+instance NFData a => NFData (D' a) where
74+ rnf Nullary' = ()
75+ rnf (Unary' n) = rnf n
76+ rnf (Product' s c x) = s `deepseq` c `deepseq` rnf x
77+ rnf (Record' d b y) = d `deepseq` b `deepseq` rnf y
78+
79+type T' = D' (D' (D' ()))
80+
81+d' :: T'
82+d' = Record'
83+ { testOne' = 1234.56789
84+ , testTwo' = True
85+ , testThree' = Product' "Hello World!" 'a' $
86+ Record'
87+ { testOne' = 9876.54321
88+ , testTwo' = False
89+ , testThree' = Product' "Yeehaa!!!" '\n' Nullary'
90+ }
91+ }
92+
93+--------------------------------------------------------------------------------
94+
95+data BigRecord = BigRecord
96+ { field01 :: !Int, field02 :: !Int, field03 :: !Int, field04 :: !Int, field05 :: !Int
97+ , field06 :: !Int, field07 :: !Int, field08 :: !Int, field09 :: !Int, field10 :: !Int
98+ , field11 :: !Int, field12 :: !Int, field13 :: !Int, field14 :: !Int, field15 :: !Int
99+ , field16 :: !Int, field17 :: !Int, field18 :: !Int, field19 :: !Int, field20 :: !Int
100+ , field21 :: !Int, field22 :: !Int, field23 :: !Int, field24 :: !Int, field25 :: !Int
101+ } deriving (Show, Eq, Generic, Data, Typeable)
102+
103+instance NFData BigRecord
104+
105+bigRecord = BigRecord 1 2 3 4 5
106+ 6 7 8 9 10
107+ 11 12 13 14 15
108+ 16 17 18 19 20
109+ 21 22 23 24 25
110+
111+gBigRecordToJSON :: BigRecord -> Value
112+gBigRecordToJSON = genericToJSON opts
113+
114+gBigRecordFromJSON :: Value -> Result BigRecord
115+gBigRecordFromJSON = parse $ genericParseJSON opts
116+
117+thBigRecordToJSON :: BigRecord -> Value
118+thBigRecordToJSON = $(mkToJSON opts ''BigRecord)
119+
120+thBigRecordFromJSON :: Value -> Result BigRecord
121+thBigRecordFromJSON = parse $(mkParseJSON opts ''BigRecord)
122+
123+--------------------------------------------------------------------------------
124+
125+data BigProduct = BigProduct
126+ !Int !Int !Int !Int !Int
127+ !Int !Int !Int !Int !Int
128+ !Int !Int !Int !Int !Int
129+ !Int !Int !Int !Int !Int
130+ !Int !Int !Int !Int !Int
131+ deriving (Show, Eq, Generic, Data, Typeable)
132+
133+instance NFData BigProduct
134+
135+bigProduct = BigProduct 1 2 3 4 5
136+ 6 7 8 9 10
137+ 11 12 13 14 15
138+ 16 17 18 19 20
139+ 21 22 23 24 25
140+
141+gBigProductToJSON :: BigProduct -> Value
142+gBigProductToJSON = genericToJSON opts
143+
144+gBigProductFromJSON :: Value -> Result BigProduct
145+gBigProductFromJSON = parse $ genericParseJSON opts
146+
147+thBigProductToJSON :: BigProduct -> Value
148+thBigProductToJSON = $(mkToJSON opts ''BigProduct)
149+
150+thBigProductFromJSON :: Value -> Result BigProduct
151+thBigProductFromJSON = parse $(mkParseJSON opts ''BigProduct)
152+
153+--------------------------------------------------------------------------------
154+
155+data BigSum = F01 | F02 | F03 | F04 | F05
156+ | F06 | F07 | F08 | F09 | F10
157+ | F11 | F12 | F13 | F14 | F15
158+ | F16 | F17 | F18 | F19 | F20
159+ | F21 | F22 | F23 | F24 | F25
160+ deriving (Show, Eq, Generic, Data, Typeable)
161+
162+instance NFData BigSum
163+
164+bigSum = F25
165+
166+gBigSumToJSON :: BigSum -> Value
167+gBigSumToJSON = genericToJSON opts
168+
169+gBigSumFromJSON :: Value -> Result BigSum
170+gBigSumFromJSON = parse $ genericParseJSON opts
171+
172+thBigSumToJSON :: BigSum -> Value
173+thBigSumToJSON = $(mkToJSON opts ''BigSum)
174+
175+thBigSumFromJSON :: Value -> Result BigSum
176+thBigSumFromJSON = parse $(mkParseJSON opts ''BigSum)
177+
178+--------------------------------------------------------------------------------
179+
180+type FJ a = Value -> Result a
181+
182+main :: IO ()
183+main = defaultMain
184+ [ let v = toJSON d
185+ in (d, d', v) `deepseq`
186+ bgroup "D"
187+ [ group "toJSON" (nf toJSON d)
188+ (nf G.toJSON d)
189+ (nf toJSON d')
190+ , group "fromJSON" (nf ( fromJSON :: FJ T ) v)
191+ (nf (G.fromJSON :: FJ T ) v)
192+ (nf ( fromJSON :: FJ T') v)
193+ ]
194+ , let v = thBigRecordToJSON bigRecord
195+ in bigRecord `deepseq` v `deepseq`
196+ bgroup "BigRecord"
197+ [ group "toJSON" (nf thBigRecordToJSON bigRecord)
198+ (nf G.toJSON bigRecord)
199+ (nf gBigRecordToJSON bigRecord)
200+ , group "fromJSON" (nf (thBigRecordFromJSON :: FJ BigRecord) v)
201+ (nf (G.fromJSON :: FJ BigRecord) v)
202+ (nf (gBigRecordFromJSON :: FJ BigRecord) v)
203+ ]
204+ , let v = thBigProductToJSON bigProduct
205+ in bigProduct `deepseq` v `deepseq`
206+ bgroup "BigProduct"
207+ [ group "toJSON" (nf thBigProductToJSON bigProduct)
208+ (nf G.toJSON bigProduct)
209+ (nf gBigProductToJSON bigProduct)
210+ , group "fromJSON" (nf (thBigProductFromJSON :: FJ BigProduct) v)
211+ (nf (G.fromJSON :: FJ BigProduct) v)
212+ (nf (gBigProductFromJSON :: FJ BigProduct) v)
213+ ]
214+ , let v = thBigSumToJSON bigSum
215+ in bigSum `deepseq` v `deepseq`
216+ bgroup "BigSum"
217+ [ group "toJSON" (nf thBigSumToJSON bigSum)
218+ (nf G.toJSON bigSum)
219+ (nf gBigSumToJSON bigSum)
220+ , group "fromJSON" (nf (thBigSumFromJSON :: FJ BigSum) v)
221+ (nf (G.fromJSON :: FJ BigSum) v)
222+ (nf (gBigSumFromJSON :: FJ BigSum) v)
223+ ]
224+ ]
225+
226+group n th syb gen = bcompare
227+ [ bgroup n [ bench "th" th
228+ , bench "syb" syb
229+ , bench "generic" gen
230+ ]
231+ ]
benchmarks/AesonEncode.hs+6−12
@@ -1,13 +1,7 @@
1−{-# LANGUAGE BangPatterns #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE OverloadedStrings #-}
4
2
5−module Main (main) where
3+import Control.Exception
6−
4+import Control.Monad
7−import Prelude.Compat
8−
9−import Control.DeepSeq
10−import Control.Monad (forM_)
11import Data.Aeson
5import Data.Aeson
12import Data.Attoparsec.ByteString (IResult(..), parseWith)
6import Data.Attoparsec.ByteString (IResult(..), parseWith)
13import Data.Char (isDigit)
7import Data.Char (isDigit)
@@ -15,6 +9,7 @@ import Data.Time.Clock
15import System.Environment (getArgs)
9import System.Environment (getArgs)
16import System.IO
10import System.IO
17import qualified Data.ByteString as B
11import qualified Data.ByteString as B
12+import Control.DeepSeq
18
13
19main :: IO ()
14main :: IO ()
20main = do
15main = do
@@ -22,9 +17,8 @@ main = do
22 let (cnt,args) = case args0 of
17 let (cnt,args) = case args0 of
23 (i:c:a) | all isDigit i && all isDigit c -> (c,a)
18 (i:c:a) | all isDigit i && all isDigit c -> (c,a)
24 (c:a) -> (c,a)
19 (c:a) -> (c,a)
25− [] -> error "Unexpected empty list"
26 let count = read cnt :: Int
20 let count = read cnt :: Int
27− forM_ args $ \arg -> withFile arg ReadMode $ \h -> do
21+ forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do
28 putStrLn $ arg ++ ":"
22 putStrLn $ arg ++ ":"
29 let refill = B.hGet h 16384
23 let refill = B.hGet h 16384
30 result0 <- parseWith refill json =<< refill
24 result0 <- parseWith refill json =<< refill
@@ -34,7 +28,7 @@ main = do
34 start <- getCurrentTime
28 start <- getCurrentTime
35 let loop !n r
29 let loop !n r
36 | n >= count = return ()
30 | n >= count = return ()
37− | otherwise = {-# SCC "loop" #-}
31+ | otherwise = {-# SCC "loop" #-} do
38 rnf (encode r) `seq` loop (n+1) r
32 rnf (encode r) `seq` loop (n+1) r
39 loop 0 r0
33 loop 0 r0
40 delta <- flip diffUTCTime start `fmap` getCurrentTime
34 delta <- flip diffUTCTime start `fmap` getCurrentTime
benchmarks/AesonFoldable.hsdeleted−86
@@ -1,86 +0,0 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−
4−module Main (main) where
5−
6−import Criterion.Main
7−
8−import Prelude.Compat
9−
10−import Data.Foldable (toList)
11−import qualified Data.Aeson as A
12−import qualified Data.Sequence as S
13−import qualified Data.Vector as V
14−import qualified Data.Vector.Unboxed as U
15−
16−-------------------------------------------------------------------------------
17−-- List
18−-------------------------------------------------------------------------------
19−
20−newtype L f = L { getL :: f Int }
21−
22−instance Foldable f => A.ToJSON (L f) where
23− toJSON = error "do not use this"
24− toEncoding = A.toEncoding . toList . getL
25−
26−-------------------------------------------------------------------------------
27−-- Foldable
28−-------------------------------------------------------------------------------
29−
30−newtype F f = F { getF :: f Int }
31−
32−instance Foldable f => A.ToJSON (F f) where
33− toJSON = error "do not use this"
34− toEncoding = A.foldable . getF
35−
36−-------------------------------------------------------------------------------
37−-- Values
38−-------------------------------------------------------------------------------
39−
40−valueList :: [Int]
41−valueList = [1..1000]
42−
43−valueSeq :: S.Seq Int
44−valueSeq = S.fromList valueList
45−
46−valueVector :: V.Vector Int
47−valueVector = V.fromList valueList
48−
49−valueUVector :: U.Vector Int
50−valueUVector = U.fromList valueList
51−
52−-------------------------------------------------------------------------------
53−-- Main
54−-------------------------------------------------------------------------------
55−
56−benchEncode
57− :: A.ToJSON a
58− => String
59− -> a
60− -> Benchmark
61−benchEncode name val
62− = bench ("A " ++ name) $ nf A.encode val
63−
64−main :: IO ()
65−main = defaultMain
66− [ bgroup "encode"
67− [ bgroup "List"
68− [ benchEncode "-" valueList
69− , benchEncode "L" $ L valueList
70− , benchEncode "F" $ F valueList
71− ]
72− , bgroup "Seq"
73− [ benchEncode "-" valueSeq
74− , benchEncode "L" $ L valueSeq
75− , benchEncode "F" $ F valueSeq
76− ]
77− , bgroup "Vector"
78− [ benchEncode "-" valueVector
79− , benchEncode "L" $ L valueVector
80− , benchEncode "F" $ F valueVector
81− ]
82− , bgroup "Vector.Unboxed"
83− [ benchEncode "-" valueUVector
84− ]
85− ]
86− ]
benchmarks/AesonMap.hs+17−28
@@ -1,24 +1,16 @@
1−{-# LANGUAGE FlexibleContexts #-}
1+{-# LANGUAGE OverloadedStrings, RankNTypes #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE RankNTypes #-}
4−
5−{-# OPTIONS_GHC -fno-warn-orphans #-}
6−
7−module Main (main) where
8−
9−import Prelude.Compat
10
2
11import Control.DeepSeq
3import Control.DeepSeq
12import Criterion.Main
4import Criterion.Main
5+import Data.Aeson
6+import Data.Aeson.Types (fromJSONKeyCoerce)
13import Data.Hashable
7import Data.Hashable
14import Data.Proxy (Proxy (..))
8import Data.Proxy (Proxy (..))
15import Data.Tagged (Tagged (..))
9import Data.Tagged (Tagged (..))
16−import Data.Aeson
17−import Data.Aeson.Types (fromJSONKeyCoerce)
18import qualified Data.ByteString.Lazy as LBS
10import qualified Data.ByteString.Lazy as LBS
19−import qualified Data.HashMap.Strict as HM
20−import qualified Data.Map as M
21import qualified Data.Text as T
11import qualified Data.Text as T
12+import qualified Data.Map as M
13+import qualified Data.HashMap.Strict as HM
22
14
23value :: Int -> HM.HashMap T.Text T.Text
15value :: Int -> HM.HashMap T.Text T.Text
24value n = HM.fromList $ map f [1..n]
16value n = HM.fromList $ map f [1..n]
@@ -43,7 +35,6 @@ instance NFData T1 where
43 rnf (T1 t) = rnf t
35 rnf (T1 t) = rnf t
44instance Hashable T1 where
36instance Hashable T1 where
45 hashWithSalt salt (T1 t) = hashWithSalt salt t
37 hashWithSalt salt (T1 t) = hashWithSalt salt t
46−
47instance FromJSON T1 where
38instance FromJSON T1 where
48 parseJSON = withText "T1" $ pure . T1
39 parseJSON = withText "T1" $ pure . T1
49instance FromJSONKey T1 where
40instance FromJSONKey T1 where
@@ -60,7 +51,6 @@ instance NFData T2 where
60 rnf (T2 t) = rnf t
51 rnf (T2 t) = rnf t
61instance Hashable T2 where
52instance Hashable T2 where
62 hashWithSalt salt (T2 t) = hashWithSalt salt t
53 hashWithSalt salt (T2 t) = hashWithSalt salt t
63−
64instance FromJSON T2 where
54instance FromJSON T2 where
65 parseJSON = withText "T2" $ pure . T2
55 parseJSON = withText "T2" $ pure . T2
66instance FromJSONKey T2 where
56instance FromJSONKey T2 where
@@ -77,7 +67,6 @@ instance NFData T3 where
77 rnf (T3 t) = rnf t
67 rnf (T3 t) = rnf t
78instance Hashable T3 where
68instance Hashable T3 where
79 hashWithSalt salt (T3 t) = hashWithSalt salt t
69 hashWithSalt salt (T3 t) = hashWithSalt salt t
80−
81instance FromJSON T3 where
70instance FromJSON T3 where
82 parseJSON = withText "T3" $ pure . T3
71 parseJSON = withText "T3" $ pure . T3
83instance FromJSONKey T3 where
72instance FromJSONKey T3 where
@@ -94,28 +83,28 @@ value1000 = value 1000
94value10000 = value 10000
83value10000 = value 10000
95
84
96encodedValue10 :: LBS.ByteString
85encodedValue10 :: LBS.ByteString
97−encodedValue10 = encode value10
86+encodedValue10 = encode $ value10
98
87
99encodedValue100 :: LBS.ByteString
88encodedValue100 :: LBS.ByteString
100−encodedValue100 = encode value100
89+encodedValue100 = encode $ value100
101
90
102encodedValue1000 :: LBS.ByteString
91encodedValue1000 :: LBS.ByteString
103−encodedValue1000 = encode value1000
92+encodedValue1000 = encode $ value1000
104
93
105encodedValue10000 :: LBS.ByteString
94encodedValue10000 :: LBS.ByteString
106−encodedValue10000 = encode value10000
95+encodedValue10000 = encode $ value10000
107
96
108-------------------------------------------------------------------------------
97-------------------------------------------------------------------------------
109-- Helpers
98-- Helpers
110-------------------------------------------------------------------------------
99-------------------------------------------------------------------------------
111
100
112decodeHM
101decodeHM
113− :: (FromJSON (HM.HashMap k T.Text), Eq k, Hashable k)
102+ :: (FromJSONKey k, Eq k, Hashable k)
114 => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
103 => Proxy k -> LBS.ByteString -> Maybe (HM.HashMap k T.Text)
115decodeHM _ = decode
104decodeHM _ = decode
116
105
117decodeMap
106decodeMap
118− :: (FromJSON (M.Map k T.Text), Ord k)
107+ :: (FromJSONKey k, Ord k)
119 => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
108 => Proxy k -> LBS.ByteString -> Maybe (M.Map k T.Text)
120decodeMap _ = decode
109decodeMap _ = decode
121
110
@@ -158,10 +147,10 @@ benchDecodeMap
158 -> LBS.ByteString
147 -> LBS.ByteString
159 -> Benchmark
148 -> Benchmark
160benchDecodeMap name val = bgroup name
149benchDecodeMap name val = bgroup name
161− [ bench "Text" $ nf (decodeMap proxyText) val
150+ [ bench "Text" $ nf (decodeMap proxyText) val
162− , bench "Identity" $ nf (decodeMap proxyT1) val
151+ , bench "Identity" $ nf (decodeMap proxyT1) val
163− , bench "Coerce" $ nf (decodeMap proxyT2) val
152+ , bench "Coerce" $ nf (decodeMap proxyT2) val
164− , bench "Parser" $ nf (decodeMap proxyT3) val
153+ , bench "Parser" $ nf (decodeMap proxyT3) val
165 ]
154 ]
166
155
167benchEncodeHM
156benchEncodeHM
@@ -169,7 +158,7 @@ benchEncodeHM
169 -> HM.HashMap T.Text T.Text
158 -> HM.HashMap T.Text T.Text
170 -> Benchmark
159 -> Benchmark
171benchEncodeHM name val = bgroup name
160benchEncodeHM name val = bgroup name
172− [ bench "Text" $ nf encode val
161+ [ bench "Text" $ nf encode val
173 ]
162 ]
174
163
175benchEncodeMap
164benchEncodeMap
@@ -177,7 +166,7 @@ benchEncodeMap
177 -> HM.HashMap T.Text T.Text
166 -> HM.HashMap T.Text T.Text
178 -> Benchmark
167 -> Benchmark
179benchEncodeMap name val = bgroup name
168benchEncodeMap name val = bgroup name
180− [ bench "Text" $ nf encode val'
169+ [ bench "Text" $ nf encode val'
181 ]
170 ]
182 where
171 where
183 val' :: M.Map T.Text T.Text
172 val' :: M.Map T.Text T.Text
benchmarks/AesonParse.hs+4−9
@@ -1,13 +1,8 @@
1−{-# LANGUAGE BangPatterns #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE OverloadedStrings #-}
4
2
5−module Main (main) where
3+import Control.Exception
6−
7−import Prelude.Compat
8−
9−import Data.Aeson
10import Control.Monad
4import Control.Monad
5+import Data.Aeson
11import Data.Attoparsec.ByteString (IResult(..), parseWith)
6import Data.Attoparsec.ByteString (IResult(..), parseWith)
12import Data.Time.Clock
7import Data.Time.Clock
13import System.Environment (getArgs)
8import System.Environment (getArgs)
@@ -19,7 +14,7 @@ main = do
19 (bs:cnt:args) <- getArgs
14 (bs:cnt:args) <- getArgs
20 let count = read cnt :: Int
15 let count = read cnt :: Int
21 blkSize = read bs
16 blkSize = read bs
22− forM_ args $ \arg -> withFile arg ReadMode $ \h -> do
17+ forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do
23 putStrLn $ arg ++ ":"
18 putStrLn $ arg ++ ":"
24 start <- getCurrentTime
19 start <- getCurrentTime
25 let loop !good !bad
20 let loop !good !bad
benchmarks/AesonTuples.hs+3−5
@@ -1,11 +1,9 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+module Main where
2
2
3−module Main (main) where
3+--------------------------------------------------------------------------------
4−
5−import Prelude.Compat
6
4
7−import Control.DeepSeq (deepseq)
8import Criterion.Main
5import Criterion.Main
6+import Control.DeepSeq (deepseq)
9import Data.Aeson
7import Data.Aeson
10
8
11--------------------------------------------------------------------------------
9--------------------------------------------------------------------------------
benchmarks/Auto/G/BigProduct.hsdeleted−33
@@ -1,33 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−
3−module Auto.G.BigProduct where
4−
5−import Control.DeepSeq
6−import Data.Aeson
7−import GHC.Generics (Generic)
8−import Options
9−
10−data BigProduct = BigProduct
11− !Int !Int !Int !Int !Int
12− !Int !Int !Int !Int !Int
13− !Int !Int !Int !Int !Int
14− !Int !Int !Int !Int !Int
15− !Int !Int !Int !Int !Int
16− deriving (Show, Eq, Generic)
17−
18−instance NFData BigProduct where
19− rnf a = a `seq` ()
20−
21−instance ToJSON BigProduct where
22− toJSON = genericToJSON opts
23− toEncoding = genericToEncoding opts
24−
25−instance FromJSON BigProduct where
26− parseJSON = genericParseJSON opts
27−
28−bigProduct :: BigProduct
29−bigProduct = BigProduct 1 2 3 4 5
30− 6 7 8 9 10
31− 11 12 13 14 15
32− 16 17 18 19 20
33− 21 22 23 24 25
benchmarks/Auto/G/BigRecord.hsdeleted−33
@@ -1,33 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−
3−module Auto.G.BigRecord where
4−
5−import Control.DeepSeq
6−import Data.Aeson
7−import GHC.Generics (Generic)
8−import Options
9−
10−data BigRecord = BigRecord
11− { field01 :: !Int, field02 :: !Int, field03 :: !Int, field04 :: !Int, field05 :: !Int
12− , field06 :: !Int, field07 :: !Int, field08 :: !Int, field09 :: !Int, field10 :: !Int
13− , field11 :: !Int, field12 :: !Int, field13 :: !Int, field14 :: !Int, field15 :: !Int
14− , field16 :: !Int, field17 :: !Int, field18 :: !Int, field19 :: !Int, field20 :: !Int
15− , field21 :: !Int, field22 :: !Int, field23 :: !Int, field24 :: !Int, field25 :: !Int
16− } deriving (Show, Eq, Generic)
17−
18−instance NFData BigRecord where
19− rnf a = a `seq` ()
20−
21−instance ToJSON BigRecord where
22− toJSON = genericToJSON opts
23− toEncoding = genericToEncoding opts
24−
25−instance FromJSON BigRecord where
26− parseJSON = genericParseJSON opts
27−
28−bigRecord :: BigRecord
29−bigRecord = BigRecord 1 2 3 4 5
30− 6 7 8 9 10
31− 11 12 13 14 15
32− 16 17 18 19 20
33− 21 22 23 24 25
benchmarks/Auto/G/BigSum.hsdeleted−28
@@ -1,28 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−
3−module Auto.G.BigSum where
4−
5−import Control.DeepSeq
6−import Data.Aeson
7−import GHC.Generics (Generic)
8−import Options
9−
10−data BigSum = F01 | F02 | F03 | F04 | F05
11− | F06 | F07 | F08 | F09 | F10
12− | F11 | F12 | F13 | F14 | F15
13− | F16 | F17 | F18 | F19 | F20
14− | F21 | F22 | F23 | F24 | F25
15− deriving (Show, Eq, Generic)
16−
17−instance NFData BigSum where
18− rnf a = a `seq` ()
19−
20−instance ToJSON BigSum where
21− toJSON = genericToJSON opts
22− toEncoding = genericToEncoding opts
23−
24−instance FromJSON BigSum where
25− parseJSON = genericParseJSON opts
26−
27−bigSum :: BigSum
28−bigSum = F25
benchmarks/Auto/G/D.hsdeleted−44
@@ -1,44 +0,0 @@
1−{-# LANGUAGE DeriveGeneric #-}
2−
3−module Auto.G.D where
4−
5−import Control.DeepSeq
6−import Data.Aeson
7−import GHC.Generics (Generic)
8−import Options
9−
10−data D a = Nullary
11− | Unary Int
12− | Product String Char a
13− | Record { testOne :: Double
14− , testTwo :: Bool
15− , testThree :: D a
16− }
17− deriving (Show, Eq, Generic)
18−
19−instance NFData a => NFData (D a) where
20− rnf Nullary = ()
21− rnf (Unary n) = rnf n
22− rnf (Product s c x) = s `deepseq` c `deepseq` rnf x
23− rnf (Record a b y) = a `deepseq` b `deepseq` rnf y
24−
25−instance ToJSON a => ToJSON (D a) where
26− toJSON = genericToJSON opts
27− toEncoding = genericToEncoding opts
28−
29−instance FromJSON a => FromJSON (D a) where
30− parseJSON = genericParseJSON opts
31−
32−type T = D (D (D ()))
33−
34−d :: T
35−d = Record
36− { testOne = 1234.56789
37− , testTwo = True
38− , testThree = Product "Hello World!" 'a'
39− Record
40− { testOne = 9876.54321
41− , testTwo = False
42− , testThree = Product "Yeehaa!!!" '\n' Nullary
43− }
44− }
benchmarks/Auto/T/BigProduct.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−
3−module Auto.T.BigProduct where
4−
5−import Control.DeepSeq
6−import Data.Aeson.TH
7−import Options
8−
9−data BigProduct = BigProduct
10− !Int !Int !Int !Int !Int
11− !Int !Int !Int !Int !Int
12− !Int !Int !Int !Int !Int
13− !Int !Int !Int !Int !Int
14− !Int !Int !Int !Int !Int
15− deriving (Show, Eq)
16−
17−instance NFData BigProduct where
18− rnf a = a `seq` ()
19−
20−deriveJSON opts ''BigProduct
21−
22−bigProduct :: BigProduct
23−bigProduct = BigProduct 1 2 3 4 5
24− 6 7 8 9 10
25− 11 12 13 14 15
26− 16 17 18 19 20
27− 21 22 23 24 25
benchmarks/Auto/T/BigRecord.hsdeleted−27
@@ -1,27 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−
3−module Auto.T.BigRecord where
4−
5−import Control.DeepSeq
6−import Data.Aeson.TH
7−import Options
8−
9−data BigRecord = BigRecord
10− { field01 :: !Int, field02 :: !Int, field03 :: !Int, field04 :: !Int, field05 :: !Int
11− , field06 :: !Int, field07 :: !Int, field08 :: !Int, field09 :: !Int, field10 :: !Int
12− , field11 :: !Int, field12 :: !Int, field13 :: !Int, field14 :: !Int, field15 :: !Int
13− , field16 :: !Int, field17 :: !Int, field18 :: !Int, field19 :: !Int, field20 :: !Int
14− , field21 :: !Int, field22 :: !Int, field23 :: !Int, field24 :: !Int, field25 :: !Int
15− } deriving (Show, Eq)
16−
17−instance NFData BigRecord where
18− rnf a = a `seq` ()
19−
20−deriveJSON opts ''BigRecord
21−
22−bigRecord :: BigRecord
23−bigRecord = BigRecord 1 2 3 4 5
24− 6 7 8 9 10
25− 11 12 13 14 15
26− 16 17 18 19 20
27− 21 22 23 24 25
benchmarks/Auto/T/BigSum.hsdeleted−22
@@ -1,22 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−
3−module Auto.T.BigSum where
4−
5−import Control.DeepSeq
6−import Data.Aeson.TH
7−import Options
8−
9−data BigSum = F01 | F02 | F03 | F04 | F05
10− | F06 | F07 | F08 | F09 | F10
11− | F11 | F12 | F13 | F14 | F15
12− | F16 | F17 | F18 | F19 | F20
13− | F21 | F22 | F23 | F24 | F25
14− deriving (Show, Eq)
15−
16−instance NFData BigSum where
17− rnf a = a `seq` ()
18−
19−deriveJSON opts ''BigSum
20−
21−bigSum :: BigSum
22−bigSum = F25
benchmarks/Auto/T/D.hsdeleted−38
@@ -1,38 +0,0 @@
1−{-# LANGUAGE TemplateHaskell #-}
2−
3−module Auto.T.D where
4−
5−import Control.DeepSeq
6−import Data.Aeson.TH
7−import Options
8−
9−data D a = Nullary
10− | Unary Int
11− | Product String Char a
12− | Record { testOne :: Double
13− , testTwo :: Bool
14− , testThree :: D a
15− }
16− deriving (Show, Eq)
17−
18−instance NFData a => NFData (D a) where
19− rnf Nullary = ()
20− rnf (Unary n) = rnf n
21− rnf (Product s c x) = s `deepseq` c `deepseq` rnf x
22− rnf (Record a b y) = a `deepseq` b `deepseq` rnf y
23−
24−deriveJSON opts ''D
25−
26−type T = D (D (D ()))
27−
28−d :: T
29−d = Record
30− { testOne = 1234.56789
31− , testTwo = True
32− , testThree = Product "Hello World!" 'a'
33− Record
34− { testOne = 9876.54321
35− , testTwo = False
36− , testThree = Product "Yeehaa!!!" '\n' Nullary
37− }
38− }
benchmarks/AutoCompare.hsdeleted−73
@@ -1,73 +0,0 @@
1−{-# LANGUAGE RankNTypes #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3−
4−module Main (main) where
5−
6−import Control.DeepSeq
7−import Control.Monad
8−import Criterion.Main
9−import Data.Aeson
10−
11−import qualified Auto.T.D as T
12−import qualified Auto.T.BigRecord as T
13−import qualified Auto.T.BigProduct as T
14−import qualified Auto.T.BigSum as T
15−import qualified Auto.G.D as G
16−import qualified Auto.G.BigRecord as G
17−import qualified Auto.G.BigProduct as G
18−import qualified Auto.G.BigSum as G
19−
20−--------------------------------------------------------------------------------
21−
22−runBench :: IO ()
23−runBench = defaultMain
24− [ compareBench "D" T.d G.d
25− , compareBench "BigRecord" T.bigRecord G.bigRecord
26− , compareBench "BigProduct" T.bigProduct G.bigProduct
27− , compareBench "BigSum" T.bigSum G.bigSum
28− ]
29−
30−group :: String -> Benchmarkable -> Benchmarkable -> Benchmark
31−group n th gen = bgroup n [ bench "th" th
32− , bench "generic" gen
33− ]
34−
35−compareBench
36− :: forall a b
37− . (ToJSON a, FromJSON a, NFData a, ToJSON b, FromJSON b, NFData b)
38− => String -> a -> b -> Benchmark
39−compareBench name a b = v `deepseq` bgroup name
40− [ group "toJSON" (nf toJSON a)
41− (nf toJSON b)
42− , group "encode" (nf encode a)
43− (nf encode b)
44− , group "fromJSON" (nf (fromJSON :: Value -> Result a) v)
45− (nf (fromJSON :: Value -> Result b) v)
46− ] where
47− v = toJSON a -- == toJSON b
48−
49−sanityCheck :: IO ()
50−sanityCheck = do
51− check T.d
52− check G.d
53− check T.bigRecord
54− check G.bigRecord
55− check T.bigProduct
56− check G.bigProduct
57− check T.bigSum
58− check G.bigSum
59−
60−check :: (Show a, Eq a, FromJSON a, ToJSON a)
61− => a -> IO ()
62−check x = do
63− unless (Success x == (fromJSON . toJSON) x) $ fail $ "toJSON: " ++ show x
64− unless (Success x == (decode_ . encode) x) $ fail $ "encode: " ++ show x
65− where
66− decode_ s = case decode s of
67− Just v -> fromJSON v
68− Nothing -> fail ""
69−
70−main :: IO ()
71−main = do
72− sanityCheck
73− runBench
benchmarks/Compare.hs+3−12
@@ -1,24 +1,17 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3{-# LANGUAGE ScopedTypeVariables #-}
1{-# LANGUAGE ScopedTypeVariables #-}
4
2
5module Main (main) where
3module Main (main) where
6
4
7−import Prelude.Compat
8−
9import Compare.BufferBuilder ()
5import Compare.BufferBuilder ()
6+import Compare.JsonBuilder ()
10import Criterion.Main
7import Criterion.Main
11import Data.BufferBuilder.Json
8import Data.BufferBuilder.Json
9+import Data.Json.Builder
12import Twitter
10import Twitter
13import Twitter.Manual ()
11import Twitter.Manual ()
14import Typed.Common
12import Typed.Common
15−import qualified Data.Aeson as Aeson
16import qualified Compare.JsonBench as JsonBench
13import qualified Compare.JsonBench as JsonBench
17−
14+import qualified Data.Aeson as Aeson
18−#ifdef MIN_VERSION_json_builder
19−import Data.Json.Builder
20−import Compare.JsonBuilder ()
21−#endif
22
15
23main :: IO ()
16main :: IO ()
24main =
17main =
@@ -27,9 +20,7 @@ main =
27 bgroup "twitter" [
20 bgroup "twitter" [
28 bench "aeson" $ nf Aeson.encode twtr
21 bench "aeson" $ nf Aeson.encode twtr
29 , bench "buffer-builder" $ nf encodeJson twtr
22 , bench "buffer-builder" $ nf encodeJson twtr
30−#ifdef MIN_VERSION_json_builder
31 , bench "json-builder" $ nf toJsonLBS twtr
23 , bench "json-builder" $ nf toJsonLBS twtr
32−#endif
33 ]
24 ]
34 , JsonBench.benchmarks
25 , JsonBench.benchmarks
35 ]
26 ]
benchmarks/Compare/BufferBuilder.hs+4−9
@@ -1,17 +1,12 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
4−
5−{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
7
3
8module Compare.BufferBuilder () where
4module Compare.BufferBuilder () where
9
5
10−import Prelude.Compat hiding ((<>))
11−
12import Data.BufferBuilder.Json
6import Data.BufferBuilder.Json
13−import Data.Int (Int64)
14import Data.Monoid ((<>))
7import Data.Monoid ((<>))
8+import Data.Int (Int64)
9+import Prelude hiding (id)
15import Twitter
10import Twitter
16import qualified Data.BufferBuilder.Utf8 as UB
11import qualified Data.BufferBuilder.Utf8 as UB
17
12
@@ -42,7 +37,7 @@ instance ToJson Story where
42 <> "metadata" .= metadata
37 <> "metadata" .= metadata
43 <> "to_user_id" .= to_user_id
38 <> "to_user_id" .= to_user_id
44 <> "text" .= text
39 <> "text" .= text
45− <> "id" .= id_
40+ <> "id" .= id
46 <> "from_user_id" .= from_user_id
41 <> "from_user_id" .= from_user_id
47 <> "geo" .= geo
42 <> "geo" .= geo
48 <> "iso_language_code" .= iso_language_code
43 <> "iso_language_code" .= iso_language_code
benchmarks/Compare/JsonBench.hs+7−21
@@ -1,18 +1,12 @@
1−{-# LANGUAGE CPP #-}
2−{-# LANGUAGE BangPatterns #-}
3−{-# LANGUAGE MagicHash #-}
4−{-# LANGUAGE NoImplicitPrelude #-}
5−{-# LANGUAGE OverloadedStrings #-}
6−{-# LANGUAGE RecordWildCards #-}
7−{-# LANGUAGE ScopedTypeVariables #-}
8−
9-- Adapted from a buffer-builder benchmark:
1-- Adapted from a buffer-builder benchmark:
10--
2--
11-- https://github.com/chadaustin/buffer-builder/blob/master/test.json
3-- https://github.com/chadaustin/buffer-builder/blob/master/test.json
12
4
13−module Compare.JsonBench (benchmarks) where
5+{-# LANGUAGE BangPatterns, OverloadedStrings, RecordWildCards #-}
6+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7+{-# LANGUAGE MagicHash, ScopedTypeVariables #-}
14
8
15−import Prelude.Compat hiding ((<>))
9+module Compare.JsonBench (benchmarks) where
16
10
17import Control.DeepSeq (NFData(..))
11import Control.DeepSeq (NFData(..))
18import Criterion
12import Criterion
@@ -20,13 +14,9 @@ import Data.Aeson ((.:))
20import Data.Monoid ((<>))
14import Data.Monoid ((<>))
21import Data.Text (Text)
15import Data.Text (Text)
22import Typed.Common (load)
16import Typed.Common (load)
23−import qualified Control.Monad.Fail as Fail
24import qualified Data.Aeson as Aeson
17import qualified Data.Aeson as Aeson
25import qualified Data.BufferBuilder.Json as Json
18import qualified Data.BufferBuilder.Json as Json
26−
27−#ifdef MIN_VERSION_json_builder
28import qualified Data.Json.Builder as JB
19import qualified Data.Json.Builder as JB
29−#endif
30
20
31data EyeColor = Green | Blue | Brown
21data EyeColor = Green | Blue | Brown
32 deriving (Eq, Show)
22 deriving (Eq, Show)
@@ -69,10 +59,10 @@ instance NFData Gender where rnf !_ = ()
69instance NFData Fruit where rnf !_ = ()
59instance NFData Fruit where rnf !_ = ()
70
60
71instance NFData Friend where
61instance NFData Friend where
72− rnf Friend {..} = rnf fId `seq` rnf fName
62+ rnf Friend {..} = (rnf fId) `seq` (rnf fName) `seq` ()
73
63
74instance NFData User where
64instance NFData User where
75− rnf User {..} = rnf uId `seq` rnf uIndex `seq` rnf uGuid `seq` rnf uIsActive `seq` rnf uBalance `seq` rnf uPicture `seq` rnf uAge `seq` rnf uEyeColor `seq` rnf uName `seq` rnf uGender `seq` rnf uCompany `seq` rnf uEmail `seq` rnf uPhone `seq` rnf uAddress `seq` rnf uAbout `seq` rnf uRegistered `seq` rnf uLatitude `seq` rnf uLongitude `seq` rnf uTags `seq` rnf uFriends `seq` rnf uGreeting `seq` rnf uFavouriteFruit
65+ rnf User {..} = (rnf uId) `seq` (rnf uIndex) `seq` (rnf uGuid) `seq` (rnf uIsActive) `seq` (rnf uBalance) `seq` (rnf uPicture) `seq` (rnf uAge) `seq` (rnf uEyeColor) `seq` (rnf uName) `seq` (rnf uGender) `seq` (rnf uCompany) `seq` (rnf uEmail) `seq` (rnf uPhone) `seq` (rnf uAddress) `seq` (rnf uAbout) `seq` (rnf uRegistered) `seq` (rnf uLatitude) `seq` (rnf uLongitude) `seq` (rnf uTags) `seq` (rnf uFriends) `seq` (rnf uGreeting) `seq` (rnf uFavouriteFruit) `seq` ()
76
66
77eyeColorTable :: [(Text, EyeColor)]
67eyeColorTable :: [(Text, EyeColor)]
78eyeColorTable = [("brown", Brown), ("green", Green), ("blue", Blue)]
68eyeColorTable = [("brown", Brown), ("green", Green), ("blue", Blue)]
@@ -83,7 +73,7 @@ genderTable = [("male", Male), ("female", Female)]
83fruitTable :: [(Text, Fruit)]
73fruitTable :: [(Text, Fruit)]
84fruitTable = [("apple", Apple), ("strawberry", Strawberry), ("banana", Banana)]
74fruitTable = [("apple", Apple), ("strawberry", Strawberry), ("banana", Banana)]
85
75
86−enumFromJson :: Fail.MonadFail m => String -> [(Text, enum)] -> (json -> m Text) -> json -> m enum
76+enumFromJson :: Monad m => String -> [(Text, enum)] -> (json -> m Text) -> json -> m enum
87enumFromJson enumName table extract v = do
77enumFromJson enumName table extract v = do
88 s <- extract v
78 s <- extract v
89 case lookup s table of
79 case lookup s table of
@@ -273,7 +263,6 @@ instance Json.ToJson User where
273 <> "greeting"# Json..=# uGreeting
263 <> "greeting"# Json..=# uGreeting
274 <> "favoriteFruit"# Json..=# uFavouriteFruit
264 <> "favoriteFruit"# Json..=# uFavouriteFruit
275
265
276−#ifdef MIN_VERSION_json_builder
277---- json-builder instances ----
266---- json-builder instances ----
278
267
279instance JB.Value EyeColor where
268instance JB.Value EyeColor where
@@ -325,7 +314,6 @@ instance JB.Value User where
325 <> t "friends" `JB.row` uFriends
314 <> t "friends" `JB.row` uFriends
326 <> t "greeting" `JB.row` uGreeting
315 <> t "greeting" `JB.row` uGreeting
327 <> t "favoriteFruit" `JB.row` uFavouriteFruit
316 <> t "favoriteFruit" `JB.row` uFavouriteFruit
328−#endif
329
317
330benchmarks :: Benchmark
318benchmarks :: Benchmark
331benchmarks = env (load "json-data/buffer-builder.json") $
319benchmarks = env (load "json-data/buffer-builder.json") $
@@ -333,7 +321,5 @@ benchmarks = env (load "json-data/buffer-builder.json") $
333 bgroup "json-bench" [
321 bgroup "json-bench" [
334 bench "aeson" $ nf Aeson.encode parsedUserList
322 bench "aeson" $ nf Aeson.encode parsedUserList
335 , bench "buffer-builder" $ nf Json.encodeJson parsedUserList
323 , bench "buffer-builder" $ nf Json.encodeJson parsedUserList
336−#ifdef MIN_VERSION_json_builder
337 , bench "json-builder" $ nf JB.toJsonLBS parsedUserList
324 , bench "json-builder" $ nf JB.toJsonLBS parsedUserList
338−#endif
339 ]
325 ]
benchmarks/Compare/JsonBuilder.hs+2−6
@@ -1,15 +1,11 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE RecordWildCards #-}
3−
4−{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
5{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
6
3
7module Compare.JsonBuilder () where
4module Compare.JsonBuilder () where
8
5
9−import Prelude.Compat hiding ((<>))
10−
11import Data.Json.Builder
6import Data.Json.Builder
12import Data.Monoid ((<>))
7import Data.Monoid ((<>))
8+import Prelude hiding (id)
13import Twitter
9import Twitter
14
10
15instance JsObject Metadata where
11instance JsObject Metadata where
@@ -40,7 +36,7 @@ instance JsObject Story where
40 row "metadata" metadata <>
36 row "metadata" metadata <>
41 row "to_user_id" to_user_id <>
37 row "to_user_id" to_user_id <>
42 row "text" text <>
38 row "text" text <>
43− row "id" id_ <>
39+ row "id" id <>
44 row "from_user_id" from_user_id <>
40 row "from_user_id" from_user_id <>
45 row "geo" geo <>
41 row "geo" geo <>
46 row "iso_language_code" iso_language_code <>
42 row "iso_language_code" iso_language_code <>
benchmarks/CompareWithJSON.hs+22−39
@@ -1,25 +1,16 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−
3{-# OPTIONS_GHC -fno-warn-orphans #-}
1{-# OPTIONS_GHC -fno-warn-orphans #-}
4
2
5−module Main (main) where
6−
7−import Prelude.Compat
8−
9import Blaze.ByteString.Builder (toLazyByteString)
3import Blaze.ByteString.Builder (toLazyByteString)
10import Blaze.ByteString.Builder.Char.Utf8 (fromString)
4import Blaze.ByteString.Builder.Char.Utf8 (fromString)
11import Control.DeepSeq (NFData(rnf))
5import Control.DeepSeq (NFData(rnf))
12import Criterion.Main
6import Criterion.Main
13−import Data.Maybe (fromMaybe)
7+import qualified Data.Aeson.Encode as A
14import qualified Data.Aeson as A
8import qualified Data.Aeson as A
15−import qualified Data.Aeson.Text as A
16−import qualified Data.Aeson.Parser.Internal as I
17−import qualified Data.ByteString as BS
18import qualified Data.ByteString.Lazy as BL
9import qualified Data.ByteString.Lazy as BL
10+import qualified Text.JSON as J
19import qualified Data.Text.Lazy as TL
11import qualified Data.Text.Lazy as TL
20import qualified Data.Text.Lazy.Builder as TLB
12import qualified Data.Text.Lazy.Builder as TLB
21import qualified Data.Text.Lazy.Encoding as TLE
13import qualified Data.Text.Lazy.Encoding as TLE
22−import qualified Text.JSON as J
23
14
24instance (NFData v) => NFData (J.JSObject v) where
15instance (NFData v) => NFData (J.JSObject v) where
25 rnf o = rnf (J.fromJSObject o)
16 rnf o = rnf (J.fromJSObject o)
@@ -27,7 +18,7 @@ instance (NFData v) => NFData (J.JSObject v) where
27instance NFData J.JSValue where
18instance NFData J.JSValue where
28 rnf J.JSNull = ()
19 rnf J.JSNull = ()
29 rnf (J.JSBool b) = rnf b
20 rnf (J.JSBool b) = rnf b
30− rnf (J.JSRational a b) = rnf a `seq` rnf b
21+ rnf (J.JSRational a b) = rnf a `seq` rnf b `seq` ()
31 rnf (J.JSString s) = rnf (J.fromJSString s)
22 rnf (J.JSString s) = rnf (J.fromJSString s)
32 rnf (J.JSArray lst) = rnf lst
23 rnf (J.JSArray lst) = rnf lst
33 rnf (J.JSObject o) = rnf o
24 rnf (J.JSObject o) = rnf o
@@ -38,18 +29,15 @@ decodeJ s =
38 J.Ok v -> v
29 J.Ok v -> v
39 J.Error _ -> error "fail to parse via JSON"
30 J.Error _ -> error "fail to parse via JSON"
40
31
41−decode :: BL.ByteString -> A.Value
32+decodeA :: BL.ByteString -> A.Value
42−decode s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
33+decodeA s = case A.decode s of
43−
34+ Just v -> v
44−decode' :: BL.ByteString -> A.Value
35+ Nothing -> error "fail to parse via Aeson"
45−decode' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
46−
47−decodeS :: BS.ByteString -> A.Value
48−decodeS s = fromMaybe (error "fail to parse via Aeson") $ A.decodeStrict' s
49
36
50−decodeIP :: BL.ByteString -> A.Value
37+decodeA' :: BL.ByteString -> A.Value
51−decodeIP s = fromMaybe (error "fail to parse via Parser.decodeWith") $
38+decodeA' s = case A.decode' s of
52− I.decodeWith I.jsonEOF A.fromJSON s
39+ Just v -> v
40+ Nothing -> error "fail to parse via Aeson"
53
41
54encodeJ :: J.JSValue -> BL.ByteString
42encodeJ :: J.JSValue -> BL.ByteString
55encodeJ = toLazyByteString . fromString . J.encode
43encodeJ = toLazyByteString . fromString . J.encode
@@ -65,37 +53,32 @@ main = do
65 let enFile = "json-data/twitter100.json"
53 let enFile = "json-data/twitter100.json"
66 jpFile = "json-data/jp100.json"
54 jpFile = "json-data/jp100.json"
67 enA <- BL.readFile enFile
55 enA <- BL.readFile enFile
68− enS <- BS.readFile enFile
69 enJ <- readFile enFile
56 enJ <- readFile enFile
70 jpA <- BL.readFile jpFile
57 jpA <- BL.readFile jpFile
71− jpS <- BS.readFile jpFile
72 jpJ <- readFile jpFile
58 jpJ <- readFile jpFile
73 defaultMain [
59 defaultMain [
74 bgroup "decode" [
60 bgroup "decode" [
75 bgroup "en" [
61 bgroup "en" [
76− bench "aeson/lazy" $ nf decode enA
62+ bench "aeson/lazy" $ nf decodeA enA
77− , bench "aeson/strict" $ nf decode' enA
63+ , bench "aeson/strict" $ nf decodeA' enA
78− , bench "aeson/stricter" $ nf decodeS enS
64+ , bench "json" $ nf decodeJ enJ
79− , bench "aeson/parser" $ nf decodeIP enA
80− , bench "json" $ nf decodeJ enJ
81 ]
65 ]
82 , bgroup "jp" [
66 , bgroup "jp" [
83− bench "aeson" $ nf decode jpA
67+ bench "aeson" $ nf decodeA jpA
84− , bench "aeson/stricter" $ nf decodeS jpS
68+ , bench "json" $ nf decodeJ jpJ
85− , bench "json" $ nf decodeJ jpJ
86 ]
69 ]
87 ]
70 ]
88 , bgroup "encode" [
71 , bgroup "encode" [
89 bgroup "en" [
72 bgroup "en" [
90− bench "aeson-to-bytestring" $ nf A.encode (decode enA)
73+ bench "aeson-to-bytestring" $ nf A.encode (decodeA enA)
91− , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decode enA)
74+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA enA)
92− , bench "aeson-to-text" $ nf encodeToText (decode enA)
75+ , bench "aeson-to-text" $ nf encodeToText (decodeA enA)
93 , bench "json" $ nf encodeJ (decodeJ enJ)
76 , bench "json" $ nf encodeJ (decodeJ enJ)
94 ]
77 ]
95 , bgroup "jp" [
78 , bgroup "jp" [
96− bench "aeson-to-bytestring" $ nf A.encode (decode jpA)
79+ bench "aeson-to-bytestring" $ nf A.encode (decodeA jpA)
97− , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decode jpA)
80+ , bench "aeson-via-text-to-bytestring" $ nf encodeViaText (decodeA jpA)
98− , bench "aeson-to-text" $ nf encodeToText (decode jpA)
81+ , bench "aeson-to-text" $ nf encodeToText (decodeA jpA)
99 , bench "json" $ nf encodeJ (decodeJ jpJ)
82 , bench "json" $ nf encodeJ (decodeJ jpJ)
100 ]
83 ]
101 ]
84 ]
benchmarks/Dates.hs+9−14
@@ -1,9 +1,4 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+import Control.Applicative ((<$>))
2−
3−module Main (main) where
4−
5−import Prelude.Compat
6−
7import Criterion.Main
2import Criterion.Main
8import Data.Aeson (decode, encode)
3import Data.Aeson (decode, encode)
9import Data.Time.Clock (UTCTime)
4import Data.Time.Clock (UTCTime)
@@ -23,22 +18,22 @@ main = do
23 defaultMain [
18 defaultMain [
24 bgroup "decode" [
19 bgroup "decode" [
25 bgroup "UTCTime" [
20 bgroup "UTCTime" [
26− env file1 $ \bs -> bench "whole" $ nf utcTime bs
21+ env file1 $ \ ~bs -> bench "whole" $ nf utcTime bs
27− , env file2 $ \bs -> bench "fractional" $ nf utcTime bs
22+ , env file2 $ \ ~bs -> bench "fractional" $ nf utcTime bs
28 ]
23 ]
29 , bgroup "ZonedTime" [
24 , bgroup "ZonedTime" [
30− env file1 $ \bs -> bench "whole" $ nf zTime bs
25+ env file1 $ \ ~bs -> bench "whole" $ nf zTime bs
31− , env file2 $ \bs -> bench "fractional" $ nf zTime bs
26+ , env file2 $ \ ~bs -> bench "fractional" $ nf zTime bs
32 ]
27 ]
33 ]
28 ]
34 , bgroup "encode" [
29 , bgroup "encode" [
35 bgroup "UTCTime" [
30 bgroup "UTCTime" [
36− env (utcTime <$> file1) $ \ts -> bench "whole" $ nf encode ts
31+ env (utcTime <$> file1) $ \ ~ts -> bench "whole" $ nf encode ts
37− , env (utcTime <$> file2) $ \ts -> bench "fractional" $ nf encode ts
32+ , env (utcTime <$> file2) $ \ ~ts -> bench "fractional" $ nf encode ts
38 ]
33 ]
39 , bgroup "ZonedTime" [
34 , bgroup "ZonedTime" [
40− env (zTime <$> file1) $ \ts -> bench "whole" $ nf encode ts
35+ env (zTime <$> file1) $ \ ~ts -> bench "whole" $ nf encode ts
41− , env (zTime <$> file2) $ \ts -> bench "fractional" $ nf encode ts
36+ , env (zTime <$> file2) $ \ ~ts -> bench "fractional" $ nf encode ts
42 ]
37 ]
43 ]
38 ]
44 ]
39 ]
benchmarks/Escape.hsdeleted−32
@@ -1,32 +0,0 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3−
4−{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
5−
6−module Main (main) where
7−
8−import Prelude.Compat
9−
10−import Criterion.Main
11−import qualified Data.Aeson.Parser.UnescapeFFI as FFI
12−import qualified Data.Aeson.Parser.UnescapePure as Pure
13−
14−import qualified Data.ByteString.Char8 as BS
15−import System.Environment (getArgs, withArgs)
16−
17−main :: IO ()
18−main = do
19− args_ <- getArgs
20− let (args, p, n) =
21− case args_ of
22− "--pattern" : p : args_ -> k p args_
23− _ -> k "\\\"" args_
24− k p args_ =
25− case args_ of
26− "--repeat" : n : args_ -> (args_, p, read n)
27− args_ -> (args_, p, 10000)
28− input = BS.concat $ replicate n $ BS.pack p
29− withArgs args $ defaultMain
30− [ bench "ffi" $ whnf FFI.unescapeText input
31− , bench "pure" $ whnf Pure.unescapeText input
32− ]
benchmarks/Issue673.hsdeleted−165
@@ -1,165 +0,0 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−
4−module Main (
5− main,
6− input17,
7− input32,
8− input64,
9− input128,
10− input256,
11− input2048,
12− input4096,
13− input8192,
14− input16384,
15− ) where
16−
17−import Criterion.Main
18−import Prelude.Compat
19−import Data.Int (Int64)
20−import Data.Scientific (Scientific)
21−import Data.Semigroup ((<>))
22−import Data.Aeson.Parser (scientific)
23−
24−import qualified Data.Attoparsec.ByteString.Lazy as AttoL
25−import qualified Data.Attoparsec.ByteString.Char8 as Atto8
26−import qualified Data.Aeson as A
27−import qualified Data.ByteString as BS
28−import qualified Data.ByteString.Lazy as LBS
29−import qualified Data.ByteString.Lazy.Char8 as LBS8
30−
31−decodeInt :: LBS.ByteString -> Maybe Int
32−decodeInt = A.decode
33−
34−decodeString :: LBS.ByteString -> Maybe String
35−decodeString = A.decode
36−
37−decodeScientific :: LBS.ByteString -> Maybe Scientific
38−decodeScientific = A.decode
39−
40−decodeViaRead :: LBS.ByteString -> Integer
41−decodeViaRead = read . LBS8.unpack
42−
43−decodeAtto :: LBS.ByteString -> Maybe Scientific
44−decodeAtto
45− = parseOnly (scientific <* AttoL.endOfInput)
46− where
47− parseOnly p lbs = case AttoL.parse p lbs of
48− AttoL.Done _ r -> Just r
49− AttoL.Fail {} -> Nothing
50−
51−decodeAtto8 :: LBS.ByteString -> Maybe Scientific
52−decodeAtto8
53− = parseOnly (Atto8.scientific <* AttoL.endOfInput)
54− where
55− parseOnly p lbs = case AttoL.parse p lbs of
56− AttoL.Done _ r -> Just r
57− AttoL.Fail {} -> Nothing
58−
59−generate :: Int64 -> LBS.ByteString
60−generate n = LBS8.replicate n '1'
61−
62−input17 :: LBS.ByteString
63−input17 = generate 17
64−
65−input32 :: LBS.ByteString
66−input32 = generate 32
67−
68−input64 :: LBS.ByteString
69−input64 = generate 64
70−
71−input128 :: LBS.ByteString
72−input128 = generate 128
73−
74−input256 :: LBS.ByteString
75−input256 = generate 256
76−
77−input2048 :: LBS.ByteString
78−input2048 = generate 2048
79−
80−input4096 :: LBS.ByteString
81−input4096 = generate 4096
82−
83−input8192 :: LBS.ByteString
84−input8192 = generate 8192
85−
86−input16384 :: LBS.ByteString
87−input16384 = generate 16384
88−
89−
90−main :: IO ()
91−main = defaultMain
92− -- works on 64bit
93− [ benchPair "17" input17
94− -- , benchPair "32" input32
95− -- , benchPair "64" input64
96− -- , benchPair "128" input128
97− -- , benchPair "256" input256
98− , benchPair "2048" input2048
99− , benchPair "4096" input4096
100− , benchPair "8192" input8192
101− , benchPair "16384" input16384
102− ]
103− where
104− benchPair name input = bgroup name
105− [ bench "Int" $ whnf decodeInt input
106− , bench "Simple" $ whnf bsToIntegerSimple (LBS.toStrict input)
107− , bench "Optim" $ whnf bsToInteger (LBS.toStrict input)
108− , bench "Read" $ whnf decodeViaRead input
109− , bench "Scientific" $ whnf decodeScientific input
110− , bench "parserA" $ whnf decodeAtto input
111− , bench "parserS" $ whnf decodeAtto8 input
112− , bench "String" $ whnf decodeString $ "\"" <> input <> "\""
113− ]
114−
115−-------------------------------------------------------------------------------
116−-- better fromInteger
117−-------------------------------------------------------------------------------
118−
119−bsToInteger :: BS.ByteString -> Integer
120−bsToInteger bs
121− | l > 40 = valInteger 10 l [ fromIntegral (w - 48) | w <- BS.unpack bs ]
122− | otherwise = bsToIntegerSimple bs
123− where
124− l = BS.length bs
125−
126−bsToIntegerSimple :: BS.ByteString -> Integer
127−bsToIntegerSimple = BS.foldl' step 0 where
128− step a b = a * 10 + fromIntegral (b - 48) -- 48 = '0'
129−
130−-- A sub-quadratic algorithm for Integer. Pairs of adjacent radix b
131−-- digits are combined into a single radix b^2 digit. This process is
132−-- repeated until we are left with a single digit. This algorithm
133−-- performs well only on large inputs, so we use the simple algorithm
134−-- for smaller inputs.
135−valInteger :: Integer -> Int -> [Integer] -> Integer
136−valInteger = go
137− where
138− go :: Integer -> Int -> [Integer] -> Integer
139− go _ _ [] = 0
140− go _ _ [d] = d
141− go b l ds
142− | l > 40 = b' `seq` go b' l' (combine b ds')
143− | otherwise = valSimple b ds
144− where
145− -- ensure that we have an even number of digits
146− -- before we call combine:
147− ds' = if even l then ds else 0 : ds
148− b' = b * b
149− l' = (l + 1) `quot` 2
150−
151− combine b (d1 : d2 : ds) = d `seq` (d : combine b ds)
152− where
153− d = d1 * b + d2
154− combine _ [] = []
155− combine _ [_] = errorWithoutStackTrace "this should not happen"
156−
157−-- The following algorithm is only linear for types whose Num operations
158−-- are in constant time.
159−valSimple :: Integer -> [Integer] -> Integer
160−valSimple base = go 0
161− where
162− go r [] = r
163− go r (d : ds) = r' `seq` go r' ds
164− where
165− r' = r * base + fromIntegral d
benchmarks/JsonParse.hs+3−10
@@ -1,23 +1,16 @@
1−{-# LANGUAGE BangPatterns #-}
1+{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−
5{-# OPTIONS_GHC -fno-warn-orphans #-}
2{-# OPTIONS_GHC -fno-warn-orphans #-}
6
3
7−module Main (main) where
8−
9−import Prelude.Compat
10−
11import Control.DeepSeq
4import Control.DeepSeq
12import Control.Monad
5import Control.Monad
6+import Text.JSON
13import Data.Time.Clock
7import Data.Time.Clock
14import System.Environment (getArgs)
8import System.Environment (getArgs)
15−import Text.JSON
16
9
17instance NFData JSValue where
10instance NFData JSValue where
18 rnf JSNull = ()
11 rnf JSNull = ()
19 rnf (JSBool b) = rnf b
12 rnf (JSBool b) = rnf b
20− rnf (JSRational b r) = rnf b `seq` rnf r
13+ rnf (JSRational b r) = rnf b `seq` rnf r `seq` ()
21 rnf (JSString s) = rnf (fromJSString s)
14 rnf (JSString s) = rnf (fromJSString s)
22 rnf (JSArray vs) = rnf vs
15 rnf (JSArray vs) = rnf vs
23 rnf (JSObject kvs) = rnf (fromJSObject kvs)
16 rnf (JSObject kvs) = rnf (fromJSObject kvs)
benchmarks/Micro.hs+6−10
@@ -1,22 +1,18 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−
3module Main (main) where
1module Main (main) where
4
2
5−import Prelude.Compat
6−
7import Criterion.Main
3import Criterion.Main
8−
4+import qualified Data.Aeson.Encode.Builder as AB
9−-- Encoding is a newtype wrapper around Builder
5+import qualified Data.ByteString.Builder as B
10−import Data.Aeson.Encoding (text, string, encodingToLazyByteString)
11import qualified Data.Text as T
6import qualified Data.Text as T
12
7
8+
13main :: IO ()
9main :: IO ()
14main = do
10main = do
15 let txt = "append (append b (primBounded w1 x1)) (primBounded w2 x2)"
11 let txt = "append (append b (primBounded w1 x1)) (primBounded w2 x2)"
16 defaultMain [
12 defaultMain [
17 bgroup "string" [
13 bgroup "string" [
18− bench "text" $ nf (encodingToLazyByteString . text) (T.pack txt)
14+ bench "text" $ nf (B.toLazyByteString . AB.text) (T.pack txt)
19− , bench "string direct" $ nf (encodingToLazyByteString . string) txt
15+ , bench "string direct" $ nf (B.toLazyByteString . AB.string) txt
20− , bench "string via text" $ nf (encodingToLazyByteString . text . T.pack) txt
16+ , bench "string via text" $ nf (B.toLazyByteString . AB.text . T.pack) txt
21 ]
17 ]
22 ]
18 ]
benchmarks/Options.hs+1−1
@@ -1,4 +1,4 @@
1−module Options (opts) where
1+module Options where
2
2
3import Data.Aeson.Types
3import Data.Aeson.Types
4
4
benchmarks/ReadFile.hs+2−8
@@ -1,10 +1,4 @@
1−{-# LANGUAGE BangPatterns #-}
1+{-# LANGUAGE BangPatterns, OverloadedStrings #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−
5−module Main (main) where
6−
7−import Prelude.Compat
8
2
9import Control.DeepSeq
3import Control.DeepSeq
10import Control.Exception
4import Control.Exception
@@ -20,7 +14,7 @@ import qualified Data.ByteString as B
20main = do
14main = do
21 (cnt:args) <- getArgs
15 (cnt:args) <- getArgs
22 let count = read cnt :: Int
16 let count = read cnt :: Int
23− forM_ args $ \arg -> withFile arg ReadMode $ \h -> do
17+ forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do
24 putStrLn $ arg ++ ":"
18 putStrLn $ arg ++ ":"
25 start <- getCurrentTime
19 start <- getCurrentTime
26 let loop !n
20 let loop !n
benchmarks/Typed.hs−7
@@ -1,9 +1,5 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−
3module Main (main) where
1module Main (main) where
4
2
5−import Prelude.Compat
6−
7import Criterion.Main
3import Criterion.Main
8import qualified Typed.Generic as Generic
4import qualified Typed.Generic as Generic
9import qualified Typed.Manual as Manual
5import qualified Typed.Manual as Manual
@@ -14,7 +10,4 @@ main = defaultMain [
14 Generic.benchmarks
10 Generic.benchmarks
15 , Manual.benchmarks
11 , Manual.benchmarks
16 , TH.benchmarks
12 , TH.benchmarks
17− , Generic.decodeBenchmarks
18− , Manual.decodeBenchmarks
19− , TH.decodeBenchmarks
20 ]
13 ]
benchmarks/Typed/Common.hs+3−9
@@ -1,16 +1,10 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−
3−{-# OPTIONS_GHC -fno-warn-unused-imports #-}
4−
5module Typed.Common (load) where
1module Typed.Common (load) where
6
2
7−import Prelude.Compat
3+import Data.Aeson hiding (Result)
8−
9import Data.ByteString.Lazy as L
4import Data.ByteString.Lazy as L
10−import System.Exit
5+import Control.Applicative
11import System.IO
6import System.IO
12−
7+import System.Exit
13−import Data.Aeson hiding (Result)
14
8
15load :: FromJSON a => FilePath -> IO a
9load :: FromJSON a => FilePath -> IO a
16load fileName = do
10load fileName = do
benchmarks/Typed/Generic.hs+8−23
@@ -1,13 +1,11 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+module Typed.Generic (benchmarks) where
2
2
3−module Typed.Generic (benchmarks, decodeBenchmarks) where
3+import Control.Applicative
4−
5−import Prelude.Compat
6−
7−import Data.Aeson hiding (Result)
8import Criterion
4import Criterion
5+import Data.Aeson hiding (Result)
6+import Data.ByteString.Builder as B
9import Data.ByteString.Lazy as L
7import Data.ByteString.Lazy as L
10−import Twitter.Generic
8+import Twitter.TH
11import Typed.Common
9import Typed.Common
12
10
13encodeDirect :: Result -> L.ByteString
11encodeDirect :: Result -> L.ByteString
@@ -19,26 +17,13 @@ encodeViaValue = encode . toJSON
19benchmarks :: Benchmark
17benchmarks :: Benchmark
20benchmarks =
18benchmarks =
21 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
19 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
22− bgroup "encodeGeneric" [
20+ bgroup "generic" [
23 bgroup "direct" [
21 bgroup "direct" [
24 bench "twitter100" $ nf encodeDirect twitter100
22 bench "twitter100" $ nf encodeDirect twitter100
25− , bench "jp100" $ nf encodeDirect jp100
23+ , bench "jp100" $ nf encodeDirect jp100
26 ]
24 ]
27 , bgroup "viaValue" [
25 , bgroup "viaValue" [
28 bench "twitter100" $ nf encodeViaValue twitter100
26 bench "twitter100" $ nf encodeViaValue twitter100
29− , bench "jp100" $ nf encodeViaValue jp100
27+ , bench "jp100" $ nf encodeViaValue jp100
30− ]
31− ]
32−
33−decodeDirect :: L.ByteString -> Maybe Result
34−decodeDirect = decode
35−
36−decodeBenchmarks :: Benchmark
37−decodeBenchmarks =
38− env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
39− bgroup "decodeGeneric"
40− [ bgroup "direct"
41− [ bench "twitter100" $ nf decodeDirect twitter100
42− , bench "jp100" $ nf decodeDirect jp100
43 ]
28 ]
44 ]
29 ]
benchmarks/Typed/Manual.hs+7−22
@@ -1,11 +1,9 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+module Typed.Manual (benchmarks) where
2
2
3−module Typed.Manual (benchmarks, decodeBenchmarks) where
3+import Control.Applicative
4−
5−import Prelude.Compat
6−
7−import Data.Aeson hiding (Result)
8import Criterion
4import Criterion
5+import Data.Aeson hiding (Result)
6+import Data.ByteString.Builder as B
9import Data.ByteString.Lazy as L
7import Data.ByteString.Lazy as L
10import Twitter.Manual
8import Twitter.Manual
11import Typed.Common
9import Typed.Common
@@ -19,26 +17,13 @@ encodeViaValue = encode . toJSON
19benchmarks :: Benchmark
17benchmarks :: Benchmark
20benchmarks =
18benchmarks =
21 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
19 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
22− bgroup "encodeManual" [
20+ bgroup "manual" [
23 bgroup "direct" [
21 bgroup "direct" [
24 bench "twitter100" $ nf encodeDirect twitter100
22 bench "twitter100" $ nf encodeDirect twitter100
25− , bench "jp100" $ nf encodeDirect jp100
23+ , bench "jp100" $ nf encodeDirect jp100
26 ]
24 ]
27 , bgroup "viaValue" [
25 , bgroup "viaValue" [
28 bench "twitter100" $ nf encodeViaValue twitter100
26 bench "twitter100" $ nf encodeViaValue twitter100
29− , bench "jp100" $ nf encodeViaValue jp100
27+ , bench "jp100" $ nf encodeViaValue jp100
30− ]
31− ]
32−
33−decodeDirect :: L.ByteString -> Maybe Result
34−decodeDirect = decode
35−
36−decodeBenchmarks :: Benchmark
37−decodeBenchmarks =
38− env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
39− bgroup "decodeManual"
40− [ bgroup "direct"
41− [ bench "twitter100" $ nf decodeDirect twitter100
42− , bench "jp100" $ nf decodeDirect jp100
43 ]
28 ]
44 ]
29 ]
benchmarks/Typed/TH.hs+7−22
@@ -1,11 +1,9 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+module Typed.TH (benchmarks) where
2
2
3−module Typed.TH (benchmarks, decodeBenchmarks) where
3+import Control.Applicative
4−
5−import Prelude.Compat
6−
7−import Data.Aeson hiding (Result)
8import Criterion
4import Criterion
5+import Data.Aeson hiding (Result)
6+import Data.ByteString.Builder as B
9import Data.ByteString.Lazy as L
7import Data.ByteString.Lazy as L
10import Twitter.TH
8import Twitter.TH
11import Typed.Common
9import Typed.Common
@@ -19,26 +17,13 @@ encodeViaValue = encode . toJSON
19benchmarks :: Benchmark
17benchmarks :: Benchmark
20benchmarks =
18benchmarks =
21 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
19 env ((,) <$> load "json-data/twitter100.json" <*> load "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
22− bgroup "encodeTH" [
20+ bgroup "th" [
23 bgroup "direct" [
21 bgroup "direct" [
24 bench "twitter100" $ nf encodeDirect twitter100
22 bench "twitter100" $ nf encodeDirect twitter100
25− , bench "jp100" $ nf encodeDirect jp100
23+ , bench "jp100" $ nf encodeDirect jp100
26 ]
24 ]
27 , bgroup "viaValue" [
25 , bgroup "viaValue" [
28 bench "twitter100" $ nf encodeViaValue twitter100
26 bench "twitter100" $ nf encodeViaValue twitter100
29− , bench "jp100" $ nf encodeViaValue jp100
27+ , bench "jp100" $ nf encodeViaValue jp100
30− ]
31− ]
32−
33−decodeDirect :: L.ByteString -> Maybe Result
34−decodeDirect = decode
35−
36−decodeBenchmarks :: Benchmark
37−decodeBenchmarks =
38− env ((,) <$> L.readFile "json-data/twitter100.json" <*> L.readFile "json-data/jp100.json") $ \ ~(twitter100, jp100) ->
39− bgroup "decodeTH"
40− [ bgroup "direct"
41− [ bench "twitter100" $ nf decodeDirect twitter100
42− , bench "jp100" $ nf decodeDirect jp100
43 ]
28 ]
44 ]
29 ]
benchmarks/aeson-benchmarks.cabal+59−226
@@ -1,193 +1,90 @@
1name: aeson-benchmarks
1name: aeson-benchmarks
2version: 0
2version: 0
3build-type: Simple
3build-type: Simple
4−cabal-version: >=1.10
5
4
6−flag bytestring-builder
5+cabal-version: >=1.8
7− description: Depend on the bytestring-builder package for backwards compatibility.
8− default: False
9− manual: False
10−
11−flag local-aeson
12− description: Build the local version of aeson, to avoid rebuilding aeson's
13− reverse dependencies for benchmarking (statistics, criterion).
14− default: True
15− manual: True
16
6
17library
7library
18− default-language: Haskell2010
8+ hs-source-dirs: .. .
19−
9+
20− if flag(bytestring-builder)
10+ exposed-modules:
21− build-depends: bytestring >= 0.9 && < 0.10.4,
11+ Data.Aeson
22− bytestring-builder >= 0.10.4 && < 1
12+ Data.Aeson.Encode
23− else
13+ Data.Aeson.Encoding
24− build-depends: bytestring >= 0.10.4
14+ Data.Aeson.Encoding.Internal
25−
15+ Data.Aeson.Internal
26− if flag(local-aeson)
16+ Data.Aeson.Internal.Time
27−
17+ Data.Aeson.Parser
28− hs-source-dirs: .. ../ffi ../pure ../attoparsec-iso8601
18+ Data.Aeson.Types
29− c-sources: ../cbits/unescape_string.c
19+ Data.Aeson.TH
30− build-depends:
20+
31− attoparsec,
21+ Data.Aeson.Encode.Builder
32− base,
22+ Data.Aeson.Functions
33− base-compat,
23+ Data.Aeson.Parser.Internal
34− containers,
24+ Data.Aeson.Parser.Time
35− deepseq,
25+ Data.Aeson.Types.FromJSON
36− dlist,
26+ Data.Aeson.Types.Generic
37− fail,
27+ Data.Aeson.Types.ToJSON
38− ghc-prim,
28+ Data.Aeson.Types.Class
39− hashable,
29+ Data.Aeson.Types.Internal
40− mtl,
41− primitive,
42− scientific,
43− syb,
44− tagged,
45− template-haskell,
46− text,
47− th-abstraction,
48− time-compat,
49− time,
50− transformers,
51− unordered-containers,
52− uuid-types,
53− vector
54−
55− if !impl(ghc >= 8.6)
56− build-depends: contravariant
57−
58− if !impl(ghc >= 8.0)
59− -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9
60− build-depends: semigroups,
61− transformers-compat
62−
63− if !impl(ghc >= 7.10)
64− -- `Numeric.Natural` is available in base only since GHC 7.10 / base 4.8
65− build-depends: nats,
66− void
67−
68− include-dirs: ../include
69−
70− ghc-options: -O2 -Wall
71− cpp-options: -DGENERICS
72−
73− exposed-modules:
74− Data.Aeson
75− Data.Aeson.Encoding
76− Data.Aeson.Encoding.Builder
77− Data.Aeson.Encoding.Internal
78− Data.Aeson.Internal
79− Data.Aeson.Internal.Functions
80− Data.Aeson.Internal.Time
81− Data.Aeson.Parser
82− Data.Aeson.Parser.Internal
83− Data.Aeson.Parser.Time
84− Data.Aeson.Parser.Unescape
85− Data.Aeson.Parser.UnescapeFFI
86− Data.Aeson.Parser.UnescapePure
87− Data.Aeson.TH
88− Data.Aeson.Text
89− Data.Aeson.Types
90− Data.Aeson.Types.Class
91− Data.Aeson.Types.FromJSON
92− Data.Aeson.Types.Generic
93− Data.Aeson.Types.Internal
94− Data.Aeson.Types.ToJSON
95− Data.Attoparsec.Time
96− Data.Attoparsec.Time.Internal
97−
98− else
99
30
100− build-depends: aeson
101−
102− reexported-modules:
103− Data.Aeson,
104− Data.Aeson.Encoding,
105− Data.Aeson.Parser.Internal,
106− Data.Aeson.Text,
107− Data.Aeson.TH,
108− Data.Aeson.Types
109−
110−executable aeson-benchmark-auto-compare
111− default-language: Haskell2010
112− main-is: AutoCompare.hs
113− hs-source-dirs: .
114− ghc-options: -Wall -O2 -rtsopts
115− other-modules:
116− Auto.T.D
117− Auto.T.BigRecord
118− Auto.T.BigProduct
119− Auto.T.BigSum
120− Auto.G.D
121− Auto.G.BigRecord
122− Auto.G.BigProduct
123− Auto.G.BigSum
124− Options
125 build-depends:
31 build-depends:
126− aeson-benchmarks,
32+ attoparsec >= 0.13.0.1,
127− base,
33+ base == 4.*,
128− criterion,
34+ base-compat >= 0.9.1 && <0.10,
35+ time-locale-compat >=0.1.1 && <0.2,
36+ bytestring >= 0.10.4.0,
37+ containers,
129 deepseq,
38 deepseq,
130− template-haskell
39+ dlist >= 0.2,
131−
40+ fail == 4.9.*,
132−executable aeson-benchmark-escape
41+ ghc-prim >= 0.2,
133− default-language: Haskell2010
42+ hashable >= 1.1.2.0,
134− main-is: Escape.hs
43+ mtl,
135− hs-source-dirs: ../examples .
44+ scientific >= 0.3.1 && < 0.4,
136− ghc-options: -Wall -O2 -rtsopts
45+ syb,
137− if flag(local-aeson)
46+ tagged >=0.8.3 && <0.9,
138− build-depends:
47+ template-haskell >= 2.4,
139− aeson-benchmarks,
48+ text >= 1.1.1.0,
140− base,
49+ time,
141− base-compat,
50+ transformers,
142− bytestring,
51+ unordered-containers >= 0.2.3.0,
143− criterion >= 1.0,
52+ vector >= 0.7.1
144− deepseq,
53+
145− ghc-prim,
54+ if impl(ghc >=7.8)
146− text
55+ cpp-options: -DHAS_COERCIBLE
147− else
56+
148− -- Disabled because of inaccessible internals
57+ if !impl(ghc >= 8.0)
149− buildable: False
58+ -- `Data.Semigroup` is available in base only since GHC 8.0 / base 4.9
59+ build-depends: semigroups >= 0.16.1 && < 0.19
60+
61+ include-dirs: ../include
62+
63+ ghc-options: -O2 -Wall
64+ cpp-options: -DGENERICS
150
65
151executable aeson-benchmark-compare
66executable aeson-benchmark-compare
152− default-language: Haskell2010
153 main-is: Compare.hs
67 main-is: Compare.hs
154 hs-source-dirs: ../examples .
68 hs-source-dirs: ../examples .
155 ghc-options: -Wall -O2 -rtsopts
69 ghc-options: -Wall -O2 -rtsopts
156− other-modules:
157− Compare.BufferBuilder
158− Compare.JsonBench
159− Twitter
160− Twitter.Manual
161− Typed.Common
162 build-depends:
70 build-depends:
163 aeson-benchmarks,
71 aeson-benchmarks,
164 base,
72 base,
165− base-compat,
166 buffer-builder,
73 buffer-builder,
167 bytestring,
74 bytestring,
168 criterion >= 1.0,
75 criterion >= 1.0,
169 deepseq,
76 deepseq,
170 ghc-prim,
77 ghc-prim,
78+ json-builder,
171 text
79 text
172
80
173− if impl(ghc < 8.4)
174− other-modules:
175− Compare.JsonBuilder
176− build-depends:
177− json-builder
178− if impl(ghc < 8.0)
179− build-depends:
180− semigroups
181−
182executable aeson-benchmark-micro
81executable aeson-benchmark-micro
183− default-language: Haskell2010
184 main-is: Micro.hs
82 main-is: Micro.hs
185 hs-source-dirs: ../examples .
83 hs-source-dirs: ../examples .
186 ghc-options: -Wall -O2 -rtsopts
84 ghc-options: -Wall -O2 -rtsopts
187 build-depends:
85 build-depends:
188 aeson-benchmarks,
86 aeson-benchmarks,
189 base,
87 base,
190− base-compat,
191 bytestring,
88 bytestring,
192 criterion >= 1.0,
89 criterion >= 1.0,
193 deepseq,
90 deepseq,
@@ -195,46 +92,25 @@ executable aeson-benchmark-micro
195 text
92 text
196
93
197executable aeson-benchmark-typed
94executable aeson-benchmark-typed
198− default-language: Haskell2010
199 main-is: Typed.hs
95 main-is: Typed.hs
200 hs-source-dirs: ../examples .
96 hs-source-dirs: ../examples .
201 ghc-options: -Wall -O2 -rtsopts
97 ghc-options: -Wall -O2 -rtsopts
202− other-modules:
203− Twitter
204− Twitter.Generic
205− Twitter.Manual
206− Twitter.Options
207− Twitter.TH
208− Typed.Common
209− Typed.Generic
210− Typed.Manual
211− Typed.TH
212 build-depends:
98 build-depends:
213 aeson-benchmarks,
99 aeson-benchmarks,
214 base,
100 base,
215− base-compat,
101+ bytestring,
216 criterion >= 1.0,
102 criterion >= 1.0,
217 deepseq,
103 deepseq,
218 ghc-prim,
104 ghc-prim,
219 text,
105 text,
220 time
106 time
221
107
222− if flag(bytestring-builder)
223− build-depends: bytestring >= 0.9 && < 0.10.4,
224− bytestring-builder >= 0.10.4 && < 1
225− else
226− build-depends: bytestring >= 0.10.4
227− if impl(ghc < 8.0)
228− build-depends: semigroups
229−
230executable aeson-benchmark-compare-with-json
108executable aeson-benchmark-compare-with-json
231− default-language: Haskell2010
232 main-is: CompareWithJSON.hs
109 main-is: CompareWithJSON.hs
233 ghc-options: -Wall -O2 -rtsopts
110 ghc-options: -Wall -O2 -rtsopts
234 build-depends:
111 build-depends:
235 aeson-benchmarks,
112 aeson-benchmarks,
236 base,
113 base,
237− base-compat,
238 blaze-builder,
114 blaze-builder,
239 bytestring,
115 bytestring,
240 criterion,
116 criterion,
@@ -243,65 +119,53 @@ executable aeson-benchmark-compare-with-json
243 text
119 text
244
120
245executable aeson-benchmark-aeson-encode
121executable aeson-benchmark-aeson-encode
246− default-language: Haskell2010
247 main-is: AesonEncode.hs
122 main-is: AesonEncode.hs
248 ghc-options: -Wall -O2 -rtsopts
123 ghc-options: -Wall -O2 -rtsopts
249 build-depends:
124 build-depends:
250 aeson-benchmarks,
125 aeson-benchmarks,
251 attoparsec,
126 attoparsec,
252 base,
127 base,
253− base-compat,
254 bytestring,
128 bytestring,
255 deepseq,
129 deepseq,
256 time
130 time
257
131
258executable aeson-benchmark-aeson-parse
132executable aeson-benchmark-aeson-parse
259− default-language: Haskell2010
260 main-is: AesonParse.hs
133 main-is: AesonParse.hs
261 ghc-options: -Wall -O2 -rtsopts
134 ghc-options: -Wall -O2 -rtsopts
262 build-depends:
135 build-depends:
263 aeson-benchmarks,
136 aeson-benchmarks,
264 attoparsec,
137 attoparsec,
265 base,
138 base,
266− base-compat,
267 bytestring,
139 bytestring,
268 time
140 time
269
141
270executable aeson-benchmark-json-parse
142executable aeson-benchmark-json-parse
271− default-language: Haskell2010
272 main-is: JsonParse.hs
143 main-is: JsonParse.hs
273 ghc-options: -Wall -O2 -rtsopts
144 ghc-options: -Wall -O2 -rtsopts
274 build-depends:
145 build-depends:
275 base,
146 base,
276− base-compat,
277 deepseq,
147 deepseq,
278 json,
148 json,
279 time
149 time
280
150
281executable aeson-benchmark-dates
151executable aeson-benchmark-dates
282− default-language: Haskell2010
283 main-is: Dates.hs
152 main-is: Dates.hs
284 ghc-options: -Wall -O2 -rtsopts
153 ghc-options: -Wall -O2 -rtsopts
285 build-depends:
154 build-depends:
286 base,
155 base,
287− base-compat,
288 bytestring,
156 bytestring,
289 criterion,
157 criterion,
290 deepseq,
158 deepseq,
291 aeson-benchmarks,
159 aeson-benchmarks,
292 text,
160 text,
293 time
161 time
294− if impl(ghc >= 8.2)
295− ghc-options: -Wno-simplifiable-class-constraints
296
162
297executable aeson-benchmark-map
163executable aeson-benchmark-map
298− default-language: Haskell2010
299 main-is: AesonMap.hs
164 main-is: AesonMap.hs
300 ghc-options: -Wall -O2 -rtsopts
165 ghc-options: -Wall -O2 -rtsopts
301 build-depends:
166 build-depends:
302 aeson-benchmarks,
167 aeson-benchmarks,
303 base,
168 base,
304− base-compat,
305 criterion >= 1.0,
169 criterion >= 1.0,
306 bytestring,
170 bytestring,
307 containers,
171 containers,
@@ -309,37 +173,6 @@ executable aeson-benchmark-map
309 hashable,
173 hashable,
310 tagged,
174 tagged,
311 text,
175 text,
176+ transformers,
177+ transformers-compat,
312 unordered-containers
178 unordered-containers
313−
314−executable aeson-benchmark-foldable
315− default-language: Haskell2010
316− main-is: AesonFoldable.hs
317− ghc-options: -Wall -O2 -rtsopts
318− build-depends:
319− aeson-benchmarks,
320− base,
321− base-compat,
322− criterion >= 1.0,
323− bytestring,
324− containers,
325− deepseq,
326− hashable,
327− tagged,
328− text,
329− unordered-containers,
330− vector
331−
332−executable aeson-issue-673
333− default-language: Haskell2010
334− main-is: Issue673.hs
335− ghc-options: -Wall -O1 -rtsopts
336− build-depends:
337− aeson-benchmarks,
338− attoparsec,
339− base,
340− bytestring,
341− scientific,
342− base-compat,
343− criterion >= 1.0
344− if impl(ghc < 8.0)
345− build-depends: semigroups
cabal.projectdeleted−5
@@ -1,5 +0,0 @@
1−with-compiler: ghc
2−packages: .
3−packages: attoparsec-iso8601
4−-- packages: benchmarks
5−tests: true
cbits/unescape_string.cdeleted−149
@@ -1,149 +0,0 @@
1−// Copyright (c) 2008-2009 Bjoern Hoehrmann
2−// Copyright (c) 2015, Ondrej Palkovsky
3−// Copyright (c) 2016, Winterland
4−
5−#include <string.h>
6−#include <stdio.h>
7−#include <stdint.h>
8−
9−
10−#define UTF8_ACCEPT 0
11−#define UTF8_REJECT 12
12−
13−static const uint8_t utf8d[] = {
14− // The first part of the table maps bytes to character classes that
15− // to reduce the size of the transition table and create bitmasks.
16− 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
17− 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
18− 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
19− 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
20− 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
21− 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
22− 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
23− 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8,
24−
25− // The second part is a transition table that maps a combination
26− // of a state of the automaton and a character class to a state.
27− 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12,
28− 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12,
29− 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12,
30− 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12,
31− 12,36,12,12,12,12,12,12,12,12,12,12,
32−};
33−
34−static inline uint32_t decode(uint32_t* state, uint32_t* codep, uint32_t byte) {
35− uint32_t type = utf8d[byte];
36−
37− *codep = (*state != UTF8_ACCEPT) ?
38− (byte & 0x3fu) | (*codep << 6) :
39− (0xff >> type) & (byte);
40−
41− *state = utf8d[256 + *state + type];
42− return *state;
43−}
44−
45−static inline uint16_t decode_hex(uint32_t c)
46−{
47− if (c >= '0' && c <= '9') return c - '0';
48− else if (c >= 'a' && c <= 'f') return c - 'a' + 10;
49− else if (c >= 'A' && c <= 'F') return c - 'A' + 10;
50− return 0xFFFF; // Should not happen
51−}
52−
53−// Decode, return non-zero value on error
54−int _js_decode_string(uint16_t *const dest, size_t *destoff,
55− const uint8_t *s, const uint8_t *const srcend)
56−{
57− uint16_t *d = dest + *destoff;
58− uint32_t state = 0;
59− uint32_t codepoint;
60−
61− uint8_t surrogate = 0;
62− uint16_t temp_hex = 0;
63− uint16_t unidata;
64−
65− // Optimized version of dispatch when just an ASCII char is expected
66− #define DISPATCH_ASCII(label) {\
67− if (s >= srcend) {\
68− return -1;\
69− }\
70− codepoint = *s++;\
71− goto label;\
72− }
73−
74− standard:
75− // Test end of stream
76− while (s < srcend) {
77− if (decode(&state, &codepoint, *s++) != UTF8_ACCEPT) {
78− if (state == UTF8_REJECT) { return -1; }
79− continue;
80− }
81−
82− if (codepoint == '\\')
83− DISPATCH_ASCII(backslash)
84− else if (codepoint <= 0xffff)
85− *d++ = (uint16_t) codepoint;
86− else {
87− *d++ = (uint16_t) (0xD7C0 + (codepoint >> 10));
88− *d++ = (uint16_t) (0xDC00 + (codepoint & 0x3FF));
89− }
90− }
91− *destoff = d - dest;
92− // Exit point
93− return (state != UTF8_ACCEPT);
94− backslash:
95− switch (codepoint) {
96− case '"':
97− case '\\':
98− case '/':
99− *d++ = (uint16_t) codepoint;
100− goto standard;
101− break;
102− case 'b': *d++ = '\b';goto standard;
103− case 'f': *d++ = '\f';goto standard;
104− case 'n': *d++ = '\n';goto standard;
105− case 'r': *d++ = '\r';goto standard;
106− case 't': *d++ = '\t';goto standard;
107− case 'u': DISPATCH_ASCII(unicode1);;break;
108− default:
109− return -1;
110− }
111− unicode1:
112− temp_hex = decode_hex(codepoint);
113− if (temp_hex == 0xFFFF) { return -1; }
114− else unidata = temp_hex << 12;
115− DISPATCH_ASCII(unicode2);
116− unicode2:
117− temp_hex = decode_hex(codepoint);
118− if (temp_hex == 0xFFFF) { return -1; }
119− else unidata |= temp_hex << 8;
120− DISPATCH_ASCII(unicode3);
121− unicode3:
122− temp_hex = decode_hex(codepoint);
123− if (temp_hex == 0xFFFF) { return -1; }
124− else unidata |= temp_hex << 4;
125− DISPATCH_ASCII(unicode4);
126− unicode4:
127− temp_hex = decode_hex(codepoint);
128− if (temp_hex == 0xFFFF) { return -1; }
129− else unidata |= temp_hex;
130− *d++ = (uint16_t) unidata;
131−
132− if (surrogate) {
133− if (unidata < 0xDC00 || unidata > 0xDFFF) // is not low surrogate
134− return -1;
135− surrogate = 0;
136− } else if (unidata >= 0xD800 && unidata <= 0xDBFF ) { // is high surrogate
137− surrogate = 1;
138− DISPATCH_ASCII(surrogate1);
139− } else if (unidata >= 0xDC00 && unidata <= 0xDFFF) { // is low surrogate
140− return -1;
141− }
142− goto standard;
143− surrogate1:
144− if (codepoint != '\\') { return -1; }
145− DISPATCH_ASCII(surrogate2)
146− surrogate2:
147− if (codepoint != 'u') { return -1; }
148− DISPATCH_ASCII(unicode1)
149−}
changelog.md+20−313
@@ -1,334 +1,41 @@
1For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md).
1For the latest version of this document, please see [https://github.com/bos/aeson/blob/master/changelog.md](https://github.com/bos/aeson/blob/master/changelog.md).
2
2
3−### upcoming
3+# 0.12.0.0
4
4
5−* `FromJSON` instance of `Ratio a` now parses numbers in addtion to
5+* Added list specific members to `ToJSON` and `FromJSON` classes. In the same
6− standard `{numerator=..., denumerator=...}` encoding.
6+ way `Read` / `Show` handle lists specifically. This removes need for
7+ overlapping instances to handle `String`.
7
8
8−### 1.4.6.0
9+* Added higher rank classes: `ToJSON1`, `ToJSON2`, `FromJSON1`, and `FromJSON2`.
9
10
10−* Provide a clearer error message when a required tagKey for a constructor is missing, thanks to Guru Devanla.
11+* Modified instances for `Map` and `HashMap`. Introduced new `FromJSONKey` and
11− The error message now looks like this: `Error in $: parsing Types.SomeType failed, expected Object with key "tag" containing one of ["nullary","unary","product","record","list"], key "tag" not found`
12+ `ToJSONKey` type classes.
12−
13−* Add `formatPath` and `formatRelativePath` functions to turn a `JSONPath` into a `String`, thanks to Robbie McMichael
14−
15−
16−### 1.4.5.0
17−
18−* Expose `(<?>)`, `JSONPath` and `JSONPathElement(..)` from `Data.Aeson.Types`. Previously only available through internal modules. Thanks to Luke Clifton.
19−
20−* Support for base-compat 0.11, thanks to Ryan Scott.
21−
22−* Travis build for GHC 8.8, thanks to Oleg Grenrus.
23−
24−### 1.4.4.0
25−
26−**New features**:
27−
28−* Adds a parameterized parser `jsonWith` that can be used to choose how to handle duplicate keys in objects, thanks to Xia Li-Yao.
29−
30−* Add generic implementations of `FromJSONKey` and `ToJSONKey`, thanks to Xia Li-Yao. Example:
31−
32−```haskell
33−data Foo = Bar
34− deriving Generic
35−
36−opts :: JSONKeyOptions
37−opts = defaultJSONKeyOptions { keyModifier = toLower }
38−
39−instance ToJSONKey Foo where
40− toJSONKey = genericToJSONKey opts
41−
42−instance FromJSONKey Foo where
43− fromJSONKey = genericFromJSONKey opts
44−```
45−
46−**Minor**:
47−* aeson now uses `time-compat` instead of `time-locale-compat`, thanks to Oleg Grenrus.
48−* Prepare for `MonadFail` breakages in GHC 8.8, thanks to Oleg Grenrus.
49−* Require `bytestring >= 0.10.8.1` for newer GHCs to avoid build failures, thanks to Oleg Grenrus.
50−* Support `primitive 0.7.*`, thanks to Adam Bergmark.
51−* Allow `semigroups 0.19.*` and `hashable 1.3.*`, thanks to Oleg Grenrus.
52−* Fix a typo in the error message when parsing `NonEmpty`, thanks to Colin Woodbury.
53−* Document surprising behavior when using `omitNothingFields` with type variables, thanks to Xia Li-Yao.
54−
55−**Internal changes**:
56−* Code cleanup by Oleg Grenrus
57−* Fix dependencies of the benchmarks on older GHC's, thanks to Xia Li-Yao.
58−
59−### 1.4.3.0
60−* Improve error messages for FromJSON in existing instances and GHC Generic implementation. Thanks to Xia Li-Yao & Igor Pashev.
61−* Tweak error-reporting combinators and their documentation. Thanks to Xia Li-Yao.
62− * `typeMismatch` is now about comparing JSON types (i.e., the expected and actual names of the Value constructor).
63− * `withObject` and other `with*` combinators now also mention the JSON types they expect
64− * New `unexpected` and `prependFailure` combinators.
65−* Add `Contravariant` `ToJSONKeyFunction` instance. Thanks to Oleg Grenrus.
66−* Add `KeyValue` instance for `Object`. Thanks to Robert Hensing.
67−* Improve performance when parsing certain large numbers, thanks to Oleg Grenrus.
68−* Add `Data.Aeson.QQ.Simple` - A limited version of aeson-qq. Thanks to Oleg Grenrus.
69−* Exposes internal helper functions like `<?>`, `JSONPath`, and `parseIndexedJSON` from `Data.Aeson` module. Thanks to Abid Uzair.
70−* Better error messages when there are syntax errors parsing objects and arrays. Thanks to Fintan Halpenny.
71−* Support building with `th-abstraction-0.3.0.0` or later. Thanks to Ryan Scott.
72−
73−### 1.4.2.0
74−
75−* Add `Data.Aeson.QQ.Simple` which is a simpler version of the `aeson-qq` package, it does not support interpolation, thanks to Oleg Grenrus.
76−* Add `Contravariant ToJSONKeyFunction` instance, thanks to Oleg Grenrus.
77−* Add `KeyValue Object` instance, thanks to Robert Hensing
78−* Improved performance when parsing large numbers, thanks to Oleg Grenrus.
79−
80−### 1.4.1.0
81−
82−* Optimizations of generics, thanks to Rémy Oudompheng, here are some numbers for GHC 8.4:
83− * Compilation time: G/BigProduct.hs is 25% faster, G/BigRecord.hs is 2x faster.
84− * Runtime performance: BigRecord/toJSON/generic and BigProduct/encode/generic are more than 2x faster.
85−* Added To/FromJSON instances for `Void` and Generics's `V1`, thanks to Will Yager
86−* Added To/FromJSON instances for `primitive`'s `Array`, `SmallArray`, `PrimArray` and `UnliftedArray`, thanks to Andrew Thad.
87−* Fixes handling of `UTCTime` wrt. leap seconds , thanks to Adam Schønemann
88−* Warning and documentation fixes thanks to tom-bop, Gabor Greif, Ian Jeffries, and Mateusz Curyło.
89−
90−## 1.4.0.0
91−
92−This release introduces bounds on the size of `Scientific` numbers when they are converted to other arbitrary precision types that do not represent them efficiently in memory.
93−
94−This means that trying to decode a number such as `1e1000000000` into an `Integer` will now fail instead of using a lot of memory. If you need to represent large numbers you can add a newtype (preferably over `Scientific`) and providing a parser using `withScientific`.
95−
96−The following instances are affected by this:
97−* `FromJSON Natural`
98−* `FromJSONKey Natural`
99−* `FromJSON Integer`
100−* `FromJSONKey Integer`
101−* `FromJSON NominalDiffTime`
102−
103−For the same reasons the following instances & functions have been removed:
104−* Remove `FromJSON Data.Attoparsec.Number` instance. Note that `Data.Attoparsec.Number` is deprecated.
105−* Remove deprecated `withNumber`, use `withScientific` instead.
106−
107−Finally, encoding integral values with large exponents now uses scientific notation, this saves space for large numbers.
108−
109−#### 1.3.1.1
110−
111−* Catch 0 denominators when parsing Ratio
112−
113−### 1.3.1.0
114−
115−* Fix bug in generically derived `FromJSON` instances that are using `unwrapUnaryRecords`, thanks to Xia Li-yao
116−* Allow base-compat 0.10.*, thanks to Oleg Grenrus
117−
118−## 1.3.0.0
119−
120−Breaking changes:
121−* `GKeyValue` has been renamed to `KeyValuePair`, thanks to Xia Li-yao
122−* Removed unused `FromJSON` constraint in `withEmbeddedJson`, thanks to Tristan Seligmann
123−
124−Other improvements:
125−* Optimizations of TH toEncoding, thanks to Xia Li-yao
126−* Optimizations of hex decoding when using the default/pure unescape implementation, thanks to Xia Li-yao
127−* Improved error message on `Day` parse failures, thanks to Gershom Bazerman
128−* Add `encodeFile` as well as `decodeFile*` variants, thanks to Markus Hauck
129−* Documentation fixes, thanks to Lennart Spitzner
130−* CPP cleanup, thanks to Ryan Scott
131−
132−### 1.2.4.0
133−
134−* Add `Ord` instance for `JSONPathElement`, thanks to Simon Hengel.
135−
136−
137−### 1.2.3.0
138−
139−* Added `withEmbeddedJSON` to help parse JSON embedded inside a JSON string, thanks to Jesse Kempf.
140−* Memory usage improvements to the default (pure) parser, thanks to Jonathan Paugh. Also thanks to Neil Mitchell & Oleg Grenrus for contributing a benchmark.
141−* `omitNothingFields` now works for the `Option` newtype, thanks to Xia Li-yao.
142−* Some documentation fixes, thanks to Jonathan Paug & Philippe Crama.
143−
144−### 1.2.2.0
145−
146−* Add `FromJSON` and `ToJSON` instances for
147− * `DiffTime`, thanks to Víctor López Juan.
148− * `CTime`, thanks to Daniel Díaz.
149−* Fix handling of fractions when parsing Natural, thanks to Yuriy Syrovetskiy.
150−* Change text in error messages for Integral types to make them follow the common pattern, thanks to Yuriy Syrovetskiy.
151−* Add missing `INCOHERENT` pragma for `RecordToPair`, thanks to Xia Li-yao.
152−* Everything related to `Options` is now exported from `Data.Aeson`, thanks to Xia Li-yao.
153−* Optimizations to not escape text in clear cases, thanks to Oleg Grenrus.
154−* Some documentation fixes, thanks to Phil de Joux & Xia Li-yao.
155−
156−### 1.2.1.0
157−
158−* Add `parserThrowError` and `parserCatchError` combinators, thanks to Oleg Grenrus.
159−
160−* Add `Generic` instance for `Value`, thanks to Xia Li-yao.
161−
162−* Fix a mistake in the 1.2.0.0 changelog, the `cffi` flag is disabled by default! Thanks to dbaynard.
163−
164−## 1.2.0.0
165−
166−* `tagSingleConstructors`, an option to encode single-constructor types as tagged sums was added to `Options`. It is disabled by default for backward compatibility.
167−
168−* The `cffi` flag is now turned off (`False`) by default, this means C FFI code is no longer used by default. You can flip the flag to get C implementation.
169−
170−* The `Options` constructor is no longer exposed to prevent new options from being breaking changes, use `defaultOptions` instead.
171−
172−* The contents of `GToJSON` and `GToEncoding` are no longer exposed.
173−
174−* Some INLINE pragmas were removed to avoid GHC running out of simplifier ticks.
175−
176−### 1.1.2.0
177−
178−* Fix an accidental change in the format of `deriveJSON`. Thanks to Xia Li-yao!
179−
180−* Documentation improvements regarding `ToJSON`, `FromJSON`, and `SumEncoding`. Thanks to Xia Li-yao and Lennart Spitzner!
181−
182−### 1.1.1.0
183−
184−* Added a pure implementation of the C FFI code, the C FFI code. If you wish to use the pure haskell version set the `cffi` flag to `False`. This should make aeson compile when C isn't available, such as for GHCJS. Thanks to James Parker & Marcin Tolysz!
185−
186−* Using the `fast` flag can no longer cause a test case to fail. As far as we know this didn't affect any users of the library itself. Thanks to Xia Li-yao!
187−
188−## 1.1.0.0
189−
190−* Added instances for `UUID`.
191−
192−* The operators for parsing fields now have named aliases:
193− - `.:` => `parseField`
194− - `.:?` => `parseFieldMaybe`
195− - `.:!` => `parseFieldMaybe'`
196− - These functions now also have variants with explicit parser functions: `explicitParseField`, `explicitParseFieldMaybe`, "explicitParseFieldMaybe'`
197−Thanks to Oleg Grenrus.
198−
199−* `ToJSONKey (Identity a)` and `FromJSONKey (Identity a)` no longer require the unnecessary `FromJSON a` constraint. Thanks to Oleg Grenrus.
200−
201−* Added `Data.Aeson.Encoding.pair'` which is a more general version of `Data.Aeson.Encoding.pair`. Thanks to Andrew Martin.
202−
203−* `Day`s BCE are properly encoded and `+` is now a valid prefix for `Day`s CE. Thanks to Matt Parsons.
204−
205−* Some commonly used ToJSON instances are now specialized in order to improve compile time. Thanks to Bartosz Nitka.
206−
207−
208−[JSONTestSuite](https://github.com/nst/JSONTestSuite) cleanups, all
209−motivated by tighter RFC 7159 compliance:
210−
211−* The parser now rejects numbers for which
212− [the integer portion contains a leading zero](https://github.com/bos/aeson/commit/3fb7c155f2255482b1b9566ec5c1eaf9895d630e).
213−* The parser now rejects numbers for which
214− [a decimal point is not followed by at least one digit](https://github.com/bos/aeson/commit/ecfca35a45286dbe2bbaf5f62354be393bc59b66),
215−* The parser now rejects documents that contain [whitespace outside the
216− set {space, newline, carriage return, tab}](https://github.com/bos/aeson/commit/8ef622c2ad8d4a109884e17c2792238a2a320e44).
217−
218−Over 90% of JSONTestSuite tests currently pass. The remainder can be
219−categorised as follows:
220−
221−* The string parser is strict with Unicode compliance where the RFC
222− leaves room for implementation-defined behaviour (tests prefixed
223− with "`i_string_`". (This is necessary because the `text` library
224− cannot accommodate invalid Unicode.)
225−
226−* The parser does not (and will not) support UTF-16, UTF-32, or byte
227− order marks (BOM).
228−* The parser accepts unescaped control characters, even though the RFC
229− states that control characters must be escaped. (This may change at
230− some point, but doesn't seem important.)
231−
232−#### 1.0.2.1
233−
234−* Fixes a regression where a bunch of valid characters caused an
235− "Invalid UTF8-Stream" error when decoding. Thanks to Vladimir
236− Shabanov who investigated and fixed this.
237−
238−### 1.0.2.0
239−
240−* Fixes a regression where it was no longer possible to derive
241− instances for types such as `data T a = T { f1 :: a, f2 :: Maybe a
242− }`.
243−
244−Thanks to Sean Leather for fixing this, and to Ryan Scott for helping out.
245−
246−### 1.0.1.0
247−
248−* Decoding performance has been significantly improved (see
249− https://github.com/bos/aeson/pull/452). Thanks to @winterland1989.
250−
251−* Add `ToJSON`/`FromJSON` instances for newtypes from
252− `Data.Semigroup`: `Min`, `Max`, `First`, `Last`, `WrappedMonoid`,
253− `Option`. Thanks to Lennart Spitzner.
254−
255−* Make the documentation for `.:!` more accurate. Thanks to Ian Jeffries.
256−
257−# 1.0.0.0
258−
259−Major enhancements:
260−
261−* Introduced new `FromJSONKey` and `ToJSONKey` type classes that are
262− used to encode maps without going through HashMap. This also allows arbitrary
263− serialization of keys where a string-like key will encode into an object and
264− other keys will encode into an array of key-value tuples.
265−
266−* Added higher rank classes: `ToJSON1`, `ToJSON2`, `FromJSON1`, and
267− `FromJSON2`.
268−
269−* Added `Data.Aeson.Encoding` with functions to safely write `ToJSON`
270− instances using `toEncoding`.
271−
272−Other enhancements:
273−
274−* A Cabal `fast` flag was added to disable building with optimizations. This drastically speeds up compiling both aeson ***and*** libraries using aeson so it is recommended to enable it during development. With cabal-install you can `cabal install aeson -ffast` and with stack you can add a flag section to your stack.yaml:
275−```
276−flags:
277− aeson:
278− fast: true
279−```
280−
281−* Added list specific members to `ToJSON` and `FromJSON` classes. In
282− the same way `Read` and `Show` handle lists specifically. This
283− removes need for overlapping instances to handle `String`.
284−
285−* Added a new `sumEncoding` option `UntaggedValue` which prevents
286− objects from being tagged with the constructor name.
287−
288−* JSONPaths are now tracked in instances derived with template-haskell
289− and generics.
290−
291−* Get rid of redundancy of JSONPath error messages in nested records.
292−
293− `eitherDecode "{\"x\":{\"a\": [1,2,true]}}" :: Either String Y`
294− previously yielded
295− `Error in $.x.a[2]: failed to parse field" x: failed to parse field a: expected Int, encountered Boolean`
296− and now yields `Error in $.x.a[2]: expected Int, encountered Boolean"`.
297−
298− Some users might prefer to insert `modifyFailure` themselves to
299− customize error messages, which previously prevented the use of
300− `(.:)`.
301−
302−* Backwards compatibility with `bytestring-0.9` using the
303− `bytestring-builder` compatibility package.
304
13
305* Export `decodeWith`, `decodeStrictWith`, `eitherDecodeWith`, and
14* Export `decodeWith`, `decodeStrictWith`, `eitherDecodeWith`, and
306 `eitherDecodeStrictWith` from `Data.Aeson.Parser`. This allows
15 `eitherDecodeStrictWith` from `Data.Aeson.Parser`. This allows
307 decoding using explicit parsers instead of using `FromJSON`
16 decoding using explicit parsers instead of using `FromJSON`
308 instances.
17 instances.
309
18
310−* Un-orphan internal instances to render them in haddocks.
311−
312−Other changes:
313−
314−* Integral `FromJSON` instances now only accept integral
315− values. E.g. parsing `3.14` to `Int` fails instead of succeeding
316− with the value `3`.
317−
318−* Over/underflows are now caught for bounded numeric types.
319−
320* Remove the `contents` field encoding with `allNullaryToStringTag = False`,
19* Remove the `contents` field encoding with `allNullaryToStringTag = False`,
321 giving us `{ "tag" : "c1" }` instead of `{ "tag" : "c1", contents : [] }`.
20 giving us `{ "tag" : "c1" }` instead of `{ "tag" : "c1", contents : [] }`.
322− The contents field is optional when parsing so this is only a breaking
21+ The contents field is optional when parsing so this is only a breaking change for ToJSON.
323− change for ToJSON instances.
324
22
325* Fix a bug where `genericToEncoding` with `unwrapUnaryRecords = True`
23* Fix a bug where `genericToEncoding` with `unwrapUnaryRecords = True`
326 would produce an invalid encoding: `"unwrap\":""`.
24 would produce an invalid encoding: `"unwrap\":""`.
327
25
328−* `ToJSON` instances using `genericToEncoding` and `omitNothingFields`
26+* Get rid of redundancy of JSONPath error messages in nested records.
329− no longer produce invalid JSON.
330
27
331−* Added instances for `DList`, `Compose`, `Product`, `Sum`.
28+ `eitherDecode "{\"x\":{\"a\": [1,2,true]}}" :: Either String Y`
29+ previously yielded `Error in $.x.a[2]: failed to parse field" x:
30+ failed to parse field a: expected Int, encountered Boolean` and now
31+ yields `Error in $.x.a[2]: expected Int, encountered Boolean"`.
32+
33+ Some users might prefer to insert `modifyFailure` themselves to
34+ customize error messages, which previously prevented the use of
35+ `(.:)`.
36+
37+* `ToJSON` instances using `genericToEncoding` and `omitNothingFields`
38+ no longer produces invalid JSON.
332
39
333### 0.11.2.0
40### 0.11.2.0
334
41
examples/Generic.hs+5−7
@@ -6,19 +6,17 @@
6-- automatically derive the Generic class for us.
6-- automatically derive the Generic class for us.
7
7
8{-# LANGUAGE DeriveGeneric #-}
8{-# LANGUAGE DeriveGeneric #-}
9−{-# LANGUAGE NoImplicitPrelude #-}
10−{-# LANGUAGE OverloadedStrings #-}
11−
12−module Main (main) where
13
9
14−import Prelude.Compat
10+{-# LANGUAGE OverloadedStrings #-}
15
11
16import Data.Aeson (FromJSON, ToJSON, decode, encode)
12import Data.Aeson (FromJSON, ToJSON, decode, encode)
17import qualified Data.ByteString.Lazy.Char8 as BL
13import qualified Data.ByteString.Lazy.Char8 as BL
18−import GHC.Generics (Generic)
19
14
20-- To decode or encode a value using the generic machinery, we must
15-- To decode or encode a value using the generic machinery, we must
21-- make the type an instance of the Generic class.
16-- make the type an instance of the Generic class.
17+
18+import GHC.Generics (Generic)
19+
22data Coord = Coord { x :: Double, y :: Double }
20data Coord = Coord { x :: Double, y :: Double }
23 deriving (Show, Generic)
21 deriving (Show, Generic)
24
22
@@ -33,5 +31,5 @@ main :: IO ()
33main = do
31main = do
34 let req = decode "{\"x\":3.0,\"y\":-1.0}" :: Maybe Coord
32 let req = decode "{\"x\":3.0,\"y\":-1.0}" :: Maybe Coord
35 print req
33 print req
36− let reply = Coord { x = 123.4, y = 20 }
34+ let reply = Coord 123.4 20
37 BL.putStrLn (encode reply)
35 BL.putStrLn (encode reply)
examples/Simplest.hs+2−8
@@ -1,12 +1,6 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE RecordWildCards #-}
4
2
5−module Main (main) where
3+import Control.Applicative ((<$>), (<*>), empty)
6−
7−import Prelude.Compat
8−
9−import Control.Applicative (empty)
10import Data.Aeson
4import Data.Aeson
11import Data.Monoid
5import Data.Monoid
12import qualified Data.ByteString.Lazy.Char8 as BL
6import qualified Data.ByteString.Lazy.Char8 as BL
examples/TemplateHaskell.hs+3−6
@@ -1,13 +1,10 @@
1-- We can use Template Haskell (TH) to generate instances of the
1-- We can use Template Haskell (TH) to generate instances of the
2-- FromJSON and ToJSON classes automatically. This is the fastest way
2-- FromJSON and ToJSON classes automatically. This is the fastest way
3-- to add JSON support for a type.
3-- to add JSON support for a type.
4−{-# LANGUAGE NoImplicitPrelude #-}
5−{-# LANGUAGE OverloadedStrings #-}
6−{-# LANGUAGE TemplateHaskell #-}
7
4
8−module Main (main) where
5+{-# LANGUAGE TemplateHaskell #-}
9
6
10−import Prelude.Compat
7+{-# LANGUAGE OverloadedStrings #-}
11
8
12import Data.Aeson (decode, encode)
9import Data.Aeson (decode, encode)
13import Data.Aeson.TH (deriveJSON, defaultOptions)
10import Data.Aeson.TH (deriveJSON, defaultOptions)
@@ -24,5 +21,5 @@ main :: IO ()
24main = do
21main = do
25 let req = decode "{\"x\":3.0,\"y\":-1.0}" :: Maybe Coord
22 let req = decode "{\"x\":3.0,\"y\":-1.0}" :: Maybe Coord
26 print req
23 print req
27− let reply = Coord { x = 123.4, y = 20 }
24+ let reply = Coord 123.4 20
28 BL.putStrLn (encode reply)
25 BL.putStrLn (encode reply)
examples/Twitter.hs+6−12
@@ -8,28 +8,22 @@
8-- renamed "type" to "type_" in the *.json files, to avoid overlap
8-- renamed "type" to "type_" in the *.json files, to avoid overlap
9-- with a Haskell reserved keyword.
9-- with a Haskell reserved keyword.
10
10
11−{-# LANGUAGE DeriveDataTypeable #-}
11+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
12−{-# LANGUAGE DeriveGeneric #-}
13−{-# LANGUAGE NoImplicitPrelude #-}
14
12
15−module Twitter
13+module Twitter (
16− (
17 Metadata(..)
14 Metadata(..)
18 , Geo(..)
15 , Geo(..)
19 , Story(..)
16 , Story(..)
20 , Result(..)
17 , Result(..)
21 ) where
18 ) where
22
19
23−import Prelude.Compat
24−
25−import Control.DeepSeq
26import Data.Data (Typeable, Data)
20import Data.Data (Typeable, Data)
27import Data.Int (Int64)
21import Data.Int (Int64)
28import Data.Text (Text)
22import Data.Text (Text)
23+-- import Data.Time (ZonedTime)
29import GHC.Generics (Generic)
24import GHC.Generics (Generic)
30−
25+import Prelude hiding (id)
31−{-# ANN module "Hlint: ignore Use camelCase" #-}
26+import Control.DeepSeq
32−{-# ANN module "Hlint: ignore Use newtype instead of data" #-}
33
27
34data Metadata = Metadata {
28data Metadata = Metadata {
35 result_type :: Text
29 result_type :: Text
@@ -53,7 +47,7 @@ data Story = Story {
53 , metadata :: Metadata
47 , metadata :: Metadata
54 , to_user_id :: Maybe Int64
48 , to_user_id :: Maybe Int64
55 , text :: Text
49 , text :: Text
56− , id_ :: Int64
50+ , id :: Int64
57 , from_user_id :: Int64
51 , from_user_id :: Int64
58 , geo :: Maybe Geo
52 , geo :: Maybe Geo
59 , iso_language_code :: Text
53 , iso_language_code :: Text
examples/Twitter/Generic.hs+9−27
@@ -1,7 +1,5 @@
1-- Use GHC generics to automatically generate good instances.
1-- Use GHC generics to automatically generate good instances.
2
2
3−{-# LANGUAGE NoImplicitPrelude #-}
4−
5{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
6
4
7module Twitter.Generic
5module Twitter.Generic
@@ -12,33 +10,17 @@ module Twitter.Generic
12 , Result(..)
10 , Result(..)
13 ) where
11 ) where
14
12
15−import Prelude.Compat ()
13+import Data.Aeson (ToJSON, FromJSON)
16−
17import Twitter
14import Twitter
18−import Twitter.Options
19−
20−import Data.Aeson (ToJSON (..), FromJSON (..), genericToJSON, genericToEncoding, genericParseJSON)
21
15
22−instance ToJSON Metadata where
16+instance ToJSON Metadata
23− toJSON = genericToJSON twitterOptions
17+instance FromJSON Metadata
24− toEncoding = genericToEncoding twitterOptions
25−instance FromJSON Metadata where
26− parseJSON = genericParseJSON twitterOptions
27
18
28−instance ToJSON Geo where
19+instance ToJSON Geo
29− toJSON = genericToJSON twitterOptions
20+instance FromJSON Geo
30− toEncoding = genericToEncoding twitterOptions
31−instance FromJSON Geo where
32− parseJSON = genericParseJSON twitterOptions
33
21
34−instance ToJSON Story where
22+instance ToJSON Story
35− toJSON = genericToJSON twitterOptions
23+instance FromJSON Story
36− toEncoding = genericToEncoding twitterOptions
37−instance FromJSON Story where
38− parseJSON = genericParseJSON twitterOptions
39
24
40−instance ToJSON Result where
25+instance ToJSON Result
41− toJSON = genericToJSON twitterOptions
26+instance FromJSON Result
42− toEncoding = genericToEncoding twitterOptions
43−instance FromJSON Result where
44− parseJSON = genericParseJSON twitterOptions
examples/Twitter/Manual.hs+6−11
@@ -1,8 +1,6 @@
1-- Manually write instances.
1-- Manually write instances.
2−{-# LANGUAGE NoImplicitPrelude #-}
3−{-# LANGUAGE OverloadedStrings #-}
4−{-# LANGUAGE RecordWildCards #-}
5
2
3+{-# LANGUAGE OverloadedStrings, RecordWildCards #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
4{-# OPTIONS_GHC -fno-warn-orphans #-}
7
5
8module Twitter.Manual
6module Twitter.Manual
@@ -13,16 +11,13 @@ module Twitter.Manual
13 , Result(..)
11 , Result(..)
14 ) where
12 ) where
15
13
16−import Prelude.Compat
17−
18import Control.Applicative
14import Control.Applicative
19−import Data.Semigroup ((<>))
20−import Twitter
21−
22import Data.Aeson hiding (Result)
15import Data.Aeson hiding (Result)
16+import Data.Monoid ((<>))
17+import Prelude hiding (id)
18+import Twitter
23
19
24instance ToJSON Metadata where
20instance ToJSON Metadata where
25−
26 toJSON Metadata{..} = object [
21 toJSON Metadata{..} = object [
27 "result_type" .= result_type
22 "result_type" .= result_type
28 ]
23 ]
@@ -60,7 +55,7 @@ instance ToJSON Story where
60 , "metadata" .= metadata
55 , "metadata" .= metadata
61 , "to_user_id" .= to_user_id
56 , "to_user_id" .= to_user_id
62 , "text" .= text
57 , "text" .= text
63− , "id" .= id_
58+ , "id" .= id
64 , "from_user_id" .= from_user_id
59 , "from_user_id" .= from_user_id
65 , "geo" .= geo
60 , "geo" .= geo
66 , "iso_language_code" .= iso_language_code
61 , "iso_language_code" .= iso_language_code
@@ -77,7 +72,7 @@ instance ToJSON Story where
77 <> "metadata" .= metadata
72 <> "metadata" .= metadata
78 <> "to_user_id" .= to_user_id
73 <> "to_user_id" .= to_user_id
79 <> "text" .= text
74 <> "text" .= text
80− <> "id" .= id_
75+ <> "id" .= id
81 <> "from_user_id" .= from_user_id
76 <> "from_user_id" .= from_user_id
82 <> "geo" .= geo
77 <> "geo" .= geo
83 <> "iso_language_code" .= iso_language_code
78 <> "iso_language_code" .= iso_language_code
examples/Twitter/Options.hsdeleted−10
@@ -1,10 +0,0 @@
1−module Twitter.Options (module Twitter.Options) where
2−
3−import Data.Aeson
4−
5−twitterOptions :: Options
6−twitterOptions = defaultOptions
7− { fieldLabelModifier = \x -> case x of
8− "id_" -> "id"
9− _ -> x
10− }
examples/Twitter/TH.hs+5−10
@@ -1,8 +1,6 @@
1-- Use Template Haskell to generate good instances.
1-- Use Template Haskell to generate good instances.
2
2
3−{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE TemplateHaskell #-}
3{-# LANGUAGE TemplateHaskell #-}
5−
6{-# OPTIONS_GHC -fno-warn-orphans #-}
4{-# OPTIONS_GHC -fno-warn-orphans #-}
7
5
8module Twitter.TH
6module Twitter.TH
@@ -13,13 +11,10 @@ module Twitter.TH
13 , Result(..)
11 , Result(..)
14 ) where
12 ) where
15
13
16−
17−import Twitter
18−import Twitter.Options
19−
20import Data.Aeson.TH
14import Data.Aeson.TH
15+import Twitter
21
16
22−$(deriveJSON twitterOptions ''Metadata)
17+$(deriveJSON defaultOptions ''Metadata)
23−$(deriveJSON twitterOptions ''Geo)
18+$(deriveJSON defaultOptions ''Geo)
24−$(deriveJSON twitterOptions ''Story)
19+$(deriveJSON defaultOptions ''Story)
25−$(deriveJSON twitterOptions ''Result)
20+$(deriveJSON defaultOptions ''Result)
examples/aeson-examples.cabal−3
@@ -9,7 +9,6 @@ executable aeson-example-generic
9 build-depends:
9 build-depends:
10 aeson >= 0.10,
10 aeson >= 0.10,
11 base,
11 base,
12− base-compat,
13 bytestring,
12 bytestring,
14 ghc-prim
13 ghc-prim
15
14
@@ -19,7 +18,6 @@ executable aeson-example-simplest
19 build-depends:
18 build-depends:
20 aeson,
19 aeson,
21 base,
20 base,
22− base-compat,
23 bytestring
21 bytestring
24
22
25executable aeson-example-th
23executable aeson-example-th
@@ -28,5 +26,4 @@ executable aeson-example-th
28 build-depends:
26 build-depends:
29 aeson,
27 aeson,
30 base,
28 base,
31− base-compat,
32 bytestring
29 bytestring
ffi/Data/Aeson/Parser/UnescapeFFI.hsdeleted−52
@@ -1,52 +0,0 @@
1−{-# LANGUAGE ForeignFunctionInterface #-}
2−{-# LANGUAGE MagicHash #-}
3−{-# LANGUAGE UnliftedFFITypes #-}
4−
5−module Data.Aeson.Parser.UnescapeFFI
6− (
7− unescapeText
8− ) where
9−
10−import Control.Exception (evaluate, throw, try)
11−import Control.Monad.ST.Unsafe (unsafeIOToST, unsafeSTToIO)
12−import Data.ByteString as B
13−import Data.ByteString.Internal as B
14−import Data.Text.Encoding.Error (UnicodeException (..))
15−import Data.Text.Internal (Text (..))
16−import Data.Text.Internal.Private (runText)
17−import Data.Text.Unsafe (unsafeDupablePerformIO)
18−import Data.Word (Word8)
19−import Foreign.C.Types (CInt (..), CSize (..))
20−import Foreign.ForeignPtr (withForeignPtr)
21−import Foreign.Marshal.Utils (with)
22−import Foreign.Ptr (Ptr, plusPtr)
23−import Foreign.Storable (peek)
24−import GHC.Base (MutableByteArray#)
25−import qualified Data.Text.Array as A
26−
27−foreign import ccall unsafe "_js_decode_string" c_js_decode
28− :: MutableByteArray# s -> Ptr CSize
29− -> Ptr Word8 -> Ptr Word8 -> IO CInt
30−
31−unescapeText' :: ByteString -> Text
32−unescapeText' (PS fp off len) = runText $ \done -> do
33− let go dest = withForeignPtr fp $ \ptr ->
34− with (0::CSize) $ \destOffPtr -> do
35− let end = ptr `plusPtr` (off + len)
36− loop curPtr = do
37− res <- c_js_decode (A.maBA dest) destOffPtr curPtr end
38− case res of
39− 0 -> do
40− n <- peek destOffPtr
41− unsafeSTToIO (done dest (fromIntegral n))
42− _ ->
43− throw (DecodeError desc Nothing)
44− loop (ptr `plusPtr` off)
45− (unsafeIOToST . go) =<< A.new len
46− where
47− desc = "Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream"
48−{-# INLINE unescapeText' #-}
49−
50−unescapeText :: ByteString -> Either UnicodeException Text
51−unescapeText = unsafeDupablePerformIO . try . evaluate . unescapeText'
52−{-# INLINE unescapeText #-}
include/incoherent-compat.hdeleted−7
@@ -1,7 +0,0 @@
1−#if __GLASGOW_HASKELL__ >= 710
2−#define INCOHERENT_ {-# INCOHERENT #-}
3−#else
4−-- This causes some type class instances to break:
5−-- {-# LANGUAGE IncoherentInstances #-}
6−#define INCOHERENT_
7−#endif
include/overlapping-compat.h+7
@@ -1,8 +1,15 @@
1#if __GLASGOW_HASKELL__ >= 710
1#if __GLASGOW_HASKELL__ >= 710
2#define OVERLAPPABLE_ {-# OVERLAPPABLE #-}
2#define OVERLAPPABLE_ {-# OVERLAPPABLE #-}
3#define OVERLAPPING_ {-# OVERLAPPING #-}
3#define OVERLAPPING_ {-# OVERLAPPING #-}
4+#ifdef NEEDS_INCOHERENT
5+#define INCOHERENT_ {-# INCOHERENT #-}
6+#endif
4#else
7#else
5{-# LANGUAGE OverlappingInstances #-}
8{-# LANGUAGE OverlappingInstances #-}
6#define OVERLAPPABLE_
9#define OVERLAPPABLE_
7#define OVERLAPPING_
10#define OVERLAPPING_
11+#ifdef NEEDS_INCOHERENT
12+{-# LANGUAGE IncoherentInstances #-}
13+#define INCOHERENT_
14+#endif
8#endif
15#endif
pure/Data/Aeson/Parser/UnescapePure.hsdeleted−254
@@ -1,254 +0,0 @@
1−-- WARNING: This file is security sensitive as it uses unsafeWrite which does
2−-- not check bounds. Any changes should be made with care and we would love to
3−-- get informed about them, just cc us in any PR targetting this file: @eskimor @jprider63
4−-- We would be happy to review the changes!
5−
6−-- The security check at the end (pos > length) only works if pos grows
7−-- monotonously, if this condition does not hold, the check is flawed.
8−module Data.Aeson.Parser.UnescapePure
9− (
10− unescapeText
11− ) where
12−
13−import Control.Exception (evaluate, throw, try)
14−import Control.Monad (when)
15−import Data.ByteString as B
16−import Data.Bits (Bits, shiftL, shiftR, (.&.), (.|.))
17−import Data.Text (Text)
18−import qualified Data.Text.Array as A
19−import Data.Text.Encoding.Error (UnicodeException (..))
20−import Data.Text.Internal.Private (runText)
21−import Data.Text.Unsafe (unsafeDupablePerformIO)
22−import Data.Word (Word8, Word16, Word32)
23−import GHC.ST (ST)
24−
25−-- Different UTF states.
26−data Utf =
27− UtfGround
28− | UtfTail1
29− | UtfU32e0
30− | UtfTail2
31− | UtfU32ed
32− | Utf843f0
33− | UtfTail3
34− | Utf843f4
35− deriving (Eq)
36−
37−data State =
38− StateNone
39− | StateUtf !Utf !Word32
40− | StateBackslash
41− | StateU0
42− | StateU1 !Word16
43− | StateU2 !Word16
44− | StateU3 !Word16
45− | StateS0
46− | StateS1
47− | StateSU0
48− | StateSU1 !Word16
49− | StateSU2 !Word16
50− | StateSU3 !Word16
51− deriving (Eq)
52−
53−-- References:
54−-- http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
55−-- https://github.com/jwilm/vte/blob/master/utf8parse/src/table.rs.in
56−
57−setByte1 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
58−setByte1 point word = point .|. fromIntegral (word .&. 0x3f)
59−{-# INLINE setByte1 #-}
60−
61−setByte2 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
62−setByte2 point word = point .|. (fromIntegral (word .&. 0x3f) `shiftL` 6)
63−{-# INLINE setByte2 #-}
64−
65−setByte2Top :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
66−setByte2Top point word = point .|. (fromIntegral (word .&. 0x1f) `shiftL` 6)
67−{-# INLINE setByte2Top #-}
68−
69−setByte3 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
70−setByte3 point word = point .|. (fromIntegral (word .&. 0x3f) `shiftL` 12)
71−{-# INLINE setByte3 #-}
72−
73−setByte3Top :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
74−setByte3Top point word = point .|. (fromIntegral (word .&. 0xf) `shiftL` 12)
75−{-# INLINE setByte3Top #-}
76−
77−setByte4 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
78−setByte4 point word = point .|. (fromIntegral (word .&. 0x7) `shiftL` 18)
79−{-# INLINE setByte4 #-}
80−
81−decode :: Utf -> Word32 -> Word8 -> (Utf, Word32)
82−decode UtfGround point word = case word of
83− w | 0x00 <= w && w <= 0x7f -> (UtfGround, fromIntegral word)
84− w | 0xc2 <= w && w <= 0xdf -> (UtfTail1, setByte2Top point word)
85− 0xe0 -> (UtfU32e0, setByte3Top point word)
86− w | 0xe1 <= w && w <= 0xec -> (UtfTail2, setByte3Top point word)
87− 0xed -> (UtfU32ed, setByte3Top point word)
88− w | 0xee <= w && w <= 0xef -> (UtfTail2, setByte3Top point word)
89− 0xf0 -> (Utf843f0, setByte4 point word)
90− w | 0xf1 <= w && w <= 0xf3 -> (UtfTail3, setByte4 point word)
91− 0xf4 -> (Utf843f4, setByte4 point word)
92− _ -> throwDecodeError
93−
94−decode UtfU32e0 point word = case word of
95− w | 0xa0 <= w && w <= 0xbf -> (UtfTail1, setByte2 point word)
96− _ -> throwDecodeError
97−
98−decode UtfU32ed point word = case word of
99− w | 0x80 <= w && w <= 0x9f -> (UtfTail1, setByte2 point word)
100− _ -> throwDecodeError
101−
102−decode Utf843f0 point word = case word of
103− w | 0x90 <= w && w <= 0xbf -> (UtfTail2, setByte3 point word)
104− _ -> throwDecodeError
105−
106−decode Utf843f4 point word = case word of
107− w | 0x80 <= w && w <= 0x8f -> (UtfTail2, setByte3 point word)
108− _ -> throwDecodeError
109−
110−decode UtfTail3 point word = case word of
111− w | 0x80 <= w && w <= 0xbf -> (UtfTail2, setByte3 point word)
112− _ -> throwDecodeError
113−
114−decode UtfTail2 point word = case word of
115− w | 0x80 <= w && w <= 0xbf -> (UtfTail1, setByte2 point word)
116− _ -> throwDecodeError
117−
118−decode UtfTail1 point word = case word of
119− w | 0x80 <= w && w <= 0xbf -> (UtfGround, setByte1 point word)
120− _ -> throwDecodeError
121−
122−decodeHex :: Word8 -> Word16
123−decodeHex x
124− | 48 <= x && x <= 57 = fromIntegral x - 48 -- 0-9
125− | 65 <= x && x <= 70 = fromIntegral x - 55 -- A-F
126− | 97 <= x && x <= 102 = fromIntegral x - 87 -- a-f
127− | otherwise = throwDecodeError
128−
129−unescapeText' :: ByteString -> Text
130−unescapeText' bs = runText $ \done -> do
131− dest <- A.new len
132−
133− (pos, finalState) <- loop dest (0, StateNone) 0
134−
135− -- Check final state. Currently pos gets only increased over time, so this check should catch overflows.
136− when ( finalState /= StateNone || pos > len)
137− throwDecodeError
138−
139− done dest pos -- TODO: pos, pos-1??? XXX
140−
141− where
142− len = B.length bs
143−
144− runUtf dest pos st point c = case decode st point c of
145− (UtfGround, 92) -> -- Backslash
146− return (pos, StateBackslash)
147− (UtfGround, w) | w <= 0xffff ->
148− writeAndReturn dest pos (fromIntegral w) StateNone
149− (UtfGround, w) -> do
150− write dest pos (0xd7c0 + fromIntegral (w `shiftR` 10))
151− writeAndReturn dest (pos + 1) (0xdc00 + fromIntegral (w .&. 0x3ff)) StateNone
152− (st', p) ->
153− return (pos, StateUtf st' p)
154−
155− loop :: A.MArray s -> (Int, State) -> Int -> ST s (Int, State)
156− loop _ ps i | i >= len = return ps
157− loop dest ps i = do
158− let c = B.index bs i -- JP: We can use unsafe index once we prove bounds with Liquid Haskell.
159− ps' <- f dest ps c
160− loop dest ps' $ i+1
161−
162− -- No pending state.
163− f dest (pos, StateNone) c = runUtf dest pos UtfGround 0 c
164−
165− -- In the middle of parsing a UTF string.
166− f dest (pos, StateUtf st point) c = runUtf dest pos st point c
167−
168− -- In the middle of escaping a backslash.
169− f dest (pos, StateBackslash) 34 = writeAndReturn dest pos 34 StateNone -- "
170− f dest (pos, StateBackslash) 92 = writeAndReturn dest pos 92 StateNone -- Backslash
171− f dest (pos, StateBackslash) 47 = writeAndReturn dest pos 47 StateNone -- /
172− f dest (pos, StateBackslash) 98 = writeAndReturn dest pos 8 StateNone -- b
173− f dest (pos, StateBackslash) 102 = writeAndReturn dest pos 12 StateNone -- f
174− f dest (pos, StateBackslash) 110 = writeAndReturn dest pos 10 StateNone -- n
175− f dest (pos, StateBackslash) 114 = writeAndReturn dest pos 13 StateNone -- r
176− f dest (pos, StateBackslash) 116 = writeAndReturn dest pos 9 StateNone -- t
177− f _ (pos, StateBackslash) 117 = return (pos, StateU0) -- u
178− f _ ( _, StateBackslash) _ = throwDecodeError
179−
180− -- Processing '\u'.
181− f _ (pos, StateU0) c =
182− let w = decodeHex c in
183− return (pos, StateU1 (w `shiftL` 12))
184−
185− f _ (pos, StateU1 w') c =
186− let w = decodeHex c in
187− return (pos, StateU2 (w' .|. (w `shiftL` 8)))
188−
189− f _ (pos, StateU2 w') c =
190− let w = decodeHex c in
191− return (pos, StateU3 (w' .|. (w `shiftL` 4)))
192−
193− f dest (pos, StateU3 w') c =
194− let w = decodeHex c in
195− let u = w' .|. w in
196−
197− -- Get next state based on surrogates.
198− let st
199− | u >= 0xd800 && u <= 0xdbff = -- High surrogate.
200− StateS0
201− | u >= 0xdc00 && u <= 0xdfff = -- Low surrogate.
202− throwDecodeError
203− | otherwise =
204− StateNone
205− in
206− writeAndReturn dest pos u st
207−
208− -- Handle surrogates.
209− f _ (pos, StateS0) 92 = return (pos, StateS1) -- Backslash
210− f _ ( _, StateS0) _ = throwDecodeError
211−
212− f _ (pos, StateS1) 117 = return (pos, StateSU0) -- u
213− f _ ( _, StateS1) _ = throwDecodeError
214−
215− f _ (pos, StateSU0) c =
216− let w = decodeHex c in
217− return (pos, StateSU1 (w `shiftL` 12))
218−
219− f _ (pos, StateSU1 w') c =
220− let w = decodeHex c in
221− return (pos, StateSU2 (w' .|. (w `shiftL` 8)))
222−
223− f _ (pos, StateSU2 w') c =
224− let w = decodeHex c in
225− return (pos, StateSU3 (w' .|. (w `shiftL` 4)))
226−
227− f dest (pos, StateSU3 w') c =
228− let w = decodeHex c in
229− let u = w' .|. w in
230−
231− -- Check if not low surrogate.
232− if u < 0xdc00 || u > 0xdfff then
233− throwDecodeError
234− else
235− writeAndReturn dest pos u StateNone
236−
237−write :: A.MArray s -> Int -> Word16 -> ST s ()
238−write dest pos char =
239− A.unsafeWrite dest pos char
240−{-# INLINE write #-}
241−
242−writeAndReturn :: A.MArray s -> Int -> Word16 -> t -> ST s (Int, t)
243−writeAndReturn dest pos char res = do
244− write dest pos char
245− return (pos + 1, res)
246−{-# INLINE writeAndReturn #-}
247−
248−throwDecodeError :: a
249−throwDecodeError =
250− let desc = "Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream" in
251− throw (DecodeError desc Nothing)
252−
253−unescapeText :: ByteString -> Either UnicodeException Text
254−unescapeText = unsafeDupablePerformIO . try . evaluate . unescapeText'
run-hlint.shdeleted−7
@@ -1,7 +0,0 @@
1−#!/bin/bash
2−
3−if hash hlint 2>/dev/null; then
4− hlint "$@"
5−else
6− ./hlint.sh "$@"
7−fi
stack-bench.yamldeleted−12
@@ -1,12 +0,0 @@
1−resolver: nightly-2019-09-21
2−# We use aeson in the snapshot to
3−# - avoid recompilation of criterion
4−# - compare against it
5−# - '.'
6−#
7−# Also we use separate working directory to avoid "unregistering aeson"
8−# caused recompilations
9−work-dir: .stack-work-bench
10−packages:
11−- benchmarks
12−extra-deps: []
stack-ffi-unescape.yamldeleted−9
@@ -1,9 +0,0 @@
1−resolver: nightly-2019-09-21
2−packages:
3−- '.'
4−flags:
5− aeson:
6− fast: true
7− cffi: true
8−extra-deps:
9−- Diff-0.4.0
stack-lts12.yamldeleted−15
@@ -1,15 +0,0 @@
1−resolver: lts-12.26
2−packages:
3−- '.'
4−- attoparsec-iso8601
5−flags:
6− aeson:
7− fast: true
8− cffi: true
9−extra-deps:
10−- base-orphans-0.8.1
11−- hashable-time-0.2.0.1
12−- QuickCheck-2.13.1
13−- quickcheck-instances-0.3.21
14−- splitmix-0.0.2
15−- time-compat-1.9.2.2
stack-nightly.yamldeleted−11
@@ -1,11 +0,0 @@
1−resolver: nightly-2019-10-14
2−packages:
3−- '.'
4−- attoparsec-iso8601
5−flags:
6− aeson:
7− fast: true
8− attoparsec-iso8601:
9− fast: true
10−extra-deps:
11−- generic-deriving-1.12.4
stack.yamlnew file+7
@@ -0,0 +1,7 @@
1+resolver: lts-5.16
2+packages:
3+- '.'
4+- benchmarks
5+extra-deps:
6+- generic-deriving-1.10.4.1
7+flags: {}
tests/DataFamilies/Encoders.hs+2−5
@@ -1,16 +1,13 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2{-# LANGUAGE GADTs #-}
2{-# LANGUAGE GADTs #-}
3−{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE TemplateHaskell #-}
3{-# LANGUAGE TemplateHaskell #-}
5
4
6−module DataFamilies.Encoders (module DataFamilies.Encoders) where
5+module DataFamilies.Encoders where
7−
8−import Prelude.Compat
9
6
10import Data.Aeson.TH
7import Data.Aeson.TH
11import Data.Aeson.Types
8import Data.Aeson.Types
12−import DataFamilies.Types
13import Options
9import Options
10+import DataFamilies.Types
14
11
15--------------------------------------------------------------------------------
12--------------------------------------------------------------------------------
16-- Nullary encoders/decoders
13-- Nullary encoders/decoders
tests/DataFamilies/Instances.hs+3−6
@@ -1,19 +1,17 @@
1{-# LANGUAGE FlexibleInstances #-}
1{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE GADTs #-}
2{-# LANGUAGE GADTs #-}
3−{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE TemplateHaskell #-}
3{-# LANGUAGE TemplateHaskell #-}
5{-# LANGUAGE TypeFamilies #-}
4{-# LANGUAGE TypeFamilies #-}
6−
7{-# OPTIONS_GHC -fno-warn-orphans #-}
5{-# OPTIONS_GHC -fno-warn-orphans #-}
8
6
9−module DataFamilies.Instances () where
7+module DataFamilies.Instances where
10−
11−import Prelude.Compat
12
8
9+import Control.Applicative
13import Data.Aeson.TH
10import Data.Aeson.TH
14import Data.Aeson.Types (FromJSON(..))
11import Data.Aeson.Types (FromJSON(..))
15import DataFamilies.Types
12import DataFamilies.Types
16import Test.QuickCheck (Arbitrary(..), elements, oneof)
13import Test.QuickCheck (Arbitrary(..), elements, oneof)
14+import Prelude
17
15
18instance (Arbitrary a) => Arbitrary (Approx a) where
16instance (Arbitrary a) => Arbitrary (Approx a) where
19 arbitrary = Approx <$> arbitrary
17 arbitrary = Approx <$> arbitrary
@@ -26,7 +24,6 @@ instance Arbitrary a => Arbitrary (SomeType c () a) where
26 , Unary <$> arbitrary
24 , Unary <$> arbitrary
27 , Product <$> arbitrary <*> arbitrary <*> arbitrary
25 , Product <$> arbitrary <*> arbitrary <*> arbitrary
28 , Record <$> arbitrary <*> arbitrary <*> arbitrary
26 , Record <$> arbitrary <*> arbitrary <*> arbitrary
29− , List <$> arbitrary
30 ]
27 ]
31
28
32instance Arbitrary (GADT String) where
29instance Arbitrary (GADT String) where
tests/DataFamilies/Properties.hs+4−7
@@ -1,21 +1,18 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2−{-# LANGUAGE NoImplicitPrelude #-}
3
2
4module DataFamilies.Properties (tests) where
3module DataFamilies.Properties (tests) where
5
4
6−import Prelude.Compat
7−
8import DataFamilies.Encoders
5import DataFamilies.Encoders
9import DataFamilies.Instances ()
6import DataFamilies.Instances ()
10−import PropUtils
11
7
8+import Properties hiding (tests)
12
9
13−import Test.Tasty (TestTree, testGroup)
10+import Test.Framework (Test, testGroup)
14−import Test.Tasty.QuickCheck (testProperty)
11+import Test.Framework.Providers.QuickCheck2 (testProperty)
15
12
16--------------------------------------------------------------------------------
13--------------------------------------------------------------------------------
17
14
18−tests :: TestTree
15+tests :: Test
19tests = testGroup "data families" [
16tests = testGroup "data families" [
20 testGroup "template-haskell" [
17 testGroup "template-haskell" [
21 testGroup "toJSON" [
18 testGroup "toJSON" [
tests/DataFamilies/Types.hs+3−8
@@ -1,17 +1,14 @@
1-- DataKinds is needed for deriveAll0 calls on GHC 8
1-- DataKinds is needed for deriveAll0 calls on GHC 8
2{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DataKinds #-}
3−{-# LANGUAGE DeriveGeneric #-}
4{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
5{-# LANGUAGE GADTs #-}
4{-# LANGUAGE GADTs #-}
6{-# LANGUAGE GeneralizedNewtypeDeriving #-}
5{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7−{-# LANGUAGE NoImplicitPrelude #-}
8{-# LANGUAGE StandaloneDeriving #-}
6{-# LANGUAGE StandaloneDeriving #-}
7+{-# LANGUAGE DeriveGeneric #-}
9{-# LANGUAGE TemplateHaskell #-}
8{-# LANGUAGE TemplateHaskell #-}
10{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE TypeFamilies #-}
11
10
12−module DataFamilies.Types (module DataFamilies.Types) where
11+module DataFamilies.Types where
13−
14−import Prelude.Compat
15
12
16import Generics.Deriving.TH (deriveAll0)
13import Generics.Deriving.TH (deriveAll0)
17import Types (ApproxEq(..))
14import Types (ApproxEq(..))
@@ -27,9 +24,7 @@ data instance SomeType c () a = Nullary
27 | Record { testOne :: Double
24 | Record { testOne :: Double
28 , testTwo :: Maybe Bool
25 , testTwo :: Maybe Bool
29 , testThree :: Maybe a
26 , testThree :: Maybe a
30− }
27+ } deriving (Eq, Show)
31− | List [a]
32− deriving (Eq, Show)
33
28
34data family Approx a
29data family Approx a
35newtype instance Approx a = Approx { fromApprox :: a }
30newtype instance Approx a = Approx { fromApprox :: a }
tests/Encoders.hs+7−232
@@ -1,12 +1,7 @@
1−{-# LANGUAGE CPP #-}
2{-# LANGUAGE GADTs #-}
1{-# LANGUAGE GADTs #-}
3−{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE TemplateHaskell #-}
2{-# LANGUAGE TemplateHaskell #-}
5
3
6−module Encoders (module Encoders) where
4+module Encoders where
7−
8−import Prelude.Compat
9−import Data.Text (Text)
10
5
11import Data.Aeson.TH
6import Data.Aeson.TH
12import Data.Aeson.Types
7import Data.Aeson.Types
@@ -97,49 +92,20 @@ gNullaryToEncodingObjectWithSingleField = genericToEncoding optsObjectWithSingle
97gNullaryParseJSONObjectWithSingleField :: Value -> Parser Nullary
92gNullaryParseJSONObjectWithSingleField :: Value -> Parser Nullary
98gNullaryParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField
93gNullaryParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField
99
94
100−keyOptions :: JSONKeyOptions
101−keyOptions = defaultJSONKeyOptions { keyModifier = ('k' :) }
102−
103−gNullaryToJSONKey :: Nullary -> Either String Text
104−gNullaryToJSONKey x = case genericToJSONKey keyOptions of
105− ToJSONKeyText p _ -> Right (p x)
106− _ -> Left "Should be a ToJSONKeyText"
107−
108−gNullaryFromJSONKey :: Text -> Parser Nullary
109−gNullaryFromJSONKey t = case genericFromJSONKey keyOptions of
110− FromJSONKeyTextParser p -> p t
111− _ -> fail "Not a TextParser"
112
95
113--------------------------------------------------------------------------------
96--------------------------------------------------------------------------------
114-- SomeType encoders/decoders
97-- SomeType encoders/decoders
115--------------------------------------------------------------------------------
98--------------------------------------------------------------------------------
116
99
117−-- Unary types
118−type LiftToJSON f a =
119− (a -> Value) -> ([a] -> Value) -> f a -> Value
120−type LiftToEncoding f a =
121− (a -> Encoding) -> ([a] -> Encoding) -> f a -> Encoding
122−type LiftParseJSON f a =
123− (Value -> Parser a) -> (Value -> Parser [a]) -> Value -> Parser (f a)
124−
125thSomeTypeToJSON2ElemArray :: SomeType Int -> Value
100thSomeTypeToJSON2ElemArray :: SomeType Int -> Value
126thSomeTypeToJSON2ElemArray = $(mkToJSON opts2ElemArray ''SomeType)
101thSomeTypeToJSON2ElemArray = $(mkToJSON opts2ElemArray ''SomeType)
127
102
128thSomeTypeToEncoding2ElemArray :: SomeType Int -> Encoding
103thSomeTypeToEncoding2ElemArray :: SomeType Int -> Encoding
129thSomeTypeToEncoding2ElemArray = $(mkToEncoding opts2ElemArray ''SomeType)
104thSomeTypeToEncoding2ElemArray = $(mkToEncoding opts2ElemArray ''SomeType)
130
105
131−thSomeTypeLiftToJSON2ElemArray :: LiftToJSON SomeType a
132−thSomeTypeLiftToJSON2ElemArray = $(mkLiftToJSON opts2ElemArray ''SomeType)
133−
134−thSomeTypeLiftToEncoding2ElemArray :: LiftToEncoding SomeType a
135−thSomeTypeLiftToEncoding2ElemArray = $(mkLiftToEncoding opts2ElemArray ''SomeType)
136−
137thSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType Int)
106thSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType Int)
138thSomeTypeParseJSON2ElemArray = $(mkParseJSON opts2ElemArray ''SomeType)
107thSomeTypeParseJSON2ElemArray = $(mkParseJSON opts2ElemArray ''SomeType)
139
108
140−thSomeTypeLiftParseJSON2ElemArray :: LiftParseJSON SomeType a
141−thSomeTypeLiftParseJSON2ElemArray = $(mkLiftParseJSON opts2ElemArray ''SomeType)
142−
143
109
144thSomeTypeToJSONTaggedObject :: SomeType Int -> Value
110thSomeTypeToJSONTaggedObject :: SomeType Int -> Value
145thSomeTypeToJSONTaggedObject = $(mkToJSON optsTaggedObject ''SomeType)
111thSomeTypeToJSONTaggedObject = $(mkToJSON optsTaggedObject ''SomeType)
@@ -147,36 +113,21 @@ thSomeTypeToJSONTaggedObject = $(mkToJSON optsTaggedObject ''SomeType)
147thSomeTypeToEncodingTaggedObject :: SomeType Int -> Encoding
113thSomeTypeToEncodingTaggedObject :: SomeType Int -> Encoding
148thSomeTypeToEncodingTaggedObject = $(mkToEncoding optsTaggedObject ''SomeType)
114thSomeTypeToEncodingTaggedObject = $(mkToEncoding optsTaggedObject ''SomeType)
149
115
150−thSomeTypeLiftToJSONTaggedObject :: LiftToJSON SomeType a
151−thSomeTypeLiftToJSONTaggedObject = $(mkLiftToJSON optsTaggedObject ''SomeType)
152−
153−thSomeTypeLiftToEncodingTaggedObject :: LiftToEncoding SomeType a
154−thSomeTypeLiftToEncodingTaggedObject = $(mkLiftToEncoding optsTaggedObject ''SomeType)
155−
156thSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType Int)
116thSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType Int)
157thSomeTypeParseJSONTaggedObject = $(mkParseJSON optsTaggedObject ''SomeType)
117thSomeTypeParseJSONTaggedObject = $(mkParseJSON optsTaggedObject ''SomeType)
158
118
159−thSomeTypeLiftParseJSONTaggedObject :: LiftParseJSON SomeType a
160−thSomeTypeLiftParseJSONTaggedObject = $(mkLiftParseJSON optsTaggedObject ''SomeType)
161−
162
119
163thSomeTypeToJSONObjectWithSingleField :: SomeType Int -> Value
120thSomeTypeToJSONObjectWithSingleField :: SomeType Int -> Value
164−thSomeTypeToJSONObjectWithSingleField = $(mkToJSON optsObjectWithSingleField ''SomeType)
121+thSomeTypeToJSONObjectWithSingleField =
122+ $(mkToJSON optsObjectWithSingleField ''SomeType)
165
123
166thSomeTypeToEncodingObjectWithSingleField :: SomeType Int -> Encoding
124thSomeTypeToEncodingObjectWithSingleField :: SomeType Int -> Encoding
167−thSomeTypeToEncodingObjectWithSingleField = $(mkToEncoding optsObjectWithSingleField ''SomeType)
125+thSomeTypeToEncodingObjectWithSingleField =
168−
126+ $(mkToEncoding optsObjectWithSingleField ''SomeType)
169−thSomeTypeLiftToJSONObjectWithSingleField :: LiftToJSON SomeType a
170−thSomeTypeLiftToJSONObjectWithSingleField = $(mkLiftToJSON optsObjectWithSingleField ''SomeType)
171−
172−thSomeTypeLiftToEncodingObjectWithSingleField :: LiftToEncoding SomeType a
173−thSomeTypeLiftToEncodingObjectWithSingleField = $(mkLiftToEncoding optsObjectWithSingleField ''SomeType)
174
127
175thSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType Int)
128thSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType Int)
176−thSomeTypeParseJSONObjectWithSingleField = $(mkParseJSON optsObjectWithSingleField ''SomeType)
129+thSomeTypeParseJSONObjectWithSingleField =
177−
130+ $(mkParseJSON optsObjectWithSingleField ''SomeType)
178−thSomeTypeLiftParseJSONObjectWithSingleField :: LiftParseJSON SomeType a
179−thSomeTypeLiftParseJSONObjectWithSingleField = $(mkLiftParseJSON optsObjectWithSingleField ''SomeType)
180
131
181
132
182gSomeTypeToJSON2ElemArray :: SomeType Int -> Value
133gSomeTypeToJSON2ElemArray :: SomeType Int -> Value
@@ -188,15 +139,6 @@ gSomeTypeToEncoding2ElemArray = genericToEncoding opts2ElemArray
188gSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType Int)
139gSomeTypeParseJSON2ElemArray :: Value -> Parser (SomeType Int)
189gSomeTypeParseJSON2ElemArray = genericParseJSON opts2ElemArray
140gSomeTypeParseJSON2ElemArray = genericParseJSON opts2ElemArray
190
141
191−gSomeTypeLiftToEncoding2ElemArray :: LiftToEncoding SomeType a
192−gSomeTypeLiftToEncoding2ElemArray = genericLiftToEncoding opts2ElemArray
193−
194−gSomeTypeLiftToJSON2ElemArray :: LiftToJSON SomeType a
195−gSomeTypeLiftToJSON2ElemArray = genericLiftToJSON opts2ElemArray
196−
197−gSomeTypeLiftParseJSON2ElemArray :: LiftParseJSON SomeType a
198−gSomeTypeLiftParseJSON2ElemArray = genericLiftParseJSON opts2ElemArray
199−
200
142
201gSomeTypeToJSONTaggedObject :: SomeType Int -> Value
143gSomeTypeToJSONTaggedObject :: SomeType Int -> Value
202gSomeTypeToJSONTaggedObject = genericToJSON optsTaggedObject
144gSomeTypeToJSONTaggedObject = genericToJSON optsTaggedObject
@@ -207,15 +149,6 @@ gSomeTypeToEncodingTaggedObject = genericToEncoding optsTaggedObject
207gSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType Int)
149gSomeTypeParseJSONTaggedObject :: Value -> Parser (SomeType Int)
208gSomeTypeParseJSONTaggedObject = genericParseJSON optsTaggedObject
150gSomeTypeParseJSONTaggedObject = genericParseJSON optsTaggedObject
209
151
210−gSomeTypeLiftToEncodingTaggedObject :: LiftToEncoding SomeType a
211−gSomeTypeLiftToEncodingTaggedObject = genericLiftToEncoding optsTaggedObject
212−
213−gSomeTypeLiftToJSONTaggedObject :: LiftToJSON SomeType a
214−gSomeTypeLiftToJSONTaggedObject = genericLiftToJSON optsTaggedObject
215−
216−gSomeTypeLiftParseJSONTaggedObject :: LiftParseJSON SomeType a
217−gSomeTypeLiftParseJSONTaggedObject = genericLiftParseJSON optsTaggedObject
218−
219
152
220gSomeTypeToJSONObjectWithSingleField :: SomeType Int -> Value
153gSomeTypeToJSONObjectWithSingleField :: SomeType Int -> Value
221gSomeTypeToJSONObjectWithSingleField = genericToJSON optsObjectWithSingleField
154gSomeTypeToJSONObjectWithSingleField = genericToJSON optsObjectWithSingleField
@@ -226,15 +159,6 @@ gSomeTypeToEncodingObjectWithSingleField = genericToEncoding optsObjectWithSingl
226gSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType Int)
159gSomeTypeParseJSONObjectWithSingleField :: Value -> Parser (SomeType Int)
227gSomeTypeParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField
160gSomeTypeParseJSONObjectWithSingleField = genericParseJSON optsObjectWithSingleField
228
161
229−gSomeTypeLiftToEncodingObjectWithSingleField :: LiftToEncoding SomeType a
230−gSomeTypeLiftToEncodingObjectWithSingleField = genericLiftToEncoding optsObjectWithSingleField
231−
232−gSomeTypeLiftToJSONObjectWithSingleField :: LiftToJSON SomeType a
233−gSomeTypeLiftToJSONObjectWithSingleField = genericLiftToJSON optsObjectWithSingleField
234−
235−gSomeTypeLiftParseJSONObjectWithSingleField :: LiftParseJSON SomeType a
236−gSomeTypeLiftParseJSONObjectWithSingleField = genericLiftParseJSON optsObjectWithSingleField
237−
238
162
239gSomeTypeToJSONOmitNothingFields :: SomeType Int -> Value
163gSomeTypeToJSONOmitNothingFields :: SomeType Int -> Value
240gSomeTypeToJSONOmitNothingFields = genericToJSON optsOmitNothingFields
164gSomeTypeToJSONOmitNothingFields = genericToJSON optsOmitNothingFields
@@ -243,104 +167,6 @@ gSomeTypeToEncodingOmitNothingFields :: SomeType Int -> Encoding
243gSomeTypeToEncodingOmitNothingFields = genericToEncoding optsOmitNothingFields
167gSomeTypeToEncodingOmitNothingFields = genericToEncoding optsOmitNothingFields
244
168
245
169
246−thSomeTypeParseJSONRejectUnknownFields :: Value -> Parser (SomeType Int)
247−thSomeTypeParseJSONRejectUnknownFields = $(mkParseJSON optsRejectUnknownFields ''SomeType)
248−
249−gSomeTypeParseJSONRejectUnknownFields :: Value -> Parser (SomeType Int)
250−gSomeTypeParseJSONRejectUnknownFields = genericParseJSON optsRejectUnknownFields
251−
252−
253−--------------------------------------------------------------------------------
254−-- Foo decoders
255−--------------------------------------------------------------------------------
256−
257−thFooParseJSONRejectUnknownFields :: Value -> Parser Foo
258−thFooParseJSONRejectUnknownFields = $(mkParseJSON optsRejectUnknownFields ''Foo)
259−
260−gFooParseJSONRejectUnknownFields :: Value -> Parser Foo
261−gFooParseJSONRejectUnknownFields = genericParseJSON optsRejectUnknownFields
262−
263−
264−thFooParseJSONRejectUnknownFieldsTagged :: Value -> Parser Foo
265−thFooParseJSONRejectUnknownFieldsTagged = $(mkParseJSON optsRejectUnknownFieldsTagged ''Foo)
266−
267−gFooParseJSONRejectUnknownFieldsTagged :: Value -> Parser Foo
268−gFooParseJSONRejectUnknownFieldsTagged = genericParseJSON optsRejectUnknownFieldsTagged
269−
270−
271−--------------------------------------------------------------------------------
272−-- Option fields
273−--------------------------------------------------------------------------------
274−
275−thOptionFieldToJSON :: OptionField -> Value
276−thOptionFieldToJSON = $(mkToJSON optsOptionField 'OptionField)
277−
278−thOptionFieldToEncoding :: OptionField -> Encoding
279−thOptionFieldToEncoding = $(mkToEncoding optsOptionField 'OptionField)
280−
281−thOptionFieldParseJSON :: Value -> Parser OptionField
282−thOptionFieldParseJSON = $(mkParseJSON optsOptionField 'OptionField)
283−
284−gOptionFieldToJSON :: OptionField -> Value
285−gOptionFieldToJSON = genericToJSON optsOptionField
286−
287−gOptionFieldToEncoding :: OptionField -> Encoding
288−gOptionFieldToEncoding = genericToEncoding optsOptionField
289−
290−gOptionFieldParseJSON :: Value -> Parser OptionField
291−gOptionFieldParseJSON = genericParseJSON optsOptionField
292−
293−thMaybeFieldToJSON :: MaybeField -> Value
294−thMaybeFieldToJSON = $(mkToJSON optsOptionField 'MaybeField)
295−
296−
297−--------------------------------------------------------------------------------
298−-- IncoherentInstancesNeeded
299−--------------------------------------------------------------------------------
300−
301−-- | This test demonstrates the need for IncoherentInstances. See the definition
302−-- of 'IncoherentInstancesNeeded' for a discussion of the issue.
303−--
304−-- NOTE 1: We only need to compile this test. We do not need to run it.
305−--
306−-- NOTE 2: We actually only use the INCOHERENT pragma on specific instances
307−-- instead of the IncoherentInstances language extension. Therefore, this is
308−-- only supported on GHC versions >= 7.10.
309−#if __GLASGOW_HASKELL__ >= 710
310−incoherentInstancesNeededParseJSONString :: FromJSON a => Value -> Parser (IncoherentInstancesNeeded a)
311−incoherentInstancesNeededParseJSONString = case () of
312− _ | True -> $(mkParseJSON defaultOptions ''IncoherentInstancesNeeded)
313− | False -> genericParseJSON defaultOptions
314−
315−incoherentInstancesNeededToJSON :: ToJSON a => IncoherentInstancesNeeded a -> Value
316−incoherentInstancesNeededToJSON = case () of
317− _ | True -> $(mkToJSON defaultOptions ''IncoherentInstancesNeeded)
318− | False -> genericToJSON defaultOptions
319−#endif
320−
321−-------------------------------------------------------------------------------
322−-- EitherTextInt encoders/decodes
323−-------------------------------------------------------------------------------
324−
325−thEitherTextIntToJSONUntaggedValue :: EitherTextInt -> Value
326−thEitherTextIntToJSONUntaggedValue = $(mkToJSON optsUntaggedValue ''EitherTextInt)
327−
328−thEitherTextIntToEncodingUntaggedValue :: EitherTextInt -> Encoding
329−thEitherTextIntToEncodingUntaggedValue = $(mkToEncoding optsUntaggedValue ''EitherTextInt)
330−
331−thEitherTextIntParseJSONUntaggedValue :: Value -> Parser EitherTextInt
332−thEitherTextIntParseJSONUntaggedValue = $(mkParseJSON optsUntaggedValue ''EitherTextInt)
333−
334−
335−gEitherTextIntToJSONUntaggedValue :: EitherTextInt -> Value
336−gEitherTextIntToJSONUntaggedValue = genericToJSON optsUntaggedValue
337−
338−gEitherTextIntToEncodingUntaggedValue :: EitherTextInt -> Encoding
339−gEitherTextIntToEncodingUntaggedValue = genericToEncoding optsUntaggedValue
340−
341−gEitherTextIntParseJSONUntaggedValue :: Value -> Parser EitherTextInt
342−gEitherTextIntParseJSONUntaggedValue = genericParseJSON optsUntaggedValue
343−
344--------------------------------------------------------------------------------
170--------------------------------------------------------------------------------
345-- Approx encoders/decoders
171-- Approx encoders/decoders
346--------------------------------------------------------------------------------
172--------------------------------------------------------------------------------
@@ -405,54 +231,3 @@ thGADTToEncodingDefault = $(mkToEncoding defaultOptions ''GADT)
405
231
406thGADTParseJSONDefault :: Value -> Parser (GADT String)
232thGADTParseJSONDefault :: Value -> Parser (GADT String)
407thGADTParseJSONDefault = $(mkParseJSON defaultOptions ''GADT)
233thGADTParseJSONDefault = $(mkParseJSON defaultOptions ''GADT)
408−
409−--------------------------------------------------------------------------------
410−-- OneConstructor encoders/decoders
411−--------------------------------------------------------------------------------
412−
413−thOneConstructorToJSONDefault :: OneConstructor -> Value
414−thOneConstructorToJSONDefault = $(mkToJSON defaultOptions ''OneConstructor)
415−
416−thOneConstructorToEncodingDefault :: OneConstructor -> Encoding
417−thOneConstructorToEncodingDefault = $(mkToEncoding defaultOptions ''OneConstructor)
418−
419−thOneConstructorParseJSONDefault :: Value -> Parser OneConstructor
420−thOneConstructorParseJSONDefault = $(mkParseJSON defaultOptions ''OneConstructor)
421−
422−thOneConstructorToJSONTagged :: OneConstructor -> Value
423−thOneConstructorToJSONTagged = $(mkToJSON optsTagSingleConstructors ''OneConstructor)
424−
425−thOneConstructorToEncodingTagged :: OneConstructor -> Encoding
426−thOneConstructorToEncodingTagged = $(mkToEncoding optsTagSingleConstructors ''OneConstructor)
427−
428−thOneConstructorParseJSONTagged :: Value -> Parser OneConstructor
429−thOneConstructorParseJSONTagged = $(mkParseJSON optsTagSingleConstructors ''OneConstructor)
430−
431−
432−gOneConstructorToJSONDefault :: OneConstructor -> Value
433−gOneConstructorToJSONDefault = genericToJSON defaultOptions
434−
435−gOneConstructorToEncodingDefault :: OneConstructor -> Encoding
436−gOneConstructorToEncodingDefault = genericToEncoding defaultOptions
437−
438−gOneConstructorParseJSONDefault :: Value -> Parser OneConstructor
439−gOneConstructorParseJSONDefault = genericParseJSON defaultOptions
440−
441−gOneConstructorToJSONTagged :: OneConstructor -> Value
442−gOneConstructorToJSONTagged = genericToJSON optsTagSingleConstructors
443−
444−gOneConstructorToEncodingTagged :: OneConstructor -> Encoding
445−gOneConstructorToEncodingTagged = genericToEncoding optsTagSingleConstructors
446−
447−gOneConstructorParseJSONTagged :: Value -> Parser OneConstructor
448−gOneConstructorParseJSONTagged = genericParseJSON optsTagSingleConstructors
449−
450−--------------------------------------------------------------------------------
451−-- Product2 encoders/decoders
452−--------------------------------------------------------------------------------
453−
454−thProduct2ParseJSON :: Value -> Parser (Product2 Int Bool)
455−thProduct2ParseJSON = $(mkParseJSON defaultOptions ''Product2)
456−
457−gProduct2ParseJSON :: Value -> Parser (Product2 Int Bool)
458−gProduct2ParseJSON = genericParseJSON defaultOptions
tests/ErrorMessages.hsdeleted−224
@@ -1,224 +0,0 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
2−{-# LANGUAGE OverloadedStrings #-}
3−{-# LANGUAGE ScopedTypeVariables #-}
4−
5−module ErrorMessages
6− (
7− tests
8− ) where
9−
10−import Prelude.Compat
11−
12−import Data.Aeson (FromJSON(..), Value, json)
13−import Data.Aeson.Types (Parser)
14−import Data.Aeson.Parser (eitherDecodeWith)
15−import Data.Aeson.Internal (formatError, iparse)
16−import Data.Algorithm.Diff (PolyDiff (..), getGroupedDiff)
17−import Data.Proxy (Proxy(..))
18−import Data.Semigroup ((<>))
19−import Data.Sequence (Seq)
20−import Instances ()
21−import Numeric.Natural (Natural)
22−import Test.Tasty (TestTree, TestName)
23−import Test.Tasty.Golden.Advanced (goldenTest)
24−import qualified Data.ByteString.Lazy.Char8 as L
25−import qualified Data.HashMap.Strict as HM
26−
27−import Encoders
28−import Types
29−
30−tests :: [TestTree]
31−tests =
32− [ aesonGoldenTest "simple" "tests/golden/simple.expected" output
33− , aesonGoldenTest "generic" "tests/golden/generic.expected" (outputGeneric G)
34− ]
35−
36−output :: Output
37−output = concat
38− [ testFor "Int" (Proxy :: Proxy Int)
39− [ "\"\""
40− , "[]"
41− , "{}"
42− , "null"
43− ]
44−
45− , testFor "Integer" (Proxy :: Proxy Integer)
46− [ "44.44"
47− ]
48−
49− , testFor "Natural" (Proxy :: Proxy Natural)
50− [ "44.44"
51− , "-50"
52− ]
53−
54− , testFor "String" (Proxy :: Proxy String)
55− [ "1"
56− , "[]"
57− , "{}"
58− , "null"
59− ]
60−
61− , testFor "HashMap" (Proxy :: Proxy (HM.HashMap String Int))
62− [ "\"\""
63− , "[]"
64− ]
65−
66− -- issue #356
67− , testFor "Either" (Proxy :: Proxy (Int, Either (Int, Bool) ()))
68− [ "[1,{\"Left\":[2,3]}]"
69− ]
70−
71− -- issue #358
72− , testFor "Seq" (Proxy :: Proxy (Seq Int))
73− [ "[0,1,true]"
74− ]
75− ]
76−
77−data Choice = TH | G
78−
79−outputGeneric :: Choice -> Output
80−outputGeneric choice = concat
81− [ testWith "OneConstructor"
82− (select
83− thOneConstructorParseJSONDefault
84− gOneConstructorParseJSONDefault)
85− [ "\"X\""
86− , "[0]"
87− ]
88−
89− , testWith "Nullary"
90− (select
91− thNullaryParseJSONString
92− gNullaryParseJSONString)
93− [ "\"X\""
94− , "[]"
95− ]
96−
97− , testWithSomeType "SomeType (tagged)"
98− (select
99− thSomeTypeParseJSONTaggedObject
100− gSomeTypeParseJSONTaggedObject)
101− [ "{\"tag\": \"unary\", \"contents\": true}"
102− , "{\"tag\": \"unary\"}"
103− , "{\"tag\": \"record\"}"
104− , "{\"tag\": \"record\", \"testone\": true, \"testtwo\": null, \"testthree\": null}"
105− , "{\"tag\": \"X\"}"
106− , "{}"
107− , "[]"
108− ]
109−
110− , testWithSomeType "SomeType (single-field)"
111− (select
112− thSomeTypeParseJSONObjectWithSingleField
113− gSomeTypeParseJSONObjectWithSingleField)
114− [ "{\"unary\": {}}"
115− , "{\"unary\": []}"
116− , "{\"X\": []}"
117− , "{\"record\": {}, \"W\":{}}"
118− , "{}"
119− , "[]"
120− , "{\"unary\""
121− , "{\"unary\":"
122− , "{\"unary\":1"
123− ]
124−
125− , testWithSomeType "SomeType (two-element array)"
126− (select
127− thSomeTypeParseJSON2ElemArray
128− gSomeTypeParseJSON2ElemArray)
129− [ "[\"unary\", true]"
130− , "[\"record\", null]"
131− , "[\"X\", 0]"
132− , "[null, 0]"
133− , "[]"
134− , "{}"
135− , "[1"
136− , "[1,"
137− ]
138−
139− , testWithSomeType "SomeType (reject unknown fields)"
140− (select
141− thSomeTypeParseJSONRejectUnknownFields
142− gSomeTypeParseJSONRejectUnknownFields)
143− [ "{\"tag\": \"record\", \"testOne\": 1.0, \"testZero\": 1}"
144− , "{\"testZero\": 1}"
145− , "{\"tag\": \"record\", \"testone\": true, \"testtwo\": null, \"testthree\": null}"
146− ]
147−
148− , testWithFoo "Foo (reject unknown fields)"
149− (select
150− thFooParseJSONRejectUnknownFields
151− gFooParseJSONRejectUnknownFields)
152− [ "{\"tag\": \"foo\"}"
153− ]
154−
155− , testWithFoo "Foo (reject unknown fields, tagged single)"
156− (select
157− thFooParseJSONRejectUnknownFieldsTagged
158− gFooParseJSONRejectUnknownFieldsTagged)
159− [ "{\"tag\": \"foo\", \"unknownField\": 0}"
160− ]
161−
162− , testWith "EitherTextInt"
163− (select
164− thEitherTextIntParseJSONUntaggedValue
165− gEitherTextIntParseJSONUntaggedValue)
166− [ "\"X\""
167− , "[]"
168− ]
169−
170− , testWith "Product2 Int Bool"
171− (select
172− thProduct2ParseJSON
173− gProduct2ParseJSON)
174− [ "[1, null]"
175− , "[]"
176− , "{}"
177− ]
178− ]
179− where
180− select a b = case choice of
181− TH -> a
182− G -> b
183−
184−-- Test infrastructure
185−
186−type Output = [String]
187−
188−outputLine :: String -> Output
189−outputLine = pure
190−
191−aesonGoldenTest :: TestName -> FilePath -> Output -> TestTree
192−aesonGoldenTest name ref out = goldenTest name (L.readFile ref) act cmp upd
193− where
194− act = pure (L.pack (unlines out))
195− upd = L.writeFile ref
196− cmp x y | x == y = return Nothing
197− cmp x y = return $ Just $ unlines $
198− concatMap f (getGroupedDiff (L.lines x) (L.lines y))
199− where
200− f (First xs) = map (cons3 '-' . L.unpack) xs
201− f (Second ys) = map (cons3 '+' . L.unpack) ys
202− -- we print unchanged lines too. It shouldn't be a problem while we have
203− -- reasonably small examples
204− f (Both xs _) = map (cons3 ' ' . L.unpack) xs
205− -- we add three characters, so the changed lines are easier to spot
206− cons3 c cs = c : c : c : ' ' : cs
207−
208−testWith :: Show a => String -> (Value -> Parser a) -> [L.ByteString] -> Output
209−testWith name parser ts =
210− outputLine name <>
211− foldMap (\s ->
212− case eitherDecodeWith json (iparse parser) s of
213− Left err -> outputLine $ uncurry formatError err
214− Right a -> outputLine $ show a) ts
215−
216−testFor :: forall a proxy. (FromJSON a, Show a)
217− => String -> proxy a -> [L.ByteString] -> Output
218−testFor name _ = testWith name (parseJSON :: Value -> Parser a)
219−
220−testWithSomeType :: String -> (Value -> Parser (SomeType Int)) -> [L.ByteString] -> Output
221−testWithSomeType = testWith
222−
223−testWithFoo :: String -> (Value -> Parser Foo) -> [L.ByteString] -> Output
224−testWithFoo = testWith
tests/Functions.hs+1−9
@@ -1,12 +1,4 @@
1−{-# LANGUAGE NoImplicitPrelude #-}
1+module Functions where
2−
3−module Functions
4− (
5− approxEq
6− , approxEqWith
7− ) where
8−
9−import Prelude.Compat
10
2
11approxEq :: (Fractional a, Ord a) => a -> a -> Bool
3approxEq :: (Fractional a, Ord a) => a -> a -> Bool
12approxEq = approxEqWith 1e-15 1e-15
4approxEq = approxEqWith 1e-15 1e-15
tests/Instances.hs+50−44
@@ -1,35 +1,39 @@
1−{-# LANGUAGE FlexibleContexts #-}
1+{-# LANGUAGE CPP #-}
2{-# LANGUAGE FlexibleInstances #-}
2{-# LANGUAGE FlexibleInstances #-}
3−{-# LANGUAGE NoImplicitPrelude #-}
4{-# LANGUAGE OverloadedStrings #-}
3{-# LANGUAGE OverloadedStrings #-}
5{-# LANGUAGE RecordWildCards #-}
4{-# LANGUAGE RecordWildCards #-}
6−
5+{-# LANGUAGE StandaloneDeriving #-}
7{-# OPTIONS_GHC -fno-warn-orphans #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
8
7
9−module Instances () where
8+module Instances where
10−
11−import Prelude.Compat
12
9
13−import Control.Applicative (empty)
10+import Types
14−import Control.Monad
15−import Data.Aeson.Types
16import Data.Function (on)
11import Data.Function (on)
17−import Data.Time (ZonedTime(..), TimeZone(..))
12+import Control.Monad
13+import Test.QuickCheck (Arbitrary(..), getNonNegative, elements,
14+ listOf1, oneof, resize)
18import Data.Time.Clock (UTCTime(..))
15import Data.Time.Clock (UTCTime(..))
16+import Data.Time (ZonedTime(..), TimeZone(..))
17+import Data.List.NonEmpty (NonEmpty(..))
18+import Data.Version
19+import Data.Aeson.Types
20+import Control.Applicative (Const(..))
21+import Data.Tagged (Tagged(..))
22+import Data.Proxy (Proxy(..))
23+import Control.Applicative
19import Functions
24import Functions
20−import Test.QuickCheck (Arbitrary(..), elements, oneof)
21−import Types
22−import qualified Data.DList as DList
23−import qualified Data.HashMap.Strict as HM
24
25
25import Data.Orphans ()
26import Data.Orphans ()
26import Test.QuickCheck.Instances ()
27import Test.QuickCheck.Instances ()
27−import Data.Hashable.Time ()
28+
29+#if !MIN_VERSION_base(4,8,0) && !MIN_VERSION_QuickCheck(2,8,3)
30+import Numeric.Natural
31+#endif
28
32
29-- "System" types.
33-- "System" types.
30
34
31instance Arbitrary DotNetTime where
35instance Arbitrary DotNetTime where
32− arbitrary = DotNetTime `fmap` arbitrary
36+ arbitrary = DotNetTime `liftM` arbitrary
33 shrink = map DotNetTime . shrink . fromDotNetTime
37 shrink = map DotNetTime . shrink . fromDotNetTime
34
38
35-- | Compare timezone part only on 'timeZoneMinutes'
39-- | Compare timezone part only on 'timeZoneMinutes'
@@ -47,20 +51,8 @@ instance ApproxEq UTCTime where
47instance ApproxEq DotNetTime where
51instance ApproxEq DotNetTime where
48 (=~) = (=~) `on` fromDotNetTime
52 (=~) = (=~) `on` fromDotNetTime
49
53
50−instance ApproxEq Float where
51− a =~ b
52− | isNaN a && isNaN b = True
53− | otherwise = approxEq a b
54−
55instance ApproxEq Double where
54instance ApproxEq Double where
56− a =~ b
55+ (=~) = approxEq
57− | isNaN a && isNaN b = True
58− | otherwise = approxEq a b
59−
60−instance (ApproxEq k, Eq v) => ApproxEq (HM.HashMap k v) where
61− a =~ b = and $ zipWith eq (HM.toList a) (HM.toList b)
62− where
63− eq (x,y) (u,v) = x =~ u && y == v
64
56
65-- Test-related types.
57-- Test-related types.
66
58
@@ -139,29 +131,43 @@ instance Arbitrary a => Arbitrary (SomeType a) where
139 , Unary <$> arbitrary
131 , Unary <$> arbitrary
140 , Product <$> arbitrary <*> arbitrary <*> arbitrary
132 , Product <$> arbitrary <*> arbitrary <*> arbitrary
141 , Record <$> arbitrary <*> arbitrary <*> arbitrary
133 , Record <$> arbitrary <*> arbitrary <*> arbitrary
142− , List <$> arbitrary
143 ]
134 ]
144
135
145−instance Arbitrary EitherTextInt where
146− arbitrary = oneof
147− [ LeftBool <$> arbitrary
148− , RightInt <$> arbitrary
149− , BothTextInt <$> arbitrary <*> arbitrary
150− , pure NoneNullary
151− ]
152−
153instance Arbitrary (GADT String) where
136instance Arbitrary (GADT String) where
154 arbitrary = GADT <$> arbitrary
137 arbitrary = GADT <$> arbitrary
155
138
156−instance Arbitrary OptionField where
157− arbitrary = OptionField <$> arbitrary
158−
159−
160instance ApproxEq Char where
139instance ApproxEq Char where
161 (=~) = (==)
140 (=~) = (==)
162
141
163instance (ApproxEq a) => ApproxEq [a] where
142instance (ApproxEq a) => ApproxEq [a] where
164 a =~ b = length a == length b && all (uncurry (=~)) (zip a b)
143 a =~ b = length a == length b && all (uncurry (=~)) (zip a b)
165
144
166−instance Arbitrary a => Arbitrary (DList.DList a) where
145+instance Arbitrary Version where
167− arbitrary = DList.fromList <$> arbitrary
146+ arbitrary = makeVersion . fmap getNonNegative <$> resize 4 (listOf1 arbitrary)
147+
148+instance Arbitrary a => Arbitrary (NonEmpty a) where
149+ arbitrary = (:|) <$> arbitrary <*> arbitrary
150+
151+-- Version tags are deprecated, so we avoid using them in the Arbitrary
152+-- instance. However, the recommended constructor 'makeVersion' is not
153+-- exported by "Data.Version" until base-4.8.0.0. For previous versions,
154+-- a definition is given below.
155+
156+#if !MIN_VERSION_base(4,8,0)
157+makeVersion :: [Int] -> Version
158+makeVersion b = Version b []
159+#endif
160+
161+#if !MIN_VERSION_base(4,8,0) && !MIN_VERSION_QuickCheck(2,8,3)
162+instance Arbitrary Natural where
163+ arbitrary = fromInteger . abs <$> arbitrary
164+#endif
165+
166+instance Arbitrary (Proxy a) where
167+ arbitrary = pure Proxy
168+
169+instance Arbitrary b => Arbitrary (Tagged a b) where
170+ arbitrary = Tagged <$> arbitrary
171+
172+instance Arbitrary a => Arbitrary (Const a b) where
173+ arbitrary = Const <$> arbitrary
tests/JSONTestSuite/LICENSEdeleted−21
@@ -1,21 +0,0 @@
1−MIT License
2−
3−Copyright (c) 2016 Nicolas Seriot
4−
5−Permission is hereby granted, free of charge, to any person obtaining a copy
6−of this software and associated documentation files (the "Software"), to deal
7−in the Software without restriction, including without limitation the rights
8−to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9−copies of the Software, and to permit persons to whom the Software is
10−furnished to do so, subject to the following conditions:
11−
12−The above copyright notice and this permission notice shall be included in all
13−copies or substantial portions of the Software.
14−
15−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17−FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18−AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19−LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20−OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21−SOFTWARE.
tests/JSONTestSuite/README.mddeleted−50
@@ -1,50 +0,0 @@
1−# JSON Parsing Test Suite
2−A comprehensive test suite for RFC 7159 compliant JSON parsers
3−
4−This repository was created as an appendix to the article [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.php).
5−
6−**/parsers/**
7−
8−This directory contains several parsers and tiny wrappers to turn the parsers into JSON validators, by returning a specific value.
9−
10−- `0` the parser did accept the content
11−- `1` the parser did reject the content
12−- `>=1` the process did crash
13−- `timeout` happens after 5 seconds
14−
15−**/test\_parsing/**
16−
17−The name of these files tell if their contents should be accepted or rejected.
18−
19−- `y_` content must be accepted by parsers
20−- `n_` content must be rejected by parsers
21−- `i_` parsers are free to accept or reject content
22−
23−**/test\_transform/**
24−
25−These files contain weird structures and characters that parsers may understand differently, eg:
26−
27−- huge numbers
28−- dictionaries with similar keys
29−- NULL characters
30−- escaped invalid strings
31−
32−These files were used to produce `results/transform.html`.
33−
34−**/run_tests.py**
35−
36−Run all parsers with all files:
37−
38− $ python3 run_tests.py
39−
40−Run all parsers with a specific file:
41−
42− $ python3 run_tests.py file.json
43−
44−The script writes logs in `results/logs.txt`.
45−
46−The script then reads `logs.txt` and generates `results/parsing.html`.
47−
48−**/results/**
49−
50−<img src="results/pruned_results.png" alt="JSON Parsing Tests" />
tests/JSONTestSuite/parsers/test-AppleJSONSerialization/bin/test-AppleJSONSerializationdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test-AppleJSONSerialization/test-AppleJSONSerialization.xcodeproj/project.pbxprojdeleted−260
@@ -1,260 +0,0 @@
1−// !$*UTF8*$!
2−{
3− archiveVersion = 1;
4− classes = {
5− };
6− objectVersion = 46;
7− objects = {
8−
9−/* Begin PBXBuildFile section */
10− 03997F941D70CE0C0001C89F /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03997F931D70CE0C0001C89F /* main.swift */; };
11−/* End PBXBuildFile section */
12−
13−/* Begin PBXCopyFilesBuildPhase section */
14− 03997F8E1D70CE0C0001C89F /* CopyFiles */ = {
15− isa = PBXCopyFilesBuildPhase;
16− buildActionMask = 2147483647;
17− dstPath = /usr/share/man/man1/;
18− dstSubfolderSpec = 0;
19− files = (
20− );
21− runOnlyForDeploymentPostprocessing = 1;
22− };
23−/* End PBXCopyFilesBuildPhase section */
24−
25−/* Begin PBXFileReference section */
26− 03997F901D70CE0C0001C89F /* test-AppleJSONSerialization */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "test-AppleJSONSerialization"; sourceTree = BUILT_PRODUCTS_DIR; };
27− 03997F931D70CE0C0001C89F /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
28−/* End PBXFileReference section */
29−
30−/* Begin PBXFrameworksBuildPhase section */
31− 03997F8D1D70CE0C0001C89F /* Frameworks */ = {
32− isa = PBXFrameworksBuildPhase;
33− buildActionMask = 2147483647;
34− files = (
35− );
36− runOnlyForDeploymentPostprocessing = 0;
37− };
38−/* End PBXFrameworksBuildPhase section */
39−
40−/* Begin PBXGroup section */
41− 03997F871D70CE0C0001C89F = {
42− isa = PBXGroup;
43− children = (
44− 03997F921D70CE0C0001C89F /* test-AppleJSONSerialization */,
45− 03997F911D70CE0C0001C89F /* Products */,
46− );
47− sourceTree = "<group>";
48− };
49− 03997F911D70CE0C0001C89F /* Products */ = {
50− isa = PBXGroup;
51− children = (
52− 03997F901D70CE0C0001C89F /* test-AppleJSONSerialization */,
53− );
54− name = Products;
55− sourceTree = "<group>";
56− };
57− 03997F921D70CE0C0001C89F /* test-AppleJSONSerialization */ = {
58− isa = PBXGroup;
59− children = (
60− 03997F931D70CE0C0001C89F /* main.swift */,
61− );
62− path = "test-AppleJSONSerialization";
63− sourceTree = "<group>";
64− };
65−/* End PBXGroup section */
66−
67−/* Begin PBXNativeTarget section */
68− 03997F8F1D70CE0C0001C89F /* test-AppleJSONSerialization */ = {
69− isa = PBXNativeTarget;
70− buildConfigurationList = 03997F971D70CE0C0001C89F /* Build configuration list for PBXNativeTarget "test-AppleJSONSerialization" */;
71− buildPhases = (
72− 03997F8C1D70CE0C0001C89F /* Sources */,
73− 03997F8D1D70CE0C0001C89F /* Frameworks */,
74− 03997F8E1D70CE0C0001C89F /* CopyFiles */,
75− );
76− buildRules = (
77− );
78− dependencies = (
79− );
80− name = "test-AppleJSONSerialization";
81− productName = "test-AppleJSONSerialization";
82− productReference = 03997F901D70CE0C0001C89F /* test-AppleJSONSerialization */;
83− productType = "com.apple.product-type.tool";
84− };
85−/* End PBXNativeTarget section */
86−
87−/* Begin PBXProject section */
88− 03997F881D70CE0C0001C89F /* Project object */ = {
89− isa = PBXProject;
90− attributes = {
91− LastSwiftUpdateCheck = 0800;
92− LastUpgradeCheck = 0800;
93− ORGANIZATIONNAME = "Nicolas Seriot";
94− TargetAttributes = {
95− 03997F8F1D70CE0C0001C89F = {
96− CreatedOnToolsVersion = 8.0;
97− DevelopmentTeam = VBYRKYS73S;
98− ProvisioningStyle = Automatic;
99− };
100− };
101− };
102− buildConfigurationList = 03997F8B1D70CE0C0001C89F /* Build configuration list for PBXProject "test-AppleJSONSerialization" */;
103− compatibilityVersion = "Xcode 3.2";
104− developmentRegion = English;
105− hasScannedForEncodings = 0;
106− knownRegions = (
107− en,
108− );
109− mainGroup = 03997F871D70CE0C0001C89F;
110− productRefGroup = 03997F911D70CE0C0001C89F /* Products */;
111− projectDirPath = "";
112− projectRoot = "";
113− targets = (
114− 03997F8F1D70CE0C0001C89F /* test-AppleJSONSerialization */,
115− );
116− };
117−/* End PBXProject section */
118−
119−/* Begin PBXSourcesBuildPhase section */
120− 03997F8C1D70CE0C0001C89F /* Sources */ = {
121− isa = PBXSourcesBuildPhase;
122− buildActionMask = 2147483647;
123− files = (
124− 03997F941D70CE0C0001C89F /* main.swift in Sources */,
125− );
126− runOnlyForDeploymentPostprocessing = 0;
127− };
128−/* End PBXSourcesBuildPhase section */
129−
130−/* Begin XCBuildConfiguration section */
131− 03997F951D70CE0C0001C89F /* Debug */ = {
132− isa = XCBuildConfiguration;
133− buildSettings = {
134− ALWAYS_SEARCH_USER_PATHS = NO;
135− CLANG_ANALYZER_NONNULL = YES;
136− CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
137− CLANG_CXX_LIBRARY = "libc++";
138− CLANG_ENABLE_MODULES = YES;
139− CLANG_ENABLE_OBJC_ARC = YES;
140− CLANG_WARN_BOOL_CONVERSION = YES;
141− CLANG_WARN_CONSTANT_CONVERSION = YES;
142− CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
143− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
144− CLANG_WARN_EMPTY_BODY = YES;
145− CLANG_WARN_ENUM_CONVERSION = YES;
146− CLANG_WARN_INFINITE_RECURSION = YES;
147− CLANG_WARN_INT_CONVERSION = YES;
148− CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
149− CLANG_WARN_SUSPICIOUS_MOVES = YES;
150− CLANG_WARN_UNREACHABLE_CODE = YES;
151− CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
152− CODE_SIGN_IDENTITY = "-";
153− COPY_PHASE_STRIP = NO;
154− DEBUG_INFORMATION_FORMAT = dwarf;
155− ENABLE_STRICT_OBJC_MSGSEND = YES;
156− ENABLE_TESTABILITY = YES;
157− GCC_C_LANGUAGE_STANDARD = gnu99;
158− GCC_DYNAMIC_NO_PIC = NO;
159− GCC_NO_COMMON_BLOCKS = YES;
160− GCC_OPTIMIZATION_LEVEL = 0;
161− GCC_PREPROCESSOR_DEFINITIONS = (
162− "DEBUG=1",
163− "$(inherited)",
164− );
165− GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
166− GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
167− GCC_WARN_UNDECLARED_SELECTOR = YES;
168− GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
169− GCC_WARN_UNUSED_FUNCTION = YES;
170− GCC_WARN_UNUSED_VARIABLE = YES;
171− MACOSX_DEPLOYMENT_TARGET = 10.11;
172− MTL_ENABLE_DEBUG_INFO = YES;
173− ONLY_ACTIVE_ARCH = YES;
174− SDKROOT = macosx;
175− SWIFT_OPTIMIZATION_LEVEL = "-Onone";
176− };
177− name = Debug;
178− };
179− 03997F961D70CE0C0001C89F /* Release */ = {
180− isa = XCBuildConfiguration;
181− buildSettings = {
182− ALWAYS_SEARCH_USER_PATHS = NO;
183− CLANG_ANALYZER_NONNULL = YES;
184− CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
185− CLANG_CXX_LIBRARY = "libc++";
186− CLANG_ENABLE_MODULES = YES;
187− CLANG_ENABLE_OBJC_ARC = YES;
188− CLANG_WARN_BOOL_CONVERSION = YES;
189− CLANG_WARN_CONSTANT_CONVERSION = YES;
190− CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
191− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
192− CLANG_WARN_EMPTY_BODY = YES;
193− CLANG_WARN_ENUM_CONVERSION = YES;
194− CLANG_WARN_INFINITE_RECURSION = YES;
195− CLANG_WARN_INT_CONVERSION = YES;
196− CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
197− CLANG_WARN_SUSPICIOUS_MOVES = YES;
198− CLANG_WARN_UNREACHABLE_CODE = YES;
199− CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
200− CODE_SIGN_IDENTITY = "-";
201− COPY_PHASE_STRIP = NO;
202− DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
203− ENABLE_NS_ASSERTIONS = NO;
204− ENABLE_STRICT_OBJC_MSGSEND = YES;
205− GCC_C_LANGUAGE_STANDARD = gnu99;
206− GCC_NO_COMMON_BLOCKS = YES;
207− GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
208− GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
209− GCC_WARN_UNDECLARED_SELECTOR = YES;
210− GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
211− GCC_WARN_UNUSED_FUNCTION = YES;
212− GCC_WARN_UNUSED_VARIABLE = YES;
213− MACOSX_DEPLOYMENT_TARGET = 10.11;
214− MTL_ENABLE_DEBUG_INFO = NO;
215− SDKROOT = macosx;
216− };
217− name = Release;
218− };
219− 03997F981D70CE0C0001C89F /* Debug */ = {
220− isa = XCBuildConfiguration;
221− buildSettings = {
222− DEVELOPMENT_TEAM = VBYRKYS73S;
223− PRODUCT_NAME = "$(TARGET_NAME)";
224− SWIFT_VERSION = 3.0;
225− };
226− name = Debug;
227− };
228− 03997F991D70CE0C0001C89F /* Release */ = {
229− isa = XCBuildConfiguration;
230− buildSettings = {
231− DEVELOPMENT_TEAM = VBYRKYS73S;
232− PRODUCT_NAME = "$(TARGET_NAME)";
233− SWIFT_VERSION = 3.0;
234− };
235− name = Release;
236− };
237−/* End XCBuildConfiguration section */
238−
239−/* Begin XCConfigurationList section */
240− 03997F8B1D70CE0C0001C89F /* Build configuration list for PBXProject "test-AppleJSONSerialization" */ = {
241− isa = XCConfigurationList;
242− buildConfigurations = (
243− 03997F951D70CE0C0001C89F /* Debug */,
244− 03997F961D70CE0C0001C89F /* Release */,
245− );
246− defaultConfigurationIsVisible = 0;
247− defaultConfigurationName = Release;
248− };
249− 03997F971D70CE0C0001C89F /* Build configuration list for PBXNativeTarget "test-AppleJSONSerialization" */ = {
250− isa = XCConfigurationList;
251− buildConfigurations = (
252− 03997F981D70CE0C0001C89F /* Debug */,
253− 03997F991D70CE0C0001C89F /* Release */,
254− );
255− defaultConfigurationIsVisible = 0;
256− };
257−/* End XCConfigurationList section */
258− };
259− rootObject = 03997F881D70CE0C0001C89F /* Project object */;
260−}
tests/JSONTestSuite/parsers/test-AppleJSONSerialization/test-AppleJSONSerialization.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7
@@ -1,7 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<Workspace
3− version = "1.0">
4− <FileRef
5− location = "self:test-AppleJSONSerialization.xcodeproj">
6− </FileRef>
7−</Workspace>
tests/JSONTestSuite/parsers/test-AppleJSONSerialization/test-AppleJSONSerialization.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test-AppleJSONSerialization/test-AppleJSONSerialization.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test-AppleJSONSerialization.xcschemedeleted−91
@@ -1,91 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<Scheme
3− LastUpgradeVersion = "0800"
4− version = "1.3">
5− <BuildAction
6− parallelizeBuildables = "YES"
7− buildImplicitDependencies = "YES">
8− <BuildActionEntries>
9− <BuildActionEntry
10− buildForTesting = "YES"
11− buildForRunning = "YES"
12− buildForProfiling = "YES"
13− buildForArchiving = "YES"
14− buildForAnalyzing = "YES">
15− <BuildableReference
16− BuildableIdentifier = "primary"
17− BlueprintIdentifier = "03997F8F1D70CE0C0001C89F"
18− BuildableName = "test-AppleJSONSerialization"
19− BlueprintName = "test-AppleJSONSerialization"
20− ReferencedContainer = "container:test-AppleJSONSerialization.xcodeproj">
21− </BuildableReference>
22− </BuildActionEntry>
23− </BuildActionEntries>
24− </BuildAction>
25− <TestAction
26− buildConfiguration = "Debug"
27− selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28− selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29− shouldUseLaunchSchemeArgsEnv = "YES">
30− <Testables>
31− </Testables>
32− <MacroExpansion>
33− <BuildableReference
34− BuildableIdentifier = "primary"
35− BlueprintIdentifier = "03997F8F1D70CE0C0001C89F"
36− BuildableName = "test-AppleJSONSerialization"
37− BlueprintName = "test-AppleJSONSerialization"
38− ReferencedContainer = "container:test-AppleJSONSerialization.xcodeproj">
39− </BuildableReference>
40− </MacroExpansion>
41− <AdditionalOptions>
42− </AdditionalOptions>
43− </TestAction>
44− <LaunchAction
45− buildConfiguration = "Debug"
46− selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
47− selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
48− launchStyle = "0"
49− useCustomWorkingDirectory = "NO"
50− ignoresPersistentStateOnLaunch = "NO"
51− debugDocumentVersioning = "YES"
52− debugServiceExtension = "internal"
53− allowLocationSimulation = "YES">
54− <BuildableProductRunnable
55− runnableDebuggingMode = "0">
56− <BuildableReference
57− BuildableIdentifier = "primary"
58− BlueprintIdentifier = "03997F8F1D70CE0C0001C89F"
59− BuildableName = "test-AppleJSONSerialization"
60− BlueprintName = "test-AppleJSONSerialization"
61− ReferencedContainer = "container:test-AppleJSONSerialization.xcodeproj">
62− </BuildableReference>
63− </BuildableProductRunnable>
64− <AdditionalOptions>
65− </AdditionalOptions>
66− </LaunchAction>
67− <ProfileAction
68− buildConfiguration = "Release"
69− shouldUseLaunchSchemeArgsEnv = "YES"
70− savedToolIdentifier = ""
71− useCustomWorkingDirectory = "NO"
72− debugDocumentVersioning = "YES">
73− <BuildableProductRunnable
74− runnableDebuggingMode = "0">
75− <BuildableReference
76− BuildableIdentifier = "primary"
77− BlueprintIdentifier = "03997F8F1D70CE0C0001C89F"
78− BuildableName = "test-AppleJSONSerialization"
79− BlueprintName = "test-AppleJSONSerialization"
80− ReferencedContainer = "container:test-AppleJSONSerialization.xcodeproj">
81− </BuildableReference>
82− </BuildableProductRunnable>
83− </ProfileAction>
84− <AnalyzeAction
85− buildConfiguration = "Debug">
86− </AnalyzeAction>
87− <ArchiveAction
88− buildConfiguration = "Release"
89− revealArchiveInOrganizer = "YES">
90− </ArchiveAction>
91−</Scheme>
tests/JSONTestSuite/parsers/test-AppleJSONSerialization/test-AppleJSONSerialization.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22
@@ -1,22 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3−<plist version="1.0">
4−<dict>
5− <key>SchemeUserState</key>
6− <dict>
7− <key>test-AppleJSONSerialization.xcscheme</key>
8− <dict>
9− <key>orderHint</key>
10− <integer>0</integer>
11− </dict>
12− </dict>
13− <key>SuppressBuildableAutocreation</key>
14− <dict>
15− <key>03997F8F1D70CE0C0001C89F</key>
16− <dict>
17− <key>primary</key>
18− <true/>
19− </dict>
20− </dict>
21−</dict>
22−</plist>
tests/JSONTestSuite/parsers/test-AppleJSONSerialization/test-AppleJSONSerialization/main.swiftdeleted−34
@@ -1,34 +0,0 @@
1−//
2−// main.swift
3−// test-AppleJSONSerialization
4−//
5−// Created by nst on 26/08/16.
6−// Copyright © 2016 Nicolas Seriot. All rights reserved.
7−//
8−
9−import Foundation
10−
11−func main() {
12−
13− guard ProcessInfo.processInfo.arguments.count == 2 else {
14− let url = NSURL(fileURLWithPath: ProcessInfo.processInfo.arguments[0])
15− guard let programName = url.lastPathComponent else { exit(1) }
16− print("Usage: ./\(programName) file.json")
17− exit(1)
18− }
19−
20− let path = ProcessInfo.processInfo.arguments[1]
21− let url = NSURL.fileURL(withPath:path)
22−
23− do {
24− let data = try Data(contentsOf:url)
25−
26− let _ = try JSONSerialization.jsonObject(with: data, options: [.allowFragments])
27−
28− exit(0)
29− } catch {
30− exit(1)
31− }
32−}
33−
34−main()
tests/JSONTestSuite/parsers/test_Bash_JSON/JSON.shdeleted−208
@@ -1,208 +0,0 @@
1−#!/bin/sh
2−
3−throw() {
4− echo "$*" >&2
5− exit 1
6−}
7−
8−BRIEF=0
9−LEAFONLY=0
10−PRUNE=0
11−NO_HEAD=0
12−NORMALIZE_SOLIDUS=0
13−
14−usage() {
15− echo
16− echo "Usage: JSON.sh [-b] [-l] [-p] [-s] [-h]"
17− echo
18− echo "-p - Prune empty. Exclude fields with empty values."
19− echo "-l - Leaf only. Only show leaf nodes, which stops data duplication."
20− echo "-b - Brief. Combines 'Leaf only' and 'Prune empty' options."
21− echo "-n - No-head. Do not show nodes that have no path (lines that start with [])."
22− echo "-s - Remove escaping of the solidus symbol (straight slash)."
23− echo "-h - This help text."
24− echo
25−}
26−
27−parse_options() {
28− set -- "$@"
29− local ARGN=$#
30− while [ "$ARGN" -ne 0 ]
31− do
32− case $1 in
33− -h) usage
34− exit 0
35− ;;
36− -b) BRIEF=1
37− LEAFONLY=1
38− PRUNE=1
39− ;;
40− -l) LEAFONLY=1
41− ;;
42− -p) PRUNE=1
43− ;;
44− -n) NO_HEAD=1
45− ;;
46− -s) NORMALIZE_SOLIDUS=1
47− ;;
48− ?*) echo "ERROR: Unknown option."
49− usage
50− exit 0
51− ;;
52− esac
53− shift 1
54− ARGN=$((ARGN-1))
55− done
56−}
57−
58−awk_egrep () {
59− local pattern_string=$1
60−
61− gawk '{
62− while ($0) {
63− start=match($0, pattern);
64− token=substr($0, start, RLENGTH);
65− print token;
66− $0=substr($0, start+RLENGTH);
67− }
68− }' pattern="$pattern_string"
69−}
70−
71−tokenize () {
72− local GREP
73− local ESCAPE
74− local CHAR
75−
76− if echo "test string" | egrep -ao --color=never "test" >/dev/null 2>&1
77− then
78− GREP='egrep -ao --color=never'
79− else
80− GREP='egrep -ao'
81− fi
82−
83− if echo "test string" | egrep -o "test" >/dev/null 2>&1
84− then
85− ESCAPE='(\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
86− CHAR='[^[:cntrl:]"\\]'
87− else
88− GREP=awk_egrep
89− ESCAPE='(\\\\[^u[:cntrl:]]|\\u[0-9a-fA-F]{4})'
90− CHAR='[^[:cntrl:]"\\\\]'
91− fi
92−
93− local STRING="\"$CHAR*($ESCAPE$CHAR*)*\""
94− local NUMBER='-?(0|[1-9][0-9]*)([.][0-9]*)?([eE][+-]?[0-9]*)?'
95− local KEYWORD='null|false|true'
96− local SPACE='[[:space:]]+'
97−
98− # Force zsh to expand $A into multiple words
99− local is_wordsplit_disabled=$(unsetopt 2>/dev/null | grep -c '^shwordsplit$')
100− if [ $is_wordsplit_disabled != 0 ]; then setopt shwordsplit; fi
101− $GREP "$STRING|$NUMBER|$KEYWORD|$SPACE|." | egrep -v "^$SPACE$"
102− if [ $is_wordsplit_disabled != 0 ]; then unsetopt shwordsplit; fi
103−}
104−
105−parse_array () {
106− local index=0
107− local ary=''
108− read -r token
109− case "$token" in
110− ']') ;;
111− *)
112− while :
113− do
114− parse_value "$1" "$index"
115− index=$((index+1))
116− ary="$ary""$value"
117− read -r token
118− case "$token" in
119− ']') break ;;
120− ',') ary="$ary," ;;
121− *) throw "EXPECTED , or ] GOT ${token:-EOF}" ;;
122− esac
123− read -r token
124− done
125− ;;
126− esac
127− [ "$BRIEF" -eq 0 ] && value=$(printf '[%s]' "$ary") || value=
128− :
129−}
130−
131−parse_object () {
132− local key
133− local obj=''
134− read -r token
135− case "$token" in
136− '}') ;;
137− *)
138− while :
139− do
140− case "$token" in
141− '"'*'"') key=$token ;;
142− *) throw "EXPECTED string GOT ${token:-EOF}" ;;
143− esac
144− read -r token
145− case "$token" in
146− ':') ;;
147− *) throw "EXPECTED : GOT ${token:-EOF}" ;;
148− esac
149− read -r token
150− parse_value "$1" "$key"
151− obj="$obj$key:$value"
152− read -r token
153− case "$token" in
154− '}') break ;;
155− ',') obj="$obj," ;;
156− *) throw "EXPECTED , or } GOT ${token:-EOF}" ;;
157− esac
158− read -r token
159− done
160− ;;
161− esac
162− [ "$BRIEF" -eq 0 ] && value=$(printf '{%s}' "$obj") || value=
163− :
164−}
165−
166−parse_value () {
167− local jpath="${1:+$1,}$2" isleaf=0 isempty=0 print=0
168− case "$token" in
169− '{') parse_object "$jpath" ;;
170− '[') parse_array "$jpath" ;;
171− # At this point, the only valid single-character tokens are digits.
172− ''|[!0-9]) throw "EXPECTED value GOT ${token:-EOF}" ;;
173− *) value=$token
174− # if asked, replace solidus ("\/") in json strings with normalized value: "/"
175− [ "$NORMALIZE_SOLIDUS" -eq 1 ] && value=$(echo "$value" | sed 's#\\/#/#g')
176− isleaf=1
177− [ "$value" = '""' ] && isempty=1
178− ;;
179− esac
180− [ "$value" = '' ] && return
181− [ "$NO_HEAD" -eq 1 ] && [ -z "$jpath" ] && return
182−
183− [ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 0 ] && print=1
184− [ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && [ $PRUNE -eq 0 ] && print=1
185− [ "$LEAFONLY" -eq 0 ] && [ "$PRUNE" -eq 1 ] && [ "$isempty" -eq 0 ] && print=1
186− [ "$LEAFONLY" -eq 1 ] && [ "$isleaf" -eq 1 ] && \
187− [ $PRUNE -eq 1 ] && [ $isempty -eq 0 ] && print=1
188− [ "$print" -eq 1 ] && printf "[%s]\t%s\n" "$jpath" "$value"
189− :
190−}
191−
192−parse () {
193− read -r token
194− parse_value
195− read -r token
196− case "$token" in
197− '') ;;
198− *) throw "EXPECTED EOF GOT $token" ;;
199− esac
200−}
201−
202−if ([ "$0" = "$BASH_SOURCE" ] || ! [ -n "$BASH_SOURCE" ]);
203−then
204− parse_options "$@"
205− tokenize | parse
206−fi
207−
208−# vi: expandtab sw=2 ts=2
tests/JSONTestSuite/parsers/test_Freddy_20160830/bin/test_Freddydeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy.xcodeproj/project.pbxprojdeleted−300
@@ -1,300 +0,0 @@
1−// !$*UTF8*$!
2−{
3− archiveVersion = 1;
4− classes = {
5− };
6− objectVersion = 46;
7− objects = {
8−
9−/* Begin PBXBuildFile section */
10− 03D84ABB1D5B0A1000776402 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D84ABA1D5B0A1000776402 /* main.swift */; };
11− 03F8F7811D5B75600021630C /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F7781D5B75600021630C /* JSON.swift */; };
12− 03F8F7821D5B75600021630C /* JSONDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F7791D5B75600021630C /* JSONDecodable.swift */; };
13− 03F8F7831D5B75600021630C /* JSONEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77A1D5B75600021630C /* JSONEncodable.swift */; };
14− 03F8F7841D5B75600021630C /* JSONEncodingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77B1D5B75600021630C /* JSONEncodingDetector.swift */; };
15− 03F8F7851D5B75600021630C /* JSONLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77C1D5B75600021630C /* JSONLiteralConvertible.swift */; };
16− 03F8F7861D5B75600021630C /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77D1D5B75600021630C /* JSONParser.swift */; };
17− 03F8F7871D5B75600021630C /* JSONParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77E1D5B75600021630C /* JSONParsing.swift */; };
18− 03F8F7881D5B75600021630C /* JSONSerializing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77F1D5B75600021630C /* JSONSerializing.swift */; };
19− 03F8F7891D5B75600021630C /* JSONSubscripting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F7801D5B75600021630C /* JSONSubscripting.swift */; };
20−/* End PBXBuildFile section */
21−
22−/* Begin PBXCopyFilesBuildPhase section */
23− 03D84AB51D5B0A1000776402 /* CopyFiles */ = {
24− isa = PBXCopyFilesBuildPhase;
25− buildActionMask = 2147483647;
26− dstPath = /usr/share/man/man1;
27− dstSubfolderSpec = 0;
28− files = (
29− );
30− runOnlyForDeploymentPostprocessing = 1;
31− };
32−/* End PBXCopyFilesBuildPhase section */
33−
34−/* Begin PBXFileReference section */
35− 03D84AB71D5B0A1000776402 /* test_Freddy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_Freddy; sourceTree = BUILT_PRODUCTS_DIR; };
36− 03D84ABA1D5B0A1000776402 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
37− 03F8F7781D5B75600021630C /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSON.swift; path = test_Freddy/JSON.swift; sourceTree = "<group>"; };
38− 03F8F7791D5B75600021630C /* JSONDecodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONDecodable.swift; path = test_Freddy/JSONDecodable.swift; sourceTree = "<group>"; };
39− 03F8F77A1D5B75600021630C /* JSONEncodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONEncodable.swift; path = test_Freddy/JSONEncodable.swift; sourceTree = "<group>"; };
40− 03F8F77B1D5B75600021630C /* JSONEncodingDetector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONEncodingDetector.swift; path = test_Freddy/JSONEncodingDetector.swift; sourceTree = "<group>"; };
41− 03F8F77C1D5B75600021630C /* JSONLiteralConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONLiteralConvertible.swift; path = test_Freddy/JSONLiteralConvertible.swift; sourceTree = "<group>"; };
42− 03F8F77D1D5B75600021630C /* JSONParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONParser.swift; path = test_Freddy/JSONParser.swift; sourceTree = "<group>"; };
43− 03F8F77E1D5B75600021630C /* JSONParsing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONParsing.swift; path = test_Freddy/JSONParsing.swift; sourceTree = "<group>"; };
44− 03F8F77F1D5B75600021630C /* JSONSerializing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONSerializing.swift; path = test_Freddy/JSONSerializing.swift; sourceTree = "<group>"; };
45− 03F8F7801D5B75600021630C /* JSONSubscripting.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONSubscripting.swift; path = test_Freddy/JSONSubscripting.swift; sourceTree = "<group>"; };
46−/* End PBXFileReference section */
47−
48−/* Begin PBXFrameworksBuildPhase section */
49− 03D84AB41D5B0A1000776402 /* Frameworks */ = {
50− isa = PBXFrameworksBuildPhase;
51− buildActionMask = 2147483647;
52− files = (
53− );
54− runOnlyForDeploymentPostprocessing = 0;
55− };
56−/* End PBXFrameworksBuildPhase section */
57−
58−/* Begin PBXGroup section */
59− 03D84AAE1D5B0A1000776402 = {
60− isa = PBXGroup;
61− children = (
62− 03F8F7781D5B75600021630C /* JSON.swift */,
63− 03F8F7791D5B75600021630C /* JSONDecodable.swift */,
64− 03F8F77A1D5B75600021630C /* JSONEncodable.swift */,
65− 03F8F77B1D5B75600021630C /* JSONEncodingDetector.swift */,
66− 03F8F77C1D5B75600021630C /* JSONLiteralConvertible.swift */,
67− 03F8F77D1D5B75600021630C /* JSONParser.swift */,
68− 03F8F77E1D5B75600021630C /* JSONParsing.swift */,
69− 03F8F77F1D5B75600021630C /* JSONSerializing.swift */,
70− 03F8F7801D5B75600021630C /* JSONSubscripting.swift */,
71− 03D84AB91D5B0A1000776402 /* test_Freddy */,
72− 03D84AB81D5B0A1000776402 /* Products */,
73− );
74− sourceTree = "<group>";
75− };
76− 03D84AB81D5B0A1000776402 /* Products */ = {
77− isa = PBXGroup;
78− children = (
79− 03D84AB71D5B0A1000776402 /* test_Freddy */,
80− );
81− name = Products;
82− sourceTree = "<group>";
83− };
84− 03D84AB91D5B0A1000776402 /* test_Freddy */ = {
85− isa = PBXGroup;
86− children = (
87− 03D84ABA1D5B0A1000776402 /* main.swift */,
88− );
89− path = test_Freddy;
90− sourceTree = "<group>";
91− };
92−/* End PBXGroup section */
93−
94−/* Begin PBXNativeTarget section */
95− 03D84AB61D5B0A1000776402 /* test_Freddy */ = {
96− isa = PBXNativeTarget;
97− buildConfigurationList = 03D84ABE1D5B0A1000776402 /* Build configuration list for PBXNativeTarget "test_Freddy" */;
98− buildPhases = (
99− 03D84AB31D5B0A1000776402 /* Sources */,
100− 03D84AB41D5B0A1000776402 /* Frameworks */,
101− 03D84AB51D5B0A1000776402 /* CopyFiles */,
102− );
103− buildRules = (
104− );
105− dependencies = (
106− );
107− name = test_Freddy;
108− productName = test_Freddy;
109− productReference = 03D84AB71D5B0A1000776402 /* test_Freddy */;
110− productType = "com.apple.product-type.tool";
111− };
112−/* End PBXNativeTarget section */
113−
114−/* Begin PBXProject section */
115− 03D84AAF1D5B0A1000776402 /* Project object */ = {
116− isa = PBXProject;
117− attributes = {
118− LastSwiftUpdateCheck = 0800;
119− LastUpgradeCheck = 0800;
120− ORGANIZATIONNAME = "Nicolas Seriot";
121− TargetAttributes = {
122− 03D84AB61D5B0A1000776402 = {
123− CreatedOnToolsVersion = 8.0;
124− DevelopmentTeam = VBYRKYS73S;
125− DevelopmentTeamName = "Nicolas Seriot";
126− ProvisioningStyle = Automatic;
127− };
128− };
129− };
130− buildConfigurationList = 03D84AB21D5B0A1000776402 /* Build configuration list for PBXProject "test_Freddy" */;
131− compatibilityVersion = "Xcode 3.2";
132− developmentRegion = English;
133− hasScannedForEncodings = 0;
134− knownRegions = (
135− en,
136− );
137− mainGroup = 03D84AAE1D5B0A1000776402;
138− productRefGroup = 03D84AB81D5B0A1000776402 /* Products */;
139− projectDirPath = "";
140− projectRoot = "";
141− targets = (
142− 03D84AB61D5B0A1000776402 /* test_Freddy */,
143− );
144− };
145−/* End PBXProject section */
146−
147−/* Begin PBXSourcesBuildPhase section */
148− 03D84AB31D5B0A1000776402 /* Sources */ = {
149− isa = PBXSourcesBuildPhase;
150− buildActionMask = 2147483647;
151− files = (
152− 03F8F7881D5B75600021630C /* JSONSerializing.swift in Sources */,
153− 03F8F7821D5B75600021630C /* JSONDecodable.swift in Sources */,
154− 03F8F7851D5B75600021630C /* JSONLiteralConvertible.swift in Sources */,
155− 03F8F7871D5B75600021630C /* JSONParsing.swift in Sources */,
156− 03F8F7861D5B75600021630C /* JSONParser.swift in Sources */,
157− 03F8F7831D5B75600021630C /* JSONEncodable.swift in Sources */,
158− 03D84ABB1D5B0A1000776402 /* main.swift in Sources */,
159− 03F8F7811D5B75600021630C /* JSON.swift in Sources */,
160− 03F8F7891D5B75600021630C /* JSONSubscripting.swift in Sources */,
161− 03F8F7841D5B75600021630C /* JSONEncodingDetector.swift in Sources */,
162− );
163− runOnlyForDeploymentPostprocessing = 0;
164− };
165−/* End PBXSourcesBuildPhase section */
166−
167−/* Begin XCBuildConfiguration section */
168− 03D84ABC1D5B0A1000776402 /* Debug */ = {
169− isa = XCBuildConfiguration;
170− buildSettings = {
171− ALWAYS_SEARCH_USER_PATHS = NO;
172− CLANG_ANALYZER_NONNULL = YES;
173− CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
174− CLANG_CXX_LIBRARY = "libc++";
175− CLANG_ENABLE_MODULES = YES;
176− CLANG_ENABLE_OBJC_ARC = YES;
177− CLANG_WARN_BOOL_CONVERSION = YES;
178− CLANG_WARN_CONSTANT_CONVERSION = YES;
179− CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
180− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
181− CLANG_WARN_EMPTY_BODY = YES;
182− CLANG_WARN_ENUM_CONVERSION = YES;
183− CLANG_WARN_INT_CONVERSION = YES;
184− CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
185− CLANG_WARN_UNREACHABLE_CODE = YES;
186− CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
187− CODE_SIGN_IDENTITY = "-";
188− COPY_PHASE_STRIP = NO;
189− DEBUG_INFORMATION_FORMAT = dwarf;
190− ENABLE_STRICT_OBJC_MSGSEND = YES;
191− ENABLE_TESTABILITY = YES;
192− GCC_C_LANGUAGE_STANDARD = gnu99;
193− GCC_DYNAMIC_NO_PIC = NO;
194− GCC_NO_COMMON_BLOCKS = YES;
195− GCC_OPTIMIZATION_LEVEL = 0;
196− GCC_PREPROCESSOR_DEFINITIONS = (
197− "DEBUG=1",
198− "$(inherited)",
199− );
200− GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
201− GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
202− GCC_WARN_UNDECLARED_SELECTOR = YES;
203− GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
204− GCC_WARN_UNUSED_FUNCTION = YES;
205− GCC_WARN_UNUSED_VARIABLE = YES;
206− MACOSX_DEPLOYMENT_TARGET = 10.11;
207− MTL_ENABLE_DEBUG_INFO = YES;
208− ONLY_ACTIVE_ARCH = YES;
209− SDKROOT = macosx;
210− SWIFT_OPTIMIZATION_LEVEL = "-Onone";
211− };
212− name = Debug;
213− };
214− 03D84ABD1D5B0A1000776402 /* Release */ = {
215− isa = XCBuildConfiguration;
216− buildSettings = {
217− ALWAYS_SEARCH_USER_PATHS = NO;
218− CLANG_ANALYZER_NONNULL = YES;
219− CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
220− CLANG_CXX_LIBRARY = "libc++";
221− CLANG_ENABLE_MODULES = YES;
222− CLANG_ENABLE_OBJC_ARC = YES;
223− CLANG_WARN_BOOL_CONVERSION = YES;
224− CLANG_WARN_CONSTANT_CONVERSION = YES;
225− CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
226− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
227− CLANG_WARN_EMPTY_BODY = YES;
228− CLANG_WARN_ENUM_CONVERSION = YES;
229− CLANG_WARN_INT_CONVERSION = YES;
230− CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
231− CLANG_WARN_UNREACHABLE_CODE = YES;
232− CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
233− CODE_SIGN_IDENTITY = "-";
234− COPY_PHASE_STRIP = NO;
235− DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
236− ENABLE_NS_ASSERTIONS = NO;
237− ENABLE_STRICT_OBJC_MSGSEND = YES;
238− GCC_C_LANGUAGE_STANDARD = gnu99;
239− GCC_NO_COMMON_BLOCKS = YES;
240− GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
241− GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
242− GCC_WARN_UNDECLARED_SELECTOR = YES;
243− GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
244− GCC_WARN_UNUSED_FUNCTION = YES;
245− GCC_WARN_UNUSED_VARIABLE = YES;
246− MACOSX_DEPLOYMENT_TARGET = 10.11;
247− MTL_ENABLE_DEBUG_INFO = NO;
248− SDKROOT = macosx;
249− };
250− name = Release;
251− };
252− 03D84ABF1D5B0A1000776402 /* Debug */ = {
253− isa = XCBuildConfiguration;
254− buildSettings = {
255− FRAMEWORK_SEARCH_PATHS = (
256− "$(inherited)",
257− "$(PROJECT_DIR)",
258− );
259− PRODUCT_NAME = "$(TARGET_NAME)";
260− SWIFT_VERSION = 2.3;
261− };
262− name = Debug;
263− };
264− 03D84AC01D5B0A1000776402 /* Release */ = {
265− isa = XCBuildConfiguration;
266− buildSettings = {
267− FRAMEWORK_SEARCH_PATHS = (
268− "$(inherited)",
269− "$(PROJECT_DIR)",
270− );
271− PRODUCT_NAME = "$(TARGET_NAME)";
272− SWIFT_VERSION = 2.3;
273− };
274− name = Release;
275− };
276−/* End XCBuildConfiguration section */
277−
278−/* Begin XCConfigurationList section */
279− 03D84AB21D5B0A1000776402 /* Build configuration list for PBXProject "test_Freddy" */ = {
280− isa = XCConfigurationList;
281− buildConfigurations = (
282− 03D84ABC1D5B0A1000776402 /* Debug */,
283− 03D84ABD1D5B0A1000776402 /* Release */,
284− );
285− defaultConfigurationIsVisible = 0;
286− defaultConfigurationName = Release;
287− };
288− 03D84ABE1D5B0A1000776402 /* Build configuration list for PBXNativeTarget "test_Freddy" */ = {
289− isa = XCConfigurationList;
290− buildConfigurations = (
291− 03D84ABF1D5B0A1000776402 /* Debug */,
292− 03D84AC01D5B0A1000776402 /* Release */,
293− );
294− defaultConfigurationIsVisible = 0;
295− defaultConfigurationName = Release;
296− };
297−/* End XCConfigurationList section */
298− };
299− rootObject = 03D84AAF1D5B0A1000776402 /* Project object */;
300−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7
@@ -1,7 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<Workspace
3− version = "1.0">
4− <FileRef
5− location = "self:test_Freddy.xcodeproj">
6− </FileRef>
7−</Workspace>
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy.xcodeproj/project.xcworkspace/xcshareddata/test_Freddy.xcscmblueprintdeleted−30
@@ -1,30 +0,0 @@
1−{
2− "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A",
3− "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4−
5− },
6− "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7− "6ADA245F937D8ED6D99F5A7865E19F5267A169E2" : 0,
8− "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A" : 0
9− },
10− "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "7B3DFA55-F9BF-41D8-8FD5-204D3162EB03",
11− "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12− "6ADA245F937D8ED6D99F5A7865E19F5267A169E2" : "dropbox\/JSON\/test_Freddy\/Vendor\/Freddy\/",
13− "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A" : "dropbox\/"
14− },
15− "DVTSourceControlWorkspaceBlueprintNameKey" : "test_Freddy",
16− "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17− "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "JSON\/test_Freddy\/test_Freddy.xcodeproj",
18− "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19− {
20− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/bignerdranch\/Freddy.git",
21− "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "6ADA245F937D8ED6D99F5A7865E19F5267A169E2"
23− },
24− {
25− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "\/Users\/nst\/Dropbox\/dropbox.git",
26− "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A"
28− }
29− ]
30−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_Freddy.xcschemedeleted−91
@@ -1,91 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<Scheme
3− LastUpgradeVersion = "0800"
4− version = "1.3">
5− <BuildAction
6− parallelizeBuildables = "YES"
7− buildImplicitDependencies = "YES">
8− <BuildActionEntries>
9− <BuildActionEntry
10− buildForTesting = "YES"
11− buildForRunning = "YES"
12− buildForProfiling = "YES"
13− buildForArchiving = "YES"
14− buildForAnalyzing = "YES">
15− <BuildableReference
16− BuildableIdentifier = "primary"
17− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
18− BuildableName = "test_Freddy"
19− BlueprintName = "test_Freddy"
20− ReferencedContainer = "container:test_Freddy.xcodeproj">
21− </BuildableReference>
22− </BuildActionEntry>
23− </BuildActionEntries>
24− </BuildAction>
25− <TestAction
26− buildConfiguration = "Debug"
27− selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28− selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29− shouldUseLaunchSchemeArgsEnv = "YES">
30− <Testables>
31− </Testables>
32− <MacroExpansion>
33− <BuildableReference
34− BuildableIdentifier = "primary"
35− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
36− BuildableName = "test_Freddy"
37− BlueprintName = "test_Freddy"
38− ReferencedContainer = "container:test_Freddy.xcodeproj">
39− </BuildableReference>
40− </MacroExpansion>
41− <AdditionalOptions>
42− </AdditionalOptions>
43− </TestAction>
44− <LaunchAction
45− buildConfiguration = "Debug"
46− selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
47− selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
48− launchStyle = "0"
49− useCustomWorkingDirectory = "NO"
50− ignoresPersistentStateOnLaunch = "NO"
51− debugDocumentVersioning = "YES"
52− debugServiceExtension = "internal"
53− allowLocationSimulation = "YES">
54− <BuildableProductRunnable
55− runnableDebuggingMode = "0">
56− <BuildableReference
57− BuildableIdentifier = "primary"
58− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
59− BuildableName = "test_Freddy"
60− BlueprintName = "test_Freddy"
61− ReferencedContainer = "container:test_Freddy.xcodeproj">
62− </BuildableReference>
63− </BuildableProductRunnable>
64− <AdditionalOptions>
65− </AdditionalOptions>
66− </LaunchAction>
67− <ProfileAction
68− buildConfiguration = "Release"
69− shouldUseLaunchSchemeArgsEnv = "YES"
70− savedToolIdentifier = ""
71− useCustomWorkingDirectory = "NO"
72− debugDocumentVersioning = "YES">
73− <BuildableProductRunnable
74− runnableDebuggingMode = "0">
75− <BuildableReference
76− BuildableIdentifier = "primary"
77− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
78− BuildableName = "test_Freddy"
79− BlueprintName = "test_Freddy"
80− ReferencedContainer = "container:test_Freddy.xcodeproj">
81− </BuildableReference>
82− </BuildableProductRunnable>
83− </ProfileAction>
84− <AnalyzeAction
85− buildConfiguration = "Debug">
86− </AnalyzeAction>
87− <ArchiveAction
88− buildConfiguration = "Release"
89− revealArchiveInOrganizer = "YES">
90− </ArchiveAction>
91−</Scheme>
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22
@@ -1,22 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3−<plist version="1.0">
4−<dict>
5− <key>SchemeUserState</key>
6− <dict>
7− <key>test_Freddy.xcscheme</key>
8− <dict>
9− <key>orderHint</key>
10− <integer>0</integer>
11− </dict>
12− </dict>
13− <key>SuppressBuildableAutocreation</key>
14− <dict>
15− <key>03D84AB61D5B0A1000776402</key>
16− <dict>
17− <key>primary</key>
18− <true/>
19− </dict>
20− </dict>
21−</dict>
22−</plist>
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSON.swiftdeleted−95
@@ -1,95 +0,0 @@
1−//
2−// JSON.swift
3−// Freddy
4−//
5−// Created by Matthew D. Mathias on 3/17/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−/// An enum to describe the structure of JSON.
10−public enum JSON {
11− /// A case for denoting an array with an associated value of `[JSON]`
12− case Array([JSON])
13− /// A case for denoting a dictionary with an associated value of `[Swift.String: JSON]`
14− case Dictionary([Swift.String: JSON])
15− /// A case for denoting a double with an associated value of `Swift.Double`.
16− case Double(Swift.Double)
17− /// A case for denoting an integer with an associated value of `Swift.Int`.
18− case Int(Swift.Int)
19− /// A case for denoting a string with an associated value of `Swift.String`.
20− case String(Swift.String)
21− /// A case for denoting a boolean with an associated value of `Swift.Bool`.
22− case Bool(Swift.Bool)
23− /// A case for denoting null.
24− case Null
25−}
26−
27−// MARK: - Errors
28−
29−extension JSON {
30−
31− /// An enum to encapsulate errors that may arise in working with `JSON`.
32− public enum Error: ErrorType {
33− /// The `index` is out of bounds for a JSON array
34− case IndexOutOfBounds(index: Swift.Int)
35−
36− /// The `key` was not found in the JSON dictionary
37− case KeyNotFound(key: Swift.String)
38−
39− /// The JSON is not subscriptable with `type`
40− case UnexpectedSubscript(type: JSONPathType.Type)
41−
42− /// Unexpected JSON `value` was found that is not convertible `to` type
43− case ValueNotConvertible(value: JSON, to: Any.Type)
44− }
45−
46−}
47−
48−// MARK: - Test Equality
49−
50−/// Return `true` if `lhs` is equal to `rhs`.
51−public func ==(lhs: JSON, rhs: JSON) -> Bool {
52− switch (lhs, rhs) {
53− case (.Array(let arrL), .Array(let arrR)):
54− return arrL == arrR
55− case (.Dictionary(let dictL), .Dictionary(let dictR)):
56− return dictL == dictR
57− case (.String(let strL), .String(let strR)):
58− return strL == strR
59− case (.Double(let dubL), .Double(let dubR)):
60− return dubL == dubR
61− case (.Double(let dubL), .Int(let intR)):
62− return dubL == Double(intR)
63− case (.Int(let intL), .Int(let intR)):
64− return intL == intR
65− case (.Int(let intL), .Double(let dubR)):
66− return Double(intL) == dubR
67− case (.Bool(let bL), .Bool(let bR)):
68− return bL == bR
69− case (.Null, .Null):
70− return true
71− default:
72− return false
73− }
74−}
75−
76−extension JSON: Equatable {}
77−
78−// MARK: - Printing
79−
80−extension JSON: CustomStringConvertible {
81−
82− /// A textual representation of `self`.
83− public var description: Swift.String {
84− switch self {
85− case .Array(let arr): return Swift.String(arr)
86− case .Dictionary(let dict): return Swift.String(dict)
87− case .String(let string): return string
88− case .Double(let double): return Swift.String(double)
89− case .Int(let int): return Swift.String(int)
90− case .Bool(let bool): return Swift.String(bool)
91− case .Null: return "null"
92− }
93− }
94−
95−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONDecodable.swiftdeleted−177
@@ -1,177 +0,0 @@
1−//
2−// JSONDecodable.swift
3−// Freddy
4−//
5−// Created by Matthew D. Mathias on 3/24/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−/// A protocol to provide functionality for creating a model object with a `JSON`
10−/// value.
11−public protocol JSONDecodable {
12−
13− /// Creates an instance of the model with a `JSON` instance.
14− /// - parameter json: An instance of a `JSON` value from which to
15− /// construct an instance of the implementing type.
16− /// - throws: Any `JSON.Error` for errors derived from inspecting the
17− /// `JSON` value, or any other error involved in decoding.
18− init(json: JSON) throws
19−
20−}
21−
22−extension Double: JSONDecodable {
23−
24− /// An initializer to create an instance of `Double` from a `JSON` value.
25− /// - parameter json: An instance of `JSON`.
26− /// - throws: The initializer will throw an instance of `JSON.Error` if
27− /// an instance of `Double` cannot be created from the `JSON` value that was
28− /// passed to this initializer.
29− public init(json: JSON) throws {
30− switch json {
31− case let .Double(double):
32− self = double
33− case let .Int(int):
34− self = Swift.Double(int)
35− default:
36− throw JSON.Error.ValueNotConvertible(value: json, to: Swift.Double)
37− }
38− }
39−
40−}
41−
42−extension Int: JSONDecodable {
43−
44− /// An initializer to create an instance of `Int` from a `JSON` value.
45− /// - parameter json: An instance of `JSON`.
46− /// - throws: The initializer will throw an instance of `JSON.Error` if
47− /// an instance of `Int` cannot be created from the `JSON` value that was
48− /// passed to this initializer.
49− public init(json: JSON) throws {
50− switch json {
51− case let .Double(double) where double <= Double(Swift.Int.max):
52− self = Swift.Int(double)
53− case let .Int(int):
54− self = int
55− default:
56− throw JSON.Error.ValueNotConvertible(value: json, to: Swift.Int)
57− }
58− }
59−
60−}
61−
62−extension String: JSONDecodable {
63−
64− /// An initializer to create an instance of `String` from a `JSON` value.
65− /// - parameter json: An instance of `JSON`.
66− /// - throws: The initializer will throw an instance of `JSON.Error` if
67− /// an instance of `String` cannot be created from the `JSON` value that was
68− /// passed to this initializer.
69− public init(json: JSON) throws {
70−
71− switch json {
72− case let .String(string):
73− self = string
74− case let .Int(int):
75− self = String(int)
76− case let .Bool(bool):
77− self = String(bool)
78− case let .Double(double):
79− self = String(double)
80− default:
81− throw JSON.Error.ValueNotConvertible(value: json, to: Swift.String)
82− }
83− }
84−
85−}
86−
87−extension Bool: JSONDecodable {
88−
89− /// An initializer to create an instance of `Bool` from a `JSON` value.
90− /// - parameter json: An instance of `JSON`.
91− /// - throws: The initializer will throw an instance of `JSON.Error` if
92− /// an instance of `Bool` cannot be created from the `JSON` value that was
93− /// passed to this initializer.
94− public init(json: JSON) throws {
95− guard case let .Bool(bool) = json else {
96− throw JSON.Error.ValueNotConvertible(value: json, to: Swift.Bool)
97− }
98− self = bool
99− }
100−
101−}
102−
103−extension RawRepresentable where RawValue: JSONDecodable {
104−
105− /// An initializer to create an instance of `RawRepresentable` from a `JSON` value.
106− /// - parameter json: An instance of `JSON`.
107− /// - throws: The initializer will throw an instance of `JSON.Error` if
108− /// an instance of `RawRepresentable` cannot be created from the `JSON` value that was
109− /// passed to this initializer.
110− public init(json: JSON) throws {
111− let raw = try json.decode(type: RawValue.self)
112− guard let value = Self(rawValue: raw) else {
113− throw JSON.Error.ValueNotConvertible(value: json, to: Self.self)
114− }
115− self = value
116− }
117−}
118−
119−internal extension JSON {
120−
121− /// Retrieves a `[JSON]` from the JSON.
122− /// - parameter: A `JSON` to be used to create the returned `Array`.
123− /// - returns: An `Array` of `JSON` elements
124− /// - throws: Any of the `JSON.Error` cases thrown by `decode(type:)`.
125− /// - seealso: `JSON.decode(_:type:)`
126− static func getArray(json: JSON) throws -> [JSON] {
127− // Ideally should be expressed as a conditional protocol implementation on Swift.Array.
128− guard case let .Array(array) = json else {
129− throw Error.ValueNotConvertible(value: json, to: Swift.Array<JSON>)
130− }
131− return array
132− }
133−
134− /// Retrieves a `[String: JSON]` from the JSON.
135− /// - parameter: A `JSON` to be used to create the returned `Dictionary`.
136− /// - returns: An `Dictionary` of `String` mapping to `JSON` elements
137− /// - throws: Any of the `JSON.Error` cases thrown by `decode(type:)`.
138− /// - seealso: `JSON.decode(_:type:)`
139− static func getDictionary(json: JSON) throws -> [Swift.String: JSON] {
140− // Ideally should be expressed as a conditional protocol implementation on Swift.Dictionary.
141− guard case let .Dictionary(dictionary) = json else {
142− throw Error.ValueNotConvertible(value: json, to: Swift.Dictionary<Swift.String, JSON>)
143− }
144− return dictionary
145− }
146−
147− /// Attempts to decode many values from a descendant JSON array at a path
148− /// into JSON.
149− /// - parameter: A `JSON` to be used to create the returned `Array` of some type conforming to `JSONDecodable`.
150− /// - returns: An `Array` of `Decoded` elements.
151− /// - throws: Any of the `JSON.Error` cases thrown by `decode(type:)`, as
152− /// well as any error that arises from decoding the contained values.
153− /// - seealso: `JSON.decode(_:type:)`
154− static func getArrayOf<Decoded: JSONDecodable>(json: JSON) throws -> [Decoded] {
155− // Ideally should be expressed as a conditional protocol implementation on Swift.Dictionary.
156− // This implementation also doesn't do the `type = Type.self` trick.
157− return try getArray(json).map(Decoded.init)
158− }
159−
160− /// Attempts to decode many values from a descendant JSON object at a path
161− /// into JSON.
162− /// - returns: A `Dictionary` of string keys and `Decoded` values.
163− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)` or
164− /// any error that arises from decoding the contained values.
165− /// - seealso: `JSON.decode(_:type:)`
166− static func getDictionaryOf<Decoded: JSONDecodable>(json: JSON) throws -> [Swift.String: Decoded] {
167− guard case let .Dictionary(dictionary) = json else {
168− throw Error.ValueNotConvertible(value: json, to: Swift.Dictionary<Swift.String, Decoded>)
169− }
170− var decodedDictionary = Swift.Dictionary<Swift.String, Decoded>(minimumCapacity: dictionary.count)
171− for (key, value) in dictionary {
172− decodedDictionary[key] = try Decoded(json: value)
173− }
174− return decodedDictionary
175− }
176−
177−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONEncodable.swiftdeleted−83
@@ -1,83 +0,0 @@
1−//
2−// JSONEncodable.swift
3−// Freddy
4−//
5−// Created by Matthew Mathias on 1/4/16.
6−// Copyright © 2016 Big Nerd Ranch. All rights reserved.
7−//
8−
9−import Foundation
10−
11−/// A protocol to facilitate encoding and decoding of `JSON`.
12−public protocol JSONEncodable {
13− /// Converts an instance of a conforming type to `JSON`.
14− /// - returns: An instance of `JSON`.
15− /// - Note: If conforming to `JSONEncodable` with a custom type of your own, you should return an instance of
16− /// `JSON.Dictionary`.
17− func toJSON() -> JSON
18−}
19−
20−extension Array where Element: JSONEncodable {
21− /// Converts an instance of `Array` whose elements conform to `JSONEncodable` to `JSON`.
22− /// - returns: An instance of `JSON` where the enum case is `.Array`.
23− public func toJSON() -> JSON {
24− let arrayOfJSON = self.map { $0.toJSON() }
25− return .Array(arrayOfJSON)
26− }
27−}
28−
29−extension Dictionary where Value: JSONEncodable {
30− /// Converts an instance of `Dictionary` whose values conform to `JSONEncodable` to `JSON`. The keys in the resulting
31− /// `JSON.Dictionary` will be of type `String`.
32− /// - returns: An instance of `JSON` where the enum case is `.Dictionary`.
33− public func toJSON() -> JSON {
34− var jsonDictionary = [String: JSON]()
35−
36− for (k, v) in self {
37− let key = String(k)
38− jsonDictionary[key] = v.toJSON()
39− }
40−
41− return .Dictionary(jsonDictionary)
42− }
43−}
44−
45−extension Int: JSONEncodable {
46− /// Converts an instance of a conforming type to `JSON`.
47− /// - returns: An instance of `JSON` where the enum case is `.Int`.
48− public func toJSON() -> JSON {
49− return .Int(self)
50− }
51−}
52−
53−extension Double: JSONEncodable {
54− /// Converts an instance of a conforming type to `JSON`.
55− /// - returns: An instance of `JSON` where the enum case is `.Double`.
56− public func toJSON() -> JSON {
57− return .Double(self)
58− }
59−}
60−
61−extension String: JSONEncodable {
62− /// Converts an instance of a conforming type to `JSON`.
63− /// - returns: An instance of `JSON` where the enum case is `.String`.
64− public func toJSON() -> JSON {
65− return .String(self)
66− }
67−}
68−
69−extension Bool: JSONEncodable {
70− /// Converts an instance of a conforming type to `JSON`.
71− /// - returns: An instance of `JSON` where the enum case is `.Bool`.
72− public func toJSON() -> JSON {
73− return .Bool(self)
74− }
75−}
76−
77−extension RawRepresentable where RawValue: JSONEncodable {
78− /// Converts an instance of a conforming type to `JSON`.
79− /// - returns: An instance of `JSON` where the enum case is whatever the underlying `RawValue` converts to.
80− public func toJSON() -> JSON {
81− return rawValue.toJSON()
82− }
83−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONEncodingDetector.swiftdeleted−110
@@ -1,110 +0,0 @@
1−//
2−// JSONEncodingDetector.swift
3−// Freddy
4−//
5−// Created by Robert Edwards on 1/27/16.
6−// Copyright © 2016 Big Nerd Ranch. All rights reserved.
7−//
8−
9−/// Struct for attempting to detect the Unicode encoding used with the data supplied to the JSONParser
10−public struct JSONEncodingDetector {
11−
12− //// The Unicode encodings looked for during detection
13− public enum Encoding {
14− //// UTF-8
15− case UTF8
16− //// UTF-16 Little Endian
17− case UTF16LE
18− //// UTF-16 Big Endian
19− case UTF16BE
20− //// UTF-32 Little Endian
21− case UTF32LE
22− //// UTF-32 Big Endian
23− case UTF32BE
24− }
25−
26− //// The Unicode encodings supported by JSONParser.swift
27− public static let supportedEncodings: [Encoding] = [.UTF8]
28−
29− typealias ByteStreamPrefixInformation = (encoding: Encoding, byteOrderMarkLength: Int)
30−
31− //// Attempts to detect the Unicode encoding used for a given set of data.
32− ////
33− //// This function initially looks for a Byte Order Mark in the following form:
34− ////
35− //// Bytes | Encoding Form
36− //// --------------|----------------
37− //// 00 00 FE FF | UTF-32, big-endian
38− //// FF FE 00 00 | UTF-32, little-endian
39− //// FE FF | UTF-16, big-endian
40− //// FF FE | UTF-16, little-endian
41− //// EF BB BF | UTF-8
42− ////
43− //// If a BOM is not found then we detect using the following approach described in
44− //// the JSON RFC http://www.ietf.org/rfc/rfc4627.txt:
45− ////
46− //// Since the first two characters of a JSON text will always be ASCII
47− //// characters [RFC0020], it is possible to determine whether an octet
48− //// stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
49− //// at the pattern of nulls in the first four octets.
50− ////
51− //// 00 00 00 xx UTF-32BE
52− //// 00 xx 00 xx UTF-16BE
53− //// xx 00 00 00 UTF-32LE
54− //// xx 00 xx 00 UTF-16LE
55− //// xx xx xx xx UTF-8
56− ////
57− //// - parameter header: The front Slice of data being read and evaluated.
58− //// - returns: A tuple containing the detected Unicode encoding and the lenght of the byte order mark.
59− static func detectEncoding(header: Slice<UnsafeBufferPointer<UInt8>>) -> ByteStreamPrefixInformation {
60−
61− guard let prefix = prefixFromHeader(header) else {
62− return (.UTF8, 0)
63− }
64−
65− if let prefixInfo = JSONEncodingDetector.encodingFromBOM(prefix) {
66− return prefixInfo
67− } else {
68− switch prefix {
69− case(0, 0, 0?, _):
70− return (.UTF32BE, 0)
71− case(_, 0, 0?, 0?):
72− return (.UTF32LE, 0)
73− case (0, _, 0?, _), (0, _, _, _):
74− return (.UTF16BE, 0)
75− case (_, 0, _, 0?), (_, 0, _, _):
76− return (.UTF16LE, 0)
77− default:
78− return (.UTF8, 0)
79− }
80− }
81− }
82−
83− private typealias EncodingBytePrefix = (UInt8, UInt8, UInt8?, UInt8?)
84−
85− private static func prefixFromHeader(header: Slice<UnsafeBufferPointer<UInt8>>) -> EncodingBytePrefix? {
86− if header.count >= 4 {
87− return(header[0], header[1], header[2], header[3])
88− } else if header.count >= 2 {
89− return (header[0], header[1], nil, nil)
90− }
91− return nil
92− }
93−
94− private static func encodingFromBOM(prefix: EncodingBytePrefix) -> ByteStreamPrefixInformation? {
95− switch prefix {
96− case(0xFE, 0xFF, _, _):
97− return (.UTF16BE, 2)
98− case(0x00, 0x00, 0xFE?, 0xFF?):
99− return (.UTF32BE, 4)
100− case(0xEF, 0xBB, 0xBF?, _):
101− return (.UTF8, 3)
102− case(0xFF, 0xFE, 0?, 0?):
103− return (.UTF32LE, 4)
104− case(0xFF, 0xFE, _, _):
105− return (.UTF16LE, 2)
106− default:
107− return nil
108− }
109− }
110−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONLiteralConvertible.swiftdeleted−130
@@ -1,130 +0,0 @@
1−//
2−// JSONLiteralConvertible.swift
3−// Freddy
4−//
5−// Created by Zachary Waldowski on 5/11/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−// MARK: - ArrayLiteralConvertible
10−
11−extension JSON: ArrayLiteralConvertible {
12−
13− /// Create an instance by copying each element of the `collection` into a
14− /// new `Array`.
15− public init<Collection: CollectionType where Collection.Generator.Element == JSON>(_ collection: Collection) {
16− self = .Array(Swift.Array(collection))
17− }
18−
19− /// Create an instance initialized with `elements`.
20− public init(arrayLiteral elements: JSON...) {
21− self.init(elements)
22− }
23−
24−}
25−
26−// MARK: - DictionaryLiteralConvertible
27−
28−extension JSON: DictionaryLiteralConvertible {
29−
30− /// Create an instance by copying each key/value pair of the `pairs` into
31− /// a new `Dictionary`.
32− public init<Dictionary: SequenceType where Dictionary.Generator.Element == (Swift.String, JSON)>(_ pairs: Dictionary) {
33− var dictionary = Swift.Dictionary<Swift.String, JSON>(minimumCapacity: pairs.underestimateCount())
34− for (key, value) in pairs {
35− dictionary[key] = value
36− }
37− self = .Dictionary(dictionary)
38− }
39−
40− /// Create an instance initialized with `pairs`.
41− public init(dictionaryLiteral pairs: (Swift.String, JSON)...) {
42− self.init(pairs)
43− }
44−
45−}
46−
47−// MARK: - FloatLiteralConvertible
48−
49−extension JSON: FloatLiteralConvertible {
50−
51− /// Create an instance initialized to `Double` `value`.
52− public init(_ value: Swift.Double) {
53− self = .Double(value)
54− }
55−
56− /// Create a literal instance initialized to `value`.
57− public init(floatLiteral value: Swift.Double) {
58− self.init(value)
59− }
60−
61−}
62−
63−// MARK: - IntegerLiteralConvertible
64−
65−extension JSON: IntegerLiteralConvertible {
66−
67− /// Create an instance initialized to `Int` by `value`.
68− public init(_ value: Swift.Int) {
69− self = .Int(value)
70− }
71−
72− /// Create a literal instance initialized to `value`.
73− public init(integerLiteral value: Swift.Int) {
74− self.init(value)
75− }
76−
77−}
78−
79−// MARK: - StringLiteralConvertible
80−
81−extension JSON: StringLiteralConvertible {
82−
83− /// Create an instance initialized to `String` by `text`.
84− public init(_ text: Swift.String) {
85− self = .String(text)
86− }
87−
88− /// Create a literal instance initialized to `value`.
89− public init(stringLiteral value: StringLiteralType) {
90− self.init(value)
91− }
92−
93− /// Create a literal instance initialized to `value`.
94− public init(extendedGraphemeClusterLiteral value: StringLiteralType) {
95− self.init(value)
96− }
97−
98− /// Create a literal instance initialized to `value`.
99− public init(unicodeScalarLiteral value: StringLiteralType) {
100− self.init(value)
101− }
102−
103−}
104−
105−// MARK: - BooleanLiteralConvertible
106−
107−extension JSON: BooleanLiteralConvertible {
108−
109− /// Create an instance initialized to `Bool` by `value`.
110− public init(_ value: Swift.Bool) {
111− self = .Bool(value)
112− }
113−
114− /// Create a literal instance initialized to `value`.
115− public init(booleanLiteral value: Swift.Bool) {
116− self.init(value)
117− }
118−
119−}
120−
121−// MARK: - NilLiteralConvertible
122−
123−extension JSON: NilLiteralConvertible {
124−
125− /// Create an instance initialized with `nil`.
126− public init(nilLiteral: ()) {
127− self = .Null
128− }
129−
130−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONParser.swiftdeleted−907
@@ -1,907 +0,0 @@
1−//
2−// JSONParser.swift
3−// Freddy
4−//
5−// Created by John Gallagher on 4/18/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−import Foundation
10−
11−private struct Literal {
12− static let BACKSLASH = UInt8(ascii: "\\")
13− static let BACKSPACE = UInt8(ascii: "\u{0008}")
14− static let COLON = UInt8(ascii: ":")
15− static let COMMA = UInt8(ascii: ",")
16− static let DOUBLE_QUOTE = UInt8(ascii: "\"")
17− static let FORMFEED = UInt8(ascii: "\u{000c}")
18− static let LEFT_BRACE = UInt8(ascii: "{")
19− static let LEFT_BRACKET = UInt8(ascii: "[")
20− static let MINUS = UInt8(ascii: "-")
21− static let NEWLINE = UInt8(ascii: "\n")
22− static let PERIOD = UInt8(ascii: ".")
23− static let PLUS = UInt8(ascii: "+")
24− static let RETURN = UInt8(ascii: "\r")
25− static let RIGHT_BRACE = UInt8(ascii: "}")
26− static let RIGHT_BRACKET = UInt8(ascii: "]")
27− static let SLASH = UInt8(ascii: "/")
28− static let SPACE = UInt8(ascii: " ")
29− static let TAB = UInt8(ascii: "\t")
30−
31− static let a = UInt8(ascii: "a")
32− static let b = UInt8(ascii: "b")
33− static let c = UInt8(ascii: "c")
34− static let d = UInt8(ascii: "d")
35− static let e = UInt8(ascii: "e")
36− static let f = UInt8(ascii: "f")
37− static let l = UInt8(ascii: "l")
38− static let n = UInt8(ascii: "n")
39− static let r = UInt8(ascii: "r")
40− static let s = UInt8(ascii: "s")
41− static let t = UInt8(ascii: "t")
42− static let u = UInt8(ascii: "u")
43−
44− static let A = UInt8(ascii: "A")
45− static let B = UInt8(ascii: "B")
46− static let C = UInt8(ascii: "C")
47− static let D = UInt8(ascii: "D")
48− static let E = UInt8(ascii: "E")
49− static let F = UInt8(ascii: "F")
50−
51− static let zero = UInt8(ascii: "0")
52− static let one = UInt8(ascii: "1")
53− static let two = UInt8(ascii: "2")
54− static let three = UInt8(ascii: "3")
55− static let four = UInt8(ascii: "4")
56− static let five = UInt8(ascii: "5")
57− static let six = UInt8(ascii: "6")
58− static let seven = UInt8(ascii: "7")
59− static let eight = UInt8(ascii: "8")
60− static let nine = UInt8(ascii: "9")
61−}
62−
63−private let ParserMaximumDepth = 512
64−
65−
66−/// A pure Swift JSON parser. This parser is much faster than the
67−/// `NSJSONSerialization`-based parser (due to the overhead of having to
68−/// dynamically cast the Objective-C objects to determine their type); however,
69−/// it is much newer and has restrictions that the `NSJSONSerialization` parser
70−/// does not. Two restrictions in particular are that it requires UTF-8 data as
71−/// input and it does not allow trailing commas in arrays or dictionaries.
72−public struct JSONParser {
73−
74− private enum Sign: Int {
75− case Positive = 1
76− case Negative = -1
77− }
78−
79− private let input: UnsafeBufferPointer<UInt8>
80− private let owner: Any?
81− private var loc = 0
82− private var depth = 0
83−
84− private init<T>(buffer: UnsafeBufferPointer<UInt8>, owner: T) {
85− self.input = buffer
86− self.owner = owner
87− }
88−
89− /// Decode the root element of the `JSON` stream. This may be any fragment
90− /// or a structural element, per RFC 7159.
91− ///
92− /// The beginning bytes are used to determine the stream's encoding.
93− /// `JSONParser` currently only supports UTF-8 encoding, with or without
94− /// a byte-order mark.
95− ///
96− /// - throws: `JSONParser.Error` for any decoding failures, including a
97− /// source location if needed.
98− public mutating func parse() throws -> JSON {
99− try guardAgainstUnsupportedEncodings()
100− let value = try parseValue()
101− skipWhitespace()
102− guard loc == input.count else {
103− throw Error.EndOfStreamGarbage(offset: loc)
104− }
105− return value
106− }
107−
108− private mutating func parseValue() throws -> JSON {
109− guard depth <= ParserMaximumDepth else {
110− throw Error.ExceededNestingLimit(offset: loc)
111− }
112−
113− guard input.count > 0 else {
114− throw Error.EndOfStreamUnexpected
115− }
116−
117− advancing: while loc < input.count {
118− do {
119− switch input[loc] {
120− case Literal.LEFT_BRACKET:
121− depth += 1
122− defer { depth -= 1 }
123− return try decodeArray()
124−
125− case Literal.LEFT_BRACE:
126− depth += 1
127− defer { depth -= 1 }
128− return try decodeObject()
129−
130− case Literal.DOUBLE_QUOTE:
131− return try decodeString()
132−
133− case Literal.f:
134− return try decodeFalse()
135−
136− case Literal.n:
137− return try decodeNull()
138−
139− case Literal.t:
140− return try decodeTrue()
141−
142− case Literal.MINUS:
143− return try decodeIntegralValue(NumberParser(loc: loc, input: input, state: .LeadingMinus))
144−
145− case Literal.zero:
146− return try decodeIntegralValue(NumberParser(loc: loc, input: input, state: .LeadingZero))
147−
148− case Literal.one...Literal.nine:
149− return try decodeIntegralValue(NumberParser(loc: loc, input: input, state: .PreDecimalDigits))
150−
151− case Literal.SPACE, Literal.TAB, Literal.RETURN, Literal.NEWLINE:
152− loc = loc.successor()
153−
154− default:
155− break advancing
156− }
157− } catch let InternalError.NumberOverflow(offset: start) {
158− return try decodeNumberAsString(start)
159− }
160− }
161−
162− if loc < input.count {
163− throw Error.ValueInvalid(offset: loc, character: UnicodeScalar(input[loc]))
164− } else {
165− throw Error.EndOfStreamUnexpected
166− }
167− }
168−
169− private mutating func skipWhitespace() {
170− while loc < input.count {
171− switch input[loc] {
172− case Literal.SPACE, Literal.TAB, Literal.RETURN, Literal.NEWLINE:
173− loc = loc.successor()
174−
175− default:
176− return
177− }
178− }
179− }
180−
181− private mutating func guardAgainstUnsupportedEncodings() throws {
182− let header = input.prefix(4)
183− let encodingPrefixInformation = JSONEncodingDetector.detectEncoding(header)
184− guard JSONEncodingDetector.supportedEncodings.contains(encodingPrefixInformation.encoding) else {
185− throw Error.InvalidUnicodeStreamEncoding(detectedEncoding: encodingPrefixInformation.encoding)
186− }
187− loc = loc.advancedBy(encodingPrefixInformation.byteOrderMarkLength)
188− }
189−
190− private mutating func decodeNull() throws -> JSON {
191− guard loc.advancedBy(3, limit: input.count) != input.count else {
192− throw Error.LiteralNilMisspelled(offset: loc)
193− }
194−
195− if input[loc+1] != Literal.u
196− || input[loc+2] != Literal.l
197− || input[loc+3] != Literal.l {
198− throw Error.LiteralNilMisspelled(offset: loc)
199− }
200−
201− loc += 4
202− return .Null
203− }
204−
205− private mutating func decodeTrue() throws -> JSON {
206− guard loc.advancedBy(3, limit: input.count) != input.count else {
207− throw Error.LiteralTrueMisspelled(offset: loc)
208− }
209−
210− if input[loc+1] != Literal.r
211− || input[loc+2] != Literal.u
212− || input[loc+3] != Literal.e {
213− throw Error.LiteralTrueMisspelled(offset: loc)
214− }
215−
216− loc += 4
217− return .Bool(true)
218− }
219−
220− private mutating func decodeFalse() throws -> JSON {
221− guard loc.advancedBy(4, limit: input.count) != input.count else {
222− throw Error.LiteralFalseMisspelled(offset: loc)
223− }
224−
225− if input[loc+1] != Literal.a
226− || input[loc+2] != Literal.l
227− || input[loc+3] != Literal.s
228− || input[loc+4] != Literal.e {
229− throw Error.LiteralFalseMisspelled(offset: loc)
230− }
231−
232− loc += 5
233− return .Bool(false)
234− }
235−
236− private var stringDecodingBuffer = [UInt8]()
237− private mutating func decodeString() throws -> JSON {
238− let start = loc
239− loc = loc.successor()
240− stringDecodingBuffer.removeAll(keepCapacity: true)
241− while loc < input.count {
242− switch input[loc] {
243− case Literal.BACKSLASH:
244− loc = loc.successor()
245− switch input[loc] {
246− case Literal.DOUBLE_QUOTE: stringDecodingBuffer.append(Literal.DOUBLE_QUOTE)
247− case Literal.BACKSLASH: stringDecodingBuffer.append(Literal.BACKSLASH)
248− case Literal.SLASH: stringDecodingBuffer.append(Literal.SLASH)
249− case Literal.b: stringDecodingBuffer.append(Literal.BACKSPACE)
250− case Literal.f: stringDecodingBuffer.append(Literal.FORMFEED)
251− case Literal.r: stringDecodingBuffer.append(Literal.RETURN)
252− case Literal.t: stringDecodingBuffer.append(Literal.TAB)
253− case Literal.n: stringDecodingBuffer.append(Literal.NEWLINE)
254− case Literal.u:
255− loc = loc.successor()
256− try readUnicodeEscape(start: loc - 2)
257−
258− // readUnicodeEscape() advances loc on its own, so we'll `continue` now
259− // to skip the typical "advance past this character" for all the other escapes
260− continue
261−
262− default:
263− throw Error.ControlCharacterUnrecognized(offset: loc)
264− }
265− loc = loc.successor()
266−
267− case Literal.DOUBLE_QUOTE:
268− loc = loc.successor()
269− stringDecodingBuffer.append(0)
270−
271− guard let string = (stringDecodingBuffer.withUnsafeBufferPointer {
272− String.fromCString(UnsafePointer($0.baseAddress))
273− }) else {
274− throw Error.UnicodeEscapeInvalid(offset: start)
275− }
276−
277− return .String(string)
278−
279− case let other:
280− stringDecodingBuffer.append(other)
281− loc = loc.successor()
282− }
283− }
284−
285− throw Error.EndOfStreamUnexpected
286− }
287−
288− private mutating func readCodeUnit() -> UInt16? {
289− guard loc + 4 <= input.count else {
290− return nil
291− }
292− var codeUnit: UInt16 = 0
293− for c in input[loc..<loc+4] {
294− let nibble: UInt16
295−
296− switch c {
297− case Literal.zero...Literal.nine:
298− nibble = UInt16(c - Literal.zero)
299−
300− case Literal.a...Literal.f:
301− nibble = 10 + UInt16(c - Literal.a)
302−
303− case Literal.A...Literal.F:
304− nibble = 10 + UInt16(c - Literal.A)
305−
306− default:
307− return nil
308− }
309− codeUnit = (codeUnit << 4) | nibble
310− }
311− loc += 4
312− return codeUnit
313− }
314−
315− private mutating func readUnicodeEscape(start start: Int) throws {
316− guard let codeUnit = readCodeUnit() else {
317− throw Error.UnicodeEscapeInvalid(offset: start)
318− }
319−
320− let codeUnits: [UInt16]
321−
322− if UTF16.isLeadSurrogate(codeUnit) {
323− // First half of a UTF16 surrogate pair - we must parse another code unit and combine them
324−
325− // First confirm and skip over that we have another "\u"
326− guard loc + 6 <= input.count && input[loc] == Literal.BACKSLASH && input[loc+1] == Literal.u else {
327− throw Error.UnicodeEscapeInvalid(offset: start)
328− }
329− loc += 2
330−
331− // Ensure the second code unit is valid for the surrogate pair
332− guard let secondCodeUnit = readCodeUnit() where UTF16.isTrailSurrogate(secondCodeUnit) else {
333− throw Error.UnicodeEscapeInvalid(offset: start)
334− }
335−
336− codeUnits = [codeUnit, secondCodeUnit]
337− } else {
338− codeUnits = [codeUnit]
339− }
340−
341− let transcodeHadError = transcode(UTF16.self, UTF8.self, codeUnits.generate(), { self.stringDecodingBuffer.append($0) }, stopOnError: true)
342−
343− if transcodeHadError {
344− throw Error.UnicodeEscapeInvalid(offset: start)
345− }
346− }
347−
348− private mutating func decodeArray() throws -> JSON {
349− let start = loc
350− loc = loc.successor()
351− var items = [JSON]()
352−
353− while loc < input.count {
354− skipWhitespace()
355−
356− if loc < input.count && input[loc] == Literal.RIGHT_BRACKET {
357− loc = loc.successor()
358− return .Array(items)
359− }
360−
361− if !items.isEmpty {
362− guard loc < input.count && input[loc] == Literal.COMMA else {
363− throw Error.CollectionMissingSeparator(offset: start)
364− }
365− loc = loc.successor()
366− }
367−
368− items.append(try parseValue())
369− }
370−
371− throw Error.EndOfStreamUnexpected
372− }
373−
374− // Decoding objects can be recursive, so we have to keep more than one
375− // buffer around for building up key/value pairs (to reduce allocations
376− // when parsing large JSON documents).
377− //
378− // Rough estimate of the difference between this and using a fresh
379− // [(String,JSON)] for the `pairs` variable in decodeObject() below is
380− // about 12% on an iPhone 5.
381− private struct DecodeObjectBuffers {
382− var buffers = [[(String,JSON)]]()
383−
384− mutating func getBuffer() -> [(String,JSON)] {
385− if !buffers.isEmpty {
386− var buffer = buffers.removeLast()
387− buffer.removeAll(keepCapacity: true)
388− return buffer
389− }
390− return [(String,JSON)]()
391− }
392−
393− mutating func putBuffer(buffer: [(String,JSON)]) {
394− buffers.append(buffer)
395− }
396− }
397−
398− private var decodeObjectBuffers = DecodeObjectBuffers()
399−
400− private mutating func decodeObject() throws -> JSON {
401− let start = loc
402− loc = loc.successor()
403− var pairs = decodeObjectBuffers.getBuffer()
404−
405− while loc < input.count {
406− skipWhitespace()
407−
408− if loc < input.count && input[loc] == Literal.RIGHT_BRACE {
409− loc = loc.successor()
410− var obj = [String:JSON](minimumCapacity: pairs.count)
411− for (k, v) in pairs {
412− obj[k] = v
413− }
414− decodeObjectBuffers.putBuffer(pairs)
415− return .Dictionary(obj)
416− }
417−
418− if !pairs.isEmpty {
419− guard loc < input.count && input[loc] == Literal.COMMA else {
420− throw Error.CollectionMissingSeparator(offset: start)
421− }
422− loc = loc.successor()
423−
424− skipWhitespace()
425− }
426−
427− guard loc < input.count && input[loc] == Literal.DOUBLE_QUOTE else {
428− throw Error.DictionaryMissingKey(offset: start)
429− }
430−
431− let key = try decodeString().string()
432− skipWhitespace()
433−
434− guard loc < input.count && input[loc] == Literal.COLON else {
435− throw Error.CollectionMissingSeparator(offset: start)
436− }
437− loc = loc.successor()
438−
439− pairs.append((key, try parseValue()))
440− }
441−
442− throw Error.EndOfStreamUnexpected
443− }
444−
445− private mutating func decodeIntegralValue(parser: NumberParser) throws -> JSON {
446− var sign = Sign.Positive
447− var parser = parser
448− var value = 0
449−
450− // This would be more natural as `while true { ... }` with a meaningful .Done case,
451− // but that causes compile time explosion in Swift 2.2. :-|
452− while parser.state != .Done {
453− switch parser.state {
454− case .LeadingMinus:
455− sign = .Negative
456− try parser.parseNegative()
457−
458− case .LeadingZero:
459− parser.parseLeadingZero()
460−
461− case .PreDecimalDigits:
462− try parser.parsePreDecimalDigits { c in
463− guard case let (exponent, false) = Int.multiplyWithOverflow(10, value) else {
464− throw InternalError.NumberOverflow(offset: parser.start)
465− }
466−
467− guard case let (newValue, false) = Int.addWithOverflow(exponent, Int(c - Literal.zero)) else {
468− throw InternalError.NumberOverflow(offset: parser.start)
469− }
470−
471− value = newValue
472− }
473−
474− case .Decimal, .Exponent:
475− return try detectingFloatingPointErrors(parser.start) {
476− try decodeFloatingPointValue(parser, sign: sign, value: Double(value))
477− }
478−
479− case .PostDecimalDigits, .ExponentSign, .ExponentDigits:
480− assertionFailure("Invalid internal state while parsing number")
481−
482− case .Done:
483− fatalError("impossible condition")
484− }
485− }
486−
487− guard case let (signedValue, false) = Int.multiplyWithOverflow(sign.rawValue, value) else {
488− throw InternalError.NumberOverflow(offset: parser.start)
489− }
490−
491− loc = parser.loc
492− return .Int(signedValue)
493− }
494−
495− private mutating func decodeFloatingPointValue(parser: NumberParser, sign: Sign, value: Double) throws -> JSON {
496− var parser = parser
497− var value = value
498− var exponentSign = Sign.Positive
499− var exponent = Double(0)
500− var position = 0.1
501−
502− // This would be more natural as `while true { ... }` with a meaningful .Done case,
503− // but that causes compile time explosion in Swift 2.2. :-|
504− while parser.state != .Done {
505− switch parser.state {
506− case .LeadingMinus, .LeadingZero, .PreDecimalDigits:
507− assertionFailure("Invalid internal state while parsing number")
508−
509− case .Decimal:
510− try parser.parseDecimal()
511−
512− case .PostDecimalDigits:
513− parser.parsePostDecimalDigits { c in
514− value += position * Double(c - Literal.zero)
515− position /= 10
516− }
517−
518− case .Exponent:
519− exponentSign = try parser.parseExponent()
520−
521− case .ExponentSign:
522− try parser.parseExponentSign()
523−
524− case .ExponentDigits:
525− parser.parseExponentDigits { c in
526− exponent = exponent * 10 + Double(c - Literal.zero)
527− }
528−
529− case .Done:
530− fatalError("impossible condition")
531− }
532− }
533−
534− loc = parser.loc
535− return .Double(Double(sign.rawValue) * value * pow(10, Double(exponentSign.rawValue) * exponent))
536− }
537−
538− private mutating func decodeNumberAsString(start: Int) throws -> JSON {
539− var parser: NumberParser = {
540− let state: NumberParser.State
541− switch input[start] {
542− case Literal.MINUS: state = .LeadingMinus
543− case Literal.zero: state = .LeadingZero
544− case Literal.one...Literal.nine: state = .PreDecimalDigits
545− default:
546− fatalError("Internal error: decodeNumber called on not-a-number")
547− }
548− return NumberParser(loc: start, input: input, state: state)
549− }()
550−
551− stringDecodingBuffer.removeAll(keepCapacity: true)
552−
553− while true {
554− switch parser.state {
555− case .LeadingMinus:
556− try parser.parseNegative()
557− stringDecodingBuffer.append(Literal.MINUS)
558−
559− case .LeadingZero:
560− parser.parseLeadingZero()
561− stringDecodingBuffer.append(Literal.zero)
562−
563− case .PreDecimalDigits:
564− parser.parsePreDecimalDigits { stringDecodingBuffer.append($0) }
565−
566− case .Decimal:
567− try parser.parseDecimal()
568− stringDecodingBuffer.append(Literal.PERIOD)
569−
570− case .PostDecimalDigits:
571− parser.parsePostDecimalDigits { stringDecodingBuffer.append($0) }
572−
573− case .Exponent:
574− stringDecodingBuffer.append(input[parser.loc])
575− _ = try parser.parseExponent()
576−
577− case .ExponentSign:
578− stringDecodingBuffer.append(input[parser.loc])
579− try parser.parseExponentSign()
580−
581− case .ExponentDigits:
582− parser.parseExponentDigits { stringDecodingBuffer.append($0) }
583−
584− case .Done:
585− stringDecodingBuffer.append(0)
586− guard let string = (stringDecodingBuffer.withUnsafeBufferPointer {
587− String.fromCString(UnsafePointer($0.baseAddress))
588− }) else {
589− // Should never fail - any problems with the number string should
590− // result in thrown errors above
591− fatalError("Internal error: Invalid numeric string")
592− }
593−
594− loc = parser.loc
595− return .String(string)
596− }
597− }
598− }
599−
600− private func detectingFloatingPointErrors<T>(loc: Int, @noescape _ f: () throws -> T) throws -> T {
601− let flags = FE_UNDERFLOW | FE_OVERFLOW
602− feclearexcept(flags)
603− let value = try f()
604− guard fetestexcept(flags) == 0 else {
605− throw InternalError.NumberOverflow(offset: loc)
606− }
607− return value
608− }
609−}
610−
611−private struct NumberParser {
612− enum State {
613− case LeadingMinus
614− case LeadingZero
615− case PreDecimalDigits
616− case Decimal
617− case PostDecimalDigits
618− case Exponent
619− case ExponentSign
620− case ExponentDigits
621− case Done
622− }
623−
624− let start: Int
625− var loc = 0
626− var state: State
627− let input: UnsafeBufferPointer<UInt8>
628−
629− init(loc: Int, input: UnsafeBufferPointer<UInt8>, state: State) {
630− assert(loc < input.count, "Invalid input to NumberParser")
631− self.start = loc
632− self.loc = loc
633− self.input = input
634− self.state = state
635− }
636−
637− mutating func parseNegative() throws {
638− assert(state == .LeadingMinus, "Unexpected state entering parseNegative")
639−
640− loc = loc.successor()
641− guard loc < input.count else {
642− throw JSONParser.Error.EndOfStreamUnexpected
643− }
644−
645− switch input[loc] {
646− case Literal.zero:
647− state = .LeadingZero
648−
649− case Literal.one...Literal.nine:
650− state = .PreDecimalDigits
651−
652− default:
653− throw JSONParser.Error.NumberSymbolMissingDigits(offset: start)
654− }
655− }
656−
657− mutating func parseLeadingZero() {
658− assert(state == .LeadingZero, "Unexpected state entering parseLeadingZero")
659−
660− loc = loc.successor()
661− guard loc < input.count else {
662− state = .Done
663− return
664− }
665−
666− guard input[loc] == Literal.PERIOD else {
667− state = .Done
668− return
669− }
670−
671− state = .Decimal
672− }
673−
674− mutating func parsePreDecimalDigits(@noescape f: (UInt8) throws -> Void) rethrows {
675− assert(state == .PreDecimalDigits, "Unexpected state entering parsePreDecimalDigits")
676− advancing: while loc < input.count {
677− let c = input[loc]
678− switch c {
679− case Literal.zero...Literal.nine:
680− try f(c)
681− loc = loc.successor()
682−
683− case Literal.PERIOD:
684− state = .Decimal
685− return
686−
687− case Literal.e, Literal.E:
688− state = .Exponent
689− return
690−
691− default:
692− break advancing
693− }
694− }
695−
696− state = .Done
697− }
698−
699− mutating func parseDecimal() throws {
700− assert(state == .Decimal, "Unexpected state entering parseDecimal")
701− loc = loc.successor()
702− guard loc < input.count else {
703− throw JSONParser.Error.EndOfStreamUnexpected
704− }
705−
706− switch input[loc] {
707− case Literal.zero...Literal.nine:
708− state = .PostDecimalDigits
709−
710− default:
711− throw JSONParser.Error.NumberMissingFractionalDigits(offset: start)
712− }
713− }
714−
715− mutating func parsePostDecimalDigits(@noescape f: (UInt8) throws -> Void) rethrows {
716− assert(state == .PostDecimalDigits, "Unexpected state entering parsePostDecimalDigits")
717−
718− advancing: while loc < input.count {
719− let c = input[loc]
720− switch c {
721− case Literal.zero...Literal.nine:
722− try f(c)
723− loc = loc.successor()
724−
725− case Literal.e, Literal.E:
726− state = .Exponent
727− return
728−
729− default:
730− break advancing
731− }
732− }
733−
734− state = .Done
735− }
736−
737− mutating func parseExponent() throws -> JSONParser.Sign {
738− assert(state == .Exponent, "Unexpected state entering parseExponent")
739−
740− loc = loc.successor()
741− guard loc < input.count else {
742− throw JSONParser.Error.EndOfStreamUnexpected
743− }
744−
745− switch input[loc] {
746− case Literal.zero...Literal.nine:
747− state = .ExponentDigits
748−
749− case Literal.PLUS:
750− state = .ExponentSign
751−
752− case Literal.MINUS:
753− state = .ExponentSign
754− return .Negative
755−
756− default:
757− throw JSONParser.Error.NumberSymbolMissingDigits(offset: start)
758− }
759−
760− return .Positive
761− }
762−
763− mutating func parseExponentSign() throws {
764− assert(state == .ExponentSign, "Unexpected state entering parseExponentSign")
765− loc = loc.successor()
766− guard loc < input.count else {
767− throw JSONParser.Error.EndOfStreamUnexpected
768− }
769−
770− switch input[loc] {
771− case Literal.zero...Literal.nine:
772− state = .ExponentDigits
773−
774− default:
775− throw JSONParser.Error.NumberSymbolMissingDigits(offset: start)
776− }
777− }
778−
779− mutating func parseExponentDigits(@noescape f: (UInt8) throws -> Void) rethrows {
780− assert(state == .ExponentDigits, "Unexpected state entering parseExponentDigits")
781− advancing: while loc < input.count {
782− let c = input[loc]
783− switch c {
784− case Literal.zero...Literal.nine:
785− try f(c)
786− loc = loc.successor()
787−
788− default:
789− break advancing
790− }
791− }
792−
793− state = .Done
794− }
795−}
796−
797−public extension JSONParser {
798−
799− /// Creates a `JSONParser` ready to parse UTF-8 encoded `NSData`.
800− ///
801− /// If the data is mutable, it is copied before parsing. The data's lifetime
802− /// is extended for the duration of parsing.
803− init(utf8Data inData: NSData) {
804− let data = inData.copy() as! NSData
805− let buffer = UnsafeBufferPointer(start: UnsafePointer<UInt8>(data.bytes), count: data.length)
806− self.init(buffer: buffer, owner: data)
807− }
808−
809− /// Creates a `JSONParser` from the code units represented by the `string`.
810− ///
811− /// The synthesized string is lifetime-extended for the duration of parsing.
812− init(string: String) {
813− let codePoints = string.nulTerminatedUTF8
814− let buffer = codePoints.withUnsafeBufferPointer { nulTerminatedBuffer in
815− // don't want to include the nul termination in the buffer - trim it off
816− UnsafeBufferPointer(start: nulTerminatedBuffer.baseAddress, count: nulTerminatedBuffer.count - 1)
817− }
818− self.init(buffer: buffer, owner: codePoints)
819− }
820−
821−}
822−
823−extension JSONParser: JSONParserType {
824−
825− /// Creates an instance of `JSON` from UTF-8 encoded `NSData`.
826− /// - parameter data: An instance of `NSData` to parse `JSON` from.
827− /// - throws: Any `JSONParser.Error` that arises during decoding.
828− /// - seealso: JSONParser.parse()
829− public static func createJSONFromData(data: NSData) throws -> JSON {
830− var parser = JSONParser(utf8Data: data)
831− return try parser.parse()
832− }
833−
834−}
835−
836−// MARK: - Errors
837−
838−extension JSONParser {
839−
840− /// Enumeration describing possible errors that occur while parsing a JSON
841− /// document. Most errors include an associated `offset`, representing the
842− /// offset into the UTF-8 characters making up the document where the error
843− /// occurred.
844− public enum Error: ErrorType {
845− /// The parser ran out of data prematurely. This usually means a value
846− /// was not escaped, such as a string literal not ending with a double
847− /// quote.
848− case EndOfStreamUnexpected
849−
850− /// Unexpected non-whitespace data was left around `offset` after
851− /// parsing all valid JSON.
852− case EndOfStreamGarbage(offset: Int)
853−
854− /// Too many nested objects or arrays occured at the literal started
855− /// around `offset`.
856− case ExceededNestingLimit(offset: Int)
857−
858− /// A `character` was not a valid start of a value around `offset`.
859− case ValueInvalid(offset: Int, character: UnicodeScalar)
860−
861− /// Badly-formed Unicode escape sequence at `offset`. A Unicode escape
862− /// uses the text "\u" followed by 4 hex digits, such as "\uF09F\uA684"
863− /// to represent U+1F984, "UNICORN FACE".
864− case UnicodeEscapeInvalid(offset: Int)
865−
866− /// Badly-formed control character around `offset`. JSON supports
867− /// backslash-escaped double quotes, slashes, whitespace control codes,
868− /// and Unicode escape sequences.
869− case ControlCharacterUnrecognized(offset: Int)
870−
871− /// Invalid token, expected `null` around `offset`
872− case LiteralNilMisspelled(offset: Int)
873−
874− /// Invalid token, expected `true` around `offset`
875− case LiteralTrueMisspelled(offset: Int)
876−
877− /// Invalid token, expected `false` around `offset`
878− case LiteralFalseMisspelled(offset: Int)
879−
880− /// Badly-formed collection at given `offset`, expected `,` or `:`
881− case CollectionMissingSeparator(offset: Int)
882−
883− /// While parsing an object literal, a value was found without a key
884− /// around `offset`. The start of a string literal was expected.
885− case DictionaryMissingKey(offset: Int)
886−
887− /// Badly-formed number with no digits around `offset`. After a decimal
888− /// point, a number must include some number of digits.
889− case NumberMissingFractionalDigits(offset: Int)
890−
891− /// Badly-formed number with symbols ("-" or "e") but no following
892− /// digits around `offset`.
893− case NumberSymbolMissingDigits(offset: Int)
894−
895− /// Supplied data is encoded in an unsupported format.
896− case InvalidUnicodeStreamEncoding(detectedEncoding: JSONEncodingDetector.Encoding)
897− }
898−
899− private enum InternalError: ErrorType {
900− /// Attempted to parse an integer outside the range of [Int.min, Int.max]
901− /// or a double outside the range of representable doubles. Note that
902− /// for doubles, this could be an overflow or an underflow - we don't
903− /// get enough information from Swift here to know which it is. The number
904− /// causing the overflow/underflow began at `offset`.
905− case NumberOverflow(offset: Int)
906− }
907−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONParsing.swiftdeleted−126
@@ -1,126 +0,0 @@
1−//
2−// JSONParsing.swift
3−// Freddy
4−//
5−// Created by Matthew D. Mathias on 3/17/15.
6−// Copyright © 2015 Big Nerd Ranch. All rights reserved.
7−//
8−
9−import Foundation
10−
11−// MARK: - Deserialize JSON
12−
13−/// Protocol describing a backend parser that can produce `JSON` from `NSData`.
14−public protocol JSONParserType {
15−
16− /// Creates an instance of `JSON` from `NSData`.
17− /// - parameter data: An instance of `NSData` to use to create `JSON`.
18− /// - throws: An error that may arise from calling `JSONObjectWithData(_:options:)` on `NSJSONSerialization` with the given data.
19− /// - returns: An instance of `JSON`.
20− static func createJSONFromData(data: NSData) throws -> JSON
21−
22−}
23−
24−extension JSON {
25−
26− /// Create `JSON` from UTF-8 `data`. By default, parses using the
27− /// Swift-native `JSONParser` backend.
28− public init(data: NSData, usingParser parser: JSONParserType.Type = JSONParser.self) throws {
29− self = try parser.createJSONFromData(data)
30− }
31−
32− /// Create `JSON` from UTF-8 `string`.
33− public init(jsonString: Swift.String, usingParser parser: JSONParserType.Type = JSONParser.self) throws {
34− self = try parser.createJSONFromData((jsonString as NSString).dataUsingEncoding(NSUTF8StringEncoding) ?? NSData())
35− }
36−}
37−
38−// MARK: - NSJSONSerialization
39−
40−extension NSJSONSerialization: JSONParserType {
41−
42− // MARK: Decode NSData
43−
44− /// Use the built-in, Objective-C based JSON parser to create `JSON`.
45− /// - parameter data: An instance of `NSData`.
46− /// - returns: An instance of `JSON`.
47− /// - throws: An error that may arise if the `NSData` cannot be parsed into an object.
48− public static func createJSONFromData(data: NSData) throws -> JSON {
49− return makeJSON(try NSJSONSerialization.JSONObjectWithData(data, options: []))
50− }
51−
52− // MARK: Make JSON
53−
54− /// Makes a `JSON` object by matching its argument to a case in the `JSON` enum.
55− /// - parameter object: The instance of `AnyObject` returned from serializing the JSON.
56− /// - returns: An instance of `JSON` matching the JSON given to the function.
57− private static func makeJSON(object: AnyObject) -> JSON {
58− switch object {
59− case let n as NSNumber:
60− let numberType = CFNumberGetType(n)
61− switch numberType {
62− case .CharType:
63− return .Bool(n.boolValue)
64−
65− case .ShortType, .IntType, .LongType, .CFIndexType, .NSIntegerType, .SInt8Type, .SInt16Type, .SInt32Type:
66− return .Int(n.integerValue)
67−
68− case .SInt64Type, .LongLongType /* overflows 32-bit Int */:
69− #if /* 32-bit arch */ arch(arm) || arch(i386)
70− // Why double, when the Freddy parser would bump to String?
71− //
72− // Returning Double avoids making the type depend on whether you're running
73− // 32-bit or 64-bit code when using the NSJSONSerialization parser.
74− // NSJSONSerialization appears to bump numbers larger than Int.max to Double on
75− // 64-bit platforms but use .SInt64Type on 32-bit platforms.
76− // If we returned a String here, you'd get a String value on 32-bit,
77− // but a Double value on 64-bit. Instead, we return Double.
78− //
79− // This means that, if you switch parsers,
80− // you'll have to switch from .double to .string for pulling out
81− // overflowing values, but if you stick with a single parser,
82− // you at least won't have architecture-dependent lookups!
83− return .Double(n.doubleValue)
84− #else
85− return .Int(n.integerValue)
86− #endif
87−
88− case .Float32Type, .Float64Type, .FloatType, .DoubleType, .CGFloatType:
89− return .Double(n.doubleValue)
90− }
91−
92− case let arr as [AnyObject]:
93− return makeJSONArray(arr)
94−
95− case let dict as [Swift.String: AnyObject]:
96− return makeJSONDictionary(dict)
97−
98− case let s as Swift.String:
99− return .String(s)
100−
101− default:
102− return .Null
103− }
104− }
105−
106− // MARK: Make a JSON Array
107−
108− /// Makes a `JSON` array from the object passed in.
109− /// - parameter jsonArray: The array to transform into a `JSON`.
110− /// - returns: An instance of `JSON` matching the array.
111− private static func makeJSONArray(jsonArray: [AnyObject]) -> JSON {
112− return .Array(jsonArray.map(makeJSON))
113− }
114−
115− // MARK: Make a JSON Dictionary
116−
117− /// Makes a `JSON` dictionary from the Cocoa dictionary passed in.
118− /// - parameter jsonDict: The dictionary to transform into `JSON`.
119− /// - returns: An instance of `JSON` matching the dictionary.
120− private static func makeJSONDictionary(jsonDict: [Swift.String: AnyObject]) -> JSON {
121− return JSON(jsonDict.lazy.map { (key, value) in
122− (key, makeJSON(value))
123− })
124− }
125−
126−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONSerializing.swiftdeleted−43
@@ -1,43 +0,0 @@
1−// Copyright (C) 2016 Big Nerd Ranch, Inc. Licensed under the MIT license WITHOUT ANY WARRANTY.
2−
3−import Foundation
4−
5−// MARK: - Serialize JSON
6−
7−extension JSON {
8−
9− /// Attempt to serialize `JSON` into an `NSData`.
10− /// - returns: A byte-stream containing the `JSON` ready for wire transfer.
11− /// - throws: Errors that arise from `NSJSONSerialization`.
12− /// - see: Foundation.NSJSONSerialization
13− public func serialize() throws -> NSData {
14− let obj: AnyObject = toNSJSONSerializationObject()
15− return try NSJSONSerialization.dataWithJSONObject(obj, options: [])
16− }
17−
18− /// A function to help with the serialization of `JSON`.
19− /// - returns: An `AnyObject` suitable for `NSJSONSerialization`'s use.
20− private func toNSJSONSerializationObject() -> AnyObject {
21− switch self {
22− case .Array(let jsonArray):
23− return jsonArray.map { $0.toNSJSONSerializationObject() }
24− case .Dictionary(let jsonDictionary):
25− var cocoaDictionary = Swift.Dictionary<Swift.String, AnyObject>(minimumCapacity: jsonDictionary.count)
26− for (key, json) in jsonDictionary {
27− cocoaDictionary[key] = json.toNSJSONSerializationObject()
28− }
29− return cocoaDictionary
30− case .String(let str):
31− return str
32− case .Double(let num):
33− return num
34− case .Int(let int):
35− return int
36− case .Bool(let b):
37− return b
38− case .Null:
39− return NSNull()
40− }
41−
42− }
43−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/JSONSubscripting.swiftdeleted−705
@@ -1,705 +0,0 @@
1−//
2−// JSONSubscripting.swift
3−// Freddy
4−//
5−// Created by Zachary Waldowski on 8/15/15.
6−// Copyright © 2015 Big Nerd Ranch. All rights reserved.
7−//
8−
9−// MARK: JSONPathType
10−
11−/// A protocol used to define a path within an instance of `JSON` that leads to some desired value.
12−///
13−/// A custom type, such as a `RawRepresentable` enum, may be made to conform to `JSONPathType`
14−/// and used with the subscript APIs.
15−public protocol JSONPathType {
16− /// Use `self` to key into a `dictionary`.
17− ///
18− /// Unlike Swift dictionaries, failing to find a value for a key should throw
19− /// an error rather than convert to `nil`.
20− ///
21− /// Upon failure, implementers should throw an error from `JSON.Error`.
22− func valueInDictionary(dictionary: [Swift.String : JSON]) throws -> JSON
23−
24− /// Use `self` to index into an `array`.
25− ///
26− /// Unlike Swift array, attempting to index outside the collection's bounds
27− /// should throw an error rather than crash.
28− ///
29− /// Upon failure, implementers should throw an error from `JSON.Error`.
30− func valueInArray(array: [JSON]) throws -> JSON
31−}
32−
33−extension JSONPathType {
34−
35− /// The default behavior for keying into a dictionary is to throw
36− /// `JSON.Error.UnexpectedSubscript`.
37− public func valueInDictionary(dictionary: [Swift.String : JSON]) throws -> JSON {
38− throw JSON.Error.UnexpectedSubscript(type: Self.self)
39− }
40−
41− /// The default behavior for indexing into an array is to throw
42− /// `JSON.Error.UnexpectedSubscript`.
43− public func valueInArray(array: [JSON]) throws -> JSON {
44− throw JSON.Error.UnexpectedSubscript(type: Self.self)
45− }
46−
47−}
48−
49−extension String: JSONPathType {
50−
51− /// A method used to retrieve a value from a given dictionary for a specific key.
52− /// - parameter dictionary: A `Dictionary` with `String` keys and `JSON` values.
53− /// - throws: `.KeyNotFound` with an associated value of `self`, where `self` is a `String`,
54− /// should the key not be present within the `JSON`.
55− /// - returns: The `JSON` value associated with the given key.
56− public func valueInDictionary(dictionary: [Swift.String : JSON]) throws -> JSON {
57− guard let next = dictionary[self] else {
58− throw JSON.Error.KeyNotFound(key: self)
59− }
60− return next
61− }
62−
63−}
64−
65−extension Int: JSONPathType {
66−
67− /// A method used to retrieve a value from a given array for a specific index.
68− /// - parameter array: An `Array` of `JSON`.
69− /// - throws: `.IndexOutOfBounds` with an associated value of `self`, where `self` is an `Int`,
70− /// should the index not be within the valid range for the array of `JSON`.
71− /// - returns: The `JSON` value found at the given index.
72− public func valueInArray(array: [JSON]) throws -> JSON {
73− guard case array.indices = self else {
74− throw JSON.Error.IndexOutOfBounds(index: self)
75− }
76− return array[self]
77− }
78−
79−}
80−
81−// MARK: - Subscripting core
82−
83−private extension JSON {
84−
85− enum SubscriptError: ErrorType {
86− case SubscriptIntoNull(JSONPathType)
87− }
88−
89− func valueForPathFragment(fragment: JSONPathType, detectNull: Swift.Bool) throws -> JSON {
90− switch self {
91− case .Null where detectNull:
92− throw SubscriptError.SubscriptIntoNull(fragment)
93− case let .Dictionary(dict):
94− return try fragment.valueInDictionary(dict)
95− case let .Array(array):
96− return try fragment.valueInArray(array)
97− default:
98− throw Error.UnexpectedSubscript(type: fragment.dynamicType)
99− }
100− }
101−
102− func valueAtPath(path: [JSONPathType], detectNull: Swift.Bool = false) throws -> JSON {
103− var result = self
104− for fragment in path {
105− result = try result.valueForPathFragment(fragment, detectNull: detectNull)
106− }
107− return result
108− }
109−
110−}
111−
112−// MARK: - Subscripting operator
113−
114−extension JSON {
115−
116− public subscript(key: Swift.String) -> JSON? {
117− return try? valueForPathFragment(key, detectNull: false)
118− }
119−
120− public subscript(index: Swift.Int) -> JSON? {
121− return try? valueForPathFragment(index, detectNull: false)
122− }
123−
124−}
125−
126−// MARK: - Simple member unpacking
127−
128−extension JSON {
129−
130− /// Attempts to decode into the returning type from a path into JSON.
131− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`.
132− /// - parameter type: If the context this method is called from does not
133− /// make the return type clear, pass a type implementing `JSONDecodable`
134− /// to disambiguate the type to decode with.
135− /// - returns: An initialized member from the inner JSON.
136− /// - throws: One of the following errors contained in `JSON.Error`:
137− /// * `KeyNotFound`: A given `String` key does not exist inside a
138− /// descendant `JSON` dictionary.
139− /// * `IndexOutOfBounds`: A given `Int` index is outside the bounds of a
140− /// descendant `JSON` array.
141− /// * `UnexpectedSubscript`: A given subscript cannot be used with the
142− /// corresponding `JSON` value.
143− /// * `TypeNotConvertible`: The target value's type inside of
144− /// the `JSON` instance does not match `Decoded`.
145− public func decode<Decoded: JSONDecodable>(path: JSONPathType..., type: Decoded.Type = Decoded.self) throws -> Decoded {
146− return try Decoded(json: valueAtPath(path))
147− }
148−
149− /// Retrieves a `Double` from a path into JSON.
150− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
151− /// - returns: A floating-point `Double`
152− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`.
153− /// - seealso: `JSON.decode(_:type:)`
154− public func double(path: JSONPathType...) throws -> Swift.Double {
155− return try Swift.Double(json: valueAtPath(path))
156− }
157−
158− /// Retrieves an `Int` from a path into JSON.
159− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
160− /// - returns: A numeric `Int`
161− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`.
162− /// - seealso: `JSON.decode(_:type:)`
163− public func int(path: JSONPathType...) throws -> Swift.Int {
164− return try Swift.Int(json: valueAtPath(path))
165− }
166−
167− /// Retrieves a `String` from a path into JSON.
168− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
169− /// - returns: A textual `String`
170− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`.
171− /// - seealso: `JSON.decode(_:type:)`
172− public func string(path: JSONPathType...) throws -> Swift.String {
173− return try Swift.String(json: valueAtPath(path))
174− }
175−
176− /// Retrieves a `Bool` from a path into JSON.
177− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
178− /// - returns: A truthy `Bool`
179− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`.
180− /// - seealso: `JSON.decode(_:type:)`
181− public func bool(path: JSONPathType...) throws -> Swift.Bool {
182− return try Swift.Bool(json: valueAtPath(path))
183− }
184−
185− /// Retrieves a `[JSON]` from a path into JSON.
186− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
187− /// - returns: An `Array` of `JSON` elements
188− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`.
189− /// - seealso: `JSON.decode(_:type:)`
190− public func array(path: JSONPathType...) throws -> [JSON] {
191− return try JSON.getArray(valueAtPath(path))
192− }
193−
194− /// Attempts to decode many values from a descendant JSON array at a path
195− /// into JSON.
196− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
197− /// - parameter type: If the context this method is called from does not
198− /// make the return type clear, pass a type implementing `JSONDecodable`
199− /// to disambiguate the type to decode with.
200− /// - returns: An `Array` of decoded elements
201− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`, or
202− /// any error that arises from decoding the contained values.
203− /// - seealso: `JSON.decode(_:type:)`
204− public func arrayOf<Decoded: JSONDecodable>(path: JSONPathType..., type: Decoded.Type = Decoded.self) throws -> [Decoded] {
205− return try JSON.getArrayOf(valueAtPath(path))
206− }
207−
208− /// Retrieves a `[String: JSON]` from a path into JSON.
209− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
210− /// - returns: An `Dictionary` of `String` mapping to `JSON` elements
211− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)`.
212− /// - seealso: `JSON.decode(_:type:)`
213− public func dictionary(path: JSONPathType...) throws -> [Swift.String: JSON] {
214− return try JSON.getDictionary(valueAtPath(path))
215− }
216−
217− /// Attempts to decode many values from a descendant JSON object at a path
218− /// into JSON.
219− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
220− /// - parameter type: If the context this method is called from does not
221− /// make the return type clear, pass a type implementing `JSONDecodable`
222− /// to disambiguate the value type to decode with.
223− /// - returns: A `Dictionary` of `String` keys and decoded values.
224− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)` or
225− /// any error that arises from decoding the contained values.
226− /// - seealso: `JSON.decode(_:type:)`
227− public func dictionaryOf<Decoded: JSONDecodable>(path: JSONPathType..., type: Decoded.Type = Decoded.self) throws -> [Swift.String: Decoded] {
228− return try JSON.getDictionaryOf(valueAtPath(path))
229− }
230−
231−}
232−
233−// MARK: - NotFound-Or-Null-to-Optional unpacking
234−
235−extension JSON {
236−
237− /// An `OptionSetType` used to represent the different options available for subscripting `JSON` with `null` values or missing keys.
238− /// * `.NullBecomesNil` - Treat `null` values as `nil`.
239− /// * `.MissingKeyBecomesNil` - Treat missing keys as `nil`.
240− public struct SubscriptingOptions: OptionSetType {
241− public let rawValue: Swift.Int
242− public init(rawValue: Swift.Int) {
243− self.rawValue = rawValue
244− }
245−
246− /// Treat `null` values as `nil`.
247− public static let NullBecomesNil = SubscriptingOptions(rawValue: 1 << 0)
248− /// Treat missing keys as `nil`.
249− public static let MissingKeyBecomesNil = SubscriptingOptions(rawValue: 1 << 1)
250− }
251−
252− private func mapOptionalAtPath<Value>(path: [JSONPathType], alongPath: SubscriptingOptions, @noescape transform: JSON throws -> Value) throws -> Value? {
253− let detectNull = alongPath.contains(.NullBecomesNil)
254− let detectNotFound = alongPath.contains(.MissingKeyBecomesNil)
255− var json: JSON?
256− do {
257− json = try valueAtPath(path, detectNull: detectNull)
258− return try json.map(transform)
259− } catch Error.IndexOutOfBounds where detectNotFound {
260− return nil
261− } catch Error.KeyNotFound where detectNotFound {
262− return nil
263− } catch Error.ValueNotConvertible where detectNull && json == .Null {
264− return nil
265− } catch SubscriptError.SubscriptIntoNull where detectNull {
266− return nil
267− }
268− }
269−}
270−
271−extension JSON {
272−
273− /// Optionally decodes into the returning type from a path into JSON.
274− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
275− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
276− /// - parameter type: If the context this method is called from does not
277− /// make the return type clear, pass a type implementing `JSONDecodable`
278− /// to disambiguate the type to decode with.
279− /// - returns: A decoded value from the inner JSON if found, or `nil`.
280− /// - throws: One of the following errors contained in `JSON.Error`:
281− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
282− /// `JSON` dictionary.
283− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
284− /// descendant `JSON` array.
285− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
286− /// corresponding `JSON` value.
287− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
288− /// instance does not match the decoded value.
289− /// * Any error that arises from decoding the value.
290− public func decode<Decoded: JSONDecodable>(path: JSONPathType..., alongPath options: SubscriptingOptions, type: Decoded.Type = Decoded.self) throws -> Decoded? {
291− return try mapOptionalAtPath(path, alongPath: options, transform: Decoded.init)
292− }
293−
294− /// Optionally retrieves a `Double` from a path into JSON.
295− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`.
296− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
297− /// - returns: A `Double` if a value could be found, otherwise `nil`.
298− /// - throws: One of the following errors contained in `JSON.Error`:
299− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
300− /// `JSON` dictionary.
301− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
302− /// descendant `JSON` array.
303− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
304− /// corresponding `JSON` value.
305− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
306− /// instance does not match the decoded value.
307− public func double(path: JSONPathType..., alongPath options: SubscriptingOptions) throws -> Swift.Double? {
308− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Double.init)
309− }
310−
311− /// Optionally retrieves a `Int` from a path into JSON.
312− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
313− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
314− /// - returns: A numeric `Int` if a value could be found, otherwise `nil`.
315− /// - throws: One of the following errors contained in `JSON.Error`:
316− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
317− /// `JSON` dictionary.
318− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
319− /// descendant `JSON` array.
320− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
321− /// corresponding `JSON` value.
322− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
323− /// instance does not match the decoded value.
324− public func int(path: JSONPathType..., alongPath options: SubscriptingOptions) throws -> Swift.Int? {
325− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Int.init)
326− }
327−
328− /// Optionally retrieves a `String` from a path into JSON.
329− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
330− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
331− /// - returns: A text `String` if a value could be found, otherwise `nil`.
332− /// - throws: One of the following errors contained in `JSON.Error`:
333− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
334− /// `JSON` dictionary.
335− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
336− /// descendant `JSON` array.
337− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
338− /// corresponding `JSON` value.
339− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
340− /// instance does not match the decoded value.
341− public func string(path: JSONPathType..., alongPath options: SubscriptingOptions) throws -> Swift.String? {
342− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.String.init)
343− }
344−
345− /// Optionally retrieves a `Bool` from a path into JSON.
346− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
347− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
348− /// - returns: A truthy `Bool` if a value could be found, otherwise `nil`.
349− /// - throws: One of the following errors contained in `JSON.Error`:
350− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
351− /// `JSON` dictionary.
352− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
353− /// descendant `JSON` array.
354− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
355− /// corresponding `JSON` value.
356− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
357− /// instance does not match the decoded value.
358− public func bool(path: JSONPathType..., alongPath options: SubscriptingOptions) throws -> Swift.Bool? {
359− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Bool.init)
360− }
361−
362− /// Optionally retrieves a `[JSON]` from a path into the recieving structure.
363− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
364− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
365− /// - returns: An `Array` of `JSON` elements if a value could be found,
366− /// otherwise `nil`.
367− /// - throws: One of the following errors contained in `JSON.Error`:
368− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
369− /// `JSON` dictionary.
370− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
371− /// descendant `JSON` array.
372− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
373− /// corresponding `JSON` value.
374− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
375− /// instance does not match the decoded value.
376− public func array(path: JSONPathType..., alongPath options: SubscriptingOptions) throws -> [JSON]? {
377− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getArray)
378− }
379−
380− /// Optionally decodes many values from a descendant array at a path into
381− /// JSON.
382− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
383− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
384− /// - parameter type: If the context this method is called from does not
385− /// make the return type clear, pass a type implementing `JSONDecodable`
386− /// to disambiguate the value type to decode with.
387− /// - returns: An `Array` of decoded elements if found, otherwise `nil`.
388− /// - throws: One of the following errors contained in `JSON.Error`:
389− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
390− /// `JSON` dictionary.
391− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
392− /// descendant `JSON` array.
393− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
394− /// corresponding `JSON` value.
395− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
396− /// instance does not match the decoded value.
397− /// * Any error that arises from decoding the value.
398− public func arrayOf<Decoded: JSONDecodable>(path: JSONPathType..., alongPath options: SubscriptingOptions, type: Decoded.Type = Decoded.self) throws -> [Decoded]? {
399− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getArrayOf)
400− }
401−
402− /// Optionally retrieves a `[String: JSON]` from a path into the recieving
403− /// structure.
404− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
405− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
406− /// - returns: A `Dictionary` of `String` mapping to `JSON` elements if a
407− /// value could be found, otherwise `nil`.
408− /// - throws: One of the following errors contained in `JSON.Error`:
409− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
410− /// `JSON` dictionary.
411− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
412− /// descendant `JSON` array.
413− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
414− /// corresponding `JSON` value.
415− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
416− /// instance does not match the decoded value.
417− public func dictionary(path: JSONPathType..., alongPath options: SubscriptingOptions) throws -> [Swift.String: JSON]? {
418− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getDictionary)
419− }
420−
421− /// Optionally attempts to decode many values from a descendant object at a path
422− /// into JSON.
423− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
424− /// - parameter alongPath: Options that control what should be done with values that are `null` or keys that are missing.
425− /// - parameter type: If the context this method is called from does not
426− /// make the return type clear, pass a type implementing `JSONDecodable`
427− /// to disambiguate the value type to decode with.
428− /// - returns: A `Dictionary` of `String` mapping to decoded elements if a
429− /// value could be found, otherwise `nil`.
430− /// - throws: One of the following errors contained in `JSON.Error`:
431− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
432− /// `JSON` dictionary.
433− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
434− /// descendant `JSON` array.
435− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
436− /// corresponding `JSON` value.
437− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
438− /// instance does not match the decoded value.
439− /// * Any error that arises from decoding the value.
440− public func dictionaryOf<Decoded: JSONDecodable>(path: JSONPathType..., alongPath options: SubscriptingOptions, type: Decoded.Type = Decoded.self) throws -> [Swift.String: Decoded]? {
441− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getDictionaryOf)
442− }
443−
444−}
445−
446−// MARK: - Missing-with-fallback unpacking
447−
448−extension JSON {
449−
450− private func mapOptionalAtPath<Value>(path: [JSONPathType], @noescape fallback: () -> Value, @noescape transform: JSON throws -> Value) throws -> Value {
451− return try mapOptionalAtPath(path, alongPath: .MissingKeyBecomesNil, transform: transform) ?? fallback()
452− }
453−
454− /// Attempts to decode into the returning type from a path into
455− /// JSON, or returns a fallback if not found.
456− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
457− /// - parameter fallback: Value to use when one is missing at the subscript.
458− /// - returns: An initialized member from the inner JSON.
459− /// - throws: One of the following errors contained in `JSON.Error`:
460− /// * `UnexpectedSubscript`: A given subscript cannot be used with the
461− /// corresponding `JSON` value.
462− /// * `TypeNotConvertible`: The target value's type inside of
463− /// the `JSON` instance does not match `Decoded`.
464− public func decode<Decoded: JSONDecodable>(path: JSONPathType..., @autoclosure or fallback: () -> Decoded) throws -> Decoded {
465− return try mapOptionalAtPath(path, fallback: fallback, transform: Decoded.init)
466− }
467−
468− /// Retrieves a `Double` from a path into JSON or a fallback if not found.
469− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
470− /// - parameter fallback: `Double` to use when one is missing at the subscript.
471− /// - returns: A floating-point `Double`
472− /// - throws: One of the `JSON.Error` cases thrown by calling `mapOptionalAtPath(_:fallback:transform:)`.
473− /// - seealso: `optionalAtPath(_:ifNotFound)`.
474− public func double(path: JSONPathType..., @autoclosure or fallback: () -> Swift.Double) throws -> Swift.Double {
475− return try mapOptionalAtPath(path, fallback: fallback, transform: Swift.Double.init)
476− }
477−
478− /// Retrieves an `Int` from a path into JSON or a fallback if not found.
479− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
480− /// - parameter fallback: `Int` to use when one is missing at the subscript.
481− /// - returns: A numeric `Int`
482− /// - throws: One of the following errors contained in `JSON.Error`:
483− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
484− /// `JSON` dictionary.
485− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
486− /// descendant `JSON` array.
487− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
488− /// corresponding `JSON` value.
489− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
490− /// instance does not match the decoded value.
491− public func int(path: JSONPathType..., @autoclosure or fallback: () -> Swift.Int) throws -> Swift.Int {
492− return try mapOptionalAtPath(path, fallback: fallback, transform: Swift.Int.init)
493− }
494−
495− /// Retrieves a `String` from a path into JSON or a fallback if not found.
496− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
497− /// - parameter fallback: `String` to use when one is missing at the subscript.
498− /// - returns: A textual `String`
499− /// - throws: One of the following errors contained in `JSON.Error`:
500− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
501− /// `JSON` dictionary.
502− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
503− /// descendant `JSON` array.
504− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
505− /// corresponding `JSON` value.
506− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
507− /// instance does not match the decoded value.
508− public func string(path: JSONPathType..., @autoclosure or fallback: () -> Swift.String) throws -> Swift.String {
509− return try mapOptionalAtPath(path, fallback: fallback, transform: Swift.String.init)
510− }
511−
512− /// Retrieves a `Bool` from a path into JSON or a fallback if not found.
513− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
514− /// - parameter fallback: `Bool` to use when one is missing at the subscript.
515− /// - returns: A truthy `Bool`
516− /// - throws: One of the following errors contained in `JSON.Error`:
517− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
518− /// `JSON` dictionary.
519− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
520− /// descendant `JSON` array.
521− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
522− /// corresponding `JSON` value.
523− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
524− /// instance does not match the decoded value.
525− public func bool(path: JSONPathType..., @autoclosure or fallback: () -> Swift.Bool) throws -> Swift.Bool {
526− return try mapOptionalAtPath(path, fallback: fallback, transform: Swift.Bool.init)
527− }
528−
529− /// Retrieves a `[JSON]` from a path into JSON or a fallback if not found.
530− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
531− /// - parameter fallback: `Array` to use when one is missing at the subscript.
532− /// - returns: An `Array` of `JSON` elements
533− /// - throws: One of the following errors contained in `JSON.Error`:
534− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
535− /// `JSON` dictionary.
536− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
537− /// descendant `JSON` array.
538− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
539− /// corresponding `JSON` value.
540− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
541− /// instance does not match the decoded value.
542− public func array(path: JSONPathType..., @autoclosure or fallback: () -> [JSON]) throws -> [JSON] {
543− return try mapOptionalAtPath(path, fallback: fallback, transform: JSON.getArray)
544− }
545−
546− /// Attempts to decodes many values from a desendant JSON array at a path
547− /// into the recieving structure, returning a fallback if not found.
548− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
549− /// - parameter fallback: `Array` to use when one is missing at the subscript.
550− /// - returns: An `Array` of decoded elements
551− /// - throws: One of the following errors contained in `JSON.Error`:
552− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
553− /// `JSON` dictionary.
554− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
555− /// descendant `JSON` array.
556− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
557− /// corresponding `JSON` value.
558− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
559− /// instance does not match the decoded value.
560− /// * Any error that arises from decoding the value.
561− public func arrayOf<Decoded: JSONDecodable>(path: JSONPathType..., @autoclosure or fallback: () -> [Decoded]) throws -> [Decoded] {
562− return try mapOptionalAtPath(path, fallback: fallback, transform: JSON.getArrayOf)
563− }
564−
565− /// Retrieves a `[String: JSON]` from a path into JSON or a fallback if not
566− /// found.
567− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
568− /// - parameter fallback: `Dictionary` to use when one is missing at the subscript.
569− /// - returns: An `Dictionary` of `String` mapping to `JSON` elements
570− /// - throws: One of the following errors contained in `JSON.Error`:
571− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
572− /// `JSON` dictionary.
573− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
574− /// descendant `JSON` array.
575− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
576− /// corresponding `JSON` value.
577− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
578− /// instance does not match the decoded value.
579− public func dictionary(path: JSONPathType..., @autoclosure or fallback: () -> [Swift.String: JSON]) throws -> [Swift.String: JSON] {
580− return try mapOptionalAtPath(path, fallback: fallback, transform: JSON.getDictionary)
581− }
582−
583− /// Attempts to decode many values from a descendant JSON object at a path
584− /// into the receiving structure, returning a fallback if not found.
585− /// - parameter path: 0 or more `String` or `Int` that subscript the `JSON`
586− /// - parameter fallback: Value to use when one is missing at the subscript
587− /// - returns: A `Dictionary` of `String` mapping to decoded elements.
588− /// - throws: One of the following errors contained in `JSON.Error`:
589− /// * `KeyNotFound`: A key `path` does not exist inside a descendant
590− /// `JSON` dictionary.
591− /// * `IndexOutOfBounds`: An index `path` is outside the bounds of a
592− /// descendant `JSON` array.
593− /// * `UnexpectedSubscript`: A `path` item cannot be used with the
594− /// corresponding `JSON` value.
595− /// * `TypeNotConvertible`: The target value's type inside of the `JSON`
596− /// instance does not match the decoded value.
597− /// * Any error that arises from decoding the value.
598− public func dictionaryOf<Decoded: JSONDecodable>(path: JSONPathType..., @autoclosure or fallback: () -> [Swift.String: Decoded]) throws -> [Swift.String: Decoded] {
599− return try mapOptionalAtPath(path, fallback: fallback, transform: JSON.getDictionaryOf)
600− }
601−
602−
603−}
604−
605−// MARK: - Deprecated methods
606−
607−extension JSON {
608−
609− @available(*, deprecated, message="Use 'decode(_:alongPath:type:)' with options '[.MissingKeyBecomesNil]'")
610− public func decode<Decoded: JSONDecodable>(path: JSONPathType..., ifNotFound: Swift.Bool, type: Decoded.Type = Decoded.self) throws -> Decoded? {
611− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
612− return try mapOptionalAtPath(path, alongPath: options, transform: Decoded.init)
613− }
614−
615− @available(*, deprecated, message="Use 'decode(_:alongPath:type:)' with options '[.NullBecomesNil]'")
616− public func decode<Decoded: JSONDecodable>(path: JSONPathType..., ifNull: Swift.Bool, type: Decoded.Type = Decoded.self) throws -> Decoded? {
617− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
618− return try mapOptionalAtPath(path, alongPath: options, transform: Decoded.init)
619− }
620−
621− @available(*, deprecated, message="Use 'double(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
622− public func double(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> Swift.Double? {
623− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
624− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Double.init)
625− }
626−
627− @available(*, deprecated, message="Use 'double(_:alongPath:)' with options '[.NullBecomesNil]'")
628− public func double(path: JSONPathType..., ifNull: Swift.Bool) throws -> Swift.Double? {
629− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
630− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Double.init)
631− }
632−
633− @available(*, deprecated, message="Use 'int(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
634− public func int(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> Swift.Int? {
635− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
636− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Int.init)
637− }
638−
639− @available(*, deprecated, message="Use 'int(_:alongPath:)' with options '[.NullBecomesNil]'")
640− public func int(path: JSONPathType..., ifNull: Swift.Bool) throws -> Swift.Int? {
641− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
642− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Int.init)
643− }
644−
645− @available(*, deprecated, message="Use 'string(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
646− public func string(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> Swift.String? {
647− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
648− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.String.init)
649− }
650−
651− @available(*, deprecated, message="Use 'string(_:alongPath:)' with options '[.NullBecomesNil]'")
652− public func string(path: JSONPathType..., ifNull: Swift.Bool) throws -> Swift.String? {
653− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
654− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.String.init)
655− }
656−
657− @available(*, deprecated, message="Use 'bool(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
658− public func bool(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> Swift.Bool? {
659− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
660− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Bool.init)
661− }
662−
663− @available(*, deprecated, message="Use 'bool(_:alongPath:)' with options '[.NullBecomesNil]'")
664− public func bool(path: JSONPathType..., ifNull: Swift.Bool) throws -> Swift.Bool? {
665− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
666− return try mapOptionalAtPath(path, alongPath: options, transform: Swift.Bool.init)
667− }
668−
669− @available(*, deprecated, message="Use 'array(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
670− public func array(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> [JSON]? {
671− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
672− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getArray)
673− }
674−
675− @available(*, deprecated, message="Use 'array(_:alongPath:)' with options '[.NullBecomesNil]'")
676− public func array(path: JSONPathType..., ifNull: Swift.Bool) throws -> [JSON]? {
677− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
678− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getArray)
679− }
680−
681− @available(*, deprecated, message="Use 'arrayOf(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
682− public func arrayOf<Decoded: JSONDecodable>(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> [Decoded]? {
683− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
684− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getArrayOf)
685− }
686−
687− @available(*, deprecated, message="Use 'arrayOf(_:alongPath:)' with options '[.NullBecomesNil]'")
688− public func arrayOf<Decoded: JSONDecodable>(path: JSONPathType..., ifNull: Swift.Bool) throws -> [Decoded]? {
689− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
690− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getArrayOf)
691− }
692−
693− @available(*, deprecated, message="Use 'dictionary(_:alongPath:)' with options '[.MissingKeyBecomesNil]'")
694− public func dictionary(path: JSONPathType..., ifNotFound: Swift.Bool) throws -> [Swift.String: JSON]? {
695− let options: SubscriptingOptions = ifNotFound ? [.MissingKeyBecomesNil] : []
696− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getDictionary)
697− }
698−
699− @available(*, deprecated, message="Use 'dictionary(_:alongPath:)' with options '[.NullBecomesNil]'")
700− public func dictionary(path: JSONPathType..., ifNull: Swift.Bool) throws -> [Swift.String: JSON]? {
701− let options: SubscriptingOptions = ifNull ? [.NullBecomesNil] : []
702− return try mapOptionalAtPath(path, alongPath: options, transform: JSON.getDictionary)
703− }
704−
705−}
tests/JSONTestSuite/parsers/test_Freddy_20160830/test_Freddy/main.swiftdeleted−37
@@ -1,37 +0,0 @@
1−//
2−// main.swift
3−// test_Freddy
4−//
5−// Created by nst on 10/08/16.
6−// Copyright © 2016 Nicolas Seriot. All rights reserved.
7−//
8−
9−import Foundation
10−
11−func main() {
12−
13− guard Process.arguments.count == 2 else {
14− let url = NSURL(fileURLWithPath: Process.arguments[0])
15− guard let programName = url.lastPathComponent else { exit(1) }
16− print("Usage: ./\(programName) file.json")
17− exit(1)
18− }
19−
20− let path = Process.arguments[1]
21− let url = NSURL.fileURLWithPath(path)
22−
23− guard let data = NSData(contentsOfURL:url) else {
24− print("*** CANNOT READ DATA AT \(url)")
25− return
26− }
27−
28− var p = JSONParser(utf8Data: data)
29− do {
30− try p.parse()
31− exit(0)
32− } catch {
33− exit(1)
34− }
35−}
36−
37−main()
tests/JSONTestSuite/parsers/test_Freddy_20161018/bin/test_Freddydeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy.xcodeproj/project.pbxprojdeleted−300
@@ -1,300 +0,0 @@
1−// !$*UTF8*$!
2−{
3− archiveVersion = 1;
4− classes = {
5− };
6− objectVersion = 46;
7− objects = {
8−
9−/* Begin PBXBuildFile section */
10− 03D84ABB1D5B0A1000776402 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03D84ABA1D5B0A1000776402 /* main.swift */; };
11− 03F8F7811D5B75600021630C /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F7781D5B75600021630C /* JSON.swift */; };
12− 03F8F7821D5B75600021630C /* JSONDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F7791D5B75600021630C /* JSONDecodable.swift */; };
13− 03F8F7831D5B75600021630C /* JSONEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77A1D5B75600021630C /* JSONEncodable.swift */; };
14− 03F8F7841D5B75600021630C /* JSONEncodingDetector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77B1D5B75600021630C /* JSONEncodingDetector.swift */; };
15− 03F8F7851D5B75600021630C /* JSONLiteralConvertible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77C1D5B75600021630C /* JSONLiteralConvertible.swift */; };
16− 03F8F7861D5B75600021630C /* JSONParser.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77D1D5B75600021630C /* JSONParser.swift */; };
17− 03F8F7871D5B75600021630C /* JSONParsing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77E1D5B75600021630C /* JSONParsing.swift */; };
18− 03F8F7881D5B75600021630C /* JSONSerializing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F77F1D5B75600021630C /* JSONSerializing.swift */; };
19− 03F8F7891D5B75600021630C /* JSONSubscripting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F8F7801D5B75600021630C /* JSONSubscripting.swift */; };
20−/* End PBXBuildFile section */
21−
22−/* Begin PBXCopyFilesBuildPhase section */
23− 03D84AB51D5B0A1000776402 /* CopyFiles */ = {
24− isa = PBXCopyFilesBuildPhase;
25− buildActionMask = 2147483647;
26− dstPath = /usr/share/man/man1;
27− dstSubfolderSpec = 0;
28− files = (
29− );
30− runOnlyForDeploymentPostprocessing = 1;
31− };
32−/* End PBXCopyFilesBuildPhase section */
33−
34−/* Begin PBXFileReference section */
35− 03D84AB71D5B0A1000776402 /* test_Freddy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_Freddy; sourceTree = BUILT_PRODUCTS_DIR; };
36− 03D84ABA1D5B0A1000776402 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
37− 03F8F7781D5B75600021630C /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSON.swift; path = test_Freddy/JSON.swift; sourceTree = "<group>"; };
38− 03F8F7791D5B75600021630C /* JSONDecodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONDecodable.swift; path = test_Freddy/JSONDecodable.swift; sourceTree = "<group>"; };
39− 03F8F77A1D5B75600021630C /* JSONEncodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONEncodable.swift; path = test_Freddy/JSONEncodable.swift; sourceTree = "<group>"; };
40− 03F8F77B1D5B75600021630C /* JSONEncodingDetector.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONEncodingDetector.swift; path = test_Freddy/JSONEncodingDetector.swift; sourceTree = "<group>"; };
41− 03F8F77C1D5B75600021630C /* JSONLiteralConvertible.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONLiteralConvertible.swift; path = test_Freddy/JSONLiteralConvertible.swift; sourceTree = "<group>"; };
42− 03F8F77D1D5B75600021630C /* JSONParser.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONParser.swift; path = test_Freddy/JSONParser.swift; sourceTree = "<group>"; };
43− 03F8F77E1D5B75600021630C /* JSONParsing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONParsing.swift; path = test_Freddy/JSONParsing.swift; sourceTree = "<group>"; };
44− 03F8F77F1D5B75600021630C /* JSONSerializing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONSerializing.swift; path = test_Freddy/JSONSerializing.swift; sourceTree = "<group>"; };
45− 03F8F7801D5B75600021630C /* JSONSubscripting.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSONSubscripting.swift; path = test_Freddy/JSONSubscripting.swift; sourceTree = "<group>"; };
46−/* End PBXFileReference section */
47−
48−/* Begin PBXFrameworksBuildPhase section */
49− 03D84AB41D5B0A1000776402 /* Frameworks */ = {
50− isa = PBXFrameworksBuildPhase;
51− buildActionMask = 2147483647;
52− files = (
53− );
54− runOnlyForDeploymentPostprocessing = 0;
55− };
56−/* End PBXFrameworksBuildPhase section */
57−
58−/* Begin PBXGroup section */
59− 03D84AAE1D5B0A1000776402 = {
60− isa = PBXGroup;
61− children = (
62− 03F8F7781D5B75600021630C /* JSON.swift */,
63− 03F8F7791D5B75600021630C /* JSONDecodable.swift */,
64− 03F8F77A1D5B75600021630C /* JSONEncodable.swift */,
65− 03F8F77B1D5B75600021630C /* JSONEncodingDetector.swift */,
66− 03F8F77C1D5B75600021630C /* JSONLiteralConvertible.swift */,
67− 03F8F77D1D5B75600021630C /* JSONParser.swift */,
68− 03F8F77E1D5B75600021630C /* JSONParsing.swift */,
69− 03F8F77F1D5B75600021630C /* JSONSerializing.swift */,
70− 03F8F7801D5B75600021630C /* JSONSubscripting.swift */,
71− 03D84AB91D5B0A1000776402 /* test_Freddy */,
72− 03D84AB81D5B0A1000776402 /* Products */,
73− );
74− sourceTree = "<group>";
75− };
76− 03D84AB81D5B0A1000776402 /* Products */ = {
77− isa = PBXGroup;
78− children = (
79− 03D84AB71D5B0A1000776402 /* test_Freddy */,
80− );
81− name = Products;
82− sourceTree = "<group>";
83− };
84− 03D84AB91D5B0A1000776402 /* test_Freddy */ = {
85− isa = PBXGroup;
86− children = (
87− 03D84ABA1D5B0A1000776402 /* main.swift */,
88− );
89− path = test_Freddy;
90− sourceTree = "<group>";
91− };
92−/* End PBXGroup section */
93−
94−/* Begin PBXNativeTarget section */
95− 03D84AB61D5B0A1000776402 /* test_Freddy */ = {
96− isa = PBXNativeTarget;
97− buildConfigurationList = 03D84ABE1D5B0A1000776402 /* Build configuration list for PBXNativeTarget "test_Freddy" */;
98− buildPhases = (
99− 03D84AB31D5B0A1000776402 /* Sources */,
100− 03D84AB41D5B0A1000776402 /* Frameworks */,
101− 03D84AB51D5B0A1000776402 /* CopyFiles */,
102− );
103− buildRules = (
104− );
105− dependencies = (
106− );
107− name = test_Freddy;
108− productName = test_Freddy;
109− productReference = 03D84AB71D5B0A1000776402 /* test_Freddy */;
110− productType = "com.apple.product-type.tool";
111− };
112−/* End PBXNativeTarget section */
113−
114−/* Begin PBXProject section */
115− 03D84AAF1D5B0A1000776402 /* Project object */ = {
116− isa = PBXProject;
117− attributes = {
118− LastSwiftUpdateCheck = 0800;
119− LastUpgradeCheck = 0800;
120− ORGANIZATIONNAME = "Nicolas Seriot";
121− TargetAttributes = {
122− 03D84AB61D5B0A1000776402 = {
123− CreatedOnToolsVersion = 8.0;
124− DevelopmentTeam = VBYRKYS73S;
125− DevelopmentTeamName = "Nicolas Seriot";
126− ProvisioningStyle = Automatic;
127− };
128− };
129− };
130− buildConfigurationList = 03D84AB21D5B0A1000776402 /* Build configuration list for PBXProject "test_Freddy" */;
131− compatibilityVersion = "Xcode 3.2";
132− developmentRegion = English;
133− hasScannedForEncodings = 0;
134− knownRegions = (
135− en,
136− );
137− mainGroup = 03D84AAE1D5B0A1000776402;
138− productRefGroup = 03D84AB81D5B0A1000776402 /* Products */;
139− projectDirPath = "";
140− projectRoot = "";
141− targets = (
142− 03D84AB61D5B0A1000776402 /* test_Freddy */,
143− );
144− };
145−/* End PBXProject section */
146−
147−/* Begin PBXSourcesBuildPhase section */
148− 03D84AB31D5B0A1000776402 /* Sources */ = {
149− isa = PBXSourcesBuildPhase;
150− buildActionMask = 2147483647;
151− files = (
152− 03F8F7881D5B75600021630C /* JSONSerializing.swift in Sources */,
153− 03F8F7821D5B75600021630C /* JSONDecodable.swift in Sources */,
154− 03F8F7851D5B75600021630C /* JSONLiteralConvertible.swift in Sources */,
155− 03F8F7871D5B75600021630C /* JSONParsing.swift in Sources */,
156− 03F8F7861D5B75600021630C /* JSONParser.swift in Sources */,
157− 03F8F7831D5B75600021630C /* JSONEncodable.swift in Sources */,
158− 03D84ABB1D5B0A1000776402 /* main.swift in Sources */,
159− 03F8F7811D5B75600021630C /* JSON.swift in Sources */,
160− 03F8F7891D5B75600021630C /* JSONSubscripting.swift in Sources */,
161− 03F8F7841D5B75600021630C /* JSONEncodingDetector.swift in Sources */,
162− );
163− runOnlyForDeploymentPostprocessing = 0;
164− };
165−/* End PBXSourcesBuildPhase section */
166−
167−/* Begin XCBuildConfiguration section */
168− 03D84ABC1D5B0A1000776402 /* Debug */ = {
169− isa = XCBuildConfiguration;
170− buildSettings = {
171− ALWAYS_SEARCH_USER_PATHS = NO;
172− CLANG_ANALYZER_NONNULL = YES;
173− CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
174− CLANG_CXX_LIBRARY = "libc++";
175− CLANG_ENABLE_MODULES = YES;
176− CLANG_ENABLE_OBJC_ARC = YES;
177− CLANG_WARN_BOOL_CONVERSION = YES;
178− CLANG_WARN_CONSTANT_CONVERSION = YES;
179− CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
180− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
181− CLANG_WARN_EMPTY_BODY = YES;
182− CLANG_WARN_ENUM_CONVERSION = YES;
183− CLANG_WARN_INT_CONVERSION = YES;
184− CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
185− CLANG_WARN_UNREACHABLE_CODE = YES;
186− CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
187− CODE_SIGN_IDENTITY = "-";
188− COPY_PHASE_STRIP = NO;
189− DEBUG_INFORMATION_FORMAT = dwarf;
190− ENABLE_STRICT_OBJC_MSGSEND = YES;
191− ENABLE_TESTABILITY = YES;
192− GCC_C_LANGUAGE_STANDARD = gnu99;
193− GCC_DYNAMIC_NO_PIC = NO;
194− GCC_NO_COMMON_BLOCKS = YES;
195− GCC_OPTIMIZATION_LEVEL = 0;
196− GCC_PREPROCESSOR_DEFINITIONS = (
197− "DEBUG=1",
198− "$(inherited)",
199− );
200− GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
201− GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
202− GCC_WARN_UNDECLARED_SELECTOR = YES;
203− GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
204− GCC_WARN_UNUSED_FUNCTION = YES;
205− GCC_WARN_UNUSED_VARIABLE = YES;
206− MACOSX_DEPLOYMENT_TARGET = 10.11;
207− MTL_ENABLE_DEBUG_INFO = YES;
208− ONLY_ACTIVE_ARCH = YES;
209− SDKROOT = macosx;
210− SWIFT_OPTIMIZATION_LEVEL = "-Onone";
211− };
212− name = Debug;
213− };
214− 03D84ABD1D5B0A1000776402 /* Release */ = {
215− isa = XCBuildConfiguration;
216− buildSettings = {
217− ALWAYS_SEARCH_USER_PATHS = NO;
218− CLANG_ANALYZER_NONNULL = YES;
219− CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
220− CLANG_CXX_LIBRARY = "libc++";
221− CLANG_ENABLE_MODULES = YES;
222− CLANG_ENABLE_OBJC_ARC = YES;
223− CLANG_WARN_BOOL_CONVERSION = YES;
224− CLANG_WARN_CONSTANT_CONVERSION = YES;
225− CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
226− CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
227− CLANG_WARN_EMPTY_BODY = YES;
228− CLANG_WARN_ENUM_CONVERSION = YES;
229− CLANG_WARN_INT_CONVERSION = YES;
230− CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
231− CLANG_WARN_UNREACHABLE_CODE = YES;
232− CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
233− CODE_SIGN_IDENTITY = "-";
234− COPY_PHASE_STRIP = NO;
235− DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
236− ENABLE_NS_ASSERTIONS = NO;
237− ENABLE_STRICT_OBJC_MSGSEND = YES;
238− GCC_C_LANGUAGE_STANDARD = gnu99;
239− GCC_NO_COMMON_BLOCKS = YES;
240− GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
241− GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
242− GCC_WARN_UNDECLARED_SELECTOR = YES;
243− GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
244− GCC_WARN_UNUSED_FUNCTION = YES;
245− GCC_WARN_UNUSED_VARIABLE = YES;
246− MACOSX_DEPLOYMENT_TARGET = 10.11;
247− MTL_ENABLE_DEBUG_INFO = NO;
248− SDKROOT = macosx;
249− };
250− name = Release;
251− };
252− 03D84ABF1D5B0A1000776402 /* Debug */ = {
253− isa = XCBuildConfiguration;
254− buildSettings = {
255− FRAMEWORK_SEARCH_PATHS = (
256− "$(inherited)",
257− "$(PROJECT_DIR)",
258− );
259− PRODUCT_NAME = "$(TARGET_NAME)";
260− SWIFT_VERSION = 3.0;
261− };
262− name = Debug;
263− };
264− 03D84AC01D5B0A1000776402 /* Release */ = {
265− isa = XCBuildConfiguration;
266− buildSettings = {
267− FRAMEWORK_SEARCH_PATHS = (
268− "$(inherited)",
269− "$(PROJECT_DIR)",
270− );
271− PRODUCT_NAME = "$(TARGET_NAME)";
272− SWIFT_VERSION = 3.0;
273− };
274− name = Release;
275− };
276−/* End XCBuildConfiguration section */
277−
278−/* Begin XCConfigurationList section */
279− 03D84AB21D5B0A1000776402 /* Build configuration list for PBXProject "test_Freddy" */ = {
280− isa = XCConfigurationList;
281− buildConfigurations = (
282− 03D84ABC1D5B0A1000776402 /* Debug */,
283− 03D84ABD1D5B0A1000776402 /* Release */,
284− );
285− defaultConfigurationIsVisible = 0;
286− defaultConfigurationName = Release;
287− };
288− 03D84ABE1D5B0A1000776402 /* Build configuration list for PBXNativeTarget "test_Freddy" */ = {
289− isa = XCConfigurationList;
290− buildConfigurations = (
291− 03D84ABF1D5B0A1000776402 /* Debug */,
292− 03D84AC01D5B0A1000776402 /* Release */,
293− );
294− defaultConfigurationIsVisible = 0;
295− defaultConfigurationName = Release;
296− };
297−/* End XCConfigurationList section */
298− };
299− rootObject = 03D84AAF1D5B0A1000776402 /* Project object */;
300−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7
@@ -1,7 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<Workspace
3− version = "1.0">
4− <FileRef
5− location = "self:test_Freddy.xcodeproj">
6− </FileRef>
7−</Workspace>
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy.xcodeproj/project.xcworkspace/xcshareddata/test_Freddy.xcscmblueprintdeleted−30
@@ -1,30 +0,0 @@
1−{
2− "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A",
3− "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
4−
5− },
6− "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
7− "6ADA245F937D8ED6D99F5A7865E19F5267A169E2" : 0,
8− "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A" : 0
9− },
10− "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "7B3DFA55-F9BF-41D8-8FD5-204D3162EB03",
11− "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
12− "6ADA245F937D8ED6D99F5A7865E19F5267A169E2" : "dropbox\/JSON\/test_Freddy\/Vendor\/Freddy\/",
13− "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A" : "dropbox\/"
14− },
15− "DVTSourceControlWorkspaceBlueprintNameKey" : "test_Freddy",
16− "DVTSourceControlWorkspaceBlueprintVersion" : 204,
17− "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "JSON\/test_Freddy\/test_Freddy.xcodeproj",
18− "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
19− {
20− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/bignerdranch\/Freddy.git",
21− "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
22− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "6ADA245F937D8ED6D99F5A7865E19F5267A169E2"
23− },
24− {
25− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "\/Users\/nst\/Dropbox\/dropbox.git",
26− "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
27− "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "ED13D74FC1ED9BC322EA1859E5AD7D001676FA6A"
28− }
29− ]
30−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_Freddy.xcschemedeleted−91
@@ -1,91 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<Scheme
3− LastUpgradeVersion = "0800"
4− version = "1.3">
5− <BuildAction
6− parallelizeBuildables = "YES"
7− buildImplicitDependencies = "YES">
8− <BuildActionEntries>
9− <BuildActionEntry
10− buildForTesting = "YES"
11− buildForRunning = "YES"
12− buildForProfiling = "YES"
13− buildForArchiving = "YES"
14− buildForAnalyzing = "YES">
15− <BuildableReference
16− BuildableIdentifier = "primary"
17− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
18− BuildableName = "test_Freddy"
19− BlueprintName = "test_Freddy"
20− ReferencedContainer = "container:test_Freddy.xcodeproj">
21− </BuildableReference>
22− </BuildActionEntry>
23− </BuildActionEntries>
24− </BuildAction>
25− <TestAction
26− buildConfiguration = "Debug"
27− selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
28− selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
29− shouldUseLaunchSchemeArgsEnv = "YES">
30− <Testables>
31− </Testables>
32− <MacroExpansion>
33− <BuildableReference
34− BuildableIdentifier = "primary"
35− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
36− BuildableName = "test_Freddy"
37− BlueprintName = "test_Freddy"
38− ReferencedContainer = "container:test_Freddy.xcodeproj">
39− </BuildableReference>
40− </MacroExpansion>
41− <AdditionalOptions>
42− </AdditionalOptions>
43− </TestAction>
44− <LaunchAction
45− buildConfiguration = "Debug"
46− selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
47− selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
48− launchStyle = "0"
49− useCustomWorkingDirectory = "NO"
50− ignoresPersistentStateOnLaunch = "NO"
51− debugDocumentVersioning = "YES"
52− debugServiceExtension = "internal"
53− allowLocationSimulation = "YES">
54− <BuildableProductRunnable
55− runnableDebuggingMode = "0">
56− <BuildableReference
57− BuildableIdentifier = "primary"
58− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
59− BuildableName = "test_Freddy"
60− BlueprintName = "test_Freddy"
61− ReferencedContainer = "container:test_Freddy.xcodeproj">
62− </BuildableReference>
63− </BuildableProductRunnable>
64− <AdditionalOptions>
65− </AdditionalOptions>
66− </LaunchAction>
67− <ProfileAction
68− buildConfiguration = "Release"
69− shouldUseLaunchSchemeArgsEnv = "YES"
70− savedToolIdentifier = ""
71− useCustomWorkingDirectory = "NO"
72− debugDocumentVersioning = "YES">
73− <BuildableProductRunnable
74− runnableDebuggingMode = "0">
75− <BuildableReference
76− BuildableIdentifier = "primary"
77− BlueprintIdentifier = "03D84AB61D5B0A1000776402"
78− BuildableName = "test_Freddy"
79− BlueprintName = "test_Freddy"
80− ReferencedContainer = "container:test_Freddy.xcodeproj">
81− </BuildableReference>
82− </BuildableProductRunnable>
83− </ProfileAction>
84− <AnalyzeAction
85− buildConfiguration = "Debug">
86− </AnalyzeAction>
87− <ArchiveAction
88− buildConfiguration = "Release"
89− revealArchiveInOrganizer = "YES">
90− </ArchiveAction>
91−</Scheme>
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22
@@ -1,22 +0,0 @@
1−<?xml version="1.0" encoding="UTF-8"?>
2−<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3−<plist version="1.0">
4−<dict>
5− <key>SchemeUserState</key>
6− <dict>
7− <key>test_Freddy.xcscheme</key>
8− <dict>
9− <key>orderHint</key>
10− <integer>0</integer>
11− </dict>
12− </dict>
13− <key>SuppressBuildableAutocreation</key>
14− <dict>
15− <key>03D84AB61D5B0A1000776402</key>
16− <dict>
17− <key>primary</key>
18− <true/>
19− </dict>
20− </dict>
21−</dict>
22−</plist>
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSON.swiftdeleted−98
@@ -1,98 +0,0 @@
1−//
2−// JSON.swift
3−// Freddy
4−//
5−// Created by Matthew D. Mathias on 3/17/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−/// An enum to describe the structure of JSON.
10−public enum JSON {
11− /// A case for denoting an array with an associated value of `[JSON]`
12− case array([JSON])
13− /// A case for denoting a dictionary with an associated value of `[Swift.String: JSON]`
14− case dictionary([String: JSON])
15− /// A case for denoting a double with an associated value of `Swift.Double`.
16− case double(Double)
17− /// A case for denoting an integer with an associated value of `Swift.Int`.
18− case int(Int)
19− /// A case for denoting a string with an associated value of `Swift.String`.
20− case string(String)
21− /// A case for denoting a boolean with an associated value of `Swift.Bool`.
22− case bool(Bool)
23− /// A case for denoting null.
24− case null
25−}
26−
27−// MARK: - Errors
28−
29−extension JSON {
30−
31− /// An enum to encapsulate errors that may arise in working with `JSON`.
32− public enum Error: Swift.Error {
33− /// The `index` is out of bounds for a JSON array
34− case indexOutOfBounds(index: Int)
35−
36− /// The `key` was not found in the JSON dictionary
37− case keyNotFound(key: String)
38−
39− /// The JSON is not subscriptable with `type`
40− case unexpectedSubscript(type: JSONPathType.Type)
41−
42− /// Unexpected JSON `value` was found that is not convertible `to` type
43− case valueNotConvertible(value: JSON, to: Any.Type)
44−
45− /// The JSON is not serializable to a `String`.
46− case stringSerializationError
47− }
48−
49−}
50−
51−// MARK: - Test Equality
52−
53−/// Return `true` if `lhs` is equal to `rhs`.
54−public func ==(lhs: JSON, rhs: JSON) -> Bool {
55− switch (lhs, rhs) {
56− case (.array(let arrL), .array(let arrR)):
57− return arrL == arrR
58− case (.dictionary(let dictL), .dictionary(let dictR)):
59− return dictL == dictR
60− case (.string(let strL), .string(let strR)):
61− return strL == strR
62− case (.double(let dubL), .double(let dubR)):
63− return dubL == dubR
64− case (.double(let dubL), .int(let intR)):
65− return dubL == Double(intR)
66− case (.int(let intL), .int(let intR)):
67− return intL == intR
68− case (.int(let intL), .double(let dubR)):
69− return Double(intL) == dubR
70− case (.bool(let bL), .bool(let bR)):
71− return bL == bR
72− case (.null, .null):
73− return true
74− default:
75− return false
76− }
77−}
78−
79−extension JSON: Equatable {}
80−
81−// MARK: - Printing
82−
83−extension JSON: CustomStringConvertible {
84−
85− /// A textual representation of `self`.
86− public var description: Swift.String {
87− switch self {
88− case .array(let arr): return String(describing: arr)
89− case .dictionary(let dict): return String(describing: dict)
90− case .string(let string): return string
91− case .double(let double): return String(describing: double)
92− case .int(let int): return String(describing: int)
93− case .bool(let bool): return String(describing: bool)
94− case .null: return "null"
95− }
96− }
97−
98−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONDecodable.swiftdeleted−186
@@ -1,186 +0,0 @@
1−//
2−// JSONDecodable.swift
3−// Freddy
4−//
5−// Created by Matthew D. Mathias on 3/24/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−/// A protocol to provide functionality for creating a model object with a `JSON`
10−/// value.
11−public protocol JSONDecodable {
12−
13− /// Creates an instance of the model with a `JSON` instance.
14− /// - parameter json: An instance of a `JSON` value from which to
15− /// construct an instance of the implementing type.
16− /// - throws: Any `JSON.Error` for errors derived from inspecting the
17− /// `JSON` value, or any other error involved in decoding.
18− init(json: JSON) throws
19−
20−}
21−
22−extension Double: JSONDecodable {
23−
24− /// An initializer to create an instance of `Double` from a `JSON` value.
25− /// - parameter json: An instance of `JSON`.
26− /// - throws: The initializer will throw an instance of `JSON.Error` if
27− /// an instance of `Double` cannot be created from the `JSON` value that was
28− /// passed to this initializer.
29− public init(json: JSON) throws {
30− if case let .double(double) = json {
31− self = double
32− } else if case let .int(int) = json {
33− self = Double(int)
34− } else if case let .string(string) = json, let s = Double(string) {
35− self = s
36− } else {
37− throw JSON.Error.valueNotConvertible(value: json, to: Double.self)
38− }
39− }
40−
41−}
42−
43−extension Int: JSONDecodable {
44−
45− /// An initializer to create an instance of `Int` from a `JSON` value.
46− /// - parameter json: An instance of `JSON`.
47− /// - throws: The initializer will throw an instance of `JSON.Error` if
48− /// an instance of `Int` cannot be created from the `JSON` value that was
49− /// passed to this initializer.
50− public init(json: JSON) throws {
51−
52− if case let .double(double) = json, double <= Double(Int.max) {
53− self = Int(double)
54− } else if case let .int(int) = json {
55− self = int
56− } else if case let .string(string) = json, let int = Int(string) {
57− self = int
58− } else if case let .string(string) = json,
59− let double = Double(string),
60− let decimalSeparator = string.characters.index(of: "."),
61− let int = Int(String(string.characters.prefix(upTo: decimalSeparator))),
62− double == Double(int) {
63− self = int
64− } else {
65− throw JSON.Error.valueNotConvertible(value: json, to: Int.self)
66− }
67− }
68−
69−}
70−
71−extension String: JSONDecodable {
72−
73− /// An initializer to create an instance of `String` from a `JSON` value.
74− /// - parameter json: An instance of `JSON`.
75− /// - throws: The initializer will throw an instance of `JSON.Error` if
76− /// an instance of `String` cannot be created from the `JSON` value that was
77− /// passed to this initializer.
78− public init(json: JSON) throws {
79− switch json {
80− case let .string(string):
81− self = string
82− case let .int(int):
83− self = String(int)
84− case let .bool(bool):
85− self = String(bool)
86− case let .double(double):
87− self = String(double)
88− default:
89− throw JSON.Error.valueNotConvertible(value: json, to: String.self)
90− }
91− }
92−
93−}
94−
95−extension Bool: JSONDecodable {
96−
97− /// An initializer to create an instance of `Bool` from a `JSON` value.
98− /// - parameter json: An instance of `JSON`.
99− /// - throws: The initializer will throw an instance of `JSON.Error` if
100− /// an instance of `Bool` cannot be created from the `JSON` value that was
101− /// passed to this initializer.
102− public init(json: JSON) throws {
103− guard case let .bool(bool) = json else {
104− throw JSON.Error.valueNotConvertible(value: json, to: Bool.self)
105− }
106− self = bool
107− }
108−
109−}
110−
111−extension RawRepresentable where RawValue: JSONDecodable {
112−
113− /// An initializer to create an instance of `RawRepresentable` from a `JSON` value.
114− /// - parameter json: An instance of `JSON`.
115− /// - throws: The initializer will throw an instance of `JSON.Error` if
116− /// an instance of `RawRepresentable` cannot be created from the `JSON` value that was
117− /// passed to this initializer.
118− public init(json: JSON) throws {
119− let raw = try json.decode(type: RawValue.self)
120− guard let value = Self(rawValue: raw) else {
121− throw JSON.Error.valueNotConvertible(value: json, to: Self.self)
122− }
123− self = value
124− }
125−}
126−
127−internal extension JSON {
128−
129− /// Retrieves a `[JSON]` from the JSON.
130− /// - parameter: A `JSON` to be used to create the returned `Array`.
131− /// - returns: An `Array` of `JSON` elements
132− /// - throws: Any of the `JSON.Error` cases thrown by `decode(type:)`.
133− /// - seealso: `JSON.decode(_:type:)`
134− static func getArray(from json: JSON) throws -> [JSON] {
135− // Ideally should be expressed as a conditional protocol implementation on Swift.Array.
136− guard case let .array(array) = json else {
137− throw Error.valueNotConvertible(value: json, to: Swift.Array<JSON>)
138− }
139− return array
140− }
141−
142− /// Retrieves a `[String: JSON]` from the JSON.
143− /// - parameter: A `JSON` to be used to create the returned `Dictionary`.
144− /// - returns: An `Dictionary` of `String` mapping to `JSON` elements
145− /// - throws: Any of the `JSON.Error` cases thrown by `decode(type:)`.
146− /// - seealso: `JSON.decode(_:type:)`
147− static func getDictionary(from json: JSON) throws -> [String: JSON] {
148− // Ideally should be expressed as a conditional protocol implementation on Swift.Dictionary.
149− guard case let .dictionary(dictionary) = json else {
150− throw Error.valueNotConvertible(value: json, to: Swift.Dictionary<String, JSON>)
151− }
152− return dictionary
153− }
154−
155− /// Attempts to decode many values from a descendant JSON array at a path
156− /// into JSON.
157− /// - parameter json: A `JSON` to be used to create the returned `Array` of some type conforming to `JSONDecodable`.
158− /// - returns: An `Array` of `Decoded` elements.
159− /// - throws: Any of the `JSON.Error` cases thrown by `decode(type:)`, as
160− /// well as any error that arises from decoding the contained values.
161− /// - seealso: `JSON.decode(_:type:)`
162− static func decodedArray<Decoded: JSONDecodable>(from json: JSON) throws -> [Decoded] {
163− // Ideally should be expressed as a conditional protocol implementation on Swift.Dictionary.
164− // This implementation also doesn't do the `type = Type.self` trick.
165− return try getArray(from: json).map(Decoded.init)
166− }
167−
168− /// Attempts to decode many values from a descendant JSON object at a path
169− /// into JSON.
170− /// - parameter json: A `JSON` to be used to create the returned `Dictionary` of some type conforming to `JSONDecodable`.
171− /// - returns: A `Dictionary` of string keys and `Decoded` values.
172− /// - throws: One of the `JSON.Error` cases thrown by `decode(_:type:)` or
173− /// any error that arises from decoding the contained values.
174− /// - seealso: `JSON.decode(_:type:)`
175− static func decodedDictionary<Decoded: JSONDecodable>(from json: JSON) throws -> [Swift.String: Decoded] {
176− guard case let .dictionary(dictionary) = json else {
177− throw Error.valueNotConvertible(value: json, to: Swift.Dictionary<String, Decoded>)
178− }
179− var decodedDictionary = Swift.Dictionary<String, Decoded>(minimumCapacity: dictionary.count)
180− for (key, value) in dictionary {
181− decodedDictionary[key] = try Decoded(json: value)
182− }
183− return decodedDictionary
184− }
185−
186−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONEncodable.swiftdeleted−83
@@ -1,83 +0,0 @@
1−//
2−// JSONEncodable.swift
3−// Freddy
4−//
5−// Created by Matthew Mathias on 1/4/16.
6−// Copyright © 2016 Big Nerd Ranch. All rights reserved.
7−//
8−
9−import Foundation
10−
11−/// A protocol to facilitate encoding and decoding of `JSON`.
12−public protocol JSONEncodable {
13− /// Converts an instance of a conforming type to `JSON`.
14− /// - returns: An instance of `JSON`.
15− /// - Note: If conforming to `JSONEncodable` with a custom type of your own, you should return an instance of
16− /// `JSON.dictionary`.
17− func toJSON() -> JSON
18−}
19−
20−extension Array where Element: JSONEncodable {
21− /// Converts an instance of `Array` whose elements conform to `JSONEncodable` to `JSON`.
22− /// - returns: An instance of `JSON` where the enum case is `.array`.
23− public func toJSON() -> JSON {
24− let arrayOfJSON = self.map { $0.toJSON() }
25− return .array(arrayOfJSON)
26− }
27−}
28−
29−extension Dictionary where Value: JSONEncodable {
30− /// Converts an instance of `Dictionary` whose values conform to `JSONEncodable` to `JSON`. The keys in the resulting
31− /// `JSON.dictionary` will be of type `String`.
32− /// - returns: An instance of `JSON` where the enum case is `.dictionary`.
33− public func toJSON() -> JSON {
34− var jsonDictionary = [String: JSON]()
35−
36− for (k, v) in self {
37− let key = String(describing: k)
38− jsonDictionary[key] = v.toJSON()
39− }
40−
41− return .dictionary(jsonDictionary)
42− }
43−}
44−
45−extension Int: JSONEncodable {
46− /// Converts an instance of a conforming type to `JSON`.
47− /// - returns: An instance of `JSON` where the enum case is `.int`.
48− public func toJSON() -> JSON {
49− return .int(self)
50− }
51−}
52−
53−extension Double: JSONEncodable {
54− /// Converts an instance of a conforming type to `JSON`.
55− /// - returns: An instance of `JSON` where the enum case is `.double`.
56− public func toJSON() -> JSON {
57− return .double(self)
58− }
59−}
60−
61−extension String: JSONEncodable {
62− /// Converts an instance of a conforming type to `JSON`.
63− /// - returns: An instance of `JSON` where the enum case is `.string`.
64− public func toJSON() -> JSON {
65− return .string(self)
66− }
67−}
68−
69−extension Bool: JSONEncodable {
70− /// Converts an instance of a conforming type to `JSON`.
71− /// - returns: An instance of `JSON` where the enum case is `.bool`.
72− public func toJSON() -> JSON {
73− return .bool(self)
74− }
75−}
76−
77−extension RawRepresentable where RawValue: JSONEncodable {
78− /// Converts an instance of a conforming type to `JSON`.
79− /// - returns: An instance of `JSON` where the enum case is whatever the underlying `RawValue` converts to.
80− public func toJSON() -> JSON {
81− return rawValue.toJSON()
82− }
83−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONEncodingDetector.swiftdeleted−110
@@ -1,110 +0,0 @@
1−//
2−// JSONEncodingDetector.swift
3−// Freddy
4−//
5−// Created by Robert Edwards on 1/27/16.
6−// Copyright © 2016 Big Nerd Ranch. All rights reserved.
7−//
8−
9−/// Struct for attempting to detect the Unicode encoding used with the data supplied to the JSONParser
10−public struct JSONEncodingDetector {
11−
12− //// The Unicode encodings looked for during detection
13− public enum Encoding {
14− //// UTF-8
15− case utf8
16− //// UTF-16 Little Endian
17− case utf16LE
18− //// UTF-16 Big Endian
19− case utf16BE
20− //// UTF-32 Little Endian
21− case utf32LE
22− //// UTF-32 Big Endian
23− case utf32BE
24− }
25−
26− //// The Unicode encodings supported by JSONParser.swift
27− public static let supportedEncodings: [Encoding] = [.utf8]
28−
29− typealias ByteStreamPrefixInformation = (encoding: Encoding, byteOrderMarkLength: Int)
30−
31− //// Attempts to detect the Unicode encoding used for a given set of data.
32− ////
33− //// This function initially looks for a Byte Order Mark in the following form:
34− ////
35− //// Bytes | Encoding Form
36− //// --------------|----------------
37− //// 00 00 FE FF | UTF-32, big-endian
38− //// FF FE 00 00 | UTF-32, little-endian
39− //// FE FF | UTF-16, big-endian
40− //// FF FE | UTF-16, little-endian
41− //// EF BB BF | UTF-8
42− ////
43− //// If a BOM is not found then we detect using the following approach described in
44− //// the JSON RFC http://www.ietf.org/rfc/rfc4627.txt:
45− ////
46− //// Since the first two characters of a JSON text will always be ASCII
47− //// characters [RFC0020], it is possible to determine whether an octet
48− //// stream is UTF-8, UTF-16 (BE or LE), or UTF-32 (BE or LE) by looking
49− //// at the pattern of nulls in the first four octets.
50− ////
51− //// 00 00 00 xx UTF-32BE
52− //// 00 xx 00 xx UTF-16BE
53− //// xx 00 00 00 UTF-32LE
54− //// xx 00 xx 00 UTF-16LE
55− //// xx xx xx xx UTF-8
56− ////
57− //// - parameter header: The front Slice of data being read and evaluated.
58− //// - returns: A tuple containing the detected Unicode encoding and the lenght of the byte order mark.
59− static func detectEncoding(_ header: RandomAccessSlice<UnsafeBufferPointer<UInt8>>) -> ByteStreamPrefixInformation {
60−
61− guard let prefix = prefixFromHeader(header) else {
62− return (.utf8, 0)
63− }
64−
65− if let prefixInfo = JSONEncodingDetector.encodingFromBOM(prefix) {
66− return prefixInfo
67− } else {
68− switch prefix {
69− case(0, 0, 0?, _):
70− return (.utf32BE, 0)
71− case(_, 0, 0?, 0?):
72− return (.utf32LE, 0)
73− case (0, _, 0?, _), (0, _, _, _):
74− return (.utf16BE, 0)
75− case (_, 0, _, 0?), (_, 0, _, _):
76− return (.utf16LE, 0)
77− default:
78− return (.utf8, 0)
79− }
80− }
81− }
82−
83− private typealias EncodingBytePrefix = (UInt8, UInt8, UInt8?, UInt8?)
84−
85− private static func prefixFromHeader(_ header: RandomAccessSlice<UnsafeBufferPointer<UInt8>>) -> EncodingBytePrefix? {
86− if header.count >= 4 {
87− return(header[0], header[1], header[2], header[3])
88− } else if header.count >= 2 {
89− return (header[0], header[1], nil, nil)
90− }
91− return nil
92− }
93−
94− private static func encodingFromBOM(_ prefix: EncodingBytePrefix) -> ByteStreamPrefixInformation? {
95− switch prefix {
96− case(0xFE, 0xFF, _, _):
97− return (.utf16BE, 2)
98− case(0x00, 0x00, 0xFE?, 0xFF?):
99− return (.utf32BE, 4)
100− case(0xEF, 0xBB, 0xBF?, _):
101− return (.utf8, 3)
102− case(0xFF, 0xFE, 0?, 0?):
103− return (.utf32LE, 4)
104− case(0xFF, 0xFE, _, _):
105− return (.utf16LE, 2)
106− default:
107− return nil
108− }
109− }
110−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONLiteralConvertible.swiftdeleted−134
@@ -1,134 +0,0 @@
1−//
2−// JSONLiteralConvertible.swift
3−// Freddy
4−//
5−// Created by Zachary Waldowski on 5/11/15.
6−// Copyright © 2015 Big Nerd Ranch. Licensed under MIT.
7−//
8−
9−// MARK: - ArrayLiteralConvertible
10−
11−extension JSON: ExpressibleByArrayLiteral {
12−
13− /// Create an instance by copying each element of the `collection` into a
14− /// new `Array`.
15− public init<Collection: Swift.Collection>(_ collection: Collection) where Collection.Iterator.Element == JSON {
16− self = .array(Swift.Array(collection))
17− }
18−
19− /// Create an instance initialized with `elements`.
20− public init(arrayLiteral elements: JSON...) {
21− self.init(elements)
22− }
23−
24−}
25−
26−// MARK: - DictionaryLiteralConvertible
27−
28−extension JSON: ExpressibleByDictionaryLiteral {
29−
30− /// Create an instance by copying each key/value pair of the `pairs` into
31− /// a new `Dictionary`.
32− public init<Dictionary: Sequence>(_ pairs: Dictionary) where Dictionary.Iterator.Element == (Swift.String, JSON) {
33− var dictionary = Swift.Dictionary<Swift.String, JSON>(minimumCapacity: pairs.underestimatedCount)
34− for (key, value) in pairs {
35− dictionary[key] = value
36− }
37− self.init(dictionary)
38− }
39−
40− /// Create an instance initialized with `pairs`.
41− public init(dictionaryLiteral pairs: (Swift.String, JSON)...) {
42− self.init(pairs)
43− }
44−
45− /// Create an instance initialized to `dictionary`.
46− public init(_ dictionary: Swift.Dictionary<Swift.String, JSON>) {
47− self = .dictionary(dictionary)
48− }
49−}
50−
51−// MARK: - FloatLiteralConvertible
52−
53−extension JSON: ExpressibleByFloatLiteral {
54−
55− /// Create an instance initialized to `Double` `value`.
56− public init(_ value: Swift.Double) {
57− self = .double(value)
58− }
59−
60− /// Create a literal instance initialized to `value`.
61− public init(floatLiteral value: Swift.Double) {
62− self.init(value)
63− }
64−
65−}
66−
67−// MARK: - IntegerLiteralConvertible
68−
69−extension JSON: ExpressibleByIntegerLiteral {
70−
71− /// Create an instance initialized to `Int` by `value`.
72− public init(_ value: Swift.Int) {
73− self = .int(value)
74− }
75−
76− /// Create a literal instance initialized to `value`.
77− public init(integerLiteral value: Swift.Int) {
78− self.init(value)
79− }
80−
81−}
82−
83−// MARK: - StringLiteralConvertible
84−
85−extension JSON: ExpressibleByStringLiteral {
86−
87− /// Create an instance initialized to `String` by `text`.
88− public init(_ text: Swift.String) {
89− self = .string(text)
90− }
91−
92− /// Create a literal instance initialized to `value`.
93− public init(stringLiteral value: StringLiteralType) {
94− self.init(value)
95− }
96−
97− /// Create a literal instance initialized to `value`.
98− public init(extendedGraphemeClusterLiteral value: StringLiteralType) {
99− self.init(value)
100− }
101−
102− /// Create a literal instance initialized to `value`.
103− public init(unicodeScalarLiteral value: StringLiteralType) {
104− self.init(value)
105− }
106−
107−}
108−
109−// MARK: - BooleanLiteralConvertible
110−
111−extension JSON: ExpressibleByBooleanLiteral {
112−
113− /// Create an instance initialized to `Bool` by `value`.
114− public init(_ value: Swift.Bool) {
115− self = .bool(value)
116− }
117−
118− /// Create a literal instance initialized to `value`.
119− public init(booleanLiteral value: Swift.Bool) {
120− self.init(value)
121− }
122−
123−}
124−
125−// MARK: - NilLiteralConvertible
126−
127−extension JSON: ExpressibleByNilLiteral {
128−
129− /// Create an instance initialized with `nil`.
130− public init(nilLiteral: ()) {
131− self = .null
132− }
133−
134−}
tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONParser.swiftdeleted−918

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONParsing.swiftdeleted−126

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONSerializing.swiftdeleted−54

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/JSONSubscripting.swiftdeleted−613

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_20161018/test_Freddy/main.swiftdeleted−40

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/bin/test_Freddy_2_1_0deleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy.xcodeproj/project.pbxprojdeleted−300

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy.xcodeproj/project.xcworkspace/xcshareddata/test_Freddy.xcscmblueprintdeleted−30

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_Freddy.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSON.swiftdeleted−95

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONDecodable.swiftdeleted−151

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONEncodable.swiftdeleted−83

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONEncodingDetector.swiftdeleted−110

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONLiteralConvertible.swiftdeleted−130

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONParser.swiftdeleted−903

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONParsing.swiftdeleted−126

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONSerializing.swiftdeleted−43

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/JSONSubscripting.swiftdeleted−643

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Freddy_2_1_0/test_Freddy/main.swiftdeleted−37

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/JSONKit.hdeleted−251

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/JSONKit.mdeleted−3065

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/bin/test-JSONKitdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_JSONKit/test-JSONKit.xcodeproj/project.pbxprojdeleted−252

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/test-JSONKit.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/test-JSONKit.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_JSONKit/test-JSONKit.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test-JSONKit.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/test-JSONKit.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_JSONKit/test-JSONKit/main.mdeleted−73

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Json.NET/Program.csdeleted−46

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Json.NET/bin/Release/netcoreapp1.0/publish/Newtonsoft.Json.dlldeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Json.NET/bin/Release/netcoreapp1.0/publish/System.Runtime.Serialization.Primitives.dlldeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Json.NET/bin/Release/netcoreapp1.0/publish/test_Json.NET.deps.jsondeleted−49

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Json.NET/bin/Release/netcoreapp1.0/publish/test_Json.NET.dlldeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Json.NET/bin/Release/netcoreapp1.0/publish/test_Json.NET.pdbdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Json.NET/bin/Release/netcoreapp1.0/publish/test_Json.NET.runtimeconfig.jsondeleted−8

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Json.NET/project.jsondeleted−21

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Json.NET/project.lock.jsondeleted−6741

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Lua_JSON/JSON.luadeleted−1451

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Lua_JSON/test_JSON.luadeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/bin/test_ObjCNSJSONSerializerdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer.xcodeproj/project.pbxprojdeleted−246

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_ObjCNSJSONSerializer.xcschemedeleted−97

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer/a.outdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer/a.out.dSYM/Contents/Info.plistdeleted−20

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer/a.out.dSYM/Contents/Resources/DWARF/a.outdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer/findings_dir/plot_datadeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ObjCNSJSONSerializer/test_ObjCNSJSONSerializer/main.mdeleted−32

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/Accessors.swiftdeleted−255

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/DecimalNumber.swiftdeleted−236

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/Decoder.swiftdeleted−294

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/Encoder.swiftdeleted−167

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/JSON.swiftdeleted−170

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/JSONError.swiftdeleted−1619

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/JSONObject.swiftdeleted−215

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/ObjectiveC.swiftdeleted−233

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/Parser.swiftdeleted−674

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/bin/test_PMJSONdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/test_PMJSON.xcodeproj/project.pbxprojdeleted−296

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/test_PMJSON.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/test_PMJSON.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/test_PMJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_PMJSON.xcschemedeleted−97

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/test_PMJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_1_0/test_PMJSON/main.swiftdeleted−46

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/Accessors.swiftdeleted−255

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/DecimalNumber.swiftdeleted−236

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/Decoder.swiftdeleted−502

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/Encoder.swiftdeleted−215

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/JSON.swiftdeleted−170

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/JSONError.swiftdeleted−1619

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/JSONObject.swiftdeleted−215

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/ObjectiveC.swiftdeleted−331

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/Parser.swiftdeleted−745

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/bin/test_PMJSONdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/test_PMJSON.xcodeproj/project.pbxprojdeleted−296

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/test_PMJSON.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/test_PMJSON.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/test_PMJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_PMJSON.xcschemedeleted−97

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/test_PMJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_PMJSON_1_2_0/test_PMJSON/main.swiftdeleted−46

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4.hdeleted−35

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4Parser.hdeleted−248

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4Parser.mdeleted−287

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamParser.hdeleted−131

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamParser.mdeleted−317

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamParserState.hdeleted−82

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamParserState.mdeleted−355

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamTokeniser.hdeleted−40

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamTokeniser.mdeleted−395

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamWriter.hdeleted−210

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamWriter.mdeleted−358

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamWriterState.hdeleted−69

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4StreamWriterState.mdeleted−147

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4Writer.hdeleted−103

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/SBJson4Writer.mdeleted−102

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/bin/test_SBJSONdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON.xcodeproj/project.pbxprojdeleted−290

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlistdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_SBJSON.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_SBJSON/test_SBJSON/main.mdeleted−38

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/project.pbxprojdeleted−361

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/project.xcworkspace/xcshareddata/STJSON.xcscmblueprintdeleted−30

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/STJSON.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/STJSONTests.xcschemedeleted−56

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−32

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON/STJSONParser.swiftdeleted−663

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSON/main.swiftdeleted−47

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSONTests/Info.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/STJSONTests/STJSONTests.swiftdeleted−92

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_STJSON/bin/STJSONdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Info.plistdeleted−563

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/MacOS/Squeakdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/English.lproj/Localizable.stringsdeleted−9

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/English.lproj/MainMenu.nibdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/Squeak.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakChanges.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakGeneric.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakImage.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakPlugin.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakProject.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakScript.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak.app/Contents/Resources/SqueakSources.icnsdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/Squeak5.1-16549-32bit.imagedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_Squeak_JSON_tonyg/test_JSON.stdeleted−9

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/bin/test_TouchJSONdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON.xcodeproj/project.pbxprojdeleted−262

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_TouchJSON.xcschemedeleted−97

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON/CJSONDeserializer.hdeleted−96

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON/CJSONDeserializer.mdeleted−1240

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_TouchJSON/test_TouchJSON/main.mdeleted−25

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/bin/test-cJSONdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_cJSON/cJSON.cdeleted−754

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/cJSON.hdeleted−153

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON.xcodeproj/project.pbxprojdeleted−257

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlistdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test-cJSON.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_cJSON/test-cJSON/main.cdeleted−69

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/bin/test_ccandeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/common.hdeleted−18

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_10.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_101.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_11.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_12.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_125.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_127.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_13.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_136.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_137.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_139.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_14.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_140.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_145.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_147.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_149.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_15.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_150.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_151.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_153.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_154.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_155.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_156.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_157.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_158.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_159.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_16.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_160.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_161.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_162.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_163.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_164.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_165.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_169.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_17.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_171.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_172.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_173.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_175.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_176.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_177.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_178.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_179.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_18.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_180.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_181.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_183.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_184.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_185.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_186.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_187.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_188.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_189.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_19.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_190.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_191.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_192.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_193.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_194.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_195.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_197.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_198.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_199.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_2.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_20.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_200.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_201.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_202.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_203.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_204.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_205.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_206.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_207.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_208.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_209.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_21.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_210.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_211.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_212.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_213.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_214.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_216.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_217.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_218.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_219.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_22.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_220.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_221.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_222.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_223.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_23.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_24.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_25.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_26.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_27.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_28.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_29.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_3.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_30.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_31.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_32.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_33.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_34.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_35.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_36.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_37.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_4.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_40.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_44.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_46.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_5.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_54.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_55.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_59.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_6.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_63.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_64.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_66.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_69.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_7.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_77.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_78.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_79.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_80.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_81.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_82.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_83.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_85.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_86.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_87.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_9.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/n_91.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_100.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_102.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_103.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_104.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_105.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_106.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_107.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_108.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_109.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_110.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_111.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_112.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_113.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_114.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_115.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_116.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_117.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_118.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_119.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_120.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_121.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_122.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_123.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_124.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_126.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_128.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_129.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_130.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_131.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_132.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_133.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_134.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_135.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_138.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_141.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_142.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_143.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_144.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_146.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_148.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_152.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_166.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_167.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_168.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_170.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_174.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_182.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_196.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_215.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_38.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_39.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_41.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_42.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_43.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_45.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_47.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_48.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_49.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_50.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_51.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_52.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_53.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_56.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_57.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_58.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_60.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_61.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_62.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_65.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_67.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_68.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_70.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_71.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_72.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_73.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_74.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_75.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_76.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_84.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_88.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_89.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_90.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_92.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_93.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_94.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_95.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_96.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_97.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_98.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/nst_files/y_99.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/run-construction.cdeleted−191

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/run-decode-encode.cdeleted−77

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/run-stringify.cdeleted−108

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/run-validate.cdeleted−49

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/test-stringsdeleted−224

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/test-strings-reencodeddeleted−90

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/_test/x.pydeleted−21

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/json.cdeleted−1381

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/json/json.hdeleted−117

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/test_ccan/test_ccan.xcodeproj/project.pbxprojdeleted−262

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/test_ccan/test_ccan.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/test_ccan/test_ccan.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_ccan_json/test_ccan/test_ccan.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_ccan.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/test_ccan/test_ccan.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_ccan_json/test_ccan/test_ccan/main.cdeleted−44

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_dkjson.luadeleted−25

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_go/test_jsondeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_go/test_json.godeleted−30

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_haskell-aeson/.gitignoredeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_haskell-aeson/package.yamldeleted−12

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_haskell-aeson/src/Main.hsdeleted−29

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_haskell-aeson/stack.yamldeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_haskell-aeson/testaesondeleted−8

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_haskell-aeson/testaeson.cabaldeleted−21

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/bin/test_janssondeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jansson/dump.cdeleted−467

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/error.cdeleted−63

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/hashtable.cdeleted−356

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/hashtable.hdeleted−184

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/hashtable_seed.cdeleted−277

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/jansson.hdeleted−298

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/jansson_config.hdeleted−43

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/jansson_private.hdeleted−109

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/load.cdeleted−1110

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/lookup3.hdeleted−381

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/memory.cdeleted−69

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/pack_unpack.cdeleted−871

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/strbuffer.cdeleted−111

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/strbuffer.hdeleted−34

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/strconv.cdeleted−145

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/test_jansson.xcodeproj/project.pbxprojdeleted−309

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/test_jansson.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/test_jansson.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jansson/test_jansson.xcodeproj/xcuserdata/nst.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlistdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/test_jansson.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_jansson.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/test_jansson.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/test_jansson/main.cdeleted−208

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/utf.cdeleted−187

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/utf.hdeleted−27

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jansson/value.cdeleted−1048

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_com_leastfixedpoint_json_1_0/META-INF/MANIFEST.MFdeleted−3

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_com_leastfixedpoint_json_1_0/README.txtdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_com_leastfixedpoint_json_1_0/TestJSONParsing.classdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_com_leastfixedpoint_json_1_0/TestJSONParsing.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_com_leastfixedpoint_json_1_0/TestJSONParsing.javadeleted−40

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_com_leastfixedpoint_json_1_0/com.leastfixedpoint.json-1.0.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_gson_2_7/META-INF/MANIFEST.MFdeleted−3

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_gson_2_7/README.txtdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_gson_2_7/TestJSONParsing.classdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_gson_2_7/TestJSONParsing.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_gson_2_7/TestJSONParsing.javadeleted−51

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_gson_2_7/gson-2.7.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/META-INF/MANIFEST.MFdeleted−3

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/README.txtdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/TestJSONParsing.classdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/TestJSONParsing.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/TestJSONParsing.javadeleted−48

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/jackson-annotations-2.2.3.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/jackson-core-2.8.4.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_jackson_2_8_4/jackson-databind-2.3.1.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_nanojson_1_0/META-INF/MANIFEST.MFdeleted−3

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_nanojson_1_0/README.txtdeleted−5

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_nanojson_1_0/TestJSONParsing.classdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_nanojson_1_0/TestJSONParsing.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_nanojson_1_0/TestJSONParsing.javadeleted−45

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_nanojson_1_0/nanojson-1.0.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_simple_json_1_1_1/META-INF/MANIFEST.MFdeleted−3

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_simple_json_1_1_1/README.txtdeleted−3

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_simple_json_1_1_1/TestJSONParsing.classdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_simple_json_1_1_1/TestJSONParsing.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_java_simple_json_1_1_1/TestJSONParsing.javadeleted−43

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_java_simple_json_1_1_1/json-simple-1.1.1.jardeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsmn/bin/test_jsmndeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsmn/jsmn.cdeleted−311

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/jsmn.hdeleted−76

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn.xcodeproj/project.pbxprojdeleted−253

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn.xcodeproj/xcuserdata/nst.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlistdeleted−23

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_jsmn.xcschemedeleted−101

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsmn/test_jsmn/test_jsmn/main.cdeleted−50

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-jq.pydeleted−34

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/bin/test_json-parserdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser.xcodeproj/project.pbxprojdeleted−258

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/test_json-parser.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser/json.cdeleted−1011

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser/json.hdeleted−283

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-parser/test_json-parser/main.cdeleted−66

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust-serde_json/rj/.gitignoredeleted−2

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust-serde_json/rj/Cargo.tomldeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust-serde_json/rj/READMEdeleted−2

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust-serde_json/rj/src/main.rsdeleted−30

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/Cargo.lockdeleted−14

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/Cargo.tomldeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/READMEdeleted−2

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/src/main.rsdeleted−42

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.cargo-lockdeleted

No changes to the content.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/json-74a82b4ec4439e90/dep-lib-jsondeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/json-74a82b4ec4439e90/lib-jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/json-74a82b4ec4439e90/lib-json.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-b5d63a9d8da2968e/bin-tjdeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-b5d63a9d8da2968e/bin-tj.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-b5d63a9d8da2968e/dep-bin-tjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-bb890ae6f101bb25/bin-tjdeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-bb890ae6f101bb25/bin-tj.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-bb890ae6f101bb25/dep-bin-tjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-bf24d0bdc8d0f4d6/bin-tjdeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-bf24d0bdc8d0f4d6/bin-tj.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/.fingerprint/tj-bf24d0bdc8d0f4d6/dep-bin-tjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/deps/libjson-6bbf4c11dd6d7c25.rlibdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/tjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/tj.dSYM/Contents/Info.plistdeleted−20

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rust/target/debug/tj.dSYM/Contents/Resources/DWARF/tjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/Cargo.lockdeleted−14

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/Cargo.tomldeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/READMEdeleted−2

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/src/main.rsdeleted−32

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.cargo-lockdeleted

No changes to the content.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rj-8f8b750d20f3bf10/bin-rjdeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rj-8f8b750d20f3bf10/bin-rj.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rj-8f8b750d20f3bf10/dep-bin-rjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rj-da0f8f63b87cf531/bin-rjdeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rj-da0f8f63b87cf531/bin-rj.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rj-da0f8f63b87cf531/dep-bin-rjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rustc-serialize-80c565222c5ccdbb/dep-lib-rustc-serializedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rustc-serialize-80c565222c5ccdbb/lib-rustc-serializedeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/.fingerprint/rustc-serialize-80c565222c5ccdbb/lib-rustc-serialize.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/deps/librustc_serialize-3561541d79c18212.rlibdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/rjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/rj.dSYM/Contents/Info.plistdeleted−20

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json-rustc_serialize/rj/target/debug/rj.dSYM/Contents/Resources/DWARF/rjdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_json.crdeleted−19

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json.jsdeleted−13

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json.phpdeleted−21

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json.pldeleted−32

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json.pydeleted−39

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json.rbdeleted−23

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/bin/jsonCheckerdeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/JSON_checker.cdeleted−400

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/JSON_checker.hdeleted−13

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/jsonChecker.xcodeproj/project.pbxprojdeleted−253

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/jsonChecker.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/jsonChecker.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/jsonChecker.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/jsonChecker.xcschemedeleted−91

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/jsonChecker.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker/jsonChecker/jsonChecker/main.cdeleted−53

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/FSM.rtfdeleted−103

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/bin/jsonChecker2deleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/JSON_checker.cdeleted−402

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/JSON_checker.hdeleted−13

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/jsonChecker/main.cdeleted−53

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/jsonChecker2.xcodeproj/project.pbxprojdeleted−253

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/jsonChecker2.xcodeproj/project.xcworkspace/contents.xcworkspacedatadeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/jsonChecker2.xcodeproj/project.xcworkspace/xcuserdata/nst.xcuserdatad/UserInterfaceState.xcuserstatedeleted

Binary file not shown.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/jsonChecker2.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/jsonChecker.xcschemedeleted−97

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonChecker2/jsonChecker2/jsonChecker2.xcodeproj/xcuserdata/nst.xcuserdatad/xcschemes/xcschememanagement.plistdeleted−22

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json_re.rbdeleted−33

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_json_xs.pldeleted−28

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_jsonlite.rdeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_oj_compat.rbdeleted−25

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_oj_strict.rbdeleted−25

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_qt/build.shdeleted−4

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_qt/main.cppdeleted−25

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_qt/test_qt.prodeleted−12

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_rjson.rdeleted−7

This diff is too big to show here.

tests/JSONTestSuite/parsers/test_yajl.rbdeleted−24

This diff is too big to show here.

tests/JSONTestSuite/results/logs.txtdeleted−2048

This diff is too big to show here.

tests/JSONTestSuite/results/parsing.htmldeleted−2816

This diff is too big to show here.

tests/JSONTestSuite/results/parsing_pruned.htmldeleted−2661

This diff is too big to show here.

tests/JSONTestSuite/results/pruned_results.pngdeleted

Binary file not shown.

tests/JSONTestSuite/results/style.cssdeleted−89

This diff is too big to show here.

tests/JSONTestSuite/results/transform.htmldeleted−1492

This diff is too big to show here.

tests/JSONTestSuite/run_tests.pydeleted−673

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_object_key_lone_2nd_surrogate.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_UTF-16LE_with_BOM.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/i_string_UTF-8_invalid_sequence.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_pair.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_incomplete_surrogates_escape_valid.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_invalid_lonely_surrogate.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_invalid_surrogate.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_inverted_surrogates_U+1D11E.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_lone_second_surrogate.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_not_in_unicode_range.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_truncated-utf-8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_unicode_U+10FFFE_nonchar.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_unicode_U+1FFFE_nonchar.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_unicode_U+FDD0_nonchar.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_string_unicode_U+FFFE_nonchar.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_structure_500_nested_arrays.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/i_structure_UTF-8_BOM_empty_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_1_true_without_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_a_invalid_utf8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_colon_instead_of_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_comma_after_close.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_comma_and_number.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_double_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_double_extra_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_extra_close.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_extra_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_incomplete.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_incomplete_invalid_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_inner_array_no_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_invalid_utf8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_items_separated_by_semicolon.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_just_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_just_minus.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_missing_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_newlines_unclosed.jsondeleted−3

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_number_and_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_number_and_several_commas.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_spaces_vertical_tab_formfeed.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_star_inside.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_unclosed.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_unclosed_trailing_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_unclosed_with_new_lines.jsondeleted−3

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_array_unclosed_with_object_inside.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_incomplete_false.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_incomplete_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_incomplete_true.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_++.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_+1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_+Inf.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_-01.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_-1.0..jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_-2..jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_-NaN.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_.-1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_.2e-3.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0.1.2.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0.3e+.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0.3e.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0.e1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0_capital_E+.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0_capital_E.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0e+.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_0e.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_1.0e+.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_1.0e-.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_1.0e.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_1_000.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_1eE2.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_2.e+3.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_2.e-3.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_2.e3.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_9.e+.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_Inf.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_NaN.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_U+FF11_fullwidth_digit_one.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_expression.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_hex_1_digit.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_hex_2_digits.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_infinity.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_invalid+-.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_invalid-negative-real.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-bigger-int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-exponent.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_minus_infinity.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_minus_sign_with_trailing_garbage.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_minus_space_1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_neg_int_starting_with_zero.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_neg_real_without_int_part.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_neg_with_garbage_at_end.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_real_garbage_after_e.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_real_with_invalid_utf8_after_e.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_real_without_fractional_part.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_starting_with_dot.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_then_00.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/n_number_with_alpha.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_with_alpha_char.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_number_with_leading_zero.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_bad_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_bracket_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_comma_instead_of_colon.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_double_colon.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_emoji.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_garbage_at_end.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_key_with_single_quotes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_missing_colon.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_missing_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_missing_semicolon.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_missing_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_no-colon.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_non_string_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_non_string_key_but_huge_number_instead.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_pi_in_key_and_trailing_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_repeated_null_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_several_trailing_commas.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_single_quote.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_trailing_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_trailing_comment.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_trailing_comment_open.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open_incomplete.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_two_commas_in_a_row.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_unquoted_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_unterminated-value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_with_single_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_object_with_trailing_garbage.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_single_space.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape u.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape u1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape u1x.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_UTF8_surrogate_U+D800.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_accentuated_char_no_quotes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_backslash_00.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/n_string_escape_x.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_escaped_backslash_bad.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_escaped_ctrl_char_tab.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_escaped_emoji.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_incomplete_escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_incomplete_escaped_character.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_incomplete_surrogate.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_incomplete_surrogate_escape_invalid.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_invalid-utf-8-in-escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_invalid_backslash_esc.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_invalid_unicode_escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_invalid_utf-8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_invalid_utf8_after_escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_iso_latin_1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_leading_uescaped_thinspace.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_lone_utf8_continuation_byte.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_no_quotes_with_bad_escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_overlong_sequence_2_bytes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_overlong_sequence_6_bytes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_overlong_sequence_6_bytes_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_single_doublequote.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_single_quote.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_single_string_no_double_quotes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_start_escape_unclosed.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_unescaped_crtl_char.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/n_string_unescaped_newline.jsondeleted−2

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_unescaped_tab.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_unicode_CapitalU.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_string_with_trailing_garbage.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_..jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_100000_opening_arrays.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_U+2060_word_joined.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_UTF8_BOM_no_data.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_array_trailing_garbage.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_array_with_extra_array_close.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_array_with_unclosed_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_ascii-unicode-identifier.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_capitalized_True.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_close_unopened_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_comma_instead_of_closing_brace.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_double_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_end_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_incomplete_UTF8_BOM.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_lone-invalid-utf-8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_lone-open-bracket.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_no_data.jsondeleted

No changes to the content.

tests/JSONTestSuite/test_parsing/n_structure_null-byte-outside-string.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/n_structure_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_number_with_trailing_garbage.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_object_followed_by_closing_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_object_unclosed_no_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_object_with_comment.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_object_with_trailing_garbage.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_array_apostrophe.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_array_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_array_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_array_open_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_array_open_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_array_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_object_close_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_object_comma.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_object_open_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_object_open_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_object_string_with_apostrophes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_open_open.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_single_point.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_single_star.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_trailing_#.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_uescaped_LF_before_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_unclosed_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_unclosed_array_partial_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_false.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_true.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_unclosed_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_unicode-identifier.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_whitespace_U+2060_word_joiner.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/n_structure_whitespace_formfeed.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_arraysWithSpaces.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_empty-string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_empty.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_ending_with_newline.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_false.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_heterogeneous.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_with_1_and_newline.jsondeleted−2

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_with_leading_space.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_with_several_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_array_with_trailing_space.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_0e+1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_0e1.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_after_space.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_double_close_to_zero.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_double_huge_neg_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_huge_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_int_with_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_minus_zero.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_neg_int_huge_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_negative_int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_negative_one.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_negative_zero.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_pos_double_huge_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_capital_e.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_capital_e_neg_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_exponent.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_fraction_exponent.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_neg_exp.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_neg_overflow.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_pos_exponent.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_pos_overflow.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_real_underflow.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_simple_int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_simple_real.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_too_big_neg_int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_too_big_pos_int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_number_very_big_negative_int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_basic.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_duplicated_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_duplicated_key_and_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_empty.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_empty_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_escaped_null_in_key.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_extreme_numbers.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_long_strings.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_simple.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_string_unicode.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_object_with_newlines.jsondeleted−3

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pair.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pairs.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_allowed_escapes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_backslash_and_u_escaped_zero.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_backslash_doublequotes.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_comments.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_double_escape_a.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_double_escape_n.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_escaped_control_character.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_escaped_noncharacter.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_in_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_in_array_with_leading_space.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_last_surrogates_1_and_2.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_newline_uescaped.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+1FFFF.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_null_escape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_one-byte-utf-8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_pi.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_simple_ascii.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_space.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_three-byte-utf-8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_two-byte-utf-8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_u+2028_line_sep.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_u+2029_par_sep.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_uEscape.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unescaped_char_delete.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unicode.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unicodeEscapedBackslash.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unicode_2.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unicode_U+2064_invisible_plus.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_unicode_escaped_double_quote.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_utf16BE_no_BOM.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/y_string_utf16LE_no_BOM.jsondeleted

Binary file not shown.

tests/JSONTestSuite/test_parsing/y_string_utf8.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_string_with_del_character.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_lonely_false.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_lonely_int.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_lonely_negative_real.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_lonely_null.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_lonely_string.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_lonely_true.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_string_empty.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_trailing_newline.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_true_in_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_parsing/y_structure_whitespace_array.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/number_1.0.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/number_1.000000000000000005.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/number_1000000000000000.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/number_10000000000000000999.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/number_1e-999.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/number_1e6.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/object_key_nfc_nfd.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/object_key_nfd_nfc.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/object_same_key_different_values.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/object_same_key_same_value.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/object_same_key_unclear_values.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_1_escaped_invalid_codepoint.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_1_invalid_codepoint.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_2_escaped_invalid_codepoints.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_2_invalid_codepoints.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_3_escaped_invalid_codepoints.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_3_invalid_codepoints.jsondeleted−1

This diff is too big to show here.

tests/JSONTestSuite/test_transform/string_with_escaped_NULL.jsondeleted−1

This diff is too big to show here.

tests/Options.hs+1−33

This diff is too big to show here.

tests/PropUtils.hsdeleted−208

This diff is too big to show here.

tests/Properties.hs+266−19

This diff is too big to show here.

tests/PropertyGeneric.hsdeleted−116

This diff is too big to show here.

tests/PropertyKeys.hsdeleted−40

This diff is too big to show here.

tests/PropertyRTFunctors.hsdeleted−51

This diff is too big to show here.

tests/PropertyRoundTrip.hsdeleted−74

This diff is too big to show here.

tests/PropertyTH.hsdeleted−130

This diff is too big to show here.

tests/SerializationFormatSpec.hsdeleted−294

This diff is too big to show here.

tests/Tests.hs+2−7

This diff is too big to show here.

tests/Types.hs+4−93

This diff is too big to show here.

tests/UnitTests.hs+94−504

This diff is too big to show here.

tests/UnitTests/NullaryConstructors.hs+3−14

This diff is too big to show here.

tests/golden/generic.expecteddeleted−48

This diff is too big to show here.

tests/golden/simple.expecteddeleted−22

This diff is too big to show here.

travis/cabal_macros.hdeleted−448

This diff is too big to show here.

travis/install.sh−11

This diff is too big to show here.

travis/script.sh+1−8

This diff is too big to show here.