module Graphics.Text.Font.Choose.Internal.FFI where
import Data.MessagePack (MessagePack, pack, unpack)
import Foreign.C.String (CString, withCString)
import Foreign.Ptr (Ptr)
import Foreign.Storable (Storable(..))
import Foreign.Marshal.Alloc (alloca)
import Data.Tuple (swap)
import Graphics.Text.Font.Choose.Result (throwNull)
import Data.Maybe (fromJust)
import Data.ByteString.Unsafe (unsafeUseAsCStringLen, unsafePackMallocCStringLen)
import Data.ByteString.Lazy (toStrict, fromStrict)
import System.IO.Unsafe (unsafePerformIO)
withMessage :: MessagePack a => (CString -> Int -> b) -> a -> b
withMessage inner arg = unsafePerformIO $
unsafeUseAsCStringLen (toStrict $ pack arg) (return . uncurry inner)
fromMessage :: MessagePack a => (Ptr Int -> CString) -> Maybe a
fromMessage inner = unpack $ fromStrict $ unsafePerformIO $ do
unsafePackMallocCStringLen . swap =<< withPtr (throwNull . inner)
fromMessage0 :: MessagePack a => (Ptr Int -> CString) -> a
fromMessage0 = fromJust . fromMessage
withCString' :: (CString -> a) -> String -> a
withCString' inner = unsafePerformIO . flip withCString (return . inner)
-- I don't want to pull in all of inline-c for this util!
withPtr :: (Storable a) => (Ptr a -> IO b) -> IO (a, b)
withPtr f = do
alloca $ \ptr -> do
x <- f ptr
y <- peek ptr
return (y, x)