module Argo.Type.String where

import qualified Argo.Decoder as Decoder
import qualified Argo.Literal as Literal
import qualified Control.DeepSeq as DeepSeq
import qualified Control.Monad as Monad
import qualified Data.ByteString as ByteString
import qualified Data.ByteString.Builder as Builder
import qualified Data.ByteString.Builder.Prim as P
import qualified Data.Char as Char
import qualified Data.Text as Text
import qualified Data.Text.Encoding as Text
import qualified Data.Word as Word

newtype String
    = String Text.Text
    deriving (String -> String -> Bool
(String -> String -> Bool)
-> (String -> String -> Bool) -> Eq String
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: String -> String -> Bool
$c/= :: String -> String -> Bool
== :: String -> String -> Bool
$c== :: String -> String -> Bool
Eq, Int -> String -> ShowS
[String] -> ShowS
String -> String
(Int -> String -> ShowS)
-> (String -> String) -> ([String] -> ShowS) -> Show String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [String] -> ShowS
$cshowList :: [String] -> ShowS
show :: String -> String
$cshow :: String -> String
showsPrec :: Int -> String -> ShowS
$cshowsPrec :: Int -> String -> ShowS
Show)

instance DeepSeq.NFData Argo.Type.String.String where
    rnf :: String -> ()
rnf (String Text
x) = Text -> ()
forall a. NFData a => a -> ()
DeepSeq.rnf Text
x

encode :: Argo.Type.String.String -> Builder.Builder
encode :: String -> Builder
encode (String Text
x) =
    Word8 -> Builder
Builder.word8 Word8
Literal.quotationMark
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> BoundedPrim Word8 -> Text -> Builder
Text.encodeUtf8BuilderEscaped BoundedPrim Word8
encodeChar Text
x
    Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Word8 -> Builder
Builder.word8 Word8
Literal.quotationMark

encodeChar :: P.BoundedPrim Word.Word8
encodeChar :: BoundedPrim Word8
encodeChar =
    (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.quotationMark) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.quotationMark)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.reverseSolidus) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.reverseSolidus)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.backspace) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.latinSmallLetterB)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.formFeed) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.latinSmallLetterF)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.newLine) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.latinSmallLetterN)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.carriageReturn) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.latinSmallLetterR)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
Literal.horizontalTabulation) (Word8 -> BoundedPrim Word8
forall a. Word8 -> BoundedPrim a
encodeShortEscape Word8
Literal.latinSmallLetterT)
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8
-> BoundedPrim Word8
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool)
-> BoundedPrim Word8 -> BoundedPrim Word8 -> BoundedPrim Word8
forall a.
(a -> Bool) -> BoundedPrim a -> BoundedPrim a -> BoundedPrim a
P.condB (Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
Literal.space) BoundedPrim Word8
encodeLongEscape
    (BoundedPrim Word8 -> BoundedPrim Word8)
-> BoundedPrim Word8 -> BoundedPrim Word8
forall a b. (a -> b) -> a -> b
$ FixedPrim Word8 -> BoundedPrim Word8
forall a. FixedPrim a -> BoundedPrim a
P.liftFixedToBounded FixedPrim Word8
P.word8

encodeShortEscape :: Word.Word8 -> P.BoundedPrim a
encodeShortEscape :: Word8 -> BoundedPrim a
encodeShortEscape Word8
x = FixedPrim a -> BoundedPrim a
forall a. FixedPrim a -> BoundedPrim a
P.liftFixedToBounded
    (FixedPrim a -> BoundedPrim a) -> FixedPrim a -> BoundedPrim a
forall a b. (a -> b) -> a -> b
$ (Word8, Word8) -> a -> (Word8, Word8)
forall a b. a -> b -> a
const (Word8
Literal.reverseSolidus, Word8
x)
    (a -> (Word8, Word8)) -> FixedPrim (Word8, Word8) -> FixedPrim a
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
P.>$< FixedPrim Word8
P.word8
    FixedPrim Word8 -> FixedPrim Word8 -> FixedPrim (Word8, Word8)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
P.>*< FixedPrim Word8
P.word8

encodeLongEscape :: P.BoundedPrim Word.Word8
encodeLongEscape :: BoundedPrim Word8
encodeLongEscape = FixedPrim Word8 -> BoundedPrim Word8
forall a. FixedPrim a -> BoundedPrim a
P.liftFixedToBounded
    (FixedPrim Word8 -> BoundedPrim Word8)
