{-# LANGUAGE BlockArguments #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnliftedFFITypes #-}

{- | Compress a contiguous sequence of bytes into a single LZ4 block.
These functions do not perform any framing.
-}
module Lz4.Internal
  ( requiredBufferSize
  , c_hs_compress_HC
  ) where

import Control.Monad.ST (runST)
import Control.Monad.ST.Run (runByteArrayST)
import Data.Bytes.Types (Bytes (Bytes))
import Data.Primitive (ByteArray (..), MutableByteArray (..))
import GHC.Exts (ByteArray#, MutableByteArray#)
import GHC.IO (unsafeIOToST)
import GHC.ST (ST (ST))

import qualified Control.Exception
import qualified Data.Primitive as PM
import qualified GHC.Exts as Exts

{- | Copied from the @LZ4_COMPRESSBOUND@ macro lz4.h to avoid using
FFI for simple arithmetic. Make sure this stays in sync with the macro.
-}
requiredBufferSize :: Int -> Int
requiredBufferSize :: Int -> Int
requiredBufferSize Int
s = Int
s Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int -> Int -> Int
forall a. Integral a => a -> a -> a
div Int
s Int
255) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
16

foreign import ccall unsafe "hs_compress_HC"
  c_hs_compress_HC ::
    ByteArray# -> -- Source
    Int -> -- Source offset
    MutableByteArray# s -> -- Destination
    Int -> -- Destination offset
    Int -> -- Input size
    Int -> -- Destination capacity
    Int -> -- Compression level
    IO Int -- Result length