{-# LANGUAGE TemplateHaskell #-}
#if defined(IS_WINDOWS)
#define OS_NAME Windows
#define OS_PATH WindowsPath
#define WORD_TYPE Word16
#define UNICODE_ENCODER encodeUtf16le'
#define UNICODE_DECODER decodeUtf16le'
#define UNICODE_DECODER_LAX decodeUtf16le
#define CODEC_NAME UTF-16LE
#define SEPARATORS @/, \\@
#else
#define OS_NAME Posix
#define OS_PATH PosixPath
#define WORD_TYPE Word8
#define UNICODE_ENCODER encodeUtf8'
#define UNICODE_DECODER decodeUtf8'
#define UNICODE_DECODER_LAX decodeUtf8
#define CODEC_NAME UTF-8
#define SEPARATORS @/@
#endif
module Streamly.Internal.FileSystem.OS_PATH
(
OS_PATH (..)
, IsPath (..)
, adapt
, validatePath
, validatePath'
, isValidPath
, fromChunk
, unsafeFromChunk
, fromChars
, fromString
, unsafeFromString
, readRaw
, path
, pathE
, toChunk
, toChars
, toChars_
, toString
, toString_
, showRaw
, dropTrailingSeparators
, isRooted
, isBranch
, unsafeAppend
, append
, append'
#ifndef IS_WINDOWS
, appendCString
, appendCString'
#endif
, splitRoot
, splitPath
, splitPath_
, splitFile
, splitExtension
, eqPath
, EqCfg(..)
, eqCfg
, eqPathWith
, eqPathBytes
)
where
import Control.Monad.Catch (MonadThrow(..))
import Data.Bifunctor (bimap)
import Data.Functor.Identity (Identity(..))
import Data.Maybe (fromJust)
import Data.Word (Word8)
#if defined(IS_WINDOWS)
import Data.Word (Word16)
#endif
#ifndef IS_WINDOWS
import Foreign.C (CString)
#endif
import Language.Haskell.TH.Syntax (lift)
import Streamly.Internal.Data.Array (Array(..))
import Streamly.Internal.Data.Stream (Stream)
import Streamly.Internal.FileSystem.Path.Common (mkQ, EqCfg(..), eqCfg)
import qualified Streamly.Internal.Data.Stream as Stream
import qualified Streamly.Internal.FileSystem.Path.Common as Common
import qualified Streamly.Internal.Unicode.Stream as Unicode
import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Streamly.Internal.Data.Path
newtype OS_PATH = OS_PATH (Array WORD_TYPE)
instance IsPath OS_PATH OS_PATH where
unsafeFromPath :: PosixPath -> PosixPath
unsafeFromPath = PosixPath -> PosixPath
forall a. a -> a
id
fromPath :: forall (m :: * -> *). MonadThrow m => PosixPath -> m PosixPath
fromPath = PosixPath -> m PosixPath
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
toPath :: PosixPath -> PosixPath
toPath = PosixPath -> PosixPath
forall a. a -> a
id
adapt :: (MonadThrow m, IsPath OS_PATH a, IsPath OS_PATH b) => a -> m b
adapt :: forall (m :: * -> *) a b.
(MonadThrow m, IsPath PosixPath a, IsPath PosixPath b) =>
a -> m b
adapt a
p = PosixPath -> m b
forall a b (m :: * -> *). (IsPath a b, MonadThrow m) => a -> m b
forall (m :: * -> *). MonadThrow m => PosixPath -> m b
fromPath (a -> PosixPath
forall a b. IsPath a b => b -> a
toPath a
p :: OS_PATH)
{-# INLINE dropTrailingSeparators #-}
dropTrailingSeparators :: OS_PATH -> OS_PATH
dropTrailingSeparators :: PosixPath -> PosixPath
dropTrailingSeparators (OS_PATH arr) =
OS_PATH (Common.dropTrailingSeparators Common.OS_NAME arr)
validatePath :: MonadThrow m => OS_PATH -> m ()
validatePath :: forall (m :: * -> *). MonadThrow m => PosixPath -> m ()
validatePath (OS_PATH a) = Common.validatePath Common.OS_NAME a
isValidPath :: OS_PATH -> Bool
isValidPath :: PosixPath -> Bool
isValidPath (OS_PATH a) = Common.isValidPath Common.OS_NAME a
validatePath' :: MonadThrow m =>
OS_PATH -> m ()
validatePath' :: forall (m :: * -> *). MonadThrow m => PosixPath -> m ()
validatePath'
(OS_PATH a) = Common.validatePath'
Common.OS_NAME a
{-# INLINE unsafeFromChunk #-}
unsafeFromChunk :: IsPath OS_PATH a => Array Word8 -> a
unsafeFromChunk :: forall a. IsPath PosixPath a => Array Word8 -> a
unsafeFromChunk =
#ifndef DEBUG
PosixPath -> a
forall a b. IsPath a b => a -> b
unsafeFromPath (PosixPath -> a) -> (Array Word8 -> PosixPath) -> Array Word8 -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS_PATH . Common.unsafeFromChunk
#else
fromJust . fromChunk
#endif
fromChunk :: (MonadThrow m, IsPath OS_PATH a) => Array Word8 -> m a
fromChunk :: forall (m :: * -> *) a.
(MonadThrow m, IsPath PosixPath a) =>
Array Word8 -> m a
fromChunk Array Word8
arr = OS -> Array Word8 -> m (Array Word8)
forall (m :: * -> *) a.
(MonadThrow m, Unbox a, Integral a) =>
OS -> Array Word8 -> m (Array a)
Common.fromChunk Common.OS_NAME arr >>= fromPath . OS_PATH
#if defined(IS_WINDOWS)
#endif
{-# INLINE fromChars #-}
fromChars :: (MonadThrow m, IsPath OS_PATH a) => Stream Identity Char -> m a
fromChars :: forall (m :: * -> *) a.
(MonadThrow m, IsPath PosixPath a) =>
Stream Identity Char -> m a
fromChars Stream Identity Char
s =
OS
-> (Stream Identity Char -> Stream Identity Word8)
-> Stream Identity Char
-> m (Array Word8)
forall (m :: * -> *) a.
(MonadThrow m, Unbox a, Integral a) =>
OS
-> (Stream Identity Char -> Stream Identity a)
-> Stream Identity Char
-> m (Array a)
Common.fromChars Common.OS_NAME Unicode.UNICODE_ENCODER s
m (Array Word8) -> (Array Word8 -> m a) -> m a
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= PosixPath -> m a
forall a b (m :: * -> *). (IsPath a b, MonadThrow m) => a -> m b
forall (m :: * -> *). MonadThrow m => PosixPath -> m a
fromPath (PosixPath -> m a)
-> (Array Word8 -> PosixPath) -> Array Word8 -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS_PATH
unsafeFromString :: IsPath OS_PATH a => [Char] -> a
unsafeFromString :: forall a. IsPath PosixPath a => [Char] -> a
unsafeFromString =
#ifndef DEBUG
PosixPath -> a
forall a b. IsPath a b => a -> b
unsafeFromPath
(PosixPath -> a) -> ([Char] -> PosixPath) -> [Char] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OS_PATH
(Array Word8 -> PosixPath)
-> ([Char] -> Array Word8) -> [Char] -> PosixPath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Stream Identity Char -> Stream Identity Word8)
-> Stream Identity Char -> Array Word8
forall a.
Unbox a =>
(Stream Identity Char -> Stream Identity a)
-> Stream Identity Char -> Array a
Common.unsafeFromChars Unicode.UNICODE_ENCODER
(Stream Identity Char -> Array Word8)
-> ([Char] -> Stream Identity Char) -> [Char] -> Array Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Stream Identity Char
forall (m :: * -> *) a. Applicative m => [a] -> Stream m a
Stream.fromList
#else
fromJust . fromString
#endif
fromString :: (MonadThrow m, IsPath OS_PATH a) => [Char] -> m a
fromString :: forall (m :: * -> *) a.
(MonadThrow m, IsPath PosixPath a) =>
[Char] -> m a
fromString = Stream Identity Char -> m a
forall (m :: * -> *) a.
(MonadThrow m, IsPath PosixPath a) =>
Stream Identity Char -> m a
fromChars (Stream Identity Char -> m a)
-> ([Char] -> Stream Identity Char) -> [Char] -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Stream Identity Char
forall (m :: * -> *) a. Applicative m => [a] -> Stream m a
Stream.fromList
liftPath :: OS_PATH -> Q Exp
liftPath :: PosixPath -> Q Exp
liftPath PosixPath
p =
[| unsafeFromString $([Char] -> Q Exp
forall t (m :: * -> *). (Lift t, Quote m) => t -> m Exp
forall (m :: * -> *). Quote m => [Char] -> m Exp
lift ([Char] -> Q Exp) -> [Char] -> Q Exp
forall a b. (a -> b) -> a -> b
$ PosixPath -> [Char]
forall a. IsPath PosixPath a => a -> [Char]
toString PosixPath
p) :: OS_PATH |]
pathE :: String -> Q Exp
pathE :: [Char] -> Q Exp
pathE = (SomeException -> Q Exp)
-> (PosixPath -> Q Exp) -> Either SomeException PosixPath -> Q Exp
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ([Char] -> Q Exp
forall a. HasCallStack => [Char] -> a
error ([Char] -> Q Exp)
-> (SomeException -> [Char]) -> SomeException -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SomeException -> [Char]
forall a. Show a => a -> [Char]
show) PosixPath -> Q Exp
liftPath (Either SomeException PosixPath -> Q Exp)
-> ([Char] -> Either SomeException PosixPath) -> [Char] -> Q Exp
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Either SomeException PosixPath
forall (m :: * -> *) a.
(MonadThrow m, IsPath PosixPath a) =>
[Char] -> m a
fromString
path :: QuasiQuoter
path :: QuasiQuoter
path = ([Char] -> Q Exp) -> QuasiQuoter
mkQ [Char] -> Q Exp
pathE
toChunk :: IsPath OS_PATH a => a -> Array Word8
toChunk :: forall a. IsPath PosixPath a => a -> Array Word8
toChunk a
p = let OS_PATH arr = toPath p in Common.toChunk arr
{-# INLINE toChars #-}
toChars :: (Monad m, IsPath OS_PATH a) => a -> Stream m Char
toChars :: forall (m :: * -> *) a.
(Monad m, IsPath PosixPath a) =>
a -> Stream m Char
toChars a
p =
let (OS_PATH arr) =
toPath p in (Stream m Word8 -> Stream m Char) -> Array Word8 -> Stream m Char
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
Common.toChars Unicode.UNICODE_DECODER arr
toChars_ :: (Monad m, IsPath OS_PATH a) => a -> Stream m Char
toChars_ :: forall (m :: * -> *) a.
(Monad m, IsPath PosixPath a) =>
a -> Stream m Char
toChars_ a
p =
let (OS_PATH arr) =
toPath p in (Stream m Word8 -> Stream m Char) -> Array Word8 -> Stream m Char
forall (m :: * -> *) a.
(Monad m, Unbox a) =>
(Stream m a -> Stream m Char) -> Array a -> Stream m Char
Common.toChars Unicode.UNICODE_DECODER_LAX arr
toString :: IsPath OS_PATH a => a -> [Char]
toString :: forall a. IsPath PosixPath a => a -> [Char]
toString = Identity [Char] -> [Char]
forall a. Identity a -> a
runIdentity (Identity [Char] -> [Char])
-> (a -> Identity [Char]) -> a -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream Identity Char -> Identity [Char]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
Stream.toList (Stream Identity Char -> Identity [Char])
-> (a -> Stream Identity Char) -> a -> Identity [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Stream Identity Char
forall (m :: * -> *) a.
(Monad m, IsPath PosixPath a) =>
a -> Stream m Char
toChars
toString_ :: IsPath OS_PATH a => a -> [Char]
toString_ :: forall a. IsPath PosixPath a => a -> [Char]
toString_ = Identity [Char] -> [Char]
forall a. Identity a -> a
runIdentity (Identity [Char] -> [Char])
-> (a -> Identity [Char]) -> a -> [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Stream Identity Char -> Identity [Char]
forall (m :: * -> *) a. Monad m => Stream m a -> m [a]
Stream.toList (Stream Identity Char -> Identity [Char])
-> (a -> Stream Identity Char) -> a -> Identity [Char]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Stream Identity Char
forall (m :: * -> *) a.
(Monad m, IsPath PosixPath a) =>
a -> Stream m Char
toChars_
showRaw :: IsPath OS_PATH a => a -> [Char]
showRaw :: forall a. IsPath PosixPath a => a -> [Char]
showRaw a
p =
let (OS_PATH arr) =
toPath p in Array Word8 -> [Char]
forall a. Show a => a -> [Char]
show Array Word8
arr
readRaw :: IsPath OS_PATH a => [Char] -> a
readRaw :: forall a. IsPath PosixPath a => [Char] -> a
readRaw = Maybe a -> a
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe a -> a) -> ([Char] -> Maybe a) -> [Char] -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Array Word8 -> Maybe a
forall (m :: * -> *) a.
(MonadThrow m, IsPath PosixPath a) =>
Array Word8 -> m a
fromChunk (Array Word8 -> Maybe a)
-> ([Char] -> Array Word8) -> [Char] -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> Array Word8
forall a. Read a => [Char] -> a
read
#ifdef IS_WINDOWS
#else
#endif
isRooted :: OS_PATH -> Bool
isRooted :: PosixPath -> Bool
isRooted (OS_PATH arr) = Common.isRooted Common.OS_NAME arr
isBranch :: OS_PATH -> Bool
isBranch :: PosixPath -> Bool
isBranch = Bool -> Bool
not (Bool -> Bool) -> (PosixPath -> Bool) -> PosixPath -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PosixPath -> Bool
isRooted
{-# INLINE unsafeAppend #-}
unsafeAppend :: OS_PATH -> OS_PATH -> OS_PATH
unsafeAppend :: PosixPath -> PosixPath -> PosixPath
unsafeAppend (OS_PATH a) (OS_PATH b) =
OS_PATH
$ Common.unsafeAppend
Common.OS_NAME (Common.toString Unicode.UNICODE_DECODER) a b
append :: OS_PATH -> OS_PATH -> OS_PATH
append :: PosixPath -> PosixPath -> PosixPath
append (OS_PATH a) (OS_PATH b) =
OS_PATH
$ Common.append
Common.OS_NAME (Common.toString Unicode.UNICODE_DECODER) a b
append' ::
OS_PATH -> OS_PATH -> OS_PATH
append' :: PosixPath -> PosixPath -> PosixPath
append'
(OS_PATH a) (OS_PATH b) =
OS_PATH
$ Common.append'
Common.OS_NAME (Common.toString Unicode.UNICODE_DECODER) a b
#ifndef IS_WINDOWS
appendCString :: OS_PATH -> CString -> IO OS_PATH
appendCString :: PosixPath -> CString -> IO PosixPath
appendCString (OS_PATH a) str =
fmap OS_PATH
$ Common.appendCString
Common.OS_NAME a str
appendCString' ::
OS_PATH -> CString -> IO OS_PATH
appendCString' :: PosixPath -> CString -> IO PosixPath
appendCString'
(OS_PATH a) str =
fmap OS_PATH
$ Common.appendCString'
Common.OS_NAME a str
#endif
splitRoot :: OS_PATH -> (OS_PATH, OS_PATH)
splitRoot :: PosixPath -> (PosixPath, PosixPath)
splitRoot (OS_PATH a) =
bimap OS_PATH OS_PATH $ Common.splitRoot Common.OS_NAME a
{-# INLINE splitPath #-}
splitPath :: Monad m => OS_PATH -> Stream m OS_PATH
splitPath :: forall (m :: * -> *). Monad m => PosixPath -> Stream m PosixPath
splitPath (OS_PATH a) = fmap OS_PATH $ Common.splitPath Common.OS_NAME a
{-# INLINE splitPath_ #-}
splitPath_ :: Monad m => OS_PATH -> Stream m OS_PATH
splitPath_ :: forall (m :: * -> *). Monad m => PosixPath -> Stream m PosixPath
splitPath_ (OS_PATH a) = fmap OS_PATH $ Common.splitPath_ Common.OS_NAME a
splitFile :: OS_PATH -> (OS_PATH, OS_PATH)
splitFile :: PosixPath -> (PosixPath, PosixPath)
splitFile (OS_PATH a) =
bimap OS_PATH OS_PATH $ Common.splitFile Common.OS_NAME a
splitExtension :: OS_PATH -> (OS_PATH, OS_PATH)
splitExtension :: PosixPath -> (PosixPath, PosixPath)
splitExtension (OS_PATH a) =
bimap OS_PATH OS_PATH $ Common.splitExtension Common.OS_NAME a
eqPath :: OS_PATH -> OS_PATH -> Bool
eqPath :: PosixPath -> PosixPath -> Bool
eqPath (OS_PATH a) (OS_PATH b) =
Common.eqPath Unicode.UNICODE_DECODER
Common.OS_NAME a b
eqPathWith :: EqCfg -> OS_PATH -> OS_PATH -> Bool
eqPathWith :: EqCfg -> PosixPath -> PosixPath -> Bool
eqPathWith EqCfg
cfg (OS_PATH a) (OS_PATH b) =
Common.eqPathWith Unicode.UNICODE_DECODER
Common.OS_NAME cfg a b
eqPathBytes :: OS_PATH -> OS_PATH -> Bool
eqPathBytes :: PosixPath -> PosixPath -> Bool
eqPathBytes (OS_PATH a) (OS_PATH b) = Common.eqPathBytes a b