-> FixedPrim Word8 -> BoundedPrim Word8
forall a b. (a -> b) -> a -> b
$ (\ Word8
x -> (Word8
Literal.reverseSolidus, (Word8
Literal.latinSmallLetterU, Word8 -> Word16
word8ToWord16 Word8
x)))
    (Word8 -> (Word8, (Word8, Word16)))
-> FixedPrim (Word8, (Word8, Word16)) -> FixedPrim Word8
forall (f :: * -> *) b a. Contravariant f => (b -> a) -> f a -> f b
P.>$< FixedPrim Word8
P.word8
    FixedPrim Word8
-> FixedPrim (Word8, Word16) -> FixedPrim (Word8, (Word8, Word16))
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
P.>*< FixedPrim Word8
P.word8
    FixedPrim Word8 -> FixedPrim Word16 -> FixedPrim (Word8, Word16)
forall (f :: * -> *) a b. Monoidal f => f a -> f b -> f (a, b)
P.>*< FixedPrim Word16
P.word16HexFixed

word8ToWord16 :: Word.Word8 -> Word.Word16
word8ToWord16 :: Word8 -> Word16
word8ToWord16 = Word8 -> Word16
forall a b. (Integral a, Num b) => a -> b
fromIntegral

decode :: Decoder.Decoder Argo.Type.String.String
decode :: Decoder String
decode = do
    Word8 -> Decoder ()
Decoder.word8 Word8
Literal.quotationMark
    ByteString
b1 <- Decoder ByteString
Decoder.get
    Int
i <- case ByteString -> Int -> Maybe Int
getClose ByteString
b1 Int
0 of
        Maybe Int
Nothing -> String -> Decoder Int
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"unterminated string"
        Just Int
i -> Int -> Decoder Int
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
i
    let (ByteString
xs, ByteString
b2) = Int -> ByteString -> (ByteString, ByteString)
ByteString.splitAt Int
i ByteString
b1
    Bool -> Decoder () -> Decoder ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
Monad.when ((Word8 -> Bool) -> ByteString -> Bool
ByteString.any (Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
Literal.space) ByteString
xs) (Decoder () -> Decoder ()) -> Decoder () -> Decoder ()
forall a b. (a -> b) -> a -> b
$ String -> Decoder ()
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"unescaped control character"
    ByteString -> Decoder ()
Decoder.put ByteString
b2
    Word8 -> Decoder ()
Decoder.word8 Word8
Literal.quotationMark
    Decoder ()
Decoder.spaces
    case ByteString -> Either UnicodeException Text
Text.decodeUtf8' ByteString
xs of
        Left UnicodeException
e -> String -> Decoder String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Decoder String) -> String -> Decoder String
forall a b. (a -> b) -> a -> b
$ UnicodeException -> String
forall a. Show a => a -> String
show UnicodeException
e
        Right Text
x -> case Text -> Maybe Text
unescapeText Text
x of
            Maybe Text
Nothing -> String -> Decoder String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid escape"
            Just Text
y -> String -> Decoder String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Decoder String) -> String -> Decoder String
forall a b. (a -> b) -> a -> b
$ Text -> String
String Text
y

findAt :: Word.Word8 -> Int -> ByteString.ByteString -> Maybe Int
findAt :: Word8 -> Int -> ByteString -> Maybe Int
findAt Word8
x Int
i = (Int -> Int) -> Maybe Int -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
i) (Maybe Int -> Maybe Int)
-> (ByteString -> Maybe Int) -> ByteString -> Maybe Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Word8 -> ByteString -> Maybe Int
ByteString.elemIndex Word8
x (ByteString -> Maybe Int)
-> (ByteString -> ByteString) -> ByteString -> Maybe Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ByteString -> ByteString
ByteString.drop Int
i

