From bb35d0bd09da2a7bea3176ab9a4f9ee0e8f4f8f6 Mon Sep 17 00:00:00 2001 From: Vadim Obradovich Date: Mon, 20 May 2024 16:29:13 +0300 Subject: [PATCH 01/14] fix(macros): unexpected input handler produces wrong output (#257) --- .cargo/config.toml | 2 + Cargo.lock | 50 +++++++++++++++-- Cargo.toml | 1 + macros/Cargo.toml | 1 + macros/core/src/service.rs | 6 ++- macros/core/src/shared.rs | 12 +++-- ...ltiple_services_with_non_empty_routes.snap | 18 ++++--- ...r_single_service_with_non_empty_route.snap | 18 ++++--- ...ram_generates_init_for_multiple_ctors.snap | 18 ++++--- ...__gprogram_generates_init_for_no_ctor.snap | 18 ++++--- ...rogram_generates_init_for_single_ctor.snap | 18 ++++--- .../snapshots/service__gservice_works.snap | 18 +++++-- ...vice_works_for_lifetimes_and_generics.snap | 18 +++++-- macros/tests/integration_tests.rs | 10 ++-- ...service_works_panic_on_unexpected_input.rs | 35 ++++++++++++ ...anic_on_unexpected_input_double_encoded.rs | 53 +++++++++++++++++++ 16 files changed, 235 insertions(+), 61 deletions(-) create mode 100644 .cargo/config.toml create mode 100644 macros/tests/ui/gservice_works_panic_on_unexpected_input.rs create mode 100644 macros/tests/ui/gservice_works_panic_on_unexpected_input_double_encoded.rs diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 100644 index 00000000..9efc0626 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.x86_64-pc-windows-msvc] +rustflags = ["-Clink-arg=/force:unresolved", "-Ctarget-feature=+crt-static"] diff --git a/Cargo.lock b/Cargo.lock index f374905d..c4a54d67 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1313,6 +1313,16 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fluent-asserter" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62cd2a1243f15c8c9d37acc8ab4ba837e50823561cb124af8406a6f676d04341" +dependencies = [ + "lazy_static", + "num", +] + [[package]] name = "fnv" version = "1.0.7" @@ -2936,6 +2946,20 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aeaf4ad7403de93e699c191202f017118df734d3850b01e13a3a8b2e6953d3c9" +[[package]] +name = "num" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3135b08af27d103b0a51f2ae0f8632117b7b185ccf931445affa8df530576a41" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.4" @@ -2947,6 +2971,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + [[package]] name = "num-format" version = "0.4.4" @@ -2959,11 +2992,21 @@ dependencies = [ [[package]] name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", + "num-integer", "num-traits", ] @@ -2981,9 +3024,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", ] @@ -3845,6 +3888,7 @@ dependencies = [ name = "sails-macros" version = "0.0.1" dependencies = [ + "fluent-asserter", "parity-scale-codec", "proc-macro-error", "sails-macros-core", diff --git a/Cargo.toml b/Cargo.toml index 407eafbe..babe2595 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,7 @@ members = [ anyhow = "1" const-format = { package = "const_format", version = "0.2" } convert-case = { package = "convert_case", version = "0.6" } +fluent-asserter = "0.1" futures = { version = "0.3", default-features = false } gear-core-errors = "1.4.1" git-download = "0.1" diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 2423bfb2..b120fabd 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -13,6 +13,7 @@ sails-macros-core = { path = "./core" } proc-macro-error.workspace = true [dev-dependencies] +fluent-asserter.workspace = true parity-scale-codec = { workspace = true, features = ["derive"] } sails-rtl.workspace = true scale-info = { workspace = true, features = ["derive"] } diff --git a/macros/core/src/service.rs b/macros/core/src/service.rs index f8904db0..fc92ad3c 100644 --- a/macros/core/src/service.rs +++ b/macros/core/src/service.rs @@ -128,6 +128,9 @@ pub fn gservice(service_impl_tokens: TokenStream2) -> TokenStream2 { let scale_codec_path = sails_paths::scale_codec_path(); let scale_info_path = sails_paths::scale_info_path(); + let unexpected_route_panic = + shared::generate_unexpected_input_panic(&input_ident, "Unknown request"); + quote!( #service_impl @@ -142,8 +145,7 @@ pub fn gservice(service_impl_tokens: TokenStream2) -> TokenStream2 { pub async fn handle(&mut self, mut #input_ident: &[u8]) -> Vec { #(#invocation_dispatches)* - let invocation_path = String::decode(&mut #input_ident).expect("Failed to decode invocation path"); - panic!("Unknown request: {}", invocation_path); + #unexpected_route_panic } #(#invocation_funcs)* diff --git a/macros/core/src/shared.rs b/macros/core/src/shared.rs index 243364da..cf592fec 100644 --- a/macros/core/src/shared.rs +++ b/macros/core/src/shared.rs @@ -1,5 +1,5 @@ use crate::route; -use proc_macro2::TokenStream as TokenStream2; +use proc_macro2::{Span, TokenStream as TokenStream2}; use proc_macro_error::abort; use quote::{quote, ToTokens}; use std::collections::BTreeMap; @@ -156,16 +156,18 @@ pub(crate) fn discover_invocation_targets( pub(crate) fn generate_unexpected_input_panic(input_ident: &Ident, message: &str) -> TokenStream2 { let message_pattern = message.to_owned() + ": {}"; + let copy_ident = Ident::new(&format!("__{}", input_ident), Span::call_site()); quote!({ - let input = String::decode(&mut #input_ident) + let mut #copy_ident = #input_ident; + let input = String::decode(&mut #copy_ident) .unwrap_or_else(|_| { if #input_ident.len() <= 8 { - format!("0x{}", hex::encode(#input_ident)) + format!("0x{}", sails_rtl::hex::encode(#input_ident)) } else { format!( "0x{}..{}", - hex::encode(&#input_ident[..4]), - hex::encode(&#input_ident[#input_ident.len() - 4..])) + sails_rtl::hex::encode(&#input_ident[..4]), + sails_rtl::hex::encode(&#input_ident[#input_ident.len() - 4..])) } }); panic!(#message_pattern, input) diff --git a/macros/core/tests/snapshots/program__gprogram_generates_handle_for_multiple_services_with_non_empty_routes.snap b/macros/core/tests/snapshots/program__gprogram_generates_handle_for_multiple_services_with_non_empty_routes.snap index a6860a35..774e6dc5 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_handle_for_multiple_services_with_non_empty_routes.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_handle_for_multiple_services_with_non_empty_routes.snap @@ -77,14 +77,15 @@ pub mod wasm { let input = gstd::msg::load_bytes().expect("Failed to read input"); if !input.is_empty() { { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); @@ -112,14 +113,15 @@ pub mod wasm { let output = service.handle(&input[__ROUTE_SVC1.len()..]).await; [__ROUTE_SVC1.as_ref(), &output].concat() } else { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); diff --git a/macros/core/tests/snapshots/program__gprogram_generates_handle_for_single_service_with_non_empty_route.snap b/macros/core/tests/snapshots/program__gprogram_generates_handle_for_single_service_with_non_empty_route.snap index 3f3396b8..d325d30a 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_handle_for_single_service_with_non_empty_route.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_handle_for_single_service_with_non_empty_route.snap @@ -56,14 +56,15 @@ pub mod wasm { let input = gstd::msg::load_bytes().expect("Failed to read input"); if !input.is_empty() { { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); @@ -85,14 +86,15 @@ pub mod wasm { let output = service.handle(&input[__ROUTE_SERVICE.len()..]).await; [__ROUTE_SERVICE.as_ref(), &output].concat() } else { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); diff --git a/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap b/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap index 41ed8c1b..83dcfc49 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap @@ -68,14 +68,15 @@ pub mod wasm { let program = MyProgram::new2(request.p2, request.p1); (program, INVOCATION_ROUTE.as_ref()) } else { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); @@ -90,14 +91,15 @@ pub mod wasm { async fn main() { let mut input: &[u8] = &gstd::msg::load_bytes().expect("Failed to read input"); let output: Vec = { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); diff --git a/macros/core/tests/snapshots/program__gprogram_generates_init_for_no_ctor.snap b/macros/core/tests/snapshots/program__gprogram_generates_init_for_no_ctor.snap index 46c4dcc5..e327814d 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_init_for_no_ctor.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_init_for_no_ctor.snap @@ -31,14 +31,15 @@ pub mod wasm { let input = gstd::msg::load_bytes().expect("Failed to read input"); if !input.is_empty() { { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); @@ -54,14 +55,15 @@ pub mod wasm { async fn main() { let mut input: &[u8] = &gstd::msg::load_bytes().expect("Failed to read input"); let output: Vec = { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); diff --git a/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap b/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap index 23383a27..25160d72 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap @@ -51,14 +51,15 @@ pub mod wasm { let program = MyProgram::new(request.p1, request.p2).await; (program, INVOCATION_ROUTE.as_ref()) } else { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); @@ -73,14 +74,15 @@ pub mod wasm { async fn main() { let mut input: &[u8] = &gstd::msg::load_bytes().expect("Failed to read input"); let output: Vec = { - let input = String::decode(&mut input) + let mut __input = input; + let input = String::decode(&mut __input) .unwrap_or_else(|_| { if input.len() <= 8 { - format!("0x{}", hex::encode(input)) + format!("0x{}", sails_rtl::hex::encode(input)) } else { format!( - "0x{}..{}", hex::encode(& input[..4]), hex::encode(& - input[input.len() - 4..]) + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) ) } }); diff --git a/macros/core/tests/snapshots/service__gservice_works.snap b/macros/core/tests/snapshots/service__gservice_works.snap index 418ed671..00581cc6 100644 --- a/macros/core/tests/snapshots/service__gservice_works.snap +++ b/macros/core/tests/snapshots/service__gservice_works.snap @@ -43,9 +43,21 @@ impl Exposure { static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; return [INVOCATION_ROUTE.as_ref(), &output].concat(); } - let invocation_path = String::decode(&mut input) - .expect("Failed to decode invocation path"); - panic!("Unknown request: {}", invocation_path); + { + let mut __input = input; + let input = String::decode(&mut __input) + .unwrap_or_else(|_| { + if input.len() <= 8 { + format!("0x{}", sails_rtl::hex::encode(input)) + } else { + format!( + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) + ) + } + }); + panic!("Unknown request: {}", input) + } } async fn __do_this(&mut self, mut input: &[u8]) -> Vec { let request = __DoThisParams::decode(&mut input) diff --git a/macros/core/tests/snapshots/service__gservice_works_for_lifetimes_and_generics.snap b/macros/core/tests/snapshots/service__gservice_works_for_lifetimes_and_generics.snap index 322fe73e..ea4ec331 100644 --- a/macros/core/tests/snapshots/service__gservice_works_for_lifetimes_and_generics.snap +++ b/macros/core/tests/snapshots/service__gservice_works_for_lifetimes_and_generics.snap @@ -39,9 +39,21 @@ where ]; return [INVOCATION_ROUTE.as_ref(), &output].concat(); } - let invocation_path = String::decode(&mut input) - .expect("Failed to decode invocation path"); - panic!("Unknown request: {}", invocation_path); + { + let mut __input = input; + let input = String::decode(&mut __input) + .unwrap_or_else(|_| { + if input.len() <= 8 { + format!("0x{}", sails_rtl::hex::encode(input)) + } else { + format!( + "0x{}..{}", sails_rtl::hex::encode(& input[..4]), + sails_rtl::hex::encode(& input[input.len() - 4..]) + ) + } + }); + panic!("Unknown request: {}", input) + } } async fn __do_this(&mut self, mut input: &[u8]) -> Vec { let request = __DoThisParams::decode(&mut input) diff --git a/macros/tests/integration_tests.rs b/macros/tests/integration_tests.rs index eaa93540..e6fe46cc 100644 --- a/macros/tests/integration_tests.rs +++ b/macros/tests/integration_tests.rs @@ -21,17 +21,17 @@ #[test] fn gservice_works() { let t = trybuild::TestCases::new(); - t.pass("tests/ui/gservice_works.rs"); + t.pass("tests/ui/gservice_works*.rs"); } #[test] -fn gservice_works_for_lifecycles_and_generics() { +fn gservice_fails() { let t = trybuild::TestCases::new(); - t.pass("tests/ui/gservice_works_for_lifecycles_and_generics.rs"); + t.compile_fail("tests/ui/gservice_fails*.rs"); } #[test] -fn fails() { +fn gprogram_fails() { let t = trybuild::TestCases::new(); - t.compile_fail("tests/ui/*fails*.rs"); + t.compile_fail("tests/ui/gprogram_fails*.rs"); } diff --git a/macros/tests/ui/gservice_works_panic_on_unexpected_input.rs b/macros/tests/ui/gservice_works_panic_on_unexpected_input.rs new file mode 100644 index 00000000..d9b50143 --- /dev/null +++ b/macros/tests/ui/gservice_works_panic_on_unexpected_input.rs @@ -0,0 +1,35 @@ +use fluent_asserter::prelude::*; +use parity_scale_codec::Encode; +use sails_rtl::{ + gstd::{gservice, services::Service}, + MessageId, +}; +use tokio::runtime::Runtime; + +struct MyService; + +#[gservice] +impl MyService { + pub async fn do_this(&mut self, p1: u32, p2: String) -> String { + format!("{p1}: ") + &p2 + } + + pub fn this(&self, p1: bool) -> bool { + !p1 + } +} + +fn main() { + let rt = Runtime::new().unwrap(); + assert_that_code!(|| { + rt.block_on(async { + let input = [0xffu8; 16]; + MyService + .expose(MessageId::from(123), &[1, 2, 3]) + .handle(&input) + .await + }) + }) + .panics() + .with_message("Unknown request: 0xffffffff..ffffffff"); +} diff --git a/macros/tests/ui/gservice_works_panic_on_unexpected_input_double_encoded.rs b/macros/tests/ui/gservice_works_panic_on_unexpected_input_double_encoded.rs new file mode 100644 index 00000000..59321708 --- /dev/null +++ b/macros/tests/ui/gservice_works_panic_on_unexpected_input_double_encoded.rs @@ -0,0 +1,53 @@ +use fluent_asserter::prelude::*; +use parity_scale_codec::Encode; +use sails_rtl::{ + gstd::{gservice, services::Service}, + MessageId, +}; +use tokio::runtime::Runtime; + +struct MyService; + +#[gservice] +impl MyService { + pub async fn do_this(&mut self, p1: u32, p2: String) -> String { + format!("{p1}: ") + &p2 + } + + pub fn this(&self, p1: bool) -> bool { + !p1 + } +} + +fn main() { + let rt = Runtime::new().unwrap(); + assert_that_code!(|| { + rt.block_on(async { + let input = [ + 44, 77, 101, 109, 101, 70, 97, 99, 116, 111, 114, 121, 84, 67, 114, 101, 97, 116, + 101, 70, 117, 110, 103, 105, 98, 108, 101, 80, 114, 111, 103, 114, 97, 109, 32, 77, + 101, 109, 101, 78, 97, 109, 101, 16, 77, 69, 77, 69, 2, 44, 68, 101, 115, 99, 114, + 105, 112, 116, 105, 111, 110, 64, 104, 116, 116, 112, 115, 58, 47, 47, 105, 109, + 103, 46, 99, 111, 109, 47, 1, 76, 104, 116, 116, 112, 58, 47, 47, 101, 120, 97, + 109, 112, 108, 101, 46, 111, 114, 103, 47, 1, 76, 104, 116, 116, 112, 58, 47, 47, + 116, 101, 108, 101, 103, 114, 97, 109, 46, 109, 101, 47, 1, 76, 104, 116, 116, 112, + 58, 47, 47, 116, 119, 105, 116, 116, 101, 114, 46, 99, 111, 109, 47, 1, 72, 104, + 116, 116, 112, 58, 47, 47, 100, 105, 115, 99, 111, 114, 100, 46, 103, 103, 47, 1, + 84, 104, 116, 116, 112, 58, 47, 47, 116, 111, 107, 101, 110, 111, 109, 105, 99, + 115, 46, 103, 103, 47, 232, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 150, 152, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ] + .encode() + .encode(); + + MyService + .expose(MessageId::from(123), &[1, 2, 3]) + .handle(&input) + .await + }) + }) + .panics() + .with_message("Unknown request: 0x81112c00..00000000"); +} From ef0d636095fd799eea8b923dc08093fa7f6c28e7 Mon Sep 17 00:00:00 2001 From: Vadim Obradovich Date: Mon, 20 May 2024 17:32:37 +0300 Subject: [PATCH 02/14] test: macros checks of attribute macros usages (#252) --- macros/core/src/lib.rs | 2 + macros/core/src/program.rs | 35 +++++++++++-- macros/core/src/service.rs | 52 +++++++++++++++++-- macros/core/src/shared.rs | 26 +++++----- macros/core/tests/program.rs | 2 +- macros/core/tests/service.rs | 2 +- .../ui/gprogram_fails_multiple_not_allowed.rs | 20 +++++++ ...gprogram_fails_multiple_not_allowed.stderr | 9 ++++ ..._fails_multiple_not_allowed_on_one_impl.rs | 14 +++++ ...ls_multiple_not_allowed_on_one_impl.stderr | 9 ++++ .../ui/gservice_fails_multiple_not_allowed.rs | 20 +++++++ ...gservice_fails_multiple_not_allowed.stderr | 9 ++++ ..._fails_multiple_not_allowed_on_one_impl.rs | 14 +++++ ...ls_multiple_not_allowed_on_one_impl.stderr | 10 ++++ 14 files changed, 203 insertions(+), 21 deletions(-) create mode 100644 macros/tests/ui/gprogram_fails_multiple_not_allowed.rs create mode 100644 macros/tests/ui/gprogram_fails_multiple_not_allowed.stderr create mode 100644 macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.rs create mode 100644 macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.stderr create mode 100644 macros/tests/ui/gservice_fails_multiple_not_allowed.rs create mode 100644 macros/tests/ui/gservice_fails_multiple_not_allowed.stderr create mode 100644 macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.rs create mode 100644 macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.stderr diff --git a/macros/core/src/lib.rs b/macros/core/src/lib.rs index 1831d639..0dd3e4c2 100644 --- a/macros/core/src/lib.rs +++ b/macros/core/src/lib.rs @@ -18,8 +18,10 @@ //! Implemntation of the procedural macros exposed via the `sails-macros` crate. +pub use program::__gprogram_internal; pub use program::gprogram; pub use route::groute; +pub use service::__gservice_internal; pub use service::gservice; mod program; diff --git a/macros/core/src/program.rs b/macros/core/src/program.rs index edc40707..1ecad21a 100644 --- a/macros/core/src/program.rs +++ b/macros/core/src/program.rs @@ -8,19 +8,46 @@ use proc_macro_error::abort; use quote::quote; use std::collections::BTreeMap; use syn::{ - parse_quote, Ident, ImplItem, ImplItemFn, ItemImpl, Receiver, ReturnType, Type, TypePath, - Visibility, + parse_quote, spanned::Spanned, Ident, ImplItem, ImplItemFn, ItemImpl, Receiver, ReturnType, + Type, TypePath, Visibility, }; +/// Static Span of Program `impl` block +static mut PROGRAM_SPAN: Option = None; + pub fn gprogram(program_impl_tokens: TokenStream2) -> TokenStream2 { - let program_impl = syn::parse2(program_impl_tokens).unwrap_or_else(|err| { + let program_impl = parse_gprogram_impl(program_impl_tokens); + ensure_single_gprogram(&program_impl); + gen_gprogram_impl(program_impl) +} + +#[doc(hidden)] +pub fn __gprogram_internal(program_impl_tokens: TokenStream2) -> TokenStream2 { + let program_impl = parse_gprogram_impl(program_impl_tokens); + gen_gprogram_impl(program_impl) +} + +fn parse_gprogram_impl(program_impl_tokens: TokenStream2) -> ItemImpl { + syn::parse2(program_impl_tokens).unwrap_or_else(|err| { abort!( err.span(), "`gprogram` attribute can be applied to impls only: {}", err ) - }); + }) +} + +fn ensure_single_gprogram(program_impl: &ItemImpl) { + if unsafe { PROGRAM_SPAN }.is_some() { + abort!( + program_impl, + "multiple `gprogram` attributes are not allowed" + ) + } + unsafe { PROGRAM_SPAN = Some(program_impl.span()) }; +} +fn gen_gprogram_impl(program_impl: ItemImpl) -> TokenStream2 { let services_ctors = discover_services_ctors(&program_impl); let mut program_impl = program_impl.clone(); diff --git a/macros/core/src/service.rs b/macros/core/src/service.rs index fc92ad3c..ecf24454 100644 --- a/macros/core/src/service.rs +++ b/macros/core/src/service.rs @@ -29,19 +29,65 @@ use proc_macro_error::abort; use quote::quote; use std::collections::BTreeMap; use syn::{ - GenericArgument, Ident, ImplItemFn, ItemImpl, Path, PathArguments, Type, TypeParamBound, - Visibility, WhereClause, WherePredicate, + spanned::Spanned, GenericArgument, Ident, ImplItemFn, ItemImpl, Path, PathArguments, Type, + TypeParamBound, Visibility, WhereClause, WherePredicate, }; +static mut SERVICE_SPANS: BTreeMap = BTreeMap::new(); + pub fn gservice(service_impl_tokens: TokenStream2) -> TokenStream2 { - let service_impl = syn::parse2(service_impl_tokens).unwrap_or_else(|err| { + let service_impl = parse_gservice_impl(service_impl_tokens); + ensure_single_gservice_on_impl(&service_impl); + ensure_single_gservice_by_name(&service_impl); + gen_gservice_impl(service_impl) +} + +#[doc(hidden)] +pub fn __gservice_internal(service_impl_tokens: TokenStream2) -> TokenStream2 { + let service_impl = parse_gservice_impl(service_impl_tokens); + gen_gservice_impl(service_impl) +} + +fn parse_gservice_impl(service_impl_tokens: TokenStream2) -> ItemImpl { + syn::parse2(service_impl_tokens).unwrap_or_else(|err| { abort!( err.span(), "`gservice` attribute can be applied to impls only: {}", err ) + }) +} + +fn ensure_single_gservice_on_impl(service_impl: &ItemImpl) { + let attr_gservice = service_impl.attrs.iter().find(|attr| { + attr.meta + .path() + .segments + .last() + .map(|s| s.ident == "gservice") + .unwrap_or(false) }); + if attr_gservice.is_some() { + abort!( + service_impl, + "multiple `gservice` attributes on the same impl are not allowed", + ) + } +} + +fn ensure_single_gservice_by_name(service_impl: &ItemImpl) { + let path = shared::impl_type_path(service_impl); + let type_ident = path.path.segments.last().unwrap().ident.to_string(); + if unsafe { SERVICE_SPANS.get(&type_ident) }.is_some() { + abort!( + service_impl, + "multiple `gservice` attributes on a type with the same name are not allowed" + ) + } + unsafe { SERVICE_SPANS.insert(type_ident, service_impl.span()) }; +} +fn gen_gservice_impl(service_impl: ItemImpl) -> TokenStream2 { let (service_type_path, service_type_args, service_type_constraints) = { let service_type = ImplType::new(&service_impl); ( diff --git a/macros/core/src/shared.rs b/macros/core/src/shared.rs index cf592fec..eb0b276a 100644 --- a/macros/core/src/shared.rs +++ b/macros/core/src/shared.rs @@ -17,18 +17,7 @@ pub(crate) struct ImplType<'a> { impl<'a> ImplType<'a> { pub(crate) fn new(item_impl: &'a ItemImpl) -> Self { - let path = { - let item_impl_type = item_impl.self_ty.as_ref(); - if let Type::Path(type_path) = item_impl_type { - type_path - } else { - abort!( - item_impl_type.span(), - "failed to parse impl type: {}", - item_impl_type.to_token_stream() - ) - } - }; + let path = impl_type_path(item_impl); let args = &path.path.segments.last().unwrap().arguments; let constraints = item_impl.generics.where_clause.as_ref(); Self { @@ -51,6 +40,19 @@ impl<'a> ImplType<'a> { } } +pub(crate) fn impl_type_path(item_impl: &ItemImpl) -> &TypePath { + let item_impl_type = item_impl.self_ty.as_ref(); + if let Type::Path(type_path) = item_impl_type { + type_path + } else { + abort!( + item_impl_type, + "failed to parse impl type: {}", + item_impl_type.to_token_stream() + ) + } +} + /// Represents parts of a handler function. #[derive(Clone)] pub(crate) struct Func<'a> { diff --git a/macros/core/tests/program.rs b/macros/core/tests/program.rs index aed40d6b..e1eb5531 100644 --- a/macros/core/tests/program.rs +++ b/macros/core/tests/program.rs @@ -1,5 +1,5 @@ use quote::quote; -use sails_macros_core::gprogram; +use sails_macros_core::__gprogram_internal as gprogram; #[test] fn gprogram_generates_init_for_single_ctor() { diff --git a/macros/core/tests/service.rs b/macros/core/tests/service.rs index a8b008dd..311ef9e7 100644 --- a/macros/core/tests/service.rs +++ b/macros/core/tests/service.rs @@ -1,5 +1,5 @@ use quote::quote; -use sails_macros_core::gservice; +use sails_macros_core::__gservice_internal as gservice; #[test] fn gservice_works() { diff --git a/macros/tests/ui/gprogram_fails_multiple_not_allowed.rs b/macros/tests/ui/gprogram_fails_multiple_not_allowed.rs new file mode 100644 index 00000000..d6c173db --- /dev/null +++ b/macros/tests/ui/gprogram_fails_multiple_not_allowed.rs @@ -0,0 +1,20 @@ +use sails_macros::gprogram; + +struct MyProgram; + +#[gprogram] +impl MyProgram { + pub fn new() -> Self { + Self + } +} + +#[gprogram] +impl MyProgram { + pub fn default() -> Self { + Self + } +} + +#[tokio::main] +async fn main() {} diff --git a/macros/tests/ui/gprogram_fails_multiple_not_allowed.stderr b/macros/tests/ui/gprogram_fails_multiple_not_allowed.stderr new file mode 100644 index 00000000..57f5d184 --- /dev/null +++ b/macros/tests/ui/gprogram_fails_multiple_not_allowed.stderr @@ -0,0 +1,9 @@ +error: multiple `gprogram` attributes are not allowed + --> tests/ui/gprogram_fails_multiple_not_allowed.rs:13:1 + | +13 | / impl MyProgram { +14 | | pub fn default() -> Self { +15 | | Self +16 | | } +17 | | } + | |_^ diff --git a/macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.rs b/macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.rs new file mode 100644 index 00000000..3da07f3c --- /dev/null +++ b/macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.rs @@ -0,0 +1,14 @@ +use sails_macros::gprogram; + +struct MyProgram; + +#[gprogram] +#[gprogram] +impl MyProgram { + pub fn new() -> Self { + Self + } +} + +#[tokio::main] +async fn main() {} diff --git a/macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.stderr b/macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.stderr new file mode 100644 index 00000000..c5df57c3 --- /dev/null +++ b/macros/tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.stderr @@ -0,0 +1,9 @@ +error: multiple `gprogram` attributes are not allowed + --> tests/ui/gprogram_fails_multiple_not_allowed_on_one_impl.rs:7:1 + | +7 | / impl MyProgram { +8 | | pub fn new() -> Self { +9 | | Self +10 | | } +11 | | } + | |_^ diff --git a/macros/tests/ui/gservice_fails_multiple_not_allowed.rs b/macros/tests/ui/gservice_fails_multiple_not_allowed.rs new file mode 100644 index 00000000..f2c694bb --- /dev/null +++ b/macros/tests/ui/gservice_fails_multiple_not_allowed.rs @@ -0,0 +1,20 @@ +use sails_macros::gservice; + +struct MyService; + +#[gservice] +impl MyService { + pub fn this(&self, p1: bool) -> bool { + !p1 + } +} + +#[gservice] +impl MyService { + pub fn this(&self, p1: bool) -> bool { + !p1 + } +} + +#[tokio::main] +async fn main() {} diff --git a/macros/tests/ui/gservice_fails_multiple_not_allowed.stderr b/macros/tests/ui/gservice_fails_multiple_not_allowed.stderr new file mode 100644 index 00000000..3dc047ad --- /dev/null +++ b/macros/tests/ui/gservice_fails_multiple_not_allowed.stderr @@ -0,0 +1,9 @@ +error: multiple `gservice` attributes on a type with the same name are not allowed + --> tests/ui/gservice_fails_multiple_not_allowed.rs:13:1 + | +13 | / impl MyService { +14 | | pub fn this(&self, p1: bool) -> bool { +15 | | !p1 +16 | | } +17 | | } + | |_^ diff --git a/macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.rs b/macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.rs new file mode 100644 index 00000000..fa01b51c --- /dev/null +++ b/macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.rs @@ -0,0 +1,14 @@ +use sails_macros::gservice; + +struct MyService; + +#[gservice] +#[gservice] +impl MyService { + pub fn this(&self, p1: bool) -> bool { + !p1 + } +} + +#[tokio::main] +async fn main() {} diff --git a/macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.stderr b/macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.stderr new file mode 100644 index 00000000..63070016 --- /dev/null +++ b/macros/tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.stderr @@ -0,0 +1,10 @@ +error: multiple `gservice` attributes on the same impl are not allowed + --> tests/ui/gservice_fails_multiple_not_allowed_on_one_impl.rs:6:1 + | +6 | / #[gservice] +7 | | impl MyService { +8 | | pub fn this(&self, p1: bool) -> bool { +9 | | !p1 +10 | | } +11 | | } + | |_^ From 81d7eb3a83692e7be01655274526dc6a378731a9 Mon Sep 17 00:00:00 2001 From: Timofey Date: Mon, 20 May 2024 20:01:52 +0300 Subject: [PATCH 03/14] feat(examples): Add example returning references (#256) --- Cargo.lock | 19 +++++++++++ Cargo.toml | 2 ++ examples/references/README.md | 3 ++ examples/references/app/Cargo.toml | 8 +++++ examples/references/app/src/lib.rs | 44 +++++++++++++++++++++++++ examples/references/wasm/Cargo.toml | 14 ++++++++ examples/references/wasm/build.rs | 15 +++++++++ examples/references/wasm/references.idl | 10 ++++++ examples/references/wasm/src/lib.rs | 14 ++++++++ 9 files changed, 129 insertions(+) create mode 100644 examples/references/README.md create mode 100644 examples/references/app/Cargo.toml create mode 100644 examples/references/app/src/lib.rs create mode 100644 examples/references/wasm/Cargo.toml create mode 100644 examples/references/wasm/build.rs create mode 100644 examples/references/wasm/references.idl create mode 100644 examples/references/wasm/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index c4a54d67..e238fd96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3623,6 +3623,25 @@ dependencies = [ "syn 2.0.63", ] +[[package]] +name = "references" +version = "0.1.0" +dependencies = [ + "gear-wasm-builder", + "gstd", + "references-app", + "sails-idl-gen", + "sails-rtl", +] + +[[package]] +name = "references-app" +version = "0.1.0" +dependencies = [ + "gstd", + "sails-rtl", +] + [[package]] name = "regalloc" version = "0.0.34" diff --git a/Cargo.toml b/Cargo.toml index babe2595..1aef9745 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,8 @@ license = "GPL-3.0" resolver = "2" members = [ "client-gen", + "examples/references/app", + "examples/references/wasm", "examples/no-svcs-prog/app", "examples/no-svcs-prog/wasm", "examples/puppeteer/app", diff --git a/examples/references/README.md b/examples/references/README.md new file mode 100644 index 00000000..178ea5ee --- /dev/null +++ b/examples/references/README.md @@ -0,0 +1,3 @@ +# references + +This program demostrates how to return references instead of owned types diff --git a/examples/references/app/Cargo.toml b/examples/references/app/Cargo.toml new file mode 100644 index 00000000..fe1def0c --- /dev/null +++ b/examples/references/app/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "references-app" +version = "0.1.0" +edition = "2021" + +[dependencies] +gstd = { workspace = true, features = ["debug"] } +sails-rtl.workspace = true diff --git a/examples/references/app/src/lib.rs b/examples/references/app/src/lib.rs new file mode 100644 index 00000000..bb223a9e --- /dev/null +++ b/examples/references/app/src/lib.rs @@ -0,0 +1,44 @@ +#![no_std] + +use core::ptr::addr_of; + +use gstd::prelude::*; +use sails_rtl::gstd::gservice; + +static mut COUNTER: Counter = Counter { count: 0 }; +static mut BYTES: Vec = Vec::new(); + +#[derive(Debug, Encode, Decode, TypeInfo)] +#[codec(crate = sails_rtl::scale_codec)] +#[scale_info(crate = sails_rtl::scale_info)] +pub struct Counter { + count: u32, +} + +#[derive(Default)] +pub struct ReferenceService; + +#[gservice] +impl ReferenceService { + pub const fn new() -> Self { + Self + } + + pub fn baked(&self) -> &'static str { + "Static str!" + } + + pub fn incr(&mut self) -> &'static Counter { + unsafe { + COUNTER.count += 1; + &*addr_of!(COUNTER) + } + } + + pub fn add_byte(&mut self, byte: u8) -> &'static [u8] { + unsafe { + BYTES.push(byte); + &*addr_of!(BYTES) + } + } +} diff --git a/examples/references/wasm/Cargo.toml b/examples/references/wasm/Cargo.toml new file mode 100644 index 00000000..e1a71abc --- /dev/null +++ b/examples/references/wasm/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "references" +version = "0.1.0" +edition = "2021" + +[dependencies] +gstd.workspace = true +sails-rtl.workspace = true +references-app = { path = "../app" } + +[build-dependencies] +gwasm-builder.workspace = true +sails-idl-gen.workspace = true +references-app = { path = "../app" } diff --git a/examples/references/wasm/build.rs b/examples/references/wasm/build.rs new file mode 100644 index 00000000..1360c2c8 --- /dev/null +++ b/examples/references/wasm/build.rs @@ -0,0 +1,15 @@ +use references_app::ReferenceService; +use sails_idl_gen::service; +use std::{env, fs::File, path::PathBuf}; + +fn main() { + gwasm_builder::build(); + + let manifest_dir_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + + let idl_file_path = manifest_dir_path.join("references.idl"); + + let idl_file = File::create(idl_file_path).unwrap(); + + service::generate_idl::(idl_file).unwrap(); +} diff --git a/examples/references/wasm/references.idl b/examples/references/wasm/references.idl new file mode 100644 index 00000000..bcf58e5d --- /dev/null +++ b/examples/references/wasm/references.idl @@ -0,0 +1,10 @@ +type Counter = struct { + count: u32, +}; + +service { + AddByte : (byte: u8) -> vec u8; + Incr : () -> Counter; + query Baked : () -> str; +}; + diff --git a/examples/references/wasm/src/lib.rs b/examples/references/wasm/src/lib.rs new file mode 100644 index 00000000..71ff0ae5 --- /dev/null +++ b/examples/references/wasm/src/lib.rs @@ -0,0 +1,14 @@ +#![no_std] + +use references_app::ReferenceService; +use sails_rtl::gstd::{msg, services::Service}; + +#[gstd::async_main] +async fn main() { + let input_bytes = msg::load_bytes().expect("Failed to read input"); + let output_bytes = ReferenceService::new() + .expose(msg::id().into(), &[1, 2, 3]) + .handle(&input_bytes) + .await; + msg::reply_bytes(output_bytes, 0).expect("Failed to send output"); +} From b4870dd76a2b7708c5e8f5ee27bc71b06e3ccd44 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:08:10 +0400 Subject: [PATCH 04/14] build(deps): Bump commander from 12.0.0 to 12.1.0 in /js (#278) --- js/package.json | 2 +- js/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/package.json b/js/package.json index 3598d98e..b4c2896c 100644 --- a/js/package.json +++ b/js/package.json @@ -61,6 +61,6 @@ "typescript": "5.4.5" }, "dependencies": { - "commander": "12.0.0" + "commander": "12.1.0" } } diff --git a/js/yarn.lock b/js/yarn.lock index 4ae05f9c..270d6161 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -1553,10 +1553,10 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -commander@12.0.0: - version "12.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.0.0.tgz#b929db6df8546080adfd004ab215ed48cf6f2592" - integrity sha512-MwVNWlYjDTtOjX5PiD7o5pK0UrFU/OYgcJfjjK4RaHZETNtjJqrZa9Y9ds88+A+f+d5lv+561eZ+yCKoS3gbAA== +commander@12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== commondir@^1.0.1: version "1.0.1" From e57d37427e5dd7a5076a743596faeacda18d06ed Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:08:34 +0400 Subject: [PATCH 05/14] build(deps-dev): Bump @types/node from 20.12.10 to 20.12.12 in /js (#277) --- js/package.json | 2 +- js/yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/package.json b/js/package.json index b4c2896c..9bba2b43 100644 --- a/js/package.json +++ b/js/package.json @@ -50,7 +50,7 @@ "@rollup/plugin-node-resolve": "15.2.3", "@rollup/plugin-typescript": "11.1.6", "@types/jest": "29.5.12", - "@types/node": "20.12.10", + "@types/node": "20.12.12", "babel-jest": "29.7.0", "jest": "29.7.0", "rollup": "4.17.2", diff --git a/js/yarn.lock b/js/yarn.lock index 270d6161..152af40c 100644 --- a/js/yarn.lock +++ b/js/yarn.lock @@ -1242,10 +1242,10 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/node@*", "@types/node@20.12.10": - version "20.12.10" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.10.tgz#8f0c3f12b0f075eee1fe20c1afb417e9765bef76" - integrity sha512-Eem5pH9pmWBHoGAT8Dr5fdc5rYA+4NAovdM4EktRPVAAiJhmWWfQrA0cFhAbOsQdSfIHjAud6YdkbL69+zSKjw== +"@types/node@*", "@types/node@20.12.12": + version "20.12.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" + integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== dependencies: undici-types "~5.26.4" From 6e795dd664761c9a6aedb409941d4b2caa0e6a78 Mon Sep 17 00:00:00 2001 From: Vadim Obradovich Date: Tue, 21 May 2024 15:38:09 +0300 Subject: [PATCH 06/14] fix(macros): rustc complains about unused fields in __NewParams, allow dead_code on generated struct (#259) --- macros/core/src/program.rs | 1 + ...ram_generates_init_for_multiple_ctors.snap | 2 + ...rogram_generates_init_for_single_ctor.snap | 1 + macros/tests/integration_tests.rs | 6 +++ macros/tests/ui/gprogram_works.rs | 39 +++++++++++++++++++ 5 files changed, 49 insertions(+) create mode 100644 macros/tests/ui/gprogram_works.rs diff --git a/macros/core/src/program.rs b/macros/core/src/program.rs index 1ecad21a..1c737a92 100644 --- a/macros/core/src/program.rs +++ b/macros/core/src/program.rs @@ -140,6 +140,7 @@ fn gen_gprogram_impl(program_impl: ItemImpl) -> TokenStream2 { #[derive(__ProgramDecode, __ProgramTypeInfo)] #[codec(crate = #scale_codec_path )] #[scale_info(crate = #scale_info_path )] + #[allow(dead_code)] #ctors_params_structs )* diff --git a/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap b/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap index 83dcfc49..63a95613 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_init_for_multiple_ctors.snap @@ -25,6 +25,7 @@ use sails_rtl::TypeInfo as __ProgramTypeInfo; #[derive(__ProgramDecode, __ProgramTypeInfo)] #[codec(crate = sails_rtl::scale_codec)] #[scale_info(crate = sails_rtl::scale_info)] +#[allow(dead_code)] struct __NewParams { p1: u32, p2: String, @@ -32,6 +33,7 @@ struct __NewParams { #[derive(__ProgramDecode, __ProgramTypeInfo)] #[codec(crate = sails_rtl::scale_codec)] #[scale_info(crate = sails_rtl::scale_info)] +#[allow(dead_code)] struct __New2Params { p2: String, p1: u32, diff --git a/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap b/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap index 25160d72..90bf5923 100644 --- a/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap +++ b/macros/core/tests/snapshots/program__gprogram_generates_init_for_single_ctor.snap @@ -22,6 +22,7 @@ use sails_rtl::TypeInfo as __ProgramTypeInfo; #[derive(__ProgramDecode, __ProgramTypeInfo)] #[codec(crate = sails_rtl::scale_codec)] #[scale_info(crate = sails_rtl::scale_info)] +#[allow(dead_code)] struct __NewParams { p1: u32, p2: String, diff --git a/macros/tests/integration_tests.rs b/macros/tests/integration_tests.rs index e6fe46cc..55659f1d 100644 --- a/macros/tests/integration_tests.rs +++ b/macros/tests/integration_tests.rs @@ -35,3 +35,9 @@ fn gprogram_fails() { let t = trybuild::TestCases::new(); t.compile_fail("tests/ui/gprogram_fails*.rs"); } + +#[test] +fn gprogram_works() { + let t = trybuild::TestCases::new(); + t.pass("tests/ui/gprogram_works*.rs"); +} diff --git a/macros/tests/ui/gprogram_works.rs b/macros/tests/ui/gprogram_works.rs new file mode 100644 index 00000000..57b00318 --- /dev/null +++ b/macros/tests/ui/gprogram_works.rs @@ -0,0 +1,39 @@ +use sails_macros::gprogram; + +struct MyProgram; + +#[gprogram] +impl MyProgram { + pub fn new(config: u32) -> Self { + let _config = config; + Self + } + + pub fn service1(&self) -> svc::MyService { + svc::MyService + } +} + +pub mod svc { + #![allow(dead_code)] + + use sails_macros::gservice; + + pub struct MyService; + + #[gservice] + impl MyService { + pub async fn do_this(&mut self, p1: u32, p2: String) -> String { + format!("{p1}: ") + &p2 + } + + pub fn this(&self, p1: bool) -> bool { + !p1 + } + } +} + +#[tokio::main] +async fn main() { + let _prg = MyProgram::new(42); +} From d429ea0c9d6e07fd217f3a2ffa2685eda12ab24f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:38:39 +0100 Subject: [PATCH 07/14] --- (#276) updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e238fd96..da3ddd7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "array-bytes" From 8cd2a5d010ef91202b82075d30e0f544dea47add Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:39:15 +0100 Subject: [PATCH 08/14] --- (#275) updated-dependencies: - dependency-name: insta dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index da3ddd7b..5a149ba3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2383,9 +2383,9 @@ checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" [[package]] name = "insta" -version = "1.38.0" +version = "1.39.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eab73f58e59ca6526037208f0e98851159ec1633cf17b6cd2e1f2c3fd5d53cc" +checksum = "810ae6042d48e2c9e9215043563a58a80b877bc863228a74cf10c49d4620a6f5" dependencies = [ "console", "lazy_static", diff --git a/Cargo.toml b/Cargo.toml index 1aef9745..0a1c9157 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,7 +41,7 @@ gwasm-builder = { package = "gear-wasm-builder", version = "1.4.1" } handlebars = "4.4" hashbrown = "0.14" hex = { version = "0.4", default-features = false } -insta = "1.38" +insta = "1.39" itertools = "0.12" lalrpop = { version = "0.20", default-features = false } lalrpop-util = "0.20" From 9d3ef5c6332ec4082c6a7bb567f31cd4b739d59d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:39:51 +0100 Subject: [PATCH 09/14] --- (#274) updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5a149ba3..4aaccd97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4077,9 +4077,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] @@ -4095,9 +4095,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", From cc48251a526b1db294088975a313612179a24c25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:40:14 +0100 Subject: [PATCH 10/14] --- (#273) updated-dependencies: - dependency-name: syn dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 78 +++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4aaccd97..e8860542 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -164,7 +164,7 @@ checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -874,7 +874,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -885,7 +885,7 @@ checksum = "1d1545d67a2149e1d93b7e5c7752dce5a7426eb5d1357ddcfd89336b94444f77" dependencies = [ "darling_core", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1178,7 +1178,7 @@ checksum = "03cdc46ec28bd728e67540c528013c6a10eb69a02eb31078a1bda695438cbfb8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1199,7 +1199,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1253,7 +1253,7 @@ dependencies = [ "fs-err", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1401,7 +1401,7 @@ dependencies = [ "proc-macro-warning", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1414,7 +1414,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1425,7 +1425,7 @@ checksum = "0c3562da4b7b8e24189036c58d459b260e10c8b7af2dd180b7869ae29bb66277" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1520,7 +1520,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -1604,7 +1604,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4952f29b83939ab19c2ed52afc219776d0dc43541864d607e869c5af85a52f3b" dependencies = [ "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2021,7 +2021,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2081,7 +2081,7 @@ dependencies = [ "hex", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2680,7 +2680,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.6.29", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2740,7 +2740,7 @@ dependencies = [ "macro_magic_core", "macro_magic_macros", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2754,7 +2754,7 @@ dependencies = [ "macro_magic_core_macros", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2765,7 +2765,7 @@ checksum = "d710e1214dffbab3b5dacb21475dde7d6ed84c69ff722b3a47a782668d44fbac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -2776,7 +2776,7 @@ checksum = "b8fb85ec1620619edf2984a7693497d4ec88a9665d8b87e942856884c92dbf2a" dependencies = [ "macro_magic_core", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3058,7 +3058,7 @@ checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3273,7 +3273,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3347,7 +3347,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3414,7 +3414,7 @@ checksum = "3d1eaa7fa0aa1929ffdf7eeb6eac234dde6268914a14ad44d23521ab6a9b258e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3620,7 +3620,7 @@ checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -3929,7 +3929,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4101,7 +4101,7 @@ checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4281,7 +4281,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4381,7 +4381,7 @@ checksum = "8dc707d9f5bf155d584900783e328cb3dc79c950f898a18a8f24066f41f040a5" dependencies = [ "quote", "sp-core-hashing", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4392,7 +4392,7 @@ checksum = "f12dae7cf6c1e825d13ffd4ce16bd9309db7c539929d0302b4443ed451a9f4e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4536,7 +4536,7 @@ dependencies = [ "proc-macro-crate 1.3.1", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4679,7 +4679,7 @@ dependencies = [ "parity-scale-codec", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -4817,9 +4817,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.63" +version = "2.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +checksum = "d2863d96a84c6439701d7a38f9de935ec562c8832cc55d1dde0f513b52fad106" dependencies = [ "proc-macro2", "quote", @@ -4906,7 +4906,7 @@ checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -5009,7 +5009,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -5088,7 +5088,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -5342,7 +5342,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", "wasm-bindgen-shared", ] @@ -5364,7 +5364,7 @@ checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6203,7 +6203,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] [[package]] @@ -6223,5 +6223,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.63", + "syn 2.0.65", ] From fe8e795493fd5a4d9648d322c3ac720b3e7b3edd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 21 May 2024 13:40:35 +0100 Subject: [PATCH 11/14] --- (#272) updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e8860542..1b30fb98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4891,18 +4891,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", From cb2b8f210f1366fb5bda42a1969e94c698cd720b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 20:07:06 +0100 Subject: [PATCH 12/14] --- (#279) updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b30fb98..6e5dada1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3419,9 +3419,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] From 04e8c304a54e8cf0a9ac6f0af3d78dc4757b0847 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 22 May 2024 20:07:26 +0100 Subject: [PATCH 13/14] --- (#280) updated-dependencies: - dependency-name: trybuild dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6e5dada1..545bae76 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5168,9 +5168,9 @@ dependencies = [ [[package]] name = "trybuild" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ddb747392ea12569d501a5bbca08852e4c8cd88b92566074b2243b8846f09e6" +checksum = "33a5f13f11071020bb12de7a16b925d2d58636175c20c11dc5f96cb64bb6c9b3" dependencies = [ "glob", "serde", From fbe22b4d91122ced4d219293032c71f175a1a601 Mon Sep 17 00:00:00 2001 From: Dmitryii Osipov Date: Thu, 23 May 2024 16:50:46 +0400 Subject: [PATCH 14/14] feat(js): support vouchers in transaction builder (#258) --- .github/workflows/ci-js.yml | 6 ++- .gitignore | 1 + Cargo.lock | 17 ++++++++ Cargo.toml | 2 + examples/ping/README.md | 3 ++ examples/ping/app/Cargo.toml | 7 ++++ examples/ping/app/src/lib.rs | 20 ++++++++++ examples/ping/app/src/service.rs | 19 +++++++++ examples/ping/wasm/Cargo.toml | 13 +++++++ examples/ping/wasm/build.rs | 15 +++++++ examples/ping/wasm/ping.idl | 8 ++++ examples/ping/wasm/src/lib.rs | 4 ++ js/jest.config.ts | 2 +- js/src/transaction-builder.ts | 21 +++++++++- js/test/modify-import.js | 2 +- js/test/ping.test.ts | 67 ++++++++++++++++++++++++++++++++ js/test/rmrk-catalog.test.ts | 13 ++++--- js/test/rmrk-resource.test.ts | 2 +- 18 files changed, 211 insertions(+), 11 deletions(-) create mode 100644 examples/ping/README.md create mode 100644 examples/ping/app/Cargo.toml create mode 100644 examples/ping/app/src/lib.rs create mode 100644 examples/ping/app/src/service.rs create mode 100644 examples/ping/wasm/Cargo.toml create mode 100644 examples/ping/wasm/build.rs create mode 100644 examples/ping/wasm/ping.idl create mode 100644 examples/ping/wasm/src/lib.rs create mode 100644 js/test/ping.test.ts diff --git a/.github/workflows/ci-js.yml b/.github/workflows/ci-js.yml index baaebd9b..65f87e6b 100644 --- a/.github/workflows/ci-js.yml +++ b/.github/workflows/ci-js.yml @@ -54,14 +54,16 @@ jobs: - name: "Prepare: build rmrk" run: | - cargo build --manifest-path=examples/rmrk/catalog/wasm/Cargo.toml - cargo build --manifest-path=examples/rmrk/resource/wasm/Cargo.toml + cargo build --manifest-path=examples/rmrk/catalog/wasm/Cargo.toml --release + cargo build --manifest-path=examples/rmrk/resource/wasm/Cargo.toml --release + cargo build --manifest-path=examples/ping/wasm/Cargo.toml --release - name: "Prepare: build rmrk client lib" working-directory: js run: | node lib/app.js generate ../examples/rmrk/catalog/wasm/rmrk-catalog.idl -o ./test/rmrk-catalog node lib/app.js generate ../examples/rmrk/resource/wasm/rmrk-resource.idl -o ./test/rmrk-resource + node lib/app.js generate ../examples/ping/wasm/ping.idl -o ./test/ping - name: "Prepare: download Gear node" run: | diff --git a/.gitignore b/.gitignore index f40e082d..85a97bc1 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ js/lib/ js/parser.wasm js/test/rmrk-*/ +js/test/ping/ node_modules/ target/ diff --git a/Cargo.lock b/Cargo.lock index 545bae76..e6594df7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3318,6 +3318,23 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "ping" +version = "0.1.0" +dependencies = [ + "gear-wasm-builder", + "ping-app", + "sails-idl-gen", + "sails-rtl", +] + +[[package]] +name = "ping-app" +version = "0.1.0" +dependencies = [ + "sails-rtl", +] + [[package]] name = "pkcs8" version = "0.10.2" diff --git a/Cargo.toml b/Cargo.toml index 0a1c9157..25aad541 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ members = [ "examples/references/wasm", "examples/no-svcs-prog/app", "examples/no-svcs-prog/wasm", + "examples/ping/app", + "examples/ping/wasm", "examples/puppeteer/app", "examples/puppeteer/wasm", "examples/rmrk/catalog/app", diff --git a/examples/ping/README.md b/examples/ping/README.md new file mode 100644 index 00000000..3e774330 --- /dev/null +++ b/examples/ping/README.md @@ -0,0 +1,3 @@ +# simple ping example + + diff --git a/examples/ping/app/Cargo.toml b/examples/ping/app/Cargo.toml new file mode 100644 index 00000000..2f4a81d0 --- /dev/null +++ b/examples/ping/app/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "ping-app" +version = "0.1.0" +edition = "2021" + +[dependencies] +sails-rtl.workspace = true diff --git a/examples/ping/app/src/lib.rs b/examples/ping/app/src/lib.rs new file mode 100644 index 00000000..edc864d2 --- /dev/null +++ b/examples/ping/app/src/lib.rs @@ -0,0 +1,20 @@ +#![no_std] + +use sails_rtl::gstd::gprogram; +use service::PingService; + +pub mod service; + +#[derive(Default)] +pub struct Program; + +#[gprogram] +impl Program { + pub fn new() -> Self { + Self + } + + pub fn ping(&self) -> service::PingService { + PingService::new() + } +} diff --git a/examples/ping/app/src/service.rs b/examples/ping/app/src/service.rs new file mode 100644 index 00000000..7d42493b --- /dev/null +++ b/examples/ping/app/src/service.rs @@ -0,0 +1,19 @@ +use sails_rtl::{gstd::gservice, prelude::*}; + +#[derive(Default)] +pub struct PingService {} + +#[gservice] +impl PingService { + pub fn new() -> Self { + Self {} + } + + pub fn ping(&mut self, input: String) -> Result { + if input != "ping" { + Err("Invalid input".into()) + } else { + Ok("pong".into()) + } + } +} diff --git a/examples/ping/wasm/Cargo.toml b/examples/ping/wasm/Cargo.toml new file mode 100644 index 00000000..67cf85d1 --- /dev/null +++ b/examples/ping/wasm/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "ping" +version = "0.1.0" +edition = "2021" + +[dependencies] +ping-app = { path = "../app" } +sails-rtl.workspace = true + +[build-dependencies] +gwasm-builder.workspace = true +ping-app = { path = "../app" } +sails-idl-gen.workspace = true diff --git a/examples/ping/wasm/build.rs b/examples/ping/wasm/build.rs new file mode 100644 index 00000000..4e2fde89 --- /dev/null +++ b/examples/ping/wasm/build.rs @@ -0,0 +1,15 @@ +use ping_app::Program; +use sails_idl_gen::program; +use std::{env, fs::File, path::PathBuf}; + +fn main() { + gwasm_builder::build(); + + let manifest_dir_path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()); + + let idl_file_path = manifest_dir_path.join("ping.idl"); + + let idl_file = File::create(idl_file_path).unwrap(); + + program::generate_idl::(idl_file).unwrap(); +} diff --git a/examples/ping/wasm/ping.idl b/examples/ping/wasm/ping.idl new file mode 100644 index 00000000..9952a2b7 --- /dev/null +++ b/examples/ping/wasm/ping.idl @@ -0,0 +1,8 @@ +constructor { + New : (); +}; + +service Ping { + Ping : (input: str) -> result (str, str); +}; + diff --git a/examples/ping/wasm/src/lib.rs b/examples/ping/wasm/src/lib.rs new file mode 100644 index 00000000..438939cd --- /dev/null +++ b/examples/ping/wasm/src/lib.rs @@ -0,0 +1,4 @@ +#![no_std] + +#[cfg(target_arch = "wasm32")] +pub use ping_app::wasm::*; diff --git a/js/jest.config.ts b/js/jest.config.ts index f0ad190e..27e1bed2 100644 --- a/js/jest.config.ts +++ b/js/jest.config.ts @@ -14,7 +14,7 @@ const config: Config.InitialOptions = { transform: { '^.+\\.tsx?$': ['ts-jest', { useESM: true }], }, - testTimeout: 30000, + testTimeout: 15_000, }; export default config; diff --git a/js/src/transaction-builder.ts b/js/src/transaction-builder.ts index b98cfd4b..7b60a922 100644 --- a/js/src/transaction-builder.ts +++ b/js/src/transaction-builder.ts @@ -1,4 +1,4 @@ -import { GearApi, HexString, MessageQueuedData, decodeAddress } from '@gear-js/api'; +import { GearApi, HexString, ICallOptions, MessageQueuedData, decodeAddress } from '@gear-js/api'; import { SignerOptions, SubmittableExtrinsic } from '@polkadot/api/types'; import { IKeyringPair, ISubmittableResult } from '@polkadot/types/types'; import { TypeRegistry, u128, u64 } from '@polkadot/types'; @@ -15,6 +15,7 @@ export class TransactionBuilder { private _account: string | IKeyringPair; private _signerOptions: Partial; private _tx: SubmittableExtrinsic<'promise', ISubmittableResult>; + private _voucher: string; public readonly programId: HexString; constructor( @@ -235,10 +236,28 @@ export class TransactionBuilder { return this; } + /** + * ## Use voucher for transaction + * @param id Voucher id + */ + public withVoucher(id: HexString) { + if (this._tx.method.method !== 'sendMessage') { + throw new Error('Voucher can be used only with sendMessage extrinsics'); + } + + this._voucher = id; + return this; + } + /** * ## Sign and send transaction */ public async signAndSend(): Promise> { + if (this._voucher) { + const callParams: ICallOptions = { SendMessage: this._tx }; + this._tx = this._api.voucher.call(this._voucher, callParams); + } + const { msgId, blockHash } = await new Promise<{ msgId: HexString; blockHash: HexString }>((resolve, reject) => this._tx .signAndSend(this._account, this._signerOptions, ({ events, status }) => { diff --git a/js/test/modify-import.js b/js/test/modify-import.js index 64339b9d..ed8738bf 100644 --- a/js/test/modify-import.js +++ b/js/test/modify-import.js @@ -1,6 +1,6 @@ import * as fs from 'fs'; -const filesToModify = ['test/rmrk-catalog/lib.ts', 'test/rmrk-resource/lib.ts']; +const filesToModify = ['test/rmrk-catalog/lib.ts', 'test/rmrk-resource/lib.ts', 'test/ping/lib.ts']; for (const path of filesToModify) { const data = fs.readFileSync(path, 'utf8').replace(`from 'sails-js'`, `from '../../lib/index.js'`); diff --git a/js/test/ping.test.ts b/js/test/ping.test.ts new file mode 100644 index 00000000..c06ba5d0 --- /dev/null +++ b/js/test/ping.test.ts @@ -0,0 +1,67 @@ +import { GearApi, HexString, MessageQueued, VoucherIssued, decodeAddress } from '@gear-js/api'; +import { KeyringPair } from '@polkadot/keyring/types'; +import { waitReady } from '@polkadot/wasm-crypto'; +import { Keyring } from '@polkadot/api'; +import { readFileSync } from 'fs'; + +import { Sails } from '../lib'; +import { Program } from './ping/lib'; + +let sails: Sails; +let api: GearApi; +let alice: KeyringPair; +let aliceRaw: HexString; +let charlie: KeyringPair; +let charlieRaw: HexString; +let code: Buffer; + +const CATALOG_WASM_PATH = '../target/wasm32-unknown-unknown/release/ping.opt.wasm'; + +beforeAll(async () => { + sails = await Sails.new(); + api = await GearApi.create({ providerAddress: 'ws://127.0.0.1:9944' }); + await waitReady(); + const keyring = new Keyring({ type: 'sr25519' }); + alice = keyring.addFromUri('//Alice'); + aliceRaw = decodeAddress(alice.address); + charlie = keyring.addFromUri('//Charlie'); + charlieRaw = decodeAddress(charlie.address); + code = readFileSync(CATALOG_WASM_PATH); +}); + +afterAll(async () => { + await api.disconnect(); + await new Promise((resolve) => { + setTimeout(resolve, 2000); + }); +}); + +describe('Ping', () => { + let program: Program; + + test('create program', async () => { + program = new Program(api); + + const transaction = await program.newCtorFromCode(code).withAccount(alice).calculateGas(); + + const { msgId, blockHash, response } = await transaction.signAndSend(); + + expect(msgId).toBeDefined(); + expect(blockHash).toBeDefined(); + + await response(); + }); + + test('ping', async () => { + const transaction = await program.ping.ping('ping').withAccount(alice).calculateGas(); + + const { msgId, blockHash, response } = await transaction.signAndSend(); + + expect(msgId).toBeDefined(); + expect(blockHash).toBeDefined(); + + const result = await response(); + + expect(result).toHaveProperty('ok', 'pong'); + }); +}); diff --git a/js/test/rmrk-catalog.test.ts b/js/test/rmrk-catalog.test.ts index f7b44759..7778d99a 100644 --- a/js/test/rmrk-catalog.test.ts +++ b/js/test/rmrk-catalog.test.ts @@ -1,4 +1,4 @@ -import { GearApi, HexString, MessageQueued, decodeAddress } from '@gear-js/api'; +import { GearApi, HexString, decodeAddress } from '@gear-js/api'; import { KeyringPair } from '@polkadot/keyring/types'; import { waitReady } from '@polkadot/wasm-crypto'; import { Keyring } from '@polkadot/api'; @@ -14,13 +14,14 @@ let aliceRaw: HexString; let code: Buffer; const IDL_PATH = '../examples/rmrk/catalog/wasm/rmrk-catalog.idl'; -const CATALOG_WASM_PATH = '../target/wasm32-unknown-unknown/debug/rmrk_catalog.opt.wasm'; +const CATALOG_WASM_PATH = '../target/wasm32-unknown-unknown/release/rmrk_catalog.opt.wasm'; beforeAll(async () => { sails = await Sails.new(); api = await GearApi.create({ providerAddress: 'ws://127.0.0.1:9944' }); await waitReady(); - alice = new Keyring().addFromUri('//Alice', {}, 'sr25519'); + const keyring = new Keyring({ type: 'sr25519' }); + alice = keyring.addFromUri('//Alice'); aliceRaw = decodeAddress(alice.address); code = readFileSync(CATALOG_WASM_PATH); }); @@ -40,7 +41,9 @@ describe('RMRK catalog', () => { test('upload catalog', async () => { sails.setApi(api); - const transaction = await sails.ctors.New.fromCode(code).withAccount(alice).calculateGas(); + const transaction = await sails.ctors.New.fromCode(code) + .withAccount(alice) + .withGas(api.blockGasLimit.toBigInt() / 2n); const { response } = await transaction.signAndSend(); await response(); }); @@ -170,7 +173,7 @@ describe('RMRK generated', () => { test('add equippables', async () => { expect(programCreated).toBeTruthy(); expect(program).toBeDefined(); - const transaction = await program.rmrkCatalog.addEquippables(3, [aliceRaw]); + const transaction = program.rmrkCatalog.addEquippables(3, [aliceRaw]); await transaction.withAccount(alice).calculateGas(); diff --git a/js/test/rmrk-resource.test.ts b/js/test/rmrk-resource.test.ts index c7af6def..4d7e57ca 100644 --- a/js/test/rmrk-resource.test.ts +++ b/js/test/rmrk-resource.test.ts @@ -15,7 +15,7 @@ let code: Buffer; let resourceId: HexString; const IDL_PATH = '../examples/rmrk/resource/wasm/rmrk-resource.idl'; -const RESOURCE_WASM_PATH = '../target/wasm32-unknown-unknown/debug/rmrk_resource.opt.wasm'; +const RESOURCE_WASM_PATH = '../target/wasm32-unknown-unknown/release/rmrk_resource.opt.wasm'; beforeAll(async () => { sails = await Sails.new();