module Foundation.Conduit
    ( Conduit
    , ResourceT
    , ZipSink (..)
    , await
    , awaitForever
    , yield
    , yields
    , yieldOr
    , leftover
    , runConduit
    , runConduitPure
    , runConduitRes
    , fuse
    , (.|)
    , sourceFile
    , sourceHandle
    , sinkFile
    , sinkHandle
    , sinkList
    , bracketConduit
    ) where

import Foundation.Conduit.Internal
import Foundation.Collection
import Foundation.IO
import Foundation.IO.File
import Basement.Compat.Base
import Foundation.Monad.Base
import Foundation.Array
import Foundation
import System.IO (Handle)


infixr 2 .|
-- | Operator version of 'fuse'.
(.|) :: Monad m => Conduit a b m () -> Conduit b c m r -> Conduit a c m r
.| :: Conduit a b m () -> Conduit b c m r -> Conduit a c m r
(.|) = Conduit a b m () -> Conduit b c m r -> Conduit a c m r
forall (m :: * -> *) a b c r.
Monad m =>
Conduit a b m () -> Conduit b c m r -> Conduit a c m r
fuse
{-# INLINE (.|) #-}

sourceFile :: MonadResource m => FilePath -> Conduit i (UArray Word8) m ()
sourceFile :: FilePath -> Conduit i (UArray Word8) m ()
sourceFile FilePath
fp = IO Handle
-> (Handle -> IO ())
-> (Handle -> Conduit i (UArray Word8) m ())
-> Conduit i (UArray Word8) m ()
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
    (FilePath -> IOMode -> IO Handle
openFile FilePath
fp IOMode
ReadMode)
    Handle -> IO ()
closeFile
    Handle -> Conduit i (UArray Word8) m ()
forall (m :: * -> *) i.
MonadIO m =>
Handle -> Conduit i (UArray Word8) m ()
sourceHandle

sourceHandle :: MonadIO m
             => Handle
             -> Conduit i (UArray Word8) m ()
sourceHandle :: Handle -> Conduit i (UArray Word8) m ()
sourceHandle Handle
h =
    Conduit i (UArray Word8) m ()
loop
  where
    defaultChunkSize :: Int
    defaultChunkSize :: Int
defaultChunkSize = (Int
32 :: Int) Int -> Int -> Int
forall a. Multiplicative a => a -> a -> a
* Int
1000 Int -> Int -> Difference Int
forall a. Subtractive a => a -> a -> Difference a
- Int
16
    loop :: Conduit i (UArray Word8) m ()
loop = do
        UArray Word8
arr <- IO (UArray Word8) -> Conduit i (UArray Word8) m (UArray Word8)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> Int -> IO (UArray Word8)
hGet Handle
h Int
defaultChunkSize)
        if UArray Word8 -> Bool
forall c. Collection c => c -> Bool
null UArray Word8
arr
            then () -> Conduit i (UArray Word8) m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
            else UArray Word8 -> Conduit i (UArray Word8) m ()
forall (m :: * -> *) o i. Monad m => o -> Conduit i o m ()
yield UArray Word8
arr Conduit i (UArray Word8) m ()
-> Conduit i (UArray Word8) m () -> Conduit i (UArray Word8) m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Conduit i (UArray Word8) m ()
loop

-- | Send values downstream.
yields :: (Monad m, Foldable os, Element os ~ o) => os -> Conduit i o m ()
-- FIXME: Should be using mapM_ once that is in Foldable, see #334
yields :: os -> Conduit i o m ()
yields = (Element os -> Conduit i o m () -> Conduit i o m ())
-> Conduit i o m () -> os -> Conduit i o m ()
forall collection a.
Foldable collection =>
(Element collection -> a -> a) -> a -> collection -> a
foldr (Conduit i o m () -> Conduit i o m () -> Conduit i o m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
(>>) (Conduit i o m () -> Conduit i o m () -> Conduit i o m ())
-> (o -> Conduit i o m ())
-> o
-> Conduit i o m ()
-> Conduit i o m ()
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. o -> Conduit i o m ()
forall (m :: * -> *) o i. Monad m => o -> Conduit i o m ()
yield) (() -> Conduit i o m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())


sinkFile :: MonadResource m => FilePath -> Conduit (UArray Word8) i m ()
sinkFile :: FilePath -> Conduit (UArray Word8) i m ()
sinkFile FilePath
fp = IO Handle
-> (Handle -> IO ())
-> (Handle -> Conduit (UArray Word8) i m ())
-> Conduit (UArray Word8) i m ()
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
    (FilePath -> IOMode -> IO Handle
openFile FilePath
fp IOMode
WriteMode)
    Handle -> IO ()
closeFile
    Handle -> Conduit (UArray Word8) i m ()
forall (m :: * -> *) o.
MonadIO m =>
Handle -> Conduit (UArray Word8) o m ()
sinkHandle

sinkHandle :: MonadIO m
           => Handle
           -> Conduit (UArray Word8) o m ()
sinkHandle :: Handle -> Conduit (UArray Word8) o m ()
sinkHandle Handle
h =
    Conduit (UArray Word8) o m ()
loop
  where
    loop :: Conduit (UArray Word8) o m ()
loop = Conduit (UArray Word8) o m (Maybe (UArray Word8))
forall i o (m :: * -> *). Conduit i o m (Maybe i)
await Conduit (UArray Word8) o m (Maybe (UArray Word8))
-> (Maybe (UArray Word8) -> Conduit (UArray Word8) o m ())
-> Conduit (UArray Word8) o m ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Conduit (UArray Word8) o m ()
-> (UArray Word8 -> Conduit (UArray Word8) o m ())
-> Maybe (UArray Word8)
-> Conduit (UArray Word8) o m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
        (() -> Conduit (UArray Word8) o m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
        (\UArray Word8
arr -> IO () -> Conduit (UArray Word8) o m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (Handle -> UArray Word8 -> IO ()
hPut Handle
h UArray Word8
arr) Conduit (UArray Word8) o m ()
-> Conduit (UArray Word8) o m () -> Conduit (UArray Word8) o m ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Conduit (UArray Word8) o m ()
loop)

sinkList :: Monad m => Conduit i o m [i]
sinkList :: Conduit i o m [i]
sinkList =
    ([i] -> [i]) -> Conduit i o m [i]
forall a c o (m :: * -> *). ([a] -> c) -> Conduit a o m c
loop [i] -> [i]
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id
  where
    loop :: ([a] -> c) -> Conduit a o m c
loop [a] -> c
front = Conduit a o m (Maybe a)
forall i o (m :: * -> *). Conduit i o m (Maybe i)
await Conduit a o m (Maybe a)
-> (Maybe a -> Conduit a o m c) -> Conduit a o m c
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Conduit a o m c
-> (a -> Conduit a o m c) -> Maybe a -> Conduit a o m c
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
        (c -> Conduit a o m c
forall (m :: * -> *) a. Monad m => a -> m a
return ([a] -> c
front []))
        (\a
x -> ([a] -> c) -> Conduit a o m c
loop ([a] -> c
front ([a] -> c) -> ([a] -> [a]) -> [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
xa -> [a] -> [a]
forall a. a -> [a] -> [a]
:)))