    {-# LANGUAGE PatternSynonyms #-}
    {-# LANGUAGE ViewPatterns #-}
    {-# LANGUAGE DeriveGeneric #-}

    -- |
    -- Module      : Unicode.Char.General.Blocks
    -- Copyright   : (c) 2020 Composewell Technologies and Contributors
    -- License     : Apache-2.0
    -- Maintainer  : streamly@composewell.com
    -- Stability   : experimental
    --
    -- Unicode [blocks](https://www.unicode.org/glossary/#block) related functions.
    --
    -- @since 0.3.1

    module Unicode.Char.General.Blocks
        ( -- * Blocks
          B.Block(..)
        , block
          -- * Blocks definitions
        , BlockDefinition(..)
        , blockDefinition
        )

    where

    import GHC.Exts (Char (..), Int (..), dataToTag#, tagToEnum#)

    import Unicode.Internal.Bits (unpackCString#)
    import qualified Unicode.Internal.Char.Blocks as B

    -- | Character [block](https://www.unicode.org/glossary/#block), if defined.
    --
    -- @since 0.3.1
    {-# INLINE block #-}
    block :: Char -> Maybe B.Block
    block :: Char -> Maybe Block
    block (C# Char#
    c#) = case Char# -> Int#
    B.block Char#
    c# of
        Int#
    -1# -> Maybe Block
    forall a. Maybe a
    Nothing
        Int#
    b#  -> Block -> Maybe Block
    forall a. a -> Maybe a
    Just (Int# -> Block
    forall a. Int# -> a
    tagToEnum# Int#
    b# :: B.Block)

    -- | Block definition: range and name.
    --
    -- @since 0.3.1
    data BlockDefinition = BlockDefinition
        { BlockDefinition -> (Int, Int)
    blockRange :: !(Int, Int) -- ^ Range
        , BlockDefinition -> String
    blockName :: !String      -- ^ Name
        } deriving (BlockDefinition -> BlockDefinition -> Bool
    (BlockDefinition -> BlockDefinition -> Bool)
    -> (BlockDefinition -> BlockDefinition -> Bool)
    -> Eq BlockDefinition
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    $c== :: BlockDefinition -> BlockDefinition -> Bool
    == :: BlockDefinition -> BlockDefinition -> Bool
    $c/= :: BlockDefinition -> BlockDefinition -> Bool
    /= :: BlockDefinition -> BlockDefinition -> Bool
    Eq, Eq BlockDefinition
    Eq BlockDefinition =>
    (BlockDefinition -> BlockDefinition -> Ordering)
    -> (BlockDefinition -> BlockDefinition -> Bool)
    -> (BlockDefinition -> BlockDefinition -> Bool)
    -> (BlockDefinition -> BlockDefinition -> Bool)
    -> (BlockDefinition -> BlockDefinition -> Bool)
    -> (BlockDefinition -> BlockDefinition -> BlockDefinition)
    -> (BlockDefinition -> BlockDefinition -> BlockDefinition)
    -> Ord BlockDefinition
    BlockDefinition -> BlockDefinition -> Bool
    BlockDefinition -> BlockDefinition -> Ordering
    BlockDefinition -> BlockDefinition -> BlockDefinition
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    $ccompare :: BlockDefinition -> BlockDefinition -> Ordering
    compare :: BlockDefinition -> BlockDefinition -> Ordering
    $c< :: BlockDefinition -> BlockDefinition -> Bool
    < :: BlockDefinition -> BlockDefinition -> Bool
    $c<= :: BlockDefinition -> BlockDefinition -> Bool
    <= :: BlockDefinition -> BlockDefinition -> Bool
    $c> :: BlockDefinition -> BlockDefinition -> Bool
    > :: BlockDefinition -> BlockDefinition -> Bool
    $c>= :: BlockDefinition -> BlockDefinition -> Bool
    >= :: BlockDefinition -> BlockDefinition -> Bool
    $cmax :: BlockDefinition -> BlockDefinition -> BlockDefinition
    max :: BlockDefinition -> BlockDefinition -> BlockDefinition
    $cmin :: BlockDefinition -> BlockDefinition -> BlockDefinition
    min :: BlockDefinition -> BlockDefinition -> BlockDefinition
    Ord, Int -> BlockDefinition -> ShowS
    [BlockDefinition] -> ShowS
    BlockDefinition -> String
    (Int -> BlockDefinition -> ShowS)
    -> (BlockDefinition -> String)
    -> ([BlockDefinition] -> ShowS)
    -> Show BlockDefinition
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> BlockDefinition -> ShowS
    showsPrec :: Int -> BlockDefinition -> ShowS
    $cshow :: BlockDefinition -> String
    show :: BlockDefinition -> String
    $cshowList :: [BlockDefinition] -> ShowS
    showList :: [BlockDefinition] -> ShowS
    Show)

    -- | Block definition
    --
    -- @since 0.3.1
    blockDefinition :: B.Block -> BlockDefinition
    blockDefinition :: Block -> BlockDefinition
    blockDefinition Block
    b = case Int# -> (# Int#, Int#, Addr# #)
    B.blockDefinition (Block -> Int#
    forall a. DataToTag a => a -> Int#
    dataToTag# Block
    b) of
        (# Int#
    lower#, Int#
    upper#, Addr#
    name# #) -> (Int, Int) -> String -> BlockDefinition
    BlockDefinition (Int, Int)
    range String
    name
            where
            !range :: (Int, Int)
    range = (Int# -> Int
    I# Int#
    lower#, Int# -> Int
    I# Int#
    upper#)
            -- Note: names are ASCII. See Unicode Standard 15.0.0, section 3.4.
            !name :: String
    name = Addr# -> String
    unpackCString# Addr#
    name#