Skip to content

Commit

Permalink
cleanup: make Codec/Json base classes
Browse files Browse the repository at this point in the history
  • Loading branch information
zshipko committed Sep 20, 2024
1 parent 1c3ee0f commit 282648a
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 21 deletions.
2 changes: 2 additions & 0 deletions bin/src/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ pub struct Options {
#[structopt(parse(from_os_str))]
pub input_py: PathBuf,

// #[structopt(parse(from_os_str))]
// pub other_files: Vec<PathBuf>,
#[structopt(short = "o", parse(from_os_str), default_value = "index.wasm")]
pub output: PathBuf,

Expand Down
4 changes: 2 additions & 2 deletions examples/imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ def reflect(x: str) -> str:
pass

@extism.import_fn("example", "update_dict")
def update_dict(x: dict) -> dict:
def update_dict(x: extism.JsonObject) -> extism.JsonObject:
pass

@extism.plugin_fn
Expand All @@ -22,5 +22,5 @@ def count_vowels():
if ch in ['A', 'a', 'E', 'e', 'I', 'i', 'O', 'o', 'U', 'u']:
total += 1
extism.log(extism.LogLevel.Info, "Hello!")
extism.output_json(update_dict({"count": total}))
extism.output(update_dict({"count": total}))

76 changes: 57 additions & 19 deletions lib/src/prelude.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Union, Optional

import json
from enum import Enum
from abc import ABC, abstractmethod

import extism_ffi as ffi

LogLevel = ffi.LogLevel
Expand All @@ -18,39 +20,37 @@
IMPORT_INDEX = 0


class Codec:
class Codec(ABC):
"""
Codec is used to serialize and deserialize values in Extism memory
"""

def __init__(self, value):
self.value = value

def get(self):
"""Method to get the inner value"""
return self.value

def set(self, x):
"""Method to set in the inner value"""
self.value = x

@abstractmethod
def encode(self) -> bytes:
"""Encode the inner value to bytes"""
raise Exception("encode not implemented")

@staticmethod
@classmethod
@abstractmethod
def decode(s: bytes):
"""Decode a value from bytes"""
raise Exception("encode not implemented")


class Json(Codec):
def encode(self) -> bytes:
return json.dumps(self.value).encode()
v = self
if not isinstance(self, dict) and hasattr(self, "__dict__"):
v = self.__dict__
return json.dumps(v).encode()

@staticmethod
def decode(s: bytes):
return Json(json.loads(s.decode()))
@classmethod
def decode(cls, s: bytes):
return cls(**json.loads(s.decode()))


class JsonObject(Json, dict):
pass


def _store(x) -> int:
Expand Down Expand Up @@ -139,16 +139,54 @@ def inner(*args):
return inner


def input_json():
def input_json(t: Optional[type] = None):
"""Get input as JSON"""
if t is not None:
return json.loads(input_str(), object_hook=lambda x: t(**x))
return json.loads(input_str())


def output_json(x):
"""Set JSON output"""
if hasattr(x, "__dict__"):
x = x.__dict__
output_str(json.dumps(x))


def input(t: type = None):
if t is None:
return None
if t is str:
return input_str()
elif t is bytes:
return input_bytes()
elif issubclass(t, Codec):
return t.decode(input_bytes())
elif t is dict or t is list:
return json.loads(input_str())
elif issubclass(t, Enum):
return t(input_str())
else:
raise Exception(f"Unsupported type for input: {t}")


def output(x=None):
if x is None:
return
if isinstance(x, str):
output_str(x)
elif isinstance(x, bytes):
output_bytes(x)
elif isinstance(x, Codec):
output_bytes(x.encode())
elif isinstance(x, dict) or isinstance(x, list):
output_json(x)
elif isinstance(x, Enum):
output_str(x.value)
else:
raise Exception(f"Unsupported type for output: {type(x)}")


class Var:
@staticmethod
def get_bytes(key: str) -> Optional[bytes]:
Expand Down

0 comments on commit 282648a

Please sign in to comment.