{-# LANGUAGE BangPatterns               #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MagicHash                  #-}
{-# LANGUAGE TypeFamilies               #-}
{-# LANGUAGE FlexibleContexts           #-}
module Basement.Types.AsciiString
    ( AsciiString(..)
    , MutableAsciiString(..)
    
    , fromBytesUnsafe
    , fromBytes
    ) where
import           Basement.Compat.Base
import           Basement.Compat.Semigroup
import           Basement.Types.Char7
import           Basement.UArray.Base
import qualified Basement.Types.Char7 as Char7
import qualified Basement.UArray as A (all, unsafeRecast)
newtype AsciiString = AsciiString { toBytes :: UArray Char7 }
    deriving (Typeable, Semigroup, Monoid, Eq, Ord)
newtype MutableAsciiString st = MutableAsciiString (MUArray Char7 st)
    deriving (Typeable)
instance Show AsciiString where
    show = fmap Char7.toChar . toList
instance IsString AsciiString where
    fromString = fromList . fmap Char7.fromCharMask
instance IsList AsciiString where
    type Item AsciiString = Char7
    fromList = AsciiString . fromList
    toList (AsciiString chars) = toList chars
fromBytesUnsafe :: UArray Word8 -> AsciiString
fromBytesUnsafe = AsciiString . A.unsafeRecast
fromBytes :: UArray Word8 -> Maybe AsciiString
fromBytes arr
    | A.all (\x -> x < 0x80) arr = Just $ AsciiString $ A.unsafeRecast arr
    | otherwise                  = Nothing