@@ -0,0 +1,37 @@
1+{-# LANGUAGE FlexibleContexts #-}
2+module Data.Conduit.Binary
3+ ( sourceFile
4+ , sinkFile
5+ ) where
6+
7+import Prelude hiding (FilePath)
8+import System.IO (hClose)
9+import Filesystem.Path.CurrentOS (FilePath)
10+import qualified Data.ByteString as S
11+import Filesystem (openFile, IOMode (ReadMode, WriteMode))
12+import Data.Conduit
13+import Control.Monad.Trans.Control (MonadBaseControl)
14+import Control.Monad.Base (liftBase)
15+import Control.Monad.Trans.Resource (with, release)
16+
17+sourceFile :: MonadBaseControl IO m
18+ => FilePath
19+ -> Source m S.ByteString
20+sourceFile fp = Source $ do
21+ (key, handle) <- with (liftBase $ openFile fp ReadMode) (liftBase . hClose)
22+ unSource $ mkSource $ do
23+ bs <- liftBase $ S.hGetSome handle 50
24+ -- FIXME protection against being called after close?
25+ if S.null bs
26+ then release key >> return EOF
27+ else return $ Chunks [bs]
28+
29+sinkFile :: MonadBaseControl IO m
30+ => FilePath
31+ -> Sink S.ByteString m ()
32+sinkFile fp = Sink $ do
33+ (key, handle) <- with (liftBase $ openFile fp WriteMode) (liftBase . hClose)
34+ return $ SinkData $ \stream -> do
35+ case stream of
36+ EOF -> release key >> return (SinkResult [] (Just ()))
37+ Chunks bss -> mapM_ (liftBase . S.hPut handle) bss >> return (SinkResult [] Nothing)