module Data.Repa.Convert.Internal.Unpacker
( Unpacker (..)
, unsafeRunUnpacker)
where
import Data.IORef
import Data.Word
import GHC.Exts
import Prelude hiding (fail)
import qualified Foreign.Ptr as F
data Unpacker a
= Unpacker
{
fromUnpacker
:: Addr#
-> Addr#
-> (Word8 -> Bool)
-> IO ()
-> (Addr# -> a -> IO ())
-> IO ()
}
instance Functor Unpacker where
fmap f (Unpacker fx)
= Unpacker $ \start end stop fail eat
-> fx start end stop fail $ \start_x x
-> eat start_x (f x)
{-# INLINE fmap #-}
instance Applicative Unpacker where
pure x
= Unpacker $ \start _end _fail _stop eat
-> eat start x
{-# INLINE pure #-}
(<*>) (Unpacker ff) (Unpacker fx)
= Unpacker $ \start end stop fail eat
-> ff start end stop fail $ \start_f f
-> fx start_f end stop fail $ \start_x x
-> eat start_x (f x)
{-# INLINE (<*>) #-}
instance Monad Unpacker where
return = pure
{-# INLINE return #-}
(>>=) (Unpacker fa) mkfb
= Unpacker $ \start end stop fail eat
-> fa start end stop fail $ \start_x x
-> case mkfb x of
Unpacker fb
-> fb start_x end stop fail eat
{-# INLINE (>>=) #-}
unsafeRunUnpacker
:: Unpacker a
-> F.Ptr Word8
-> Int
-> (Word8 -> Bool)
-> IO (Maybe (a, F.Ptr Word8))
unsafeRunUnpacker (Unpacker f) (Ptr start) (I# len) stop
= do ref <- newIORef Nothing
f start
(plusAddr# start len)
stop
(return ())
(\addr' x -> writeIORef ref (Just (x, (Ptr addr'))))
readIORef ref
{-# INLINE unsafeRunUnpacker #-}