-- This module heavily relies on code borrowed from the "safecopy"
-- library by David Himmelstrup and Felipe Lessa, found on
-- "https://github.com/acid-state/safecopy"
--
-- Though it has gone through extensive refactoring because of
-- desired behaviour being different from the safecopy library
-- and the fact that this library works with JSON, instead of
-- byte serialization.
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE UndecidableInstances #-}
{-|
Module      : Data.SafeJSON.Internal
Copyright   : (c) 2019 Felix Paulusma
License     : MIT
Maintainer  : felix.paulusma@gmail.com
Stability   : experimental

This module contains all "under-the-hood" functions
and types. "Data.SafeJSON" exports everything for the
outward-facing API.
-}
module Data.SafeJSON.Internal where


#if MIN_VERSION_base(4,13,0)
import Control.Applicative (Const(..), (<|>))
#else
import Control.Applicative (Applicative(..), Const(..), (<|>))
import Control.Monad.Fail (MonadFail)
#endif
import Control.Monad (when)
import Data.Aeson
import Data.Aeson.Types (Parser, explicitParseField, explicitParseFieldMaybe, explicitParseFieldMaybe')
import Data.DList as DList (DList, fromList)
import Data.Fixed (Fixed, HasResolution)
import Data.Functor.Identity (Identity(..))
import Data.Functor.Compose (Compose (..))
import Data.Functor.Product (Product (..))
import Data.Functor.Sum (Sum(..))
import Data.Hashable (Hashable)
import Data.HashMap.Strict (HashMap)
import qualified Data.HashSet as HS (HashSet, fromList, toList)
import Data.Int (Int16, Int32, Int64, Int8)
import Data.IntMap as IM (IntMap, fromList)
import Data.IntSet (IntSet)
import qualified Data.List as List (intercalate, lookup)
import Data.List.NonEmpty (NonEmpty(..))
import Data.Map as M (Map, singleton)
import Data.Maybe (fromMaybe, isJust, isNothing)
#if MIN_VERSION_base(4,11,0)
import Data.Monoid (Dual(..))
#else
import Data.Monoid (Dual(..), (<>))
#endif
import Data.Proxy (Proxy (..))
import Data.Ratio (Ratio)
import Data.Scientific (Scientific)
import Data.Semigroup (First(..), Last(..), Max(..), Min(..))
import Data.Sequence (Seq)
import qualified Data.Set as S
import Data.Text as T (Text)
import qualified Data.Text.Lazy as LT (Text)
import Data.Time
    ( Day,
      DiffTime,
      NominalDiffTime,
      UTCTime,
      LocalTime,
      TimeOfDay,
      ZonedTime )
import Data.Tree (Tree)
import Data.Typeable (Typeable, typeRep)
import Data.UUID.Types (UUID)
import qualified Data.Vector as V
import qualified Data.Vector.Generic as VG
import qualified Data.Vector.Primitive as VP
import qualified Data.Vector.Storable as VS
import qualified Data.Vector.Unboxed as VU
import qualified Data.Version as DV (Version)
import Data.Void (Void)
import Data.Word (Word8, Word16, Word32, Word64)
import Foreign.C.Types (CTime)
import Numeric.Natural (Natural)
import Test.Tasty.QuickCheck (Arbitrary(..), shrinkIntegral)

#if MIN_VERSION_aeson(2,0,0)
import qualified Data.Aeson.Key as K (Key)
import qualified Data.Aeson.KeyMap as Map (KeyMap, delete, insert, lookup, size, toList)
#if !MIN_VERSION_aeson(2,0,1)
import qualified Data.Aeson.KeyMapp as Map (fromMap)
#endif
#else
import qualified Data.HashMap.Strict as Map (delete, insert, lookup, size, toList)
#endif

-- | A type that can be converted from and to JSON with versioning baked
--   in, using 'Migrate' to automate migration between versions, reducing
--   headaches when the need arrises to modify JSON formats while old
--   formats can't simply be disregarded.
class SafeJSON a where
  -- | The version of the type.
  --
  --   Only used as a key so it __must be unique__ (this is checked at run-time)
  --
  --   Version numbering __doesn't have to be sequential or continuous__.
  --
  --   /The default version is 0 (zero)./
  version :: Version a
  version = Version a
0

  -- | The kind specifies how versions are dealt with. By default,
  --   values are tagged with version 0 and don't have any
  --   previous versions.
  --
  --   /The default kind is/ 'base'
  kind :: Kind a
  kind = Kind a
forall a. Kind a
Base

  -- | This method defines how a value should be serialized without worrying
  --   about adding the version. The default implementation uses 'toJSON', but
  --   can be modified if need be.
  --
  --   This function cannot be used directly. Use 'safeToJSON', instead.
  safeTo :: a -> Contained Value
  default safeTo :: ToJSON a => a -> Contained Value
  safeTo = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> (a -> Value) -> a -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Value
forall a. ToJSON a => a -> Value
toJSON

  -- | This method defines how a value should be parsed without also worrying
  --   about writing out the version tag. The default implementation uses 'parseJSON',
  --   but can be modified if need be.
  --
  --   This function cannot be used directly. Use 'safeFromJSON', instead.
  safeFrom :: Value -> Contained (Parser a)
  default safeFrom :: FromJSON a => Value -> Contained (Parser a)
  safeFrom = Parser a -> Contained (Parser a)
forall a. a -> Contained a
contain (Parser a -> Contained (Parser a))
-> (Value -> Parser a) -> Value -> Contained (Parser a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Parser a
forall a. FromJSON a => Value -> Parser a
parseJSON

  -- | The name of the type. This is used in error message strings and the
  --   'Profile' report.
  --
  --   Doesn't have to be defined if your type is 'Data.Typeable.Typeable'. The default
  --   implementation is 'typeName0'. (cf. 'typeName1', 'typeName2', etc.)
  typeName :: Proxy a -> String
  default typeName :: Typeable a => Proxy a -> String
  typeName = Proxy a -> String
forall a. Typeable a => Proxy a -> String
typeName0

  --   Internal function that should not be overrided.
  --   @Consistent@ if the version history is consistent
  --   (i.e. there are no duplicate version numbers) and
  --   the chain of migrations is valid.
  --
  --   This function is in the typeclass so that this
  --   information is calculated only once during the program
  --   lifetime, instead of everytime 'safeFrom' or 'safeTo' is used.
  internalConsistency :: Consistency a
  internalConsistency = Proxy a -> Consistency a
forall a. SafeJSON a => Proxy a -> Consistency a
computeConsistency Proxy a
forall k (t :: k). Proxy t
Proxy

  -- | Version profile.
  --
  --   Shows the current version of the type and all supported
  --   versions it can migrate from.
  objectProfile :: Profile a
  objectProfile = Proxy a -> Profile a
forall a. SafeJSON a => Proxy a -> Profile a
mkProfile Proxy a
forall k (t :: k). Proxy t
Proxy

  {-# MINIMAL #-}

-- | This instance is needed to handle the migration between
--   older and newer versions.
--
--   Note that, where @('Migrate' a)@ migrates from the previous
--   version to the type @a@, @('Migrate' ('Reverse' a))@ migrates
--   from the future version to the type @a@.
--
-- === __Example__
--
-- __Two types that can migrate to each other.__
--
-- (Don't forget to give @OldType@ one of the @extended@ 'kind's,
-- and @NewType@ one of the @extension@ 'kind's.)
--
-- @
-- instance 'Migrate' NewType where
--   type 'MigrateFrom' NewType = OldType
--   'migrate' OldType = NewType
--
-- instance 'Migrate' ('Reverse' OldType) where
--   type 'MigrateFrom' ('Reverse' OldType) = NewType
--   'migrate' NewType = 'Reverse' OldType
-- @
class SafeJSON (MigrateFrom a) => Migrate a where
  -- | The type from which will be migrated to type @a@
  type MigrateFrom a
  -- | The migration from the previous version to the
  --   current type @a@. OR, in case of a @('Reverse' a)@,
  --   the migration from the future version back to
  --   the current type @a@
  migrate :: MigrateFrom a -> a


-- | This is an impenetrable container. A security measure
--   used to ensure 'safeFrom' and 'safeTo' are never used
--   directly. Instead, always use 'safeFromJSON' and
--   'safeToJSON'.
newtype Contained a = Contained {Contained a -> a
unsafeUnpack :: a}
  -- Opens up mis-use of 'safeFrom' / 'safeTo', better to not
  -- derive a Functor instance

-- | Used when defining 'safeFrom' or 'safeTo'.
contain :: a -> Contained a
contain :: a -> Contained a
contain = a -> Contained a
forall a. a -> Contained a
Contained

-- | A simple numeric version id.
--
--   'Version' has a 'Num' instance and should be
--   declared using integer literals: @'version' = 2@
newtype Version a = Version {Version a -> Maybe Int32
unVersion :: Maybe Int32}
  deriving (Version a -> Version a -> Bool
(Version a -> Version a -> Bool)
-> (Version a -> Version a -> Bool) -> Eq (Version a)
forall a. Version a -> Version a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Version a -> Version a -> Bool
$c/= :: forall a. Version a -> Version a -> Bool
== :: Version a -> Version a -> Bool
$c== :: forall a. Version a -> Version a -> Bool
Eq)

-- | This is used for types that don't have
--   a version tag.
--
--   This is used for primitive values that are not tagged with
--   a version number, like @Int@, @Text@, @[a]@, etc.
--
--   But also when implementing 'SafeJSON' after the fact,
--   when a format is already in use, but you still want to
--   be able to 'migrate' from it to a newer type or format.
--
--   /N.B./ @'version' = 'noVersion'@ /is distinctively different/
--   /from/ @'version' = 0@/, which will add a version tag with/
--   /the number 0 (zero), whereas/ 'noVersion' /will not add a/
--   /'version' tag./
noVersion :: Version a
noVersion :: Version a
noVersion = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version Maybe Int32
forall a. Maybe a
Nothing

-- | Same as 'setVersion', but requires a 'Version' parameter.
--
-- >>> encode $ setVersion' (version :: Version Test) val
-- "{\"~v\":0,\"~d\":\"test\"}"
--
-- @since 1.0.0
setVersion' :: forall a. SafeJSON a => Version a -> Value -> Value
setVersion' :: Version a -> Value -> Value
setVersion' (Version Maybe Int32
mVersion) Value
val =
  case Maybe Int32
mVersion of
    Maybe Int32
Nothing -> Value
val
    Just Int32
i -> case Value
val of
      Object Object
o ->
          let vField :: Key
vField = Key -> (Value -> Key) -> Maybe Value -> Key
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Key
versionField
                             (Key -> Value -> Key
forall a b. a -> b -> a
const Key
dataVersionField)
                             (Maybe Value -> Key) -> Maybe Value -> Key
forall a b. (a -> b) -> a -> b
$ Key
dataVersionField Key -> Object -> Maybe Value
forall v. Key -> KeyMap v -> Maybe v
`Map.lookup` Object
o
          in Object -> Value
Object (Object -> Value) -> Object -> Value
forall a b. (a -> b) -> a -> b
$ Key -> Value -> Object -> Object
forall v. Key -> v -> KeyMap v -> KeyMap v
Map.insert Key
vField (Int32 -> Value
forall a. ToJSON a => a -> Value
toJSON Int32
i) Object
o
      Value
other -> [Pair] -> Value
object
          [ Key
dataVersionField Key -> Int32 -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Int32
i
          , Key
dataField Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= Value
other
          ]

-- | /CAUTION: Only use this function if you know what you're doing./
--   /The version will be set top-level, without inspection of the 'Value'!/
--
--   (cf. 'removeVersion') In some rare cases, you might want to interpret
--   a versionless 'Value' as a certain type/version. 'setVersion' allows
--   you to (unsafely) insert a version field.
--
--   __If possible, it is advised to use a 'FromJSON' instance instead.__
--   (One that doesn't also use `safeFromJSON` in its methods!)
--
--   This might be needed when data sent to an API endpoint doesn't
--   need to implement SafeJSON standards. E.g. in the case of
--   endpoints for third parties or customers.
--
-- @
-- USAGE:
--
-- {-\# LANGUAGE TypeApplications \#-}
-- data Test = Test String
-- instance 'SafeJSON' Test where ...
--
-- >>> val = 'Data.Aeson.String' "test" :: 'Value'
-- String "test"
-- >>> 'encode' val
-- "\"test\""
-- >>> 'encode' $ 'setVersion' \@Test val
-- "{\"~v\":0,\"~d\":\"test\"}"
-- >>> parseMaybe 'safeFromJSON' $ 'setVersion' \@Test val
-- Just (Test "test")
-- @
--
-- @since 1.0.0
setVersion :: forall a. SafeJSON a => Value -> Value
setVersion :: Value -> Value
setVersion = Version a -> Value -> Value
forall a. SafeJSON a => Version a -> Value -> Value
setVersion' (SafeJSON a => Version a
forall a. SafeJSON a => Version a
version @a)

-- | /CAUTION: Only use this function if you know what you're doing./
--
--   (cf. 'setVersion') 'removeVersion' removes all the 'SafeJSON'
--   versioning from a JSON 'Value'. Even recursively.
--
--   This might be necessary if the resulting JSON is sent to a
--   third party (e.g. customer) and the 'SafeJSON' versioning
--   should be hidden.
--
-- @since 1.0.0
removeVersion :: Value -> Value
removeVersion :: Value -> Value
removeVersion = \case
    Object Object
o -> Object -> Value
go Object
o
    -- Recursively find all version tags and remove them.
    Array Array
a -> Array -> Value
Array (Array -> Value) -> Array -> Value
forall a b. (a -> b) -> a -> b
$ Value -> Value
removeVersion (Value -> Value) -> Array -> Array
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Array
a
    Value
other -> Value
other
        -- Recursively find all version tags and remove them.
  where go :: Object -> Value
go Object
o = Value -> (Value -> Value) -> Maybe Value -> Value
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Value
regular Value -> Value
removeVersion (Maybe Value -> Value) -> Maybe Value -> Value
forall a b. (a -> b) -> a -> b
$ do
                  Value
_ <- Key
dataVersionField Key -> Object -> Maybe Value
forall v. Key -> KeyMap v -> Maybe v
`Map.lookup` Object
o
                  Key
dataField Key -> Object -> Maybe Value
forall v. Key -> KeyMap v -> Maybe v
`Map.lookup` Object
o
          where regular :: Value
regular = Object -> Value
Object (Object -> Value) -> Object -> Value
forall a b. (a -> b) -> a -> b
$ Value -> Value
removeVersion (Value -> Value) -> Object -> Object
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Key -> Object -> Object
forall v. Key -> KeyMap v -> KeyMap v
Map.delete Key
versionField Object
o

instance Show (Version a) where
  show :: Version a -> String
show (Version Maybe Int32
mi) = String
"Version " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Maybe Int32 -> String
showV Maybe Int32
mi

liftV :: Integer -> (Int32 -> Int32 -> Int32) -> Maybe Int32 -> Maybe Int32 -> Maybe Int32
liftV :: Integer
-> (Int32 -> Int32 -> Int32)
-> Maybe Int32
-> Maybe Int32
-> Maybe Int32
liftV Integer
_ Int32 -> Int32 -> Int32
_ Maybe Int32
Nothing Maybe Int32
Nothing = Maybe Int32
forall a. Maybe a
Nothing
liftV Integer
i Int32 -> Int32 -> Int32
f Maybe Int32
ma Maybe Int32
mb = Int32 -> Maybe Int32
forall a. a -> Maybe a
Just (Int32 -> Maybe Int32) -> Int32 -> Maybe Int32
forall a b. (a -> b) -> a -> b
$ Maybe Int32 -> Int32
toZ Maybe Int32
ma Int32 -> Int32 -> Int32
`f` Maybe Int32 -> Int32
toZ Maybe Int32
mb
  where toZ :: Maybe Int32 -> Int32
toZ = Int32 -> Maybe Int32 -> Int32
forall a. a -> Maybe a -> a
fromMaybe (Int32 -> Maybe Int32 -> Int32) -> Int32 -> Maybe Int32 -> Int32
forall a b. (a -> b) -> a -> b
$ Integer -> Int32
forall a. Num a => Integer -> a
fromInteger Integer
i

-- 'Version Nothing' is handled as if it's mempty... mostly.
-- | It is strongly discouraged to use any methods other
--   than 'fromInteger' of 'Version''s 'Num' instance.
instance Num (Version a) where
  Version Maybe Int32
ma + :: Version a -> Version a -> Version a
+ Version Maybe Int32
mb = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Integer
-> (Int32 -> Int32 -> Int32)
-> Maybe Int32
-> Maybe Int32
-> Maybe Int32
liftV Integer
0 Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
(+) Maybe Int32
ma Maybe Int32
mb
  Version Maybe Int32
ma - :: Version a -> Version a -> Version a
- Version Maybe Int32
mb = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Integer
-> (Int32 -> Int32 -> Int32)
-> Maybe Int32
-> Maybe Int32
-> Maybe Int32
liftV Integer
0 (-) Maybe Int32
ma Maybe Int32
mb
  Version Maybe Int32
ma * :: Version a -> Version a -> Version a
* Version Maybe Int32
mb = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Integer
-> (Int32 -> Int32 -> Int32)
-> Maybe Int32
-> Maybe Int32
-> Maybe Int32
liftV Integer
1 Int32 -> Int32 -> Int32
forall a. Num a => a -> a -> a
(*) Maybe Int32
ma Maybe Int32
mb
  negate :: Version a -> Version a
negate (Version Maybe Int32
ma) = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Int32 -> Int32
forall a. Num a => a -> a
negate (Int32 -> Int32) -> Maybe Int32 -> Maybe Int32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Int32
ma
  abs :: Version a -> Version a
abs    (Version Maybe Int32
ma) = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Int32 -> Int32
forall a. Num a => a -> a
abs    (Int32 -> Int32) -> Maybe Int32 -> Maybe Int32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Int32
ma
  signum :: Version a -> Version a
signum (Version Maybe Int32
ma) = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Int32 -> Int32
forall a. Num a => a -> a
signum (Int32 -> Int32) -> Maybe Int32 -> Maybe Int32
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Int32
ma
  fromInteger :: Integer -> Version a
fromInteger Integer
i = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Int32 -> Maybe Int32
forall a. a -> Maybe a
Just (Int32 -> Maybe Int32) -> Int32 -> Maybe Int32
forall a b. (a -> b) -> a -> b
$ Integer -> Int32
forall a. Num a => Integer -> a
fromInteger Integer
i

-- | This instance explicitly doesn't consider 'noVersion', since it
-- is an exception in almost every sense.
instance Arbitrary (Version a) where
  arbitrary :: Gen (Version a)
arbitrary = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a)
-> (Int32 -> Maybe Int32) -> Int32 -> Version a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> Maybe Int32
forall a. a -> Maybe a
Just (Int32 -> Version a) -> Gen Int32 -> Gen (Version a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Gen Int32
forall a. Arbitrary a => Gen a
arbitrary
  shrink :: Version a -> [Version a]
shrink (Version Maybe Int32
Nothing) = []
  shrink (Version (Just Int32
a)) = Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a)
-> (Int32 -> Maybe Int32) -> Int32 -> Version a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int32 -> Maybe Int32
forall a. a -> Maybe a
Just (Int32 -> Version a) -> [Int32] -> [Version a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Int32 -> [Int32]
forall a. Integral a => a -> [a]
shrinkIntegral Int32
a

castVersion :: Version a -> Version b
castVersion :: Version a -> Version b
castVersion (Version Maybe Int32
i) = Maybe Int32 -> Version b
forall a. Maybe Int32 -> Version a
Version Maybe Int32
i

-- | This is a wrapper type used migrating backwards in the chain of compatible types.
--
--   This is useful when running updates in production where new-format JSON will be
--   received by old-format expecting programs.
newtype Reverse a = Reverse { Reverse a -> a
unReverse :: a }

-- | The 'kind' of a 'SafeJSON' type determines how it can be migrated to.
data Kind a where
  Base :: Kind a
  Extends :: Migrate a => Proxy (MigrateFrom a) -> Kind a
  Extended :: Migrate (Reverse a) => Kind a -> Kind a

-- | Used to define 'kind'.
--   @Base@ types do not extend any type.
base :: Kind a
base :: Kind a
base = Kind a
forall a. Kind a
Base

-- | Used to define 'kind'.
--   Extends a previous version.
extension :: (SafeJSON a, Migrate a) => Kind a
extension :: Kind a
extension = Proxy (MigrateFrom a) -> Kind a
forall a. Migrate a => Proxy (MigrateFrom a) -> Kind a
Extends Proxy (MigrateFrom a)
forall k (t :: k). Proxy t
Proxy

-- | Used to define 'kind'.
--   Types that are 'extended_base', are extended by a
--   future version and as such can migrate backward from
--   that future version. (cf. 'extended_extension', 'base')
extended_base :: (SafeJSON a, Migrate (Reverse a)) => Kind a
extended_base :: Kind a
extended_base = Kind a -> Kind a
forall a. Migrate (Reverse a) => Kind a -> Kind a
Extended Kind a
forall a. Kind a
base

-- | Used to define 'kind'.
--   Types that are 'extended_extension' are extended
--   by a future version and as such can migrate from
--   that future version, but they also extend a previous
--   version. (cf. 'extended_base', 'extension')
extended_extension :: (SafeJSON a, Migrate a, Migrate (Reverse a)) => Kind a
extended_extension :: Kind a
extended_extension = Kind a -> Kind a
forall a. Migrate (Reverse a) => Kind a -> Kind a
Extended Kind a
forall a. (SafeJSON a, Migrate a) => Kind a
extension

-- The '!' and '~' used in these set fields are chosen for their
-- low probability of showing up naturally in JSON objects one
-- would normally find or construct.

#if MIN_VERSION_aeson(2,0,0)
versionField, dataVersionField, dataField :: Key
#else
versionField, dataVersionField, dataField :: Text
#endif
versionField :: Key
versionField = Key
"!v"
dataVersionField :: Key
dataVersionField = Key
"~v"
dataField :: Key
dataField = Key
"~d"

-- | Use this exactly how you would use 'toJSON' from "Data.Aeson".
--   Though most use cases will probably use one of the 'Data.Aeson.Safe.encode'
--   functions from "Data.Aeson.Safe".
--
--   'safeToJSON' will add a version tag to the 'Data.Aeson.Value' created.
--   If the 'Data.Aeson.Value' resulting from 'safeTo' (by default the same as 'toJSON')
--   is an @'Object'@, an extra field with the version number will be added.
--
-- > Example value:
-- >   {"type":"test", "data":true}
-- >
-- > Resulting object:
-- >   {"!v": 1, "type":"test", "data":true}
--
--   If the resulting 'Value' is not an @'Object'@, it will be wrapped
--   in one, with a version field:
--
-- > Example value:
-- >   "arbitrary string"
-- >
-- > Resulting object:
-- >   {"~v": 1, "~d": "arbitrary string"}
--
--   __This function does not check consistency of the 'SafeJSON' instances.__
--   __It is advised to always 'Data.SafeJSON.Test.testConsistency' for all__
--   __your instances in a production setting.__
safeToJSON :: forall a. SafeJSON a => a -> Value
safeToJSON :: a -> Value
safeToJSON a
a = case Kind a
thisKind of
    Kind a
Base          | Maybe Int32 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int32
i -> Value
tojson
    Extended Kind a
Base | Maybe Int32 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int32
i -> Value
tojson
    Kind a
_ -> Value -> Value
forall a. SafeJSON a => Value -> Value
setVersion @a Value
tojson
  where tojson :: Value
tojson = Contained Value -> Value
forall a. Contained a -> a
unsafeUnpack (Contained Value -> Value) -> Contained Value -> Value
forall a b. (a -> b) -> a -> b
$ a -> Contained Value
forall a. SafeJSON a => a -> Contained Value
safeTo a
a
        Version Maybe Int32
i = Version a
forall a. SafeJSON a => Version a
version :: Version a
        thisKind :: Kind a
thisKind = Kind a
forall a. SafeJSON a => Kind a
kind :: Kind a

-- The consistency is checked on first parse, after that
-- there is no overhead.
-- | Use this exactly how you would use 'parseJSON' from "Data.Aeson".
--   Though most use cases will probably use one of the 'Data.Aeson.Safe.decode'
--   functions from "Data.Aeson.Safe".
--
--   'safeFromJSON' tries to find the version number in the JSON
--   'Value' provided, find the appropriate parser and migrate the
--   parsed result back to the requested type using 'Migrate'
--   instances.
--
--   If there is no version number (that means this can also happen with
--   completely unrelated JSON messages), and there is a 'SafeJSON'
--   instance in the chain that has 'version' defined as 'noVersion',
--   it will try to parse that type.
--
--   __N.B. If the consistency of the 'SafeJSON' instance in__
--   __question is faulty, this will always fail.__
safeFromJSON :: forall a. SafeJSON a => Value -> Parser a
safeFromJSON :: Value -> Parser a
safeFromJSON Value
origVal = Proxy a -> (ProfileVersions -> Parser a) -> Parser a
forall a (m :: * -> *) b.
(SafeJSON a, MonadFail m) =>
Proxy a -> (ProfileVersions -> m b) -> m b
checkConsistency Proxy a
p ((ProfileVersions -> Parser a) -> Parser a)
-> (ProfileVersions -> Parser a) -> Parser a
forall a b. (a -> b) -> a -> b
$ \ProfileVersions
vs -> do
    let hasVNil :: Bool
hasVNil = ProfileVersions -> Bool
noVersionPresent ProfileVersions
vs
    case Kind a
origKind of
      Kind a
Base       | Maybe Int32 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int32
i -> Contained (Parser a) -> Parser a
forall a. Contained a -> a
unsafeUnpack (Contained (Parser a) -> Parser a)
-> Contained (Parser a) -> Parser a
forall a b. (a -> b) -> a -> b
$ Value -> Contained (Parser a)
forall a. SafeJSON a => Value -> Contained (Parser a)
safeFrom Value
origVal
      Extended Kind a
k | Maybe Int32 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int32
i -> Bool -> Kind a -> Parser a
Migrate (Reverse a) => Bool -> Kind a -> Parser a
extendedCase Bool
hasVNil Kind a
k
      Kind a
_ -> Bool -> Parser a
regularCase Bool
hasVNil
  where Version Maybe Int32
i = Version a
forall a. SafeJSON a => Version a
version :: Version a
        origKind :: Kind a
origKind = Kind a
forall a. SafeJSON a => Kind a
kind :: Kind a
        p :: Proxy a
p = Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a
        safejsonErr :: String -> m a
safejsonErr String
s = String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m a) -> String -> m a
forall a b. (a -> b) -> a -> b
$ String
"safejson: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
s
        regularCase :: Bool -> Parser a
regularCase Bool
hasVNil = case Value
origVal of
            Object Object
o -> do
                (Value
val, Version a
v) <- Object -> Parser (Value, Version a)
tryIt Object
o
                Version a -> Value -> Kind a -> Parser a
forall b. SafeJSON b => Version b -> Value -> Kind b -> Parser b
withVersion Version a
v Value
val Kind a
origKind
            Value
_ -> Parser a
withoutVersion Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
safejsonErr (String
"unparsable JSON value (not an object): " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Proxy a -> String
forall a. SafeJSON a => Proxy a -> String
typeName Proxy a
p)
          where withoutVersion :: Parser a
withoutVersion = Version a -> Value -> Kind a -> Parser a
forall b. SafeJSON b => Version b -> Value -> Kind b -> Parser b
withVersion Version a
forall a. Version a
noVersion Value
origVal Kind a
origKind
                tryIt :: Object -> Parser (Value, Version a)
tryIt Object
o
                  | Bool
hasVNil = Object -> Parser (Value, Version a)
forall a. Object -> Parser (Value, Version a)
firstTry Object
o Parser (Value, Version a)
-> Parser (Value, Version a) -> Parser (Value, Version a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object -> Parser (Value, Version a)
forall a a. FromJSON a => Object -> Parser (a, Version a)
secondTry Object
o Parser (Value, Version a)
-> Parser (Value, Version a) -> Parser (Value, Version a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Value, Version a) -> Parser (Value, Version a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Value
origVal, Version a
forall a. Version a
noVersion)
                  | Bool
otherwise = Object -> Parser (Value, Version a)
forall a. Object -> Parser (Value, Version a)
firstTry Object
o Parser (Value, Version a)
-> Parser (Value, Version a) -> Parser (Value, Version a)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object -> Parser (Value, Version a)
forall a a. FromJSON a => Object -> Parser (a, Version a)
secondTry Object
o

        -- This only runs if the SafeJSON being tried has 'kind' of 'extended_*'
        -- and the version is 'noVersion'.
        -- (internalConsistency checks that it should be an 'Extended Base' since it has 'noVersion')
        -- We check the newer version first, since it's better to try to find the
        -- version, if there is one, to guarantee the right parser.
        extendedCase :: Migrate (Reverse a) => Bool -> Kind a -> Parser a
        extendedCase :: Bool -> Kind a -> Parser a
extendedCase Bool
hasVNil Kind a
k = case Kind a
k of { Kind a
Base -> Parser a
go; Kind a
_ -> Bool -> Parser a
regularCase Bool
hasVNil }
          where go :: Parser a
go = case Value
origVal of
                        Object Object
o -> Object -> Parser a
tryNew Object
o Parser a -> Parser a -> Parser a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser a
tryOrig
                        Value
_ -> Parser a
tryOrig
                tryNew :: Object -> Parser a
tryNew Object
o = do
                    (Value
val, Version Any
v) <- Object -> Parser (Value, Version Any)
forall a. Object -> Parser (Value, Version a)
firstTry Object
o Parser (Value, Version Any)
-> Parser (Value, Version Any) -> Parser (Value, Version Any)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Object -> Parser (Value, Version Any)
forall a a. FromJSON a => Object -> Parser (a, Version a)
secondTry Object
o
                    let forwardKind :: Kind (MigrateFrom (Reverse a))
forwardKind = Kind a -> Kind (MigrateFrom (Reverse a))
forall a.
Migrate (Reverse a) =>
Kind a -> Kind (MigrateFrom (Reverse a))
getForwardKind Kind a
k
                        forwardVersion :: Version (MigrateFrom (Reverse a))
forwardVersion = Version Any -> Version (MigrateFrom (Reverse a))
forall a b. Version a -> Version b
castVersion Version Any
v
                        getForwardParser :: Parser (MigrateFrom (Reverse a))
getForwardParser = Version (MigrateFrom (Reverse a))
-> Value
-> Kind (MigrateFrom (Reverse a))
-> Parser (MigrateFrom (Reverse a))
forall b. SafeJSON b => Version b -> Value -> Kind b -> Parser b
withVersion Version (MigrateFrom (Reverse a))
forwardVersion Value
val Kind (MigrateFrom (Reverse a))
forwardKind
                    Reverse a -> a
forall a. Reverse a -> a
unReverse (Reverse a -> a)
-> (MigrateFrom (Reverse a) -> Reverse a)
-> MigrateFrom (Reverse a)
-> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MigrateFrom (Reverse a) -> Reverse a
forall a. Migrate a => MigrateFrom a -> a
migrate (MigrateFrom (Reverse a) -> a)
-> Parser (MigrateFrom (Reverse a)) -> Parser a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser (MigrateFrom (Reverse a))
getForwardParser
                tryOrig :: Parser a
tryOrig = Contained (Parser a) -> Parser a
forall a. Contained a -> a
unsafeUnpack (Contained (Parser a) -> Parser a)
-> Contained (Parser a) -> Parser a
forall a b. (a -> b) -> a -> b
$ Value -> Contained (Parser a)
forall a. SafeJSON a => Value -> Contained (Parser a)
safeFrom Value
origVal

        withVersion :: forall b. SafeJSON b => Version b -> Value ->  Kind b -> Parser b
        withVersion :: Version b -> Value -> Kind b -> Parser b
withVersion Version b
v Value
val Kind b
k = (String -> Parser b)
-> (Parser b -> Parser b) -> Either String (Parser b) -> Parser b
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> Parser b
forall (m :: * -> *) a. MonadFail m => String -> m a
fail Parser b -> Parser b
forall a. a -> a
id Either String (Parser b)
eResult
          where eResult :: Either String (Parser b)
eResult = Value -> Version b -> Kind b -> Either String (Parser b)
forall a.
SafeJSON a =>
Value -> Version a -> Kind a -> Either String (Parser a)
constructParserFromVersion Value
val Version b
v Kind b
k

        firstTry :: Object -> Parser (Value, Version a)
firstTry Object
o = do
            Int32
v <- Object
o Object -> Key -> Parser Int32
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
versionField
            let versionLessObj :: Object
versionLessObj = Key -> Object -> Object
forall v. Key -> KeyMap v -> KeyMap v
Map.delete Key
versionField Object
o
            (Value, Version a) -> Parser (Value, Version a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Object -> Value
Object Object
versionLessObj, Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Int32 -> Maybe Int32
forall a. a -> Maybe a
Just Int32
v)
        secondTry :: Object -> Parser (a, Version a)
secondTry Object
o = do
            Int32
v  <- Object
o Object -> Key -> Parser Int32
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
dataVersionField
            a
bd <- Object
o Object -> Key -> Parser a
forall a. FromJSON a => Object -> Key -> Parser a
.: Key
dataField
            -- This is an extra counter measure against false parsing.
            -- The simple data object should contain exactly the
            -- (~v) and (~d) fields
            Bool -> Parser () -> Parser ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Object -> Int
forall v. KeyMap v -> Int
Map.size Object
o Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/= Int
2) (Parser () -> Parser ()) -> Parser () -> Parser ()
forall a b. (a -> b) -> a -> b
$ String -> Parser ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser ()) -> String -> Parser ()
forall a b. (a -> b) -> a -> b
$ String
"malformed simple data (" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Version Any -> String
forall a. Show a => a -> String
show (Maybe Int32 -> Version Any
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version Any) -> Maybe Int32 -> Version Any
forall a b. (a -> b) -> a -> b
$ Int32 -> Maybe Int32
forall a. a -> Maybe a
Just Int32
v) String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
")"
            (a, Version a) -> Parser (a, Version a)
