Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Improve usability of manifest types #124

Merged
merged 9 commits into from Dec 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 6 additions & 6 deletions extism.go
Expand Up @@ -53,19 +53,19 @@ type WasmFile struct {
}

type WasmUrl struct {
Url string `json:"url"`
Hash string `json:"hash,omitempty"`
Header map[string]string `json:"header,omitempty"`
Name string `json:"name,omitempty"`
Method string `json:"method,omitempty"`
Url string `json:"url"`
Hash string `json:"hash,omitempty"`
Headers map[string]string `json:"headers,omitempty"`
Name string `json:"name,omitempty"`
Method string `json:"method,omitempty"`
}

type Wasm interface{}

type Manifest struct {
Wasm []Wasm `json:"wasm"`
Memory struct {
Max uint32 `json:"max,omitempty"`
MaxPages uint32 `json:"max_pages,omitempty"`
} `json:"memory,omitempty"`
Config map[string]string `json:"config,omitempty"`
AllowedHosts []string `json:"allowed_hosts,omitempty"`
Expand Down
8 changes: 4 additions & 4 deletions haskell/manifest/Extism/Manifest.hs
Expand Up @@ -43,14 +43,14 @@ instance JSONValue Memory where
data HTTPRequest = HTTPRequest
{
url :: String
, header :: Maybe [(String, String)]
, headers :: Maybe [(String, String)]
, method :: Maybe String
}

requestObj (HTTPRequest url header method) =
requestObj (HTTPRequest url headers method) =
[
"url" .= url ,
"header" .= header,
"headers" .= headers,
"method" .= method
]

Expand Down Expand Up @@ -118,7 +118,7 @@ wasmFile path =

wasmURL :: String -> String -> Wasm
wasmURL method url =
let r = HTTPRequest { url = url, header = Nothing, method = Just method } in
let r = HTTPRequest { url = url, headers = Nothing, method = Just method } in
URL WasmURL { req = r, urlName = Nothing, urlHash = Nothing }

wasmCode :: B.ByteString -> Wasm
Expand Down
14 changes: 7 additions & 7 deletions manifest/schema.json
Expand Up @@ -22,27 +22,27 @@
},
"memory": {
"default": {
"max": null
"max_pages": null
},
"allOf": [
{
"$ref": "#/definitions/ManifestMemory"
"$ref": "#/definitions/MemoryOptions"
}
]
},
"wasm": {
"default": [],
"type": "array",
"items": {
"$ref": "#/definitions/ManifestWasm"
"$ref": "#/definitions/Wasm"
}
}
},
"definitions": {
"ManifestMemory": {
"MemoryOptions": {
"type": "object",
"properties": {
"max": {
"max_pages": {
"type": [
"integer",
"null"
Expand All @@ -52,7 +52,7 @@
}
}
},
"ManifestWasm": {
"Wasm": {
"anyOf": [
{
"type": "object",
Expand Down Expand Up @@ -113,7 +113,7 @@
"null"
]
},
"header": {
"headers": {
"default": {},
"type": "object",
"additionalProperties": {
Expand Down
120 changes: 106 additions & 14 deletions manifest/src/lib.rs
@@ -1,25 +1,30 @@
use std::collections::BTreeMap;

#[deprecated]
pub type ManifestMemory = MemoryOptions;

#[derive(Default, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct ManifestMemory {
pub max: Option<u32>,
pub struct MemoryOptions {
#[serde(alias = "max")]
pub max_pages: Option<u32>,
}

#[derive(serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct HttpRequest {
pub url: String,
#[serde(default)]
pub header: std::collections::BTreeMap<String, String>,
#[serde(alias = "header")]
pub headers: std::collections::BTreeMap<String, String>,
pub method: Option<String>,
}

impl HttpRequest {
pub fn new(url: impl Into<String>) -> HttpRequest {
HttpRequest {
url: url.into(),
header: Default::default(),
headers: Default::default(),
method: None,
}
}
Expand All @@ -30,35 +35,112 @@ impl HttpRequest {
}

pub fn with_header(mut self, key: impl Into<String>, value: impl Into<String>) -> HttpRequest {
self.header.insert(key.into(), value.into());
self.headers.insert(key.into(), value.into());
self
}
}

#[derive(Default, serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct WasmMetadata {
pub name: Option<String>,
pub hash: Option<String>,
}

impl From<HttpRequest> for Wasm {
fn from(req: HttpRequest) -> Self {
Wasm::Url {
req,
meta: WasmMetadata::default(),
}
}
}

impl From<std::path::PathBuf> for Wasm {
fn from(path: std::path::PathBuf) -> Self {
Wasm::File {
path,
meta: WasmMetadata::default(),
}
}
}

impl From<Vec<u8>> for Wasm {
fn from(data: Vec<u8>) -> Self {
Wasm::Data {
data,
meta: WasmMetadata::default(),
}
}
}

#[deprecated]
pub type ManifestWasm = Wasm;

#[derive(serde::Serialize, serde::Deserialize)]
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
#[serde(untagged)]
pub enum ManifestWasm {
pub enum Wasm {
File {
path: std::path::PathBuf,
name: Option<String>,
hash: Option<String>,

#[serde(flatten)]
meta: WasmMetadata,
},
Data {
#[serde(with = "base64")]
#[cfg_attr(feature = "json_schema", schemars(schema_with = "base64_schema"))]
data: Vec<u8>,
name: Option<String>,
hash: Option<String>,
#[serde(flatten)]
meta: WasmMetadata,
},
Url {
#[serde(flatten)]
req: HttpRequest,
name: Option<String>,
hash: Option<String>,
#[serde(flatten)]
meta: WasmMetadata,
},
}

impl Wasm {
pub fn file(path: impl AsRef<std::path::Path>) -> Self {
Wasm::File {
path: path.as_ref().to_path_buf(),
meta: Default::default(),
}
}

pub fn data(data: impl Into<Vec<u8>>) -> Self {
Wasm::Data {
data: data.into(),
meta: Default::default(),
}
}

pub fn url(req: HttpRequest) -> Self {
Wasm::Url {
req,
meta: Default::default(),
}
}

pub fn meta(&self) -> &WasmMetadata {
match self {
Wasm::File { path: _, meta } => &meta,
Wasm::Data { data: _, meta } => &meta,
Wasm::Url { req: _, meta } => &meta,
}
}

pub fn meta_mut(&mut self) -> &mut WasmMetadata {
match self {
Wasm::File { path: _, meta } => meta,
Wasm::Data { data: _, meta } => meta,
Wasm::Url { req: _, meta } => meta,
}
}
}

#[cfg(feature = "json_schema")]
fn base64_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
use schemars::{schema::SchemaObject, JsonSchema};
Expand All @@ -71,15 +153,25 @@ fn base64_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::
#[cfg_attr(feature = "json_schema", derive(schemars::JsonSchema))]
pub struct Manifest {
#[serde(default)]
pub wasm: Vec<ManifestWasm>,
pub wasm: Vec<Wasm>,
#[serde(default)]
pub memory: ManifestMemory,
pub memory: MemoryOptions,
#[serde(default)]
pub config: BTreeMap<String, String>,
#[serde(default)]
pub allowed_hosts: Option<Vec<String>>,
}

impl Manifest {
/// Create a new manifest
pub fn new(wasm: impl Into<Vec<Wasm>>) -> Manifest {
Manifest {
wasm: wasm.into(),
..Default::default()
}
}
}

mod base64 {
use serde::{Deserialize, Serialize};
use serde::{Deserializer, Serializer};
Expand Down
2 changes: 1 addition & 1 deletion node/src/index.ts
Expand Up @@ -145,7 +145,7 @@ export type ManifestWasmData = {
* Memory options for the {@link Plugin}
*/
export type ManifestMemory = {
max?: number;
max_pages?: number;
};

/**
Expand Down
6 changes: 3 additions & 3 deletions ocaml/lib/extism.ml
Expand Up @@ -93,7 +93,7 @@ end
type error = [ `Msg of string ]

module Manifest = struct
type memory = { max : int option [@yojson.option] } [@@deriving yojson]
type memory = { max_pages : int option [@yojson.option] } [@@deriving yojson]

type wasm_file = {
path : string;
Expand All @@ -116,7 +116,7 @@ module Manifest = struct

type wasm_url = {
url : string;
header : (string * string) list option; [@yojson.option]
headers : (string * string) list option; [@yojson.option]
name : string option; [@yojson.option]
meth : string option; [@yojson.option] [@key "method"]
hash : string option; [@yojson.option]
Expand Down Expand Up @@ -161,7 +161,7 @@ module Manifest = struct

let file ?name ?hash path = File { path; name; hash }
let data ?name ?hash data = Data { data; name; hash }
let url ?header ?name ?meth ?hash url = Url { header; name; meth; hash; url }
let url ?headers ?name ?meth ?hash url = Url { headers; name; meth; hash; url }

let v ?config ?memory ?allowed_hosts wasm =
{ config; wasm; memory; allowed_hosts }
Expand Down
6 changes: 3 additions & 3 deletions ocaml/lib/extism.mli
Expand Up @@ -4,7 +4,7 @@ type error = [ `Msg of string ]
val extism_version : unit -> string

module Manifest : sig
type memory = { max : int option } [@@deriving yojson]
type memory = { max_pages : int option } [@@deriving yojson]

type wasm_file = {
path : string;
Expand All @@ -20,7 +20,7 @@ module Manifest : sig

type wasm_url = {
url : string;
header : (string * string) list option; [@yojson.option]
headers : (string * string) list option; [@yojson.option]
name : string option; [@yojson.option]
meth : string option; [@yojson.option] [@key "method"]
hash : string option; [@yojson.option]
Expand All @@ -40,7 +40,7 @@ module Manifest : sig
val data : ?name:string -> ?hash:string -> string -> wasm

val url :
?header:(string * string) list ->
?headers:(string * string) list ->
?name:string ->
?meth:string ->
?hash:string ->
Expand Down
2 changes: 1 addition & 1 deletion python/tests/test_extism.py
Expand Up @@ -66,7 +66,7 @@ def test_extism_version(self):
def _manifest(self):
wasm = self._count_vowels_wasm()
hash = hashlib.sha256(wasm).hexdigest()
return {"wasm": [{"data": wasm, "hash": hash}], "memory": {"max": 5}}
return {"wasm": [{"data": wasm, "hash": hash}], "memory": {"max_pages": 5}}

def _count_vowels_wasm(self):
path = join(dirname(__file__), "code.wasm")
Expand Down