Skip to content

Commit

Permalink
add new readme
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Nov 8, 2023
1 parent 91e6d2e commit 2859088
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 91 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ target/
example/Cargo.lock
bindings.json
.DS_Store
deno.lock
3 changes: 1 addition & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
MIT License

Copyright (c) 2021-2022 Divy Srivastava <dj.srivastava23@gmail.com>
Copyright (c) 2022 the Deno authors
Copyright (c) 2023 Divy Srivastava <dj.srivastava23@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
11 changes: 7 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ fmt:
cargo fmt
deno fmt --ignore=target/,example/target/,example/bindings/

test:
cd example && deno run -A ../cli.ts && deno test -A --unstable
build:
cargo build

bench:
cd example && deno run -A ../cli.ts && deno bench -A --unstable bench.js
test: build
cd example && ../target/debug/deno_bindgen -o bindings/bindings.ts && deno test -A --unstable

bench: build
cd example && ../target/debug/deno_bindgen -o bindings/bindings.ts && deno bench -A --unstable bench.js
69 changes: 67 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,86 @@
## `deno_bindgen`
# `deno_bindgen`

<img src="./assets/illustration.png" width=200>
<img align="right" src="./assets/illustration.png" width=200>

This tool aims to simplify glue code generation for Deno FFI libraries written
in Rust.

## Install

Install the command-line via `cargo`:

```bash
cargo install deno_bindgen_cli
```

## Usage

```rust
use deno_bindgen::deno_bindgen;

// Export `add` function to JavaScript.
#[deno_bindgen]
fn add(a: u32, b: u32) -> u32 {
a + b
}
```

Use the exported functions directly in ESM with TypeScript typings

```typescript
import { add } from "@ffi/example";

add(1, 2);
```

## Design

The tool is designed to make it very easy to write high performance FFI
bindings. A lot of the things have been redesigned in `0.10` to prevent perf
footguns.

TypeScript types are generated and supported OOTB.

All class handles support disposing memory via the Explicit Resource Management
API (`using`).

```rust
#[deno_bindgen]
pub struct Foo;

#[deno_bindgen]
impl Foo {
#[constructor]
pub fn new() -> Self {
Self
}

pub fn bar(&self) {
// ...
}
}
```

```js
import { Foo } from "@ffi/example";

{
using foo = new Foo();
foo.bar();
// foo is disposed here...
}
```

High performance. Codegen tries its best to take the fastest possible path for all bindings as-if they were written by hand to properly leverage the power of the Deno FFI JIT calls.

```
> make bench
cpu: Apple M1
runtime: deno 1.38.0 (aarch64-apple-darwin)
file:///Users/divy/gh/deno_bindgen/example/bench.js
benchmark time (avg) iter/s (min … max) p75 p99 p995
--------------------------------------------------------------- -----------------------------
add 6.88 ns/iter 145,297,626.6 (6.78 ns … 13.33 ns) 6.81 ns 8.22 ns 9.4 ns
bytelen 8.05 ns/iter 124,278,976.3 (7.81 ns … 18.1 ns) 8.09 ns 10.39 ns 11.64 ns
```
53 changes: 0 additions & 53 deletions deno.lock

This file was deleted.

10 changes: 5 additions & 5 deletions deno_bindgen_ir/codegen/deno.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ impl<'a> Codegen<'a> {
allow_empty: bool,
callback: impl Fn(&mut W, &[T]) -> Result<()>,
nesting_spaces: usize,
delim: (char, char),
delim: (char, &str),
) -> Result<()> {
let (start, end) = delim;
write!(writer, "{start}")?;
Expand Down Expand Up @@ -218,7 +218,7 @@ impl<'a> Codegen<'a> {
Ok(())
},
0,
('(', ')'),
('(', ")"),
)?;
let ret_ty = TypeScriptType::from(symbol.return_type);
writeln!(
Expand Down Expand Up @@ -249,7 +249,7 @@ impl<'a> Codegen<'a> {
Ok(())
},
2,
('(', ')'),
('(', ")"),
)?;

if let Some(ret_transform) = maybe_ret_transform {
Expand Down Expand Up @@ -345,15 +345,15 @@ impl<'a> Codegen<'a> {
Ok(())
},
4,
('(', ')'),
('(', ")"),
)?;

writeln!(writer, "\n }}")?;
}
Ok(())
},
0,
('{', '}'),
('{', "}\n\n"),
)?;
}
}
Expand Down
2 changes: 1 addition & 1 deletion example/bench.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { add, bytelen } from "./bindings/bindings.ts";

// Optimized fast paths:
Deno.bench("add", () => add(1, 2));

const b = new Uint8Array([1, 2, 3, 4]);
Deno.bench("bytelen", () => bytelen(b));
70 changes: 65 additions & 5 deletions example/bindings/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,25 @@ const { symbols } = dlopen('./target/debug/libdeno_bindgen_test.dylib', {
result: 'i32',
nonblocking: false
},
add2: {
__Input_new: {
parameters: [
'i32',
'i32',
],
result: 'pointer',
nonblocking: false
},
__Input_dealloc: {
parameters: [
'pointer',
],
result: 'void',
nonblocking: false
},
add2: {
parameters: [
'pointer',
],
result: 'i32',
nonblocking: false
},
Expand Down Expand Up @@ -108,14 +122,59 @@ export function add(
)
}

export function add2(
function __Input_new(
arg0: number,
arg1: number,
): number {
return symbols.add2(
): Input {
const ret = symbols.__Input_new(
arg0,
arg1,
)
return Input.__constructor(ret);
}

function __Input_dealloc(
arg0: Deno.PointerObject | null,
): void {
return symbols.__Input_dealloc(
arg0,
)
}

export class Input {
ptr: Deno.PointerObject | null = null;

static __constructor(ptr: Deno.PointerObject | null) {
const self = Object.create(Input.prototype);
self.ptr = ptr;
return self;
}

[Symbol.dispose]() {
this.dealloc();
this.ptr = null;
}

constructor(arg0: number, arg1: number) {
return __Input_new(
arg0,
arg1,
)
}

dealloc(): void {
return __Input_dealloc(
this.ptr,
)
}
}

export function add2(
arg0: Input,
): number {
return symbols.add2(
arg0.ptr,
)
}

export function bytelen(
Expand Down Expand Up @@ -238,4 +297,5 @@ export class Foo {
this.ptr,
)
}
}
}

Loading

0 comments on commit 2859088

Please sign in to comment.