    -- | Unlifted "System.IO".
    --
    -- @since 0.1.0.0
    module UnliftIO.IO
      ( IOMode (..)
      , Handle
      , IO.stdin
      , IO.stdout
      , IO.stderr
      , withFile
      , withBinaryFile
      , hClose
      , hFlush
      , hFileSize
      , hSetFileSize
      , hIsEOF
      , IO.BufferMode (..)
      , hSetBuffering
      , hGetBuffering
      , hSeek
      , IO.SeekMode
      , hTell
      , hIsOpen
      , hIsClosed
      , hIsReadable
      , hIsWritable
      , hIsSeekable
      , hIsTerminalDevice
      , hSetEcho
      , hGetEcho
      , hWaitForInput
      , hReady
      , getMonotonicTime
      ) where

    import qualified System.IO as IO
    import System.IO (Handle, IOMode (..))
    import Control.Monad.IO.Unlift

    import System.IO.Unsafe (unsafePerformIO)

    -- | Unlifted version of 'IO.withFile'.
    --
    -- @since 0.1.0.0
    withFile :: MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m a) -> m a
    withFile fp mode inner = withRunInIO $ \run -> IO.withFile fp mode $ run . inner

    -- | Unlifted version of 'IO.withBinaryFile'.
    --
    -- @since 0.1.0.0
    withBinaryFile :: MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m a) -> m a
    withBinaryFile fp mode inner = withRunInIO $ \run -> IO.withBinaryFile fp mode $ run . inner

    -- | Lifted version of 'IO.hClose'
    --
    -- @since 0.2.1.0
    hClose :: MonadIO m => Handle -> m ()
    hClose = liftIO . IO.hClose

    -- | Lifted version of 'IO.hFlush'
    --
    -- @since 0.2.1.0
    hFlush :: MonadIO m => Handle -> m ()
    hFlush = liftIO . IO.hFlush

    -- | Lifted version of 'IO.hFileSize'
    --
    -- @since 0.2.1.0
    hFileSize :: MonadIO m => Handle -> m Integer
    hFileSize = liftIO . IO.hFileSize

    -- | Lifted version of 'IO.hSetFileSize'
    --
    -- @since 0.2.1.0
    hSetFileSize :: MonadIO m => Handle -> Integer -> m ()
    hSetFileSize h = liftIO . IO.hSetFileSize h

    -- | Lifted version of 'IO.hIsEOF'
    --
    -- @since 0.2.1.0
    hIsEOF :: MonadIO m => Handle -> m Bool
    hIsEOF = liftIO . IO.hIsEOF

    -- | Lifted version of 'IO.hSetBuffering'
    --
    -- @since 0.2.1.0
    hSetBuffering :: MonadIO m => Handle -> IO.BufferMode -> m ()
    hSetBuffering h = liftIO . IO.hSetBuffering h

    -- | Lifted version of 'IO.hGetBuffering'
    --
    -- @since 0.2.1.0
    hGetBuffering :: MonadIO m => Handle -> m IO.BufferMode
    hGetBuffering = liftIO . IO.hGetBuffering

    -- | Lifted version of 'IO.hSeek'
    --
    -- @since 0.2.1.0
    hSeek :: MonadIO m => Handle -> IO.SeekMode -> Integer -> m ()
    hSeek h s = liftIO . IO.hSeek h s

    -- | Lifted version of 'IO.hTell'
    --
    -- @since 0.2.1.0
    hTell :: MonadIO m => Handle -> m Integer
    hTell = liftIO . IO.hTell

    -- | Lifted version of 'IO.hIsOpen'
    --
    -- @since 0.2.1.0
    hIsOpen :: MonadIO m => Handle -> m Bool
    hIsOpen = liftIO . IO.hIsOpen

    -- | Lifted version of 'IO.hIsClosed'
    --
    -- @since 0.2.1.0
    hIsClosed :: MonadIO m => Handle -> m Bool
    hIsClosed = liftIO . IO.hIsClosed

    -- | Lifted version of 'IO.hIsReadable'
    --
    -- @since 0.2.1.0
    hIsReadable :: MonadIO m => Handle -> m Bool
    hIsReadable = liftIO . IO.hIsReadable

    -- | Lifted version of 'IO.hIsWritable'
    --
    -- @since 0.2.1.0
    hIsWritable :: MonadIO m => Handle -> m Bool
    hIsWritable = liftIO . IO.hIsWritable

    -- | Lifted version of 'IO.hIsSeekable'
    --
    -- @since 0.2.1.0
    hIsSeekable :: MonadIO m => Handle -> m Bool
    hIsSeekable = liftIO . IO.hIsSeekable

    -- | Lifted version of 'IO.hIsTerminalDevice'
    --
    -- @since 0.2.1.0
    hIsTerminalDevice :: MonadIO m => Handle -> m Bool
    hIsTerminalDevice = liftIO . IO.hIsTerminalDevice

    -- | Lifted version of 'IO.hSetEcho'
    --
    -- @since 0.2.1.0
    hSetEcho :: MonadIO m => Handle -> Bool -> m ()
    hSetEcho h = liftIO . IO.hSetEcho h

    -- | Lifted version of 'IO.hGetEcho'
    --
    -- @since 0.2.1.0
    hGetEcho :: MonadIO m => Handle -> m Bool
    hGetEcho = liftIO . IO.hGetEcho

    -- | Lifted version of 'IO.hWaitForInput'
    --
    -- @since 0.2.1.0
    hWaitForInput :: MonadIO m => Handle -> Int -> m Bool
    hWaitForInput h = liftIO . IO.hWaitForInput h

    -- | Lifted version of 'IO.hReady'
    --
    -- @since 0.2.1.0
    hReady :: MonadIO m => Handle -> m Bool
    hReady = liftIO . IO.hReady

    -- | Get the number of seconds which have passed since an arbitrary starting
    -- time, useful for calculating runtime in a program.
    --
    -- @since 0.2.3.0
    getMonotonicTime :: MonadIO m => m Double
    getMonotonicTime = liftIO $ initted `seq` getMonotonicTime'

    -- | Set up time measurement.
    foreign import ccall unsafe "unliftio_inittime" initializeTime :: IO ()

    initted :: ()
    initted = unsafePerformIO initializeTime
    {-# NOINLINE initted #-}

    foreign import ccall unsafe "unliftio_gettime" getMonotonicTime' :: IO Double