module Main (main) where import Test.Hspec import ASCII.Case (Case (..)) import ASCII.CaseRefinement (ASCII'lower, ASCII'upper, asciiCaseUnsafe) import ASCII.Char (Char (..)) import ASCII.Refinement (ASCII, asciiUnsafe) import ASCII.Superset (fromChar, fromCharList) import qualified ASCII.Case as Case import qualified ASCII.Caseless as CC import qualified ASCII.CaseRefinement as CaseRefinement import qualified ASCII.Char as ASCII import qualified ASCII.Refinement as Refinement import qualified ASCII.Superset as Superset import qualified Data.Foldable as Foldable import Data.Function ((&)) import Data.Text (Text) import Data.Word (Word8) import Numeric.Natural (Natural) import Prelude import qualified Data.Char as Unicode main :: IO () main = hspec $ do describe "fromChar" $ do it "letter" $ do let f x = fromChar x :: Word8 f CapitalLetterA `shouldBe` 65 it "to unicode" $ do let f = fromChar f CapitalLetterA `shouldBe` 'A' it "id" $ do let f x = fromChar (x :: ASCII.Char) :: ASCII.Char f CapitalLetterA `shouldBe` CapitalLetterA describe "refinement" $ do it "validateChar" $ do let f x = Refinement.validateChar x :: Maybe (ASCII Int) f (-1) `shouldBe` Nothing f 65 `shouldBe` Just (asciiUnsafe 65) f 97 `shouldBe` Just (asciiUnsafe 97) f 128 `shouldBe` Nothing describe "fromCharList" $ do it "Text" $ do let f x = fromCharList x :: Text f [CapitalLetterH, SmallLetterI, ExclamationMark] `shouldBe` "Hi!" it "ASCII Text" $ do let f x = Refinement.fromCharList x :: ASCII Text f [CapitalLetterH, SmallLetterI, ExclamationMark] `shouldBe` asciiUnsafe "Hi!" it "toCharList" $ do let f x = Refinement.toCharList (Refinement.substituteString x :: ASCII Text) f "Piñata" `shouldBe` [CapitalLetterP, SmallLetterI, Substitute, SmallLetterA, SmallLetterT, SmallLetterA] it "substituteString" $ do let f x = Refinement.substituteString x :: ASCII Text f "Cristóbal" `shouldBe` asciiUnsafe "Crist\SUBbal" it "validateString" $ do let f x = Refinement.validateString x :: Maybe (ASCII Text) f "Hello" `shouldBe` Just (asciiUnsafe "Hello") f "Cristóbal" `shouldBe` Nothing describe "case refinement" $ do describe "validateChar" $ do it "lower" $ do let f x = CaseRefinement.validateChar x :: Maybe (ASCII'lower Int) f (-1) `shouldBe` Nothing f 65 `shouldBe` Nothing f 97 `shouldBe` Just (asciiCaseUnsafe 97) f 128 `shouldBe` Nothing it "upper" $ do let f x = CaseRefinement.validateChar x :: Maybe (ASCII'upper Int) f (-1) `shouldBe` Nothing f 65 `shouldBe` Just (asciiCaseUnsafe 65) f 97 `shouldBe` Nothing f 128 `shouldBe` Nothing describe "fromCaselessCharList" $ do it "lower" $ do let f x = CaseRefinement.fromCaselessCharList x :: ASCII'lower Text f [CC.LetterH, CC.LetterI, CC.ExclamationMark] `shouldBe` asciiCaseUnsafe "hi!" it "upper" $ do let f x = CaseRefinement.fromCaselessCharList x :: ASCII'upper Text f [CC.LetterH, CC.LetterI, CC.ExclamationMark] `shouldBe` asciiCaseUnsafe "HI!" describe "toCaselessCharList" $ do it "lower" $ do let f x = CaseRefinement.toCaselessCharList (x :: ASCII'lower Text) f (asciiCaseUnsafe "hi!") `shouldBe` [CC.LetterH, CC.LetterI, CC.ExclamationMark] it "upper" $ do let f x = CaseRefinement.toCaselessCharList (x :: ASCII'upper Text) f (asciiCaseUnsafe "HI!") `shouldBe` [CC.LetterH, CC.LetterI, CC.ExclamationMark] describe "substituteString" $ do it "lower" $ do let f x = CaseRefinement.substituteString x :: ASCII'lower Text f "Cób" `shouldBe` asciiCaseUnsafe "\SUB\SUBb" it "upper" $ do let f x = CaseRefinement.substituteString x :: ASCII'upper Text f "Cób" `shouldBe` asciiCaseUnsafe "C\SUB\SUB" describe "validateString" $ do it "lower" $ do let f x = CaseRefinement.validateString x :: Maybe (ASCII'lower Text) f "hello" `shouldBe` Just (asciiCaseUnsafe "hello") f "Hello" `shouldBe` Nothing it "upper" $ do let f x = CaseRefinement.validateString x :: Maybe (ASCII'upper Text) f "HELLO" `shouldBe` Just (asciiCaseUnsafe "HELLO") f "Hello" `shouldBe` Nothing describe "case conversion" $ do describe "toCaseChar" $ do let check :: forall a. Eq a => Superset.CharSuperset a => Expectation check = ([UpperCase, LowerCase] & Foldable.all (\c -> ASCII.allCharacters & Foldable.all (\x -> Superset.toCaseChar c (fromChar @a x) == fromChar @a (Case.toCase c x) ))) `shouldBe` True it "ASCII.Char" $ check @ASCII.Char it "Unicode.Char" $ check @Unicode.Char it "Natural" $ check @Natural it "Int" $ check @Int it "Word8" $ check @Word8 describe "toCaseString" $ do it "Text" $ do let x = "012 abc DEF ﬓ" :: Text Superset.toCaseString UpperCase x `shouldBe` "012 ABC DEF ﬓ" Superset.toCaseString LowerCase x `shouldBe` "012 abc def ﬓ" describe "refineStringToCase" $ do it "Text" $ do let x = asciiUnsafe "Hi!" :: ASCII Text CaseRefinement.refineStringToCase x `shouldBe` (asciiCaseUnsafe "HI!" :: ASCII'upper Text) CaseRefinement.refineStringToCase x `shouldBe` (asciiCaseUnsafe "hi!" :: ASCII'lower Text) describe "toCasefulChar" $ do describe "lower case" $ do let a :: Superset.ToCasefulChar 'LowerCase char => char a = Superset.toCasefulChar @'LowerCase CC.LetterA it "can be Char" $ a `shouldBe` SmallLetterA it "can be superset type" $ a `shouldBe` 'a' it "can be case-refined type" $ a `shouldBe` (asciiCaseUnsafe 'a' :: ASCII'lower Unicode.Char) describe "upper case" $ do let a :: Superset.ToCasefulChar 'UpperCase char => char a = Superset.toCasefulChar @'UpperCase CC.LetterA it "can be Char" $ a `shouldBe` CapitalLetterA it "can be superset type" $ a `shouldBe` 'A' it "can be case-refined type" $ a `shouldBe` (asciiCaseUnsafe 'A' :: ASCII'upper Unicode.Char) describe "toCasefulString" $ do describe "lower case" $ do let x :: Superset.ToCasefulString 'LowerCase string => string x = Superset.toCasefulString @'LowerCase [CC.LetterH, CC.LetterI, CC.ExclamationMark] it "can be [Char]" $ x `shouldBe` [SmallLetterH, SmallLetterI, ExclamationMark] it "can be superset type" $ x `shouldBe` ("hi!" :: Text) it "can be case-refined type" $ x `shouldBe` (asciiCaseUnsafe "hi!" :: ASCII'lower Text) describe "upper case" $ do let x :: Superset.ToCasefulString 'UpperCase string => string x = Superset.toCasefulString @'UpperCase [CC.LetterH, CC.LetterI, CC.ExclamationMark] it "can be [Char]" $ x `shouldBe` [CapitalLetterH, CapitalLetterI, ExclamationMark] it "can be superset type" $ x `shouldBe` ("HI!" :: Text) it "can be case-refined type" $ x `shouldBe` (asciiCaseUnsafe "HI!" :: ASCII'upper Text)