Skip to content

Commit

Permalink
support non_blocking attribute for symbols (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy authored Oct 18, 2021
1 parent 266a717 commit 3fbaa41
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 34 deletions.
15 changes: 10 additions & 5 deletions codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ function resolveDlopenParameter(typeDefs: TypeDef, type: any): string {
type Sig = Record<string, {
parameters: any[];
result: string;
nonBlocking?: boolean;
}>;

type Options = {
Expand Down Expand Up @@ -70,12 +71,12 @@ const _lib = await Plug.prepare(opts, {
return `"${ffiParam}"${typeof p !== "string" ? `, "usize"` : ""}`;
})
.join(", ")
} ], result: "${signature[sig].result}" }`
} ], result: "${signature[sig].result}", nonblocking: ${
String(!!signature[sig].nonBlocking)
} }`
).join(", ")
} });
${
Object.keys(decl).map((def) => typescript[def]).join("\n")
}
${Object.keys(decl).map((def) => typescript[def]).join("\n")}
${
Object.keys(signature).map((sig) =>
`export function ${sig}(${
Expand All @@ -94,7 +95,11 @@ ${
signature[sig].parameters.map((p, i) =>
typeof p !== "string" ? `a${i}_buf, a${i}_buf.byteLength` : `a${i}`
).join(", ")
}) as ${resolveType(decl, signature[sig].result)}
}) as ${
signature[sig].nonBlocking
? `Promise<${resolveType(decl, signature[sig].result)}>`
: resolveType(decl, signature[sig].result)
}
}`
).join("\n")
}
Expand Down
16 changes: 14 additions & 2 deletions example/add_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import {
add,
add2,
OptionStruct,
sleep,
test_mixed,
test_mixed_order,
test_serde,
} from "./bindings/bindings.ts";
import { assertEquals } from "https://deno.land/std/testing/asserts.ts";
import { assert, assertEquals } from "https://deno.land/std/testing/asserts.ts";

