module Data.SouSiT.Source (
Source,
transfer,
SimpleSource(..),
FeedSource(..),
($$),
concatSources,
concatSources',
(=+=),
(=+|=),
actionSource,
bracketActionSource
) where
import Data.SouSiT.Sink
import Control.Exception (bracket)
class Source src where
transfer :: Monad m => src m a -> Sink a m r -> m r
($$) :: (Source src, Monad m) => src m a -> Sink a m r -> m r
($$) = transfer
infixl 0 $$
data SimpleSource m a = SimpleSource (forall r. Sink a m r -> m r)
instance Source SimpleSource where
transfer (SimpleSource f) = f
data FeedSource m a = FeedSource { feedToSink :: forall r. Sink a m r -> m (Sink a m r) }
instance Source FeedSource where
transfer src sink = feedToSink src sink >>= closeSink
concatSources :: (Source src2, Monad m) => FeedSource m a -> src2 m a -> SimpleSource m a
concatSources src1 src2 = SimpleSource f
where f sink = feedToSink src1 sink >>= transfer src2
concatSources' :: Monad m => FeedSource m a -> FeedSource m a -> FeedSource m a
concatSources' src1 src2 = FeedSource f
where f sink = feedToSink src1 sink >>= feedToSink src2
(=+=) :: Monad m => FeedSource m a -> FeedSource m a -> FeedSource m a
(=+=) = concatSources'
infixl 3 =+=
(=+|=) :: (Source src2, Monad m) => FeedSource m a -> src2 m a -> SimpleSource m a
(=+|=) = concatSources
infixl 3 =+|=
actionSource :: Monad m => m (Maybe i) -> FeedSource m i
actionSource f = FeedSource (handleActionSource f)
bracketActionSource :: IO a -> (a -> IO ()) -> (a -> IO (Maybe i)) -> FeedSource IO i
bracketActionSource open close f = FeedSource handle
where handle sink = bracket open close step
where step a = handleActionSource (f a) sink
handleActionSource :: Monad m => m (Maybe i) -> Sink i m r -> m (Sink i m r)
handleActionSource f !sink = sinkStatus sink >>= handleStatus
where handleStatus (Done _) = return sink
handleStatus (Cont nf _) = f >>= handleInput nf
handleInput _ Nothing = return sink
handleInput nf (Just i) = handleActionSource f (nf i)