{- |
Copyright  : Will Thompson, Iñaki García Etxebarria and Jonas Platte
License    : LGPL-2.1
Maintainer : Iñaki García Etxebarria (inaki@blueleaf.cc)

An opaque structure representing a HMAC operation.
To create a new GHmac, use @/g_hmac_new()/@. To free
a GHmac, use 'GI.GLib.Structs.Hmac.hmacUnref'.

/Since: 2.30/
-}

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

module GI.GLib.Structs.Hmac
    (

-- * Exported types
    Hmac(..)                                ,
    noHmac                                  ,


 -- * Methods
-- ** getDigest #method:getDigest#

#if ENABLE_OVERLOADING
    HmacGetDigestMethodInfo                 ,
#endif
    hmacGetDigest                           ,


-- ** getString #method:getString#

#if ENABLE_OVERLOADING
    HmacGetStringMethodInfo                 ,
#endif
    hmacGetString                           ,


-- ** unref #method:unref#

#if ENABLE_OVERLOADING
    HmacUnrefMethodInfo                     ,
#endif
    hmacUnref                               ,


-- ** update #method:update#

#if ENABLE_OVERLOADING
    HmacUpdateMethodInfo                    ,
#endif
    hmacUpdate                              ,




    ) 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.ManagedPtr as B.ManagedPtr
import qualified Data.GI.Base.GClosure as B.GClosure
import qualified Data.GI.Base.GError as B.GError
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.Text as T
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


-- | Memory-managed wrapper type.
newtype Hmac = Hmac (ManagedPtr Hmac)
-- XXX Wrapping a foreign struct/union with no known destructor or size, leak?
instance WrappedPtr Hmac where
    wrappedPtrCalloc = return nullPtr
    wrappedPtrCopy = return
    wrappedPtrFree = Nothing

-- | A convenience alias for `Nothing` :: `Maybe` `Hmac`.
noHmac :: Maybe Hmac
noHmac = Nothing


