-- |An applicative interface for working with Storable values. The idea -- is that the underlying pointer is threaded through the computation -- to make reading and writing consecutive values easier. module Ros.Internal.Util.StorableMonad (peek, poke, runStorable, StorableM) where import Control.Monad.State.Strict import Foreign.Ptr import Foreign.Storable hiding (peek, poke) import qualified Foreign.Storable as S -- |A state monad that threads a pointer through a computation. type StorableM a = StateT (Ptr ()) IO a -- |Action that pokes a value into the current pointer location, then -- moves the pointer to just after the poked value. poke :: Storable a => a -> StorableM () poke x = do ptr <- get liftIO $ S.poke (castPtr ptr) x put (plusPtr ptr (sizeOf x)) -- |Action that peeks a value from the current pointer location, then -- moves the pointer to just after the peeked value. peek :: Storable a => StorableM a peek = do ptr <- get x <- liftIO $ S.peek (castPtr ptr) put (plusPtr ptr (sizeOf x)) return x -- |Run a StorableM action with the supplied initial pointer location. runStorable :: StorableM a -> Ptr b -> IO a runStorable s p = evalStateT s (castPtr p)