{-# LANGUAGE BangPatterns  #-}
{-# LANGUAGE MagicHash     #-}
{-# LANGUAGE UnboxedTuples #-}

{-|
Module      : Z.Data.Text.UTF8Codec
Description : UTF-8 codecs and helpers.
Copyright   : (c) Dong Han, 2017-2018
License     : BSD
Maintainer  : winterland1989@gmail.com
Stability   : experimental
Portability : non-portable

UTF-8 codecs and helpers.

-}

module Z.Data.Text.UTF8Codec where

import           Control.Monad.Primitive
import           Data.Primitive.ByteArray
import           Data.Primitive.PrimArray
import           GHC.Prim
import           GHC.ST
import           GHC.Types
import           GHC.Word

-- | Return a codepoint's encoded length in bytes
--
-- If the codepoint is invalid, we return 3(encoded bytes length of replacement char @\U+FFFD@).
--
encodeCharLength :: Char -> Int
{-# INLINE encodeCharLength #-}
encodeCharLength :: Char -> Int
encodeCharLength Char
n
    | Char
n Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x00007F' = Int
1
    | Char
n Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x0007FF' = Int
2
    | Char
n Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x00FFFF' = Int
3
    | Char
n Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x10FFFF' = Int
4
    | Bool
otherwise = Int
3

-- | Encode a 'Char' into bytes, write 'replacementChar' for invalid unicode codepoint.
--
-- This function assumed there're enough space for encoded bytes, and return the advanced index.
encodeChar :: MutablePrimArray s Word8 -> Int -> Char -> ST s Int
{-# INLINE encodeChar #-}
encodeChar :: MutablePrimArray s Word8 -> Int -> Char -> ST s Int
encodeChar (MutablePrimArray MutableByteArray# s
mba#) (I# Int#
i#) (C# Char#
c#) = STRep s Int -> ST s Int
forall s a. STRep s a -> ST s a
ST (\ State# s
s# ->
    let !(# State# s
s1#, Int#
j# #) = MutableByteArray# s
-> Int# -> Char# -> State# s -> (# State# s, Int# #)
forall s.
MutableByteArray# s
-> Int# -> Char# -> State# s -> (# State# s, Int# #)
encodeChar# MutableByteArray# s
mba# Int#
i# Char#
c# State# s
s# in (# State# s
s1#, Int# -> Int
I# Int#
j# #))

-- | The unboxed version of 'encodeChar'.
--
-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier
-- due to too much branches.
encodeChar# :: MutableByteArray# s -> Int# -> Char# -> State# s -> (# State# s, Int# #)
{-# NOINLINE encodeChar# #-} -- codesize vs speed choice here
encodeChar# :: MutableByteArray# s
-> Int# -> Char# -> State# s -> (# State# s, Int# #)
encodeChar# MutableByteArray# s
mba# Int#
i# Char#
c# = case (Int# -> Word#
int2Word# (Char# -> Int#
ord# Char#
c#)) of
    Word#
n#
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0000007F##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# Word#
n# State# s
s#
            in (# State# s
s1#, Int#
i# Int# -> Int# -> Int#
+# Int#
1# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x000007FF##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xC0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
            in (# State# s
s2#, Int#
i# Int# -> Int# -> Int#
+# Int#
2# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0000D7FF##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xE0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
12#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s2#
            in (# State# s
s3#, Int#
i# Int# -> Int# -> Int#
+# Int#
3# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0000DFFF##) -> \ State# s
s# -> -- write replacement char \U+FFFD
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# Word#
0xEF## State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) Word#
0xBF## State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) Word#
0xBD## State# s
s2#
            in (# State# s
s3#, Int#
i# Int# -> Int# -> Int#
+# Int#
3# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0000FFFF##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xE0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
12#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s2#
            in (# State# s
s3#, Int#
i# Int# -> Int# -> Int#
+# Int#
3# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0010FFFF##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xF0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
18#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
12#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s2#
                s4# :: State# s
s4# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
3#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s3#
            in (# State# s
s4#, Int#
i# Int# -> Int# -> Int#
+# Int#
4# #)
        | Bool
otherwise -> \ State# s
s# -> -- write replacement char \U+FFFD
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i#  Word#
0xEF## State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) Word#
0xBF## State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) Word#
0xBD## State# s
s2#
            in (# State# s
s3#, Int#
i# Int# -> Int# -> Int#
+# Int#
3# #)


-- | Encode a 'Char' into bytes with non-standard UTF-8 encoding(Used in "Data.CBytes").
--
-- '\NUL' is encoded as two bytes @C0 80@ , '\xD800' ~ '\xDFFF' is encoded as a three bytes normal UTF-8 codepoint.
-- This function assumed there're enough space for encoded bytes, and return the advanced index.
encodeCharModifiedUTF8 :: (PrimMonad m) => MutablePrimArray (PrimState m) Word8 -> Int -> Char -> m Int
{-# INLINE encodeCharModifiedUTF8 #-}
encodeCharModifiedUTF8 :: MutablePrimArray (PrimState m) Word8 -> Int -> Char -> m Int
encodeCharModifiedUTF8 (MutablePrimArray MutableByteArray# (PrimState m)
mba#) (I# Int#
i#) (C# Char#
c#) = (State# (PrimState m) -> (# State# (PrimState m), Int #)) -> m Int
forall (m :: * -> *) a.
PrimMonad m =>
(State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
primitive (\ State# (PrimState m)
s# ->
    let !(# State# (PrimState m)
s1#, Int#
j# #) = MutableByteArray# (PrimState m)
-> Int#
-> Char#
-> State# (PrimState m)
-> (# State# (PrimState m), Int# #)
forall s.
MutableByteArray# s
-> Int# -> Char# -> State# s -> (# State# s, Int# #)
encodeCharModifiedUTF8# MutableByteArray# (PrimState m)
mba# Int#
i# Char#
c# State# (PrimState m)
s# in (# State# (PrimState m)
s1#, Int# -> Int
I# Int#
j# #))

-- | The unboxed version of 'encodeCharModifiedUTF8'.
encodeCharModifiedUTF8# :: MutableByteArray# s -> Int# -> Char# -> State# s -> (# State# s, Int# #)
{-# NOINLINE encodeCharModifiedUTF8# #-} -- codesize vs speed choice here
encodeCharModifiedUTF8# :: MutableByteArray# s
-> Int# -> Char# -> State# s -> (# State# s, Int# #)
encodeCharModifiedUTF8# MutableByteArray# s
mba# Int#
i# Char#
c# = case (Int# -> Word#
int2Word# (Char# -> Int#
ord# Char#
c#)) of
    Word#
n#
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`eqWord#` Word#
0x00000000##) -> \ State# s
s# ->    -- encode \NUL as \xC0 \x80
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# Word#
0xC0## State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) Word#
0x80## State# s
s1#
            in (# State# s
s2#, Int#
i# Int# -> Int# -> Int#
+# Int#
2# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0000007F##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# Word#
n# State# s
s#
            in (# State# s
s1#, Int#
i# Int# -> Int# -> Int#
+# Int#
1# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x000007FF##) -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xC0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
            in (# State# s
s2#, Int#
i# Int# -> Int# -> Int#
+# Int#
2# #)
        | Int# -> Bool
isTrue# (Word#
n# Word# -> Word# -> Int#
`leWord#` Word#
0x0000FFFF##) -> \ State# s
s# ->    -- \xD800 ~ \xDFFF is encoded as normal UTF-8 codepoints
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xE0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
12#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s2#
            in (# State# s
s3#, Int#
i# Int# -> Int# -> Int#
+# Int#
3# #)
        | Bool
otherwise -> \ State# s
s# ->
            let s1# :: State# s
s1# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# Int#
i# (Word#
0xF0## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
18#)) State# s
s#
                s2# :: State# s
s2# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
1#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
12#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s1#
                s3# :: State# s
s3# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
2#) (Word#
0x80## Word# -> Word# -> Word#
`or#` ((Word#
n# Word# -> Int# -> Word#
`uncheckedShiftRL#` Int#
6#) Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s2#
                s4# :: State# s
s4# = MutableByteArray# s -> Int# -> Word# -> State# s -> State# s
forall d.
MutableByteArray# d -> Int# -> Word# -> State# d -> State# d
writeWord8Array# MutableByteArray# s
mba# (Int#
i# Int# -> Int# -> Int#
+# Int#
3#) (Word#
0x80## Word# -> Word# -> Word#
`or#` (Word#
n# Word# -> Word# -> Word#
`and#` Word#
0x3F##)) State# s
s3#
            in (# State# s
s4#, Int#
i# Int# -> Int# -> Int#
+# Int#
4# #)

--------------------------------------------------------------------------------

-- | Decode a 'Char' from bytes
--
-- This function assumed all bytes are UTF-8 encoded, and the index param point to the
-- beginning of a codepoint, the decoded character and the advancing offset are returned.
--
-- It's annoying to use unboxed tuple here but we really don't want allocation even if
-- GHC can't optimize it away.
decodeChar :: PrimArray Word8 -> Int -> (# Char, Int #)
{-# INLINE decodeChar #-}
decodeChar :: PrimArray Word8 -> Int -> (# Char, Int #)
decodeChar (PrimArray ByteArray#
ba#) (I# Int#
idx#) =
    let !(# Char#
c#, Int#
i# #) = ByteArray# -> Int# -> (# Char#, Int# #)
decodeChar# ByteArray#
ba# Int#
idx# in (# Char# -> Char
C# Char#
c#, Int# -> Int
I# Int#
i# #)

decodeChar_ :: PrimArray Word8 -> Int -> Char
{-# INLINE decodeChar_ #-}
decodeChar_ :: PrimArray Word8 -> Int -> Char
decodeChar_ (PrimArray ByteArray#
ba#) (I# Int#
idx#) =
    let !(# Char#
c#, Int#
_ #) = ByteArray# -> Int# -> (# Char#, Int# #)
decodeChar# ByteArray#
ba# Int#
idx# in Char# -> Char
C# Char#
c#

-- | The unboxed version of 'decodeChar'
--
-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier
-- due to too much branches.
decodeChar# :: ByteArray# -> Int# -> (# Char#, Int# #)
{-# NOINLINE decodeChar# #-} -- This branchy code make GHC impossible to fuse, DON'T inline
decodeChar# :: ByteArray# -> Int# -> (# Char#, Int# #)
decodeChar# ByteArray#
ba# Int#
idx# = case ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# Int#
idx# of
    Word#
w1#
        | Int# -> Bool
isTrue# (Word#
w1# Word# -> Word# -> Int#
`leWord#` Word#
0x7F##) -> (# Word# -> Char#
chr1# Word#
w1#, Int#
1# #)
        | Int# -> Bool
isTrue# (Word#
w1# Word# -> Word# -> Int#
`leWord#` Word#
0xDF##) ->
            let w2# :: Word#
w2# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
+# Int#
1#)
            in (# Word# -> Word# -> Char#
chr2# Word#
w1# Word#
w2#, Int#
2# #)
        | Int# -> Bool
isTrue# (Word#
w1# Word# -> Word# -> Int#
`leWord#` Word#
0xEF##) ->
            let w2# :: Word#
w2# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
+# Int#
1#)
                w3# :: Word#
w3# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
+# Int#
2#)
            in (# Word# -> Word# -> Word# -> Char#
chr3# Word#
w1# Word#
w2# Word#
w3#, Int#
3# #)
        | Bool
otherwise ->
            let w2# :: Word#
w2# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
+# Int#
1#)
                w3# :: Word#
w3# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
+# Int#
2#)
                w4# :: Word#
w4# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
+# Int#
3#)
            in (# Word# -> Word# -> Word# -> Word# -> Char#
chr4# Word#
w1# Word#
w2# Word#
w3# Word#
w4#, Int#
4# #)

-- | Decode a codepoint's length in bytes
--
-- This function assumed all bytes are UTF-8 encoded, and the index param point to the
-- beginning of a codepoint.
--
decodeCharLen :: PrimArray Word8 -> Int -> Int
{-# INLINE decodeCharLen #-}
decodeCharLen :: PrimArray Word8 -> Int -> Int
decodeCharLen (PrimArray ByteArray#
ba#) (I# Int#
idx#) =
    let i# :: Int#
i# = ByteArray# -> Int# -> Int#
decodeCharLen# ByteArray#
ba# Int#
idx# in Int# -> Int
I# Int#
i#

-- | The unboxed version of 'decodeCharLen'
--
-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier
-- due to too much branches.
decodeCharLen# :: ByteArray# -> Int# -> Int#
{-# INLINE decodeCharLen# #-} -- This branchy code make GHC impossible to fuse, DON'T inline
decodeCharLen# :: ByteArray# -> Int# -> Int#
decodeCharLen# ByteArray#
ba# Int#
idx# = case ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# Int#
idx# of
    Word#
w1#
        | Int# -> Bool
isTrue# (Word#
w1# Word# -> Word# -> Int#
`leWord#` Word#
0x7F##) -> Int#
1#
        | Int# -> Bool
isTrue# (Word#
w1# Word# -> Word# -> Int#
`leWord#` Word#
0xDF##) -> Int#
2#
        | Int# -> Bool
isTrue# (Word#
w1# Word# -> Word# -> Int#
`leWord#` Word#
0xEF##) -> Int#
3#
        | Bool
otherwise -> Int#
4#

-- | Decode a 'Char' from bytes in rerverse order.
--
-- This function assumed all bytes are UTF-8 encoded, and the index param point to the end
-- of a codepoint, the decoded character and the backward advancing offset are returned.
--
decodeCharReverse :: PrimArray Word8 -> Int -> (# Char, Int #)
{-# INLINE decodeCharReverse #-}
decodeCharReverse :: PrimArray Word8 -> Int -> (# Char, Int #)
decodeCharReverse (PrimArray ByteArray#
ba#) (I# Int#
idx#) =
    let !(# Char#
c#, Int#
i# #) = ByteArray# -> Int# -> (# Char#, Int# #)
decodeCharReverse# ByteArray#
ba# Int#
idx# in (# Char# -> Char
C# Char#
c#, Int# -> Int
I# Int#
i# #)

decodeCharReverse_ :: PrimArray Word8 -> Int -> Char
{-# INLINE decodeCharReverse_ #-}
decodeCharReverse_ :: PrimArray Word8 -> Int -> Char
decodeCharReverse_ (PrimArray ByteArray#
ba#) (I# Int#
idx#) =
    let !(# Char#
c#, Int#
_ #) = ByteArray# -> Int# -> (# Char#, Int# #)
decodeCharReverse# ByteArray#
ba# Int#
idx# in Char# -> Char
C# Char#
c#

-- | The unboxed version of 'decodeCharReverse'
--
-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier
-- due to too much branches.
decodeCharReverse# :: ByteArray# -> Int# -> (# Char#, Int# #)
{-# NOINLINE decodeCharReverse# #-} -- This branchy code make GHC impossible to fuse, DON'T inline
decodeCharReverse# :: ByteArray# -> Int# -> (# Char#, Int# #)
decodeCharReverse# ByteArray#
ba# Int#
idx# =
    let w1# :: Word#
w1# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# Int#
idx#
    in if Word# -> Bool
isContinueByte# Word#
w1#
    then
        let w2# :: Word#
w2# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
-# Int#
1#)
        in if Word# -> Bool
isContinueByte# Word#
w2#
        then
            let w3# :: Word#
w3# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
-# Int#
2#)
            in if Word# -> Bool
isContinueByte# Word#
w3#
            then
                let w4# :: Word#
w4# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
-# Int#
3#)
                in (# Word# -> Word# -> Word# -> Word# -> Char#
chr4# Word#
w4# Word#
w3# Word#
w2# Word#
w1#, Int#
4# #)
            else (# Word# -> Word# -> Word# -> Char#
chr3# Word#
w3# Word#
w2# Word#
w1#, Int#
3# #)
        else  (# Word# -> Word# -> Char#
chr2# Word#
w2# Word#
w1#, Int#
2# #)
    else (# Word# -> Char#
chr1# Word#
w1#, Int#
1# #)


-- | Decode a codepoint's length in bytes in reverse order.
--
-- This function assumed all bytes are UTF-8 encoded, and the index param point to the end
-- of a codepoint.
--
decodeCharLenReverse :: PrimArray Word8 -> Int -> Int
{-# INLINE decodeCharLenReverse #-}
decodeCharLenReverse :: PrimArray Word8 -> Int -> Int
decodeCharLenReverse (PrimArray ByteArray#
ba#) (I# Int#
idx#) =
    let i# :: Int#
i# = ByteArray# -> Int# -> Int#
decodeCharLenReverse# ByteArray#
ba# Int#
idx# in Int# -> Int
I# Int#
i#

-- | The unboxed version of 'decodeCharLenReverse'
--
-- This function is marked as @NOINLINE@ to reduce code size, and stop messing up simplifier
-- due to too much branches.
decodeCharLenReverse# :: ByteArray# -> Int# -> Int#
{-# NOINLINE decodeCharLenReverse# #-} -- This branchy code make GHC impossible to fuse, DON'T inline
decodeCharLenReverse# :: ByteArray# -> Int# -> Int#
decodeCharLenReverse# ByteArray#
ba# Int#
idx# =
    let w1# :: Word#
w1# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# Int#
idx#
    in if Word# -> Bool
isContinueByte# Word#
w1#
    then
        let w2# :: Word#
w2# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
-# Int#
1#)
        in if Word# -> Bool
isContinueByte# Word#
w2#
        then
            let w3# :: Word#
w3# = ByteArray# -> Int# -> Word#
indexWord8Array# ByteArray#
ba# (Int#
idx# Int# -> Int# -> Int#
-# Int#
2#)
            in if Word# -> Bool
isContinueByte# Word#
w3#
            then Int#
4#
            else Int#
3#
        else Int#
2#
    else Int#
1#

--------------------------------------------------------------------------------

between# :: Word# -> Word# -> Word# -> Bool
{-# INLINE between# #-}
between# :: Word# -> Word# -> Word# -> Bool
between# Word#
w# Word#
l# Word#
h# = Int# -> Bool
isTrue# (Word#
w# Word# -> Word# -> Int#
`geWord#` Word#
l#) Bool -> Bool -> Bool
&& Int# -> Bool
isTrue# (Word#
w# Word# -> Word# -> Int#
`leWord#` Word#
h#)

isContinueByte# :: Word# -> Bool
{-# INLINE isContinueByte# #-}
isContinueByte# :: Word# -> Bool
isContinueByte# Word#
w# = Int# -> Bool
isTrue# (Word# -> Word# -> Word#
and# Word#
w# Word#
0xC0## Word# -> Word# -> Int#
`eqWord#` Word#
0x80##)

chr1# :: Word# -> Char#
{-# INLINE chr1# #-}
chr1# :: Word# -> Char#
chr1# Word#
x1# = Int# -> Char#
chr# Int#
y1#
  where
    !y1# :: Int#
y1# = Word# -> Int#
word2Int# Word#
x1#

chr2# :: Word# -> Word# -> Char#
{-# INLINE chr2# #-}
chr2# :: Word# -> Word# -> Char#
chr2# Word#
x1# Word#
x2# = Int# -> Char#
chr# (Int#
z1# Int# -> Int# -> Int#
+# Int#
z2#)
  where
    !y1# :: Int#
y1# = Word# -> Int#
word2Int# Word#
x1#
    !y2# :: Int#
y2# = Word# -> Int#
word2Int# Word#
x2#
    !z1# :: Int#
z1# = Int# -> Int# -> Int#
uncheckedIShiftL# (Int#
y1# Int# -> Int# -> Int#
-# Int#
0xC0#) Int#
6#
    !z2# :: Int#
z2# = Int#
y2# Int# -> Int# -> Int#
-# Int#
0x80#

chr3# :: Word# -> Word# -> Word# -> Char#
{-# INLINE chr3# #-}
chr3# :: Word# -> Word# -> Word# -> Char#
chr3# Word#
x1# Word#
x2# Word#
x3# = Int# -> Char#
chr# (Int#
z1# Int# -> Int# -> Int#
+# Int#
z2# Int# -> Int# -> Int#
+# Int#
z3#)
  where
    !y1# :: Int#
y1# = Word# -> Int#
word2Int# Word#
x1#
    !y2# :: Int#
y2# = Word# -> Int#
word2Int# Word#
x2#
    !y3# :: Int#
y3# = Word# -> Int#
word2Int# Word#
x3#
    !z1# :: Int#
z1# = Int# -> Int# -> Int#
uncheckedIShiftL# (Int#
y1# Int# -> Int# -> Int#
-# Int#
0xE0#) Int#
12#
    !z2# :: Int#
z2# = Int# -> Int# -> Int#
uncheckedIShiftL# (Int#
y2# Int# -> Int# -> Int#
-# Int#
0x80#) Int#
6#
    !z3# :: Int#
z3# = Int#
y3# Int# -> Int# -> Int#
-# Int#
0x80#

chr4# :: Word# -> Word# -> Word# -> Word# -> Char#
{-# INLINE chr4# #-}
chr4# :: Word# -> Word# -> Word# -> Word# -> Char#
chr4# Word#
x1# Word#
x2# Word#
x3# Word#
x4# = Int# -> Char#
chr# (Int#
z1# Int# -> Int# -> Int#
+# Int#
z2# Int# -> Int# -> Int#
+# Int#
z3# Int# -> Int# -> Int#
+# Int#
z4#)
  where
    !y1# :: Int#
y1# = Word# -> Int#
word2Int# Word#
x1#
    !y2# :: Int#
y2# = Word# -> Int#
word2Int# Word#
x2#
    !y3# :: Int#
y3# = Word# -> Int#
word2Int# Word#
x3#
    !y4# :: Int#
y4# = Word# -> Int#
word2Int# Word#
x4#
    !z1# :: Int#
z1# = Int# -> Int# -> Int#
uncheckedIShiftL# (Int#
y1# Int# -> Int# -> Int#
-# Int#
0xF0#) Int#
18#
    !z2# :: Int#
z2# = Int# -> Int# -> Int#
uncheckedIShiftL# (Int#
y2# Int# -> Int# -> Int#
-# Int#
0x80#) Int#
12#
    !z3# :: Int#
z3# = Int# -> Int# -> Int#
uncheckedIShiftL# (Int#
y3# Int# -> Int# -> Int#
-# Int#
0x80#) Int#
6#
    !z4# :: Int#
z4# = Int#
y4# Int# -> Int# -> Int#
-# Int#
0x80#

--------------------------------------------------------------------------------

-- | Unrolled copy loop for copying a utf8-encoded codepoint from source array to target array.
--
copyChar :: Int                       -- copy length, must be 1, 2, 3 or 4
         -> MutablePrimArray s Word8  -- target array
         -> Int                       -- writing offset
         -> PrimArray Word8           -- source array
         -> Int                       -- reading offset
         -> ST s ()
{-# INLINE copyChar #-}
copyChar :: Int
-> MutablePrimArray s Word8
-> Int
-> PrimArray Word8
-> Int
-> ST s ()
copyChar !Int
l !MutablePrimArray s Word8
mba !Int
j !PrimArray Word8
ba !Int
i = case Int
l of
    Int
1 -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba Int
i
    Int
2 -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba Int
i
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
    Int
3 -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba Int
i
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)
    Int
_ -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba Int
i
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) (Word8 -> ST s ()) -> Word8 -> ST s ()
forall a b. (a -> b) -> a -> b
$ PrimArray Word8 -> Int -> Word8
forall a. Prim a => PrimArray a -> Int -> a
indexPrimArray PrimArray Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3)

-- | Unrolled copy loop for copying a utf8-encoded codepoint from source array to target array.
--
copyChar' :: Int                       -- copy length, must be 1, 2, 3 or 4
          -> MutablePrimArray s Word8  -- target array
          -> Int                       -- writing offset
          -> MutablePrimArray s Word8  -- source array
          -> Int                       -- reading offset
          -> ST s ()
{-# INLINE copyChar' #-}
copyChar' :: Int
-> MutablePrimArray s Word8
-> Int
-> MutablePrimArray s Word8
-> Int
-> ST s ()
copyChar' !Int
l !MutablePrimArray s Word8
mba !Int
j !MutablePrimArray s Word8
ba !Int
i = case Int
l of
    Int
1 -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba Int
i
    Int
2 -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba Int
i
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
    Int
3 -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba Int
i
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)
    Int
_ -> do MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba Int
j (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba Int
i
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1) (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2) (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
2)
            MutablePrimArray (PrimState (ST s)) Word8
-> Int -> Word8 -> ST s ()
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> a -> m ()
writePrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
mba (Int
jInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3) (Word8 -> ST s ()) -> ST s Word8 -> ST s ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< MutablePrimArray (PrimState (ST s)) Word8 -> Int -> ST s Word8
forall a (m :: * -> *).
(Prim a, PrimMonad m) =>
MutablePrimArray (PrimState m) a -> Int -> m a
readPrimArray MutablePrimArray s Word8
MutablePrimArray (PrimState (ST s)) Word8
ba (Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
3)

-- | @\xFFFD@, which will be encoded as @0xEF 0xBF 0xBD@ 3 bytes.
replacementChar :: Char
replacementChar :: Char
replacementChar = Char
'\xFFFD'