{-# LANGUAGE CPP                        #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}

-- | This module is a top-level convenience module which re-exports most of the
-- @io-streams@ library.
--
-- It is recommended to import this module qualified, as follows:
--
-- @
-- import           "System.IO.Streams" ('Generator', 'InputStream', 'OutputStream')
-- import qualified "System.IO.Streams" as Streams
-- @
--
-- For an in-depth tutorial on how to use @io-streams@, please see the
-- "System.IO.Streams.Tutorial" module.
--
-- Is there a function missing from this library? Interested in contributing?
-- Send a pull request to <http://github.com/snapframework/io-streams>.
module System.IO.Streams
 ( -- * Stream types
   InputStream
 , OutputStream


   -- ** A note about resource acquisition\/release semantics
   -- $resource

   -- * Creating streams
 , makeInputStream
 , makeOutputStream

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

   -- * Connecting streams together
 , connect
 , connectTo
 , supply
 , supplyTo
 , appendInputStream
 , concatInputStreams

   -- * Thread safety \/ concurrency
 , lockingInputStream
 , lockingOutputStream

   -- * Utility streams
 , nullInput
 , nullOutput

    -- * Generator monad
    -- $generator
  , Generator
  , fromGenerator
  , yield

   -- * Batteries included
 , module System.IO.Streams.Builder
 , module System.IO.Streams.ByteString
 , module System.IO.Streams.Combinators
 , module System.IO.Streams.Handle
 , module System.IO.Streams.File
 , module System.IO.Streams.List
#ifdef ENABLE_NETWORK
 , module System.IO.Streams.Network
#endif
 , module System.IO.Streams.Process
 , module System.IO.Streams.Text
 , module System.IO.Streams.Vector
#ifdef ENABLE_ZLIB
 , module System.IO.Streams.Zlib
#endif
 ) where

------------------------------------------------------------------------------
import           Prelude                       ()

------------------------------------------------------------------------------
import           System.IO.Streams.Internal

import           System.IO.Streams.Builder
import           System.IO.Streams.ByteString
import           System.IO.Streams.Combinators
import           System.IO.Streams.File
import           System.IO.Streams.Handle
import           System.IO.Streams.List
#ifdef ENABLE_NETWORK
import           System.IO.Streams.Network
#endif
import           System.IO.Streams.Process
import           System.IO.Streams.Text
import           System.IO.Streams.Vector
#ifdef ENABLE_ZLIB
import           System.IO.Streams.Zlib
#endif

------------------------------------------------------------------------------
-- $generator
-- #generator#
--
-- The 'Generator' monad makes it easier for you to define more complicated
-- 'InputStream's. Generators have a couple of basic features:
--
-- 'Generator' is a 'MonadIO', so you can run IO actions from within it using
-- 'liftIO':
--
-- @
-- foo :: 'Generator' r a
-- foo = 'liftIO' fireTheMissiles
-- @
--
-- 'Generator' has a 'yield' function:
--
-- @
-- 'yield' :: r -> 'Generator' r ()
-- @
--
-- A call to \"'yield' @x@\" causes \"'Just' @x@\" to appear when reading the
-- 'InputStream'. Finally, 'Generator' comes with a function to turn a
-- 'Generator' into an 'InputStream':
--
-- @
-- 'fromGenerator' :: 'Generator' r a -> 'IO' ('InputStream' r)
-- @
--
-- Once the 'Generator' action finishes, 'fromGenerator' will cause an
-- end-of-stream 'Nothing' marker to appear at the output. Example:
--
-- @
-- ghci> (Streams.'fromGenerator' $ 'Control.Monad.sequence' $ 'Prelude.map' Streams.'yield' [1..5::Int]) >>= Streams.'toList'
-- [1,2,3,4,5]
-- @


------------------------------------------------------------------------------
-- $resource
-- #resource#
--
-- In general, the convention within this library is that input and output
-- streams do not deal with resource acquisition\/release semantics, with rare
-- exceptions like 'System.IO.Streams.withFileAsInput'. For example, sending
-- \"end-of-stream\" to an 'OutputStream' wrapped around a 'System.IO.Handle'
-- doesn't cause the handle to be closed. You can think of streams as little
-- state machines that are attached to the underlying resources, and the
-- finalization\/release of these resources is up to you.
--
-- This means that you can use standard Haskell idioms like
-- 'Control.Exception.bracket' to handle resource acquisition and cleanup in an
-- exception-safe way.
--