Deno.test({
name: "add#test",
Expand Down Expand Up @@ -45,10 +46,21 @@ Deno.test({
});

Deno.test({
name: "test_options",
name: "test_options#test",
fn: () => {
let opts: OptionStruct = { maybe: " " };
opts.maybe = null;
opts.maybe = undefined;
},
});

Deno.test({
name: "sleep#test",
fn: async () => {
const ms = 100;
const start = performance.now();
const promise = sleep(ms).then(() => assert(start >= ms));
assert(performance.now() - start < ms);
await promise;
},
});
72 changes: 48 additions & 24 deletions example/bindings/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,71 @@ import { Plug } from "https://deno.land/x/[email protected]/mod.ts";
const encode = (s: string) => new TextEncoder().encode(s);
const opts = {
name: "add",
url: "target/debug"
url: "target/debug",
};
const _lib = await Plug.prepare(opts, {
add: { parameters: [ "i32", "i32" ], result: "i32" }, test_mixed: { parameters: [ "isize", "buffer", "usize" ], result: "i32" }, test_serde: { parameters: [ "buffer", "usize" ], result: "u8" }, add2: { parameters: [ "buffer", "usize" ], result: "i32" }, test_mixed_order: { parameters: [ "i32", "buffer", "usize", "i32" ], result: "i32" } });
export type OptionStruct = {
maybe: string | undefined | null;
add: { parameters: ["i32", "i32"], result: "i32", nonblocking: false },
sleep: { parameters: ["u64"], result: "void", nonblocking: true },
test_serde: {
parameters: ["buffer", "usize"],
result: "u8",
nonblocking: false,
},
add2: { parameters: ["buffer", "usize"], result: "i32", nonblocking: false },
test_mixed_order: {
parameters: ["i32", "buffer", "usize", "i32"],
result: "i32",
nonblocking: false,
},
test_mixed: {
parameters: ["isize", "buffer", "usize"],
result: "i32",
nonblocking: false,
},
});
export type MyStruct = {
arr: Array<string>;
};
/**
* Doc comment for `Input` struct.
* ...testing multiline
**/
* Doc comment for `Input` struct.
* ...testing multiline
*/
export type Input = {
/**
* Doc comments get
* transformed to JS doc
* comments.
**/
* Doc comments get
* transformed to JS doc
* comments.
*/
a: number;
b: number;
};
export type MyStruct = {
arr: Array<string>;
export type OptionStruct = {
maybe: string | undefined | null;
};
export function add(a0: number,a1: number) {

return _lib.symbols.add(a0, a1) as number
export function add(a0: number, a1: number) {
return _lib.symbols.add(a0, a1) as number;
}
export function test_mixed(a0: number,a1: Input) {
const a1_buf = encode(JSON.stringify(a1));
return _lib.symbols.test_mixed(a0, a1_buf, a1_buf.byteLength) as number
export function sleep(a0: number) {
return _lib.symbols.sleep(a0) as Promise<null>;
}
export function test_serde(a0: MyStruct) {
const a0_buf = encode(JSON.stringify(a0));
return _lib.symbols.test_serde(a0_buf, a0_buf.byteLength) as number
return _lib.symbols.test_serde(a0_buf, a0_buf.byteLength) as number;
}
export function add2(a0: Input) {
const a0_buf = encode(JSON.stringify(a0));
return _lib.symbols.add2(a0_buf, a0_buf.byteLength) as number
return _lib.symbols.add2(a0_buf, a0_buf.byteLength) as number;
}
export function test_mixed_order(a0: number, a1: Input, a2: number) {
const a1_buf = encode(JSON.stringify(a1));
return _lib.symbols.test_mixed_order(
a0,
a1_buf,
a1_buf.byteLength,
a2,
) as number;
}
export function test_mixed_order(a0: number,a1: Input,a2: number) {
export function test_mixed(a0: number, a1: Input) {
const a1_buf = encode(JSON.stringify(a1));
return _lib.symbols.test_mixed_order(a0, a1_buf, a1_buf.byteLength, a2) as number
return _lib.symbols.test_mixed(a0, a1_buf, a1_buf.byteLength) as number;
}

7 changes: 7 additions & 0 deletions example/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,10 @@ fn test_serde(s: MyStruct) -> u8 {
struct OptionStruct {
maybe: Option<String>,
}

// Test non_blocking
#[deno_bindgen(non_blocking)]
fn sleep(ms: u64) {
std::thread::sleep(std::time::Duration::from_millis(ms));
}

24 changes: 21 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,14 @@ use std::env;
use std::fs::OpenOptions;
use std::io::Read;
use std::io::Write;
use syn::parse_macro_input;
use syn::parse_quote;
use syn::Data;
use syn::DataStruct;
use syn::Fields;
use syn::ItemFn;
use syn::Meta;
use syn::NestedMeta;

#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
Expand Down Expand Up @@ -71,9 +74,11 @@ impl From<Type> for syn::Type {
}

#[derive(Serialize, Deserialize, Clone)]
#[serde(rename_all = "camelCase")]
struct Symbol {
parameters: Vec<Type>,
result: Type,
non_blocking: bool,
}

#[derive(Serialize, Deserialize, Default)]
Expand All @@ -95,7 +100,7 @@ const ENDIANNESS: bool = true;
const ENDIANNESS: bool = false;

#[proc_macro_attribute]
pub fn deno_bindgen(_attr: TokenStream, input: TokenStream) -> TokenStream {
pub fn deno_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut metadata: Glue = match OpenOptions::new().read(true).open(METAFILE) {
Ok(mut fd) => {
let mut meta = String::new();
Expand All @@ -119,7 +124,8 @@ pub fn deno_bindgen(_attr: TokenStream, input: TokenStream) -> TokenStream {

let (func, symbol) = match syn::parse::<ItemFn>(input.clone()) {
Ok(func) => {
let symbol = process_function(func.clone(), &mut metadata).unwrap();
let attr = parse_macro_input!(attr as syn::AttributeArgs);
let symbol = process_function(func.clone(), attr, &mut metadata).unwrap();
(func, symbol)
}
Err(_) => {
Expand Down Expand Up @@ -199,6 +205,7 @@ pub fn deno_bindgen(_attr: TokenStream, input: TokenStream) -> TokenStream {

fn process_function(
function: ItemFn,
attr: syn::AttributeArgs,
metadata: &mut Glue,
) -> Result<Symbol, String> {
let params = &function.sig.inputs;
Expand Down Expand Up @@ -268,7 +275,18 @@ fn process_function(
};

let symbol_name = function.sig.ident.to_string();
let symbol = Symbol { parameters, result };
let non_blocking = match attr.get(0).as_ref() {
Some(NestedMeta::Meta(Meta::Path(ref attr_ident))) => {
attr_ident.is_ident("non_blocking")
}
_ => false,
};

let symbol = Symbol {
parameters,
result,
non_blocking,
};
metadata.symbols.insert(symbol_name, symbol.clone());

Ok(symbol)
Expand Down

0 comments on commit 3fbaa41

Please sign in to comment.