lean-0.0.0.1: Lean/IO/Util.hs
{-# LANGUAGE TypeFamilies #-}
module Lean.IO.Util where
import Control.Applicative
import Control.Exception.Base
import Control.Monad
import Data.Text (Text)
import qualified Data.Text.Foreign as Text
import Foreign
import Foreign.C.Types
import Foreign.ForeignPtr.Unsafe
import System.IO.Unsafe
import Lean.Wrapper
unwrap' :: Wrapper a -> Ptr a
unwrap' = unsafeForeignPtrToPtr . unwrap
class Storable (Raw a) => FromRaw a where
type Raw a
fromRaw :: Raw a -> IO a
instance Drop a => FromRaw (Wrapper a) where
type Raw (Wrapper a) = Ptr a
fromRaw = wrap
instance FromRaw Bool where
type Raw Bool = CInt
fromRaw = pure . (/= 0)
instance FromRaw Word where
type Raw Word = CUInt
fromRaw = pure . fromIntegral
instance FromRaw Int where
type Raw Int = CInt
fromRaw = pure . fromIntegral
instance FromRaw Text where
type Raw Text = Ptr CChar
fromRaw = getCompose $ Compose (liftA2 (=<<) Text.fromPtr (fmap fromIntegral . cNulArrayLen) . castPtr) <* Compose dropString
foreign import ccall unsafe "lean_string_del" dropString :: Ptr CChar -> IO ()
liftLean0 :: (FromRaw z, Drop ex, Exception (Wrapper ex)) => (Ptr (Raw z) -> Ptr (Ptr ex) -> IO CInt) -> IO z
liftLean0 f = alloca $ \ p -> alloca $ \ q ->
f p q >>= \ case 0 -> peek q >>= wrap >>= throw; _ -> peek p >>= fromRaw
liftLean1 :: (FromRaw z, Drop ex, Exception (Wrapper ex)) => (Ptr a -> Ptr (Raw z) -> Ptr (Ptr ex) -> IO CInt) -> Wrapper a -> IO z
liftLean1 f a = liftLean0 $ f (unwrap' a)
liftLean2 :: (FromRaw z, Drop ex, Exception (Wrapper ex)) => (Ptr a -> Ptr b -> Ptr (Raw z) -> Ptr (Ptr ex) -> IO CInt) -> Wrapper a -> Wrapper b -> IO z
liftLean2 f a b = liftLean0 $ f (unwrap' a) (unwrap' b)
liftLean3 :: (FromRaw z, Drop ex, Exception (Wrapper ex)) => (Ptr a -> Ptr b -> Ptr c -> Ptr (Raw z) -> Ptr (Ptr ex) -> IO CInt) -> Wrapper a -> Wrapper b -> Wrapper c -> IO z
liftLean3 f a b c = liftLean0 $ f (unwrap' a) (unwrap' b) (unwrap' c)
checked :: (Ptr s -> Bool) -> (Wrapper s -> IO z) -> Wrapper s -> Maybe z
checked pred f s = unsafePerformIO . sequenceA $ f s <$ guard (pred (unwrap' s))
cNulArrayLen :: _ => Ptr a -> IO Word
cNulArrayLen = go 0 where
go n ptr = peek ptr >>= \ case
0 -> pure n
_ -> go (n+1) $ plusPtr ptr 1