{- |
Module      : Servant.API.Routes.Utils
Copyright   : (c) Frederick Pringle, 2025
License     : BSD-3-Clause
Maintainer  : frederick.pringle@fpringle.com

Common useful functions.
-}
module Servant.API.Routes.Utils
  ( knownSymbolT
  , typeRepToJSON
  , showTypeRep
  , typeRepOf
  )
where

import Data.Aeson
import Data.Kind
import qualified Data.Text as T
import Data.Typeable
import GHC.TypeLits

-- | Get the term-level equivalent of a 'Symbol' as a 'T.Text'.
knownSymbolT :: forall name. (KnownSymbol name) => T.Text
knownSymbolT :: forall (name :: Symbol). KnownSymbol name => Text
knownSymbolT = String -> Text
T.pack (String -> Text) -> (Proxy name -> String) -> Proxy name -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Proxy name -> String
forall (n :: Symbol) (proxy :: Symbol -> *).
KnownSymbol n =>
proxy n -> String
symbolVal (Proxy name -> Text) -> Proxy name -> Text
forall a b. (a -> b) -> a -> b
$ forall {k} (t :: k). Proxy t
forall (t :: Symbol). Proxy t
Proxy @name

-- | Convert a 'TypeRep' to a JSON 'Value' via its 'Show' instance.
typeRepToJSON :: TypeRep -> Value
typeRepToJSON :: TypeRep -> Value
typeRepToJSON = String -> Value
forall a. ToJSON a => a -> Value
toJSON (String -> Value) -> (TypeRep -> String) -> TypeRep -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> String
show @TypeRep

-- | Get the 'TypeRep' of a 'Typeable' type without having to mess around with 'Proxy'.
typeRepOf :: forall a. (Typeable a) => TypeRep
typeRepOf :: forall a. Typeable a => TypeRep
typeRepOf = Proxy a -> TypeRep
forall {k} (proxy :: k -> *) (a :: k).
Typeable a =>
proxy a -> TypeRep
typeRep (Proxy a -> TypeRep) -> Proxy a -> TypeRep
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @a

-- | Get the 'TypeRep' of a 'Typeable' type as a 'T.Text'.
showTypeRep :: forall (a :: Type). (Typeable a) => T.Text
showTypeRep :: forall a. Typeable a => Text
showTypeRep = String -> Text
T.pack (String -> Text) -> (TypeRep -> String) -> TypeRep -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TypeRep -> String
forall a. Show a => a -> String
show (TypeRep -> Text) -> TypeRep -> Text
forall a b. (a -> b) -> a -> b
$ forall a. Typeable a => TypeRep
typeRepOf @a