    -- |
    -- Module      :  System.AtomicWrite.Writer.ByteStringBuilder
    -- Copyright   :  © 2015-2019 Stack Builders Inc.
    -- License     :  MIT
    --
    -- Maintainer  :  Stack Builders <hackage@stackbuilders.com>
    -- Stability   :  experimental
    -- Portability :  portable
    --
    -- Provides functionality to dump the contents of a ByteStringBuilder
    -- to a file.

    module System.AtomicWrite.Writer.ByteStringBuilder (atomicWriteFile, atomicWriteFileWithMode) where

    import           System.AtomicWrite.Internal (closeAndRename, maybeSetFileMode,
                                                  tempFileFor)

    import           Data.ByteString.Builder     (Builder, hPutBuilder)

    import           GHC.IO.Handle               (BufferMode (BlockBuffering),
                                                  hSetBinaryMode, hSetBuffering)

    import           System.Posix.Types          (FileMode)

    -- | Creates or modifies a file atomically on POSIX-compliant
    -- systems while preserving permissions.
    atomicWriteFile ::
      FilePath    -- ^ The path where the file will be updated or created
      -> Builder  -- ^ The content to write to the file
      -> IO ()
    atomicWriteFile :: FilePath -> Builder -> IO ()
    atomicWriteFile =
      Maybe FileMode -> FilePath -> Builder -> IO ()
    atomicWriteFileMaybeMode Maybe FileMode
    forall a. Maybe a
    Nothing

    -- | Creates or modifies a file atomically on POSIX-compliant
    -- systems and updates permissions.
    atomicWriteFileWithMode ::
      FileMode
      -> FilePath    -- ^ The path where the file will be updated or created
      -> Builder  -- ^ The content to write to the file
      -> IO ()
    atomicWriteFileWithMode :: FileMode -> FilePath -> Builder -> IO ()
    atomicWriteFileWithMode FileMode
    mode =
      Maybe FileMode -> FilePath -> Builder -> IO ()
    atomicWriteFileMaybeMode (Maybe FileMode -> FilePath -> Builder -> IO ())
    -> Maybe FileMode -> FilePath -> Builder -> IO ()
    forall a b. (a -> b) -> a -> b
    $ FileMode -> Maybe FileMode
    forall a. a -> Maybe a
    Just FileMode
    mode

    -- Helper function
    atomicWriteFileMaybeMode ::
      Maybe FileMode
      -> FilePath    -- ^ The path where the file will be updated or created
      -> Builder  -- ^ The content to write to the file
      -> IO ()
    atomicWriteFileMaybeMode :: Maybe FileMode -> FilePath -> Builder -> IO ()
    atomicWriteFileMaybeMode Maybe FileMode
    mmode FilePath
    path Builder
    builder = do
      (temppath, h) <- FilePath -> IO (FilePath, Handle)
    tempFileFor FilePath
    path

      -- Recommendations for binary and buffering are from the
      -- Data.ByteString.Builder docs:
      -- http://hackage.haskell.org/package/bytestring-0.10.2.0/docs/Data-ByteString-Builder.html#v:hPutBuilder
      hSetBinaryMode h True
      hSetBuffering h (BlockBuffering Nothing)

      hPutBuilder h builder

      closeAndRename h temppath path

      -- set new permissions if a FileMode was provided
      maybeSetFileMode path mmode