-- |
-- Utilities for the UTF-8 encoding.
module ByteString.StrictBuilder.UTF8 where

import ByteString.StrictBuilder.Prelude

-- |
-- Church encoding of a UTF8-encoded character.
type UTF8Char =
  forall a.
  (Word8 -> a) ->
  (Word8 -> Word8 -> a) ->
  (Word8 -> Word8 -> Word8 -> a) ->
  (Word8 -> Word8 -> Word8 -> Word8 -> a) ->
  a

{-# INLINE char #-}
char :: Char -> UTF8Char
char :: Char -> UTF8Char
char Char
x =
  Int -> UTF8Char
unicodeCodePoint (Char -> Int
ord Char
x)

{-# INLINE unicodeCodePoint #-}
unicodeCodePoint :: Int -> UTF8Char
unicodeCodePoint :: Int -> UTF8Char
unicodeCodePoint Int
x Word8 -> a
f1 Word8 -> Word8 -> a
f2 Word8 -> Word8 -> Word8 -> a
f3 Word8 -> Word8 -> Word8 -> Word8 -> a
f4 =
  if Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0x7F
    then Word8 -> a
f1 (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
x)
    else
      if Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0x07FF
        then
          Word8 -> Word8 -> a
f2
            (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Int
x Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
6) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
0xC0))
            (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Int
x Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0x3F) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
0x80))
        else
          if Int
x Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0xFFFF
            then
              Word8 -> Word8 -> Word8 -> a
f3
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
x Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
12) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0xE0)
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Int
x Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
6) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0x3F) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0x80)
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
x Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0x3F) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0x80)
            else
              Word8 -> Word8 -> Word8 -> Word8 -> a
f4
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
x Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
18) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0xF0)
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Int
x Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
12) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0x3F) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0x80)
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral ((Int
x Int -> Int -> Int
forall a. Bits a => a -> Int -> a
`shiftR` Int
6) Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0x3F) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0x80)
                (Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int
x Int -> Int -> Int
forall a. Bits a => a -> a -> a
.&. Int
0x3F) Word8 -> Word8 -> Word8
forall a. Num a => a -> a -> a
+ Word8
0x80)