-- |
-- Utilities for the UTF-8 encoding.
module Iri.Utf8CodePoint where

import Iri.Prelude

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

{-# INLINE char #-}
char :: Char -> Utf8CodePoint
char :: Char -> Utf8CodePoint
char Char
a =
  Int -> Utf8CodePoint
unicodeCodePoint (Char -> Int
ord Char
a)

{-# INLINE unicodeCodePoint #-}
unicodeCodePoint :: Int -> Utf8CodePoint
unicodeCodePoint :: Int -> Utf8CodePoint
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)