module Hans.Monad (
Hans()
, runHans, runHansOnce
, setEscape, escape, dropPacket
, callCC
, io
, decode, decode'
) where
import Hans.Device.Types (DeviceStats(),updateDropped,statRX)
import qualified Control.Applicative as A
import qualified Data.ByteString as S
import Data.IORef (newIORef,writeIORef,readIORef)
import Data.Serialize.Get (runGet,runGetState,Get)
import MonadLib (BaseM(..))
newtype Hans a = Hans { unHans :: IO () -> (a -> IO ()) -> IO () }
instance Functor Hans where
fmap f m = Hans (\ e k -> unHans m e (k . f))
instance A.Applicative Hans where
pure x = Hans (\ _ k -> k x)
f <*> x = Hans $ \ e k -> unHans f e
$ \ g -> unHans x e
$ \ y -> k (g y)
instance Monad Hans where
return = A.pure
m >>= f = Hans $ \ e k -> unHans m e
$ \ a -> unHans (f a) e k
instance BaseM Hans IO where
inBase = io
runHansOnce :: Hans a -> IO (Maybe a)
runHansOnce (Hans f) =
do res <- newIORef Nothing
f (writeIORef res Nothing) (\x -> writeIORef res (Just x))
readIORef res
runHans :: Hans () -> IO ()
runHans (Hans m) = loop ()
where
loop () = m (loop ()) loop
setEscape :: Hans () -> Hans ()
setEscape m = Hans (\ _ k -> unHans m (k ()) k)
escape :: Hans a
escape = Hans (\ e _ -> e)
callCC :: ((b -> Hans a) -> Hans b) -> Hans b
callCC f = Hans (\e k -> unHans (f (\b -> Hans (\_ _ -> k b))) e k)
dropPacket :: DeviceStats -> Hans a
dropPacket stats =
do io (updateDropped statRX stats)
escape
io :: IO a -> Hans a
io m = Hans (\ _ k -> m >>= k )
decode :: DeviceStats -> Get a -> S.ByteString -> Hans a
decode dev m bytes =
case runGet m bytes of
Right a -> return a
Left _ -> dropPacket dev
decode' :: DeviceStats -> Get a -> S.ByteString -> Hans (a,S.ByteString)
decode' dev m bytes =
case runGetState m bytes 0 of
Right a -> return a
Left _ -> dropPacket dev