{-# LANGUAGE CPP #-}
module Lua.Userdata
( hslua_fromuserdata
, hslua_newhsuserdata
, hslua_newudmetatable
, hslua_putuserdata
) where
import Foreign.C (CInt (CInt), CString)
import Lua.Auxiliary (luaL_testudata)
import Lua.Primary (lua_newuserdata)
import Lua.Types
( LuaBool (..)
, StackIndex (..)
, State (..)
)
import Foreign.Ptr (castPtr, nullPtr)
import Foreign.StablePtr (newStablePtr, deRefStablePtr, freeStablePtr)
import Foreign.Storable (peek, poke, sizeOf)
#ifdef ALLOW_UNSAFE_GC
#define SAFTY unsafe
#else
#define SAFTY safe
#endif
foreign import ccall SAFTY "hsludata.h hslua_newudmetatable"
hslua_newudmetatable :: State
-> CString
-> IO LuaBool
hslua_newhsuserdata :: State -> a -> IO ()
hslua_newhsuserdata :: State -> a -> IO ()
hslua_newhsuserdata State
l a
x = do
StablePtr a
xPtr <- a -> IO (StablePtr a)
forall a. a -> IO (StablePtr a)
newStablePtr a
x
Ptr ()
udPtr <- State -> CSize -> IO (Ptr ())
lua_newuserdata State
l (Int -> CSize
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> CSize) -> Int -> CSize
forall a b. (a -> b) -> a -> b
$ StablePtr a -> Int
forall a. Storable a => a -> Int
sizeOf StablePtr a
xPtr)
Ptr (StablePtr a) -> StablePtr a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr () -> Ptr (StablePtr a)
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
udPtr) StablePtr a
xPtr
{-# INLINABLE hslua_newhsuserdata #-}
hslua_fromuserdata :: State
-> StackIndex
-> CString
-> IO (Maybe a)
hslua_fromuserdata :: State -> StackIndex -> CString -> IO (Maybe a)
hslua_fromuserdata State
l StackIndex
idx CString
name = do
Ptr ()
udPtr <- State -> StackIndex -> CString -> IO (Ptr ())
luaL_testudata State
l StackIndex
idx CString
name
if Ptr ()
udPtr Ptr () -> Ptr () -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr ()
forall a. Ptr a
nullPtr
then Maybe a -> IO (Maybe a)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe a
forall a. Maybe a
Nothing
else a -> Maybe a
forall a. a -> Maybe a
Just (a -> Maybe a) -> IO a -> IO (Maybe a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Ptr (StablePtr a) -> IO (StablePtr a)
forall a. Storable a => Ptr a -> IO a
peek (Ptr () -> Ptr (StablePtr a)
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
udPtr) IO (StablePtr a) -> (StablePtr a -> IO a) -> IO a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= StablePtr a -> IO a
forall a. StablePtr a -> IO a
deRefStablePtr)
{-# INLINABLE hslua_fromuserdata #-}
hslua_putuserdata :: State
-> StackIndex
-> CString
-> a
-> IO Bool
hslua_putuserdata :: State -> StackIndex -> CString -> a -> IO Bool
hslua_putuserdata State
l StackIndex
idx CString
name a
x = do
StablePtr a
xPtr <- a -> IO (StablePtr a)
forall a. a -> IO (StablePtr a)
newStablePtr a
x
Ptr ()
udPtr <- State -> StackIndex -> CString -> IO (Ptr ())
luaL_testudata State
l StackIndex
idx CString
name
if Ptr ()
udPtr Ptr () -> Ptr () -> Bool
forall a. Eq a => a -> a -> Bool
== Ptr ()
forall a. Ptr a
nullPtr
then Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
else do
Ptr (StablePtr Any) -> IO (StablePtr Any)
forall a. Storable a => Ptr a -> IO a
peek (Ptr () -> Ptr (StablePtr Any)
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
udPtr) IO (StablePtr Any) -> (StablePtr Any -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= StablePtr Any -> IO ()
forall a. StablePtr a -> IO ()
freeStablePtr
Ptr (StablePtr a) -> StablePtr a -> IO ()
forall a. Storable a => Ptr a -> a -> IO ()
poke (Ptr () -> Ptr (StablePtr a)
forall a b. Ptr a -> Ptr b
castPtr Ptr ()
udPtr) StablePtr a
xPtr
Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
True
{-# INLINABLE hslua_putuserdata #-}