@@ -1,7 +1,15 @@
1−{-# LANGUAGE DefaultSignatures, EmptyDataDecls, FlexibleContexts,
1+{-# LANGUAGE DefaultSignatures
2− FlexibleInstances, FunctionalDependencies, IncoherentInstances,
4+ , FunctionalDependencies
3− KindSignatures, OverlappingInstances, ScopedTypeVariables, TypeOperators,
6+ , OverlappingInstances
4− UndecidableInstances, ViewPatterns #-}
9+ , UndecidableInstances
5{-# OPTIONS_GHC -fno-warn-orphans #-}
13{-# OPTIONS_GHC -fno-warn-orphans #-}
@@ -18,10 +26,10 @@ module Data.Aeson.Types.Generic ( ) where
19import Control.Applicative
27import Control.Applicative
20import Control.Monad.State.Strict
28import Control.Monad.State.Strict
29+import Data.Bits (shiftR)
21import Data.Aeson.Types.Class
30import Data.Aeson.Types.Class
22import Data.Aeson.Types.Internal
31import Data.Aeson.Types.Internal
23import Data.Text (pack, unpack)
32import Data.Text (pack, unpack)
24−import Data.Vector ((!?))
25import GHC.Generics
33import GHC.Generics
26import qualified Data.Map as M
34import qualified Data.Map as M
27import qualified Data.Text as T
35import qualified Data.Text as T
@@ -60,6 +68,8 @@ instance (GObject a, GObject b) => GToJSON (a :+: b) where
60class ConsToJSON f where consToJSON :: f a -> Value
68class ConsToJSON f where consToJSON :: f a -> Value
61class ConsToJSON' b f where consToJSON' :: Tagged b (f a -> Value)
69class ConsToJSON' b f where consToJSON' :: Tagged b (f a -> Value)
71+newtype Tagged s b = Tagged {unTagged :: b}
63instance (IsRecord f b, ConsToJSON' b f) => ConsToJSON f where
73instance (IsRecord f b, ConsToJSON' b f) => ConsToJSON f where
64 consToJSON = unTagged (consToJSON' :: Tagged b (f a -> Value))
74 consToJSON = unTagged (consToJSON' :: Tagged b (f a -> Value))
65 {-# INLINE consToJSON #-}
75 {-# INLINE consToJSON #-}
@@ -109,7 +119,7 @@ instance (GObject a, GObject b) => GObject (a :+: b) where
109 {-# INLINE gObject #-}
119 {-# INLINE gObject #-}
111instance (Constructor c, GToJSON a, ConsToJSON a) => GObject (C1 c a) where
121instance (Constructor c, GToJSON a, ConsToJSON a) => GObject (C1 c a) where
112− gObject m1 = M.singleton (pack (conName m1)) (gToJSON m1)
122+ gObject = M.singleton (pack $ conName (undefined :: t c a p)) . gToJSON
113 {-# INLINE gObject #-}
123 {-# INLINE gObject #-}
115--------------------------------------------------------------------------------
125--------------------------------------------------------------------------------
@@ -133,16 +143,33 @@ instance (ConsFromJSON a) => GFromJSON (C1 c a) where
133 gParseJSON = fmap M1 . consParseJSON
143 gParseJSON = fmap M1 . consParseJSON
134 {-# INLINE gParseJSON #-}
144 {-# INLINE gParseJSON #-}
136−instance (GFromProduct a, GFromProduct b) => GFromJSON (a :*: b) where
146+instance ( GFromProduct a, GFromProduct b
147+ , ProductSize a, ProductSize b) => GFromJSON (a :*: b) where
137− gParseJSON (Array arr) = gParseProduct arr
148+ gParseJSON (Array arr)
149+ | lenArray == lenProduct = gParseProduct arr 0 lenProduct
151+ fail $ "When expecting a product of " ++ show lenProduct ++
152+ " values, encountered an Array of " ++ show lenArray ++
155+ lenArray = V.length arr
156+ lenProduct = unTagged2 (productSize :: Tagged2 (a :*: b) Int)
138 gParseJSON v = typeMismatch "product (:*:)" v
158 gParseJSON v = typeMismatch "product (:*:)" v
139 {-# INLINE gParseJSON #-}
159 {-# INLINE gParseJSON #-}
141instance (GFromSum a, GFromSum b) => GFromJSON (a :+: b) where
161instance (GFromSum a, GFromSum b) => GFromJSON (a :+: b) where
142− gParseJSON (Object (M.toList -> [keyVal])) = gParseSum keyVal
162+ gParseJSON (Object (M.toList -> [keyVal@(key, _)])) =
163+ case gParseSum keyVal of
164+ Nothing -> notFound $ unpack key
143 gParseJSON v = typeMismatch "sum (:+:)" v
166 gParseJSON v = typeMismatch "sum (:+:)" v
144 {-# INLINE gParseJSON #-}
167 {-# INLINE gParseJSON #-}
169+notFound :: String -> Parser a
170+notFound key = fail $ "The key \"" ++ key ++ "\" was not found"
171+{-# INLINE notFound #-}
146--------------------------------------------------------------------------------
173--------------------------------------------------------------------------------
148class ConsFromJSON f where consParseJSON :: Value -> Parser (f a)
175class ConsFromJSON f where consParseJSON :: Value -> Parser (f a)
@@ -173,56 +200,66 @@ instance (GFromRecord a, GFromRecord b) => GFromRecord (a :*: b) where
173 {-# INLINE gParseRecord #-}
200 {-# INLINE gParseRecord #-}
175instance (Selector s, GFromJSON a) => GFromRecord (S1 s a) where
202instance (Selector s, GFromJSON a) => GFromRecord (S1 s a) where
176− gParseRecord obj = case M.lookup (T.pack key) obj of
203+ gParseRecord = maybe (notFound key) gParseJSON . M.lookup (T.pack key)
177− Nothing -> notFound key
178− Just v -> gParseJSON v
180 key = selName (undefined :: t s a p)
205 key = selName (undefined :: t s a p)
181 {-# INLINE gParseRecord #-}
206 {-# INLINE gParseRecord #-}
183--------------------------------------------------------------------------------
208--------------------------------------------------------------------------------
210+class ProductSize f where
211+ productSize :: Tagged2 f Int
213+newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}
215+instance (ProductSize a, ProductSize b) => ProductSize (a :*: b) where
216+ productSize = Tagged2 $ unTagged2 (productSize :: Tagged2 a Int) +
217+ unTagged2 (productSize :: Tagged2 b Int)
219+instance ProductSize (S1 s a) where
220+ productSize = Tagged2 1
222+--------------------------------------------------------------------------------
185class GFromProduct f where
224class GFromProduct f where
186− gParseProduct :: Array -> Parser (f a)
225+ gParseProduct :: Array -> Int -> Int -> Parser (f a)
188instance (GFromProduct a, GFromProduct b) => GFromProduct (a :*: b) where
227instance (GFromProduct a, GFromProduct b) => GFromProduct (a :*: b) where
189− gParseProduct arr = (:*:) <$> gParseProduct arrL <*> gParseProduct arrR
228+ gParseProduct arr ix len = (:*:) <$> gParseProduct arr ix lenL
229+ <*> gParseProduct arr ixR lenR
191− (arrL, arrR) = V.splitAt (V.length arr `div` 2) arr
231+ lenL = len `shiftR` 1
192 {-# INLINE gParseProduct #-}
234 {-# INLINE gParseProduct #-}
194−instance (GFromJSON a) => GFromProduct a where
236+instance (GFromJSON a) => GFromProduct (S1 s a) where
195− gParseProduct ((!? 0) -> Just v) = gParseJSON v
237+ gParseProduct arr ix _ = gParseJSON $ V.unsafeIndex arr ix
196− gParseProduct _ = fail "Array to small"
197 {-# INLINE gParseProduct #-}
238 {-# INLINE gParseProduct #-}
199--------------------------------------------------------------------------------
240--------------------------------------------------------------------------------
201class GFromSum f where
242class GFromSum f where
202− gParseSum :: Pair -> Parser (f a)
243+ gParseSum :: Pair -> Maybe (Parser (f a))
204instance (GFromSum a, GFromSum b) => GFromSum (a :+: b) where
245instance (GFromSum a, GFromSum b) => GFromSum (a :+: b) where
205− gParseSum keyVal = (L1 <$> gParseSum keyVal) <|> (R1 <$> gParseSum keyVal)
246+ gParseSum keyVal = (fmap L1 <$> gParseSum keyVal) <|>
247+ (fmap R1 <$> gParseSum keyVal)
206 {-# INLINE gParseSum #-}
248 {-# INLINE gParseSum #-}
208instance (Constructor c, GFromJSON a, ConsFromJSON a) => GFromSum (C1 c a) where
250instance (Constructor c, GFromJSON a, ConsFromJSON a) => GFromSum (C1 c a) where
209 gParseSum (key, value)
251 gParseSum (key, value)
210− | key == pack (conName (undefined :: t c a p)) = gParseJSON value
252+ | key == pack (conName (undefined :: t c a p)) = Just $ gParseJSON value
211− | otherwise = notFound $ unpack key
253+ | otherwise = Nothing
212 {-# INLINE gParseSum #-}
254 {-# INLINE gParseSum #-}
214−notFound :: String -> Parser a
215−notFound key = fail $ "The key \"" ++ key ++ "\" was not found"
217--------------------------------------------------------------------------------
256--------------------------------------------------------------------------------
219−newtype Tagged s b = Tagged {unTagged :: b}
258+class IsRecord (f :: * -> *) b | f -> b
222data False
261data False
224−class IsRecord (f :: * -> *) b | f -> b
226instance (IsRecord f b) => IsRecord (f :*: g) b
263instance (IsRecord f b) => IsRecord (f :*: g) b
227instance IsRecord (M1 S NoSelector f) False
264instance IsRecord (M1 S NoSelector f) False
228instance (IsRecord f b) => IsRecord (M1 S c f) b
265instance (IsRecord f b) => IsRecord (M1 S c f) b