forall (m :: * -> *) a. Monad m => a -> m a
return (a
bd, Maybe Int32 -> Version a
forall a. Maybe Int32 -> Version a
Version (Maybe Int32 -> Version a) -> Maybe Int32 -> Version a
forall a b. (a -> b) -> a -> b
$ Int32 -> Maybe Int32
forall a. a -> Maybe a
Just Int32
v)

-- This takes the version number found (or Nothing) and tries find the type in
-- the chain that has that version number. It will attempt to go one type up
-- (try 'Migrate (Reverse a)' once) and after that down the chain.
constructParserFromVersion :: SafeJSON a => Value -> Version a -> Kind a -> Either String (Parser a)
constructParserFromVersion :: Value -> Version a -> Kind a -> Either String (Parser a)
constructParserFromVersion Value
val Version a
origVersion Kind a
origKind =
    Bool -> Version a -> Kind a -> Either String (Parser a)
forall b.
SafeJSON b =>
Bool -> Version b -> Kind b -> Either String (Parser b)
worker Bool
False Version a
origVersion Kind a
origKind
  where
    worker :: forall b. SafeJSON b => Bool -> Version b -> Kind b -> Either String (Parser b)
    worker :: Bool -> Version b -> Kind b -> Either String (Parser b)
worker Bool
fwd Version b
thisVersion Kind b
thisKind
      | Version b
