servant-routes-0.1.1.0: src/Servant/API/Routes/Internal/Path.hs
{-# OPTIONS_HADDOCK not-home #-}
{- |
Module : Servant.API.Routes.Internal.Path
Copyright : (c) Frederick Pringle, 2025
License : BSD-3-Clause
Maintainer : frederick.pringle@fpringle.com
Internal module, subject to change.
-}
module Servant.API.Routes.Internal.Path
( Path (..)
, renderPath
, pathSeparator
, PathPart (..)
)
where
import Data.Aeson
import Data.String
import qualified Data.Text as T
import Data.Typeable
-- | A segment of an API path (between @"/"@s).
data PathPart
= -- | Just a plain path part, e.g. @"api/"@.
StringPart T.Text
| -- | Capture a path part as a variable.
CapturePart T.Text TypeRep
| -- | Capture all path part as a list of variables.
CaptureAllPart T.Text TypeRep
deriving (Eq, Ord)
instance IsString PathPart where
fromString = StringPart . T.pack
instance Show PathPart where
show = T.unpack . renderPathPart
-- | Pretty-print a path part.
renderPathPart :: PathPart -> T.Text
renderPathPart = \case
StringPart t -> t
CapturePart _ typ -> "<" <> T.pack (show typ) <> ">"
CaptureAllPart _ typ -> "<[" <> T.pack (show typ) <> "]>"
-- | Standard path separator @"/"@.
pathSeparator :: T.Text
pathSeparator = "/"
-- | Simple representation of a URL path.
newtype Path = Path
{ unPath :: [PathPart]
}
deriving (Eq, Ord) via [PathPart]
instance Show Path where
show = T.unpack . renderPath
instance ToJSON Path where
toJSON = toJSON . renderPath
-- | Pretty-print a path, including the leading @/@.
renderPath :: Path -> T.Text
renderPath = (pathSeparator <>) . T.intercalate pathSeparator . fmap renderPathPart . unPath