@@ -71,7 +71,7 @@ import Data.Text (Text, pack, unpack)
71import Data.Time.Clock (UTCTime)
71import Data.Time.Clock (UTCTime)
72import Data.Time.Format (FormatTime, formatTime, parseTime)
72import Data.Time.Format (FormatTime, formatTime, parseTime)
73import Data.Typeable (Typeable)
73import Data.Typeable (Typeable)
74−import Data.Vector (Vector, (!?))
74+import Data.Vector (Vector)
75import Data.Word (Word, Word8, Word16, Word32, Word64)
75import Data.Word (Word, Word8, Word16, Word32, Word64)
76import Foreign.Storable (Storable)
76import Foreign.Storable (Storable)
77import System.Locale (defaultTimeLocale)
77import System.Locale (defaultTimeLocale)
@@ -953,6 +953,8 @@ instance (GObject a, GObject b) => GToJSON (a :+: b) where
953class ConsToJSON f where consToJSON :: f a -> Value
953class ConsToJSON f where consToJSON :: f a -> Value
954class ConsToJSON' b f where consToJSON' :: Tagged b (f a -> Value)
954class ConsToJSON' b f where consToJSON' :: Tagged b (f a -> Value)
956+newtype Tagged s b = Tagged {unTagged :: b}
956instance (IsRecord f b, ConsToJSON' b f) => ConsToJSON f where
958instance (IsRecord f b, ConsToJSON' b f) => ConsToJSON f where
957 consToJSON = unTagged (consToJSON' :: Tagged b (f a -> Value))
959 consToJSON = unTagged (consToJSON' :: Tagged b (f a -> Value))
958 {-# INLINE consToJSON #-}
960 {-# INLINE consToJSON #-}
@@ -1029,8 +1031,18 @@ instance (ConsFromJSON a) => GFromJSON (C1 c a) where
1029 gParseJSON = fmap M1 . consParseJSON
1031 gParseJSON = fmap M1 . consParseJSON
1030 {-# INLINE gParseJSON #-}
1032 {-# INLINE gParseJSON #-}
1032−instance (GFromProduct a, GFromProduct b) => GFromJSON (a :*: b) where
1034+instance ( GFromProduct a, GFromProduct b
1035+ , ProductSize a, ProductSize b) => GFromJSON (a :*: b) where
1033− gParseJSON (Array arr) = gParseProduct arr
1036+ gParseJSON (Array arr)
1037+ | lenArray == lenProduct = gParseProduct arr
1039+ fail $ "When expecting a product of " ++ show lenProduct ++
1040+ " values, encountered an Array of " ++ show lenArray ++
1041+ " elements instead"
1043+ lenArray = V.length arr
1044+ lenProduct = unTagged2 (productSize :: Tagged2 (a :*: b) Int)
1034 gParseJSON v = typeMismatch "product (:*:)" v
1046 gParseJSON v = typeMismatch "product (:*:)" v
1035 {-# INLINE gParseJSON #-}
1047 {-# INLINE gParseJSON #-}
@@ -1078,6 +1090,20 @@ instance (Selector s, GFromJSON a) => GFromRecord (S1 s a) where
1079--------------------------------------------------------------------------------
1091--------------------------------------------------------------------------------
1093+class ProductSize f where
1094+ productSize :: Tagged2 f Int
1096+newtype Tagged2 (s :: * -> *) b = Tagged2 {unTagged2 :: b}
1098+instance (ProductSize a, ProductSize b) => ProductSize (a :*: b) where
1099+ productSize = Tagged2 $ unTagged2 (productSize :: Tagged2 a Int) +
1100+ unTagged2 (productSize :: Tagged2 b Int)
1102+instance ProductSize (S1 s a) where
1103+ productSize = Tagged2 1
1105+--------------------------------------------------------------------------------
1081class GFromProduct f where
1107class GFromProduct f where
1082 gParseProduct :: Array -> Parser (f a)
1108 gParseProduct :: Array -> Parser (f a)
@@ -1087,9 +1113,8 @@ instance (GFromProduct a, GFromProduct b) => GFromProduct (a :*: b) where
1087 (arrL, arrR) = V.splitAt (V.length arr `div` 2) arr
1113 (arrL, arrR) = V.splitAt (V.length arr `div` 2) arr
1088 {-# INLINE gParseProduct #-}
1114 {-# INLINE gParseProduct #-}
1090−instance (GFromJSON a) => GFromProduct a where
1116+instance (GFromJSON a) => GFromProduct (S1 s a) where
1091− gParseProduct ((!? 0) -> Just v) = gParseJSON v
1117+ gParseProduct arr = gParseJSON $ V.unsafeIndex arr 0
1092− gParseProduct _ = fail "Array to small"
1093 {-# INLINE gParseProduct #-}
1118 {-# INLINE gParseProduct #-}
1095--------------------------------------------------------------------------------
1120--------------------------------------------------------------------------------
@@ -1109,16 +1134,15 @@ instance (Constructor c, GFromJSON a, ConsFromJSON a) => GFromSum (C1 c a) where
1110notFound :: String -> Parser a
1135notFound :: String -> Parser a
1111notFound key = fail $ "The key \"" ++ key ++ "\" was not found"
1136notFound key = fail $ "The key \"" ++ key ++ "\" was not found"
1137+{-# INLINE notFound #-}
1113--------------------------------------------------------------------------------
1139--------------------------------------------------------------------------------
1115−newtype Tagged s b = Tagged {unTagged :: b}
1141+class IsRecord (f :: * -> *) b | f -> b
1117data True
1143data True
1118data False
1144data False
1120−class IsRecord (f :: * -> *) b | f -> b
1122instance (IsRecord f b) => IsRecord (f :*: g) b
1146instance (IsRecord f b) => IsRecord (f :*: g) b
1123instance IsRecord (M1 S NoSelector f) False
1147instance IsRecord (M1 S NoSelector f) False
1124instance (IsRecord f b) => IsRecord (M1 S c f) b
1148instance (IsRecord f b) => IsRecord (M1 S c f) b