@@ -21,10 +21,13 @@ module Streamly.Internal.FileSystem.Dir
2121 -- ** Read from Directory
2222 read
2323 , readFiles
24− {-
25− , readWithBufferOf
24+ , readDirs
25+ , readEither
26+ -- , readWithBufferOf
2627
2728 , toStream
29+ , toStreamEither
30+ {-
2831 , toStreamWithBufferOf
2932
3033 , readChunks
@@ -53,31 +56,32 @@ module Streamly.Internal.FileSystem.Dir
5356where
5457
5558import Control.Monad.IO.Class (MonadIO(..))
56−import Data.Word (Word8)
57−import Foreign.ForeignPtr (withForeignPtr)
58−import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
59−import Foreign.Ptr (minusPtr, plusPtr)
60−import Foreign.Storable (Storable(..))
61−import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
62−import System.IO (Handle, hGetBufSome, hPutBuf)
59+import Data.Either (isRight, fromRight, isLeft, fromLeft)
60+-- import Data.Word (Word8)
61+-- import Foreign.ForeignPtr (withForeignPtr)
62+-- import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
63+-- import Foreign.Ptr (minusPtr, plusPtr)
64+-- import Foreign.Storable (Storable(..))
65+-- import GHC.ForeignPtr (mallocPlainForeignPtrBytes)
66+-- import System.IO (Handle, hGetBufSome, hPutBuf)
6367import Prelude hiding (read)
6468
65−import Streamly.Data.Fold (Fold)
69+-- import Streamly.Data.Fold (Fold)
6670import Streamly.Internal.Data.Unfold.Types (Unfold(..))
67−import Streamly.Internal.Memory.Array.Types
68− (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
69− lpackArraysChunksOf)
70−import Streamly.Streams.Serial (SerialT)
71−import Streamly.Streams.StreamK.Type (IsStream, mkStream)
71+-- import Streamly.Internal.Memory.Array.Types
72+-- (Array(..), writeNUnsafe, defaultChunkSize, shrinkToFit,
73+-- lpackArraysChunksOf)
74+-- import Streamly.Streams.Serial (SerialT)
75+import Streamly.Streams.StreamK.Type (IsStream)
7276-- import Streamly.String (encodeUtf8, decodeUtf8, foldLines)
7377
74−import qualified Streamly.Data.Fold as FL
75−import qualified Streamly.Internal.Data.Fold.Types as FL
78+-- import qualified Streamly.Data.Fold as FL
79+-- import qualified Streamly.Internal.Data.Fold.Types as FL
7680import 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
7882import qualified Streamly.Internal.Prelude as S
79−import qualified Streamly.Memory.Array as A
80−import qualified Streamly.Streams.StreamD.Type as D
83+-- import qualified Streamly.Memory.Array as A
84+-- import qualified Streamly.Internal.Data.Stream.StreamD.Type as D
8185import qualified System.Directory as Dir
8286
8387{-
@@ -200,33 +204,71 @@ toStreamWithBufferOf :: (IsStream t, MonadIO m) => Int -> Handle -> t m Word8
200204toStreamWithBufferOf chunkSize h = AS.concat $ toChunksWithBufferOf chunkSize h
201205-}
202206
203−-- TODO
204−-- Generate a stream of elements of the given type from a file 'Handle'.
205−-- read :: (IsStream t, MonadIO m, Storable a) => Handle -> t m a
207+-- XXX exception handling
208+-- | Raw read of a directory
206209--
207−-- | Unfolds a file handle into a byte stream. IO requests to the device are
208−-- performed in sizes of
209−-- 'Streamly.Internal.Memory.Array.Types.defaultChunkSize'.
210+-- /Internal/
210211--
211−-- @since 0.7.0
212−-- XXX exception handling
213−-- XXX this is not stream read
214212{-# INLINE read #-}
215213read :: MonadIO m => Unfold m String String
216−read = UF.lmapM (liftIO . Dir.getDirectoryContents) UF.fromList
214+read =
215+ -- XXX use proper streaming read of the dir
216+ UF.lmapM (liftIO . Dir.getDirectoryContents) UF.fromList
217+
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
221+-- created.
222+
223+-- | Read directories as Left and files as Right. Filter out "." and ".."
224+-- entries.
225+--
226+-- /Internal/
227+--
228+{-# INLINE readEither #-}
229+readEither :: MonadIO m => Unfold m String (Either String String)
230+readEither =
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
235+ where
236+ classify dir x = do
237+ r <- liftIO $ Dir.doesDirectoryExist (dir ++ "/" ++ x)
238+ return $ if r then Left x else Right x
217239
240+--
241+-- | Read files only.
242+--
243+-- /Internal/
244+--
218245{-# INLINE readFiles #-}
219246readFiles :: 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
221248
222−{-
223−-- | Generate a byte stream from a file 'Handle'.
249+-- | Read directories only. Filter out "." and ".." entries.
250+--
251+-- /Internal/
252+--
253+{-# INLINE readDirs #-}
254+readDirs :: MonadIO m => Unfold m String String
255+readDirs = UF.map (fromLeft undefined) $ UF.filter isLeft readEither
256+
257+-- | Raw read of a directory.
224258--
225259-- /Internal/
226260{-# INLINE toStream #-}
227−toStream :: (IsStream t, MonadIO m) => Handle -> t m Word8
228−toStream = AS.concat . toChunks
229−-}
261+toStream :: (IsStream t, MonadIO m) => String -> t m String
262+toStream = S.unfold read
263+
264+-- | Read directories as Left and files as Right. Filter out "." and ".."
265+-- entries.
266+--
267+-- /Internal/
268+{-# INLINE toStreamEither #-}
269+toStreamEither :: (IsStream t, MonadIO m)
270+ => String -> t m (Either String String)
271+toStreamEither = S.unfold readEither
230272
231273{-
232274-------------------------------------------------------------------------------