@@ -21,10 +21,13 @@ module Streamly.Internal.FileSystem.Dir
21 -- ** Read from Directory
21 -- ** Read from Directory
23 , readFiles
23 , readFiles
25− , readWithBufferOf
26+ -- , readWithBufferOf
27 , toStream
28 , toStream
28 , toStreamWithBufferOf
31 , toStreamWithBufferOf
30 , readChunks
33 , readChunks
@@ -53,31 +56,32 @@ module Streamly.Internal.FileSystem.Dir
55import Control.Monad.IO.Class (MonadIO(..))
58import Control.Monad.IO.Class (MonadIO(..))
59+import Data.Either (isRight, fromRight, isLeft, fromLeft)
56−import Data.Word (Word8)
60+-- import Data.Word (Word8)
57−import Foreign.ForeignPtr (withForeignPtr)
61+-- import Foreign.ForeignPtr (withForeignPtr)
58−import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
62+-- import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
59−import Foreign.Ptr (minusPtr, plusPtr)
63+-- import Foreign.Ptr (minusPtr, plusPtr)
60−import Foreign.Storable (Storable(..))
64+-- import Foreign.Storable (Storable(..))
61−import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
65+-- import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
62−import System.IO (Handle, hGetBufSome, hPutBuf)
66+-- import System.IO (Handle, hGetBufSome, hPutBuf)
63import Prelude hiding (read)
67import Prelude hiding (read)
65−import Streamly.Data.Fold (Fold)
69+-- import Streamly.Data.Fold (Fold)
66import Streamly.Internal.Data.Unfold.Types (Unfold(..))
70import Streamly.Internal.Data.Unfold.Types (Unfold(..))
67−import Streamly.Internal.Memory.Array.Types
71+-- import Streamly.Internal.Memory.Array.Types
68− (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
72+-- (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
69− lpackArraysChunksOf)
73+-- lpackArraysChunksOf)
70−import Streamly.Streams.Serial (SerialT)
74+-- import Streamly.Streams.Serial (SerialT)
71−import Streamly.Streams.StreamK.Type (IsStream, mkStream)
75+import Streamly.Streams.StreamK.Type (IsStream)
72-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
76-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
74−import qualified Streamly.Data.Fold as FL
78+-- import qualified Streamly.Data.Fold as FL
75−import qualified Streamly.Internal.Data.Fold.Types as FL
79+-- import qualified Streamly.Internal.Data.Fold.Types as FL
76import qualified Streamly.Internal.Data.Unfold as UF
80import qualified Streamly.Internal.Data.Unfold as UF
77−import qualified Streamly.Internal.Memory.ArrayStream as AS
81+-- import qualified Streamly.Internal.Memory.ArrayStream as AS
78import qualified Streamly.Internal.Prelude as S
82import qualified Streamly.Internal.Prelude as S
79−import qualified Streamly.Memory.Array as A
83+-- import qualified Streamly.Memory.Array as A
80−import qualified Streamly.Streams.StreamD.Type as D
84+-- import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
81import qualified System.Directory as Dir
85import qualified System.Directory as Dir
@@ -200,33 +204,71 @@ toStreamWithBufferOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
200toStreamWithBufferOf chunkSize h = AS.concat $ toChunksWithBufferOf chunkSize h
204toStreamWithBufferOf chunkSize h = AS.concat $ toChunksWithBufferOf chunkSize h
203−-- TODO
207+-- XXX exception handling
204−-- Generate a stream of elements of the given type from a file 'Handle'.
208+-- | Raw read of a directory
205−-- read :: (IsStream t, MonadIO m, Storable a) => Handle -> t m a
207−-- | Unfolds a file handle into a byte stream. IO requests to the device are
210+-- /Internal/
208−-- performed in sizes of
209−-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'.
212−-- XXX exception handling
213−-- XXX this is not stream read
214{-# INLINE read #-}
212{-# INLINE read #-}
215read :: MonadIO m => Unfold m String String
213read :: MonadIO m => Unfold m String String
215+ -- XXX use proper streaming read of the dir
216−read = UF.lmapM (liftIO . Dir.getDirectoryContents) UF.fromList
216+ UF.lmapM (liftIO . Dir.getDirectoryContents) UF.fromList
218+-- XXX We can use a more general mechanism to filter the contents of a
219+-- directory. We can just stat each child and pass on the stat information. We
220+-- can then use that info to do a general filtering. "find" like filters can be
223+-- | Read directories as Left and files as Right. Filter out "." and ".."
228+{-# INLINE readEither #-}
229+readEither :: MonadIO m => Unfold m String (Either String String)
231+ UF.mapMWithInput classify
232+ $ UF.filter (\x -> x /= "." && x /= "..")
233+ -- XXX use proper streaming read of the dir
234+ $ UF.lmapM (liftIO . Dir.getDirectoryContents) UF.fromList
237+ r <- liftIO $ Dir.doesDirectoryExist (dir ++ "/" ++ x)
238+ return $ if r then Left x else Right x
241+-- | Read files only.
218{-# INLINE readFiles #-}
245{-# INLINE readFiles #-}
219readFiles :: MonadIO m => Unfold m String String
246readFiles :: MonadIO m => Unfold m String String
220−readFiles = UF.filterM (fmap not . liftIO . Dir.doesDirectoryExist) read
247+readFiles = UF.map (fromRight undefined) $ UF.filter isRight readEither
222−{-
249+-- | Read directories only. Filter out "." and ".." entries.
223−-- | Generate a byte stream from a file 'Handle'.
250+--
253+{-# INLINE readDirs #-}
254+readDirs :: MonadIO m => Unfold m String String
255+readDirs = UF.map (fromLeft undefined) $ UF.filter isLeft readEither
257+-- | Raw read of a directory.
225-- /Internal/
259-- /Internal/
226{-# INLINE toStream #-}
260{-# INLINE toStream #-}
227−toStream :: (IsStream t, MonadIO m) => Handle -> t m Word8
261+toStream :: (IsStream t, MonadIO m) => String -> t m String
228−toStream = AS.concat . toChunks
262+toStream = S.unfold read
264+-- | Read directories as Left and files as Right. Filter out "." and ".."
268+{-# INLINE toStreamEither #-}
269+toStreamEither :: (IsStream t, MonadIO m)
270+ => String -> t m (Either String String)
271+toStreamEither = S.unfold readEither
232-------------------------------------------------------------------------------
274-------------------------------------------------------------------------------