forall a. SafeJSON a => Version a
version Version b -> Version b -> Bool
forall a. Eq a => a -> a -> Bool
== Version b
thisVersion = Parser b -> Either String (Parser b)
forall (m :: * -> *) a. Monad m => a -> m a
return (Parser b -> Either String (Parser b))
-> Parser b -> Either String (Parser b)
forall a b. (a -> b) -> a -> b
$ Contained (Parser b) -> Parser b
forall a. Contained a -> a
unsafeUnpack (Contained (Parser b) -> Parser b)
-> Contained (Parser b) -> Parser b
forall a b. (a -> b) -> a -> b
$ Value -> Contained (Parser b)
forall a. SafeJSON a => Value -> Contained (Parser a)
safeFrom Value
val
      | Bool
otherwise = case Kind b
thisKind of
          Kind b
Base          -> String -> Either String (Parser b)
forall a b. a -> Either a b
Left String
versionNotFound
          Extends Proxy (MigrateFrom b)
p     -> (MigrateFrom b -> b) -> Parser (MigrateFrom b) -> Parser b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap MigrateFrom b -> b
forall a. Migrate a => MigrateFrom a -> a
migrate (Parser (MigrateFrom b) -> Parser b)
-> Either String (Parser (MigrateFrom b))
-> Either String (Parser b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Bool
-> Version (MigrateFrom b)
-> Kind (MigrateFrom b)
-> Either String (Parser (MigrateFrom b))
forall b.
SafeJSON b =>
Bool -> Version b -> Kind b -> Either String (Parser b)
worker Bool
fwd (Version b -> Version (MigrateFrom b)
forall a b. Version a -> Version b
castVersion Version b
thisVersion) (Proxy (MigrateFrom b) -> Kind (MigrateFrom b)
forall a. SafeJSON a => Proxy a -> Kind a
kindFromProxy Proxy (MigrateFrom b)
p)
          Extended Kind b
k    -> do
              -- Technically, the forward and backward parsing could be
              -- infinite, as long as all 'Migrate' instances are defined.
              -- The problem is that chains can fork if, after going forward,
              -- the kind of that forward type is used to continue, since
              -- there's no guarantee that the migrations will continue backward
              -- down the previous chain.
              --
              -- TODO: Somehow restrict Migrate instances in such a way that, if defined:
              -- > MigrateFrom (Reverse b) = a
              -- >  THEN ALSO
              -- > MigrateFrom a = b
              --
              -- @
              -- v1 Base   v1' Base      v1'' Ext_Base
              --  |         |            /\
              --  |         |             |
              -- \/        \/            \/
              -- v2 Exs -> v3 Ext_Exs -> v4 Exs
              -- @
              --
              -- I've opted for the following approach:
              -- "Try forward once, if the version is wrong, go down your own chain"
              --
              -- IDEA: Maybe it could be written in such a way that the backward type
              -- (Base or Extends) in the Extended data constructor is passed along on
              -- up the chain until the top is reached, after which the run downward
              -- starts with Extends, or the run ends in case it was a Base type.
              let forwardParser :: Either String (Parser b)
                  forwardParser :: Either String (Parser b)
forwardParser = do
                      if Version b -> Version (MigrateFrom (Reverse b))
forall a b. Version a -> Version b
castVersion Version b
thisVersion Version (MigrateFrom (Reverse b))
-> Version (MigrateFrom (Reverse b)) -> Bool
forall a. Eq a => a -> a -> Bool
== Proxy (MigrateFrom (Reverse b))
-> Version (MigrateFrom (Reverse b))
forall a. SafeJSON a => Proxy a -> Version a
versionFromProxy Proxy (MigrateFrom (Reverse b))
reverseProxy
                          then Parser b -> Either String (Parser b)
forall a b. b -> Either a b
Right (Parser b -> Either String (Parser b))
-> Parser b -> Either String (Parser b)
forall a b. (a -> b) -> a -> b
$ Reverse b -> b
forall a. Reverse a -> a
unReverse (Reverse b -> b)
-> (MigrateFrom (Reverse b) -> Reverse b)
-> MigrateFrom (Reverse b)
-> b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MigrateFrom (Reverse b) -> Reverse b
forall a. Migrate a => MigrateFrom a -> a
migrate (MigrateFrom (Reverse b) -> b)
-> Parser (MigrateFrom (Reverse b)) -> Parser b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Contained (Parser (MigrateFrom (Reverse b)))
-> Parser (MigrateFrom (Reverse b))
forall a. Contained a -> a
unsafeUnpack (Value -> Contained (Parser (MigrateFrom (Reverse b)))
forall a. SafeJSON a => Value -> Contained (Parser a)
safeFrom Value
val)
                          else Either String (Parser b)
previousParser

                  previousParser :: Either String (Parser b)
                  previousParser :: Either String (Parser b)
previousParser = Bool -> Version b -> Kind b -> Either String (Parser b)
forall b.
SafeJSON b =>
Bool -> Version b -> Kind b -> Either String (Parser b)
worker Bool
True Version b
thisVersion Kind b
k
              -- If we've already looked ahead, or if it's 'noVersion', we go back.
              -- ('noVersion' means we need to find the 'Base', that's always backwards)
              if Bool
fwd Bool -> Bool -> Bool
|| Version b
thisVersion Version b -> Version b -> Bool
forall a. Eq a => a -> a -> Bool
== Version b
forall a. Version a
noVersion
                then Either String (Parser b)
previousParser
                else (String -> Either String (Parser b))
-> (Parser b -> Either String (Parser b))
-> Either String (Parser b)
-> Either String (Parser b)
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (Either String (Parser b) -> String -> Either String (Parser b)
forall a b. a -> b -> a
const Either String (Parser b)
previousParser) Parser b -> Either String (Parser b)
forall a b. b -> Either a b
Right Either String (Parser b)
forwardParser
      where versionNotFound :: String
versionNotFound = String
"Cannot find parser associated with: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Version a -> String
forall a. Show a => a -> String
show Version a
origVersion
            reverseProxy :: Proxy (MigrateFrom (Reverse b))
            reverseProxy :: Proxy (MigrateFrom (Reverse b))
reverseProxy = Proxy (MigrateFrom (Reverse b))
forall k (t :: k). Proxy t
Proxy

-- | Type name string representation of a __nullary__ type constructor.
typeName0 :: Typeable a => Proxy a -> String
typeName0 :: Proxy a -> String
typeName0 = TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String) -> (Proxy a -> TypeRep) -> Proxy a -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy a -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep

-- | Type name string representation of a __unary__ type constructor.
typeName1 :: forall t a. Typeable t => Proxy (t a) -> String
typeName1 :: Proxy (t a) -> String
typeName1 Proxy (t a)
_ = TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String) -> TypeRep -> String
forall a b. (a -> b) -> a -> b
$ Proxy t -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy t
forall k (t :: k). Proxy t
Proxy :: Proxy t)

