Skip to content

Commit

Permalink
experiment: rewrite macro state
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Nov 6, 2023
1 parent 0553628 commit f5d9b9f
Show file tree
Hide file tree
Showing 11 changed files with 337 additions and 144 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
[workspace]
resolver = "2"
members = [
"deno_bindgen_macro",
"deno_bindgen",
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ in Rust.

### QuickStart

Annotate on top of Rust `fn`, `struct` and `enum` to make them available to Deno.
Annotate on top of Rust `fn`, `struct` and `enum` to make them available to
Deno.

```rust
// add.rs
Expand Down
74 changes: 74 additions & 0 deletions cli2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import { parse } from "https://deno.land/std@0.132.0/flags/mod.ts";

const flags = parse(Deno.args, { "--": true });
const release = !!flags.release;

function build() {
const args = ["build"];
if (release) args.push("--release");
args.push(...flags["--"]);
const proc = new Deno.Command("cargo", { args, stderr: "inherit" });
return proc.outputSync();
}

function nm() {
// Run `nm` to get the symbols from the compiled library.
const args = [
"nm",
"--format=bsd",
"--defined-only",
"target/debug/libdeno_bindgen_test.dylib",
];
if (release) args.push("--demangle");
const proc = new Deno.Command("nm", { args, stdout: "piped" });
const output = proc.outputSync();
const stdout = new TextDecoder().decode(output.stdout);
const symbols = stdout.split("\n").filter((s) => s.length > 0).slice(1);

const symbols2 = symbols.map((s) => {
const [addr, ty, name] = s.split(" ");
return { addr, ty, name };
}).filter((s) => s.name.startsWith("___de90_"));
return symbols2;
}

function run_init(symbols) {
const symbols_obj = {};
symbols.forEach(({ name }) => {
symbols_obj[name.slice(1)] = {
parameters: ["buffer", "buffer"],
result: "pointer",
};
});

const lib = Deno.dlopen("./target/debug/libdeno_bindgen_test.dylib", symbols_obj);
const params = new Uint8Array(20);
const result = new Uint8Array(1);
const processed = [];
for (const fn in lib.symbols) {
const name_ptr = lib.symbols[fn](params, result);
const name = Deno.UnsafePointerView.getCString(name_ptr);
processed.push({ name, params: [...params].map(p => C_TYPE[p]), result: C_TYPE[result[0]] })
}
return processed;
}

const C_TYPE = ["A", "B"];

function codegen(symbols) {
let code = '';
for (let i = 0; i < symbols.length; i++) {
const { name, params, result } = symbols[i];
const params_str = params.map((p, j) => `p${j}: ${p}`).join(', ');
const params_idents = params.map((p, j) => `p${j}`).join(', ');
code += `export function ${name}(${params_str}): ${result} { return lib.${name}(${params_idents}); }\n`;
}

console.log(code)
}

build();
const symbols = nm();
const processed = run_init(symbols);
codegen(processed);

53 changes: 53 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 1 addition & 5 deletions deno_bindgen_macro/src/attrs.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.

use syn::Attribute;
use syn::Lit;
use syn::Meta;
use syn::NestedMeta;

use inflector::Inflector;
use syn::{Attribute, Lit, Meta, NestedMeta};

#[derive(Debug)]
pub enum SerdeAttr {
Expand Down
15 changes: 5 additions & 10 deletions deno_bindgen_macro/src/derive_fn.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.

use crate::meta::Glue;
use crate::meta::Symbol;
use crate::meta::Type;
use syn::AttributeArgs;
use syn::FnArg;
use syn::ItemFn;
use syn::Meta;
use syn::NestedMeta;
use syn::PathArguments;
use syn::ReturnType;
use syn::{
AttributeArgs, FnArg, ItemFn, Meta, NestedMeta, PathArguments, ReturnType,
};

use crate::meta::{Glue, Symbol, Type};

pub fn process_function(
function: ItemFn,
Expand Down
18 changes: 8 additions & 10 deletions deno_bindgen_macro/src/derive_struct.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.

use crate::attrs::get_serde_attrs;
use crate::attrs::SerdeAttr;
use crate::docs::get_docs;
use crate::meta::Glue;

use std::collections::HashMap;
use syn::ext::IdentExt;
use syn::Data;
use syn::DataStruct;
use syn::DeriveInput;
use syn::Fields;

use syn::{ext::IdentExt, Data, DataStruct, DeriveInput, Fields};

use crate::{
attrs::{get_serde_attrs, SerdeAttr},
docs::get_docs,
meta::Glue,
};

macro_rules! variant_instance {
( $variant:path, $iterator:expr ) => {
Expand Down
4 changes: 1 addition & 3 deletions deno_bindgen_macro/src/docs.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.

use syn::Attribute;
use syn::Lit;
use syn::Meta;
use syn::{Attribute, Lit, Meta};

pub fn get_docs(attrs: &Vec<Attribute>) -> String {
let mut doc: Vec<String> = vec![];
Expand Down
55 changes: 36 additions & 19 deletions deno_bindgen_macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.

use proc_macro::TokenStream;
use quote::format_ident;
use quote::quote;
use std::env;
use std::fs::OpenOptions;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use syn::parse_macro_input;
use syn::parse_quote;
use syn::ItemFn;
use std::{
env,
fs::OpenOptions,
io::{Read, Write},
path::Path,
};

use proc_macro::{TokenStream};
use quote::{format_ident,quote};
use syn::{parse_macro_input, parse_quote, ItemFn};

mod attrs;
mod derive_fn;
mod derive_struct;
mod docs;
mod meta;

use crate::derive_fn::process_function;
use crate::derive_struct::process_struct;
use crate::meta::Glue;
use crate::meta::Type;
use crate::{
derive_fn::process_function,
derive_struct::process_struct,
meta::{Glue, Type},
};

#[cfg(target_endian = "little")]
const ENDIANNESS: bool = true;
Expand Down Expand Up @@ -72,7 +72,7 @@ pub fn deno_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
let mut input_idents = vec![];
let mut c_index = 0;

for parameter in symbol.parameters {
for parameter in &symbol.parameters {
match parameter {
Type::StructEnum { .. } => {
let ident = format_ident!("arg{}", c_index.to_string());
Expand Down Expand Up @@ -136,7 +136,7 @@ pub fn deno_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
// TODO
_ => {
let ident = format_ident!("arg{}", c_index.to_string());
let ty = syn::Type::from(parameter);
let ty = syn::Type::from(parameter.clone());
params.push(quote! { #ident: #ty });
input_idents.push(ident);
}
Expand Down Expand Up @@ -189,7 +189,7 @@ pub fn deno_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
(ty, transformer)
}
Type::Ptr => (parse_quote! { *const u8 }, quote! { result }),
_ => (syn::Type::from(symbol.result), quote! { result }),
_ => (syn::Type::from(symbol.result.clone()), quote! { result }),
};

let name = &func.sig.ident;
Expand All @@ -205,7 +205,9 @@ pub fn deno_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
metafile
.write_all(&serde_json::to_vec(&metadata).unwrap())
.unwrap();

let xname = format_ident!("__de90_{}", name.to_string());
let xparams = symbol.parameters.iter().map(|p| meta::CType::from(p) as u8).map(|p| quote!(#p)).collect::<Vec<_>>();
let xresult = meta::CType::from(&symbol.result) as u8;
TokenStream::from(quote! {
#[no_mangle]
pub extern "C" fn #name <'sym> (#(#params,) *) -> #result {
Expand All @@ -214,6 +216,21 @@ pub fn deno_bindgen(attr: TokenStream, input: TokenStream) -> TokenStream {
let result = __inner_impl(#(#input_idents, ) *);
#transformer
}

#[no_mangle]
pub unsafe extern "C" fn #xname (
params: *mut u8,
result: *mut u8,
) -> *const u8 {
let mut idx = 0;
let params = ::std::slice::from_raw_parts_mut(params, 200);
#(
params[idx] = #xparams;
idx += 1;
)*;
*result = #xresult;
concat!(stringify!(#name), "\0").as_ptr()
}
})
}
Err(_) => {
Expand Down
52 changes: 50 additions & 2 deletions deno_bindgen_macro/src/meta.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// Copyright 2020-2021 the Deno authors. All rights reserved. MIT license.

use serde::Deserialize;
use serde::Serialize;
use std::collections::HashMap;

use serde::{Deserialize, Serialize};
use syn::parse_quote;

#[derive(Serialize, Deserialize, Clone)]
Expand Down Expand Up @@ -38,6 +38,54 @@ pub enum Type {
},
}

#[repr(u8)]
pub enum CType {
/// Straight forward types supported
/// by Deno's FFI
I8,
U8,
I16,
U16,
I32,
U32,
I64,
U64,
F32,
F64,
Usize,
Isize,
Void,
Buffer,
BufferMut,
Str,
Ptr,
}

impl From<&Type> for CType {
fn from(ty: &Type) -> Self {
match ty {
Type::I8 => CType::I8,
Type::U8 => CType::U8,
Type::I16 => CType::I16,
Type::U16 => CType::U16,
Type::I32 => CType::I32,
Type::U32 => CType::U32,
Type::I64 => CType::I64,
Type::U64 => CType::U64,
Type::F32 => CType::F32,
Type::F64 => CType::F64,
Type::Usize => CType::Usize,
Type::Isize => CType::Isize,
Type::Void => CType::Void,
Type::Buffer => CType::Buffer,
Type::BufferMut => CType::BufferMut,
Type::Str => CType::Str,
Type::Ptr => CType::Ptr,
Type::StructEnum { .. } => CType::Ptr,
}
}
}

impl From<Type> for syn::Type {
fn from(ty: Type) -> Self {
match ty {
Expand Down
Loading

0 comments on commit f5d9b9f

Please sign in to comment.