    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE DataKinds, TypeFamilies #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeApplications #-}
    {-# LANGUAGE AllowAmbiguousTypes #-}

    module Data.GI.Base.GValue
        (
        -- * Constructing GValues
          GValue(..)
        , IsGValue(..)
        , toGValue
        , fromGValue
        , GValueConstruct(..)
        , ptr_to_gvalue_free

        , newGValue
        , buildGValue
        , disownGValue
        , noGValue
        , newGValueFromPtr
        , wrapGValuePtr
        , unsetGValue
        , gvalueType

        -- * Packing GValues into arrays
        , packGValueArray
        , unpackGValueArrayWithLength
        , mapGValueArrayWithLength

        -- * Packing Haskell values into GValues
        , HValue(..)

        -- * Setters and getters
        , set_object
        , get_object
        , set_boxed
        , get_boxed
        , set_variant
        , get_variant
        , set_enum
        , get_enum
        , set_flags
        , get_flags
        , set_stablePtr
        , get_stablePtr
        , take_stablePtr
        , set_param
        , get_param
        , set_hvalue
        , get_hvalue
        ) where

    import Control.Monad.IO.Class (MonadIO, liftIO)

    import Data.Coerce (coerce)
    import Data.Word
    import Data.Int
    import Data.Text (Text, pack, unpack)

    import Foreign.C.Types (CInt(..), CUInt(..), CFloat(..), CDouble(..),
                            CLong(..), CULong(..))
    import Foreign.C.String (CString)
    import Foreign.Ptr (Ptr, nullPtr, plusPtr, FunPtr)
    import Foreign.StablePtr (StablePtr, castStablePtrToPtr, castPtrToStablePtr,
                              newStablePtr, deRefStablePtr)
    import Type.Reflection (typeRep, TypeRep)
    import System.IO (hPutStrLn, stderr)

    import Data.Dynamic (toDyn, fromDynamic, Typeable)
    import Data.GI.Base.BasicTypes
    import Data.GI.Base.BasicConversions (cstringToText, textToCString)
    import Data.GI.Base.GType
    import Data.GI.Base.ManagedPtr
    import Data.GI.Base.Utils (callocBytes, freeMem)
    import Data.GI.Base.Internal.CTypes (cgvalueSize)
    import Data.GI.Base.Overloading (ParentTypes, HasParentTypes)

    -- | Haskell-side representation of a @GValue@.
    newtype GValue = GValue (ManagedPtr GValue)

    -- | A pointer to a function freeing GValues.
    foreign import ccall "&haskell_gi_gvalue_free" ptr_to_gvalue_free ::
        FunPtr (Ptr GValue -> IO ())

    -- | There are no types in the bindings that a `GValue` can be safely
    -- cast to.
    type instance ParentTypes GValue = '[]
    instance HasParentTypes GValue

    foreign import ccall unsafe "g_value_get_type" c_g_value_get_type ::
        IO GType

    -- | Find the associated `GType` for `GValue`.
    instance TypedObject GValue where
      glibType :: IO GType
    glibType = IO GType
    c_g_value_get_type

    -- | `GValue`s are registered as boxed in the GLib type system.
    instance GBoxed GValue

    foreign import ccall "g_value_init" g_value_init ::
        Ptr GValue -> CGType -> IO (Ptr GValue)

    -- | A type holding a `GValue` with an associated label. It is
    -- parameterized by a phantom type encoding the target type for the
    -- `GValue` (useful when constructing properties).
    data GValueConstruct o = GValueConstruct String GValue

    -- | Build a new, empty, `GValue` of the given type.
    newGValue :: GType -> IO GValue
    newGValue :: GType -> IO GValue
    newGValue (GType CGType
    gtype) = do
      gvptr <- Int -> IO (Ptr GValue)
    forall a. Int -> IO (Ptr a)
    callocBytes Int
    cgvalueSize
      _ <- g_value_init gvptr gtype
      gv <- wrapBoxed GValue gvptr
      return $! gv

    -- | Take ownership of a passed in 'Ptr'.
    wrapGValuePtr :: Ptr GValue -> IO GValue
    wrapGValuePtr :: Ptr GValue -> IO GValue
    wrapGValuePtr Ptr GValue
    ptr = (ManagedPtr GValue -> GValue) -> Ptr GValue -> IO GValue
    forall a.
    (HasCallStack, GBoxed a) =>
    (ManagedPtr a -> a) -> Ptr a -> IO a
    wrapBoxed ManagedPtr GValue -> GValue
    GValue Ptr GValue
    ptr

    -- | Construct a Haskell wrapper for the given 'GValue', making a
    -- copy.
    newGValueFromPtr :: Ptr GValue -> IO GValue
    newGValueFromPtr :: Ptr GValue -> IO GValue
    newGValueFromPtr Ptr GValue
    ptr = (ManagedPtr GValue -> GValue) -> Ptr GValue -> IO GValue
    forall a.
    (HasCallStack, GBoxed a) =>
    (ManagedPtr a -> a) -> Ptr a -> IO a
    newBoxed ManagedPtr GValue -> GValue
    GValue Ptr GValue
    ptr

    -- | A convenience function for building a new GValue and setting the
    -- initial value.
    buildGValue :: GType -> (Ptr GValue -> a -> IO ()) -> a -> IO GValue
    buildGValue :: forall a. GType -> (Ptr GValue -> a -> IO ()) -> a -> IO GValue
    buildGValue GType
    gtype Ptr GValue -> a -> IO ()
    setter a
    val = do
      gv <- GType -> IO GValue
    newGValue GType
    gtype
      withManagedPtr gv $ \Ptr GValue
    gvPtr -> Ptr GValue -> a -> IO ()
    setter Ptr GValue
    gvPtr a
    val
      return gv

    -- | Disown a `GValue`, i.e. do not unref the underlying object when
    -- the Haskell object is garbage collected.
    disownGValue :: GValue -> IO (Ptr GValue)
    disownGValue :: GValue -> IO (Ptr GValue)
    disownGValue = GValue -> IO (Ptr GValue)
    forall a b. (HasCallStack, ManagedPtrNewtype a) => a -> IO (Ptr b)
    disownManagedPtr

    foreign import ccall "_haskell_gi_g_value_get_type" g_value_get_type :: Ptr GValue -> IO CGType

    -- | Return the `GType` contained by a `GValue`.
    gvalueType :: GValue -> IO GType
    gvalueType :: GValue -> IO GType
    gvalueType GValue
    gv = GValue -> (Ptr GValue -> IO GType) -> IO GType
    forall a c.
    (HasCallStack, ManagedPtrNewtype a) =>
    a -> (Ptr a -> IO c) -> IO c
    withManagedPtr GValue
    gv ((Ptr GValue -> IO GType) -> IO GType)
    -> (Ptr GValue -> IO GType) -> IO GType
    forall a b. (a -> b) -> a -> b
    $ \Ptr GValue
    gvptr -> do
      cgtype <- Ptr GValue -> IO CGType
    g_value_get_type Ptr GValue
    gvptr
      return (GType cgtype)

    foreign import ccall "g_value_unset" g_value_unset :: Ptr GValue -> IO ()

    -- | Unset the `GValue`, freeing all resources associated to it.
    unsetGValue :: Ptr GValue -> IO ()
    unsetGValue :: Ptr GValue -> IO ()
    unsetGValue = Ptr GValue -> IO ()
    g_value_unset

    -- | A convenient alias for @Nothing :: Maybe GValue@.
    noGValue :: Maybe GValue
    noGValue :: Maybe GValue
    noGValue = Maybe GValue
    forall a. Maybe a
    Nothing

    -- | Class for types that can be marshaled back and forth between
    -- Haskell values and `GValue`s. These are low-level methods, you
    -- might want to use `toGValue` and `fromGValue` instead for a higher
    -- level interface.
    class IsGValue a where
      gvalueGType_ :: IO GType     -- ^ `GType` for the `GValue`
                                   -- containing values of this type.
      gvalueSet_   :: Ptr GValue -> a -> IO ()  -- ^ Set the `GValue` to
                                                -- the given Haskell
                                                -- value.
      gvalueGet_   :: Ptr GValue -> IO a -- ^ Get the Haskel value inside
                                         -- the `GValue`.

    -- | Create a `GValue` from the given Haskell value.
    toGValue :: forall a m. (IsGValue a, MonadIO m) => a -> m GValue
    toGValue :: forall a (m :: * -> *). (IsGValue a, MonadIO m) => a -> m GValue
    toGValue a
    val = IO GValue -> m GValue
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO GValue -> m GValue) -> IO GValue -> m GValue
    forall a b. (a -> b) -> a -> b
    $ do
      gvptr <- Int -> IO (Ptr GValue)
    forall a. Int -> IO (Ptr a)
    callocBytes Int
    cgvalueSize
      GType gtype <- gvalueGType_ @a
      _ <- g_value_init gvptr gtype
      gvalueSet_ gvptr val
      gv <- wrapBoxed GValue gvptr
      return $! gv

    -- | Create a Haskell object out of the given `GValue`.
    fromGValue :: (IsGValue a, MonadIO m) => GValue -> m a
    fromGValue :: forall a (m :: * -> *). (IsGValue a, MonadIO m) => GValue -> m a
    fromGValue GValue
    gv = IO a -> m a
    forall a. IO a -> m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO a -> m a) -> IO a -> m a
    forall a b. (a -> b) -> a -> b
    $ GValue -> (Ptr GValue -> IO a) -> IO a
    forall a c.
    (HasCallStack, ManagedPtrNewtype a) =>
    a -> (Ptr a -> IO c) -> IO c
    withManagedPtr GValue
    gv Ptr GValue -> IO a
    forall a. IsGValue a => Ptr GValue -> IO a
    gvalueGet_

    instance IsGValue (Maybe String) where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeString
      gvalueSet_ :: Ptr GValue -> Maybe String -> IO ()
    gvalueSet_ Ptr GValue
    gvPtr Maybe String
    mstr = Ptr GValue -> Maybe Text -> IO ()
    set_string Ptr GValue
    gvPtr (String -> Text
    pack (String -> Text) -> Maybe String -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe String
    mstr)
      gvalueGet_ :: Ptr GValue -> IO (Maybe String)
    gvalueGet_ Ptr GValue
    v = ((Text -> String) -> Maybe Text -> Maybe String
    forall a b. (a -> b) -> Maybe a -> Maybe b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap Text -> String
    unpack) (Maybe Text -> Maybe String)
    -> IO (Maybe Text) -> IO (Maybe String)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO (Maybe Text)
    get_string Ptr GValue
    v

    instance IsGValue (Maybe Text) where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeString
      gvalueSet_ :: Ptr GValue -> Maybe Text -> IO ()
    gvalueSet_ = Ptr GValue -> Maybe Text -> IO ()
    set_string
      gvalueGet_ :: Ptr GValue -> IO (Maybe Text)
    gvalueGet_ = Ptr GValue -> IO (Maybe Text)
    get_string

    instance IsGValue (Ptr a) where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypePointer
      gvalueSet_ :: Ptr GValue -> Ptr a -> IO ()
    gvalueSet_ = Ptr GValue -> Ptr a -> IO ()
    forall a. Ptr GValue -> Ptr a -> IO ()
    set_pointer
      gvalueGet_ :: Ptr GValue -> IO (Ptr a)
    gvalueGet_ = Ptr GValue -> IO (Ptr a)
    forall a. Ptr GValue -> IO (Ptr a)
    get_pointer

    instance IsGValue Int32 where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeInt
      gvalueSet_ :: Ptr GValue -> Int32 -> IO ()
    gvalueSet_ = Ptr GValue -> Int32 -> IO ()
    set_int32
      gvalueGet_ :: Ptr GValue -> IO Int32
    gvalueGet_ = Ptr GValue -> IO Int32
    get_int32

    instance IsGValue Word32 where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeUInt
      gvalueSet_ :: Ptr GValue -> Word32 -> IO ()
    gvalueSet_ = Ptr GValue -> Word32 -> IO ()
    set_uint32
      gvalueGet_ :: Ptr GValue -> IO Word32
    gvalueGet_ = Ptr GValue -> IO Word32
    get_uint32

    instance IsGValue CInt where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeInt
      gvalueSet_ :: Ptr GValue -> CInt -> IO ()
    gvalueSet_ = Ptr GValue -> CInt -> IO ()
    set_int
      gvalueGet_ :: Ptr GValue -> IO CInt
    gvalueGet_ = Ptr GValue -> IO CInt
    get_int

    instance IsGValue CUInt where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeUInt
      gvalueSet_ :: Ptr GValue -> CUInt -> IO ()
    gvalueSet_ = Ptr GValue -> CUInt -> IO ()
    set_uint
      gvalueGet_ :: Ptr GValue -> IO CUInt
    gvalueGet_ = Ptr GValue -> IO CUInt
    get_uint

    instance IsGValue CLong where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeLong
      gvalueSet_ :: Ptr GValue -> CLong -> IO ()
    gvalueSet_ = Ptr GValue -> CLong -> IO ()
    set_long
      gvalueGet_ :: Ptr GValue -> IO CLong
    gvalueGet_ = Ptr GValue -> IO CLong
    get_long

    instance IsGValue CULong where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeULong
      gvalueSet_ :: Ptr GValue -> CULong -> IO ()
    gvalueSet_ = Ptr GValue -> CULong -> IO ()
    set_ulong
      gvalueGet_ :: Ptr GValue -> IO CULong
    gvalueGet_ = Ptr GValue -> IO CULong
    get_ulong

    instance IsGValue Int64 where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeInt64
      gvalueSet_ :: Ptr GValue -> Int64 -> IO ()
    gvalueSet_ = Ptr GValue -> Int64 -> IO ()
    set_int64
      gvalueGet_ :: Ptr GValue -> IO Int64
    gvalueGet_ = Ptr GValue -> IO Int64
    get_int64

    instance IsGValue Word64 where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeUInt64
      gvalueSet_ :: Ptr GValue -> CGType -> IO ()
    gvalueSet_ = Ptr GValue -> CGType -> IO ()
    set_uint64
      gvalueGet_ :: Ptr GValue -> IO CGType
    gvalueGet_ = Ptr GValue -> IO CGType
    get_uint64

    instance IsGValue Float where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeFloat
      gvalueSet_ :: Ptr GValue -> Float -> IO ()
    gvalueSet_ = Ptr GValue -> Float -> IO ()
    set_float
      gvalueGet_ :: Ptr GValue -> IO Float
    gvalueGet_ = Ptr GValue -> IO Float
    get_float

    instance IsGValue Double where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeDouble
      gvalueSet_ :: Ptr GValue -> Double -> IO ()
    gvalueSet_ = Ptr GValue -> Double -> IO ()
    set_double
      gvalueGet_ :: Ptr GValue -> IO Double
    gvalueGet_ = Ptr GValue -> IO Double
    get_double

    instance IsGValue Bool where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeBoolean
      gvalueSet_ :: Ptr GValue -> Bool -> IO ()
    gvalueSet_ = Ptr GValue -> Bool -> IO ()
    set_boolean
      gvalueGet_ :: Ptr GValue -> IO Bool
    gvalueGet_ = Ptr GValue -> IO Bool
    get_boolean

    instance IsGValue GType where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeGType
      gvalueSet_ :: Ptr GValue -> GType -> IO ()
    gvalueSet_ = Ptr GValue -> GType -> IO ()
    set_gtype
      gvalueGet_ :: Ptr GValue -> IO GType
    gvalueGet_ = Ptr GValue -> IO GType
    get_gtype

    instance IsGValue (StablePtr a) where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeStablePtr
      gvalueSet_ :: Ptr GValue -> StablePtr a -> IO ()
    gvalueSet_ = Ptr GValue -> StablePtr a -> IO ()
    forall a. Ptr GValue -> StablePtr a -> IO ()
    set_stablePtr
      gvalueGet_ :: Ptr GValue -> IO (StablePtr a)
    gvalueGet_ = Ptr GValue -> IO (StablePtr a)
    forall a. Ptr GValue -> IO (StablePtr a)
    get_stablePtr

    instance IsGValue (Maybe GParamSpec) where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeParam
      gvalueSet_ :: Ptr GValue -> Maybe GParamSpec -> IO ()
    gvalueSet_ = Ptr GValue -> Maybe GParamSpec -> IO ()
    set_param
      gvalueGet_ :: Ptr GValue -> IO (Maybe GParamSpec)
    gvalueGet_ = Ptr GValue -> IO (Maybe GParamSpec)
    get_param

    instance Typeable a => IsGValue (HValue a) where
      gvalueGType_ :: IO GType
    gvalueGType_ = GType -> IO GType
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return GType
    gtypeHValue
      gvalueSet_ :: Ptr GValue -> HValue a -> IO ()
    gvalueSet_ = Ptr GValue -> HValue a -> IO ()
    forall a. Typeable a => Ptr GValue -> HValue a -> IO ()
    set_hvalue
      gvalueGet_ :: Ptr GValue -> IO (HValue a)
    gvalueGet_ = Ptr GValue -> IO (HValue a)
    forall a. Typeable a => Ptr GValue -> IO (HValue a)
    get_hvalue

    foreign import ccall "g_value_set_string" _set_string ::
        Ptr GValue -> CString -> IO ()
    foreign import ccall "g_value_get_string" _get_string ::
        Ptr GValue -> IO CString

    set_string :: Ptr GValue -> Maybe Text -> IO ()
    set_string :: Ptr GValue -> Maybe Text -> IO ()
    set_string Ptr GValue
    ptr Maybe Text
    maybeStr = do
      cstr <- case Maybe Text
    maybeStr of
                Just Text
    str -> Text -> IO CString
    textToCString Text
    str
                Maybe Text
    Nothing -> CString -> IO CString
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return CString
    forall a. Ptr a
    nullPtr
      _set_string ptr cstr
      freeMem cstr

    get_string :: Ptr GValue -> IO (Maybe Text)
    get_string :: Ptr GValue -> IO (Maybe Text)
    get_string Ptr GValue
    gvptr = do
      cstr <- Ptr GValue -> IO CString
    _get_string Ptr GValue
    gvptr
      if cstr /= nullPtr
        then Just <$> cstringToText cstr
        else return Nothing

    foreign import ccall unsafe "g_value_set_pointer" set_pointer ::
        Ptr GValue -> Ptr a -> IO ()
    foreign import ccall unsafe "g_value_get_pointer" get_pointer ::
        Ptr GValue -> IO (Ptr b)

    foreign import ccall unsafe "g_value_set_int" set_int ::
        Ptr GValue -> CInt -> IO ()
    foreign import ccall unsafe "g_value_get_int" get_int ::
        Ptr GValue -> IO CInt

    set_int32 :: Ptr GValue -> Int32 -> IO ()
    set_int32 :: Ptr GValue -> Int32 -> IO ()
    set_int32 Ptr GValue
    gv Int32
    n = Ptr GValue -> CInt -> IO ()
    set_int Ptr GValue
    gv (Int32 -> CInt
    forall a b. Coercible a b => a -> b
    coerce Int32
    n)

    get_int32 :: Ptr GValue -> IO Int32
    get_int32 :: Ptr GValue -> IO Int32
    get_int32 Ptr GValue
    gv = CInt -> Int32
    forall a b. Coercible a b => a -> b
    coerce (CInt -> Int32) -> IO CInt -> IO Int32
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO CInt
    get_int Ptr GValue
    gv

    foreign import ccall unsafe "g_value_set_uint" set_uint ::
        Ptr GValue -> CUInt -> IO ()
    foreign import ccall unsafe "g_value_get_uint" get_uint ::
        Ptr GValue -> IO CUInt

    set_uint32 :: Ptr GValue -> Word32 -> IO ()
    set_uint32 :: Ptr GValue -> Word32 -> IO ()
    set_uint32 Ptr GValue
    gv Word32
    n = Ptr GValue -> CUInt -> IO ()
    set_uint Ptr GValue
    gv (Word32 -> CUInt
    forall a b. Coercible a b => a -> b
    coerce Word32
    n)

    get_uint32 :: Ptr GValue -> IO Word32
    get_uint32 :: Ptr GValue -> IO Word32
    get_uint32 Ptr GValue
    gv = CUInt -> Word32
    forall a b. Coercible a b => a -> b
    coerce (CUInt -> Word32) -> IO CUInt -> IO Word32
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO CUInt
    get_uint Ptr GValue
    gv

    foreign import ccall unsafe "g_value_set_long" set_long ::
        Ptr GValue -> CLong -> IO ()
    foreign import ccall unsafe "g_value_get_long" get_long ::
        Ptr GValue -> IO CLong

    foreign import ccall unsafe "g_value_set_ulong" set_ulong ::
        Ptr GValue -> CULong -> IO ()
    foreign import ccall unsafe "g_value_get_ulong" get_ulong ::
        Ptr GValue -> IO CULong

    foreign import ccall unsafe "g_value_set_int64" set_int64 ::
        Ptr GValue -> Int64 -> IO ()
    foreign import ccall unsafe "g_value_get_int64" get_int64 ::
        Ptr GValue -> IO Int64

    foreign import ccall unsafe "g_value_set_uint64" set_uint64 ::
        Ptr GValue -> Word64 -> IO ()
    foreign import ccall unsafe "g_value_get_uint64" get_uint64 ::
        Ptr GValue -> IO Word64

    foreign import ccall unsafe "g_value_set_float" _set_float ::
        Ptr GValue -> CFloat -> IO ()
    foreign import ccall unsafe "g_value_get_float" _get_float ::
        Ptr GValue -> IO CFloat

    set_float :: Ptr GValue -> Float -> IO ()
    set_float :: Ptr GValue -> Float -> IO ()
    set_float Ptr GValue
    gv Float
    f = Ptr GValue -> CFloat -> IO ()
    _set_float Ptr GValue
    gv (Float -> CFloat
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac Float
    f)

    get_float :: Ptr GValue -> IO Float
    get_float :: Ptr GValue -> IO Float
    get_float Ptr GValue
    gv = CFloat -> Float
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac (CFloat -> Float) -> IO CFloat -> IO Float
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO CFloat
    _get_float Ptr GValue
    gv

    foreign import ccall unsafe "g_value_set_double" _set_double ::
        Ptr GValue -> CDouble -> IO ()
    foreign import ccall unsafe "g_value_get_double" _get_double ::
        Ptr GValue -> IO CDouble

    set_double :: Ptr GValue -> Double -> IO ()
    set_double :: Ptr GValue -> Double -> IO ()
    set_double Ptr GValue
    gv Double
    d = Ptr GValue -> CDouble -> IO ()
    _set_double Ptr GValue
    gv (Double -> CDouble
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac Double
    d)

    get_double :: Ptr GValue -> IO Double
    get_double :: Ptr GValue -> IO Double
    get_double Ptr GValue
    gv = CDouble -> Double
    forall a b. (Real a, Fractional b) => a -> b
    realToFrac (CDouble -> Double) -> IO CDouble -> IO Double
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO CDouble
    _get_double Ptr GValue
    gv

    foreign import ccall unsafe "g_value_set_boolean" _set_boolean ::
        Ptr GValue -> CInt -> IO ()
    foreign import ccall unsafe "g_value_get_boolean" _get_boolean ::
        Ptr GValue -> IO CInt

    set_boolean :: Ptr GValue -> Bool -> IO ()
    set_boolean :: Ptr GValue -> Bool -> IO ()
    set_boolean Ptr GValue
    gv Bool
    b = Ptr GValue -> CInt -> IO ()
    _set_boolean Ptr GValue
    gv (Int -> CInt
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral (Int -> CInt) -> Int -> CInt
    forall a b. (a -> b) -> a -> b
    $ Bool -> Int
    forall a. Enum a => a -> Int
    fromEnum Bool
    b)

    get_boolean :: Ptr GValue -> IO Bool
    get_boolean :: Ptr GValue -> IO Bool
    get_boolean Ptr GValue
    gv = (CInt -> CInt -> Bool
    forall a. Eq a => a -> a -> Bool
    /= CInt
    0) (CInt -> Bool) -> IO CInt -> IO Bool
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO CInt
    _get_boolean Ptr GValue
    gv

    foreign import ccall unsafe "g_value_set_gtype" _set_gtype ::
        Ptr GValue -> CGType -> IO ()
    foreign import ccall unsafe "g_value_get_gtype" _get_gtype ::
        Ptr GValue -> IO CGType

    set_gtype :: Ptr GValue -> GType -> IO ()
    set_gtype :: Ptr GValue -> GType -> IO ()
    set_gtype Ptr GValue
    gv (GType CGType
    g) = Ptr GValue -> CGType -> IO ()
    _set_gtype Ptr GValue
    gv CGType
    g

    get_gtype :: Ptr GValue -> IO GType
    get_gtype :: Ptr GValue -> IO GType
    get_gtype Ptr GValue
    gv = CGType -> GType
    GType (CGType -> GType) -> IO CGType -> IO GType
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO CGType
    _get_gtype Ptr GValue
    gv

    foreign import ccall "g_value_set_object" _set_object ::
        Ptr GValue -> Ptr a -> IO ()
    foreign import ccall "g_value_get_object" _get_object ::
        Ptr GValue -> IO (Ptr a)

    set_object :: GObject a => Ptr GValue -> Ptr a -> IO ()
    set_object :: forall a. GObject a => Ptr GValue -> Ptr a -> IO ()
    set_object = Ptr GValue -> Ptr a -> IO ()
    forall a. Ptr GValue -> Ptr a -> IO ()
    _set_object

    get_object :: GObject a => Ptr GValue -> IO (Ptr a)
    get_object :: forall a. GObject a => Ptr GValue -> IO (Ptr a)
    get_object = Ptr GValue -> IO (Ptr a)
    forall a. Ptr GValue -> IO (Ptr a)
    _get_object

    foreign import ccall "g_value_set_boxed" set_boxed ::
        Ptr GValue -> Ptr a -> IO ()
    foreign import ccall "g_value_get_boxed" get_boxed ::
        Ptr GValue -> IO (Ptr b)
    foreign import ccall "g_value_dup_boxed" dup_boxed ::
        Ptr GValue -> IO (Ptr b)

    foreign import ccall "g_value_set_variant" set_variant ::
        Ptr GValue -> Ptr GVariant -> IO ()
    foreign import ccall "g_value_get_variant" get_variant ::
        Ptr GValue -> IO (Ptr GVariant)

    foreign import ccall unsafe "g_value_set_enum" set_enum ::
        Ptr GValue -> CUInt -> IO ()
    foreign import ccall unsafe "g_value_get_enum" get_enum ::
        Ptr GValue -> IO CUInt

    foreign import ccall unsafe "g_value_set_flags" set_flags ::
        Ptr GValue -> CUInt -> IO ()
    foreign import ccall unsafe "g_value_get_flags" get_flags ::
        Ptr GValue -> IO CUInt

    -- | Set the value of `GValue` containing a `StablePtr`
    set_stablePtr :: Ptr GValue -> StablePtr a -> IO ()
    set_stablePtr :: forall a. Ptr GValue -> StablePtr a -> IO ()
    set_stablePtr Ptr GValue
    gv StablePtr a
    ptr = Ptr GValue -> Ptr () -> IO ()
    forall a. Ptr GValue -> Ptr a -> IO ()
    set_boxed Ptr GValue
    gv (StablePtr a -> Ptr ()
    forall a. StablePtr a -> Ptr ()
    castStablePtrToPtr StablePtr a
    ptr)

    foreign import ccall g_value_take_boxed :: Ptr GValue -> Ptr a -> IO ()

    -- | Like `set_stablePtr`, but the `GValue` takes ownership of the `StablePtr`
    take_stablePtr :: Ptr GValue -> StablePtr a -> IO ()
    take_stablePtr :: forall a. Ptr GValue -> StablePtr a -> IO ()
    take_stablePtr Ptr GValue
    gvPtr StablePtr a
    stablePtr =
      Ptr GValue -> Ptr () -> IO ()
    forall a. Ptr GValue -> Ptr a -> IO ()
    g_value_take_boxed Ptr GValue
    gvPtr (StablePtr a -> Ptr ()
    forall a. StablePtr a -> Ptr ()
    castStablePtrToPtr StablePtr a
    stablePtr)

    -- | Get (a freshly allocated copy of) the value of a `GValue`
    -- containing a `StablePtr`
    get_stablePtr :: Ptr GValue -> IO (StablePtr a)
    get_stablePtr :: forall a. Ptr GValue -> IO (StablePtr a)
    get_stablePtr Ptr GValue
    gv = Ptr () -> StablePtr a
    forall a. Ptr () -> StablePtr a
    castPtrToStablePtr (Ptr () -> StablePtr a) -> IO (Ptr ()) -> IO (StablePtr a)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Ptr GValue -> IO (Ptr ())
    forall a. Ptr GValue -> IO (Ptr a)
    dup_boxed Ptr GValue
    gv

    foreign import ccall g_value_copy :: Ptr GValue -> Ptr GValue -> IO ()

    -- | Pack the given list of GValues contiguously into a C array
    packGValueArray :: [GValue] -> IO (Ptr GValue)
    packGValueArray :: [GValue] -> IO (Ptr GValue)
    packGValueArray [GValue]
    gvalues = [GValue] -> ([Ptr GValue] -> IO (Ptr GValue)) -> IO (Ptr GValue)
    forall a c.
    (HasCallStack, ManagedPtrNewtype a) =>
    [a] -> ([Ptr a] -> IO c) -> IO c
    withManagedPtrList [GValue]
    gvalues (([Ptr GValue] -> IO (Ptr GValue)) -> IO (Ptr GValue))
    -> ([Ptr GValue] -> IO (Ptr GValue)) -> IO (Ptr GValue)
    forall a b. (a -> b) -> a -> b
    $ \[Ptr GValue]
    ptrs -> do
      let nitems :: Int
    nitems = [Ptr GValue] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [Ptr GValue]
    ptrs
      mem <- Int -> IO (Ptr GValue)
    forall a. Int -> IO (Ptr a)
    callocBytes (Int -> IO (Ptr GValue)) -> Int -> IO (Ptr GValue)
    forall a b. (a -> b) -> a -> b
    $ Int
    cgvalueSize Int -> Int -> Int
    forall a. Num a => a -> a -> a
    * Int
    nitems
      fill mem ptrs
      return mem
      where fill :: Ptr GValue -> [Ptr GValue] -> IO ()
            fill :: Ptr GValue -> [Ptr GValue] -> IO ()
    fill Ptr GValue
    _ [] = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            fill Ptr GValue
    ptr (Ptr GValue
    x:[Ptr GValue]
    xs) = do
              gtype <- Ptr GValue -> IO CGType
    g_value_get_type Ptr GValue
    x
              _ <- g_value_init ptr gtype
              g_value_copy x ptr
              fill (ptr `plusPtr` cgvalueSize) xs

    -- | Unpack an array of contiguous GValues into a list of GValues.
    unpackGValueArrayWithLength :: Integral a =>
                                   a -> Ptr GValue -> IO [GValue]
    unpackGValueArrayWithLength :: forall a. Integral a => a -> Ptr GValue -> IO [GValue]
    unpackGValueArrayWithLength a
    nitems Ptr GValue
    gvalues = Int -> Ptr GValue -> IO [GValue]
    go (a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    nitems) Ptr GValue
    gvalues
      where go :: Int -> Ptr GValue -> IO [GValue]
            go :: Int -> Ptr GValue -> IO [GValue]
    go Int
    0 Ptr GValue
    _ = [GValue] -> IO [GValue]
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return []
            go Int
    n Ptr GValue
    ptr = do
              gv <- Int -> IO (Ptr GValue)
    forall a. Int -> IO (Ptr a)
    callocBytes Int
    cgvalueSize
              gtype <- g_value_get_type ptr
              _ <- g_value_init gv gtype
              g_value_copy ptr gv
              wrapped <- wrapGValuePtr gv
              (wrapped :) <$> go (n-1) (ptr `plusPtr` cgvalueSize)

    -- | Map over the `GValue`s inside a C array.
    mapGValueArrayWithLength :: Integral a =>
                                a -> (Ptr GValue -> IO c) -> Ptr GValue -> IO ()
    mapGValueArrayWithLength :: forall a c.
    Integral a =>
    a -> (Ptr GValue -> IO c) -> Ptr GValue -> IO ()
    mapGValueArrayWithLength a
    nvalues Ptr GValue -> IO c
    f Ptr GValue
    arrayPtr
      | (Ptr GValue
    arrayPtr Ptr GValue -> Ptr GValue -> Bool
    forall a. Eq a => a -> a -> Bool
    == Ptr GValue
    forall a. Ptr a
    nullPtr) = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      | (a
    nvalues a -> a -> Bool
    forall a. Ord a => a -> a -> Bool
    <= a
    0) = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
      | Bool
    otherwise = Int -> Ptr GValue -> IO ()
    go (a -> Int
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral a
    nvalues) Ptr GValue
    arrayPtr
      where go :: Int -> Ptr GValue -> IO ()
            go :: Int -> Ptr GValue -> IO ()
    go Int
    0 Ptr GValue
    _ = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
            go Int
    n Ptr GValue
    ptr = do
              _ <- Ptr GValue -> IO c
    f Ptr GValue
    ptr
              go (n-1) (ptr `plusPtr` cgvalueSize)

    foreign import ccall unsafe "g_value_set_param" _set_param ::
        Ptr GValue -> Ptr GParamSpec -> IO ()
    foreign import ccall unsafe "g_value_get_param" _get_param ::
        Ptr GValue -> IO (Ptr GParamSpec)

    -- | Set the value of `GValue` containing a `GParamSpec`
    set_param :: Ptr GValue -> Maybe GParamSpec -> IO ()
    set_param :: Ptr GValue -> Maybe GParamSpec -> IO ()
    set_param Ptr GValue
    gv (Just GParamSpec
    ps) = GParamSpec -> (Ptr GParamSpec -> IO ()) -> IO ()
    forall a c.
    (HasCallStack, ManagedPtrNewtype a) =>
    a -> (Ptr a -> IO c) -> IO c
    withManagedPtr GParamSpec
    ps (Ptr GValue -> Ptr GParamSpec -> IO ()
    _set_param Ptr GValue
    gv)
    set_param Ptr GValue
    gv Maybe GParamSpec
    Nothing = Ptr GValue -> Ptr GParamSpec -> IO ()
    _set_param Ptr GValue
    gv Ptr GParamSpec
    forall a. Ptr a
    nullPtr

    foreign import ccall "g_param_spec_ref" g_param_spec_ref ::
        Ptr GParamSpec -> IO (Ptr GParamSpec)
    foreign import ccall "&g_param_spec_unref" ptr_to_g_param_spec_unref ::
        FunPtr (Ptr GParamSpec -> IO ())

    -- | Get the value of a `GValue` containing a `GParamSpec`
    get_param :: Ptr GValue -> IO (Maybe GParamSpec)
    get_param :: Ptr GValue -> IO (Maybe GParamSpec)
    get_param Ptr GValue
    gv = do
      ptr <- Ptr GValue -> IO (Ptr GParamSpec)
    _get_param Ptr GValue
    gv
      if ptr == nullPtr
        then return Nothing
        else do
        fPtr <- g_param_spec_ref ptr >>= newManagedPtr' ptr_to_g_param_spec_unref
        return . Just $! GParamSpec fPtr

    -- | A type isomorphic to `Maybe a`, used to indicate to
    -- `fromGValue`/`toGValue` that we are packing a native Haskell value,
    -- without attempting to marshall it to the corresponding C type.
    data HValue a = HValue a -- ^ A packed value of type `a`
                  | NoHValue -- ^ An empty `HValue`
      deriving (Int -> HValue a -> ShowS
    [HValue a] -> ShowS
    HValue a -> String
    (Int -> HValue a -> ShowS)
    -> (HValue a -> String) -> ([HValue a] -> ShowS) -> Show (HValue a)
    forall a. Show a => Int -> HValue a -> ShowS
    forall a. Show a => [HValue a] -> ShowS
    forall a. Show a => HValue a -> String
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: forall a. Show a => Int -> HValue a -> ShowS
    showsPrec :: Int -> HValue a -> ShowS
    $cshow :: forall a. Show a => HValue a -> String
    show :: HValue a -> String
    $cshowList :: forall a. Show a => [HValue a] -> ShowS
    showList :: [HValue a] -> ShowS
    Show, HValue a -> HValue a -> Bool
    (HValue a -> HValue a -> Bool)
    -> (HValue a -> HValue a -> Bool) -> Eq (HValue a)
    forall a. Eq a => HValue a -> HValue a -> Bool
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: forall a. Eq a => HValue a -> HValue a -> Bool
    == :: HValue a -> HValue a -> Bool
    $c/= :: forall a. Eq a => HValue a -> HValue a -> Bool
    /= :: HValue a -> HValue a -> Bool
    Eq)

    -- | Set the `GValue` to the given Haskell value.
    set_hvalue :: Typeable a => Ptr GValue -> HValue a -> IO ()
    set_hvalue :: forall a. Typeable a => Ptr GValue -> HValue a -> IO ()
    set_hvalue Ptr GValue
    gvPtr HValue a
    NoHValue = Ptr GValue -> Ptr (ZonkAny 0) -> IO ()
    forall a. Ptr GValue -> Ptr a -> IO ()
    set_boxed Ptr GValue
    gvPtr Ptr (ZonkAny 0)
    forall a. Ptr a
    nullPtr
    set_hvalue Ptr GValue
    gvPtr (HValue a
    v) = do
      sPtr <- Dynamic -> IO (StablePtr Dynamic)
    forall a. a -> IO (StablePtr a)
    newStablePtr (a -> Dynamic
    forall a. Typeable a => a -> Dynamic
    toDyn a
    v)
      g_value_take_boxed gvPtr (castStablePtrToPtr sPtr)

    -- | Get the value in the GValue, checking that the type is
    -- `gtypeHValue`. Will return NULL and print a warning if the GValue
    -- is of the wrong type.
    foreign import ccall "haskell_gi_safe_get_boxed_haskell_value" safe_get_boxed_hvalue ::
        Ptr GValue -> IO (Ptr b)

    -- | Read the Haskell value of the given type from the `GValue`. If
    -- the `GValue` contains no value of the expected type, `NoHValue`
    -- will be returned instead, and an error will be printed to stderr.
    get_hvalue :: forall a. Typeable a => Ptr GValue -> IO (HValue a)
    get_hvalue :: forall a. Typeable a => Ptr GValue -> IO (HValue a)
    get_hvalue Ptr GValue
    gvPtr = do
      hvaluePtr <- Ptr GValue -> IO (Ptr ())
    forall a. Ptr GValue -> IO (Ptr a)
    safe_get_boxed_hvalue Ptr GValue
    gvPtr
      if hvaluePtr == nullPtr
        then return NoHValue
        else do
          dyn <- deRefStablePtr (castPtrToStablePtr hvaluePtr)
          case fromDynamic dyn of
            Maybe a
    Nothing -> do
              Handle -> String -> IO ()
    hPutStrLn Handle
    stderr (String
    "HASKELL-GI: Unexpected type ‘" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> Dynamic -> String
    forall a. Show a => a -> String
    show Dynamic
    dyn
                                 String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "’ inside the GValue at ‘" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> Ptr GValue -> String
    forall a. Show a => a -> String
    show Ptr GValue
    gvPtr
                                 String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "’.\n\tExpected ‘" String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> TypeRep a -> String
    forall a. Show a => a -> String
    show (TypeRep a
    forall {k} (a :: k). Typeable a => TypeRep a
    typeRep :: TypeRep a)
                                 String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    "’.")
              HValue a -> IO (HValue a)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return HValue a
    forall a. HValue a
    NoHValue
            Just a
    val -> HValue a -> IO (HValue a)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a -> HValue a
    forall a. a -> HValue a
    HValue a
    val)