Skip to content

Commit

Permalink
cleanup: use internal ByteArray pointers to reduce copying (#6)
Browse files Browse the repository at this point in the history
* cleanup: use internal bytestring functions to avoid making copies

* docs: add some comments
  • Loading branch information
zshipko authored Sep 22, 2023
1 parent 9565083 commit 89ef7b7
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 11 deletions.
10 changes: 7 additions & 3 deletions src/Extism.hs
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,15 @@ module Extism (
import Foreign.ForeignPtr
import Foreign.C.String
import Foreign.Ptr
import GHC.Ptr
import Foreign.Marshal.Array
import Foreign.Marshal.Alloc
import Foreign.Storable
import Foreign.StablePtr
import Foreign.Concurrent
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL
import Data.ByteString.Internal (c2w, w2c)
import Data.ByteString.Internal (c2w, w2c, unsafePackLenAddress)
import Data.ByteString.Unsafe (unsafeUseAsCString)
import qualified Text.JSON (encode, decode, toJSObject, showJSON, Result(..))
import qualified Extism.JSON (JSON(..))
Expand Down Expand Up @@ -143,18 +144,20 @@ functionExists (Plugin plugin) name =
b <- withCString name (extism_plugin_function_exists plugin')
if b == 1 then return True else return False)

-- Used to convert a value into linear memory
class ToBytes a where
toBytes :: a -> B.ByteString

-- Used to read a value from linear memory
class FromPointer a where
fromPointer :: CString -> Int -> IO (Result a)

instance ToBytes B.ByteString where
toBytes x = x

instance FromPointer B.ByteString where
fromPointer ptr len = do
x <- B.packCStringLen (castPtr ptr, fromIntegral len)
fromPointer (Ptr ptr) len = do
x <- unsafePackLenAddress (fromIntegral len) ptr
return $ Right x

instance ToBytes [Char] where
Expand All @@ -167,6 +170,7 @@ instance FromPointer [Char] where
Left e -> return $ Left e
Right bs -> return $ Right $ fromByteString bs

-- Wraps a `JSON` value for input/output
newtype JSONValue x = JSONValue x

instance Extism.JSON.JSON a => ToBytes (JSONValue a) where
Expand Down
13 changes: 5 additions & 8 deletions src/Extism/HostFunction.hs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ import Foreign.C.String
import Foreign.StablePtr
import Foreign.Concurrent
import Foreign.Marshal.Array
import qualified Data.ByteString.Internal as BS (c2w)
import GHC.Ptr
import qualified Data.ByteString.Internal as BS (c2w, unsafePackLenAddress)
import Data.IORef

-- | Access the plugin that is currently executing from inside a host function
Expand Down Expand Up @@ -76,19 +77,15 @@ memoryOffset (CurrentPlugin plugin _ _ _) (MemoryHandle offs) = do
-- | Access the data associated with a handle as a 'ByteString'
memoryBytes :: CurrentPlugin -> MemoryHandle -> IO B.ByteString
memoryBytes plugin offs = do
ptr <- memoryOffset plugin offs
Ptr ptr <- memoryOffset plugin offs
len <- memoryLength plugin offs
arr <- peekArray (fromIntegral len) ptr
return $ B.pack arr
BS.unsafePackLenAddress (fromIntegral len) ptr


-- | Access the data associated with a handle as a 'String'
memoryString :: CurrentPlugin -> MemoryHandle -> IO String
memoryString plugin offs = do
ptr <- memoryOffset plugin offs
len <- memoryLength plugin offs
arr <- peekArray (fromIntegral len) ptr
return $ fromByteString $ B.pack arr
fromByteString <$> memoryBytes plugin offs

-- | Access the data associated with a handle and convert it into a Haskell type
memoryGet :: FromPointer a => CurrentPlugin -> MemoryHandle -> IO (Result a)
Expand Down

0 comments on commit 89ef7b7

Please sign in to comment.