module ASCII.Case ( Case (..), letterCase, isCase, toCase ) where
import ASCII.Char ( Char (..) )
import Data.Bool ( Bool, otherwise )
import Data.Data ( Data )
import Data.Eq ( Eq )
import Data.Function ( (.), ($) )
import Data.Hashable ( Hashable )
import Data.Ord ( Ord, (<=), (>=) )
import GHC.Generics ( Generic )
import Prelude ( Enum, Bounded, Int, (+), (-) )
import Text.Show ( Show )
import Data.Maybe ( Maybe (..) )
import qualified ASCII.Char as Char
import qualified Data.Bool as Bool
data Case =
UpperCase
| LowerCase
deriving stock instance Eq Case
deriving stock instance Ord Case
deriving stock instance Enum Case
deriving stock instance Bounded Case
deriving stock instance Show Case
deriving stock instance Data Case
deriving stock instance Generic Case
deriving anyclass instance Hashable Case
letterCase :: Char -> Maybe Case
letterCase x | isCase UpperCase x = Just UpperCase
| isCase LowerCase x = Just LowerCase
| otherwise = Nothing
isCase :: Case -> Char -> Bool
isCase c x = (Bool.&&) ( x >= a ) ( x <= z ) where (a, z) = az c
az :: Case -> (Char, Char)
az UpperCase = (CapitalLetterA, CapitalLetterZ)
az LowerCase = (SmallLetterA, SmallLetterZ)
toCase :: Case -> Char -> Char
toCase c x = if isCase (opposite c) x then changeCaseUnsafe c x else x
changeCaseUnsafe :: Case -> Char -> Char
changeCaseUnsafe c = charAsIntUnsafe (changeCaseInt c)
changeCaseInt :: Case -> Int -> Int
changeCaseInt LowerCase i = i + 32
changeCaseInt UpperCase i = i - 32
opposite UpperCase = LowerCase
opposite LowerCase = UpperCase
charAsIntUnsafe :: (Int -> Int) -> (Char -> Char)
charAsIntUnsafe f = Char.fromIntUnsafe . f . Char.toInt