ascii-superset-1.3.0.1: library/ASCII/Refinement/Internal.hs
module ASCII.Refinement.Internal where
import ASCII.Char qualified as ASCII
import ASCII.Isomorphism qualified as I
import ASCII.Superset qualified as S
import {-# SOURCE #-} ASCII.SupersetConversion (StringSupersetConversion)
import {-# SOURCE #-} ASCII.SupersetConversion qualified as SupersetConversion
import Data.Bool qualified as Bool
import Data.Data (Data)
import Data.Eq (Eq)
import Data.Function (id, ($), (.))
import Data.Hashable (Hashable)
import Data.Kind (Type)
import Data.List (map)
import Data.Maybe (Maybe (..))
import Data.Monoid (Monoid)
import Data.Ord (Ord, (>))
import Data.Semigroup (Semigroup)
import GHC.Generics (Generic)
import Text.Show qualified as Show
import Prelude (succ)
-- | This type constructor indicates that a value from some ASCII superset
-- is valid ASCII
--
-- The type parameter is the ASCII superset, which should be a type with an
-- instance of either 'CharSuperset' or 'StringSuperset'.
--
-- For example, whereas a 'Data.Text.Text' value may contain a combination of ASCII
-- and non-ASCII characters, a value of type @'ASCII' 'Data.Text.Text'@ may contain
-- only ASCII characters.
newtype ASCII (superset :: Type) = ASCII_Unsafe {lift :: superset}
deriving stock instance Eq superset => Eq (ASCII superset)
deriving stock instance Ord superset => Ord (ASCII superset)
deriving newtype instance Hashable superset => Hashable (ASCII superset)
deriving newtype instance Semigroup superset => Semigroup (ASCII superset)
deriving newtype instance Monoid superset => Monoid (ASCII superset)
deriving stock instance Data superset => Data (ASCII superset)
deriving stock instance Generic (ASCII superset)
instance Show.Show superset => Show.Show (ASCII superset) where
showsPrec d x =
Show.showParen (d > app_prec) $
Show.showString "asciiUnsafe " . Show.showsPrec (succ app_prec) (lift x)
where
app_prec = 10
showList x = Show.showString "asciiUnsafe " . Show.showList (map lift x)
instance S.ToCaselessChar char => S.ToCaselessChar (ASCII char) where
isAsciiCaselessChar _ = Bool.True
toCaselessCharUnsafe = S.toCaselessCharUnsafe . lift
instance S.CharSuperset char => S.ToChar (ASCII char) where
isAsciiChar _ = Bool.True
toCharUnsafe = S.toCharUnsafe . lift
instance S.CharSuperset char => S.FromChar (ASCII char) where
fromChar = asciiUnsafe . S.fromChar
instance S.CharSuperset char => S.CharSuperset (ASCII char) where
toCaseChar c = asciiUnsafe . S.toCaseChar c . lift
instance S.CharSuperset char => I.CharIso (ASCII char) where
toChar = S.toCharUnsafe
instance S.ToCaselessString string => S.ToCaselessString (ASCII string) where
isAsciiCaselessString _ = Bool.True
toCaselessCharListUnsafe = S.toCaselessCharListUnsafe . lift
toCaselessCharListSub = S.toCaselessCharListSub . lift
instance S.ToString string => S.ToString (ASCII string) where
isAsciiString _ = Bool.True
toCharListUnsafe = S.toCharListUnsafe . lift
toCharListSub = S.toCharListUnsafe . lift
instance S.FromString string => S.FromString (ASCII string) where
fromCharList = asciiUnsafe . S.fromCharList
instance S.StringSuperset string => S.StringSuperset (ASCII string) where
substituteString = id
toCaseString c = asciiUnsafe . S.toCaseString c . lift
instance S.StringSuperset string => I.StringIso (ASCII string) where
toCharList = S.toCharListUnsafe
mapChars = S.mapCharsUnsafe
-- | Change the type of an ASCII superset value that is known to be valid ASCII
--
-- This is "unsafe" because this assertion is unchecked, so this function is capable
-- of producing an invalid 'ASCII' value.
asciiUnsafe :: superset -> ASCII superset
asciiUnsafe = ASCII_Unsafe
-- |
--
-- @
-- (map validateChar [-1, 65, 97, 128] :: [Maybe (ASCII Int)])
-- == [Nothing, Just (asciiUnsafe 65), Just (asciiUnsafe 97), Nothing]
-- @
validateChar :: S.CharSuperset superset => superset -> Maybe (ASCII superset)
validateChar x = if S.isAsciiChar x then Just (asciiUnsafe x) else Nothing
substituteChar :: S.CharSuperset superset => superset -> ASCII superset
substituteChar x = if S.isAsciiChar x then asciiUnsafe x else fromChar ASCII.Substitute
fromChar :: S.CharSuperset superset => ASCII.Char -> ASCII superset
fromChar = asciiUnsafe . S.fromChar
toChar :: S.CharSuperset superset => ASCII superset -> ASCII.Char
toChar = S.toCharUnsafe . lift
-- |
--
-- @
-- fromCharList [CapitalLetterH, SmallLetterI, ExclamationMark]
-- == (asciiUnsafe "Hi!" :: ASCII Text)
-- @
fromCharList :: S.StringSuperset superset => [ASCII.Char] -> ASCII superset
fromCharList = asciiUnsafe . S.fromCharList
-- |
--
-- @
-- toCharList (substituteString \"Piñata" :: ASCII Text) ==
-- [CapitalLetterP, SmallLetterI, Substitute, SmallLetterA, SmallLetterT, SmallLetterA]
-- @
toCharList :: S.StringSuperset superset => ASCII superset -> [ASCII.Char]
toCharList = S.toCharListUnsafe . lift
-- | Forces a string from a larger character set into ASCII by using the
-- 'ASCII.Substitute' character in place of any non-ASCII characters
--
-- @
-- (substituteString \"Cristóbal" :: ASCII Text) == asciiUnsafe "Crist\SUBbal"
-- @
substituteString :: S.StringSuperset superset => superset -> ASCII superset
substituteString = asciiUnsafe . S.substituteString
-- |
--
-- @
-- (map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII Text)])
-- == [Just (asciiUnsafe \"Hello"), Nothing]
--
-- (map validateString [\"Hello", \"Cristóbal"] :: [Maybe (ASCII String)])
-- == [Just (asciiUnsafe \"Hello"), Nothing]
-- @
validateString :: S.StringSuperset superset => superset -> Maybe (ASCII superset)
validateString x = if S.isAsciiString x then Just (asciiUnsafe x) else Nothing
asChar :: S.CharSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
asChar f = asciiUnsafe . S.asCharUnsafe f . lift
mapChars :: S.StringSuperset superset => (ASCII.Char -> ASCII.Char) -> ASCII superset -> ASCII superset
mapChars f = asciiUnsafe . S.mapCharsUnsafe f . lift
-- | For example, this function can convert @ASCII ByteString@ to @ASCII Text@ and vice versa
convertRefinedString :: StringSupersetConversion a b => ASCII a -> ASCII b
convertRefinedString (ASCII_Unsafe x) = ASCII_Unsafe (SupersetConversion.convertStringUnsafe x)