-
Notifications
You must be signed in to change notification settings - Fork 2
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
ZK-1337: Create http server which serves bindings functions #96
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
[package] | ||
name = "macros-core" | ||
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. do we really need yet another crate? why can't its content belong to |
||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
once_cell = { workspace = true } | ||
serde_json = { workspace = true } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
use std::sync::Mutex; | ||
|
||
use once_cell::sync::Lazy; | ||
use serde_json::Value; | ||
|
||
pub type JsonFnPointer = fn(Value) -> Value; | ||
|
||
/// A simple struct to hold info about an "exported" function. | ||
#[derive(Debug, Clone)] | ||
pub struct JsonizedFunction { | ||
/// The function name as a string. | ||
pub name: &'static str, | ||
/// Pointer to the bridging function. | ||
pub func: JsonFnPointer, | ||
} | ||
|
||
/// A global registry of exported functions. | ||
/// | ||
/// By using `Lazy<Mutex<...>>`, we can push to this vector at compile time | ||
/// (technically, it's “init-time” for each static), and read it later. | ||
pub static EXPORTED_FUNCTIONS: Lazy<Mutex<Vec<JsonizedFunction>>> = | ||
Lazy::new(|| Mutex::new(Vec::new())); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
[package] | ||
name = "macros" | ||
version = "0.1.0" | ||
edition = "2021" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can inherit many attributes from the workspace |
||
|
||
[lib] | ||
proc-macro = true | ||
|
||
[dependencies] | ||
ctor = { workspace = true } | ||
macros-core = { workspace = true } | ||
once_cell = { workspace = true } | ||
proc-macro2 = { workspace = true } | ||
quote = { workspace = true } | ||
syn = { version = "1", features = ["full"] } |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
use proc_macro2::Ident; | ||
use quote::{format_ident, quote}; | ||
use syn::{FnArg, Pat, Type}; | ||
|
||
/// Helper struct to store parsed argument information | ||
pub struct ArgumentInfo { | ||
pub name: Ident, | ||
pub ty: Box<Type>, | ||
} | ||
|
||
/// Parse function arguments into a vector of ArgumentInfo | ||
pub fn parse_arguments( | ||
inputs: &syn::punctuated::Punctuated<FnArg, syn::token::Comma>, | ||
) -> Vec<ArgumentInfo> { | ||
let mut args = Vec::new(); | ||
|
||
for (i, arg) in inputs.iter().enumerate() { | ||
if let FnArg::Typed(pat_type) = arg { | ||
let arg_name = match &*pat_type.pat { | ||
Pat::Ident(ident) => ident.ident.clone(), | ||
_ => format_ident!("arg{}", i), | ||
}; | ||
args.push(ArgumentInfo { | ||
name: arg_name, | ||
ty: pat_type.ty.clone(), | ||
}); | ||
} | ||
} | ||
|
||
args | ||
} | ||
|
||
/// Generate Deserealizable struct definition for function arguments | ||
pub fn generate_args_struct( | ||
struct_name: &Ident, | ||
args: &[ArgumentInfo], | ||
) -> proc_macro2::TokenStream { | ||
let fields = args.iter().map(|arg| { | ||
let name = &arg.name; | ||
let ty = &arg.ty; | ||
quote! { pub #name: #ty } | ||
}); | ||
let fields_ts = quote! { | ||
#(#fields),* | ||
}; | ||
|
||
quote! { | ||
#[allow(non_camel_case_types)] | ||
#[derive(::serde::Deserialize)] | ||
struct #struct_name { | ||
#fields_ts | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
use proc_macro2::Ident; | ||
use quote::quote; | ||
|
||
use crate::args::ArgumentInfo; | ||
|
||
/// Generate bridging function that converts between JSON and native types | ||
/// JSON is parsed into a Deserealizable struct, then the function is called | ||
/// with the struct fields as arguments. The result is then serialized back | ||
/// into JSON. | ||
pub fn generate_bridging_fn( | ||
fn_name: &Ident, | ||
struct_name: &Ident, | ||
args: &[ArgumentInfo], | ||
ret_type: &proc_macro2::TokenStream, | ||
call_path: proc_macro2::TokenStream, | ||
) -> (proc_macro2::TokenStream, Ident) { | ||
let arg_names: Vec<_> = args.iter().map(|arg| &arg.name).collect(); | ||
let bridging_name = quote::format_ident!("{}_json", fn_name); | ||
|
||
( | ||
quote! { | ||
#[allow(non_snake_case)] | ||
fn #bridging_name(input: ::serde_json::Value) -> ::serde_json::Value { | ||
let args: #struct_name = match ::serde_json::from_value(input) { | ||
Ok(val) => val, | ||
Err(e) => { | ||
return ::serde_json::json!({ | ||
"error": format!("Invalid input JSON: {}", e) | ||
}); | ||
} | ||
}; | ||
|
||
let result: #ret_type = #call_path(#( args.#arg_names ),*); | ||
::serde_json::json!(result) | ||
} | ||
}, | ||
bridging_name, | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's keep them sorted (I will look for some lint to check this automatically)