{-# LANGUAGE TypeApplications #-}


-- | Copyright  : Will Thompson and Iñaki García Etxebarria
-- License    : LGPL-2.1
-- Maintainer : Iñaki García Etxebarria
-- 
-- @GConverter@ is an interface for streaming conversions.
-- 
-- @GConverter@ is implemented by objects that convert
-- binary data in various ways. The conversion can be
-- stateful and may fail at any place.
-- 
-- Some example conversions are: character set conversion,
-- compression, decompression and regular expression
-- replace.
-- 
-- /Since: 2.24/

#if (MIN_VERSION_haskell_gi_overloading(1,0,0) && !defined(__HADDOCK_VERSION__))
#define ENABLE_OVERLOADING
#endif

module GI.Gio.Interfaces.Converter
    ( 

-- * Exported types
    Converter(..)                           ,
    IsConverter                             ,
    toConverter                             ,


 -- * Methods
-- | 
-- 
--  === __Click to display all available methods, including inherited ones__
-- ==== Methods
-- [bindProperty]("GI.GObject.Objects.Object#g:method:bindProperty"), [bindPropertyFull]("GI.GObject.Objects.Object#g:method:bindPropertyFull"), [convert]("GI.Gio.Interfaces.Converter#g:method:convert"), [convertBytes]("GI.Gio.Interfaces.Converter#g:method:convertBytes"), [forceFloating]("GI.GObject.Objects.Object#g:method:forceFloating"), [freezeNotify]("GI.GObject.Objects.Object#g:method:freezeNotify"), [getv]("GI.GObject.Objects.Object#g:method:getv"), [isFloating]("GI.GObject.Objects.Object#g:method:isFloating"), [notify]("GI.GObject.Objects.Object#g:method:notify"), [notifyByPspec]("GI.GObject.Objects.Object#g:method:notifyByPspec"), [ref]("GI.GObject.Objects.Object#g:method:ref"), [refSink]("GI.GObject.Objects.Object#g:method:refSink"), [reset]("GI.Gio.Interfaces.Converter#g:method:reset"), [runDispose]("GI.GObject.Objects.Object#g:method:runDispose"), [stealData]("GI.GObject.Objects.Object#g:method:stealData"), [stealQdata]("GI.GObject.Objects.Object#g:method:stealQdata"), [thawNotify]("GI.GObject.Objects.Object#g:method:thawNotify"), [unref]("GI.GObject.Objects.Object#g:method:unref"), [watchClosure]("GI.GObject.Objects.Object#g:method:watchClosure").
-- 
-- ==== Getters
-- [getData]("GI.GObject.Objects.Object#g:method:getData"), [getProperty]("GI.GObject.Objects.Object#g:method:getProperty"), [getQdata]("GI.GObject.Objects.Object#g:method:getQdata").
-- 
-- ==== Setters
-- [setData]("GI.GObject.Objects.Object#g:method:setData"), [setDataFull]("GI.GObject.Objects.Object#g:method:setDataFull"), [setProperty]("GI.GObject.Objects.Object#g:method:setProperty").

#if defined(ENABLE_OVERLOADING)
    ResolveConverterMethod                  ,
#endif

-- ** convert #method:convert#

#if defined(ENABLE_OVERLOADING)
    ConverterConvertMethodInfo              ,
#endif
    converterConvert                        ,


-- ** convertBytes #method:convertBytes#

#if defined(ENABLE_OVERLOADING)
    ConverterConvertBytesMethodInfo         ,
#endif
    converterConvertBytes                   ,


-- ** reset #method:reset#

#if defined(ENABLE_OVERLOADING)
    ConverterResetMethodInfo                ,
#endif
    converterReset                          ,




    ) where

import Data.GI.Base.ShortPrelude
import qualified Data.GI.Base.ShortPrelude as SP
import qualified Data.GI.Base.Overloading as O
import qualified Prelude as P

import qualified Data.GI.Base.Attributes as GI.Attributes
import qualified Data.GI.Base.BasicTypes as B.Types
import qualified Data.GI.Base.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GArray as B.GArray
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
import qualified Data.GI.Base.GHashTable as B.GHT
import qualified Data.GI.Base.GVariant as B.GVariant
import qualified Data.GI.Base.GValue as B.GValue
import qualified Data.GI.Base.GParamSpec as B.GParamSpec
import qualified Data.GI.Base.CallStack as B.CallStack
import qualified Data.GI.Base.Properties as B.Properties
import qualified Data.GI.Base.Signals as B.Signals
import qualified Control.Monad.IO.Class as MIO
import qualified Data.Coerce as Coerce
import qualified Data.Text as T
import qualified Data.Kind as DK
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map
import qualified Foreign.Ptr as FP
import qualified GHC.OverloadedLabels as OL
import qualified GHC.Records as R
import qualified Data.Word as DW
import qualified Data.Int as DI
import qualified System.Posix.Types as SPT
import qualified Foreign.C.Types as FCT

-- Workaround for https://gitlab.haskell.org/ghc/ghc/-/issues/23392
#if MIN_VERSION_base(4,18,0)
import qualified GI.GLib.Structs.Bytes as GLib.Bytes
import qualified GI.GObject.Objects.Object as GObject.Object
import {-# SOURCE #-} qualified GI.Gio.Enums as Gio.Enums
import {-# SOURCE #-} qualified GI.Gio.Flags as Gio.Flags

#else
import qualified GI.GLib.Structs.Bytes as GLib.Bytes
import qualified GI.GObject.Objects.Object as GObject.Object
import {-# SOURCE #-} qualified GI.Gio.Enums as Gio.Enums
import {-# SOURCE #-} qualified GI.Gio.Flags as Gio.Flags

#endif

-- interface Converter 
-- | Memory-managed wrapper type.
newtype Converter = Converter (SP.ManagedPtr Converter)
    deriving (Eq)

instance SP.ManagedPtrNewtype Converter where
    toManagedPtr (Converter p) = p

foreign import ccall "g_converter_get_type"
    c_g_converter_get_type :: IO B.Types.GType

instance B.Types.TypedObject Converter where
    glibType = c_g_converter_get_type

instance B.Types.GObject Converter

-- | Type class for types which can be safely cast to t'Converter', for instance with `toConverter`.
class (SP.GObject o, O.IsDescendantOf Converter o) => IsConverter o
instance (SP.GObject o, O.IsDescendantOf Converter o) => IsConverter o

instance O.HasParentTypes Converter
type instance O.ParentTypes Converter = '[GObject.Object.Object]

-- | Cast to t'Converter', for types for which this is known to be safe. For general casts, use 'Data.GI.Base.ManagedPtr.castTo'.
toConverter :: (MIO.MonadIO m, IsConverter o) => o -> m Converter
toConverter = MIO.liftIO . B.ManagedPtr.unsafeCastTo Converter

-- | Convert t'Converter' to and from t'Data.GI.Base.GValue.GValue'. See 'Data.GI.Base.GValue.toGValue' and 'Data.GI.Base.GValue.fromGValue'.
instance B.GValue.IsGValue (Maybe Converter) where
    gvalueGType_ = c_g_converter_get_type
    gvalueSet_ gv P.Nothing = B.GValue.set_object gv (FP.nullPtr :: FP.Ptr Converter)
    gvalueSet_ gv (P.Just obj) = B.ManagedPtr.withManagedPtr obj (B.GValue.set_object gv)
    gvalueGet_ gv = do
        ptr <- B.GValue.get_object gv :: IO (FP.Ptr Converter)
        if ptr /= FP.nullPtr
        then P.Just <$> B.ManagedPtr.newObject Converter ptr
        else return P.Nothing
        
    

#if defined(ENABLE_OVERLOADING)
instance O.HasAttributeList Converter
type instance O.AttributeList Converter = ConverterAttributeList
type ConverterAttributeList = ('[ ] :: [(Symbol, DK.Type)])
#endif

#if defined(ENABLE_OVERLOADING)
#endif

#if defined(ENABLE_OVERLOADING)
type family ResolveConverterMethod (t :: Symbol) (o :: DK.Type) :: DK.Type where
    ResolveConverterMethod "bindProperty" o = GObject.Object.ObjectBindPropertyMethodInfo
    ResolveConverterMethod "bindPropertyFull" o = GObject.Object.ObjectBindPropertyFullMethodInfo
    ResolveConverterMethod "convert" o = ConverterConvertMethodInfo
    ResolveConverterMethod "convertBytes" o = ConverterConvertBytesMethodInfo
    ResolveConverterMethod "forceFloating" o = GObject.Object.ObjectForceFloatingMethodInfo
    ResolveConverterMethod "freezeNotify" o = GObject.Object.ObjectFreezeNotifyMethodInfo
    ResolveConverterMethod "getv" o = GObject.Object.ObjectGetvMethodInfo
    ResolveConverterMethod "isFloating" o = GObject.Object.ObjectIsFloatingMethodInfo
    ResolveConverterMethod "notify" o = GObject.Object.ObjectNotifyMethodInfo
    ResolveConverterMethod "notifyByPspec" o = GObject.Object.ObjectNotifyByPspecMethodInfo
    ResolveConverterMethod "ref" o = GObject.Object.ObjectRefMethodInfo
    ResolveConverterMethod "refSink" o = GObject.Object.ObjectRefSinkMethodInfo
    ResolveConverterMethod "reset" o = ConverterResetMethodInfo
    ResolveConverterMethod "runDispose" o = GObject.Object.ObjectRunDisposeMethodInfo
    ResolveConverterMethod "stealData" o = GObject.Object.ObjectStealDataMethodInfo
    ResolveConverterMethod "stealQdata" o = GObject.Object.ObjectStealQdataMethodInfo
    ResolveConverterMethod "thawNotify" o = GObject.Object.ObjectThawNotifyMethodInfo
    ResolveConverterMethod "unref" o = GObject.Object.ObjectUnrefMethodInfo
    ResolveConverterMethod "watchClosure" o = GObject.Object.ObjectWatchClosureMethodInfo
    ResolveConverterMethod "getData" o = GObject.Object.ObjectGetDataMethodInfo
    ResolveConverterMethod "getProperty" o = GObject.Object.ObjectGetPropertyMethodInfo
    ResolveConverterMethod "getQdata" o = GObject.Object.ObjectGetQdataMethodInfo
    ResolveConverterMethod "setData" o = GObject.Object.ObjectSetDataMethodInfo
    ResolveConverterMethod "setDataFull" o = GObject.Object.ObjectSetDataFullMethodInfo
    ResolveConverterMethod "setProperty" o = GObject.Object.ObjectSetPropertyMethodInfo
    ResolveConverterMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveConverterMethod t Converter, O.OverloadedMethod info Converter p) => OL.IsLabel t (Converter -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod @info
#else
    fromLabel _ = O.overloadedMethod @info
#endif

#if MIN_VERSION_base(4,13,0)
instance (info ~ ResolveConverterMethod t Converter, O.OverloadedMethod info Converter p, R.HasField t Converter p) => R.HasField t Converter p where
    getField = O.overloadedMethod @info

#endif

instance (info ~ ResolveConverterMethod t Converter, O.OverloadedMethodInfo info Converter) => OL.IsLabel t (O.MethodProxy info Converter) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.MethodProxy
#else
    fromLabel _ = O.MethodProxy
#endif

#endif

-- method Converter::convert
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "converter"
--           , argType =
--               TInterface Name { namespace = "Gio" , name = "Converter" }
--           , argCType = Just "GConverter*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GConverter." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "inbuf"
--           , argType = TCArray False (-1) 2 (TBasicType TUInt8)
--           , argCType = Just "void*"
--           , direction = DirectionIn
--           , mayBeNull = True
--           , argDoc =
--               Documentation
--                 { rawDocText =
--                     Just "the buffer\n        containing the data to convert."
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "inbuf_size"
--           , argType = TBasicType TSize
--           , argCType = Just "gsize"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "the number of bytes in @inbuf"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "outbuf"
--           , argType = TCArray False (-1) 4 (TBasicType TUInt8)
--           , argCType = Just "void*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a\n   buffer to write converted data in."
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "outbuf_size"
--           , argType = TBasicType TSize
--           , argCType = Just "gsize"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText =
--                     Just "the number of bytes in @outbuf, must be at least one"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "flags"
--           , argType =
--               TInterface Name { namespace = "Gio" , name = "ConverterFlags" }
--           , argCType = Just "GConverterFlags"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText =
--                     Just "a #GConverterFlags controlling the conversion details"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "bytes_read"
--           , argType = TBasicType TSize
--           , argCType = Just "gsize*"
--           , direction = DirectionOut
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText =
--                     Just
--                       "will be set to the number of bytes read\n   from @inbuf on success"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferEverything
--           }
--       , Arg
--           { argCName = "bytes_written"
--           , argType = TBasicType TSize
--           , argCType = Just "gsize*"
--           , direction = DirectionOut
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText =
--                     Just
--                       "will be set to the number of bytes\n   written to @outbuf on success"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferEverything
--           }
--       ]
-- Lengths: [ Arg
--              { argCName = "outbuf_size"
--              , argType = TBasicType TSize
--              , argCType = Just "gsize"
--              , direction = DirectionIn
--              , mayBeNull = False
--              , argDoc =
--                  Documentation
--                    { rawDocText =
--                        Just "the number of bytes in @outbuf, must be at least one"
--                    , sinceVersion = Nothing
--                    }
--              , argScope = ScopeTypeInvalid
--              , argClosure = -1
--              , argDestroy = -1
--              , argCallerAllocates = False
--              , argCallbackUserData = False
--              , transfer = TransferNothing
--              }
--          , Arg
--              { argCName = "inbuf_size"
--              , argType = TBasicType TSize
--              , argCType = Just "gsize"
--              , direction = DirectionIn
--              , mayBeNull = False
--              , argDoc =
--                  Documentation
--                    { rawDocText = Just "the number of bytes in @inbuf"
--                    , sinceVersion = Nothing
--                    }
--              , argScope = ScopeTypeInvalid
--              , argClosure = -1
--              , argDestroy = -1
--              , argCallerAllocates = False
--              , argCallbackUserData = False
--              , transfer = TransferNothing
--              }
--          ]
-- returnType: Just
--               (TInterface Name { namespace = "Gio" , name = "ConverterResult" })
-- throws : True
-- Skip return : False

foreign import ccall "g_converter_convert" g_converter_convert :: 
    Ptr Converter ->                        -- converter : TInterface (Name {namespace = "Gio", name = "Converter"})
    Ptr Word8 ->                            -- inbuf : TCArray False (-1) 2 (TBasicType TUInt8)
    FCT.CSize ->                            -- inbuf_size : TBasicType TSize
    Ptr Word8 ->                            -- outbuf : TCArray False (-1) 4 (TBasicType TUInt8)
    FCT.CSize ->                            -- outbuf_size : TBasicType TSize
    CUInt ->                                -- flags : TInterface (Name {namespace = "Gio", name = "ConverterFlags"})
    Ptr FCT.CSize ->                        -- bytes_read : TBasicType TSize
    Ptr FCT.CSize ->                        -- bytes_written : TBasicType TSize
    Ptr (Ptr GError) ->                     -- error
    IO CUInt

-- | This is the main operation used when converting data. It is to be called
-- multiple times in a loop, and each time it will do some work, i.e.
-- producing some output (in /@outbuf@/) or consuming some input (from /@inbuf@/) or
-- both. If its not possible to do any work an error is returned.
-- 
-- Note that a single call may not consume all input (or any input at all).
-- Also a call may produce output even if given no input, due to state stored
-- in the converter producing output.
-- 
-- If any data was either produced or consumed, and then an error happens, then
-- only the successful conversion is reported and the error is returned on the
-- next call.
-- 
-- A full conversion loop involves calling this method repeatedly, each time
-- giving it new input and space output space. When there is no more input
-- data after the data in /@inbuf@/, the flag 'GI.Gio.Flags.ConverterFlagsInputAtEnd' must be set.
-- The loop will be (unless some error happens) returning 'GI.Gio.Enums.ConverterResultConverted'
-- each time until all data is consumed and all output is produced, then
-- 'GI.Gio.Enums.ConverterResultFinished' is returned instead. Note, that 'GI.Gio.Enums.ConverterResultFinished'
-- may be returned even if 'GI.Gio.Flags.ConverterFlagsInputAtEnd' is not set, for instance
-- in a decompression converter where the end of data is detectable from the
-- data (and there might even be other data after the end of the compressed data).
-- 
-- When some data has successfully been converted /@bytesRead@/ and is set to
-- the number of bytes read from /@inbuf@/, and /@bytesWritten@/ is set to indicate
-- how many bytes was written to /@outbuf@/. If there are more data to output
-- or consume (i.e. unless the 'GI.Gio.Flags.ConverterFlagsInputAtEnd' is specified) then
-- 'GI.Gio.Enums.ConverterResultConverted' is returned, and if no more data is to be output
-- then 'GI.Gio.Enums.ConverterResultFinished' is returned.
-- 
-- On error 'GI.Gio.Enums.ConverterResultError' is returned and /@error@/ is set accordingly.
-- Some errors need special handling:
-- 
-- 'GI.Gio.Enums.IOErrorEnumNoSpace' is returned if there is not enough space
-- to write the resulting converted data, the application should
-- call the function again with a larger /@outbuf@/ to continue.
-- 
-- 'GI.Gio.Enums.IOErrorEnumPartialInput' is returned if there is not enough
-- input to fully determine what the conversion should produce,
-- and the 'GI.Gio.Flags.ConverterFlagsInputAtEnd' flag is not set. This happens for
-- example with an incomplete multibyte sequence when converting text,
-- or when a regexp matches up to the end of the input (and may match
-- further input). It may also happen when /@inbufSize@/ is zero and
-- there is no more data to produce.
-- 
-- When this happens the application should read more input and then
-- call the function again. If further input shows that there is no
-- more data call the function again with the same data but with
-- the 'GI.Gio.Flags.ConverterFlagsInputAtEnd' flag set. This may cause the conversion
-- to finish as e.g. in the regexp match case (or, to fail again with
-- 'GI.Gio.Enums.IOErrorEnumPartialInput' in e.g. a charset conversion where the
-- input is actually partial).
-- 
-- After 'GI.Gio.Interfaces.Converter.converterConvert' has returned 'GI.Gio.Enums.ConverterResultFinished' the
-- converter object is in an invalid state where its not allowed
-- to call 'GI.Gio.Interfaces.Converter.converterConvert' anymore. At this time you can only
-- free the object or call 'GI.Gio.Interfaces.Converter.converterReset' to reset it to the
-- initial state.
-- 
-- If the flag 'GI.Gio.Flags.ConverterFlagsFlush' is set then conversion is modified
-- to try to write out all internal state to the output. The application
-- has to call the function multiple times with the flag set, and when
-- the available input has been consumed and all internal state has
-- been produced then 'GI.Gio.Enums.ConverterResultFlushed' (or 'GI.Gio.Enums.ConverterResultFinished' if
-- really at the end) is returned instead of 'GI.Gio.Enums.ConverterResultConverted'.
-- This is somewhat similar to what happens at the end of the input stream,
-- but done in the middle of the data.
-- 
-- This has different meanings for different conversions. For instance
-- in a compression converter it would mean that we flush all the
-- compression state into output such that if you uncompress the
-- compressed data you get back all the input data. Doing this may
-- make the final file larger due to padding though. Another example
-- is a regexp conversion, where if you at the end of the flushed data
-- have a match, but there is also a potential longer match. In the
-- non-flushed case we would ask for more input, but when flushing we
-- treat this as the end of input and do the match.
-- 
-- Flushing is not always possible (like if a charset converter flushes
-- at a partial multibyte sequence). Converters are supposed to try
-- to produce as much output as possible and then return an error
-- (typically 'GI.Gio.Enums.IOErrorEnumPartialInput').
-- 
-- /Since: 2.24/
converterConvert ::
    (B.CallStack.HasCallStack, MonadIO m, IsConverter a) =>
    a
    -- ^ /@converter@/: a t'GI.Gio.Interfaces.Converter.Converter'.
    -> Maybe (ByteString)
    -- ^ /@inbuf@/: the buffer
    --         containing the data to convert.
    -> ByteString
    -- ^ /@outbuf@/: a
    --    buffer to write converted data in.
    -> [Gio.Flags.ConverterFlags]
    -- ^ /@flags@/: a t'GI.Gio.Flags.ConverterFlags' controlling the conversion details
    -> m ((Gio.Enums.ConverterResult, FCT.CSize, FCT.CSize))
    -- ^ __Returns:__ a t'GI.Gio.Enums.ConverterResult', 'GI.Gio.Enums.ConverterResultError' on error. /(Can throw 'Data.GI.Base.GError.GError')/
converterConvert converter inbuf outbuf flags = liftIO $ do
    let outbufSize = fromIntegral $ B.length outbuf
    let inbufSize = case inbuf of
            Nothing -> 0
            Just jInbuf -> fromIntegral $ B.length jInbuf
    converter' <- unsafeManagedPtrCastPtr converter
    maybeInbuf <- case inbuf of
        Nothing -> return FP.nullPtr
        Just jInbuf -> do
            jInbuf' <- packByteString jInbuf
            return jInbuf'
    outbuf' <- packByteString outbuf
    let flags' = gflagsToWord flags
    bytesRead <- allocMem :: IO (Ptr FCT.CSize)
    bytesWritten <- allocMem :: IO (Ptr FCT.CSize)
    onException (do
        result <- propagateGError $ g_converter_convert converter' maybeInbuf inbufSize outbuf' outbufSize flags' bytesRead bytesWritten
        let result' = (toEnum . fromIntegral) result
        bytesRead' <- peek bytesRead
        bytesWritten' <- peek bytesWritten
        touchManagedPtr converter
        freeMem maybeInbuf
        freeMem outbuf'
        freeMem bytesRead
        freeMem bytesWritten
        return (result', bytesRead', bytesWritten')
     ) (do
        freeMem maybeInbuf
        freeMem outbuf'
        freeMem bytesRead
        freeMem bytesWritten
     )

#if defined(ENABLE_OVERLOADING)
data ConverterConvertMethodInfo
instance (signature ~ (Maybe (ByteString) -> ByteString -> [Gio.Flags.ConverterFlags] -> m ((Gio.Enums.ConverterResult, FCT.CSize, FCT.CSize))), MonadIO m, IsConverter a) => O.OverloadedMethod ConverterConvertMethodInfo a signature where
    overloadedMethod = converterConvert

instance O.OverloadedMethodInfo ConverterConvertMethodInfo a where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.Gio.Interfaces.Converter.converterConvert",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-gio-2.0.38/docs/GI-Gio-Interfaces-Converter.html#v:converterConvert"
        })


#endif

-- method Converter::convert_bytes
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "converter"
--           , argType =
--               TInterface Name { namespace = "Gio" , name = "Converter" }
--           , argCType = Just "GConverter*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "the `GConverter` to use"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       , Arg
--           { argCName = "bytes"
--           , argType = TInterface Name { namespace = "GLib" , name = "Bytes" }
--           , argCType = Just "GBytes*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "the data to convert"
--                 , sinceVersion = Nothing
--                 }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Just (TInterface Name { namespace = "GLib" , name = "Bytes" })
-- throws : True
-- Skip return : False

foreign import ccall "g_converter_convert_bytes" g_converter_convert_bytes :: 
    Ptr Converter ->                        -- converter : TInterface (Name {namespace = "Gio", name = "Converter"})
    Ptr GLib.Bytes.Bytes ->                 -- bytes : TInterface (Name {namespace = "GLib", name = "Bytes"})
    Ptr (Ptr GError) ->                     -- error
    IO (Ptr GLib.Bytes.Bytes)

-- | Applies /@converter@/ to the data in /@bytes@/.
-- 
-- /Since: 2.82/
converterConvertBytes ::
    (B.CallStack.HasCallStack, MonadIO m, IsConverter a) =>
    a
    -- ^ /@converter@/: the @GConverter@ to use
    -> GLib.Bytes.Bytes
    -- ^ /@bytes@/: the data to convert
    -> m GLib.Bytes.Bytes
    -- ^ __Returns:__ A newly-allocated
    --   @GBytes@ with the converted data, or @NULL@ if an error
    --   occurred /(Can throw 'Data.GI.Base.GError.GError')/
converterConvertBytes converter bytes = liftIO $ do
    converter' <- unsafeManagedPtrCastPtr converter
    bytes' <- unsafeManagedPtrGetPtr bytes
    onException (do
        result <- propagateGError $ g_converter_convert_bytes converter' bytes'
        checkUnexpectedReturnNULL "converterConvertBytes" result
        result' <- (wrapBoxed GLib.Bytes.Bytes) result
        touchManagedPtr converter
        touchManagedPtr bytes
        return result'
     ) (do
        return ()
     )

#if defined(ENABLE_OVERLOADING)
data ConverterConvertBytesMethodInfo
instance (signature ~ (GLib.Bytes.Bytes -> m GLib.Bytes.Bytes), MonadIO m, IsConverter a) => O.OverloadedMethod ConverterConvertBytesMethodInfo a signature where
    overloadedMethod = converterConvertBytes

instance O.OverloadedMethodInfo ConverterConvertBytesMethodInfo a where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.Gio.Interfaces.Converter.converterConvertBytes",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-gio-2.0.38/docs/GI-Gio-Interfaces-Converter.html#v:converterConvertBytes"
        })


#endif

-- method Converter::reset
-- method type : OrdinaryMethod
-- Args: [ Arg
--           { argCName = "converter"
--           , argType =
--               TInterface Name { namespace = "Gio" , name = "Converter" }
--           , argCType = Just "GConverter*"
--           , direction = DirectionIn
--           , mayBeNull = False
--           , argDoc =
--               Documentation
--                 { rawDocText = Just "a #GConverter." , sinceVersion = Nothing }
--           , argScope = ScopeTypeInvalid
--           , argClosure = -1
--           , argDestroy = -1
--           , argCallerAllocates = False
--           , argCallbackUserData = False
--           , transfer = TransferNothing
--           }
--       ]
-- Lengths: []
-- returnType: Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_converter_reset" g_converter_reset :: 
    Ptr Converter ->                        -- converter : TInterface (Name {namespace = "Gio", name = "Converter"})
    IO ()

-- | Resets all internal state in the converter, making it behave
-- as if it was just created. If the converter has any internal
-- state that would produce output then that output is lost.
-- 
-- /Since: 2.24/
converterReset ::
    (B.CallStack.HasCallStack, MonadIO m, IsConverter a) =>
    a
    -- ^ /@converter@/: a t'GI.Gio.Interfaces.Converter.Converter'.
    -> m ()
converterReset converter = liftIO $ do
    converter' <- unsafeManagedPtrCastPtr converter
    g_converter_reset converter'
    touchManagedPtr converter
    return ()

#if defined(ENABLE_OVERLOADING)
data ConverterResetMethodInfo
instance (signature ~ (m ()), MonadIO m, IsConverter a) => O.OverloadedMethod ConverterResetMethodInfo a signature where
    overloadedMethod = converterReset

instance O.OverloadedMethodInfo ConverterResetMethodInfo a where
    overloadedMethodInfo = P.Just (O.ResolvedSymbolInfo {
        O.resolvedSymbolName = "GI.Gio.Interfaces.Converter.converterReset",
        O.resolvedSymbolURL = "https://hackage.haskell.org/package/gi-gio-2.0.38/docs/GI-Gio-Interfaces-Converter.html#v:converterReset"
        })


#endif

#if defined(ENABLE_OVERLOADING)
type instance O.SignalList Converter = ConverterSignalList
type ConverterSignalList = ('[ '("notify", GObject.Object.ObjectNotifySignalInfo)] :: [(Symbol, DK.Type)])

#endif


