    -- |
    -- 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.Types.OffsetSize
    import Basement.Numerical.Additive
    import Basement.Monad

    import GHC.Prim
    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 = Int -> Offset Word8
    forall ty. Int -> Offset ty
    Offset 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
    (Int -> ISO_8859_1_Invalid -> ShowS)
    -> (ISO_8859_1_Invalid -> String)
    -> ([ISO_8859_1_Invalid] -> ShowS)
    -> Show ISO_8859_1_Invalid
    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
    (ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool)
    -> (ISO_8859_1_Invalid -> ISO_8859_1_Invalid -> Bool)
    -> Eq ISO_8859_1_Invalid
    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  _ = (Offset Word8 -> Word8)
    -> Offset Word8 -> Either ISO_8859_1_Invalid (Char, Offset Word8)
    (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))
    next
        encodingWrite :: ISO_8859_1
    -> Char
    -> Builder
         (UArray (Unit ISO_8859_1))
         (MUArray (Unit ISO_8859_1))
         (Unit ISO_8859_1)
         st
         err
         ()
    encodingWrite _ = Char
    -> Builder
         (UArray (Unit ISO_8859_1))
         (MUArray (Unit ISO_8859_1))
         (Unit ISO_8859_1)
         st
         err
         ()
    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 getter :: Offset Word8 -> Word8
    getter off :: Offset Word8
    off = (Char, Offset Word8)
    -> Either ISO_8859_1_Invalid (Char, Offset Word8)
    forall a b. b -> Either a b
    Right (Word# -> Char
    toChar Word#
    w, Offset Word8
    off Offset Word8 -> Offset Word8 -> Offset Word8
    forall a. Additive a => a -> a -> a
    + Offset Word8
    aone)
      where
        !(W8# w :: Word#
    w) = Offset Word8 -> Word8
    getter Offset Word8
    off
        toChar :: Word# -> Char
        toChar :: Word# -> Char
    toChar a :: Word#
    a = Char# -> Char
    C# (Int# -> Char#
    chr# (Word# -> Int#
    word2Int# Word#
    a))

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