-- |
-- Module      : Streamly.Internal.Unicode.Utf8
-- Copyright   : (c) 2021 Composewell Technologies
-- License     : BSD-3-Clause
-- Maintainer  : streamly@composewell.com
-- Stability   : experimental
-- Portability : GHC
--
module Streamly.Internal.Unicode.Utf8
    (
    -- * Type
      Utf8

    -- * Creation and elimination
    , pack
    , unpack
    , toArray
    )
where

--------------------------------------------------------------------------------
-- Imports
--------------------------------------------------------------------------------

import Control.DeepSeq (NFData)
import Data.Word (Word8)
import Streamly.Internal.Data.Array.Foreign.Type (Array)
import System.IO.Unsafe (unsafePerformIO)

import qualified Streamly.Internal.Data.Array.Foreign as Array
import qualified Streamly.Internal.Data.Stream.IsStream as Stream
import qualified Streamly.Internal.Unicode.Stream as Unicode

--------------------------------------------------------------------------------
-- Type
--------------------------------------------------------------------------------

-- | A space efficient, packed, unboxed Unicode container.
newtype Utf8 =
    Utf8 (Array Word8)
    deriving (Utf8 -> ()
forall a. (a -> ()) -> NFData a
rnf :: Utf8 -> ()
$crnf :: Utf8 -> ()
NFData)

--------------------------------------------------------------------------------
-- Functions
--------------------------------------------------------------------------------

{-# INLINE toArray #-}
toArray :: Utf8 -> Array Word8
toArray :: Utf8 -> Array Word8
toArray (Utf8 Array Word8
arr) = Array Word8
arr


{-# INLINEABLE pack #-}
pack :: String -> Utf8
pack :: String -> Utf8
pack String
s =
    Array Word8 -> Utf8
Utf8
        forall a b. (a -> b) -> a -> b
$ forall a. IO a -> a
unsafePerformIO
        forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(MonadIO m, Storable a) =>
Int -> SerialT m a -> m (Array a)
Array.fromStreamN Int
len forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) (t :: (* -> *) -> * -> *).
(Monad m, IsStream t) =>
t m Char -> t m Word8
Unicode.encodeUtf8' forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) (t :: (* -> *) -> * -> *) a.
(Monad m, IsStream t) =>
[a] -> t m a
Stream.fromList String
s

    where

    len :: Int
len = forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s

{-# INLINEABLE unpack #-}
unpack :: Utf8 -> String
unpack :: Utf8 -> String
unpack Utf8
u =
    forall a. IO a -> a
unsafePerformIO
        forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => SerialT m a -> m [a]
Stream.toList forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) (t :: (* -> *) -> * -> *).
(Monad m, IsStream t) =>
t m Word8 -> t m Char
Unicode.decodeUtf8' forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a.
(Monad m, Storable a) =>
Array a -> SerialT m a
Array.toStream forall a b. (a -> b) -> a -> b
$ Utf8 -> Array Word8
toArray Utf8
u