module Piped.Resume ( createResumableSource , createResumableSink , runResumableSource , runResumableSink , ResumableSource(..) , ResumableSink(..) , ResumableResult(..) ) where import Piped.Internal -- | Either a resumable source or sink, plus the result of the pipe that finished. -- data ResumableResult e m a b = ResumeSource (ResumableSource e m a b) b | ResumeSink (ResumableSink e m a b) a -- | A source that may be resumed -- newtype ResumableSource o m a b = ResumableSource (Await o m (ResumableResult o m a b)) -- | A sink that may be resumed -- newtype ResumableSink i m a b = ResumableSink (Yield i m (ResumableResult i m a b)) -- | Create a resumable source from a Pipe -- createResumableSource :: Monad m => Pipe () o m a -> ResumableSource o m a b createResumableSource (Pipe f) = ResumableSource $ Await $ f (\l r a -> pure $ ResumeSink (ResumableSink r) a) termLeft -- | Create a resumable sink from a Pipe -- createResumableSink :: Monad m => Pipe i Void m b -> ResumableSink i m a b createResumableSink (Pipe f) = ResumableSink $ Yield ( f resumeLeft termLeft voidRight) (\i left -> f resumeLeft (addLeftover i left) voidRight) where resumeLeft l _ b = pure $ ResumeSource (ResumableSource l) b -- | Run a resumable source -- runResumableSource :: Monad m => ResumableSource i m a b -> Pipe i Void m b -> m (ResumableResult i m a b) runResumableSource (ResumableSource source) (Pipe f) = f (\l _ b -> pure $ ResumeSource (ResumableSource l) b) source voidRight -- | Run a resumable sink -- runResumableSink :: Monad m => Pipe () o m a -> ResumableSink o m a b -> m (ResumableResult o m a b) runResumableSink (Pipe f) (ResumableSink sink) = f (\_ r a -> pure $ ResumeSink (ResumableSink r) a) termLeft sink