{-# Language ForeignFunctionInterface #-}
module EVM.Precompiled (execute) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Foreign.C
import Foreign.Ptr
import Foreign.ForeignPtr
import System.IO.Unsafe
data EthjetContext
foreign import ccall "ethjet_init"
ethjet_init :: IO (Ptr EthjetContext)
foreign import ccall "ðjet_free"
ethjet_free :: FunPtr (Ptr EthjetContext -> IO ())
foreign import ccall "ethjet"
ethjet
:: Ptr EthjetContext
-> CInt
-> Ptr CChar -> CInt
-> Ptr CChar -> CInt
-> IO CInt
globalContext :: ForeignPtr EthjetContext
{-# NOINLINE globalContext #-}
globalContext :: ForeignPtr EthjetContext
globalContext =
IO (ForeignPtr EthjetContext) -> ForeignPtr EthjetContext
forall a. IO a -> a
unsafePerformIO (IO (ForeignPtr EthjetContext) -> ForeignPtr EthjetContext)
-> IO (ForeignPtr EthjetContext) -> ForeignPtr EthjetContext
forall a b. (a -> b) -> a -> b
$
IO (Ptr EthjetContext)
ethjet_init IO (Ptr EthjetContext)
-> (Ptr EthjetContext -> IO (ForeignPtr EthjetContext))
-> IO (ForeignPtr EthjetContext)
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= FinalizerPtr EthjetContext
-> Ptr EthjetContext -> IO (ForeignPtr EthjetContext)
forall a. FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
newForeignPtr FinalizerPtr EthjetContext
ethjet_free
execute
:: Int
-> ByteString
-> Int
-> Maybe ByteString
execute :: Int -> ByteString -> Int -> Maybe ByteString
execute Int
contract ByteString
input Int
outputSize =
IO (Maybe ByteString) -> Maybe ByteString
forall a. IO a -> a
unsafePerformIO (IO (Maybe ByteString) -> Maybe ByteString)
-> ((CStringLen -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (CStringLen -> IO (Maybe ByteString))
-> Maybe ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString
-> (CStringLen -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.useAsCStringLen ByteString
input ((CStringLen -> IO (Maybe ByteString)) -> Maybe ByteString)
-> (CStringLen -> IO (Maybe ByteString)) -> Maybe ByteString
forall a b. (a -> b) -> a -> b
$
\(Ptr CChar
inputPtr, Int
inputSize) -> do
ForeignPtr CChar
outputForeignPtr <- Int -> IO (ForeignPtr CChar)
forall a. Int -> IO (ForeignPtr a)
mallocForeignPtrBytes Int
outputSize
ForeignPtr CChar
-> (Ptr CChar -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr CChar
outputForeignPtr ((Ptr CChar -> IO (Maybe ByteString)) -> IO (Maybe ByteString))
-> (Ptr CChar -> IO (Maybe ByteString)) -> IO (Maybe ByteString)
forall a b. (a -> b) -> a -> b
$ \Ptr CChar
outputPtr -> do
CInt
status <-
ForeignPtr EthjetContext
-> (Ptr EthjetContext -> IO CInt) -> IO CInt
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr EthjetContext
globalContext ((Ptr EthjetContext -> IO CInt) -> IO CInt)
-> (Ptr EthjetContext -> IO CInt) -> IO CInt
forall a b. (a -> b) -> a -> b
$ \Ptr EthjetContext
contextPtr ->
Ptr EthjetContext
-> CInt -> Ptr CChar -> CInt -> Ptr CChar -> CInt -> IO CInt
ethjet Ptr EthjetContext
contextPtr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
contract)
Ptr CChar
inputPtr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
inputSize)
Ptr CChar
outputPtr (Int -> CInt
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
outputSize)
case CInt
status of
CInt
1 -> ByteString -> Maybe ByteString
forall a. a -> Maybe a
Just (ByteString -> Maybe ByteString)
-> IO ByteString -> IO (Maybe ByteString)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> CStringLen -> IO ByteString
BS.packCStringLen (Ptr CChar
outputPtr, Int
outputSize)
CInt
_ -> Maybe ByteString -> IO (Maybe ByteString)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Maybe ByteString
forall a. Maybe a
Nothing