    {-# LANGUAGE CPP #-}

    #if __GLASGOW_HASKELL__ <= 708
    {-# LANGUAGE Trustworthy #-}
    #else
    {-# LANGUAGE Safe #-}
    #endif

    module System.Log.FastLogger.IO where

    import Data.ByteString.Builder.Extra (Next (..))
    import qualified Data.ByteString.Builder.Extra as BBE
    import Foreign.ForeignPtr (withForeignPtr)
    import Foreign.Marshal.Alloc (free, mallocBytes)
    import Foreign.Ptr (Ptr, plusPtr)

    import System.Log.FastLogger.Imports
    import System.Log.FastLogger.LogStr

    type Buffer = Ptr Word8

    -- | The type for buffer size of each core.
    type BufSize = Int

    -- | The default buffer size (4,096 bytes).
    defaultBufSize :: BufSize
    defaultBufSize :: BufSize
    defaultBufSize = BufSize
    4096

    getBuffer :: BufSize -> IO Buffer
    getBuffer :: BufSize -> IO Buffer
    getBuffer = BufSize -> IO Buffer
    forall a. BufSize -> IO (Ptr a)
    mallocBytes

    freeBuffer :: Buffer -> IO ()
    freeBuffer :: Buffer -> IO ()
    freeBuffer = Buffer -> IO ()
    forall a. Ptr a -> IO ()
    free

    toBufIOWith :: Buffer -> BufSize -> (Buffer -> Int -> IO ()) -> Builder -> IO ()
    toBufIOWith :: Buffer
    -> BufSize -> (Buffer -> BufSize -> IO ()) -> Builder -> IO ()
    toBufIOWith Buffer
    buf BufSize
    size Buffer -> BufSize -> IO ()
    io Builder
    builder = BufferWriter -> IO ()
    loop (BufferWriter -> IO ()) -> BufferWriter -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Builder -> BufferWriter
    BBE.runBuilder Builder
    builder
      where
        loop :: BufferWriter -> IO ()
    loop BufferWriter
    writer = do
            (len, next) <- BufferWriter
    writer Buffer
    buf BufSize
    size
            io buf len
            case next of
                Next
    Done -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                More BufSize
    minSize BufferWriter
    writer'
                    | BufSize
    size BufSize -> BufSize -> Bool
    forall a. Ord a => a -> a -> Bool
    < BufSize
    minSize -> [Char] -> IO ()
    forall a. HasCallStack => [Char] -> a
    error [Char]
    "toBufIOWith: More: minSize"
                    | Bool
    otherwise -> BufferWriter -> IO ()
    loop BufferWriter
    writer'
                Chunk (PS ForeignPtr Word8
    fptr BufSize
    off BufSize
    siz) BufferWriter
    writer' ->
                    ForeignPtr Word8 -> (Buffer -> IO ()) -> IO ()
    forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
    withForeignPtr ForeignPtr Word8
    fptr ((Buffer -> IO ()) -> IO ()) -> (Buffer -> IO ()) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ \Buffer
    ptr -> Buffer -> BufSize -> IO ()
    io (Buffer
    ptr Buffer -> BufSize -> Buffer
    forall a b. Ptr a -> BufSize -> Ptr b
    `plusPtr` BufSize
    off) BufSize
    siz IO () -> IO () -> IO ()
    forall a b. IO a -> IO b -> IO b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> BufferWriter -> IO ()
    loop BufferWriter
    writer'