-- | Type name string representation of a __binary__ type constructor.
typeName2 :: forall t a b. Typeable t => Proxy (t a b) -> String
typeName2 :: Proxy (t a b) -> String
typeName2 Proxy (t a b)
_ = TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String) -> TypeRep -> String
forall a b. (a -> b) -> a -> b
$ Proxy t -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy t
forall k (t :: k). Proxy t
Proxy :: Proxy t)

-- | Type name string representation of a __ternary__ type constructor.
typeName3 :: forall t a b c. Typeable t => Proxy (t a b c) -> String
typeName3 :: Proxy (t a b c) -> String
typeName3 Proxy (t a b c)
_ = TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String) -> TypeRep -> String
forall a b. (a -> b) -> a -> b
$ Proxy t -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy t
forall k (t :: k). Proxy t
Proxy :: Proxy t)

-- | Type name string representation of a __4-ary__ type constructor.
typeName4 :: forall t a b c d. Typeable t => Proxy (t a b c d) -> String
typeName4 :: Proxy (t a b c d) -> String
typeName4 Proxy (t a b c d)
_ = TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String) -> TypeRep -> String
forall a b. (a -> b) -> a -> b
$ Proxy t -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy t
forall k (t :: k). Proxy t
Proxy :: Proxy t)

-- | Type name string representation of a __5-ary__ type constructor.
typeName5 :: forall t a b c d e. Typeable t => Proxy (t a b c d e) -> String
typeName5 :: Proxy (t a b c d e) -> String
typeName5 Proxy (t a b c d e)
_ = TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> String) -> TypeRep -> String
forall a b. (a -> b) -> a -> b
$ Proxy t -> TypeRep
forall k (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy t
forall k (t :: k). Proxy t
Proxy :: Proxy t)


-- | Profile of the internal consistency of a 'SafeJSON' instance.
--
--   /N.B. 'noVersion' shows as/ @null@ /instead of a number./
data Profile a = InvalidProfile String -- ^ There is something wrong with versioning
               | Profile ProfileVersions -- ^ Profile of consistent versions
  deriving (Profile a -> Profile a -> Bool
(Profile a -> Profile a -> Bool)
-> (Profile a -> Profile a -> Bool) -> Eq (Profile a)
forall a. Profile a -> Profile a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Profile a -> Profile a -> Bool
$c/= :: forall a. Profile a -> Profile a -> Bool
== :: Profile a -> Profile a -> Bool
$c== :: forall a. Profile a -> Profile a -> Bool
Eq)

-- | Version profile of a consistent 'SafeJSON' instance.
data ProfileVersions = ProfileVersions {
    ProfileVersions -> Maybe Int32
profileCurrentVersion :: Maybe Int32, -- ^ Version of the type checked for consistency.
    ProfileVersions -> [(Maybe Int32, String)]
profileSupportedVersions :: [(Maybe Int32, String)] -- ^ All versions in the chain with their type names.
  } deriving (ProfileVersions -> ProfileVersions -> Bool
(ProfileVersions -> ProfileVersions -> Bool)
-> (ProfileVersions -> ProfileVersions -> Bool)
-> Eq ProfileVersions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ProfileVersions -> ProfileVersions -> Bool
$c/= :: ProfileVersions -> ProfileVersions -> Bool
== :: ProfileVersions -> ProfileVersions -> Bool
$c== :: ProfileVersions -> ProfileVersions -> Bool
Eq)

noVersionPresent :: ProfileVersions -> Bool
noVersionPresent :: ProfileVersions -> Bool
noVersionPresent (ProfileVersions Maybe Int32
c [(Maybe Int32, String)]
vs) =
    Maybe Int32 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int32
c Bool -> Bool -> Bool
|| Maybe String -> Bool
forall a. Maybe a -> Bool
isJust (Maybe Int32
forall a. Maybe a
Nothing Maybe Int32 -> [(Maybe Int32, String)] -> Maybe String
forall a b. Eq a => a -> [(a, b)] -> Maybe b
`List.lookup` [(Maybe Int32, String)]
vs)

showV :: Maybe Int32 -> String
showV :: Maybe Int32 -> String
showV Maybe Int32
Nothing  = String
"null"
showV (Just Int32
i) = Int32 -> String
forall a. Show a => a -> String
show Int32
i

showVs :: [(Maybe Int32, String)] -> String
showVs :: [(Maybe Int32, String)] -> String
showVs = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
List.intercalate String
", " ([String] -> String)
-> ([(Maybe Int32, String)] -> [String])
-> [(Maybe Int32, String)]
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Maybe Int32, String) -> String)
-> [(Maybe Int32, String)] -> [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe Int32, String) -> String
go
  where go :: (Maybe Int32, String) -> String
go (Maybe Int32
mi, String
s) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat [String
"(", Maybe Int32 -> String
showV Maybe Int32
mi, String
", ", String
s, String
")"]

-- | @'Version' Nothing@ shows as @null@
instance Show ProfileVersions where
  show :: ProfileVersions -> String
show (ProfileVersions Maybe Int32
cur [(Maybe Int32, String)]
sup) = [String] -> String
forall a. Monoid a => [a] -> a
mconcat
      [ String
"version ", Maybe Int32 -> String
showV Maybe Int32
cur, String
": ["
      , [(Maybe Int32, String)] -> String
showVs [(Maybe Int32, String)]
sup, String
"]"
      ]

instance Typeable a => Show (Profile a) where
  show :: Profile a -> String
show (InvalidProfile String
s) = String
"InvalidProfile: " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s
  show (Profile ProfileVersions
pv) =
      let p :: Proxy a
p = Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a
      in [String] -> String
forall a. Monoid a => [a] -> a
mconcat [ String
"Profile for \"", Proxy a -> String
forall a. Typeable a => Proxy a -> String
typeName0 Proxy a
p
                 , String
"\" (", ProfileVersions -> String
forall a. Show a => a -> String
show ProfileVersions
pv, String
")"
                 ]

-- | Easy way to get a printable failure/success report
-- of the internal consistency of a SafeJSON instance.
mkProfile :: forall a. SafeJSON a => Proxy a -> Profile a
mkProfile :: Proxy a -> Profile a
mkProfile Proxy a
p = case Proxy a -> Consistency a
forall a. SafeJSON a => Proxy a -> Consistency a
computeConsistency Proxy a
p of
    NotConsistent String
t -> String -> Profile a
forall a. String -> Profile a
InvalidProfile String
t
    Consistency a
Consistent -> ProfileVersions -> Profile a
forall a. ProfileVersions -> Profile a
Profile (ProfileVersions -> Profile a) -> ProfileVersions -> Profile a
forall a b. (a -> b) -> a -> b
$ ProfileVersions :: Maybe Int32 -> [(Maybe Int32, String)] -> ProfileVersions
ProfileVersions {
        profileCurrentVersion :: Maybe Int32
profileCurrentVersion    = Version a -> Maybe Int32
forall a. Version a -> Maybe Int32
unVersion (SafeJSON a => Version a
forall a. SafeJSON a => Version a
version @a),
        profileSupportedVersions :: [(Maybe Int32, String)]
profileSupportedVersions = Proxy a -> [(Maybe Int32, String)]
forall a. SafeJSON a => Proxy a -> [(Maybe Int32, String)]
availableVersions Proxy a
p
      }

data Consistency a = Consistent
                   | NotConsistent String

checkConsistency :: (SafeJSON a, MonadFail m) => Proxy a -> (ProfileVersions -> m b) -> m b
checkConsistency :: Proxy a -> (ProfileVersions -> m b) -> m b
checkConsistency Proxy a
p ProfileVersions -> m b
m =
    case Proxy a -> Profile a
forall a. SafeJSON a => Proxy a -> Profile a
mkProfile Proxy a
p of
      InvalidProfile String
s -> String -> m b
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
s
      Profile ProfileVersions
vs -> ProfileVersions -> m b
m ProfileVersions
vs

