{-# LANGUAGE CPP #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiWayIf #-}
module Streamly.External.Posix.DirStream
(
unfoldDirContents
, dirContentsStream
, dirContents
)
where
import Control.Exception.Safe
import Control.Monad.IO.Class ( liftIO
, MonadIO
)
import Data.Word8
import Prelude hiding ( readFile )
import System.Posix.ByteString
import System.Posix.Directory.ByteString
as PosixBS
import System.Posix.Foreign ( DirType )
import System.Posix.RawFilePath.Directory.Traversals
hiding ( getDirectoryContents )
import qualified Data.ByteString as BS
import qualified Streamly.Internal.Data.Stream.StreamD.Type
as D
#if MIN_VERSION_streamly(0,7,1)
import qualified Streamly.Internal.Data.Unfold as SIU
#endif
#if MIN_VERSION_streamly(0,8,0)
import Streamly.Prelude
import Streamly.Internal.Data.Unfold.Type
#else
import Streamly
import Streamly.Internal.Data.Unfold.Types
import qualified Streamly.Internal.Prelude as S
#endif
unfoldDirContents :: MonadIO m => Unfold m DirStream (DirType, RawFilePath)
unfoldDirContents :: Unfold m DirStream (DirType, RawFilePath)
unfoldDirContents = (DirStream -> m (Step DirStream (DirType, RawFilePath)))
-> (DirStream -> m DirStream)
-> Unfold m DirStream (DirType, RawFilePath)
forall (m :: * -> *) a b s.
(s -> m (Step s b)) -> (a -> m s) -> Unfold m a b
Unfold DirStream -> m (Step DirStream (DirType, RawFilePath))
forall (m :: * -> *).
MonadIO m =>
DirStream -> m (Step DirStream (DirType, RawFilePath))
step DirStream -> m DirStream
forall (m :: * -> *) a. Monad m => a -> m a
return
where
{-# INLINE [0] step #-}
step :: DirStream -> m (Step DirStream (DirType, RawFilePath))
step DirStream
dirstream = do
(DirType
typ, RawFilePath
e) <- IO (DirType, RawFilePath) -> m (DirType, RawFilePath)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (DirType, RawFilePath) -> m (DirType, RawFilePath))
-> IO (DirType, RawFilePath) -> m (DirType, RawFilePath)
forall a b. (a -> b) -> a -> b
$ DirStream -> IO (DirType, RawFilePath)
readDirEnt DirStream
dirstream
Step DirStream (DirType, RawFilePath)
-> m (Step DirStream (DirType, RawFilePath))
forall (m :: * -> *) a. Monad m => a -> m a
return (Step DirStream (DirType, RawFilePath)
-> m (Step DirStream (DirType, RawFilePath)))
-> Step DirStream (DirType, RawFilePath)
-> m (Step DirStream (DirType, RawFilePath))
forall a b. (a -> b) -> a -> b
$ if
| RawFilePath -> Bool
BS.null RawFilePath
e -> Step DirStream (DirType, RawFilePath)
forall s a. Step s a
D.Stop
| [Word8] -> RawFilePath
BS.pack [Word8
_period] RawFilePath -> RawFilePath -> Bool
forall a. Eq a => a -> a -> Bool
== RawFilePath
e -> DirStream -> Step DirStream (DirType, RawFilePath)
forall s a. s -> Step s a
D.Skip DirStream
dirstream
| [Word8] -> RawFilePath
BS.pack [Word8
_period, Word8
_period] RawFilePath -> RawFilePath -> Bool
forall a. Eq a => a -> a -> Bool
== RawFilePath
e -> DirStream -> Step DirStream (DirType, RawFilePath)
forall s a. s -> Step s a
D.Skip DirStream
dirstream
| Bool
otherwise -> (DirType, RawFilePath)
-> DirStream -> Step DirStream (DirType, RawFilePath)
forall s a. a -> s -> Step s a
D.Yield (DirType
typ, RawFilePath
e) DirStream
dirstream
dirContentsStream :: (MonadCatch m, MonadAsync m, MonadMask m)
=> DirStream
-> SerialT m (DirType, RawFilePath)
dirContentsStream :: DirStream -> SerialT m (DirType, RawFilePath)
dirContentsStream DirStream
ds =
#if MIN_VERSION_streamly(0,8,0)
Unfold m DirStream (DirType, RawFilePath)
-> DirStream -> SerialT m (DirType, RawFilePath)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a b.
(IsStream t, Monad m) =>
Unfold m a b -> a -> t m b
unfold ((DirStream -> m ())
-> Unfold m DirStream (DirType, RawFilePath)
-> Unfold m DirStream (DirType, RawFilePath)
forall (m :: * -> *) a c b.
(MonadAsync m, MonadCatch m) =>
(a -> m c) -> Unfold m a b -> Unfold m a b
SIU.finally (IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (DirStream -> IO ()) -> DirStream -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DirStream -> IO ()
PosixBS.closeDirStream) Unfold m DirStream (DirType, RawFilePath)
forall (m :: * -> *).
MonadIO m =>
Unfold m DirStream (DirType, RawFilePath)
unfoldDirContents) (DirStream -> SerialT m (DirType, RawFilePath))
-> DirStream -> SerialT m (DirType, RawFilePath)
forall a b. (a -> b) -> a -> b
$ DirStream
ds
#else
#if MIN_VERSION_streamly(0,7,1)
S.unfold (SIU.finallyIO (liftIO . PosixBS.closeDirStream) unfoldDirContents) $ ds
#else
S.finally (liftIO . PosixBS.closeDirStream $ ds) . S.unfold unfoldDirContents $ ds
#endif
#endif
dirContents :: (MonadCatch m, MonadAsync m, MonadMask m)
=> DirStream
-> m [(DirType, RawFilePath)]
#if MIN_VERSION_streamly(0,8,0)
dirContents :: DirStream -> m [(DirType, RawFilePath)]
dirContents = SerialT m (DirType, RawFilePath) -> m [(DirType, RawFilePath)]
forall (m :: * -> *) a. Monad m => SerialT m a -> m [a]
toList (SerialT m (DirType, RawFilePath) -> m [(DirType, RawFilePath)])
-> (DirStream -> SerialT m (DirType, RawFilePath))
-> DirStream
-> m [(DirType, RawFilePath)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DirStream -> SerialT m (DirType, RawFilePath)
forall (m :: * -> *).
(MonadCatch m, MonadAsync m, MonadMask m) =>
DirStream -> SerialT m (DirType, RawFilePath)
dirContentsStream
#else
dirContents = S.toList . dirContentsStream
#endif