    {-# LANGUAGE CApiFFI          #-}
    {-# LANGUAGE MagicHash        #-}
    {-# LANGUAGE Trustworthy      #-}
    {-# LANGUAGE UnliftedFFITypes #-}
    module Data.Hashable.FFI (
        -- * One shot
        unsafe_xxh3_64bit_withSeed_ptr,
        unsafe_xxh3_64bit_withSeed_ba,
        unsafe_xxh3_64bit_withSeed_u64,
        unsafe_xxh3_64bit_withSeed_u32,
        -- * Incremental
        unsafe_xxh3_sizeof_state,
        unsafe_xxh3_initState,
        unsafe_xxh3_64bit_reset_withSeed,
        unsafe_xxh3_64bit_digest,
        unsafe_xxh3_64bit_update_ptr,
        unsafe_xxh3_64bit_update_ba,
        unsafe_xxh3_64bit_update_u64,
        unsafe_xxh3_64bit_update_u32,
    ) where

    import Data.Word       (Word32, Word64, Word8)
    import Foreign.C.Types (CSize (..))
    import Foreign.Ptr     (Ptr)
    import GHC.Exts        (ByteArray#, MutableByteArray#)

    -- Note: we use unsafe FFI calls, as we expect our use case to be hashing only small data (<1kb, at most 4k).

    -------------------------------------------------------------------------------
    -- OneShot
    -------------------------------------------------------------------------------

    foreign import capi unsafe "HsXXHash.h XXH3_64bits_withSeed"
        unsafe_xxh3_64bit_withSeed_ptr :: Ptr Word8 -> CSize -> Word64 -> IO Word64

    foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_offset"
        unsafe_xxh3_64bit_withSeed_ba :: ByteArray# -> CSize -> CSize -> Word64 -> Word64

    foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_u64"
        unsafe_xxh3_64bit_withSeed_u64 :: Word64 -> Word64 -> Word64

    foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_u32"
        unsafe_xxh3_64bit_withSeed_u32 :: Word32 -> Word64 -> Word64

    -------------------------------------------------------------------------------
    -- Incremental
    -------------------------------------------------------------------------------

    -- reset and update functions return OK/Error
    -- we ignore that:
    -- * reset errors only on NULL state
    -- * update cannot even error

    foreign import capi unsafe "HsXXHash.h value hs_XXH3_sizeof_state_s"
        unsafe_xxh3_sizeof_state :: Int

    foreign import capi unsafe "HsXXHash.h XXH3_INITSTATE"
        unsafe_xxh3_initState :: MutableByteArray# s -> IO ()

    foreign import capi unsafe "HsXXHash.h XXH3_64bits_reset_withSeed"
        unsafe_xxh3_64bit_reset_withSeed :: MutableByteArray# s -> Word64 -> IO ()

    foreign import capi unsafe "HsXXHash.h XXH3_64bits_digest"
        unsafe_xxh3_64bit_digest :: MutableByteArray# s -> IO Word64

    foreign import capi unsafe "HsXXHash.h XXH3_64bits_update"
        unsafe_xxh3_64bit_update_ptr :: MutableByteArray# s -> Ptr Word8 -> CSize -> IO ()

    foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_offset"
        unsafe_xxh3_64bit_update_ba :: MutableByteArray# s -> ByteArray# -> CSize -> CSize -> IO ()

    foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_u64"
        unsafe_xxh3_64bit_update_u64 :: MutableByteArray# s -> Word64 -> IO ()

    foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_u32"
        unsafe_xxh3_64bit_update_u32 :: MutableByteArray# s -> Word32 -> IO ()