54 lines
1.4 KiB
Haskell
54 lines
1.4 KiB
Haskell
![]() |
-- | Marshall from a Rust-side allocated buffer
|
||
|
--
|
||
|
-- Intended for unqualified import.
|
||
|
module Foreign.Rust.Marshall.External (
|
||
|
fromExternalBorsh
|
||
|
) where
|
||
|
|
||
|
import Codec.Borsh
|
||
|
import Control.Exception
|
||
|
import Data.Typeable
|
||
|
import Data.Word
|
||
|
import Foreign.C
|
||
|
import Foreign.Concurrent
|
||
|
import Foreign.Ptr
|
||
|
|
||
|
import qualified Data.ByteString.Internal as Strict
|
||
|
|
||
|
import Foreign.Rust.Marshall.Util
|
||
|
|
||
|
data External
|
||
|
|
||
|
foreign import ccall "haskell_ffi_external_ptr"
|
||
|
externalPtr
|
||
|
:: Ptr External -> Ptr Word8
|
||
|
|
||
|
foreign import ccall "haskell_ffi_external_len"
|
||
|
externalLen
|
||
|
:: Ptr External -> CSize
|
||
|
|
||
|
foreign import ccall "haskell_ffi_external_free"
|
||
|
externalFree
|
||
|
:: Ptr External -> IO ()
|
||
|
|
||
|
-- | Internal auxiliary: cast pointer
|
||
|
--
|
||
|
-- For ease of integration with c2hs, 'fromExternalBorsh' takes a @Ptr ()@ as
|
||
|
-- input instead of the more accurate @Ptr External@.
|
||
|
castToExternal :: Ptr () -> Ptr External
|
||
|
castToExternal = castPtr
|
||
|
|
||
|
-- | Output marshaller for values stored in Rust-allocated buffer
|
||
|
--
|
||
|
-- Should be used together with the Rust function @marshall_to_haskell_external@
|
||
|
-- (from @haskell-ffi@).
|
||
|
fromExternalBorsh :: (FromBorsh a, Typeable a) => Ptr () -> IO a
|
||
|
fromExternalBorsh (castToExternal -> ptr) = do
|
||
|
len <- evaluate $ fromIntegral $ externalLen ptr
|
||
|
fptr <- newForeignPtr (externalPtr ptr) (externalFree ptr)
|
||
|
|
||
|
let bs :: Strict.ByteString
|
||
|
bs = Strict.PS fptr 0 len
|
||
|
|
||
|
return $ deserialiseStrictOrPanic bs
|