Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/cli/src/lib/project/manifests/plugin/languages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { BindLanguage } from "@polywrap/schema-bind";

export const pluginManifestLanguages = {
"plugin/typescript": "plugin/typescript",
"plugin/rust": "plugin/rust",
};

export type PluginManifestLanguages = typeof pluginManifestLanguages;
Expand All @@ -22,6 +23,8 @@ export function pluginManifestLanguageToBindLanguage(
switch (manifestLanguage) {
case "plugin/typescript":
return "plugin-ts";
case "plugin/rust":
return "plugin-rs";
default:
throw Error(
intlMsg.lib_language_unsupportedManifestLanguage({
Expand Down
2 changes: 2 additions & 0 deletions packages/schema/bind/src/bindings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ export function getGenerateBindingFn(
return Rust.Wasm.generateBinding;
case "plugin-ts":
return TypeScript.Plugin.generateBinding;
case "plugin-rs":
return Rust.Plugin.generateBinding;
case "app-ts":
return TypeScript.App.generateBinding;
default:
Expand Down
1 change: 1 addition & 0 deletions packages/schema/bind/src/bindings/rust/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * as Wasm from "./wasm";
export * as Plugin from "./plugin";
export * as Functions from "./functions";
export * as Types from "./types";
80 changes: 80 additions & 0 deletions packages/schema/bind/src/bindings/rust/plugin/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import * as Transforms from "./transforms";
import { Functions } from "../";
import { GenerateBindingFn, renderTemplates } from "../..";
import { BindOptions, BindOutput } from "../../..";

import {
transformAbi,
extendType,
addFirstLast,
toPrefixedGraphQLType,
hasImports,
methodParentPointers,
latestWrapManifestVersion,
} from "@polywrap/schema-parse";
import path from "path";
import { WrapAbi } from "@polywrap/wrap-manifest-types-js/src";

const templatePath = (subpath: string) =>
path.join(__dirname, "./templates", subpath);

const sort = (obj: Record<string, unknown>) =>
Object.keys(obj)
.sort()
.reduce((map: Record<string, unknown>, key: string) => {
if (typeof obj[key] === "object") {
map[key] = sort(obj[key] as Record<string, unknown>);

if (Array.isArray(obj[key])) {
map[key] = Object.values(map[key] as Record<string, unknown>);
}
} else {
map[key] = obj[key];
}
return map;
}, {});

export const generateBinding: GenerateBindingFn = (
options: BindOptions
): BindOutput => {
const result: BindOutput = {
output: {
entries: [],
},
outputDirAbs: options.outputDirAbs,
};
const output = result.output;
const abi = applyTransforms(options.abi);

const manifest = {
name: options.projectName,
type: "plugin",
version: latestWrapManifestVersion,
abi: JSON.stringify(
sort((options.abi as unknown) as Record<string, unknown>),
null,
2
),
};

output.entries = renderTemplates(templatePath(""), { ...abi, manifest }, {});

return result;
};

function applyTransforms(abi: WrapAbi): WrapAbi {
const transforms = [
extendType(Functions),
addFirstLast,
toPrefixedGraphQLType,
hasImports,
methodParentPointers(),
Transforms.propertyDeps(),
Transforms.byRef(),
];

for (const transform of transforms) {
abi = transformAbi(abi, transform);
}
return abi;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/// NOTE: This is an auto-generated file.
/// All modifications will be overwritten.

pub mod types;
#[path = "wrap.info.rs"]
pub mod wrap_info;
pub mod module;
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/// NOTE: This is an auto-generated file.
/// All modifications will be overwritten.

use std::sync::Arc;
use polywrap_core::invoke::Invoker;
use polywrap_plugin::error::PluginError;
use polywrap_plugin::module::PluginModule;
use serde::{Serialize, Deserialize};
use super::types::*;
use async_trait::async_trait;
pub use polywrap_plugin::impl_plugin_traits;

#[macro_export]
macro_rules! impl_traits {
($plugin_type:ty) => {
$crate::wrap::module::impl_plugin_traits!(
$plugin_type,
$crate::wrap::wrap_info::get_manifest(),
{{#moduleType}}
{{#methods}}
({{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}, $crate::wrap::module::Args{{#toUpper}}{{name}}{{/toUpper}}),
{{/methods}}
{{/moduleType}}
);
};
}

{{#moduleType}}
{{#methods}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Args{{#toUpper}}{{name}}{{/toUpper}} {
{{#arguments}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}pub {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}: {{#toWasm}}{{toGraphQLType}}{{/toWasm}},
{{/arguments}}
}

{{/methods}}
{{/moduleType}}
#[async_trait]
pub trait Module: PluginModule {
{{#moduleType}}
{{#methods}}
async fn {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}(&mut self, args: &Args{{#toUpper}}{{name}}{{/toUpper}}, invoker: Arc<dyn Invoker>) -> Result<{{#return}}{{#toWasm}}{{toGraphQLType}}{{/toWasm}}{{/return}}, PluginError>;
{{^last}}

{{/last}}
{{/methods}}
{{/moduleType}}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
#![allow(unused_imports)]
#![allow(non_camel_case_types)]

/// NOTE: This is an auto-generated file.
/// All modifications will be overwritten.
use serde::{Serialize, Deserialize};
use num_bigint::BigInt;
use bigdecimal::BigDecimal as BigNumber;
use serde_json as JSON;
use std::collections::BTreeMap as Map;
{{#importedModuleTypes}}
use std::sync::Arc;
use polywrap_msgpack::{decode, serialize};
use polywrap_core::{invoke::{Invoker, InvokeArgs}, uri::Uri};
use polywrap_plugin::error::PluginError;
{{/importedModuleTypes}}

/// Env START ///

{{#envType}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#properties}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}pub {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}: {{#toWasm}}{{toGraphQLType}}{{/toWasm}},
{{/properties}}
}
{{/envType}}
/// Env END ///

/// Objects START ///

{{#objectTypes}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#properties}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}pub {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}: {{#toWasm}}{{toGraphQLType}}{{/toWasm}},
{{/properties}}
}
{{/objectTypes}}
/// Objects END ///

/// Enums START ///

{{#enumTypes}}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#constants}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}{{#detectKeyword}}{{.}}{{/detectKeyword}},
{{/constants}}
_MAX_
}
{{/enumTypes}}
/// Enums END ///

/// Imported objects START ///

{{#importedObjectTypes}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#properties}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}pub {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}: {{#toWasm}}{{toGraphQLType}}{{/toWasm}},
{{/properties}}
}
{{/importedObjectTypes}}
/// Imported objects END ///

/// Imported envs START ///

{{#importedEnvType}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#properties}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}pub {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}: {{#toWasm}}{{toGraphQLType}}{{/toWasm}},
{{/properties}}
}
{{/importedEnvType}}
/// Imported envs END ///

/// Imported enums START ///

{{#importedEnumTypes}}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub enum {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#constants}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}{{#detectKeyword}}{{.}}{{/detectKeyword}},
{{/constants}}
_MAX_
}
{{/importedEnumTypes}}
/// Imported enums END ///

/// Imported Modules START ///

{{#importedModuleTypes}}
{{#methods}}
/// URI: "{{parent.uri}}" ///
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#toUpper}}{{parent.type}}{{/toUpper}}Args{{#toUpper}}{{name}}{{/toUpper}} {
{{#arguments}}
{{#serdeKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/serdeKeyword}}pub {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}: {{#toWasm}}{{toGraphQLType}}{{/toWasm}},
{{/arguments}}
}

{{/methods}}
{{^isInterface}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {}

impl {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
pub const URI: &'static str = "{{uri}}";

pub fn new() -> {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {
{{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} {}
}

{{#methods}}
pub async fn {{#detectKeyword}}{{#toLower}}{{name}}{{/toLower}}{{/detectKeyword}}(args: &{{#toUpper}}{{parent.type}}{{/toUpper}}Args{{#toUpper}}{{name}}{{/toUpper}}, invoker: Arc<dyn Invoker>) -> Result<{{#return}}{{#toWasm}}{{toGraphQLType}}{{/toWasm}}{{/return}}, PluginError> {
let uri = {{#parent}}{{#toUpper}}{{type}}{{/toUpper}}{{/parent}}::URI;
let serialized_args = InvokeArgs::UIntArray(serialize(args.clone()).unwrap());
let opt_args = Some(&serialized_args);
let uri = Uri::try_from(uri).unwrap();
let result = invoker.invoke(
&uri,
"{{name}}",
opt_args,
None,
None
)
.await
.map_err(|e| PluginError::SubinvocationError {
uri: uri.to_string(),
method: "{{name}}".to_string(),
args: serde_json::to_string(&args).unwrap(),
exception: e.to_string(),
})?;

Ok({{#return}}{{^required}}Some({{/required}}{{/return}}decode(result.as_slice())?{{#return}}{{^required}}){{/required}}{{/return}})
}
{{^last}}

{{/last}}
{{/methods}}
}
{{/isInterface}}
{{#isInterface}}
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}}<'a> {
{{#isInterface}}uri: &'a str{{/isInterface}}
}

impl<'a> {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}}<'a> {
pub const INTERFACE_URI: &'static str = "{{uri}}";

pub fn new(uri: &'a str) -> {{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}}<'a> {
{{#detectKeyword}}{{#toUpper}}{{type}}{{/toUpper}}{{/detectKeyword}} { uri: uri }
}

{{#methods}}
pub async fn {{#toLower}}{{name}}{{/toLower}}(&self, args: &{{#toUpper}}{{parent.type}}{{/toUpper}}Args{{#toUpper}}{{name}}{{/toUpper}}) -> Result<{{#return}}{{#toWasm}}{{toGraphQLType}}{{/toWasm}}{{/return}}, PluginError> {
let uri = self.uri;
let serialized_args = InvokeArgs::UIntArray(serialize(args.clone()).unwrap());
let result = invoker.invoke(
uri,
"{{name}}",
serialized_args,
None,
None
.await
.map_err(|e| PluginError::SubinvocationError {
uri: uri.to_string(),
method: "{{name}}".to_string(),
args: serde_json::to_string(&args).unwrap(),
exception: e.to_string(),
})?;

Ok({{#return}}{{^required}}Some({{/required}}{{/return}}decode(result.as_slice())?{{#return}}{{^required}}){{/required}}{{/return}})
}
{{^last}}

{{/last}}
{{/methods}}
}
{{/isInterface}}
{{/importedModuleTypes}}
/// Imported Modules END ///
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/// NOTE: This is an auto-generated file.
/// All modifications will be overwritten.
use polywrap_manifest::versions::{WrapManifest, WrapManifestAbi};
use serde_json::{json, from_value};

{{#manifest}}
pub fn get_manifest() -> WrapManifest {
WrapManifest {
name: "{{name}}".to_string(),
type_: "{{type}}".to_string(),
version: "{{version}}".to_string(),
abi: from_value::<WrapManifestAbi>(json!({{abi}})).unwrap()
}
}
{{/manifest}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { AbiTransforms } from "@polywrap/schema-parse";
import { AnyDefinition } from "@polywrap/wrap-manifest-types-js";

export function byRef(): AbiTransforms {
return {
enter: {
// eslint-disable-next-line @typescript-eslint/naming-convention
AnyDefinition: (def: AnyDefinition) => {
const byRefScalars = ["String", "BigInt", "BigNumber", "Map", "Bytes"];

if (def.scalar) {
if (byRefScalars.indexOf(def.scalar.type) > -1 || !def.required) {
return {
...def,
byRef: true,
};
}
}

return def;
},
},
};
}
Loading