headroom-0.1.0.0: src/Headroom/Types/Utils.hs
{-|
Module : Headroom.Types.Utils
Description : tilities related to data types
Copyright : (c) 2019-2020 Vaclav Svejcar
License : BSD-3
Maintainer : vaclav.svejcar@gmail.com
Stability : experimental
Portability : POSIX
Utilities related to data types.
-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoImplicitPrelude #-}
module Headroom.Types.Utils
( allValues
, customOptions
, dropFieldPrefix
, readEnumCI
, symbolCase
)
where
import Data.Aeson ( Options
, defaultOptions
, fieldLabelModifier
)
import RIO
import qualified RIO.Char as C
import qualified RIO.List as L
import Text.Read ( ReadS )
-- | Returns all values of enum.
allValues :: (Bounded a, Enum a) => [a]
allValues = [minBound ..]
-- | Custom /Aeson/ options.
customOptions :: Options
customOptions =
defaultOptions { fieldLabelModifier = symbolCase '-' . dropFieldPrefix }
-- | Drops prefix from camel-case text.
--
-- >>> dropFieldPrefix "xxHelloWorld"
-- "helloWorld"
dropFieldPrefix :: String -> String
dropFieldPrefix = \case
(x : n : xs) | C.isUpper x && C.isUpper n -> x : n : xs
(x : n : xs) | C.isUpper x -> C.toLower x : n : xs
(_ : xs) -> dropFieldPrefix xs
[] -> []
-- | Parses enum value from its string representation.
readEnumCI :: (Bounded a, Enum a, Show a) => ReadS a
readEnumCI str =
let textRepr = fmap C.toLower . show
result = L.find (\item -> textRepr item == fmap C.toLower str) allValues
in maybe [] (\item -> [(item, "")]) result
-- | Transforms camel-case text into text cased with given symbol.
--
-- >>> symbolCase '-' "fooBar"
-- "foo-bar"
symbolCase :: Char -- ^ word separator symbol
-> String -- ^ input text
-> String -- ^ processed text
symbolCase sym = \case
[] -> []
(x : xs) | C.isUpper x -> sym : C.toLower x : symbolCase sym xs
| otherwise -> x : symbolCase sym xs