module Foundation.String.Encoding.ASCII7
    ( ASCII7(..)
    , ASCII7_Invalid(..)
    ) where
import Foundation.Internal.Base
import Foundation.Primitive.Types.OffsetSize
import Foundation.Numerical
import Foundation.Primitive.Monad
import GHC.Prim
import GHC.Word
import GHC.Types
import Foundation.Array.Unboxed
import Foundation.Array.Unboxed.Mutable (MUArray)
import Foundation.Boot.Builder
import Foundation.String.Encoding.Encoding
isAscii :: Word8 -> Bool
isAscii (W8# w) = W8# (and# w 0x80## ) == 0
aone :: Offset Word8
aone = Offset 1
data ASCII7_Invalid
    = ByteOutOfBound Word8
    | CharNotAscii   Char
  deriving (Typeable, Show, Eq)
instance Exception ASCII7_Invalid
data ASCII7 = ASCII7
instance Encoding ASCII7 where
    type Unit ASCII7 = Word8
    type Error ASCII7 = ASCII7_Invalid
    encodingNext  _ = next
    encodingWrite _ = write
next :: (Offset Word8 -> Word8)
          
     -> Offset Word8
          
     -> Either ASCII7_Invalid (Char, Offset Word8)
          
          
next getter off
    | isAscii w8 = Right (toChar w, off + aone)
    | otherwise  = Left $ ByteOutOfBound w8
  where
    !w8@(W8# w) = getter off
    toChar :: Word# -> Char
    toChar a = C# (chr# (word2Int# a))
write :: (PrimMonad st, Monad st)
      => Char
           
           
      -> Builder (UArray Word8) (MUArray Word8) Word8 st ()
write c
    | c < toEnum 0x80 = builderAppend $ w8 c
    | otherwise       = throw $ CharNotAscii c
  where
    w8 :: Char -> Word8
    w8 (C# ch) = W8# (int2Word# (ord# ch))