computeConsistency :: forall a. SafeJSON a => Proxy a -> Consistency a
computeConsistency :: Proxy a -> Consistency a
computeConsistency Proxy a
p
-- This checks the chain of versions to not clash or loop,
-- and it verifies only 'Base' or 'Extended Base' kinds can
-- have 'noVersion'
  | Kind a -> Bool
forall a. Kind a -> Bool
isObviouslyConsistent (SafeJSON a => Kind a
forall a. SafeJSON a => Kind a
kind @a) = Consistency a
forall a. Consistency a
Consistent
  | Just String
s <- Proxy a -> Maybe String
forall a. SafeJSON a => Proxy a -> Maybe String
invalidChain Proxy a
p = String -> Consistency a
forall a. String -> Consistency a
NotConsistent String
s
  | Bool
otherwise = Consistency a
forall a. Consistency a
Consistent
{-# INLINE computeConsistency #-}

isObviouslyConsistent :: Kind a -> Bool
isObviouslyConsistent :: Kind a -> Bool
isObviouslyConsistent Kind a
Base = Bool
True
isObviouslyConsistent Kind a
_    = Bool
False

availableVersions :: forall a. SafeJSON a => Proxy a -> [(Maybe Int32, String)]
availableVersions :: Proxy a -> [(Maybe Int32, String)]
availableVersions Proxy a
_ =
    Bool -> Kind a -> [(Maybe Int32, String)]
forall b. SafeJSON b => Bool -> Kind b -> [(Maybe Int32, String)]
worker Bool
False (SafeJSON a => Kind a
forall a. SafeJSON a => Kind a
kind @a)
  where
    worker :: forall b. SafeJSON b => Bool -> Kind b -> [(Maybe Int32, String)]
    worker :: Bool -> Kind b -> [(Maybe Int32, String)]
worker Bool
fwd Kind b
thisKind = case Kind b
thisKind of
        Kind b
Base       -> [(Maybe Int32, String)
tup]
        Extends Proxy (MigrateFrom b)
p' -> (Maybe Int32, String)
tup (Maybe Int32, String)
-> [(Maybe Int32, String)] -> [(Maybe Int32, String)]
forall a. a -> [a] -> [a]
: Bool -> Kind (MigrateFrom b) -> [(Maybe Int32, String)]
forall b. SafeJSON b => Bool -> Kind b -> [(Maybe Int32, String)]
worker Bool
fwd (Proxy (MigrateFrom b) -> Kind (MigrateFrom b)
forall a. SafeJSON a => Proxy a -> Kind a
kindFromProxy Proxy (MigrateFrom b)
p')
        Extended Kind b
k | Bool -> Bool
not Bool
fwd -> Bool -> Kind (MigrateFrom (Reverse b)) -> [(Maybe Int32, String)]
forall b. SafeJSON b => Bool -> Kind b -> [(Maybe Int32, String)]
worker Bool
True (Kind b -> Kind (MigrateFrom (Reverse b))
forall a.
Migrate (Reverse a) =>
Kind a -> Kind (MigrateFrom (Reverse a))
getForwardKind Kind b
k)
        Extended Kind b
k -> Bool -> Kind b -> [(Maybe Int32, String)]
forall b. SafeJSON b => Bool -> Kind b -> [(Maybe Int32, String)]
worker Bool
True Kind b
k

      where Version Maybe Int32
v = SafeJSON b => Version b
forall a. SafeJSON a => Version a
version @b
            name :: String
name = Proxy b -> String
forall a. SafeJSON a => Proxy a -> String
typeName (Proxy b
forall k (t :: k). Proxy t
Proxy @b)
            tup :: (Maybe Int32, String)
tup = (Maybe Int32
v, String
name)

-- TODO: Have this output a custom type to differentiate between bad outcomes.
-- That way the tests can be more reliable. (Did they catch what they were
-- supposed to catch?)
invalidChain :: forall a. SafeJSON a => Proxy a -> Maybe String
invalidChain :: Proxy a -> Maybe String
invalidChain Proxy a
_ =
  Set (Maybe Int32)
-> Set (Maybe Int32, String) -> Kind a -> Maybe String
forall b.
SafeJSON b =>
Set (Maybe Int32)
-> Set (Maybe Int32, String) -> Kind b -> Maybe String
worker Set (Maybe Int32)
forall a. Monoid a => a
mempty Set (Maybe Int32, String)
forall a. Monoid a => a
mempty (SafeJSON a => Kind a
forall a. SafeJSON a => Kind a
kind @a)
  where
    --                                Version set            Version set with type name     Kind      Maybe error
    worker :: forall b. SafeJSON b => S.Set (Maybe Int32) -> S.Set (Maybe Int32, String) -> Kind b -> Maybe String
    worker :: Set (Maybe Int32)
-> Set (Maybe Int32, String) -> Kind b -> Maybe String
worker Set (Maybe Int32)
vs Set (Maybe Int32, String)
vSs Kind b
k
      | Maybe Int32
i Maybe Int32 -> Set (Maybe Int32) -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.member` Set (Maybe Int32)
vs = String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Monoid a => [a] -> a
mconcat
          [ String
"Double occurence of version number '", Maybe Int32 -> String
showV Maybe Int32
i
          , String
"' (type: ", Proxy b -> String
forall a. SafeJSON a => Proxy a -> String
typeName Proxy b
p
          , String
"). Looping instances if the previous combination of type and version number are found here: "
          , [(Maybe Int32, String)] -> String
showVs ([(Maybe Int32, String)] -> String)
-> [(Maybe Int32, String)] -> String
forall a b. (a -> b) -> a -> b
$ Set (Maybe Int32, String) -> [(Maybe Int32, String)]
forall a. Set a -> [a]
S.toList Set (Maybe Int32, String)
vSs
          ]
      | Bool
otherwise = case Kind b
k of
          Kind b
Base -> Maybe String
forall a. Maybe a
Nothing
          Extends{} | Maybe Int32 -> Bool
forall a. Maybe a -> Bool
isNothing Maybe Int32
i -> String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall a. Monoid a => [a] -> a
mconcat
              [ Proxy b -> String
forall a. SafeJSON a => Proxy a -> String
typeName Proxy b
p, String
" has defined 'version = noVersion', "
              , String
" but it's 'kind' definition is not 'base' or 'extended_base'"
              ]
          Extends Proxy (MigrateFrom b)
a_proxy -> Set (Maybe Int32)
-> Set (Maybe Int32, String)
-> Kind (MigrateFrom b)
-> Maybe String
forall b.
SafeJSON b =>
Set (Maybe Int32)
-> Set (Maybe Int32, String) -> Kind b -> Maybe String
worker Set (Maybe Int32)
newVSet Set (Maybe Int32, String)
newVsSet (Proxy (MigrateFrom b) -> Kind (MigrateFrom b)
forall a. SafeJSON a => Proxy a -> Kind a
kindFromProxy Proxy (MigrateFrom b)
a_proxy)
          Extended Kind b
a_kind -> let v :: Version (MigrateFrom (Reverse b))
v@(Version Maybe Int32
i') = Kind (MigrateFrom (Reverse b)) -> Version (MigrateFrom (Reverse b))
forall a. SafeJSON a => Kind a -> Version a
versionFromKind (Kind (MigrateFrom (Reverse b))
 -> Version (MigrateFrom (Reverse b)))
-> Kind (MigrateFrom (Reverse b))
-> Version (MigrateFrom (Reverse b))
forall a b. (a -> b) -> a -> b
$ Kind b -> Kind (MigrateFrom (Reverse b))
forall a.
Migrate (Reverse a) =>
Kind a -> Kind (MigrateFrom (Reverse a))
getForwardKind Kind b
a_kind
                                 tup :: (Maybe Int32, String)
tup = (Maybe Int32
i', Proxy (MigrateFrom (Reverse b)) -> String
forall a. SafeJSON a => Proxy a -> String
typeName (Version (MigrateFrom (Reverse b))
-> Proxy (MigrateFrom (Reverse b))
forall a. Version a -> Proxy a
proxyFromVersion Version (MigrateFrom (Reverse b))
v))
                              in Set (Maybe Int32)
-> Set (Maybe Int32, String) -> Kind b -> Maybe String
forall b.
SafeJSON b =>
Set (Maybe Int32)
-> Set (Maybe Int32, String) -> Kind b -> Maybe String
worker (Maybe Int32 -> Set (Maybe Int32) -> Set (Maybe Int32)
forall a. Ord a => a -> Set a -> Set a
S.insert Maybe Int32
i' Set (Maybe Int32)
vs) ((Maybe Int32, String)
-> Set (Maybe Int32, String) -> Set (Maybe Int32, String)
forall a. Ord a => a -> Set a -> Set a
S.insert (Maybe Int32, String)
tup Set (Maybe Int32, String)
vSs) Kind b
a_kind
      where Version Maybe Int32
i = SafeJSON b => Version b
forall a. SafeJSON a => Version a
version @b
            p :: Proxy b
p = Proxy b
forall k (t :: k). Proxy t
Proxy @b
            newVSet :: Set (Maybe Int32)
newVSet = Maybe Int32 -> Set (Maybe Int32) -> Set (Maybe Int32)
forall a. Ord a => a -> Set a -> Set a
S.insert Maybe Int32
i Set (Maybe Int32)
vs
            newVsSet :: Set (Maybe Int32, String)
newVsSet = (Maybe Int32, String)
-> Set (Maybe Int32, String) -> Set (Maybe Int32, String)
forall a. Ord a => a -> Set a -> Set a
S.insert (Maybe Int32
i, Proxy b -> String
forall a. SafeJSON a => Proxy a -> String
typeName Proxy b
p) Set (Maybe Int32, String)
vSs


----------------------------------------------------------
-- Conversion functions
----------------------------------------------------------

proxyFromVersion :: Version a -> Proxy a
proxyFromVersion :: Version a -> Proxy a
proxyFromVersion Version a
_ = Proxy a
forall k (t :: k). Proxy t
Proxy

kindFromProxy :: SafeJSON a => Proxy a -> Kind a
kindFromProxy :: Proxy a -> Kind a
kindFromProxy Proxy a
_ = Kind a
forall a. SafeJSON a => Kind a
kind

versionFromProxy :: SafeJSON a => Proxy a -> Version a
versionFromProxy :: Proxy a -> Version a
versionFromProxy Proxy a
_ = Version a
forall a. SafeJSON a => Version a
version

versionFromKind :: SafeJSON a => Kind a -> Version a
versionFromKind :: Kind a -> Version a
versionFromKind Kind a
_ = Version a
forall a. SafeJSON a => Version a
version

getForwardKind :: Migrate (Reverse a) => Kind a -> Kind (MigrateFrom (Reverse a))
getForwardKind :: Kind a -> Kind (MigrateFrom (Reverse a))
getForwardKind Kind a
_ = Kind (MigrateFrom (Reverse a))
forall a. SafeJSON a => Kind a
kind


-- ---------------------- --
--   Defining safeFrom    --
-- ---------------------- --

withContained :: (a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained :: (a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained a -> b -> c -> m d
f a
name b
prs = m d -> Contained (m d)
forall a. a -> Contained a
contain (m d -> Contained (m d)) -> (c -> m d) -> c -> Contained (m d)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> b -> c -> m d
f a
name b
prs


-- | Similar to 'Data.Aeson.withObject', but 'contain'ed to be used
-- in 'safeFrom' definitions
--
-- @since 1.0.0
containWithObject :: String -> (Object -> Parser a) -> Value -> Contained (Parser a)
containWithObject :: String -> (Object -> Parser a) -> Value -> Contained (Parser a)
containWithObject = (String -> (Object -> Parser a) -> Value -> Parser a)
-> String -> (Object -> Parser a) -> Value -> Contained (Parser a)
forall a b c (m :: * -> *) d.
(a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained String -> (Object -> Parser a) -> Value -> Parser a
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject

-- | Similar to 'Data.Aeson.withArray', but 'contain'ed to be used
-- in 'safeFrom' definitions
--
-- @since 1.0.0
containWithArray :: String -> (Array -> Parser a) -> Value -> Contained (Parser a)
containWithArray :: String -> (Array -> Parser a) -> Value -> Contained (Parser a)
containWithArray = (String -> (Array -> Parser a) -> Value -> Parser a)
-> String -> (Array -> Parser a) -> Value -> Contained (Parser a)
forall a b c (m :: * -> *) d.
(a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained String -> (Array -> Parser a) -> Value -> Parser a
forall a. String -> (Array -> Parser a) -> Value -> Parser a
withArray

-- | Similar to 'Data.Aeson.withText', but 'contain'ed to be used
-- in 'safeFrom' definitions
--
-- @since 1.0.0
containWithText :: String -> (Text -> Parser a) -> Value -> Contained (Parser a)
containWithText :: String -> (Text -> Parser a) -> Value -> Contained (Parser a)
containWithText = (String -> (Text -> Parser a) -> Value -> Parser a)
-> String -> (Text -> Parser a) -> Value -> Contained (Parser a)
forall a b c (m :: * -> *) d.
(a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained String -> (Text -> Parser a) -> Value -> Parser a
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText

-- | Similar to 'Data.Aeson.withScientific', but 'contain'ed to be used
-- in 'safeFrom' definitions
--
-- @since 1.0.0
containWithScientific :: String -> (Scientific -> Parser a) -> Value -> Contained (Parser a)
containWithScientific :: String -> (Scientific -> Parser a) -> Value -> Contained (Parser a)
containWithScientific = (String -> (Scientific -> Parser a) -> Value -> Parser a)
-> String
-> (Scientific -> Parser a)
-> Value
-> Contained (Parser a)
forall a b c (m :: * -> *) d.
(a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained String -> (Scientific -> Parser a) -> Value -> Parser a
forall a. String -> (Scientific -> Parser a) -> Value -> Parser a
withScientific

-- | Similar to 'Data.Aeson.withBool', but 'contain'ed to be used
-- in 'safeFrom' definitions
--
-- @since 1.0.0
containWithBool :: String -> (Bool -> Parser a) -> Value -> Contained (Parser a)
containWithBool :: String -> (Bool -> Parser a) -> Value -> Contained (Parser a)
containWithBool = (String -> (Bool -> Parser a) -> Value -> Parser a)
-> String -> (Bool -> Parser a) -> Value -> Contained (Parser a)
forall a b c (m :: * -> *) d.
(a -> b -> c -> m d) -> a -> b -> c -> Contained (m d)
withContained String -> (Bool -> Parser a) -> Value -> Parser a
forall a. String -> (Bool -> Parser a) -> Value -> Parser a
withBool

-- | Similar to 'Data.Aeson..:', but uses `safeFromJSON` instead of parseJSON
-- to parse the value in the given field.
--
-- @since 1.0.0
#if MIN_VERSION_aeson(2,0,0)
(.:$) :: SafeJSON a => Object -> Key -> Parser a
#else
(.:$) :: SafeJSON a => Object -> Text -> Parser a
#endif
.:$ :: Object -> Key -> Parser a
(.:$) = (Value -> Parser a) -> Object -> Key -> Parser a
forall a. (Value -> Parser a) -> Object -> Key -> Parser a
explicitParseField Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON

-- | Similar to 'Data.Aeson..:?', but uses `safeFromJSON` instead of parseJSON
-- to maybe parse the value in the given field.
--
-- @since 1.0.0
#if MIN_VERSION_aeson(2,0,0)
(.:$?) :: SafeJSON a => Object -> Key -> Parser (Maybe a)
#else
(.:$?) :: SafeJSON a => Object -> Text -> Parser (Maybe a)
#endif
.:$? :: Object -> Key -> Parser (Maybe a)
(.:$?) = (Value -> Parser a) -> Object -> Key -> Parser (Maybe a)
forall a. (Value -> Parser a) -> Object -> Key -> Parser (Maybe a)
explicitParseFieldMaybe Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON

-- | Similar to 'Data.Aeson..:!', but uses `safeFromJSON` instead of parseJSON
-- to maybe parse the value in the given field.
--
-- @since 1.0.0
#if MIN_VERSION_aeson(2,0,0)
(.:$!) :: SafeJSON a => Object -> Key -> Parser (Maybe a)
#else
(.:$!) :: SafeJSON a => Object -> Text -> Parser (Maybe a)
#endif
.:$! :: Object -> Key -> Parser (Maybe a)
(.:$!) = (Value -> Parser a) -> Object -> Key -> Parser (Maybe a)
forall a. (Value -> Parser a) -> Object -> Key -> Parser (Maybe a)
explicitParseFieldMaybe' Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON


-- -------------------- --
--   Defining safeTo    --
-- -------------------- --


-- | Similarly to 'Data.Aeson..=', but uses 'safeToJSON' instead of toJSON
-- to convert the value in that key-value pair.
--
-- @since 1.0.0
#if MIN_VERSION_aeson(2,0,0)
(.=$) :: (SafeJSON a, KeyValue kv) => Key -> a -> kv
#else
(.=$) :: (SafeJSON a, KeyValue kv) => Text -> a -> kv
#endif
Key
name .=$ :: Key -> a -> kv
.=$ a
val = Key
name Key -> Value -> kv
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
.= a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
val


-- ---------------------- --
--   SafeJSON Instances   --
-- ---------------------- --

#define BASIC_NULLARY(T) \
instance SafeJSON T where { version = noVersion }

BASIC_NULLARY(Void)
BASIC_NULLARY(Bool)
BASIC_NULLARY(Ordering)
BASIC_NULLARY(())
BASIC_NULLARY(Char)
BASIC_NULLARY(Float)
BASIC_NULLARY(Double)
BASIC_NULLARY(Int)
BASIC_NULLARY(Natural)
BASIC_NULLARY(Integer)
BASIC_NULLARY(Int8)
BASIC_NULLARY(Int16)
BASIC_NULLARY(Int32)
BASIC_NULLARY(Int64)
BASIC_NULLARY(Word)
BASIC_NULLARY(Word8)
BASIC_NULLARY(Word16)
BASIC_NULLARY(Word32)
BASIC_NULLARY(Word64)
BASIC_NULLARY(T.Text)
BASIC_NULLARY(LT.Text)
#if MIN_VERSION_aeson(2,0,0)
BASIC_NULLARY(K.Key)
#endif
BASIC_NULLARY(DV.Version)
BASIC_NULLARY(Scientific)
BASIC_NULLARY(IntSet)
BASIC_NULLARY(UUID)
BASIC_NULLARY(Value)

instance (FromJSON a, ToJSON a, Integral a) => SafeJSON (Ratio a) where
  typeName :: Proxy (Ratio a) -> String
typeName = Proxy (Ratio a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Ratio a)
version = Version (Ratio a)
forall a. Version a
noVersion

instance HasResolution a => SafeJSON (Fixed a) where
  typeName :: Proxy (Fixed a) -> String
typeName = Proxy (Fixed a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Fixed a)
version = Version (Fixed a)
forall a. Version a
noVersion

instance SafeJSON (Proxy a) where
  typeName :: Proxy (Proxy a) -> String
typeName = Proxy (Proxy a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Proxy a)
version = Version (Proxy a)
forall a. Version a
noVersion

instance {-# OVERLAPPING #-} SafeJSON String where
  typeName :: Proxy String -> String
typeName Proxy String
_ = String
"String"
  version :: Version String
version = Version String
forall a. Version a
noVersion


-- --------------------------- --
--   SafeJSON Time Instances   --
-- --------------------------- --

BASIC_NULLARY(CTime)
BASIC_NULLARY(ZonedTime)
BASIC_NULLARY(LocalTime)
BASIC_NULLARY(TimeOfDay)
BASIC_NULLARY(UTCTime)
BASIC_NULLARY(NominalDiffTime)
BASIC_NULLARY(DiffTime)
BASIC_NULLARY(Day)
BASIC_NULLARY(DotNetTime)

-- ------------------------------------ --
--   More involved SafeJSON instances   --
-- ------------------------------------ --

instance SafeJSON a => SafeJSON (Const a b) where
  safeFrom :: Value -> Contained (Parser (Const a b))
safeFrom Value
val = Parser (Const a b) -> Contained (Parser (Const a b))
forall a. a -> Contained a
contain (Parser (Const a b) -> Contained (Parser (Const a b)))
-> Parser (Const a b) -> Contained (Parser (Const a b))
forall a b. (a -> b) -> a -> b
$ a -> Const a b
forall k a (b :: k). a -> Const a b
Const (a -> Const a b) -> Parser a -> Parser (Const a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
  safeTo :: Const a b -> Contained Value
safeTo (Const a
a) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a
  typeName :: Proxy (Const a b) -> String
typeName = Proxy (Const a b) -> String
forall (t :: * -> * -> *) a b.
Typeable t =>
Proxy (t a b) -> String
typeName2
  version :: Version (Const a b)
version = Version (Const a b)
forall a. Version a
noVersion

instance SafeJSON a => SafeJSON (Maybe a) where
  safeFrom :: Value -> Contained (Parser (Maybe a))
safeFrom Value
val = Parser (Maybe a) -> Contained (Parser (Maybe a))
forall a. a -> Contained a
contain (Parser (Maybe a) -> Contained (Parser (Maybe a)))
-> Parser (Maybe a) -> Contained (Parser (Maybe a))
forall a b. (a -> b) -> a -> b
$
      Value -> Parser (Maybe Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val Parser (Maybe Value)
-> (Maybe Value -> Parser (Maybe a)) -> Parser (Maybe a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Parser a) -> Maybe Value -> Parser (Maybe a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON
  -- Nothing means do whatever Aeson thinks Nothing should be
  safeTo :: Maybe a -> Contained Value
safeTo Maybe a
Nothing = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ Maybe Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Maybe Value
forall a. Maybe a
Nothing :: Maybe Value)
  -- If there's something, keep it safe
  safeTo (Just a
a) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a
  typeName :: Proxy (Maybe a) -> String
typeName = Proxy (Maybe a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Maybe a)
version = Version (Maybe a)
forall a. Version a
noVersion

instance (SafeJSON a, SafeJSON b) => SafeJSON (Either a b) where
  safeFrom :: Value -> Contained (Parser (Either a b))
safeFrom Value
val = Parser (Either a b) -> Contained (Parser (Either a b))
forall a. a -> Contained a
contain (Parser (Either a b) -> Contained (Parser (Either a b)))
-> Parser (Either a b) -> Contained (Parser (Either a b))
forall a b. (a -> b) -> a -> b
$ do
      Either Value Value
eVal <- Value -> Parser (Either Value Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val
      case Either Value Value
eVal of
        Left Value
a  -> a -> Either a b
forall a b. a -> Either a b
Left  (a -> Either a b) -> Parser a -> Parser (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
a
        Right Value
b -> b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> Parser b -> Parser (Either a b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser b
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
b
  safeTo :: Either a b -> Contained Value
safeTo (Left a
a)  = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ Either Value Void -> Value
forall a. ToJSON a => a -> Value
toJSON (Value -> Either Value Void
forall a b. a -> Either a b
Left  (Value -> Either Value Void) -> Value -> Either Value Void
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a :: Either Value Void)
  safeTo (Right b
b) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ Either Void Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Value -> Either Void Value
forall a b. b -> Either a b
Right (Value -> Either Void Value) -> Value -> Either Void Value
forall a b. (a -> b) -> a -> b
$ b -> Value
forall a. SafeJSON a => a -> Value
safeToJSON b
b :: Either Void Value)
  typeName :: Proxy (Either a b) -> String
typeName = Proxy (Either a b) -> String
forall (t :: * -> * -> *) a b.
Typeable t =>
Proxy (t a b) -> String
typeName2
  version :: Version (Either a b)
version = Version (Either a b)
forall a. Version a
noVersion

#define BASIC_UNARY(T)                             \
instance SafeJSON a => SafeJSON (T a) where {      \
  safeFrom val = contain $ T <$> safeFromJSON val; \
  safeTo (T a) = contain $ safeToJSON a;           \
  typeName = typeName1;                            \
  version = noVersion }

BASIC_UNARY(Identity)
BASIC_UNARY(First)
BASIC_UNARY(Last)
BASIC_UNARY(Min)
BASIC_UNARY(Max)
BASIC_UNARY(Dual)

fromGenericVector :: (SafeJSON a, VG.Vector v a) => Value -> Contained (Parser (v a))
fromGenericVector :: Value -> Contained (Parser (v a))
fromGenericVector Value
val = Parser (v a) -> Contained (Parser (v a))
forall a. a -> Contained a
contain (Parser (v a) -> Contained (Parser (v a)))
-> Parser (v a) -> Contained (Parser (v a))
forall a b. (a -> b) -> a -> b
$ do
      Array
v <- Value -> Parser Array
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val
      Vector a -> v a
forall (v :: * -> *) a (w :: * -> *).
(Vector v a, Vector w a) =>
v a -> w a
VG.convert (Vector a -> v a) -> Parser (Vector a) -> Parser (v a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Value -> Parser a) -> Array -> Parser (Vector a)
forall (m :: * -> *) (v :: * -> *) a b.
(Monad m, Vector v a, Vector v b) =>
(a -> m b) -> v a -> m (v b)
VG.mapM Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON (Array
v :: V.Vector Value)

toGenericVector :: (SafeJSON a, VG.Vector v a) => v a -> Contained Value
toGenericVector :: v a -> Contained Value
toGenericVector = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (v a -> Value) -> v a -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Value] -> Value
forall a. ToJSON a => a -> Value
toJSON ([Value] -> Value) -> (v a -> [Value]) -> v a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Value) -> [a] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON ([a] -> [Value]) -> (v a -> [a]) -> v a -> [Value]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. v a -> [a]
forall (v :: * -> *) a. Vector v a => v a -> [a]
VG.toList

instance SafeJSON a => SafeJSON (V.Vector a) where
  safeFrom :: Value -> Contained (Parser (Vector a))
safeFrom = Value -> Contained (Parser (Vector a))
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
Value -> Contained (Parser (v a))
fromGenericVector
  safeTo :: Vector a -> Contained Value
safeTo = Vector a -> Contained Value
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
v a -> Contained Value
toGenericVector
  typeName :: Proxy (Vector a) -> String
typeName = Proxy (Vector a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Vector a)
version = Version (Vector a)
forall a. Version a
noVersion

instance (SafeJSON a, VP.Prim a) => SafeJSON (VP.Vector a) where
  safeFrom :: Value -> Contained (Parser (Vector a))
safeFrom = Value -> Contained (Parser (Vector a))
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
Value -> Contained (Parser (v a))
fromGenericVector
  safeTo :: Vector a -> Contained Value
safeTo = Vector a -> Contained Value
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
v a -> Contained Value
toGenericVector
  typeName :: Proxy (Vector a) -> String
typeName = Proxy (Vector a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Vector a)
version = Version (Vector a)
forall a. Version a
noVersion

instance (SafeJSON a, VS.Storable a) => SafeJSON (VS.Vector a) where
  safeFrom :: Value -> Contained (Parser (Vector a))
safeFrom = Value -> Contained (Parser (Vector a))
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
Value -> Contained (Parser (v a))
fromGenericVector
  safeTo :: Vector a -> Contained Value
safeTo = Vector a -> Contained Value
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
v a -> Contained Value
toGenericVector
  typeName :: Proxy (Vector a) -> String
typeName = Proxy (Vector a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Vector a)
version = Version (Vector a)
forall a. Version a
noVersion

instance (SafeJSON a, VG.Vector VU.Vector a) => SafeJSON (VU.Vector a) where
  safeFrom :: Value -> Contained (Parser (Vector a))
safeFrom = Value -> Contained (Parser (Vector a))
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
Value -> Contained (Parser (v a))
fromGenericVector
  safeTo :: Vector a -> Contained Value
safeTo = Vector a -> Contained Value
forall a (v :: * -> *).
(SafeJSON a, Vector v a) =>
v a -> Contained Value
toGenericVector
  typeName :: Proxy (Vector a) -> String
typeName = Proxy (Vector a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Vector a)
version = Version (Vector a)
forall a. Version a
noVersion

-- | Lists and any other \"container\" are seen as only that:
--   a container for 'SafeJSON' values.
--
--   \"Containers\" are implemented in such a way that when parsing
--   a collection of all migratable versions, the result will be
--   a list of that type where each element has been migrated as
--   appropriate.
instance  {-# OVERLAPPABLE #-} SafeJSON a => SafeJSON [a] where
  safeFrom :: Value -> Contained (Parser [a])
safeFrom Value
val = Parser [a] -> Contained (Parser [a])
forall a. a -> Contained a
contain (Parser [a] -> Contained (Parser [a]))
-> Parser [a] -> Contained (Parser [a])
forall a b. (a -> b) -> a -> b
$
      Value -> Parser [Value]
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val Parser [Value] -> ([Value] -> Parser [a]) -> Parser [a]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Parser a) -> [Value] -> Parser [a]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON
  safeTo :: [a] -> Contained Value
safeTo [a]
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> ([Value] -> Value) -> [Value] -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Value] -> Value
forall a. ToJSON a => a -> Value
toJSON ([Value] -> Contained Value) -> [Value] -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> [a] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a]
as
  typeName :: Proxy [a] -> String
typeName = Proxy [a] -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version [a]
version = Version [a]
forall a. Version a
noVersion

#define BASIC_UNARY_FUNCTOR(T)                      \
instance SafeJSON a => SafeJSON (T a) where {       \
  safeFrom val = contain $                          \
      parseJSON val >>= traverse safeFromJSON;      \
  safeTo as = contain . toJSON $ safeToJSON <$> as; \
  typeName = typeName1;                             \
  version = noVersion }

BASIC_UNARY_FUNCTOR(NonEmpty)
BASIC_UNARY_FUNCTOR(Seq)
BASIC_UNARY_FUNCTOR(Tree)

instance SafeJSON a => SafeJSON (IntMap a) where
  safeFrom :: Value -> Contained (Parser (IntMap a))
safeFrom Value
val = Parser (IntMap a) -> Contained (Parser (IntMap a))
forall a. a -> Contained a
contain (Parser (IntMap a) -> Contained (Parser (IntMap a)))
-> Parser (IntMap a) -> Contained (Parser (IntMap a))
forall a b. (a -> b) -> a -> b
$
      [(Int, a)] -> IntMap a
forall a. [(Int, a)] -> IntMap a
IM.fromList ([(Int, a)] -> IntMap a) -> Parser [(Int, a)] -> Parser (IntMap a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser [(Int, a)]
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
  safeTo :: IntMap a -> Contained Value
safeTo IntMap a
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (IntMap Value -> Value) -> IntMap Value -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IntMap Value -> Value
forall a. ToJSON a => a -> Value
toJSON (IntMap Value -> Contained Value)
-> IntMap Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> IntMap a -> IntMap Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IntMap a
as
  typeName :: Proxy (IntMap a) -> String
typeName = Proxy (IntMap a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (IntMap a)
version = Version (IntMap a)
forall a. Version a
noVersion

instance (SafeJSON a) => SafeJSON (DList a) where
  safeFrom :: Value -> Contained (Parser (DList a))
safeFrom Value
val = Parser (DList a) -> Contained (Parser (DList a))
forall a. a -> Contained a
contain (Parser (DList a) -> Contained (Parser (DList a)))
-> Parser (DList a) -> Contained (Parser (DList a))
forall a b. (a -> b) -> a -> b
$
      [a] -> DList a
forall a. [a] -> DList a
DList.fromList ([a] -> DList a) -> Parser [a] -> Parser (DList a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser [a]
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
  safeTo :: DList a -> Contained Value
safeTo DList a
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (DList Value -> Value) -> DList Value -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DList Value -> Value
forall a. ToJSON a => a -> Value
toJSON (DList Value -> Contained Value) -> DList Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> DList a -> DList Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DList a
as
  typeName :: Proxy (DList a) -> String
typeName = Proxy (DList a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (DList a)
version = Version (DList a)
forall a. Version a
noVersion

instance (SafeJSON a, Ord a) => SafeJSON (S.Set a) where
  safeFrom :: Value -> Contained (Parser (Set a))
safeFrom Value
val = Parser (Set a) -> Contained (Parser (Set a))
forall a. a -> Contained a
contain (Parser (Set a) -> Contained (Parser (Set a)))
-> Parser (Set a) -> Contained (Parser (Set a))
forall a b. (a -> b) -> a -> b
$
      [a] -> Set a
forall a. Ord a => [a] -> Set a
S.fromList ([a] -> Set a) -> Parser [a] -> Parser (Set a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser [a]
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
  safeTo :: Set a -> Contained Value
safeTo Set a
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> ([Value] -> Value) -> [Value] -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Value] -> Value
forall a. ToJSON a => a -> Value
toJSON ([Value] -> Contained Value) -> [Value] -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> [a] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Set a -> [a]
forall a. Set a -> [a]
S.toList Set a
as
  typeName :: Proxy (Set a) -> String
typeName = Proxy (Set a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (Set a)
version = Version (Set a)
forall a. Version a
noVersion

instance (Ord k, FromJSONKey k, ToJSONKey k, SafeJSON a) => SafeJSON (Map k a) where
  safeFrom :: Value -> Contained (Parser (Map k a))
safeFrom Value
val = Parser (Map k a) -> Contained (Parser (Map k a))
forall a. a -> Contained a
contain (Parser (Map k a) -> Contained (Parser (Map k a)))
-> Parser (Map k a) -> Contained (Parser (Map k a))
forall a b. (a -> b) -> a -> b
$
      Value -> Parser (Map k Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val Parser (Map k Value)
-> (Map k Value -> Parser (Map k a)) -> Parser (Map k a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Parser a) -> Map k Value -> Parser (Map k a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON
  safeTo :: Map k a -> Contained Value
safeTo Map k a
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (Map k Value -> Value) -> Map k Value -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map k Value -> Value
forall a. ToJSON a => a -> Value
toJSON (Map k Value -> Contained Value) -> Map k Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> Map k a -> Map k Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Map k a
as
  typeName :: Proxy (Map k a) -> String
typeName = Proxy (Map k a) -> String
forall (t :: * -> * -> *) a b.
Typeable t =>
Proxy (t a b) -> String
typeName2
  version :: Version (Map k a)
version = Version (Map k a)
forall a. Version a
noVersion

instance (SafeJSON a, Eq a, Hashable a) => SafeJSON (HS.HashSet a) where
  safeFrom :: Value -> Contained (Parser (HashSet a))
safeFrom Value
val = Parser (HashSet a) -> Contained (Parser (HashSet a))
forall a. a -> Contained a
contain (Parser (HashSet a) -> Contained (Parser (HashSet a)))
-> Parser (HashSet a) -> Contained (Parser (HashSet a))
forall a b. (a -> b) -> a -> b
$
      [a] -> HashSet a
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HS.fromList ([a] -> HashSet a) -> Parser [a] -> Parser (HashSet a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser [a]
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
  safeTo :: HashSet a -> Contained Value
safeTo HashSet a
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> ([Value] -> Value) -> [Value] -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Value] -> Value
forall a. ToJSON a => a -> Value
toJSON ([Value] -> Contained Value) -> [Value] -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> [a] -> [Value]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashSet a -> [a]
forall a. HashSet a -> [a]
HS.toList HashSet a
as
  typeName :: Proxy (HashSet a) -> String
typeName = Proxy (HashSet a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (HashSet a)
version = Version (HashSet a)
forall a. Version a
noVersion

instance (Hashable a, FromJSONKey a, ToJSONKey a, Eq a, SafeJSON b) => SafeJSON (HashMap a b) where
  safeFrom :: Value -> Contained (Parser (HashMap a b))
safeFrom Value
val = Parser (HashMap a b) -> Contained (Parser (HashMap a b))
forall a. a -> Contained a
contain (Parser (HashMap a b) -> Contained (Parser (HashMap a b)))
-> Parser (HashMap a b) -> Contained (Parser (HashMap a b))
forall a b. (a -> b) -> a -> b
$
      Value -> Parser (HashMap a Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val Parser (HashMap a Value)
-> (HashMap a Value -> Parser (HashMap a b))
-> Parser (HashMap a b)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Value -> Parser b) -> HashMap a Value -> Parser (HashMap a b)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser b
forall a. SafeJSON a => Value -> Parser a
safeFromJSON
  safeTo :: HashMap a b -> Contained Value
safeTo HashMap a b
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (HashMap a Value -> Value) -> HashMap a Value -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashMap a Value -> Value
forall a. ToJSON a => a -> Value
toJSON (HashMap a Value -> Contained Value)
-> HashMap a Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ b -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (b -> Value) -> HashMap a b -> HashMap a Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashMap a b
as
  typeName :: Proxy (HashMap a b) -> String
typeName = Proxy (HashMap a b) -> String
forall (t :: * -> * -> *) a b.
Typeable t =>
Proxy (t a b) -> String
typeName2
  version :: Version (HashMap a b)
version = Version (HashMap a b)
forall a. Version a
noVersion

#if MIN_VERSION_aeson(2,0,0)
-- | @since 1.1.2.0
instance SafeJSON a => SafeJSON (Map.KeyMap a) where
  safeFrom :: Value -> Contained (Parser (KeyMap a))
safeFrom Value
val = Parser (KeyMap a) -> Contained (Parser (KeyMap a))
forall a. a -> Contained a
contain (Parser (KeyMap a) -> Contained (Parser (KeyMap a)))
-> Parser (KeyMap a) -> Contained (Parser (KeyMap a))
forall a b. (a -> b) -> a -> b
$
#if !MIN_VERSION_aeson(2,0,1)
      fmap Map.fromMap $
#endif
          Value -> Parser Object
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val Parser Object -> (Object -> Parser (KeyMap a)) -> Parser (KeyMap a)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
              (Value -> Parser a) -> Object -> Parser (KeyMap a)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON
  safeTo :: KeyMap a -> Contained Value
safeTo KeyMap a
as = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (Object -> Value) -> Object -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Object -> Value
forall a. ToJSON a => a -> Value
toJSON (Object -> Contained Value) -> Object -> Contained Value
forall a b. (a -> b) -> a -> b
$ a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (a -> Value) -> KeyMap a -> Object
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> KeyMap a
as
  typeName :: Proxy (KeyMap a) -> String
typeName = Proxy (KeyMap a) -> String
forall (t :: * -> *) a. Typeable t => Proxy (t a) -> String
typeName1
  version :: Version (KeyMap a)
version = Version (KeyMap a)
forall a. Version a
noVersion
#endif

instance (SafeJSON a, SafeJSON b) => SafeJSON (a, b) where
  safeFrom :: Value -> Contained (Parser (a, b))
safeFrom Value
x = Parser (a, b) -> Contained (Parser (a, b))
forall a. a -> Contained a
contain (Parser (a, b) -> Contained (Parser (a, b)))
-> Parser (a, b) -> Contained (Parser (a, b))
forall a b. (a -> b) -> a -> b
$ do
      (Value
a',Value
b') <- Value -> Parser (Value, Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
x
      a
a <- Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
a'
      b
b <- Value -> Parser b
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
b'
      (a, b) -> Parser (a, b)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a,b
b)
  safeTo :: (a, b) -> Contained Value
safeTo (a
a,b
b) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ (Value, Value) -> Value
forall a. ToJSON a => a -> Value
toJSON (a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a, b -> Value
forall a. SafeJSON a => a -> Value
safeToJSON b
b)
  typeName :: Proxy (a, b) -> String
typeName = Proxy (a, b) -> String
forall (t :: * -> * -> *) a b.
Typeable t =>
Proxy (t a b) -> String
typeName2
  version :: Version (a, b)
version = Version (a, b)
forall a. Version a
noVersion

instance (SafeJSON a, SafeJSON b, SafeJSON c) => SafeJSON (a, b, c) where
  safeFrom :: Value -> Contained (Parser (a, b, c))
safeFrom Value
x = Parser (a, b, c) -> Contained (Parser (a, b, c))
forall a. a -> Contained a
contain (Parser (a, b, c) -> Contained (Parser (a, b, c)))
-> Parser (a, b, c) -> Contained (Parser (a, b, c))
forall a b. (a -> b) -> a -> b
$ do
      (Value
a',Value
b',Value
c') <- Value -> Parser (Value, Value, Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
x
      a
a <- Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
a'
      b
b <- Value -> Parser b
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
b'
      c
c <- Value -> Parser c
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
c'
      (a, b, c) -> Parser (a, b, c)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a,b
b,c
c)
  safeTo :: (a, b, c) -> Contained Value
safeTo (a
a,b
b,c
c) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ (Value, Value, Value) -> Value
forall a. ToJSON a => a -> Value
toJSON (a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a, b -> Value
forall a. SafeJSON a => a -> Value
safeToJSON b
b, c -> Value
forall a. SafeJSON a => a -> Value
safeToJSON c
c)
  typeName :: Proxy (a, b, c) -> String
typeName = Proxy (a, b, c) -> String
forall (t :: * -> * -> * -> *) a b c.
Typeable t =>
Proxy (t a b c) -> String
typeName3
  version :: Version (a, b, c)
version = Version (a, b, c)
forall a. Version a
noVersion

instance (SafeJSON a, SafeJSON b, SafeJSON c, SafeJSON d) => SafeJSON (a, b, c, d) where
  safeFrom :: Value -> Contained (Parser (a, b, c, d))
safeFrom Value
x = Parser (a, b, c, d) -> Contained (Parser (a, b, c, d))
forall a. a -> Contained a
contain (Parser (a, b, c, d) -> Contained (Parser (a, b, c, d)))
-> Parser (a, b, c, d) -> Contained (Parser (a, b, c, d))
forall a b. (a -> b) -> a -> b
$ do
      (Value
a',Value
b',Value
c',Value
d') <- Value -> Parser (Value, Value, Value, Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
x
      a
a <- Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
a'
      b
b <- Value -> Parser b
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
b'
      c
c <- Value -> Parser c
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
c'
      d
d <- Value -> Parser d
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
d'
      (a, b, c, d) -> Parser (a, b, c, d)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a,b
b,c
c,d
d)
  safeTo :: (a, b, c, d) -> Contained Value
safeTo (a
a,b
b,c
c,d
d) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ (Value, Value, Value, Value) -> Value
forall a. ToJSON a => a -> Value
toJSON (a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a, b -> Value
forall a. SafeJSON a => a -> Value
safeToJSON b
b, c -> Value
forall a. SafeJSON a => a -> Value
safeToJSON c
c, d -> Value
forall a. SafeJSON a => a -> Value
safeToJSON d
d)
  typeName :: Proxy (a, b, c, d) -> String
typeName = Proxy (a, b, c, d) -> String
forall (t :: * -> * -> * -> * -> *) a b c d.
Typeable t =>
Proxy (t a b c d) -> String
typeName4
  version :: Version (a, b, c, d)
version = Version (a, b, c, d)
forall a. Version a
noVersion

instance (SafeJSON a, SafeJSON b, SafeJSON c, SafeJSON d, SafeJSON e) => SafeJSON (a, b, c, d, e) where
  safeFrom :: Value -> Contained (Parser (a, b, c, d, e))
safeFrom Value
x = Parser (a, b, c, d, e) -> Contained (Parser (a, b, c, d, e))
forall a. a -> Contained a
contain (Parser (a, b, c, d, e) -> Contained (Parser (a, b, c, d, e)))
-> Parser (a, b, c, d, e) -> Contained (Parser (a, b, c, d, e))
forall a b. (a -> b) -> a -> b
$ do
      (Value
a',Value
b',Value
c',Value
d',Value
e') <- Value -> Parser (Value, Value, Value, Value, Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
x
      a
a <- Value -> Parser a
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
a'
      b
b <- Value -> Parser b
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
b'
      c
c <- Value -> Parser c
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
c'
      d
d <- Value -> Parser d
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
d'
      e
e <- Value -> Parser e
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
e'
      (a, b, c, d, e) -> Parser (a, b, c, d, e)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a
a,b
b,c
c,d
d,e
e)
  safeTo :: (a, b, c, d, e) -> Contained Value
safeTo (a
a,b
b,c
c,d
d,e
e) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ (Value, Value, Value, Value, Value) -> Value
forall a. ToJSON a => a -> Value
toJSON (a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON a
a, b -> Value
forall a. SafeJSON a => a -> Value
safeToJSON b
b, c -> Value
forall a. SafeJSON a => a -> Value
safeToJSON c
c, d -> Value
forall a. SafeJSON a => a -> Value
safeToJSON d
d, e -> Value
forall a. SafeJSON a => a -> Value
safeToJSON e
e)
  typeName :: Proxy (a, b, c, d, e) -> String
typeName = Proxy (a, b, c, d, e) -> String
forall (t :: * -> * -> * -> * -> * -> *) a b c d e.
Typeable t =>
Proxy (t a b c d e) -> String
typeName5
  version :: Version (a, b, c, d, e)
version = Version (a, b, c, d, e)
forall a. Version a
noVersion

-- | @since 1.1.2.0
instance SafeJSON (f (g a)) => SafeJSON (Compose f g a) where
    safeFrom :: Value -> Contained (Parser (Compose f g a))
safeFrom Value
val = Parser (Compose f g a) -> Contained (Parser (Compose f g a))
forall a. a -> Contained a
contain (Parser (Compose f g a) -> Contained (Parser (Compose f g a)))
-> Parser (Compose f g a) -> Contained (Parser (Compose f g a))
forall a b. (a -> b) -> a -> b
$ f (g a) -> Compose f g a
forall k k1 (f :: k -> *) (g :: k1 -> k) (a :: k1).
f (g a) -> Compose f g a
Compose (f (g a) -> Compose f g a)
-> Parser (f (g a)) -> Parser (Compose f g a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (f (g a))
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
    safeTo :: Compose f g a -> Contained Value
safeTo (Compose f (g a)
val) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ f (g a) -> Value
forall a. SafeJSON a => a -> Value
safeToJSON f (g a)
val
    typeName :: Proxy (Compose f g a) -> String
typeName Proxy (Compose f g a)
_ = String
"Compose"
    version :: Version (Compose f g a)
version = Version (Compose f g a)
forall a. Version a
noVersion

-- | @since 1.1.2.0
instance (SafeJSON (f a), SafeJSON (g a)) => SafeJSON (Sum f g a) where
    safeFrom :: Value -> Contained (Parser (Sum f g a))
safeFrom = String
-> (Object -> Parser (Sum f g a))
-> Value
-> Contained (Parser (Sum f g a))
forall a.
String -> (Object -> Parser a) -> Value -> Contained (Parser a)
containWithObject String
"Sum" ((Object -> Parser (Sum f g a))
 -> Value -> Contained (Parser (Sum f g a)))
-> (Object -> Parser (Sum f g a))
-> Value
-> Contained (Parser (Sum f g a))
forall a b. (a -> b) -> a -> b
$ \Object
o -> do
        case Object -> [Pair]
forall v. KeyMap v -> [(Key, v)]
Map.toList Object
o of
            [(Key
"InL", Value
val)] -> f a -> Sum f g a
forall k (f :: k -> *) (g :: k -> *) (a :: k). f a -> Sum f g a
InL (f a -> Sum f g a) -> Parser (f a) -> Parser (Sum f g a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (f a)
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
            [(Key
"InR", Value
val)] -> g a -> Sum f g a
forall k (f :: k -> *) (g :: k -> *) (a :: k). g a -> Sum f g a
InR (g a -> Sum f g a) -> Parser (g a) -> Parser (Sum f g a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (g a)
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
val
            [Pair]
_ -> String -> Parser (Sum f g a)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Sum expects an object with one field: \"InL\" or \"InR\""
    safeTo :: Sum f g a -> Contained Value
safeTo = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value)
-> (Sum f g a -> Value) -> Sum f g a -> Contained Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map String Value -> Value
forall a. SafeJSON a => a -> Value
safeToJSON (Map String Value -> Value)
-> (Sum f g a -> Map String Value) -> Sum f g a -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Value -> Map String Value)
-> (String, Value) -> Map String Value
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry String -> Value -> Map String Value
forall k a. k -> a -> Map k a
M.singleton ((String, Value) -> Map String Value)
-> (Sum f g a -> (String, Value)) -> Sum f g a -> Map String Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. \case
        InL f a
fa -> (String
"InL" :: String, f a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON f a
fa)
        InR g a
ga -> (String
"InR" :: String, g a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON g a
ga)
    typeName :: Proxy (Sum f g a) -> String
typeName Proxy (Sum f g a)
_ = String
"Sum"
    version :: Version (Sum f g a)
version = Version (Sum f g a)
forall a. Version a
noVersion

-- | @since 1.1.2.0
instance (SafeJSON (f a), SafeJSON (g a), SafeJSON a) => SafeJSON (Product f g a) where
    safeFrom :: Value -> Contained (Parser (Product f g a))
safeFrom Value
val = Parser (Product f g a) -> Contained (Parser (Product f g a))
forall a. a -> Contained a
contain (Parser (Product f g a) -> Contained (Parser (Product f g a)))
-> Parser (Product f g a) -> Contained (Parser (Product f g a))
forall a b. (a -> b) -> a -> b
$ do
        (Value
f, Value
g) <- Value -> Parser (Value, Value)
forall a. FromJSON a => Value -> Parser a
parseJSON Value
val
        f a -> g a -> Product f g a
forall k (f :: k -> *) (g :: k -> *) (a :: k).
f a -> g a -> Product f g a
Pair (f a -> g a -> Product f g a)
-> Parser (f a) -> Parser (g a -> Product f g a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (f a)
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
f Parser (g a -> Product f g a)
-> Parser (g a) -> Parser (Product f g a)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Value -> Parser (g a)
forall a. SafeJSON a => Value -> Parser a
safeFromJSON Value
g
    safeTo :: Product f g a -> Contained Value
safeTo (Pair f a
f g a
g) = Value -> Contained Value
forall a. a -> Contained a
contain (Value -> Contained Value) -> Value -> Contained Value
forall a b. (a -> b) -> a -> b
$ (Value, Value) -> Value
forall a. ToJSON a => a -> Value
toJSON (f a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON f a
f, g a -> Value
forall a. SafeJSON a => a -> Value
safeToJSON g a
g)
    typeName :: Proxy (Product f g a) -> String
typeName Proxy (Product f g a)
_ = String
"Product"
    version :: Version (Product f g a)
version = Version (Product f g a)
forall a. Version a
noVersion