countConsecutive :: Word.Word8 -> Int -> ByteString.ByteString -> Int
countConsecutive :: Word8 -> Int -> ByteString -> Int
countConsecutive Word8
x Int
i = ByteString -> Int
ByteString.length (ByteString -> Int)
-> (ByteString -> ByteString) -> ByteString -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Word8 -> Bool) -> ByteString -> ByteString
ByteString.takeWhileEnd (Word8 -> Word8 -> Bool
forall a. Eq a => a -> a -> Bool
== Word8
x) (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> ByteString -> ByteString
ByteString.take Int
i

getClose :: ByteString.ByteString -> Int -> Maybe Int
getClose :: ByteString -> Int -> Maybe Int
getClose ByteString
b Int
i = do
    Int
j <- Word8 -> Int -> ByteString -> Maybe Int
findAt Word8
Literal.quotationMark Int
i ByteString
b
    let n :: Int
n = Word8 -> Int -> ByteString -> Int
countConsecutive Word8
Literal.reverseSolidus Int
j ByteString
b
    if Int -> Bool
forall a. Integral a => a -> Bool
even Int
n then Int -> Maybe Int
forall a. a -> Maybe a
Just Int
j else ByteString -> Int -> Maybe Int
getClose ByteString
b (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Int
j Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1

unescapeText :: Text.Text -> Maybe Text.Text
unescapeText :: Text -> Maybe Text
unescapeText = (String -> Text) -> Maybe String -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Text
Text.pack (String -> Text) -> ShowS -> String -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ShowS
combineSurrogatePairs) (Maybe String -> Maybe Text)
-> (Text -> Maybe String) -> Text -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe String
unescapeString (String -> Maybe String)
-> (Text -> String) -> Text -> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
Text.unpack

combineSurrogatePairs :: Prelude.String -> Prelude.String
combineSurrogatePairs :: ShowS
combineSurrogatePairs String
xs = case String
xs of
    String
"" -> String
xs
    Char
x : Char
y : String
zs | Char -> Bool
isHighSurrogate Char
x Bool -> Bool -> Bool
&& Char -> Bool
isLowSurrogate Char
y ->
        Char -> Char -> Char
combineSurrogatePair Char
x Char
y Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
combineSurrogatePairs String
zs
    Char
x : String
ys -> Char
x Char -> ShowS
forall a. a -> [a] -> [a]
: ShowS
combineSurrogatePairs String
ys

combineSurrogatePair :: Char -> Char -> Char
combineSurrogatePair :: Char -> Char -> Char
combineSurrogatePair Char
hi Char
lo = Int -> Char
Char.chr
    (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Int
0x10000
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ ((Char -> Int
Char.ord Char
hi Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
0xd800) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
0x400)
    Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Char -> Int
Char.ord Char
lo Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
0xdc00)

isHighSurrogate :: Char -> Bool
isHighSurrogate :: Char -> Bool
isHighSurrogate Char
x = Char
'\xd800' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
x Bool -> Bool -> Bool
&& Char
x Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xdbff'

isLowSurrogate :: Char -> Bool
isLowSurrogate :: Char -> Bool
isLowSurrogate Char
x = Char
'\xdc00' Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
x Bool -> Bool -> Bool
&& Char
x Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xdfff'

unescapeString :: Prelude.String -> Maybe Prelude.String
unescapeString :: String -> Maybe String
unescapeString String
xs = case String
xs of
    String
"" -> String -> Maybe String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
xs
    Char
'\\' : String
ys -> case String
ys of
        String
"" -> String -> Maybe String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"empty escape"
        Char
x : String
zs -> case Char
x of
            Char
'"' -> (Char
'"' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'\\' -> (Char
'\\' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'/' -> (Char
'/' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'b' -> (Char
'\b' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'f' -> (Char
'\f' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'n' -> (Char
'\n' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'r' -> (Char
'\r' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
't' -> (Char
'\t' Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
zs
            Char
'u' -> case String
zs of
                Char
a : Char
b : Char
c : Char
d : String
es | Just Char
y <- Char -> Char -> Char -> Char -> Maybe Char
fromLongEscape Char
a Char
b Char
c Char
d ->
                    (Char
y Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
es
                String
_ -> String -> Maybe String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid long escape"
            Char
_ -> String -> Maybe String
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"invalid short escape"
    Char
x : String
ys -> (Char
x Char -> ShowS
forall a. a -> [a] -> [a]
:) ShowS -> Maybe String -> Maybe String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe String
unescapeString String
ys

fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char
fromLongEscape :: Char -> Char -> Char -> Char -> Maybe Char
fromLongEscape Char
a Char
b Char
c Char
d = do
    Int
w <- Char -> Maybe Int
fromHexadecimalDigit Char
a
    Int
x <- Char -> Maybe Int
fromHexadecimalDigit Char
b
    Int
y <- Char -> Maybe Int
fromHexadecimalDigit Char
c
    Int
z <- Char -> Maybe Int
fromHexadecimalDigit Char
d
    Char -> Maybe Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Char -> Maybe Char) -> (Int -> Char) -> Int -> Maybe Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Char
Char.chr (Int -> Maybe Char) -> Int -> Maybe Char
forall a b. (a -> b) -> a -> b
$ (Int
0x1000 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
0x100 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
x) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ (Int
0x10 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
y) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
z

fromHexadecimalDigit :: Char -> Maybe Int
fromHexadecimalDigit :: Char -> Maybe Int
fromHexadecimalDigit Char
x =
    if Char -> Bool
Char.isHexDigit Char
x then Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$ Char -> Int
Char.digitToInt Char
x else Maybe Int
forall a. Maybe a
Nothing