{-# LANGUAGE DeriveDataTypeable #-}
{- | This module implements KOI8-R encoding which covers the russian and bulgarian alphabet.
     See <http://en.wikipedia.org/wiki/KOI8-R> for more information.
 -}
module Data.Encoding.KOI8R
	(KOI8R(..)) where

import Control.Throws
import Data.Array.Unboxed
import Data.Char (ord,chr)
import Data.Map hiding (map,(!))
import Data.Word
import Prelude hiding (lookup)
import Data.Typeable

import Data.Encoding.Base
import Data.Encoding.ByteSource
import Data.Encoding.ByteSink
import Data.Encoding.Exception

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

koi8rArr :: UArray Word8 Char
koi8rArr :: UArray Word8 Char
koi8rArr = (Word8, Word8) -> String -> UArray Word8 Char
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
(i, i) -> [e] -> a i e
listArray (Word8
128,Word8
255) String
koi8rList

koi8rMap :: Map Char Word8
koi8rMap :: Map Char Word8
koi8rMap = [(Char, Word8)] -> Map Char Word8
forall k a. Ord k => [(k, a)] -> Map k a
fromList (String -> [Word8] -> [(Char, Word8)]
forall a b. [a] -> [b] -> [(a, b)]
zip String
koi8rList [Word8
128..])

koi8rList :: [Char]
koi8rList :: String
koi8rList =
	[Char
'\x2500',Char
'\x2502',Char
'\x250c',Char
'\x2510',Char
'\x2514',Char
'\x2518',Char
'\x251c',Char
'\x2524'
	,Char
'\x252c',Char
'\x2534',Char
'\x253c',Char
'\x2580',Char
'\x2584',Char
'\x2588',Char
'\x258c',Char
'\x2590'
	,Char
'\x2591',Char
'\x2592',Char
'\x2593',Char
'\x2320',Char
'\x25a0',Char
'\x2219',Char
'\x221a',Char
'\x2248'
	,Char
'\x2264',Char
'\x2265',Char
'\x00a0',Char
'\x2321',Char
'\x00b0',Char
'\x00b2',Char
'\x00b7',Char
'\x00f7'
	,Char
'\x2550',Char
'\x2551',Char
'\x2552',Char
'\x0451',Char
'\x2553',Char
'\x2554',Char
'\x2555',Char
'\x2556'
	,Char
'\x2557',Char
'\x2558',Char
'\x2559',Char
'\x255a',Char
'\x255b',Char
'\x255c',Char
'\x255d',Char
'\x255e'
	,Char
'\x255f',Char
'\x2560',Char
'\x2561',Char
'\x0401',Char
'\x2562',Char
'\x2563',Char
'\x2564',Char
'\x2565'
	,Char
'\x2566',Char
'\x2567',Char
'\x2568',Char
'\x2569',Char
'\x256a',Char
'\x256b',Char
'\x256c',Char
'\x00a9'
	,Char
'\x044e',Char
'\x0430',Char
'\x0431',Char
'\x0446',Char
'\x0434',Char
'\x0435',Char
'\x0444',Char
'\x0433'
	,Char
'\x0445',Char
'\x0438',Char
'\x0439',Char
'\x043a',Char
'\x043b',Char
'\x043c',Char
'\x043d',Char
'\x043e'
	,Char
'\x043f',Char
'\x044f',Char
'\x0440',Char
'\x0441',Char
'\x0442',Char
'\x0443',Char
'\x0436',Char
'\x0432'
	,Char
'\x044c',Char
'\x044b',Char
'\x0437',Char
'\x0448',Char
'\x044d',Char
'\x0449',Char
'\x0447',Char
'\x044a'
	,Char
'\x042e',Char
'\x0410',Char
'\x0411',Char
'\x0426',Char
'\x0414',Char
'\x0415',Char
'\x0424',Char
'\x0413'
	,Char
'\x0425',Char
'\x0418',Char
'\x0419',Char
'\x041a',Char
'\x041b',Char
'\x041c',Char
'\x041d',Char
'\x041e'
	,Char
'\x041f',Char
'\x042f',Char
'\x0420',Char
'\x0421',Char
'\x0422',Char
'\x0423',Char
'\x0416',Char
'\x0412'
	,Char
'\x042c',Char
'\x042b',Char
'\x0417',Char
'\x0428',Char
'\x042d',Char
'\x0429',Char
'\x0427',Char
'\x042a'
	]

instance Encoding KOI8R where
    decodeChar :: KOI8R -> m Char
decodeChar KOI8R
_ = do
      Word8
w <- m Word8
forall (m :: * -> *). ByteSource m => m Word8
fetchWord8
      if Word8
w Word8 -> Word8 -> Bool
forall a. Ord a => a -> a -> Bool
< Word8
128
        then Char -> m Char
forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> m Char) -> Char -> m Char
forall a b. (a -> b) -> a -> b
$ Int -> Char
chr (Int -> Char) -> Int -> Char
forall a b. (a -> b) -> a -> b
$ Word8 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word8
w
        else Char -> m Char
forall (m :: * -> *) a. Monad m => a -> m a
return (Char -> m Char) -> Char -> m Char
forall a b. (a -> b) -> a -> b
$ UArray Word8 Char
koi8rArrUArray Word8 Char -> Word8 -> Char
forall (a :: * -> * -> *) e i.
(IArray a e, Ix i) =>
a i e -> i -> e
!Word8
w
    encodeChar :: KOI8R -> Char -> m ()
encodeChar KOI8R
_ Char
ch
	| Char
ch Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
< Char
'\128' = Word8 -> m ()
forall (m :: * -> *). ByteSink m => Word8 -> m ()
pushWord8 (Word8 -> m ()) -> Word8 -> m ()
forall a b. (a -> b) -> a -> b
$ Int -> Word8
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Word8) -> Int -> Word8
forall a b. (a -> b) -> a -> b
$ Char -> Int
ord Char
ch
	| Bool
otherwise   = case Char -> Map Char Word8 -> Maybe Word8
forall k a. Ord k => k -> Map k a -> Maybe a
lookup Char
ch Map Char Word8
koi8rMap of
		Just Word8
w -> Word8 -> m ()
forall (m :: * -> *). ByteSink m => Word8 -> m ()
pushWord8 Word8
w
		Maybe Word8
Nothing -> EncodingException -> m ()
forall e (m :: * -> *) a. Throws e m => e -> m a
throwException (Char -> EncodingException
HasNoRepresentation Char
ch)
    encodeable :: KOI8R -> Char -> Bool
encodeable KOI8R
_ Char
c = Char -> Map Char Word8 -> Bool
forall k a. Ord k => k -> Map k a -> Bool
member Char
c Map Char Word8
koi8rMap