#if ENABLE_OVERLOADING
instance O.HasAttributeList Hmac
type instance O.AttributeList Hmac = HmacAttributeList
type HmacAttributeList = ('[ ] :: [(Symbol, *)])
#endif

-- method Hmac::get_digest
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "hmac", argType = TInterface (Name {namespace = "GLib", name = "Hmac"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GHmac", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "buffer", argType = TCArray False (-1) 2 (TBasicType TUInt8), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "output buffer", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "digest_len", argType = TBasicType TUInt64, direction = DirectionInout, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an inout parameter. The caller initializes it to the\n  size of @buffer. After the call it contains the length of the digest", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
-- Lengths : [Arg {argCName = "digest_len", argType = TBasicType TUInt64, direction = DirectionInout, mayBeNull = False, argDoc = Documentation {rawDocText = Just "an inout parameter. The caller initializes it to the\n  size of @buffer. After the call it contains the length of the digest", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferEverything}]
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_hmac_get_digest" g_hmac_get_digest ::
    Ptr Hmac ->                             -- hmac : TInterface (Name {namespace = "GLib", name = "Hmac"})
    Ptr Word8 ->                            -- buffer : TCArray False (-1) 2 (TBasicType TUInt8)
    Ptr Word64 ->                           -- digest_len : TBasicType TUInt64
    IO ()

{- |
Gets the digest from /@checksum@/ as a raw binary array and places it
into /@buffer@/. The size of the digest depends on the type of checksum.

Once this function has been called, the 'GI.GLib.Structs.Hmac.Hmac' is closed and can
no longer be updated with 'GI.GLib.Structs.Checksum.checksumUpdate'.

/Since: 2.30/
-}
hmacGetDigest ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Hmac
    {- ^ /@hmac@/: a 'GI.GLib.Structs.Hmac.Hmac' -}
    -> ByteString
    {- ^ /@buffer@/: output buffer -}
    -> m ()
hmacGetDigest hmac buffer = liftIO $ do
    let digestLen = fromIntegral $ B.length buffer
    hmac' <- unsafeManagedPtrGetPtr hmac
    buffer' <- packByteString buffer
    digestLen' <- allocMem :: IO (Ptr Word64)
    poke digestLen' digestLen
    g_hmac_get_digest hmac' buffer' digestLen'
    digestLen'' <- peek digestLen'
    touchManagedPtr hmac
    freeMem buffer'
    freeMem digestLen'
    return ()

#if ENABLE_OVERLOADING
data HmacGetDigestMethodInfo
instance (signature ~ (ByteString -> m ()), MonadIO m) => O.MethodInfo HmacGetDigestMethodInfo Hmac signature where
    overloadedMethod _ = hmacGetDigest

#endif

-- method Hmac::get_string
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "hmac", argType = TInterface (Name {namespace = "GLib", name = "Hmac"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GHmac", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Just (TBasicType TUTF8)
-- throws : False
-- Skip return : False

foreign import ccall "g_hmac_get_string" g_hmac_get_string ::
    Ptr Hmac ->                             -- hmac : TInterface (Name {namespace = "GLib", name = "Hmac"})
    IO CString

{- |
Gets the HMAC as an hexadecimal string.

Once this function has been called the 'GI.GLib.Structs.Hmac.Hmac' can no longer be
updated with 'GI.GLib.Structs.Hmac.hmacUpdate'.

The hexadecimal characters will be lower case.

/Since: 2.30/
-}
hmacGetString ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Hmac
    {- ^ /@hmac@/: a 'GI.GLib.Structs.Hmac.Hmac' -}
    -> m T.Text
    {- ^ __Returns:__ the hexadecimal representation of the HMAC. The
  returned string is owned by the HMAC and should not be modified
  or freed. -}
hmacGetString hmac = liftIO $ do
    hmac' <- unsafeManagedPtrGetPtr hmac
    result <- g_hmac_get_string hmac'
    checkUnexpectedReturnNULL "hmacGetString" result
    result' <- cstringToText result
    touchManagedPtr hmac
    return result'

#if ENABLE_OVERLOADING
data HmacGetStringMethodInfo
instance (signature ~ (m T.Text), MonadIO m) => O.MethodInfo HmacGetStringMethodInfo Hmac signature where
    overloadedMethod _ = hmacGetString

#endif

-- method Hmac::unref
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "hmac", argType = TInterface (Name {namespace = "GLib", name = "Hmac"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GHmac", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : []
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_hmac_unref" g_hmac_unref ::
    Ptr Hmac ->                             -- hmac : TInterface (Name {namespace = "GLib", name = "Hmac"})
    IO ()

{- |
Atomically decrements the reference count of /@hmac@/ by one.

If the reference count drops to 0, all keys and values will be
destroyed, and all memory allocated by the hash table is released.
This function is MT-safe and may be called from any thread.
Frees the memory allocated for /@hmac@/.

/Since: 2.30/
-}
hmacUnref ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Hmac
    {- ^ /@hmac@/: a 'GI.GLib.Structs.Hmac.Hmac' -}
    -> m ()
hmacUnref hmac = liftIO $ do
    hmac' <- unsafeManagedPtrGetPtr hmac
    g_hmac_unref hmac'
    touchManagedPtr hmac
    return ()

#if ENABLE_OVERLOADING
data HmacUnrefMethodInfo
instance (signature ~ (m ()), MonadIO m) => O.MethodInfo HmacUnrefMethodInfo Hmac signature where
    overloadedMethod _ = hmacUnref

#endif

-- method Hmac::update
-- method type : OrdinaryMethod
-- Args : [Arg {argCName = "hmac", argType = TInterface (Name {namespace = "GLib", name = "Hmac"}), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "a #GHmac", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "data", argType = TCArray False (-1) 2 (TBasicType TUInt8), direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "buffer used to compute the checksum", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing},Arg {argCName = "length", argType = TBasicType TInt64, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "size of the buffer, or -1 if it is a nul-terminated string", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- Lengths : [Arg {argCName = "length", argType = TBasicType TInt64, direction = DirectionIn, mayBeNull = False, argDoc = Documentation {rawDocText = Just "size of the buffer, or -1 if it is a nul-terminated string", sinceVersion = Nothing}, argScope = ScopeTypeInvalid, argClosure = -1, argDestroy = -1, argCallerAllocates = False, transfer = TransferNothing}]
-- returnType : Nothing
-- throws : False
-- Skip return : False

foreign import ccall "g_hmac_update" g_hmac_update ::
    Ptr Hmac ->                             -- hmac : TInterface (Name {namespace = "GLib", name = "Hmac"})
    Ptr Word8 ->                            -- data : TCArray False (-1) 2 (TBasicType TUInt8)
    Int64 ->                                -- length : TBasicType TInt64
    IO ()

{- |
Feeds /@data@/ into an existing 'GI.GLib.Structs.Hmac.Hmac'.

The HMAC must still be open, that is 'GI.GLib.Structs.Hmac.hmacGetString' or
'GI.GLib.Structs.Hmac.hmacGetDigest' must not have been called on /@hmac@/.

/Since: 2.30/
-}
hmacUpdate ::
    (B.CallStack.HasCallStack, MonadIO m) =>
    Hmac
    {- ^ /@hmac@/: a 'GI.GLib.Structs.Hmac.Hmac' -}
    -> ByteString
    {- ^ /@data@/: buffer used to compute the checksum -}
    -> m ()
hmacUpdate hmac data_ = liftIO $ do
    let length_ = fromIntegral $ B.length data_
    hmac' <- unsafeManagedPtrGetPtr hmac
    data_' <- packByteString data_
    g_hmac_update hmac' data_' length_
    touchManagedPtr hmac
    freeMem data_'
    return ()

#if ENABLE_OVERLOADING
data HmacUpdateMethodInfo
instance (signature ~ (ByteString -> m ()), MonadIO m) => O.MethodInfo HmacUpdateMethodInfo Hmac signature where
    overloadedMethod _ = hmacUpdate

#endif

#if ENABLE_OVERLOADING
type family ResolveHmacMethod (t :: Symbol) (o :: *) :: * where
    ResolveHmacMethod "unref" o = HmacUnrefMethodInfo
    ResolveHmacMethod "update" o = HmacUpdateMethodInfo
    ResolveHmacMethod "getDigest" o = HmacGetDigestMethodInfo
    ResolveHmacMethod "getString" o = HmacGetStringMethodInfo
    ResolveHmacMethod l o = O.MethodResolutionFailed l o

instance (info ~ ResolveHmacMethod t Hmac, O.MethodInfo info Hmac p) => OL.IsLabel t (Hmac -> p) where
#if MIN_VERSION_base(4,10,0)
    fromLabel = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#else
    fromLabel _ = O.overloadedMethod (O.MethodProxy :: O.MethodProxy info)
#endif

#endif