    {-# LANGUAGE CPP, MagicHash #-}

    -- |
    -- Module      : Data.Text.Internal.Unsafe.Char
    -- Copyright   : (c) 2008, 2009 Tom Harper,
    --               (c) 2009, 2010 Bryan O'Sullivan,
    --               (c) 2009 Duncan Coutts
    --
    -- License     : BSD-style
    -- Maintainer  : bos@serpentine.com
    -- Stability   : experimental
    -- Portability : GHC
    --
    -- /Warning/: this is an internal module, and does not have a stable
    -- API or name. Functions in this module may not check or enforce
    -- preconditions expected by public modules. Use at your own risk!
    --
    -- Fast character manipulation functions.
    module Data.Text.Internal.Unsafe.Char
        (
          ord
        , unsafeChr16
        , unsafeChr8
        , unsafeChr32
        , unsafeWrite
        ) where

    import Control.Monad.ST (ST)
    import Data.Text.Internal.Encoding.Utf8
    import GHC.Exts (Char(..), Int(..), chr#, ord#, word2Int#)
    import GHC.Word (Word8(..), Word16(..), Word32(..))
    import qualified Data.Text.Array as A
    import Data.Text.Internal.PrimCompat ( word8ToWord#, word16ToWord#, word32ToWord# )
    #if defined(ASSERTS)
    import GHC.Stack (HasCallStack)
    #endif

    ord :: Char -> Int
    ord :: Char -> Int
    ord (C# Char#
    c#) = Int# -> Int
    I# (Char# -> Int#
    ord# Char#
    c#)
    {-# INLINE ord #-}

    -- | @since 2.0
    unsafeChr16 :: Word16 -> Char
    unsafeChr16 :: Word16 -> Char
    unsafeChr16 (W16# Word16#
    w#) = Char# -> Char
    C# (Int# -> Char#
    chr# (Word# -> Int#
    word2Int# (Word16# -> Word#
    word16ToWord# Word16#
    w#)))
    {-# INLINE unsafeChr16 #-}

    unsafeChr8 :: Word8 -> Char
    unsafeChr8 :: Word8 -> Char
    unsafeChr8 (W8# Word8#
    w#) = Char# -> Char
    C# (Int# -> Char#
    chr# (Word# -> Int#
    word2Int# (Word8# -> Word#
    word8ToWord# Word8#
    w#)))
    {-# INLINE unsafeChr8 #-}

    unsafeChr32 :: Word32 -> Char
    unsafeChr32 :: Word32 -> Char
    unsafeChr32 (W32# Word32#
    w#) = Char# -> Char
    C# (Int# -> Char#
    chr# (Word# -> Int#
    word2Int# (Word32# -> Word#
    word32ToWord# Word32#
    w#)))
    {-# INLINE unsafeChr32 #-}

    -- | Write a character into the array at the given offset.  Returns
    -- the number of 'Word8's written.
    unsafeWrite ::
    #if defined(ASSERTS)
        HasCallStack =>
    #endif
        A.MArray s -> Int -> Char -> ST s Int
    unsafeWrite :: forall s. MArray s -> Int -> Char -> ST s Int
    unsafeWrite MArray s
    marr Int
    i Char
    c = case Char -> Int
    utf8Length Char
    c of
        Int
    1 -> do
            let n0 :: Word8
    n0 = Int -> Word8
    intToWord8 (Char -> Int
    ord Char
    c)
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr Int
    i Word8
    n0
            Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    1
        Int
    2 -> do
            let (Word8
    n0, Word8
    n1) = Char -> (Word8, Word8)
    ord2 Char
    c
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr Int
    i     Word8
    n0
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) Word8
    n1
            Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    2
        Int
    3 -> do
            let (Word8
    n0, Word8
    n1, Word8
    n2) = Char -> (Word8, Word8, Word8)
    ord3 Char
    c
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr Int
    i     Word8
    n0
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) Word8
    n1
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    2) Word8
    n2
            Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    3
        Int
    _ -> do
            let (Word8
    n0, Word8
    n1, Word8
    n2, Word8
    n3) = Char -> (Word8, Word8, Word8, Word8)
    ord4 Char
    c
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr Int
    i     Word8
    n0
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    1) Word8
    n1
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    2) Word8
    n2
            MArray s -> Int -> Word8 -> ST s ()
    forall s. MArray s -> Int -> Word8 -> ST s ()
    A.unsafeWrite MArray s
    marr (Int
    iInt -> Int -> Int
    forall a. Num a => a -> a -> a
    +Int
    3) Word8
    n3
            Int -> ST s Int
    forall a. a -> ST s a
    forall (m :: * -> *) a. Monad m => a -> m a
    return Int
    4
    {-# INLINE unsafeWrite #-}

    intToWord8 :: Int -> Word8
    intToWord8 :: Int -> Word8
    intToWord8 = Int -> Word8
    forall a b. (Integral a, Num b) => a -> b
    fromIntegral