module Data.Conduit.Util.Source
( sourceState
, SourceStateResult (..)
, sourceIO
, SourceIOResult (..)
, transSource
) where
import Control.Monad.Trans.Resource
import Control.Monad.Trans.Class (lift)
import Data.Conduit.Types.Source
data SourceStateResult state output = StateOpen state output | StateClosed
sourceState
:: Resource m
=> state
-> (state -> ResourceT m (SourceStateResult state output))
-> Source m output
sourceState state0 pull0 =
src state0
where
src state = Source (pull state) close
pull state = do
res <- pull0 state
return $ case res of
StateOpen state' val -> Open (src state') val
StateClosed -> Closed
close = return ()
data SourceIOResult output = IOOpen output | IOClosed
sourceIO :: ResourceIO m
=> IO state
-> (state -> IO ())
-> (state -> m (SourceIOResult output))
-> Source m output
sourceIO alloc cleanup pull0 =
Source
{ sourcePull = do
(key, state) <- withIO alloc cleanup
pull key state
, sourceClose = return ()
}
where
src key state = Source (pull key state) (release key)
pull key state = do
res <- lift $ pull0 state
case res of
IOClosed -> do
release key
return Closed
IOOpen val -> return $ Open (src key state) val
transSource :: (Base m ~ Base n, Monad m)
=> (forall a. m a -> n a)
-> Source m output
-> Source n output
transSource f c = c
{ sourcePull = transResourceT f (fmap go2 $ sourcePull c)
, sourceClose = transResourceT f (sourceClose c)
}
where
go2 (Open p a) = Open (transSource f p) a
go2 Closed = Closed