module UnliftIO.Streams
  ( -- * Stream types
    InputStream
  , OutputStream

    -- * Creating streams
  , makeInputStream
  , makeOutputStream

    -- * Primitive stream operations
  , read
  , unRead
  , peek
  , write
  , writeTo
  , atEOF

    -- * Utility streams

  , nullInput
  , nullOutput

    -- * Batteries included
  , module UnliftIO.Streams.ByteString
  , module UnliftIO.Streams.Combinators
  , module UnliftIO.Streams.File
  , module UnliftIO.Streams.List
  , module UnliftIO.Streams.Text
  ) where

import           Control.Monad.IO.Unlift (MonadUnliftIO, liftIO, withRunInIO)
import           Prelude hiding (read)
import           System.IO.Streams (InputStream, OutputStream)
import qualified System.IO.Streams as S
import           UnliftIO.Streams.Combinators
import           UnliftIO.Streams.ByteString
import           UnliftIO.Streams.File
import           UnliftIO.Streams.List
import           UnliftIO.Streams.Text

{-# INLINE makeInputStream #-}
makeInputStream :: MonadUnliftIO m => m (Maybe a) -> m (InputStream a)
makeInputStream :: m (Maybe a) -> m (InputStream a)
makeInputStream m (Maybe a)
f = ((forall a. m a -> IO a) -> IO (InputStream a))
-> m (InputStream a)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO (InputStream a))
 -> m (InputStream a))
-> ((forall a. m a -> IO a) -> IO (InputStream a))
-> m (InputStream a)
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io -> IO (Maybe a) -> IO (InputStream a)
forall a. IO (Maybe a) -> IO (InputStream a)
S.makeInputStream (m (Maybe a) -> IO (Maybe a)
forall a. m a -> IO a
io (m (Maybe a) -> IO (Maybe a)) -> m (Maybe a) -> IO (Maybe a)
forall a b. (a -> b) -> a -> b
$ m (Maybe a)
f)

{-# INLINE makeOutputStream #-}
makeOutputStream :: MonadUnliftIO m => (Maybe a -> m ()) -> m (OutputStream a)
makeOutputStream :: (Maybe a -> m ()) -> m (OutputStream a)
makeOutputStream Maybe a -> m ()
f = ((forall a. m a -> IO a) -> IO (OutputStream a))
-> m (OutputStream a)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO (OutputStream a))
 -> m (OutputStream a))
-> ((forall a. m a -> IO a) -> IO (OutputStream a))
-> m (OutputStream a)
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
io -> (Maybe a -> IO ()) -> IO (OutputStream a)
forall a. (Maybe a -> IO ()) -> IO (OutputStream a)
S.makeOutputStream (m () -> IO ()
forall a. m a -> IO a
io (m () -> IO ()) -> (Maybe a -> m ()) -> Maybe a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe a -> m ()
f)

{-# INLINE peek #-}
peek :: MonadUnliftIO m => InputStream a -> m (Maybe a)
peek :: InputStream a -> m (Maybe a)
peek InputStream a
as = IO (Maybe a) -> m (Maybe a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe a) -> m (Maybe a)) -> IO (Maybe a) -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ InputStream a -> IO (Maybe a)
forall a. InputStream a -> IO (Maybe a)
S.peek InputStream a
as

{-# INLINE read #-}
read :: MonadUnliftIO m => InputStream a -> m (Maybe a)
read :: InputStream a -> m (Maybe a)
read InputStream a
as = IO (Maybe a) -> m (Maybe a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Maybe a) -> m (Maybe a)) -> IO (Maybe a) -> m (Maybe a)
forall a b. (a -> b) -> a -> b
$ InputStream a -> IO (Maybe a)
forall a. InputStream a -> IO (Maybe a)
S.read InputStream a
as

{-# INLINE unRead #-}
unRead :: MonadUnliftIO m => a -> InputStream a -> m ()
unRead :: a -> InputStream a -> m ()
unRead a
a InputStream a
as = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ a -> InputStream a -> IO ()
forall a. a -> InputStream a -> IO ()
S.unRead a
a InputStream a
as

{-# INLINE write #-}
write :: MonadUnliftIO m => Maybe a -> OutputStream a -> m ()
write :: Maybe a -> OutputStream a -> m ()
write Maybe a
a OutputStream a
as = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ Maybe a -> OutputStream a -> IO ()
forall a. Maybe a -> OutputStream a -> IO ()
S.write Maybe a
a OutputStream a
as

{-# INLINE writeTo #-}
writeTo :: MonadUnliftIO m => OutputStream a -> Maybe a -> m ()
writeTo :: OutputStream a -> Maybe a -> m ()
writeTo OutputStream a
as Maybe a
a = IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ OutputStream a -> Maybe a -> IO ()
forall a. OutputStream a -> Maybe a -> IO ()
S.writeTo OutputStream a
as Maybe a
a

{-# INLINE atEOF #-}
atEOF :: MonadUnliftIO m => InputStream a -> m Bool
atEOF :: InputStream a -> m Bool
atEOF InputStream a
as = IO Bool -> m Bool
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> m Bool) -> IO Bool -> m Bool
forall a b. (a -> b) -> a -> b
$ InputStream a -> IO Bool
forall a. InputStream a -> IO Bool
S.atEOF InputStream a
as

{-# INLINE nullInput #-}
nullInput :: MonadUnliftIO m => m (InputStream a)
nullInput :: m (InputStream a)
nullInput = IO (InputStream a) -> m (InputStream a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (InputStream a) -> m (InputStream a))
-> IO (InputStream a) -> m (InputStream a)
forall a b. (a -> b) -> a -> b
$ IO (InputStream a)
forall a. IO (InputStream a)
S.nullInput

{-# INLINE nullOutput #-}
nullOutput :: MonadUnliftIO m => m (OutputStream a)
nullOutput :: m (OutputStream a)
nullOutput = IO (OutputStream a) -> m (OutputStream a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (OutputStream a) -> m (OutputStream a))
-> IO (OutputStream a) -> m (OutputStream a)
forall a b. (a -> b) -> a -> b
$ IO (OutputStream a)
forall a. IO (OutputStream a)
S.nullOutput