module RustClient ( callRustMessage, callRustSummary, ) where import Control.Exception (bracket) import Foreign.C.String (CString, peekCString, withCString) import Foreign.C.Types (CInt (..)) import Foreign.Marshal.Alloc (alloca) import Foreign.Ptr (Ptr, nullPtr) import Foreign.Storable (peek) import Interop.Shared (Summary, SharedStats, summaryFromSharedStats) foreign import ccall unsafe "rust_compute_stats" rustComputeStats :: CInt -> CInt -> Ptr SharedStats -> IO CInt foreign import ccall unsafe "rust_make_message" rustMakeMessage :: CString -> CInt -> CInt -> IO CString foreign import ccall unsafe "rust_free_string" rustFreeString :: CString -> IO () callRustSummary :: Int -> Int -> IO Summary callRustSummary left right = alloca $ \outStats -> do status <- rustComputeStats (fromIntegral left) (fromIntegral right) outStats if status /= 0 then fail ("rustComputeStats returned status " ++ show status) else summaryFromSharedStats <$> peek outStats callRustMessage :: String -> Int -> Int -> IO String callRustMessage name left right = withCString name $ \namePtr -> do messagePtr <- rustMakeMessage namePtr (fromIntegral left) (fromIntegral right) if messagePtr == nullPtr then fail "rustMakeMessage returned a null pointer" else bracket (pure messagePtr) rustFreeString peekCString