Blame Network/Stream.hs

Packit acf257
-----------------------------------------------------------------------------
Packit acf257
-- |
Packit acf257
-- Module      :  Network.Stream
Packit acf257
-- Copyright   :  See LICENSE file
Packit acf257
-- License     :  BSD
Packit acf257
--
Packit acf257
-- Maintainer  :  Ganesh Sittampalam <ganesh@earth.li>
Packit acf257
-- Stability   :  experimental
Packit acf257
-- Portability :  non-portable (not tested)
Packit acf257
--
Packit acf257
-- An library for creating abstract streams. Originally part of Gray's\/Bringert's
Packit acf257
-- HTTP module.
Packit acf257
--
Packit acf257
-- * Changes by Robin Bate Boerop <robin@bateboerop.name>:
Packit acf257
--      - Removed unnecessary import statements.
Packit acf257
--      - Moved Debug code to StreamDebugger.hs
Packit acf257
--      - Moved Socket-related code to StreamSocket.hs.
Packit acf257
--
Packit acf257
-- * Changes by Simon Foster:
Packit acf257
--      - Split Network.HTTPmodule up into to separate
Packit acf257
--        Network.[Stream,TCP,HTTP] modules
Packit acf257
-----------------------------------------------------------------------------
Packit acf257
module Network.Stream
Packit acf257
   ( Stream(..)
Packit acf257
   , ConnError(..)
Packit acf257
   , Result
Packit acf257
   , bindE
Packit acf257
   , fmapE
Packit acf257
Packit acf257
   , failParse -- :: String -> Result a
Packit acf257
   , failWith  -- :: ConnError -> Result a
Packit acf257
   , failMisc  -- :: String -> Result a
Packit acf257
   ) where
Packit acf257
Packit acf257
import Control.Monad.Error
Packit acf257
Packit acf257
data ConnError 
Packit acf257
 = ErrorReset 
Packit acf257
 | ErrorClosed
Packit acf257
 | ErrorParse String
Packit acf257
 | ErrorMisc String
Packit acf257
   deriving(Show,Eq)
Packit acf257
Packit acf257
instance Error ConnError where
Packit acf257
  noMsg = strMsg "unknown error"
Packit acf257
  strMsg x = ErrorMisc x
Packit acf257
Packit acf257
-- in GHC 7.0 the Monad instance for Error no longer
Packit acf257
-- uses fail x = Left (strMsg x). failMisc is therefore
Packit acf257
-- used instead.
Packit acf257
failMisc :: String -> Result a
Packit acf257
failMisc x = failWith (strMsg x)
Packit acf257
Packit acf257
failParse :: String -> Result a
Packit acf257
failParse x = failWith (ErrorParse x)
Packit acf257
Packit acf257
failWith :: ConnError -> Result a
Packit acf257
failWith x = Left x
Packit acf257
Packit acf257
bindE :: Result a -> (a -> Result b) -> Result b
Packit acf257
bindE (Left e)  _ = Left e
Packit acf257
bindE (Right v) f = f v
Packit acf257
Packit acf257
fmapE :: (a -> Result b) -> IO (Result a) -> IO (Result b)
Packit acf257
fmapE f a = do
Packit acf257
 x <- a
Packit acf257
 case x of
Packit acf257
   Left  e -> return (Left e)
Packit acf257
   Right r -> return (f r) 
Packit acf257
  
Packit acf257
-- | This is the type returned by many exported network functions.
Packit acf257
type Result a = Either ConnError   {- error  -}
Packit acf257
                       a           {- result -}
Packit acf257
Packit acf257
-- | Streams should make layering of TLS protocol easier in future,
Packit acf257
-- they allow reading/writing to files etc for debugging,
Packit acf257
-- they allow use of protocols other than TCP/IP
Packit acf257
-- and they allow customisation.
Packit acf257
--
Packit acf257
-- Instances of this class should not trim
Packit acf257
-- the input in any way, e.g. leave LF on line
Packit acf257
-- endings etc. Unless that is exactly the behaviour
Packit acf257
-- you want from your twisted instances ;)
Packit acf257
class Stream x where 
Packit acf257
    readLine   :: x -> IO (Result String)
Packit acf257
    readBlock  :: x -> Int -> IO (Result String)
Packit acf257
    writeBlock :: x -> String -> IO (Result ())
Packit acf257
    close      :: x -> IO ()
Packit acf257
    closeOnEnd :: x -> Bool -> IO ()
Packit acf257
      -- ^ True => shutdown the connection when response has been read / end-of-stream
Packit acf257
      --           has been reached.