Skip to content
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

Water Macros first pass [Draft] #9

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
18 changes: 18 additions & 0 deletions crates/macros/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "water_macros"
version = "0.0.1"
authors.workspace = true
description.workspace = true
edition.workspace = true

[lib]
proc-macro = true
doctest=false

[features]

[dependencies]
proc-macro2 = "1.0.7"
quote = "1"
lazy_static = "~1.4.0"
syn = { version = "2.0", features = ["full"] }
131 changes: 131 additions & 0 deletions crates/macros/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#[allow(unused_extern_crates)]
extern crate proc_macro;
extern crate proc_macro2;

extern crate quote;
extern crate syn;

mod v0;
use v0::{entrypoint, impl_water_dial, impl_water_listen, impl_water_wrap};

use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput};

/// Marks async function to be executed by the selected runtime. This macro
/// helps set up a `Runtime` without requiring the user to use
/// [Runtime](../tokio/runtime/struct.Runtime.html) or
/// [Builder](../tokio/runtime/struct.Builder.html) directly.
///
/// Note: This macro is designed to be simplistic and targets applications that
/// do not require a complex setup. If the provided functionality is not
/// sufficient, you may be interested in using
/// [Builder](../tokio/runtime/struct.Builder.html), which provides a more
/// powerful interface.
///
/// Note: This macro can be used on any function and not just the `main`
/// function. Using it on a non-main function makes the function behave as if it
/// was synchronous by starting a new runtime each time it is called. If the
/// function is called often, it is preferable to create the runtime using the
/// runtime builder so the runtime can be reused across calls.
///
/// # Non-worker async function
///
/// Note that the async function marked with this macro does not run as a
/// worker. The expectation is that other tasks are spawned by the function here.
/// Awaiting on other futures from the function provided here will not
/// perform as fast as those spawned as workers.
///
/// ```
/// #[water_macros_v0::entry]
/// # fn entry() {}
/// ```
/// ## Usage
///
/// ### Using the multi-thread runtime
///
/// ```rust
/// #[water_macros_v0::entry]
/// async fn main() {
/// println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[water_macros_v0::entry]`
///
/// ```rust
/// fn entry() {
/// tokio::runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// println!("Hello world");
/// })
/// }
/// ```
///
/// ### Rename package
///
/// ```rust
/// use water_macros_v0 as wtr0;
///
/// #[water_macros_v0::entry(crate = "wtr0")]
/// fn entry() {
/// println!("Hello world");
/// }
/// ```
///
/// Equivalent code not using `#[tokio::main]`
///
/// ```rust
/// use water_macros_v0 as wtr0;
///
/// fn entry() {
/// tokio1::runtime::Builder::new_multi_thread()
/// .enable_all()
/// .build()
/// .unwrap()
/// .block_on(async {
/// println!("Hello world");
/// })
/// }
/// ```
#[proc_macro_attribute]
// #[cfg(not(test))] // Work around for rust-lang/rust#62127
pub fn entry(args: TokenStream, item: TokenStream) -> TokenStream {
entrypoint(args.into(), item.into()).into()
}

// // Disabled for now since Testing with C interface doesn't make a lot if sense yet.
// #[cfg(test)]
// #[proc_macro_attribute]
// pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
// entry::test(args.into(), item.into()).into()
// }

#[proc_macro_derive(WaterDialer)]
pub fn water_dial_macro(input: TokenStream) -> TokenStream {
// Parse the string representation
let ast = parse_macro_input!(input as DeriveInput);

// Build the impl
impl_water_dial(&ast)
}

#[proc_macro_derive(WaterListener)]
pub fn water_listen_macro(input: TokenStream) -> TokenStream {
// Parse the string representation
let ast = parse_macro_input!(input as DeriveInput);

// Build the impl
impl_water_listen(&ast)
}

#[proc_macro_derive(WaterWrapper)]
pub fn water_wrap_macro(input: TokenStream) -> TokenStream {
// Parse the string representation
let ast = parse_macro_input!(input as DeriveInput);

// Build the impl
impl_water_wrap(&ast)
}
64 changes: 64 additions & 0 deletions crates/macros/src/v0/dial.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use proc_macro::TokenStream;
use quote::{format_ident, quote};

pub(crate) fn impl_water_dial(ast: &syn::DeriveInput) -> TokenStream {
let name = &ast.ident;
let inst_name = &format_ident!("OBJ_{}", name.to_string().to_uppercase());

quote! {
// version-independent API
#[export_name = "_version"]
pub fn _version() -> i32 {
::water_wasm::v0::VERSION
}

// version-independent API
#[export_name = "_role"]
pub fn _role() -> i32 {
::water_wasm::common::Role::Dialer as i32
}


lazy_static! {
static ref #inst_name: std::sync::Arc<
std::sync::Mutex<
std::boxed::Box< dyn ::water_wasm::v0::ReadWriteDial + Sized>>> = {
let m = std::sync::Arc::new(std::sync::Mutex::new(<#name>::new()));
m
};
}

#[export_name = "_config"]
pub fn _config(fd: i32) -> i32 {
0
}

#[export_name = "_dial"]
pub fn _dial(caller_conn_fd: i32) -> i32 {
println!("Dialing...");
let mut obj = #inst_name.lock().unwrap();
obj.dial(caller_conn_fd)
}


// V0 API
#[export_name = "_read"]
pub fn _read() -> i32 {
println!("Dialing...");
let mut obj = #inst_name.lock().unwrap();
// obj.Read(caller_conn_fd)
}

// V0 API
#[export_name = "_write"]
pub fn _write() -> i32 {
0
}

// V0 API
#[export_name = "_close"]
pub fn _close() { }

}
.into()
}
Loading
Loading