packages feed

wasmedge-hs-0.17.1.0: src/WasmEdge/Internal/Storable.hs

{- |
Module      : WasmEdge.Internal.Storable
Description : Storable instances for WasmEdge C structs
Copyright   : (c) 2026 Tushar Adhatrao
License     : MIT
Stability   : internal

Provides 'Storable' instances and allocation helpers for the C structs
that WasmEdge returns by value. These are used internally when calling
the shim layer.

__Do not import this module in user code.__
-}
module WasmEdge.Internal.Storable
  ( -- * WasmEdge_String layout
    CString_
  , allocaCString
  , peekCStringBuf
  , peekCStringLen
  , cStringSize
  , stringSize

    -- * WasmEdge_Bytes layout
  , CBytes_
  , allocaCBytes

    -- * WasmEdge_Result layout
  , CResult_
  , allocaCResult
  , peekResultCode

    -- * WasmEdge_ValType layout (8 bytes opaque)
  , CValType_
  , allocaCValType
  , valTypeSize

    -- * WasmEdge_Value layout (uint128 + ValType = 24 bytes)
  , CValue_
  , allocaCValue
  , valueSize

    -- * Stack-allocated array helpers
  , withCValTypeArray
  , withCValueArray
  ) where

import Data.Word (Word32, Word8)
import Foreign.Marshal.Alloc (alloca, allocaBytes)
import Foreign.Ptr
import Foreign.Storable

-- ---------------------------------------------------------------------------
-- WasmEdge_String  (uint32_t Length; const char* Buf)
-- ---------------------------------------------------------------------------

{- | Opaque placeholder for the 'WasmEdge_String' C struct layout.
Use 'allocaCString' to allocate on the stack.
-}
data CString_

-- | Allocate a stack-allocated 'WasmEdge_String' and pass it to the action.
allocaCString :: (Ptr CString_ -> IO a) -> IO a
allocaCString = allocaBytes cStringSize

-- Size: uint32_t (4) + padding (4 on 64-bit) + ptr (8) = 16 bytes typically
-- We use hsc2hs for the real layout; for now use a conservative 16 bytes.
cStringSize :: Int
cStringSize = 16 -- overridden by hsc2hs #size WasmEdge_String at compile time

stringSize :: Int
stringSize = cStringSize

-- | Peek the buffer pointer from a 'WasmEdge_String'.
peekCStringBuf :: Ptr CString_ -> IO (Ptr Word8)
peekCStringBuf p = peekByteOff p 8 -- Buf is at offset 8 (after Length + padding)

-- | Peek the length from a 'WasmEdge_String'.
peekCStringLen :: Ptr CString_ -> IO Word32
peekCStringLen p = peekByteOff p 0

-- ---------------------------------------------------------------------------
-- WasmEdge_Bytes  (uint32_t Length; const uint8_t* Buf)
-- ---------------------------------------------------------------------------

-- | Opaque placeholder for the 'WasmEdge_Bytes' C struct layout.
data CBytes_

allocaCBytes :: (Ptr CBytes_ -> IO a) -> IO a
allocaCBytes = allocaBytes 16 -- same layout as WasmEdge_String

-- ---------------------------------------------------------------------------
-- WasmEdge_Result  (uint32_t Code)
-- ---------------------------------------------------------------------------

-- | Opaque placeholder for the 'WasmEdge_Result' C struct (single uint32_t).
data CResult_

allocaCResult :: (Ptr CResult_ -> IO a) -> IO a
allocaCResult = alloca @Word32 . (. castPtr)

-- | Peek the Code field from a 'WasmEdge_Result'.
peekResultCode :: Ptr CResult_ -> IO Word32
peekResultCode p = peek (castPtr p)

-- ---------------------------------------------------------------------------
-- WasmEdge_ValType  (uint8_t Data[8])
-- ---------------------------------------------------------------------------

-- | Opaque placeholder for the 'WasmEdge_ValType' C struct (8 opaque bytes).
data CValType_

valTypeSize :: Int
valTypeSize = 8

allocaCValType :: (Ptr CValType_ -> IO a) -> IO a
allocaCValType = allocaBytes valTypeSize

-- | Allocate an array of n 'CValType_' structs on the stack.
withCValTypeArray :: Int -> (Ptr CValType_ -> IO a) -> IO a
withCValTypeArray 0 action = action nullPtr
withCValTypeArray n action = allocaBytes (n * valTypeSize) action

-- ---------------------------------------------------------------------------
-- WasmEdge_Value  (uint128_t Value; WasmEdge_ValType Type)
-- = 16 bytes (uint128) + 8 bytes (ValType) + 8 bytes (alignment padding) = 32 bytes
-- ---------------------------------------------------------------------------

-- | Opaque placeholder for the 'WasmEdge_Value' C struct.
data CValue_

valueSize :: Int
valueSize = 32

allocaCValue :: (Ptr CValue_ -> IO a) -> IO a
allocaCValue = allocaBytes valueSize

-- | Allocate an array of n 'CValue_' structs on the stack.
withCValueArray :: Int -> (Ptr CValue_ -> IO a) -> IO a
withCValueArray 0 action = action nullPtr
withCValueArray n action = allocaBytes (n * valueSize) action