-- Module      : Foundation.Conduit.Internal
-- License     : BSD-style
-- Maintainer  : Foundation
-- Stability   : experimental
-- Portability : portable
--
-- Taken from the conduit package almost verbatim, and
-- Copyright (c) 2012 Michael Snoyman
--
{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_GHC -Wno-inline-rule-shadowing #-}

module Foundation.Conduit.Internal
    ( Pipe(..)
    , Conduit(..)
    , ZipSink(..)
    , ResourceT(..)
    , MonadResource(..)
    , runResourceT
    , await
    , awaitForever
    , yield
    , yieldOr
    , leftover
    , runConduit
    , runConduitRes
    , runConduitPure
    , fuse
    , bracketConduit
    ) where

import Basement.Imports hiding (throw)
import Foundation.Monad
import Foundation.Numerical
import Basement.Monad
import Control.Monad ((>=>), liftM, void, mapM_, join)
import Control.Exception (SomeException, mask_)
import Data.IORef (atomicModifyIORef)

-- | A pipe producing and consuming values
--
-- A basic intuition is that every @Pipe@ produces a stream of /output/ values
-- and eventually indicates that this stream is terminated by sending a
-- /result/. On the receiving end of a @Pipe@, these become the /input/ and /upstream/
-- parameters.
data Pipe leftOver input output upstream monad result =
      -- | Provide new output to be sent downstream. This constructor has three
      -- fields: the next @Pipe@ to be used, a finalization function, and the
      -- output value.
      Yield (Pipe leftOver input output upstream monad result) (monad ()) output
      -- | Request more input from upstream. The first field takes a new input
      -- value and provides a new @Pipe@. The second takes an upstream result
      -- value, which indicates that upstream is producing no more results.
    | Await (input -> Pipe leftOver input output upstream monad result)
                (upstream -> Pipe leftOver input output upstream monad result)
      -- | Processing with this @Pipe@ is complete, providing the final result.
    | Done result
      -- | Require running of a monadic action to get the next @Pipe@.
    | PipeM (monad (Pipe leftOver input output upstream monad result))
      -- | Return leftover input, which should be provided to future operations.
    | Leftover (Pipe leftOver input output upstream monad result) leftOver

instance Applicative m => Functor (Pipe l i o u m) where
    fmap :: forall a b. (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
fmap = (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
(<$>)
    {-# INLINE fmap #-}

instance Applicative m => Applicative (Pipe l i o u m) where
    pure :: forall a. a -> Pipe l i o u m a
pure = a -> Pipe l i o u m a
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done
    {-# INLINE pure #-}

    Yield Pipe l i o u m (a -> b)
p m ()
c o
o  <*> :: forall a b.
Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
<*> Pipe l i o u m a
fa = Pipe l i o u m b -> m () -> o -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield (Pipe l i o u m (a -> b)
p Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall a b.
Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pipe l i o u m a
fa) m ()
c o
o
    Await i -> Pipe l i o u m (a -> b)
p u -> Pipe l i o u m (a -> b)
c    <*> Pipe l i o u m a
fa = (i -> Pipe l i o u m b)
-> (u -> Pipe l i o u m b) -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await (\i
i -> i -> Pipe l i o u m (a -> b)
p i
i Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall a b.
Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pipe l i o u m a
fa) (\u
o -> u -> Pipe l i o u m (a -> b)
c u
o Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall a b.
Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pipe l i o u m a
fa)
    Done a -> b
r       <*> Pipe l i o u m a
fa = a -> b
r (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Pipe l i o u m a
fa
    PipeM m (Pipe l i o u m (a -> b))
mp     <*> Pipe l i o u m a
fa = m (Pipe l i o u m b) -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM ((Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall a b.
Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pipe l i o u m a
fa) (Pipe l i o u m (a -> b) -> Pipe l i o u m b)
-> m (Pipe l i o u m (a -> b)) -> m (Pipe l i o u m b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Pipe l i o u m (a -> b))
mp)
    Leftover Pipe l i o u m (a -> b)
p l
i <*> Pipe l i o u m a
fa = Pipe l i o u m b -> l -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> leftOver -> Pipe leftOver input output upstream monad result
Leftover (Pipe l i o u m (a -> b)
p Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall a b.
Pipe l i o u m (a -> b) -> Pipe l i o u m a -> Pipe l i o u m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Pipe l i o u m a
fa) l
i
    {-# INLINE (<*>) #-}

instance (Functor m, Monad m) => Monad (Pipe l i o u m) where
    return :: forall a. a -> Pipe l i o u m a
return = a -> Pipe l i o u m a
forall a. a -> Pipe l i o u m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    {-# INLINE return #-}

    Yield Pipe l i o u m a
p m ()
c o
o  >>= :: forall a b.
Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
>>= a -> Pipe l i o u m b
fp = Pipe l i o u m b -> m () -> o -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield    (Pipe l i o u m a
p Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
forall a b.
Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Pipe l i o u m b
fp)            m ()
c          o
o
    Await i -> Pipe l i o u m a
p u -> Pipe l i o u m a
c    >>= a -> Pipe l i o u m b
fp = (i -> Pipe l i o u m b)
-> (u -> Pipe l i o u m b) -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await    (i -> Pipe l i o u m a
p (i -> Pipe l i o u m a)
-> (a -> Pipe l i o u m b) -> i -> Pipe l i o u m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> a -> Pipe l i o u m b
fp)            (u -> Pipe l i o u m a
c (u -> Pipe l i o u m a)
-> (a -> Pipe l i o u m b) -> u -> Pipe l i o u m b
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> a -> Pipe l i o u m b
fp)
    Done a
x       >>= a -> Pipe l i o u m b
fp = a -> Pipe l i o u m b
fp a
x
    PipeM m (Pipe l i o u m a)
mp     >>= a -> Pipe l i o u m b
fp = m (Pipe l i o u m b) -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM    ((Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
forall a b.
Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Pipe l i o u m b
fp) (Pipe l i o u m a -> Pipe l i o u m b)
-> m (Pipe l i o u m a) -> m (Pipe l i o u m b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m (Pipe l i o u m a)
mp)
    Leftover Pipe l i o u m a
p l
i >>= a -> Pipe l i o u m b
fp = Pipe l i o u m b -> l -> Pipe l i o u m b
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> leftOver -> Pipe leftOver input output upstream monad result
Leftover (Pipe l i o u m a
p Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
forall a b.
Pipe l i o u m a -> (a -> Pipe l i o u m b) -> Pipe l i o u m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= a -> Pipe l i o u m b
fp)            l
i

-- | A component of a conduit pipeline, which takes a stream of
-- @input@, produces a stream of @output@, performs actions in the
-- underlying @monad@, and produces a value of @result@ when no more
-- output data is available.
newtype Conduit input output monad result = Conduit
    { forall input output (monad :: * -> *) result.
Conduit input output monad result
-> forall a.
   (result -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
unConduit :: forall a .  (result -> Pipe input input output () monad a) -> Pipe input input output () monad a
    }

instance Functor (Conduit i o m) where
    fmap :: forall a b. (a -> b) -> Conduit i o m a -> Conduit i o m b
fmap a -> b
f (Conduit forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
c) = (forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m b
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m b)
-> (forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m b
forall a b. (a -> b) -> a -> b
$ \b -> Pipe i i o () m a
resPipe -> (a -> Pipe i i o () m a) -> Pipe i i o () m a
forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
c (b -> Pipe i i o () m a
resPipe (b -> Pipe i i o () m a) -> (a -> b) -> a -> Pipe i i o () m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> b
f)

instance Applicative (Conduit i o m) where
    pure :: forall a. a -> Conduit i o m a
pure a
x = (forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m a
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((a -> Pipe i i o () m a) -> a -> Pipe i i o () m a
forall a b. (a -> b) -> a -> b
$ a
x)
    {-# INLINE pure #-}

    Conduit i o m (a -> b)
fab <*> :: forall a b.
Conduit i o m (a -> b) -> Conduit i o m a -> Conduit i o m b
<*> Conduit i o m a
fa = Conduit i o m (a -> b)
fab Conduit i o m (a -> b)
-> ((a -> b) -> Conduit i o m b) -> Conduit i o m b
forall a b.
Conduit i o m a -> (a -> Conduit i o m b) -> Conduit i o m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a -> b
ab -> Conduit i o m a
fa Conduit i o m a -> (a -> Conduit i o m b) -> Conduit i o m b
forall a b.
Conduit i o m a -> (a -> Conduit i o m b) -> Conduit i o m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \a
a -> b -> Conduit i o m b
forall a. a -> Conduit i o m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (a -> b
ab a
a)
    {-# INLINE (<*>) #-}

instance Monad (Conduit i o m) where
    return :: forall a. a -> Conduit i o m a
return = a -> Conduit i o m a
forall a. a -> Conduit i o m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Conduit forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
f >>= :: forall a b.
Conduit i o m a -> (a -> Conduit i o m b) -> Conduit i o m b
>>= a -> Conduit i o m b
g = (forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m b
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m b)
-> (forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m b
forall a b. (a -> b) -> a -> b
$ \b -> Pipe i i o () m a
h -> (a -> Pipe i i o () m a) -> Pipe i i o () m a
forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
f ((a -> Pipe i i o () m a) -> Pipe i i o () m a)
-> (a -> Pipe i i o () m a) -> Pipe i i o () m a
forall a b. (a -> b) -> a -> b
$ \a
a -> Conduit i o m b
-> forall a. (b -> Pipe i i o () m a) -> Pipe i i o () m a
forall input output (monad :: * -> *) result.
Conduit input output monad result
-> forall a.
   (result -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
unConduit (a -> Conduit i o m b
g a
a) b -> Pipe i i o () m a
h

instance MonadTrans (Conduit i o) where
    lift :: forall (m :: * -> *) a. Monad m => m a -> Conduit i o m a
lift m a
m = (forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m a
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m a)
-> (forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m a
forall a b. (a -> b) -> a -> b
$ \a -> Pipe i i o () m a
rest -> m (Pipe i i o () m a) -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM (m (Pipe i i o () m a) -> Pipe i i o () m a)
-> m (Pipe i i o () m a) -> Pipe i i o () m a
forall a b. (a -> b) -> a -> b
$ (a -> Pipe i i o () m a) -> m a -> m (Pipe i i o () m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> Pipe i i o () m a
rest m a
m

instance MonadIO m => MonadIO (Conduit i o m) where
    liftIO :: forall a. IO a -> Conduit i o m a
liftIO = m a -> Conduit i o m a
forall (m :: * -> *) a. Monad m => m a -> Conduit i o m a
forall (trans :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans trans, Monad m) =>
m a -> trans m a
lift (m a -> Conduit i o m a)
-> (IO a -> m a) -> IO a -> Conduit i o m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO

instance MonadFailure m => MonadFailure (Conduit i o m) where
    type Failure (Conduit i o m) = Failure m
    mFail :: Failure (Conduit i o m) -> Conduit i o m ()
mFail = m () -> Conduit i o m ()
forall (m :: * -> *) a. Monad m => m a -> Conduit i o m a
forall (trans :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans trans, Monad m) =>
m a -> trans m a
lift (m () -> Conduit i o m ())
-> (Failure m -> m ()) -> Failure m -> Conduit i o m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Failure m -> m ()
forall (m :: * -> *). MonadFailure m => Failure m -> m ()
mFail

instance MonadThrow m => MonadThrow (Conduit i o m) where
    throw :: forall e a. Exception e => e -> Conduit i o m a
throw = m a -> Conduit i o m a
forall (m :: * -> *) a. Monad m => m a -> Conduit i o m a
forall (trans :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans trans, Monad m) =>
m a -> trans m a
lift (m a -> Conduit i o m a) -> (e -> m a) -> e -> Conduit i o m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. e -> m a
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throw

instance MonadCatch m => MonadCatch (Conduit i o m) where
    catch :: forall e a.
Exception e =>
Conduit i o m a -> (e -> Conduit i o m a) -> Conduit i o m a
catch (Conduit forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
c0) e -> Conduit i o m a
onExc = (forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m a
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m a)
-> (forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m a
forall a b. (a -> b) -> a -> b
$ \a -> Pipe i i o () m a
rest -> let
        go :: Pipe i i o () m a -> Pipe i i o () m a
go (PipeM m (Pipe i i o () m a)
m) =
            m (Pipe i i o () m a) -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM (m (Pipe i i o () m a) -> Pipe i i o () m a)
-> m (Pipe i i o () m a) -> Pipe i i o () m a
forall a b. (a -> b) -> a -> b
$ m (Pipe i i o () m a)
-> (e -> m (Pipe i i o () m a)) -> m (Pipe i i o () m a)
forall e a. Exception e => m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
catch ((Pipe i i o () m a -> Pipe i i o () m a)
-> m (Pipe i i o () m a) -> m (Pipe i i o () m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Pipe i i o () m a -> Pipe i i o () m a
go m (Pipe i i o () m a)
m) (\e
x -> Pipe i i o () m a -> m (Pipe i i o () m a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Pipe i i o () m a -> m (Pipe i i o () m a))
-> Pipe i i o () m a -> m (Pipe i i o () m a)
forall a b. (a -> b) -> a -> b
$ Conduit i o m a
-> forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
forall input output (monad :: * -> *) result.
Conduit input output monad result
-> forall a.
   (result -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
unConduit (e -> Conduit i o m a
onExc e
x) a -> Pipe i i o () m a
rest)
        go (Done a
r) = a -> Pipe i i o () m a
rest a
r
        go (Await i -> Pipe i i o () m a
p () -> Pipe i i o () m a
c) = (i -> Pipe i i o () m a)
-> (() -> Pipe i i o () m a) -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await (Pipe i i o () m a -> Pipe i i o () m a
go (Pipe i i o () m a -> Pipe i i o () m a)
-> (i -> Pipe i i o () m a) -> i -> Pipe i i o () m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. i -> Pipe i i o () m a
p) (Pipe i i o () m a -> Pipe i i o () m a
go (Pipe i i o () m a -> Pipe i i o () m a)
-> (() -> Pipe i i o () m a) -> () -> Pipe i i o () m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. () -> Pipe i i o () m a
c)
        go (Yield Pipe i i o () m a
p m ()
m o
o) = Pipe i i o () m a -> m () -> o -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield (Pipe i i o () m a -> Pipe i i o () m a
go Pipe i i o () m a
p) m ()
m o
o
        go (Leftover Pipe i i o () m a
p i
i) = Pipe i i o () m a -> i -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> leftOver -> Pipe leftOver input output upstream monad result
Leftover (Pipe i i o () m a -> Pipe i i o () m a
go Pipe i i o () m a
p) i
i

        in Pipe i i o () m a -> Pipe i i o () m a
go ((a -> Pipe i i o () m a) -> Pipe i i o () m a
forall a. (a -> Pipe i i o () m a) -> Pipe i i o () m a
c0 a -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done)

-- | Await for a value from upstream.
await :: Conduit i o m (Maybe i)
await :: forall i o (m :: * -> *). Conduit i o m (Maybe i)
await = (forall a. (Maybe i -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m (Maybe i)
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (Maybe i -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m (Maybe i))
-> (forall a. (Maybe i -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m (Maybe i)
forall a b. (a -> b) -> a -> b
$ \Maybe i -> Pipe i i o () m a
f -> (i -> Pipe i i o () m a)
-> (() -> Pipe i i o () m a) -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await (Maybe i -> Pipe i i o () m a
f (Maybe i -> Pipe i i o () m a)
-> (i -> Maybe i) -> i -> Pipe i i o () m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. i -> Maybe i
forall a. a -> Maybe a
Just) (Pipe i i o () m a -> () -> Pipe i i o () m a
forall a b. a -> b -> a
const (Maybe i -> Pipe i i o () m a
f Maybe i
forall a. Maybe a
Nothing))
{-# NOINLINE[1] await  #-}

await' :: Conduit i o m r
       -> (i -> Conduit i o m r)
       -> Conduit i o m r
await' :: forall i o (m :: * -> *) r.
Conduit i o m r -> (i -> Conduit i o m r) -> Conduit i o m r
await' Conduit i o m r
f i -> Conduit i o m r
g = (forall a. (r -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m r
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (r -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m r)
-> (forall a. (r -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m r
forall a b. (a -> b) -> a -> b
$ \r -> Pipe i i o () m a
rest -> (i -> Pipe i i o () m a)
-> (() -> Pipe i i o () m a) -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await
    (\i
i -> Conduit i o m r
-> forall a. (r -> Pipe i i o () m a) -> Pipe i i o () m a
forall input output (monad :: * -> *) result.
Conduit input output monad result
-> forall a.
   (result -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
unConduit (i -> Conduit i o m r
g i
i) r -> Pipe i i o () m a
rest)
    (Pipe i i o () m a -> () -> Pipe i i o () m a
forall a b. a -> b -> a
const (Pipe i i o () m a -> () -> Pipe i i o () m a)
-> Pipe i i o () m a -> () -> Pipe i i o () m a
forall a b. (a -> b) -> a -> b
$ Conduit i o m r
-> forall a. (r -> Pipe i i o () m a) -> Pipe i i o () m a
forall input output (monad :: * -> *) result.
Conduit input output monad result
-> forall a.
   (result -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
unConduit Conduit i o m r
f r -> Pipe i i o () m a
rest)
{-# INLINE await' #-}
{-# RULES "conduit: await >>= maybe" [2] forall x y. await >>= maybe x y = await' x y #-}

awaitForever :: (input -> Conduit input output monad b) -> Conduit input output monad ()
awaitForever :: forall input output (monad :: * -> *) b.
(input -> Conduit input output monad b)
-> Conduit input output monad ()
awaitForever input -> Conduit input output monad b
f = (forall a.
 (() -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad ()
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a.
  (() -> Pipe input input output () monad a)
  -> Pipe input input output () monad a)
 -> Conduit input output monad ())
-> (forall a.
    (() -> Pipe input input output () monad a)
    -> Pipe input input output () monad a)
-> Conduit input output monad ()
forall a b. (a -> b) -> a -> b
$ \() -> Pipe input input output () monad a
rest ->
    let go :: Pipe input input output () monad a
go = (input -> Pipe input input output () monad a)
-> (() -> Pipe input input output () monad a)
-> Pipe input input output () monad a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await (\input
i -> Conduit input output monad b
-> forall a.
   (b -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
forall input output (monad :: * -> *) result.
Conduit input output monad result
-> forall a.
   (result -> Pipe input input output () monad a)
   -> Pipe input input output () monad a
unConduit (input -> Conduit input output monad b
f input
i) (Pipe input input output () monad a
-> b -> Pipe input input output () monad a
forall a b. a -> b -> a
const Pipe input input output () monad a
go)) () -> Pipe input input output () monad a
rest
     in Pipe input input output () monad a
go

-- | Send a value downstream.
yield :: Monad m => o -> Conduit i o m ()
yield :: forall (m :: * -> *) o i. Monad m => o -> Conduit i o m ()
yield o
o = (forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m ()
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m ())
-> (forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m ()
forall a b. (a -> b) -> a -> b
$ \() -> Pipe i i o () m a
f -> Pipe i i o () m a -> m () -> o -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield (() -> Pipe i i o () m a
f ()) (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) o
o

-- | Same as 'yield', but additionally takes a finalizer to be run if
-- the downstream component terminates.
yieldOr :: o
        -> m () -- ^ finalizer
        -> Conduit i o m ()
yieldOr :: forall o (m :: * -> *) i. o -> m () -> Conduit i o m ()
yieldOr o
o m ()
m = (forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m ()
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m ())
-> (forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m ()
forall a b. (a -> b) -> a -> b
$ \() -> Pipe i i o () m a
f -> Pipe i i o () m a -> m () -> o -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield (() -> Pipe i i o () m a
f ()) m ()
m o
o

-- | Provide leftover input to be consumed by the next component in
-- the current monadic binding.
leftover :: i -> Conduit i o m ()
leftover :: forall i o (m :: * -> *). i -> Conduit i o m ()
leftover i
i = (forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m ()
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
 -> Conduit i o m ())
-> (forall a. (() -> Pipe i i o () m a) -> Pipe i i o () m a)
-> Conduit i o m ()
forall a b. (a -> b) -> a -> b
$ \() -> Pipe i i o () m a
f -> Pipe i i o () m a -> i -> Pipe i i o () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> leftOver -> Pipe leftOver input output upstream monad result
Leftover (() -> Pipe i i o () m a
f ()) i
i

-- | Run a conduit pipeline to completion.
runConduit :: Monad m => Conduit () () m r -> m r
runConduit :: forall (m :: * -> *) r. Monad m => Conduit () () m r -> m r
runConduit (Conduit forall a. (r -> Pipe () () () () m a) -> Pipe () () () () m a
f) = Pipe () () () () m r -> m r
forall (m :: * -> *) r. Monad m => Pipe () () () () m r -> m r
runPipe ((r -> Pipe () () () () m r) -> Pipe () () () () m r
forall a. (r -> Pipe () () () () m a) -> Pipe () () () () m a
f r -> Pipe () () () () m r
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done)

-- | Run a pure conduit pipeline to completion.
runConduitPure :: Conduit () () Identity r -> r
runConduitPure :: forall r. Conduit () () Identity r -> r
runConduitPure = Identity r -> r
forall a. Identity a -> a
runIdentity (Identity r -> r)
-> (Conduit () () Identity r -> Identity r)
-> Conduit () () Identity r
-> r
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Conduit () () Identity r -> Identity r
forall (m :: * -> *) r. Monad m => Conduit () () m r -> m r
runConduit

-- | Run a conduit pipeline in a 'ResourceT' context for acquiring resources.
runConduitRes :: (MonadBracket m, MonadIO m) => Conduit () () (ResourceT m) r -> m r
runConduitRes :: forall (m :: * -> *) r.
(MonadBracket m, MonadIO m) =>
Conduit () () (ResourceT m) r -> m r
runConduitRes = ResourceT m r -> m r
forall (m :: * -> *) a.
(MonadBracket m, MonadIO m) =>
ResourceT m a -> m a
runResourceT (ResourceT m r -> m r)
-> (Conduit () () (ResourceT m) r -> ResourceT m r)
-> Conduit () () (ResourceT m) r
-> m r
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Conduit () () (ResourceT m) r -> ResourceT m r
forall (m :: * -> *) r. Monad m => Conduit () () m r -> m r
runConduit

bracketConduit :: MonadResource m
               => IO a
               -> (a -> IO b)
               -> (a -> Conduit i o m r)
               -> Conduit i o m r
bracketConduit :: forall (m :: * -> *) a b i o r.
MonadResource m =>
IO a -> (a -> IO b) -> (a -> Conduit i o m r) -> Conduit i o m r
bracketConduit IO a
acquire a -> IO b
cleanup a -> Conduit i o m r
inner = do
    (a
resource, Conduit i o m ()
release) <- IO a -> (a -> IO b) -> Conduit i o m (a, Conduit i o m ())
forall (m :: * -> *) (n :: * -> *) a b.
(MonadResource m, MonadIO n) =>
IO a -> (a -> IO b) -> m (a, n ())
allocate IO a
acquire a -> IO b
cleanup
    r
result <- a -> Conduit i o m r
inner a
resource
    Conduit i o m ()
release
    r -> Conduit i o m r
forall a. a -> Conduit i o m a
forall (m :: * -> *) a. Monad m => a -> m a
return r
result

-- | Internal: run a @Pipe@
runPipe :: Monad m => Pipe () () () () m r -> m r
runPipe :: forall (m :: * -> *) r. Monad m => Pipe () () () () m r -> m r
runPipe =
    Pipe () () () () m r -> m r
forall {m :: * -> *} {input} {a}.
Monad m =>
Pipe () input () () m a -> m a
go
  where
    go :: Pipe () input () () m a -> m a
go (Yield Pipe () input () () m a
p m ()
_ ()) = Pipe () input () () m a -> m a
go Pipe () input () () m a
p
    go (Await input -> Pipe () input () () m a
_ () -> Pipe () input () () m a
p) = Pipe () input () () m a -> m a
go (() -> Pipe () input () () m a
p ())
    go (Done a
r) = a -> m a
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
r
    go (PipeM m (Pipe () input () () m a)
mp) = m (Pipe () input () () m a)
mp m (Pipe () input () () m a)
-> (Pipe () input () () m a -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Pipe () input () () m a -> m a
go
    go (Leftover Pipe () input () () m a
p ()) = Pipe () input () () m a -> m a
go Pipe () input () () m a
p

-- | Send the output of the first Conduit component to the second
-- Conduit component.
fuse :: Monad m => Conduit a b m () -> Conduit b c m r -> Conduit a c m r
fuse :: forall (m :: * -> *) a b c r.
Monad m =>
Conduit a b m () -> Conduit b c m r -> Conduit a c m r
fuse (Conduit forall a. (() -> Pipe a a b () m a) -> Pipe a a b () m a
left0) (Conduit forall a. (r -> Pipe b b c () m a) -> Pipe b b c () m a
right0) = (forall a. (r -> Pipe a a c () m a) -> Pipe a a c () m a)
-> Conduit a c m r
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (r -> Pipe a a c () m a) -> Pipe a a c () m a)
 -> Conduit a c m r)
-> (forall a. (r -> Pipe a a c () m a) -> Pipe a a c () m a)
-> Conduit a c m r
forall a b. (a -> b) -> a -> b
$ \r -> Pipe a a c () m a
rest ->
    let goRight :: m ()
-> Pipe a a b () m () -> Pipe b b c () m r -> Pipe a a c () m a
goRight m ()
final Pipe a a b () m ()
left Pipe b b c () m r
right =
            case Pipe b b c () m r
right of
                Yield Pipe b b c () m r
p m ()
c c
o       -> Pipe a a c () m a -> m () -> c -> Pipe a a c () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield (Pipe b b c () m r -> Pipe a a c () m a
recurse Pipe b b c () m r
p) (m ()
c m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> m ()
final) c
o
                Await b -> Pipe b b c () m r
rp () -> Pipe b b c () m r
rc       -> (b -> Pipe b b c () m r)
-> (() -> Pipe b b c () m r)
-> m ()
-> Pipe a a b () m ()
-> Pipe a a c () m a
goLeft b -> Pipe b b c () m r
rp () -> Pipe b b c () m r
rc m ()
final Pipe a a b () m ()
left
                Done r
r2           -> m (Pipe a a c () m a) -> Pipe a a c () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM (m ()
final m () -> m (Pipe a a c () m a) -> m (Pipe a a c () m a)
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Pipe a a c () m a -> m (Pipe a a c () m a)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (r -> Pipe a a c () m a
rest r
r2))
                PipeM m (Pipe b b c () m r)
mp          -> m (Pipe a a c () m a) -> Pipe a a c () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM ((Pipe b b c () m r -> Pipe a a c () m a)
-> m (Pipe b b c () m r) -> m (Pipe a a c () m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Pipe b b c () m r -> Pipe a a c () m a
recurse m (Pipe b b c () m r)
mp)
                Leftover Pipe b b c () m r
right' b
i -> m ()
-> Pipe a a b () m () -> Pipe b b c () m r -> Pipe a a c () m a
goRight m ()
final (Pipe a a b () m () -> m () -> b -> Pipe a a b () m ()
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield Pipe a a b () m ()
left m ()
final b
i) Pipe b b c () m r
right'
          where
            recurse :: Pipe b b c () m r -> Pipe a a c () m a
recurse = m ()
-> Pipe a a b () m () -> Pipe b b c () m r -> Pipe a a c () m a
goRight m ()
final Pipe a a b () m ()
left

        goLeft :: (b -> Pipe b b c () m r)
-> (() -> Pipe b b c () m r)
-> m ()
-> Pipe a a b () m ()
-> Pipe a a c () m a
goLeft b -> Pipe b b c () m r
rp () -> Pipe b b c () m r
rc m ()
final Pipe a a b () m ()
left =
            case Pipe a a b () m ()
left of
                Yield Pipe a a b () m ()
left' m ()
final' b
o -> m ()
-> Pipe a a b () m () -> Pipe b b c () m r -> Pipe a a c () m a
goRight m ()
final' Pipe a a b () m ()
left' (b -> Pipe b b c () m r
rp b
o)
                Await a -> Pipe a a b () m ()
left' () -> Pipe a a b () m ()
lc       -> (a -> Pipe a a c () m a)
-> (() -> Pipe a a c () m a) -> Pipe a a c () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await (Pipe a a b () m () -> Pipe a a c () m a
recurse (Pipe a a b () m () -> Pipe a a c () m a)
-> (a -> Pipe a a b () m ()) -> a -> Pipe a a c () m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> Pipe a a b () m ()
left') (Pipe a a b () m () -> Pipe a a c () m a
recurse (Pipe a a b () m () -> Pipe a a c () m a)
-> (() -> Pipe a a b () m ()) -> () -> Pipe a a c () m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. () -> Pipe a a b () m ()
lc)
                Done ()
r1              -> m ()
-> Pipe a a b () m () -> Pipe b b c () m r -> Pipe a a c () m a
goRight (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) (() -> Pipe a a b () m ()
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done ()
r1) (() -> Pipe b b c () m r
rc ()
r1)
                PipeM m (Pipe a a b () m ())
mp             -> m (Pipe a a c () m a) -> Pipe a a c () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM ((Pipe a a b () m () -> Pipe a a c () m a)
-> m (Pipe a a b () m ()) -> m (Pipe a a c () m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Pipe a a b () m () -> Pipe a a c () m a
recurse m (Pipe a a b () m ())
mp)
                Leftover Pipe a a b () m ()
left' a
i     -> Pipe a a c () m a -> a -> Pipe a a c () m a
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> leftOver -> Pipe leftOver input output upstream monad result
Leftover (Pipe a a b () m () -> Pipe a a c () m a
recurse Pipe a a b () m ()
left') a
i
          where
            recurse :: Pipe a a b () m () -> Pipe a a c () m a
recurse = (b -> Pipe b b c () m r)
-> (() -> Pipe b b c () m r)
-> m ()
-> Pipe a a b () m ()
-> Pipe a a c () m a
goLeft b -> Pipe b b c () m r
rp () -> Pipe b b c () m r
rc m ()
final
     in m ()
-> Pipe a a b () m () -> Pipe b b c () m r -> Pipe a a c () m a
goRight (() -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()) ((() -> Pipe a a b () m ()) -> Pipe a a b () m ()
forall a. (() -> Pipe a a b () m a) -> Pipe a a b () m a
left0 () -> Pipe a a b () m ()
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done) ((r -> Pipe b b c () m r) -> Pipe b b c () m r
forall a. (r -> Pipe b b c () m a) -> Pipe b b c () m a
right0 r -> Pipe b b c () m r
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done)

{- FIXME for later, if we add resourcet
-- | Safely acquire a resource and register a cleanup action for it,
-- in the context of a 'Conduit'.
bracketConduit :: MonadResource m
               => IO a -- ^ acquire
               -> (a -> IO ()) -- ^ cleanup
               -> (a -> Conduit i o m r)
               -> Conduit i o m r
bracketConduit alloc cleanup inner = Conduit $ \rest -> PipeM $ do
    (key, val) <- allocate alloc cleanup
    return $ unConduit (addCleanup (const $ release key) (inside seed)) rest

addCleanup :: Monad m
           => (Bool -> m ())
           -> Conduit i o m r
           -> Conduit i o m r
addCleanup cleanup (Conduit c0) = Conduit $ \rest -> let
    go (Done r) = PipeM (cleanup True >> return (rest r))
    go (Yield src close x) = Yield
        (go src)
        (cleanup False >> close)
        x
    go (PipeM msrc) = PipeM (liftM (go) msrc)
    go (Await p c) = Await
        (go . p)
        (go . c)
    go (Leftover p i) = Leftover (go p) i
    in go (c0 Done)
-}

newtype ZipSink i m r = ZipSink { forall i (m :: * -> *) r. ZipSink i m r -> Conduit i () m r
getZipSink :: Conduit i () m r }

instance Monad m => Functor (ZipSink i m) where
    fmap :: forall a b. (a -> b) -> ZipSink i m a -> ZipSink i m b
fmap a -> b
f (ZipSink Conduit i () m a
x) = Conduit i () m b -> ZipSink i m b
forall i (m :: * -> *) r. Conduit i () m r -> ZipSink i m r
ZipSink ((a -> b) -> Conduit i () m a -> Conduit i () m b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM a -> b
f Conduit i () m a
x)
instance Monad m => Applicative (ZipSink i m) where
    pure :: forall a. a -> ZipSink i m a
pure  = Conduit i () m a -> ZipSink i m a
forall i (m :: * -> *) r. Conduit i () m r -> ZipSink i m r
ZipSink (Conduit i () m a -> ZipSink i m a)
-> (a -> Conduit i () m a) -> a -> ZipSink i m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> Conduit i () m a
forall a. a -> Conduit i () m a
forall (m :: * -> *) a. Monad m => a -> m a
return
    ZipSink (Conduit forall a. ((a -> b) -> Pipe i i () () m a) -> Pipe i i () () m a
f0) <*> :: forall a b. ZipSink i m (a -> b) -> ZipSink i m a -> ZipSink i m b
<*> ZipSink (Conduit forall a. (a -> Pipe i i () () m a) -> Pipe i i () () m a
x0) =
      Conduit i () m b -> ZipSink i m b
forall i (m :: * -> *) r. Conduit i () m r -> ZipSink i m r
ZipSink (Conduit i () m b -> ZipSink i m b)
-> Conduit i () m b -> ZipSink i m b
forall a b. (a -> b) -> a -> b
$ (forall a. (b -> Pipe i i () () m a) -> Pipe i i () () m a)
-> Conduit i () m b
forall input output (monad :: * -> *) result.
(forall a.
 (result -> Pipe input input output () monad a)
 -> Pipe input input output () monad a)
-> Conduit input output monad result
Conduit ((forall a. (b -> Pipe i i () () m a) -> Pipe i i () () m a)
 -> Conduit i () m b)
-> (forall a. (b -> Pipe i i () () m a) -> Pipe i i () () m a)
-> Conduit i () m b
forall a b. (a -> b) -> a -> b
$ \b -> Pipe i i () () m a
rest -> let
        go :: Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go (Leftover Pipe Void i () () m (a -> b)
_ Void
i) Pipe Void i () () m a
_ = Void -> Pipe i i () () m a
forall a. Void -> a
absurd Void
i
        go Pipe Void i () () m (a -> b)
_ (Leftover Pipe Void i () () m a
_ Void
i) = Void -> Pipe i i () () m a
forall a. Void -> a
absurd Void
i
        go (Yield Pipe Void i () () m (a -> b)
f m ()
_ ()) Pipe Void i () () m a
x = Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go Pipe Void i () () m (a -> b)
f Pipe Void i () () m a
x
        go Pipe Void i () () m (a -> b)
f (Yield Pipe Void i () () m a
x m ()
_ ()) = Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go Pipe Void i () () m (a -> b)
f Pipe Void i () () m a
x
        go (PipeM m (Pipe Void i () () m (a -> b))
mf) Pipe Void i () () m a
x = m (Pipe i i () () m a) -> Pipe i i () () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM ((Pipe Void i () () m (a -> b) -> Pipe i i () () m a)
-> m (Pipe Void i () () m (a -> b)) -> m (Pipe i i () () m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
`go` Pipe Void i () () m a
x) m (Pipe Void i () () m (a -> b))
mf)
        go Pipe Void i () () m (a -> b)
f (PipeM m (Pipe Void i () () m a)
mx) = m (Pipe i i () () m a) -> Pipe i i () () m a
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM ((Pipe Void i () () m a -> Pipe i i () () m a)
-> m (Pipe Void i () () m a) -> m (Pipe i i () () m a)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go Pipe Void i () () m (a -> b)
f) m (Pipe Void i () () m a)
mx)
        go (Done a -> b
f) (Done a
x) = b -> Pipe i i () () m a
rest (a -> b
f a
x)
        go (Await i -> Pipe Void i () () m (a -> b)
pf () -> Pipe Void i () () m (a -> b)
cf) (Await i -> Pipe Void i () () m a
px () -> Pipe Void i () () m a
cx) = (i -> Pipe i i () () m a)
-> (() -> Pipe i i () () m a) -> Pipe i i () () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await
            (\i
i -> Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go (i -> Pipe Void i () () m (a -> b)
pf i
i) (i -> Pipe Void i () () m a
px i
i))
            (\() -> Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go (() -> Pipe Void i () () m (a -> b)
cf ()) (() -> Pipe Void i () () m a
cx ()))
        go (Await i -> Pipe Void i () () m (a -> b)
pf () -> Pipe Void i () () m (a -> b)
cf) x :: Pipe Void i () () m a
x@Done{} = (i -> Pipe i i () () m a)
-> (() -> Pipe i i () () m a) -> Pipe i i () () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await
            (\i
i -> Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go (i -> Pipe Void i () () m (a -> b)
pf i
i) Pipe Void i () () m a
x)
            (\() -> Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go (() -> Pipe Void i () () m (a -> b)
cf ()) Pipe Void i () () m a
x)
        go f :: Pipe Void i () () m (a -> b)
f@Done{} (Await i -> Pipe Void i () () m a
px () -> Pipe Void i () () m a
cx) = (i -> Pipe i i () () m a)
-> (() -> Pipe i i () () m a) -> Pipe i i () () m a
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await
            (\i
i -> Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go Pipe Void i () () m (a -> b)
f (i -> Pipe Void i () () m a
px i
i))
            (\() -> Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go Pipe Void i () () m (a -> b)
f (() -> Pipe Void i () () m a
cx ()))

      in Pipe Void i () () m (a -> b)
-> Pipe Void i () () m a -> Pipe i i () () m a
go (Pipe i i () () m (a -> b) -> Pipe Void i () () m (a -> b)
forall (m :: * -> *) i o u r l.
Monad m =>
Pipe i i o u m r -> Pipe l i o u m r
injectLeftovers (((a -> b) -> Pipe i i () () m (a -> b))
-> Pipe i i () () m (a -> b)
forall a. ((a -> b) -> Pipe i i () () m a) -> Pipe i i () () m a
f0 (a -> b) -> Pipe i i () () m (a -> b)
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done)) (Pipe i i () () m a -> Pipe Void i () () m a
forall (m :: * -> *) i o u r l.
Monad m =>
Pipe i i o u m r -> Pipe l i o u m r
injectLeftovers ((a -> Pipe i i () () m a) -> Pipe i i () () m a
forall a. (a -> Pipe i i () () m a) -> Pipe i i () () m a
x0 a -> Pipe i i () () m a
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done))

data Void

absurd :: Void -> a
absurd :: forall a. Void -> a
absurd Void
_ = String -> a
forall a. HasCallStack => String -> a
error String
"Foundation.Conduit.Internal.absurd"

injectLeftovers :: Monad m => Pipe i i o u m r -> Pipe l i o u m r
injectLeftovers :: forall (m :: * -> *) i o u r l.
Monad m =>
Pipe i i o u m r -> Pipe l i o u m r
injectLeftovers =
    [i] -> Pipe i i o u m r -> Pipe l i o u m r
forall {monad :: * -> *} {input} {output} {upstream} {result}
       {leftOver}.
Monad monad =>
[input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go []
  where
    go :: [input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go [input]
ls (Yield Pipe input input output upstream monad result
p monad ()
c output
o) = Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
forall leftOver input output upstream (monad :: * -> *) result.
Pipe leftOver input output upstream monad result
-> monad ()
-> output
-> Pipe leftOver input output upstream monad result
Yield ([input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go [input]
ls Pipe input input output upstream monad result
p) monad ()
c output
o
    go (input
l:[input]
ls) (Await input -> Pipe input input output upstream monad result
p upstream -> Pipe input input output upstream monad result
_) = [input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go [input]
ls (Pipe input input output upstream monad result
 -> Pipe leftOver input output upstream monad result)
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
forall a b. (a -> b) -> a -> b
$ input -> Pipe input input output upstream monad result
p input
l
    go [] (Await input -> Pipe input input output upstream monad result
p upstream -> Pipe input input output upstream monad result
c) = (input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
forall leftOver input output upstream (monad :: * -> *) result.
(input -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
Await ([input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go [] (Pipe input input output upstream monad result
 -> Pipe leftOver input output upstream monad result)
-> (input -> Pipe input input output upstream monad result)
-> input
-> Pipe leftOver input output upstream monad result
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. input -> Pipe input input output upstream monad result
p) ([input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go [] (Pipe input input output upstream monad result
 -> Pipe leftOver input output upstream monad result)
-> (upstream -> Pipe input input output upstream monad result)
-> upstream
-> Pipe leftOver input output upstream monad result
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. upstream -> Pipe input input output upstream monad result
c)
    go [input]
_ (Done result
r) = result -> Pipe leftOver input output upstream monad result
forall leftOver input output upstream (monad :: * -> *) result.
result -> Pipe leftOver input output upstream monad result
Done result
r
    go [input]
ls (PipeM monad (Pipe input input output upstream monad result)
mp) = monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
forall leftOver input output upstream (monad :: * -> *) result.
monad (Pipe leftOver input output upstream monad result)
-> Pipe leftOver input output upstream monad result
PipeM ((Pipe input input output upstream monad result
 -> Pipe leftOver input output upstream monad result)
-> monad (Pipe input input output upstream monad result)
-> monad (Pipe leftOver input output upstream monad result)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ([input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go [input]
ls) monad (Pipe input input output upstream monad result)
mp)
    go [input]
ls (Leftover Pipe input input output upstream monad result
p input
l) = [input]
-> Pipe input input output upstream monad result
-> Pipe leftOver input output upstream monad result
go (input
linput -> [input] -> [input]
forall a. a -> [a] -> [a]
:[input]
ls) Pipe input input output upstream monad result
p

---------------------
-- ResourceT
---------------------
newtype ResourceT m a = ResourceT { forall (m :: * -> *) a.
ResourceT m a -> PrimVar IO ReleaseMap -> m a
unResourceT :: PrimVar IO ReleaseMap -> m a }
instance Functor m => Functor (ResourceT m) where
    fmap :: forall a b. (a -> b) -> ResourceT m a -> ResourceT m b
fmap a -> b
f (ResourceT PrimVar IO ReleaseMap -> m a
m) = (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((PrimVar IO ReleaseMap -> m b) -> ResourceT m b)
-> (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall a b. (a -> b) -> a -> b
$ \PrimVar IO ReleaseMap
r -> (a -> b) -> m a -> m b
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (PrimVar IO ReleaseMap -> m a
m PrimVar IO ReleaseMap
r)
instance Applicative m => Applicative (ResourceT m) where
    pure :: forall a. a -> ResourceT m a
pure = (IORef ReleaseMap -> m a) -> ResourceT m a
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((IORef ReleaseMap -> m a) -> ResourceT m a)
-> (a -> IORef ReleaseMap -> m a) -> a -> ResourceT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. m a -> IORef ReleaseMap -> m a
forall a b. a -> b -> a
const (m a -> IORef ReleaseMap -> m a)
-> (a -> m a) -> a -> IORef ReleaseMap -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. a -> m a
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    ResourceT PrimVar IO ReleaseMap -> m (a -> b)
mf <*> :: forall a b. ResourceT m (a -> b) -> ResourceT m a -> ResourceT m b
<*> ResourceT PrimVar IO ReleaseMap -> m a
ma = (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((PrimVar IO ReleaseMap -> m b) -> ResourceT m b)
-> (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall a b. (a -> b) -> a -> b
$ \PrimVar IO ReleaseMap
r ->
        PrimVar IO ReleaseMap -> m (a -> b)
mf PrimVar IO ReleaseMap
r m (a -> b) -> m a -> m b
forall a b. m (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> PrimVar IO ReleaseMap -> m a
ma PrimVar IO ReleaseMap
r
instance Monad m => Monad (ResourceT m) where
#if !MIN_VERSION_base(4,8,0)
    return = ResourceT . const . return
#endif
    ResourceT PrimVar IO ReleaseMap -> m a
ma >>= :: forall a b. ResourceT m a -> (a -> ResourceT m b) -> ResourceT m b
>>= a -> ResourceT m b
f = (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((PrimVar IO ReleaseMap -> m b) -> ResourceT m b)
-> (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall a b. (a -> b) -> a -> b
$ \PrimVar IO ReleaseMap
r -> do
        a
a <- PrimVar IO ReleaseMap -> m a
ma PrimVar IO ReleaseMap
r
        let ResourceT PrimVar IO ReleaseMap -> m b
f' = a -> ResourceT m b
f a
a
        PrimVar IO ReleaseMap -> m b
f' PrimVar IO ReleaseMap
r
instance MonadTrans ResourceT where
    lift :: forall (m :: * -> *) a. Monad m => m a -> ResourceT m a
lift = (IORef ReleaseMap -> m a) -> ResourceT m a
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((IORef ReleaseMap -> m a) -> ResourceT m a)
-> (m a -> IORef ReleaseMap -> m a) -> m a -> ResourceT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. m a -> IORef ReleaseMap -> m a
forall a b. a -> b -> a
const
instance MonadIO m => MonadIO (ResourceT m) where
    liftIO :: forall a. IO a -> ResourceT m a
liftIO = m a -> ResourceT m a
forall (m :: * -> *) a. Monad m => m a -> ResourceT m a
forall (trans :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans trans, Monad m) =>
m a -> trans m a
lift (m a -> ResourceT m a) -> (IO a -> m a) -> IO a -> ResourceT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO
instance MonadThrow m => MonadThrow (ResourceT m) where
    throw :: forall e a. Exception e => e -> ResourceT m a
throw = m a -> ResourceT m a
forall (m :: * -> *) a. Monad m => m a -> ResourceT m a
forall (trans :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans trans, Monad m) =>
m a -> trans m a
lift (m a -> ResourceT m a) -> (e -> m a) -> e -> ResourceT m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. e -> m a
forall e a. Exception e => e -> m a
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throw
instance MonadCatch m => MonadCatch (ResourceT m) where
    catch :: forall e a.
Exception e =>
ResourceT m a -> (e -> ResourceT m a) -> ResourceT m a
catch (ResourceT PrimVar IO ReleaseMap -> m a
f) e -> ResourceT m a
g = (PrimVar IO ReleaseMap -> m a) -> ResourceT m a
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((PrimVar IO ReleaseMap -> m a) -> ResourceT m a)
-> (PrimVar IO ReleaseMap -> m a) -> ResourceT m a
forall a b. (a -> b) -> a -> b
$ \PrimVar IO ReleaseMap
env -> PrimVar IO ReleaseMap -> m a
f PrimVar IO ReleaseMap
env m a -> (e -> m a) -> m a
forall e a. Exception e => m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` \e
e -> ResourceT m a -> PrimVar IO ReleaseMap -> m a
forall (m :: * -> *) a.
ResourceT m a -> PrimVar IO ReleaseMap -> m a
unResourceT (e -> ResourceT m a
g e
e) PrimVar IO ReleaseMap
env
instance MonadBracket m => MonadBracket (ResourceT m) where
    generalBracket :: forall a b ignored1 ignored2.
ResourceT m a
-> (a -> b -> ResourceT m ignored1)
-> (a -> SomeException -> ResourceT m ignored2)
-> (a -> ResourceT m b)
-> ResourceT m b
generalBracket ResourceT m a
acquire a -> b -> ResourceT m ignored1
onSuccess a -> SomeException -> ResourceT m ignored2
onExc a -> ResourceT m b
inner = (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((PrimVar IO ReleaseMap -> m b) -> ResourceT m b)
-> (PrimVar IO ReleaseMap -> m b) -> ResourceT m b
forall a b. (a -> b) -> a -> b
$ \PrimVar IO ReleaseMap
env -> m a
-> (a -> b -> m ignored1)
-> (a -> SomeException -> m ignored2)
-> (a -> m b)
-> m b
forall a b ignored1 ignored2.
m a
-> (a -> b -> m ignored1)
-> (a -> SomeException -> m ignored2)
-> (a -> m b)
-> m b
forall (m :: * -> *) a b ignored1 ignored2.
MonadBracket m =>
m a
-> (a -> b -> m ignored1)
-> (a -> SomeException -> m ignored2)
-> (a -> m b)
-> m b
generalBracket
        (ResourceT m a -> PrimVar IO ReleaseMap -> m a
forall (m :: * -> *) a.
ResourceT m a -> PrimVar IO ReleaseMap -> m a
unResourceT ResourceT m a
acquire PrimVar IO ReleaseMap
env)
        (\a
x b
y -> ResourceT m ignored1 -> PrimVar IO ReleaseMap -> m ignored1
forall (m :: * -> *) a.
ResourceT m a -> PrimVar IO ReleaseMap -> m a
unResourceT (a -> b -> ResourceT m ignored1
onSuccess a
x b
y) PrimVar IO ReleaseMap
env)
        (\a
x SomeException
y -> ResourceT m ignored2 -> PrimVar IO ReleaseMap -> m ignored2
forall (m :: * -> *) a.
ResourceT m a -> PrimVar IO ReleaseMap -> m a
unResourceT (a -> SomeException -> ResourceT m ignored2
onExc a
x SomeException
y) PrimVar IO ReleaseMap
env)
        (\a
x -> ResourceT m b -> PrimVar IO ReleaseMap -> m b
forall (m :: * -> *) a.
ResourceT m a -> PrimVar IO ReleaseMap -> m a
unResourceT (a -> ResourceT m b
inner a
x) PrimVar IO ReleaseMap
env)

data ReleaseMap =
    ReleaseMap !NextKey !RefCount ![(Word, (ReleaseType -> IO ()))] -- FIXME use a proper Map?
  | ReleaseMapClosed

data ReleaseType = ReleaseEarly
                 | ReleaseNormal
                 | ReleaseException

type RefCount = Word
type NextKey = Word

runResourceT :: (MonadBracket m, MonadIO m) => ResourceT m a -> m a
runResourceT :: forall (m :: * -> *) a.
(MonadBracket m, MonadIO m) =>
ResourceT m a -> m a
runResourceT (ResourceT PrimVar IO ReleaseMap -> m a
inner) = m (IORef ReleaseMap)
-> (IORef ReleaseMap -> a -> m ())
-> (IORef ReleaseMap -> SomeException -> m ())
-> (IORef ReleaseMap -> m a)
-> m a
forall a b ignored1 ignored2.
m a
-> (a -> b -> m ignored1)
-> (a -> SomeException -> m ignored2)
-> (a -> m b)
-> m b
forall (m :: * -> *) a b ignored1 ignored2.
MonadBracket m =>
m a
-> (a -> b -> m ignored1)
-> (a -> SomeException -> m ignored2)
-> (a -> m b)
-> m b
generalBracket
    (IO (IORef ReleaseMap) -> m (IORef ReleaseMap)
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (IORef ReleaseMap) -> m (IORef ReleaseMap))
-> IO (IORef ReleaseMap) -> m (IORef ReleaseMap)
forall a b. (a -> b) -> a -> b
$ ReleaseMap -> IO (PrimVar IO ReleaseMap)
forall a. a -> IO (PrimVar IO a)
forall (m :: * -> *) a. PrimMonad m => a -> m (PrimVar m a)
primVarNew (ReleaseMap -> IO (PrimVar IO ReleaseMap))
-> ReleaseMap -> IO (PrimVar IO ReleaseMap)
forall a b. (a -> b) -> a -> b
$ NextKey
-> NextKey -> [(NextKey, ReleaseType -> IO ())] -> ReleaseMap
ReleaseMap NextKey
forall a. Bounded a => a
maxBound (NextKey
forall a. Bounded a => a
minBound NextKey -> NextKey -> NextKey
forall a. Additive a => a -> a -> a
+ NextKey
1) [])
    (\IORef ReleaseMap
state a
_res -> IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef ReleaseMap -> ReleaseType -> IO ()
cleanup IORef ReleaseMap
state ReleaseType
ReleaseNormal)
    (\IORef ReleaseMap
state SomeException
_exc -> IO () -> m ()
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ IORef ReleaseMap -> ReleaseType -> IO ()
cleanup IORef ReleaseMap
state ReleaseType
ReleaseException)
    IORef ReleaseMap -> m a
PrimVar IO ReleaseMap -> m a
inner
  where
    cleanup :: IORef ReleaseMap -> ReleaseType -> IO ()
cleanup IORef ReleaseMap
istate ReleaseType
rtype = do
        Maybe [(NextKey, ReleaseType -> IO ())]
mm <- IORef ReleaseMap
-> (ReleaseMap
    -> (ReleaseMap, Maybe [(NextKey, ReleaseType -> IO ())]))
-> IO (Maybe [(NextKey, ReleaseType -> IO ())])
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef ReleaseMap
istate ((ReleaseMap
  -> (ReleaseMap, Maybe [(NextKey, ReleaseType -> IO ())]))
 -> IO (Maybe [(NextKey, ReleaseType -> IO ())]))
-> (ReleaseMap
    -> (ReleaseMap, Maybe [(NextKey, ReleaseType -> IO ())]))
-> IO (Maybe [(NextKey, ReleaseType -> IO ())])
forall a b. (a -> b) -> a -> b
$ \ReleaseMap
rm ->
            case ReleaseMap
rm of
                ReleaseMap NextKey
nk NextKey
rf [(NextKey, ReleaseType -> IO ())]
m ->
                    let rf' :: Difference NextKey
rf' = NextKey
rf NextKey -> NextKey -> Difference NextKey
forall a. Subtractive a => a -> a -> Difference a
- NextKey
1
                    in if NextKey
Difference NextKey
rf' NextKey -> NextKey -> Bool
forall a. Eq a => a -> a -> Bool
== NextKey
forall a. Bounded a => a
minBound
                            then (ReleaseMap
ReleaseMapClosed, [(NextKey, ReleaseType -> IO ())]
-> Maybe [(NextKey, ReleaseType -> IO ())]
forall a. a -> Maybe a
Just [(NextKey, ReleaseType -> IO ())]
m)
                            else (NextKey
-> NextKey -> [(NextKey, ReleaseType -> IO ())] -> ReleaseMap
ReleaseMap NextKey
nk NextKey
Difference NextKey
rf' [(NextKey, ReleaseType -> IO ())]
m, Maybe [(NextKey, ReleaseType -> IO ())]
forall a. Maybe a
Nothing)
                ReleaseMap
ReleaseMapClosed -> String -> (ReleaseMap, Maybe [(NextKey, ReleaseType -> IO ())])
forall a. HasCallStack => String -> a
error String
"runResourceT: cleanup on ReleaseMapClosed"
        case Maybe [(NextKey, ReleaseType -> IO ())]
mm of
            Just [(NextKey, ReleaseType -> IO ())]
m -> ((NextKey, ReleaseType -> IO ()) -> IO ())
-> [(NextKey, ReleaseType -> IO ())] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\(NextKey
_, ReleaseType -> IO ()
x) -> IO () -> IO ()
forall {m :: * -> *} {a}. MonadCatch m => m a -> m ()
ignoreExceptions (ReleaseType -> IO ()
x ReleaseType
rtype)) [(NextKey, ReleaseType -> IO ())]
m
            Maybe [(NextKey, ReleaseType -> IO ())]
Nothing -> () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      where
        ignoreExceptions :: m a -> m ()
ignoreExceptions m a
io = m a -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void m a
io m () -> (SomeException -> m ()) -> m ()
forall e a. Exception e => m a -> (e -> m a) -> m a
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> (e -> m a) -> m a
`catch` (\(SomeException
_ :: SomeException) -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ())

allocate :: (MonadResource m, MonadIO n) => IO a -> (a -> IO b) -> m (a, n ())
allocate :: forall (m :: * -> *) (n :: * -> *) a b.
(MonadResource m, MonadIO n) =>
IO a -> (a -> IO b) -> m (a, n ())
allocate IO a
acquire a -> IO b
release = ResourceT IO (a, n ()) -> m (a, n ())
forall a. ResourceT IO a -> m a
forall (m :: * -> *) a. MonadResource m => ResourceT IO a -> m a
liftResourceT (ResourceT IO (a, n ()) -> m (a, n ()))
-> ResourceT IO (a, n ()) -> m (a, n ())
forall a b. (a -> b) -> a -> b
$ (PrimVar IO ReleaseMap -> IO (a, n ())) -> ResourceT IO (a, n ())
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT ((PrimVar IO ReleaseMap -> IO (a, n ())) -> ResourceT IO (a, n ()))
-> (PrimVar IO ReleaseMap -> IO (a, n ()))
-> ResourceT IO (a, n ())
forall a b. (a -> b) -> a -> b
$ \PrimVar IO ReleaseMap
istate -> IO (a, n ()) -> IO (a, n ())
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (a, n ()) -> IO (a, n ())) -> IO (a, n ()) -> IO (a, n ())
forall a b. (a -> b) -> a -> b
$ IO (a, n ()) -> IO (a, n ())
forall a. IO a -> IO a
mask_ (IO (a, n ()) -> IO (a, n ())) -> IO (a, n ()) -> IO (a, n ())
forall a b. (a -> b) -> a -> b
$ do
    a
a <- IO a
acquire
    NextKey
key <- IORef ReleaseMap
-> (ReleaseMap -> (ReleaseMap, NextKey)) -> IO NextKey
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef ReleaseMap
PrimVar IO ReleaseMap
istate ((ReleaseMap -> (ReleaseMap, NextKey)) -> IO NextKey)
-> (ReleaseMap -> (ReleaseMap, NextKey)) -> IO NextKey
forall a b. (a -> b) -> a -> b
$ \ReleaseMap
rm ->
        case ReleaseMap
rm of
            ReleaseMap NextKey
key NextKey
rf [(NextKey, ReleaseType -> IO ())]
m ->
                ( NextKey
-> NextKey -> [(NextKey, ReleaseType -> IO ())] -> ReleaseMap
ReleaseMap (NextKey
key NextKey -> NextKey -> Difference NextKey
forall a. Subtractive a => a -> a -> Difference a
- NextKey
1) NextKey
rf ((NextKey
key, IO () -> ReleaseType -> IO ()
forall a b. a -> b -> a
const (IO () -> ReleaseType -> IO ()) -> IO () -> ReleaseType -> IO ()
forall a b. (a -> b) -> a -> b
$ IO b -> IO ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (IO b -> IO ()) -> IO b -> IO ()
forall a b. (a -> b) -> a -> b
$ a -> IO b
release a
a) (NextKey, ReleaseType -> IO ())
-> [(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
forall a. a -> [a] -> [a]
: [(NextKey, ReleaseType -> IO ())]
m)
                , NextKey
key
                )
            ReleaseMap
ReleaseMapClosed -> String -> (ReleaseMap, NextKey)
forall a. HasCallStack => String -> a
error String
"allocate: ReleaseMapClosed"
    let release' :: IO ()
release' = IO (IO ()) -> IO ()
forall (m :: * -> *) a. Monad m => m (m a) -> m a
join (IO (IO ()) -> IO ()) -> IO (IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ IORef ReleaseMap
-> (ReleaseMap -> (ReleaseMap, IO ())) -> IO (IO ())
forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef ReleaseMap
PrimVar IO ReleaseMap
istate ((ReleaseMap -> (ReleaseMap, IO ())) -> IO (IO ()))
-> (ReleaseMap -> (ReleaseMap, IO ())) -> IO (IO ())
forall a b. (a -> b) -> a -> b
$ \ReleaseMap
rm ->
            case ReleaseMap
rm of
                ReleaseMap NextKey
nextKey NextKey
rf [(NextKey, ReleaseType -> IO ())]
m ->
                    let loop :: ([(NextKey, ReleaseType -> IO ())]
 -> [(NextKey, ReleaseType -> IO ())])
-> [(NextKey, ReleaseType -> IO ())] -> (ReleaseMap, IO ())
loop [(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
front [] = (NextKey
-> NextKey -> [(NextKey, ReleaseType -> IO ())] -> ReleaseMap
ReleaseMap NextKey
nextKey NextKey
rf ([(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
front []), () -> IO ()
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ())
                        loop [(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
front ((NextKey
key', ReleaseType -> IO ()
action):[(NextKey, ReleaseType -> IO ())]
rest)
                            | NextKey
key NextKey -> NextKey -> Bool
forall a. Eq a => a -> a -> Bool
== NextKey
key' =
                                ( NextKey
-> NextKey -> [(NextKey, ReleaseType -> IO ())] -> ReleaseMap
ReleaseMap NextKey
nextKey NextKey
rf ([(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
front [(NextKey, ReleaseType -> IO ())]
rest)
                                , ReleaseType -> IO ()
action ReleaseType
ReleaseEarly
                                )
                            | Bool
otherwise = ([(NextKey, ReleaseType -> IO ())]
 -> [(NextKey, ReleaseType -> IO ())])
-> [(NextKey, ReleaseType -> IO ())] -> (ReleaseMap, IO ())
loop ([(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
front ([(NextKey, ReleaseType -> IO ())]
 -> [(NextKey, ReleaseType -> IO ())])
-> ([(NextKey, ReleaseType -> IO ())]
    -> [(NextKey, ReleaseType -> IO ())])
-> [(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ((NextKey
key', ReleaseType -> IO ()
action)(NextKey, ReleaseType -> IO ())
-> [(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
forall a. a -> [a] -> [a]
:)) [(NextKey, ReleaseType -> IO ())]
rest
                     in ([(NextKey, ReleaseType -> IO ())]
 -> [(NextKey, ReleaseType -> IO ())])
-> [(NextKey, ReleaseType -> IO ())] -> (ReleaseMap, IO ())
loop [(NextKey, ReleaseType -> IO ())]
-> [(NextKey, ReleaseType -> IO ())]
forall a. a -> a
forall {k} (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id [(NextKey, ReleaseType -> IO ())]
m
                ReleaseMap
ReleaseMapClosed -> String -> (ReleaseMap, IO ())
forall a. HasCallStack => String -> a
error String
"allocate: ReleaseMapClosed (2)"
    (a, n ()) -> IO (a, n ())
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
a, IO () -> n ()
forall a. IO a -> n a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ()
release')

class MonadIO m => MonadResource m where
    liftResourceT :: ResourceT IO a -> m a
instance MonadIO m => MonadResource (ResourceT m) where
    liftResourceT :: forall a. ResourceT IO a -> ResourceT m a
liftResourceT (ResourceT PrimVar IO ReleaseMap -> IO a
f) = (PrimVar IO ReleaseMap -> m a) -> ResourceT m a
forall (m :: * -> *) a.
(PrimVar IO ReleaseMap -> m a) -> ResourceT m a
ResourceT (IO a -> m a
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a)
-> (IORef ReleaseMap -> IO a) -> IORef ReleaseMap -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. IORef ReleaseMap -> IO a
PrimVar IO ReleaseMap -> IO a
f)
instance MonadResource m => MonadResource (Conduit i o m) where
    liftResourceT :: forall a. ResourceT IO a -> Conduit i o m a
liftResourceT = m a -> Conduit i o m a
forall (m :: * -> *) a. Monad m => m a -> Conduit i o m a
forall (trans :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans trans, Monad m) =>
m a -> trans m a
lift (m a -> Conduit i o m a)
-> (ResourceT IO a -> m a) -> ResourceT IO a -> Conduit i o m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
forall {k} (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. ResourceT IO a -> m a
forall a. ResourceT IO a -> m a
forall (m :: * -> *) a. MonadResource m => ResourceT IO a -> m a
liftResourceT