{-# LANGUAGE OverloadedStrings, BangPatterns #-}
module Network.Wai.Application.Classic.Path (
Path
, pathString
, fromString
, (</>), (<\>), (<.>)
, breakAtSeparator, hasLeadingPathSeparator, hasTrailingPathSeparator
, isSuffixOf
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as B8
import Data.String
import Data.Word
type Path = ByteString
pathString :: Path -> String
pathString :: ByteString -> String
pathString = ByteString -> String
B8.unpack
{-# INLINE pathString #-}
pathDotBS :: ByteString
pathDotBS :: ByteString
pathDotBS = ByteString
"."
pathSep :: Word8
pathSep :: Word8
pathSep = Word8
47
pathSepBS :: ByteString
pathSepBS :: ByteString
pathSepBS = ByteString
"/"
hasLeadingPathSeparator :: Path -> Bool
hasLeadingPathSeparator :: ByteString -> Bool
hasLeadingPathSeparator ByteString
bs
| ByteString -> Bool
BS.null ByteString
bs = Bool
False
| HasCallStack => ByteString -> Word8
ByteString -> Word8
BS.head ByteString
bs Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
pathSep = Bool
True
| Bool
otherwise = Bool
False
{-# INLINE hasLeadingPathSeparator #-}
hasTrailingPathSeparator :: Path -> Bool
hasTrailingPathSeparator :: ByteString -> Bool
hasTrailingPathSeparator ByteString
bs
| ByteString -> Bool
BS.null ByteString
bs = Bool
False
| HasCallStack => ByteString -> Word8
ByteString -> Word8
BS.last ByteString
bs Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
pathSep = Bool
True
| Bool
otherwise = Bool
False
{-# INLINE hasTrailingPathSeparator #-}
(</>) :: Path -> Path -> Path
ByteString
p1 </> :: ByteString -> ByteString -> ByteString
</> ByteString
p2 = ByteString
p
where
!has1 :: Bool
has1 = ByteString -> Bool
hasTrailingPathSeparator ByteString
p1
!has2 :: Bool
has2 = ByteString -> Bool
hasLeadingPathSeparator ByteString
p2
!p :: ByteString
p | Bool
has1 Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
has2 = ByteString
p1 ByteString -> ByteString -> ByteString
`BS.append` ByteString
p2
| Bool -> Bool
not Bool
has1 Bool -> Bool -> Bool
&& Bool
has2 = ByteString
p1 ByteString -> ByteString -> ByteString
`BS.append` ByteString
p2
| Bool
has1 = ByteString
p1 ByteString -> ByteString -> ByteString
`BS.append` HasCallStack => ByteString -> ByteString
ByteString -> ByteString
BS.tail ByteString
p2
| Bool
otherwise = [ByteString] -> ByteString
BS.concat [ByteString
p1,ByteString
pathSepBS,ByteString
p2]
{-# INLINE (</>) #-}
(<\>) :: Path -> Path -> Path
ByteString
p1 <\> :: ByteString -> ByteString -> ByteString
<\> ByteString
p2 = ByteString
p
where
!p :: ByteString
p = Int -> ByteString -> ByteString
BS.drop (ByteString -> Int
BS.length ByteString
p2) ByteString
p1
{-# INLINE (<\>) #-}
(<.>) :: Path -> Path -> Path
ByteString
p1 <.> :: ByteString -> ByteString -> ByteString
<.> ByteString
p2 = ByteString
p
where
!p :: ByteString
p = [ByteString] -> ByteString
BS.concat [ByteString
p1,ByteString
pathDotBS,ByteString
p2]
{-# INLINE (<.>) #-}
breakAtSeparator :: Path -> (Path,Path)
breakAtSeparator :: ByteString -> (ByteString, ByteString)
breakAtSeparator ByteString
p = (Word8 -> Bool) -> ByteString -> (ByteString, ByteString)
BS.break (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
pathSep) ByteString
p
{-# INLINE breakAtSeparator #-}
isSuffixOf :: Path -> Path -> Bool
isSuffixOf :: ByteString -> ByteString -> Bool
isSuffixOf = ByteString -> ByteString -> Bool
BS.isSuffixOf
{-# INLINE isSuffixOf #-}