{-# LANGUAGE Trustworthy #-}

module Data.Columbia.Integral where

import Data.Generics.SYB.WithClass.Basics
import Data.Bits
import Data.Word
import Control.Monad
import Control.Monad.Reader
import Control.Monad.Trans
import Data.Columbia.SeekableStream
import Data.Columbia.SeekableWriter

{-readIntegral :: (Monad m, Integral i) => ReaderT(SeekableStream m Word8) m i
readIntegral = liftM fromIntegral consumeIntegralToken

writeIntegral :: (Monad m, Integral i) => i -> ReaderT(SeekableWriter m Word8) m ()
writeIntegral = putIntegralToken.fromIntegral-}

readIntegral :: (Monad m, Bits i, Integral i) => ReaderT(SeekableStream m Word8) m i
readIntegral = liftM4(\x1 x2 x3 x4 -> shiftL(fromIntegral x1) 24 .|.
	shiftL(fromIntegral x2) 16 .|.
	shiftL(fromIntegral x3) 8 .|.
	fromIntegral x4)
	consumeToken
	consumeToken
	consumeToken
	consumeToken

writeIntegral :: (Monad m, Bits i, Integral i) => i -> ReaderT(SeekableWriter m Word8) m ()
writeIntegral x = do
	putToken$!fromIntegral$shiftR x 24
	putToken$!fromIntegral$shiftR x 16
	putToken$!fromIntegral$shiftR x 8
	putToken$!fromIntegral x

readIntegral16 :: (Monad m, Bits i, Integral i) => ReaderT(SeekableStream m Word8) m i
readIntegral16 = liftM2(\x1 x2 -> shiftL(fromIntegral x1) 8 .|.
	fromIntegral x2)
	consumeToken
	consumeToken

writeIntegral16 :: (Monad m, Bits i, Integral i) => i -> ReaderT(SeekableWriter m Word8) m ()
writeIntegral16 x = do
	putToken$!fromIntegral$shiftR x 8
	putToken$!fromIntegral x

seekByPointer :: (Monad m) => ReaderT(SeekableStream m Word8) m ()
seekByPointer = do
	n <- readIntegral
	seek n