-- |
-- Module      : Basement.String.Encoding.ISO_8859_1
-- License     : BSD-style
-- Maintainer  : Foundation
-- Stability   : experimental
-- Portability : portable
--

{-# LANGUAGE MagicHash #-}

module Basement.String.Encoding.ISO_8859_1
    ( ISO_8859_1(..)
    , ISO_8859_1_Invalid(..)
    ) where

import Basement.Compat.Base
import Basement.Compat.Primitive
import Basement.Types.OffsetSize
import Basement.Numerical.Additive
import Basement.Monad

import GHC.Prim (int2Word#, ord#)
import GHC.Word
import GHC.Types
import Basement.UArray
import Basement.UArray.Mutable (MUArray)
import Basement.MutableBuilder

import Basement.String.Encoding.Encoding

-- offset of size one
aone :: Offset Word8
aone :: Offset Word8
aone = forall ty. Int -> Offset ty
Offset Int
1

data ISO_8859_1_Invalid
    = NotISO_8859_1 Char
  deriving (Typeable, Int -> ISO_8859_1_Invalid -> ShowS
[ISO_8859_1_Invalid] -> ShowS
ISO_8859_1_Invalid -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ISO_8859_1_Invalid] -> ShowS
$cshowList :: [ISO_8859_1_Invalid] -> ShowS
show :: ISO_8859_1_Invalid -> String
$cshow :: ISO_8859_1_Invalid -> String
showsPrec :: Int -> ISO_8859_1_Invalid -> ShowS
$cshowsPrec :: Int -> ISO_8859_1_Invalid -> ShowS
Show, ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
$c/= :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
== :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
$c== :: ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool
Eq)
instance Exception ISO_8859_1_Invalid

data ISO_8859_1 = ISO_8859_1

instance Encoding ISO_8859_1 where
    type Unit ISO_8859_1 = Word8
    type Error ISO_8859_1 = ISO_8859_1_Invalid
    encodingNext :: ISO_8859_1
-> (Offset (Unit ISO_8859_1) -> Unit ISO_8859_1)
-> Offset (Unit ISO_8859_1)
-> Either (Error ISO_8859_1) (Char, Offset (Unit ISO_8859_1))
encodingNext  ISO_8859_1
_ = (Offset Word8 -> Word8)
-> Offset Word8 -> Either ISO_8859_1_Invalid (Char, Offset Word8)
next
    encodingWrite :: forall (st :: * -> *) err.
(PrimMonad st, Monad st) =>
ISO_8859_1
-> Char
-> Builder
     (UArray (Unit ISO_8859_1))
     (MUArray (Unit ISO_8859_1))
     (Unit ISO_8859_1)
     st
     err
     ()
encodingWrite ISO_8859_1
_ = forall (st :: * -> *) err.
(PrimMonad st, Monad st) =>
Char -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
write

next :: (Offset Word8 -> Word8)
     -> Offset Word8
     -> Either ISO_8859_1_Invalid (Char, Offset Word8)
next :: (Offset Word8 -> Word8)
-> Offset Word8 -> Either ISO_8859_1_Invalid (Char, Offset Word8)
next Offset Word8 -> Word8
getter Offset Word8
off = forall a b. b -> Either a b
Right (Word8# -> Char
toChar Word8#
w, Offset Word8
off forall a. Additive a => a -> a -> a
+ Offset Word8
aone)
  where
    !(W8# Word8#
w) = Offset Word8 -> Word8
getter Offset Word8
off
    toChar :: Word8# -> Char
    toChar :: Word8# -> Char
toChar Word8#
a = Char# -> Char
C# (Word8# -> Char#
word8ToChar# Word8#
w)

write :: (PrimMonad st, Monad st)
      => Char
      -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
write :: forall (st :: * -> *) err.
(PrimMonad st, Monad st) =>
Char -> Builder (UArray Word8) (MUArray Word8) Word8 st err ()
write c :: Char
c@(C# Char#
ch)
    | Char
c forall a. Ord a => a -> a -> Bool
<= forall a. Enum a => Int -> a
toEnum Int
0xFF = forall ty (state :: * -> *) err.
(PrimType ty, PrimMonad state) =>
ty -> Builder (UArray ty) (MUArray ty) ty state err ()
builderAppend (Word8# -> Word8
W8# Word8#
x)
    | Bool
otherwise        = forall a e. Exception e => e -> a
throw forall a b. (a -> b) -> a -> b
$ Char -> ISO_8859_1_Invalid
NotISO_8859_1 Char
c
  where
    x :: Word8#
    !x :: Word8#
x = Word# -> Word8#
wordToWord8# (Int# -> Word#
int2Word# (Char# -> Int#
ord# Char#
ch))