Routing ideas

This commit is contained in:
Johan B.W. de Vries 2023-04-10 14:12:50 +02:00
parent 2063a6ea9c
commit 34aaaa4ccb
7 changed files with 148 additions and 5 deletions

View File

@ -0,0 +1,8 @@
class BaseRouter:
def post_message(self, namespace: bytes, topic: bytes, kind: bytes, body: bytes) -> None:
raise NotImplementedError
class StdOutRouter(BaseRouter):
def post_message(self, namespace: bytes, topic: bytes, kind: bytes, body: bytes) -> None:
print(f'{namespace.decode()}: {topic.decode()}: {kind.decode()}: {body.decode()}')

View File

@ -1,8 +1,10 @@
import sys import sys
from phasmplatform.common.config import from_toml from phasmplatform.common.config import from_toml
from phasmplatform.common.router import StdOutRouter
from .runner import run_once from .runners.base import BaseRunner
from .runners.wasmtime import WasmTimeRunner
def main() -> int: def main() -> int:
@ -11,8 +13,19 @@ def main() -> int:
del config del config
stdout_router = StdOutRouter()
foo: BaseRunner
with open('/home/johan/projects/idea/phasm/examples/crc32.wasm', 'rb') as fil: with open('/home/johan/projects/idea/phasm/examples/crc32.wasm', 'rb') as fil:
run_once(fil.read()) foo = WasmTimeRunner(stdout_router, fil.read())
namespace = b'test-namespace'
topic = b'test-topic'
kind = b'test-kind'
body = b'test-body'
foo.handle_message(namespace, topic, kind, body)
return 0 return 0

View File

@ -3,11 +3,22 @@ import wasm3 # type: ignore
from phasmplatform.common.exceptions import PhashPlatformNonIntMainReturnError from phasmplatform.common.exceptions import PhashPlatformNonIntMainReturnError
def run_once(wasm_bin: bytes) -> int: def post_message(namespace: int, topic: int, kind: int, body: int) -> None:
print('namespace', namespace)
print('topic', topic)
print('kind', kind)
print('body', body)
def run_once_wasm3(wasm_bin: bytes) -> int:
env = wasm3.Environment() env = wasm3.Environment()
rtime = env.new_runtime(1024 * 1024) rtime = env.new_runtime(1024 * 1024)
rtime.load(env.parse_module(wasm_bin))
result = rtime.find_function('main')() mod = env.parse_module(wasm_bin)
mod.link_function('imports', 'post_message', post_message)
rtime.load(mod)
result = rtime.find_function('handle_message')()
if result is None: if result is None:
return 0 return 0

View File

View File

@ -0,0 +1,33 @@
from phasmplatform.common.router import BaseRouter
class BaseRunner:
__slots__ = ('router', )
router: BaseRouter
def __init__(self, router: BaseRouter) -> None:
self.router = router
def alloc_bytes(self, data: bytes) -> int:
"""
Calls upon stdlib.types.__alloc_bytes__ to allocate a bytes object
"""
raise NotImplementedError
def read_bytes(self, ptr: int) -> bytes:
"""
Reads a byte object allocated by stdlib.types.__alloc_bytes__
"""
raise NotImplementedError
def handle_message(self, namespace: bytes, topic: bytes, kind: bytes, body: bytes) -> None:
raise NotImplementedError
def post_message(self, namespace_ptr: int, topic_ptr: int, kind_ptr: int, body_ptr: int) -> None:
namespace = self.read_bytes(namespace_ptr)
topic = self.read_bytes(topic_ptr)
kind = self.read_bytes(kind_ptr)
body = self.read_bytes(body_ptr)
self.router.post_message(namespace, topic, kind, body)

View File

@ -0,0 +1,77 @@
import ctypes
import struct
import wasmtime
from phasmplatform.common.router import BaseRouter
from .base import BaseRunner
class WasmTimeRunner(BaseRunner):
__slots__ = ('store', 'module', 'instance', 'exports')
def __init__(self, router: BaseRouter, wasm_bin: bytes) -> None:
super().__init__(router)
self.store = wasmtime.Store()
post_message_bind = wasmtime.Func(self.store, wasmtime.FuncType([
wasmtime.ValType.i32(),
wasmtime.ValType.i32(),
wasmtime.ValType.i32(),
wasmtime.ValType.i32(),
], []), self.post_message)
self.module = wasmtime.Module(self.store.engine, wasm_bin)
self.instance = wasmtime.Instance(self.store, self.module, [
post_message_bind,
])
self.exports = self.instance.exports(self.store)
def alloc_bytes(self, data: bytes) -> int:
alloc_bytes = self.exports['stdlib.types.__alloc_bytes__']
assert isinstance(alloc_bytes, wasmtime.Func)
ptr = alloc_bytes(self.store, len(data))
assert isinstance(ptr, int) # type hint
memory = self.exports['memory']
assert isinstance(memory, wasmtime.Memory) # type hint
data_ptr = memory.data_ptr(self.store)
data_len = memory.data_len(self.store)
idx = ptr + 8 # This is the header from alloc plus the header from __alloc_bytes__
for byt in data:
assert idx < data_len
data_ptr[idx] = ctypes.c_ubyte(byt)
idx += 1
return ptr
def read_bytes(self, ptr: int) -> bytes:
memory = self.exports['memory']
assert isinstance(memory, wasmtime.Memory) # type hint
data_ptr = memory.data_ptr(self.store)
data_len = memory.data_len(self.store)
raw = ctypes.string_at(data_ptr, data_len)
ptr = ptr + 4 # This is the header from alloc
print('raw[ptr:ptr + 4]', raw[ptr:ptr + 4])
length = struct.unpack('<I', raw[ptr:ptr + 4])
print('length', length)
return b'?'
def handle_message(self, namespace: bytes, topic: bytes, kind: bytes, body: bytes) -> None:
namespace_ptr = self.alloc_bytes(namespace)
topic_ptr = self.alloc_bytes(topic)
kind_ptr = self.alloc_bytes(kind)
body_ptr = self.alloc_bytes(body)
handle_message = self.exports['handle_message']
assert isinstance(handle_message, wasmtime.Func)
handle_message(self.store, namespace_ptr, topic_ptr, kind_ptr, body_ptr)

View File

@ -1,3 +1,4 @@
pywasm3==0.5.0 pywasm3==0.5.0
redis==4.5.4 redis==4.5.4
tomli==2.0.1 ; python_version < '3.11' tomli==2.0.1 ; python_version < '3.11'
wasmtime==7.0.0