{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Basement.String.Builder
    ( Builder
    , run
    , runUnsafe
    
    , emit
    , emitChar
    
    , unsafeStringBuilder
    ) where
import qualified Basement.Block.Base as Block (length)
import qualified Basement.Block.Builder as Block
import           Basement.Compat.Base
import           Basement.Compat.Semigroup
import           Basement.Monad
import           Basement.String (String, ValidationFailure, Encoding (UTF8), fromBytes)
import           Basement.UArray.Base (UArray)
import qualified Basement.UArray.Base as A
newtype Builder = Builder Block.Builder
  deriving (Semigroup, Monoid)
unsafeStringBuilder :: Block.Builder -> Builder
unsafeStringBuilder = Builder
{-# INLINE unsafeStringBuilder #-}
run :: PrimMonad prim => Builder -> prim (String, Maybe ValidationFailure, UArray Word8)
run (Builder builder) = do
    block <- Block.run builder
    let array = A.UArray 0 (Block.length block) (A.UArrayBA block)
    pure $ fromBytes UTF8 array
runUnsafe :: PrimMonad prim => Builder -> prim String
runUnsafe (Builder builder) = Block.unsafeRunString builder
emit :: String -> Builder
emit = Builder . Block.emitString
emitChar :: Char -> Builder
emitChar = Builder . Block.emitUTF8Char