diff --git a/rs/macros/core/src/service/mod.rs b/rs/macros/core/src/service/mod.rs index e7aebb3f..09295b20 100644 --- a/rs/macros/core/src/service/mod.rs +++ b/rs/macros/core/src/service/mod.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . //! Supporting functions and structures for the `gservice` macro. - +#![allow(unused_variables)] // temporary use crate::{ sails_paths, shared::{self, Func}, @@ -27,10 +27,10 @@ use convert_case::{Case, Casing}; use parity_scale_codec::Encode; use proc_macro2::{Span, TokenStream}; use proc_macro_error::abort; -use quote::quote; +use quote::{format_ident, quote}; use std::collections::BTreeMap; use syn::{ - parse_quote, punctuated::Punctuated, spanned::Spanned, token::Comma, Ident, ImplItemFn, + parse_quote, punctuated::Punctuated, spanned::Spanned, token::Comma, Ident, ImplItemFn, Index, ItemImpl, Lifetime, Path, Type, Visibility, }; @@ -305,77 +305,153 @@ fn generate_gservice(args: TokenStream, service_impl: ItemImpl) -> TokenStream { .iter() .filter(|attr| matches!(attr.path().get_ident(), Some(ident) if ident == "allow")); - quote!( - #service_impl + // V2 + let trait_ident = format_ident!("{}ImplTrait", service_ident); - pub struct #exposure_type_path<#exposure_generic_args> { - #message_id_ident : #sails_path::MessageId, - #route_ident : &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - #inner_ident : Box, // Ensure service is not movable - #[cfg(not(target_arch = "wasm32"))] - #inner_ptr_ident : *const T, // Prevent exposure being Send + Sync - #[cfg(target_arch = "wasm32")] - #inner_ident : T, - #( #base_exposures_members )* - } + let mut trait_funcs = Vec::with_capacity(service_handlers.len()); + let mut trait_funcs_impl = Vec::with_capacity(service_handlers.len()); + let mut invocation_dispatches = Vec::with_capacity(service_handlers.len()); + for (handler_route, (handler_fn, ..)) in &service_handlers { + let handler_allow_attrs = handler_fn + .attrs + .iter() + .filter(|attr| attr.path().is_ident("allow")); + let handler_docs_attrs = handler_fn + .attrs + .iter() + .filter(|attr| attr.path().is_ident("doc")); - #exposure_drop_code + let handler_sig = &handler_fn.sig; + let handler_func = Func::from(handler_sig); - #( #exposure_allow_attrs )* - impl #generics #exposure_type_path< #exposure_args > #service_type_constraints { - #( #exposure_funcs )* + trait_funcs.push(quote! { + #handler_sig; + }); - #( #base_exposure_accessors )* + let handler_ident = handler_func.ident(); + let handler_params = handler_func.params().iter().map(|item| item.0); + let handler_await_token = handler_func.is_async().then(|| quote!(.await)); + trait_funcs_impl.push({ + quote!( + #( #handler_allow_attrs )* + #handler_sig { + let exposure_scope = #sails_path::gstd::services::ExposureCallScope::new2(self); + self. #inner_ident . #handler_ident (#(#handler_params),*) #handler_await_token + } + ) + }); - pub async fn handle(&mut self, #input_ident: &[u8]) -> (Vec, u128) { - self.try_handle( #input_ident ).await.unwrap_or_else(|| { - #unexpected_route_panic - }) - } + let handler_generator = HandlerGenerator::from(handler_func.clone()); + let invocation_func = handler_generator.invocation_func_v2(&meta_module_ident, &sails_path); - pub async fn try_handle(&mut self, #input_ident : &[u8]) -> Option<(Vec, u128)> { - #( #invocation_dispatches )* - #( #base_exposures_invocations )* - None - } + invocation_dispatches.push({ + quote!( + #handler_route => { + #invocation_func + Some((#sails_path::Encode::encode(&(#handler_route, &result)), value)) + } + ) + }); + } + + let mut exposure_lifetimes: Punctuated = Punctuated::new(); + for lt in lifetimes.iter().map(|lt| { + let lt = format!("'{lt}"); + Lifetime::new(<, Span::call_site()) + }) { + exposure_lifetimes.push(lt); + } + let trait_lifetimes = if !exposure_lifetimes.is_empty() { + quote! { < #exposure_lifetimes> } + } else { + quote! {} + }; + + // base v2 + let single_base_type = service_args.base_types().len() == 1; + + let mut base_expo_types = Vec::with_capacity(service_args.base_types().len()); + let mut base_types_funcs = Vec::with_capacity(service_args.base_types().len()); + let mut base_types_impl = Vec::with_capacity(service_args.base_types().len()); + let mut base_exposure_instantiation = Vec::with_capacity(service_args.base_types().len()); + + service_args.base_types().iter() + .enumerate() + .for_each(|(idx, base_type)| { + let as_base_ident = format_ident!("as_base_{}", idx); + let base_expo_type = quote! { #sails_path::gstd::services::ServiceExposure< #base_type, () > }; + + base_expo_types.push(quote! { + #base_expo_type + }); + + base_types_funcs.push(quote!{ + fn #as_base_ident (&self) -> & #base_expo_type; + }); + + let extend_ref = if single_base_type { + quote! { &self.extend } + } else { + let base_idx = Index::from(idx); + quote! { &self.extend.#base_idx } + }; + + base_types_impl.push(quote!{ + fn #as_base_ident (&self) -> & #base_expo_type { + #extend_ref + } + }); + + base_exposure_instantiation.push(quote!( + < #base_type as Clone>::clone(AsRef::< #base_type >::as_ref( &self )).expose( #message_id_ident , #route_ident ) + )); + }); + + let base_type = if single_base_type { + let single_type = &base_expo_types[0]; + quote! { #single_type } + } else { + quote! { ( #( #base_expo_types ),* ) } + }; + let base_inst: TokenStream = quote! { ( #( #base_exposure_instantiation ),* ) }; - #( #invocation_funcs )* + let expo_type = + quote! { #sails_path::gstd::services::ServiceExposure< #service_type_path, #base_type > }; - #exposure_set_event_listener_code + quote!( + #service_impl + + #[allow(async_fn_in_trait)] + pub trait #trait_ident #trait_lifetimes { + #( #trait_funcs )* + + #( #base_types_funcs )* } - impl #generics #sails_path::gstd::services::Exposure for #exposure_type_path< #exposure_args > #service_type_constraints { - fn message_id(&self) -> #sails_path::MessageId { - self. #message_id_ident - } + impl #generics #trait_ident #trait_lifetimes for #expo_type #service_type_constraints { + #( #trait_funcs_impl )* + + #( #base_types_impl )* + } - fn route(&self) -> &'static [u8] { - self. #route_ident + impl #generics #sails_path::gstd::services::ServiceHandle for #service_type_path #service_type_constraints { + async fn try_handle(&mut self, #input_ident : &[u8]) -> Option<(Vec, u128)> { + let mut __input = #input_ident; + let route: String = #sails_path::Decode::decode(&mut __input).ok()?; + match route.as_str() { + #( #invocation_dispatches )* + _ => None, + } } } impl #generics #sails_path::gstd::services::Service for #service_type_path #service_type_constraints { - type Exposure = #exposure_type_path< #exposure_args >; + type Exposure = #expo_type; + type Extend = #base_type; fn expose(self, #message_id_ident : #sails_path::MessageId, #route_ident : &'static [u8]) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let #inner_ident = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let #inner_ident = &self; - Self::Exposure { - #message_id_ident , - #route_ident , - #( #base_exposures_instantiations )* - #[cfg(not(target_arch = "wasm32"))] - #inner_ptr_ident : inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - #inner_ident : inner_box , - #[cfg(target_arch = "wasm32")] - #inner_ident : self, - } + let extend = #base_inst; + Self::Exposure::new(#message_id_ident, #route_ident, self, extend) } } @@ -588,4 +664,32 @@ impl<'a> HandlerGenerator<'a> { } ) } + + fn invocation_func_v2(&self, meta_module_ident: &Ident, sails_path: &Path) -> TokenStream { + let params_struct_ident = self.params_struct_ident(); + let handler_func_ident = self.handler_func_ident(); + let handler_func_params = self.handler.params().iter().map(|item| { + let param_ident = item.0; + quote!(request.#param_ident) + }); + + let result_type = self.result_type(); + let await_token = self.handler.is_async().then(|| quote!(.await)); + let handle_token = if self.reply_with_value() { + quote! { + let command_reply: CommandReply<#result_type> = self.#handler_func_ident(#(#handler_func_params),*)#await_token.into(); + let (result, value) = command_reply.to_tuple(); + } + } else { + quote! { + let result = self.#handler_func_ident(#(#handler_func_params),*)#await_token; + let value = 0u128; + } + }; + + quote!( + let request: #meta_module_ident::#params_struct_ident = #sails_path::Decode::decode(&mut __input).expect("Failed to decode request"); + #handle_token + ) + } } diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_allow_attrs.snap b/rs/macros/core/tests/snapshots/gservice__works_with_allow_attrs.snap index 040332a3..4cbe3bf3 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_allow_attrs.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_allow_attrs.snap @@ -13,120 +13,60 @@ impl SomeService { p1 } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + async fn do_this(&mut self, p1: u32, p2: String) -> u32; + fn this(&self, p1: bool) -> bool; } -#[allow(warnings)] -#[allow(clippy::all)] -impl SomeServiceExposure { +impl SomeServiceImplTrait +for sails_rs::gstd::services::ServiceExposure { #[allow(unused)] - pub async fn do_this(&mut self, p1: u32, p2: String) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + async fn do_this(&mut self, p1: u32, p2: String) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this(p1, p2).await } - pub fn this(&self, p1: bool) -> bool { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn this(&self, p1: bool) -> bool { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.this(p1) } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__this(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(request.p1, request.p2).await; - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __this(&self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.this(request.p1); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } } -impl sails_rs::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(request.p1, request.p2).await; + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + "This" => { + let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.this(request.p1); + let value = 0u128; + Some((sails_rs::Encode::encode(&("This", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for SomeService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_basics.snap b/rs/macros/core/tests/snapshots/gservice__works_with_basics.snap index 4739d282..f6b72fc9 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_basics.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_basics.snap @@ -10,117 +10,59 @@ impl SomeService { p1 } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + async fn do_this(&mut self, p1: u32, p2: String) -> u32; + fn this(&self, p1: bool) -> bool; } -impl SomeServiceExposure { - pub async fn do_this(&mut self, p1: u32, p2: String) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl SomeServiceImplTrait +for sails_rs::gstd::services::ServiceExposure { + async fn do_this(&mut self, p1: u32, p2: String) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this(p1, p2).await } - pub fn this(&self, p1: bool) -> bool { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn this(&self, p1: bool) -> bool { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.this(p1) } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__this(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(request.p1, request.p2).await; - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __this(&self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.this(request.p1); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } } -impl sails_rs::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(request.p1, request.p2).await; + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + "This" => { + let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.this(request.p1); + let value = 0u128; + Some((sails_rs::Encode::encode(&("This", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for SomeService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_crate_path.snap b/rs/macros/core/tests/snapshots/gservice__works_with_crate_path.snap index 314cec7d..c0775f01 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_crate_path.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_crate_path.snap @@ -10,117 +10,59 @@ impl SomeService { p1 } } -pub struct SomeServiceExposure { - message_id: sails_rename::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + async fn do_this(&mut self, p1: u32, p2: String) -> u32; + fn this(&self, p1: bool) -> bool; } -impl SomeServiceExposure { - pub async fn do_this(&mut self, p1: u32, p2: String) -> u32 { - let exposure_scope = sails_rename::gstd::services::ExposureCallScope::new(self); +impl SomeServiceImplTrait +for sails_rename::gstd::services::ServiceExposure { + async fn do_this(&mut self, p1: u32, p2: String) -> u32 { + let exposure_scope = sails_rename::gstd::services::ExposureCallScope::new2(self); self.inner.do_this(p1, p2).await } - pub fn this(&self, p1: bool) -> bool { - let exposure_scope = sails_rename::gstd::services::ExposureCallScope::new(self); + fn this(&self, p1: bool) -> bool { + let exposure_scope = sails_rename::gstd::services::ExposureCallScope::new2(self); self.inner.this(p1) } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rename::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rename::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rename::hex::encode(& input[..4]), - sails_rename::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__this(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rename::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(request.p1, request.p2).await; - let value = 0u128; - return (sails_rename::Encode::encode(&result), value); - } - async fn __this(&self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__ThisParams = sails_rename::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.this(request.p1); - let value = 0u128; - return (sails_rename::Encode::encode(&result), value); - } } -impl sails_rename::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rename::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rename::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rename::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rename::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(request.p1, request.p2).await; + let value = 0u128; + Some((sails_rename::Encode::encode(&("DoThis", &result)), value)) + } + "This" => { + let request: some_service_meta::__ThisParams = sails_rename::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.this(request.p1); + let value = 0u128; + Some((sails_rename::Encode::encode(&("This", &result)), value)) + } + _ => None, + } } } impl sails_rename::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rename::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rename::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rename::meta::ServiceMeta for SomeService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_docs.snap b/rs/macros/core/tests/snapshots/gservice__works_with_docs.snap index 48d34ff8..3a319718 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_docs.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_docs.snap @@ -13,117 +13,59 @@ impl SomeService { p1 } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + async fn do_this(&mut self, p1: u32, p2: String) -> u32; + fn this(&self, p1: bool) -> bool; } -impl SomeServiceExposure { - pub async fn do_this(&mut self, p1: u32, p2: String) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl SomeServiceImplTrait +for sails_rs::gstd::services::ServiceExposure { + async fn do_this(&mut self, p1: u32, p2: String) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this(p1, p2).await } - pub fn this(&self, p1: bool) -> bool { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn this(&self, p1: bool) -> bool { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.this(p1) } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__this(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(request.p1, request.p2).await; - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __this(&self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.this(request.p1); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } } -impl sails_rs::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(request.p1, request.p2).await; + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + "This" => { + let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.this(request.p1); + let value = 0u128; + Some((sails_rs::Encode::encode(&("This", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for SomeService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_events.snap b/rs/macros/core/tests/snapshots/gservice__works_with_events.snap index 0bcc8eca..3dff6fe6 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_events.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_events.snap @@ -25,143 +25,59 @@ impl SomeService { sails_rs::gstd::events::__notify_on(event) } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + fn do_this(&mut self) -> u32; + fn this(&self) -> bool; } -#[cfg(not(target_arch = "wasm32"))] -impl Drop for SomeServiceExposure { - fn drop(&mut self) { - let service_ptr = self.inner_ptr as usize; - let mut event_listeners = sails_rs::gstd::events::event_listeners().lock(); - if event_listeners.remove(&service_ptr).is_some() { - panic!("there should be no any event listeners left by this time"); - } - } -} -impl SomeServiceExposure { - pub fn do_this(&mut self) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl SomeServiceImplTrait +for sails_rs::gstd::services::ServiceExposure { + fn do_this(&mut self) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this() } - pub fn this(&self) -> bool { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn this(&self) -> bool { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.this() } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__this(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __this(&self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.this(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - #[cfg(not(target_arch = "wasm32"))] - pub fn set_event_listener<'__elg>( - &self, - listener: impl FnMut(&SomeEvents) + '__elg, - ) -> sails_rs::gstd::events::EventListenerGuard<'__elg> { - if core::mem::size_of_val(self.inner.as_ref()) == 0 { - panic!( - "setting event listener on a zero-sized service is not supported for now" - ); - } - let service_ptr = self.inner_ptr as usize; - let listener: Box = Box::new(listener); - let listener = Box::new(listener); - let listener_ptr = Box::into_raw(listener) as usize; - sails_rs::gstd::events::EventListenerGuard::new(service_ptr, listener_ptr) - } } -impl sails_rs::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + "This" => { + let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.this(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("This", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for SomeService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_extends.snap b/rs/macros/core/tests/snapshots/gservice__works_with_extends.snap index fb3ec113..5364c32f 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_extends.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_extends.snap @@ -7,125 +7,81 @@ impl SomeService { 42 } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, - base_0: ::Exposure, - base_1: ::Exposure, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + fn do_this(&mut self) -> u32; + fn as_base_0( + &self, + ) -> &sails_rs::gstd::services::ServiceExposure; + fn as_base_1( + &self, + ) -> &sails_rs::gstd::services::ServiceExposure; } -impl SomeServiceExposure { - pub fn do_this(&mut self) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl SomeServiceImplTrait +for sails_rs::gstd::services::ServiceExposure< + SomeService, + ( + sails_rs::gstd::services::ServiceExposure, + sails_rs::gstd::services::ServiceExposure, + ), +> { + fn do_this(&mut self) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this() } - pub fn as_base_0( + fn as_base_0( &self, - ) -> &::Exposure { - &self.base_0 + ) -> &sails_rs::gstd::services::ServiceExposure { + &self.extend.0 } - pub fn as_base_1( + fn as_base_1( &self, - ) -> &::Exposure { - &self.base_1 - } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if let Some((output, value)) = self.base_0.try_handle(input).await { - return Some((output, value)); - } - if let Some((output, value)) = self.base_1.try_handle(input).await { - return Some((output, value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); + ) -> &sails_rs::gstd::services::ServiceExposure { + &self.extend.1 } } -impl sails_rs::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure< + SomeService, + ( + sails_rs::gstd::services::ServiceExposure, + sails_rs::gstd::services::ServiceExposure, + ), + >; + type Extend = ( + sails_rs::gstd::services::ServiceExposure, + sails_rs::gstd::services::ServiceExposure, + ); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - base_0: ::clone( - AsRef::::as_ref(inner), - ) + let extend = ( + ::clone(AsRef::::as_ref(&self)) .expose(message_id, route), - base_1: ::clone( - AsRef::::as_ref(inner), - ) + ::clone(AsRef::::as_ref(&self)) .expose(message_id, route), - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + ); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for SomeService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_extends_and_lifetimes.snap b/rs/macros/core/tests/snapshots/gservice__works_with_extends_and_lifetimes.snap index 985c493d..0e1d323e 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_extends_and_lifetimes.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_extends_and_lifetimes.snap @@ -10,155 +10,76 @@ impl<'a> ExtendedLifetime<'a> { "extended".to_string() } } -pub struct ExtendedLifetimeExposure<'a, T> { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, - base_0: as sails_rs::gstd::services::Service>::Exposure, +#[allow(async_fn_in_trait)] +pub trait ExtendedLifetimeImplTrait<'a> { + fn extended_name(&self) -> String; + fn name(&self) -> String; + fn as_base_0( + &self, + ) -> &sails_rs::gstd::services::ServiceExposure, ()>; } -impl<'a> ExtendedLifetimeExposure<'a, ExtendedLifetime<'a>> { - pub fn extended_name(&self) -> String { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl<'a> ExtendedLifetimeImplTrait<'a> +for sails_rs::gstd::services::ServiceExposure< + ExtendedLifetime<'a>, + sails_rs::gstd::services::ServiceExposure, ()>, +> { + fn extended_name(&self) -> String { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.extended_name() } - pub fn name(&self) -> String { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn name(&self) -> String { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.name() } - pub fn as_base_0( + fn as_base_0( &self, - ) -> & as sails_rs::gstd::services::Service>::Exposure { - &self.base_0 - } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input - .starts_with( - &[ - 48u8, - 69u8, - 120u8, - 116u8, - 101u8, - 110u8, - 100u8, - 101u8, - 100u8, - 78u8, - 97u8, - 109u8, - 101u8, - ], - ) - { - let (output, value) = self.__extended_name(&input[13usize..]).await; - static INVOCATION_ROUTE: [u8; 13usize] = [ - 48u8, - 69u8, - 120u8, - 116u8, - 101u8, - 110u8, - 100u8, - 101u8, - 100u8, - 78u8, - 97u8, - 109u8, - 101u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 78u8, 97u8, 109u8, 101u8]) { - let (output, value) = self.__name(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 78u8, 97u8, 109u8, 101u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if let Some((output, value)) = self.base_0.try_handle(input).await { - return Some((output, value)); - } - None - } - async fn __extended_name(&self, mut input: &[u8]) -> (Vec, u128) { - let request: extended_lifetime_meta::__ExtendedNameParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.extended_name(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __name(&self, mut input: &[u8]) -> (Vec, u128) { - let request: extended_lifetime_meta::__NameParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.name(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); + ) -> &sails_rs::gstd::services::ServiceExposure, ()> { + &self.extend } } -impl<'a> sails_rs::gstd::services::Exposure -for ExtendedLifetimeExposure<'a, ExtendedLifetime<'a>> { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl<'a> sails_rs::gstd::services::ServiceHandle for ExtendedLifetime<'a> { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "ExtendedName" => { + let request: extended_lifetime_meta::__ExtendedNameParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.extended_name(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("ExtendedName", &result)), value)) + } + "Name" => { + let request: extended_lifetime_meta::__NameParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.name(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("Name", &result)), value)) + } + _ => None, + } } } impl<'a> sails_rs::gstd::services::Service for ExtendedLifetime<'a> { - type Exposure = ExtendedLifetimeExposure<'a, ExtendedLifetime<'a>>; + type Exposure = sails_rs::gstd::services::ServiceExposure< + ExtendedLifetime<'a>, + sails_rs::gstd::services::ServiceExposure, ()>, + >; + type Extend = sails_rs::gstd::services::ServiceExposure, ()>; fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - base_0: as Clone>::clone(AsRef::>::as_ref(inner)) - .expose(message_id, route), - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = ( as Clone>::clone(AsRef::>::as_ref(&self)) + .expose(message_id, route)); + Self::Exposure::new(message_id, route, self, extend) } } impl<'a> sails_rs::meta::ServiceMeta for ExtendedLifetime<'a> { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_events.snap b/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_events.snap index 622cb45a..78adabef 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_events.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_events.snap @@ -25,135 +25,57 @@ where sails_rs::gstd::events::__notify_on(event) } } -pub struct MyGenericEventsServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait MyGenericEventsServiceImplTrait<'a> { + fn do_this(&mut self) -> u32; } -#[cfg(not(target_arch = "wasm32"))] -impl Drop for MyGenericEventsServiceExposure { - fn drop(&mut self) { - let service_ptr = self.inner_ptr as usize; - let mut event_listeners = sails_rs::gstd::events::event_listeners().lock(); - if event_listeners.remove(&service_ptr).is_some() { - panic!("there should be no any event listeners left by this time"); - } - } -} -impl<'a, T> MyGenericEventsServiceExposure> +impl<'a, T> MyGenericEventsServiceImplTrait<'a> +for sails_rs::gstd::services::ServiceExposure, ()> where T: Clone, { - pub fn do_this(&mut self) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn do_this(&mut self) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this() } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: my_generic_events_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - #[cfg(not(target_arch = "wasm32"))] - pub fn set_event_listener<'__elg>( - &self, - listener: impl FnMut(&MyEvents) + '__elg, - ) -> sails_rs::gstd::events::EventListenerGuard<'__elg> { - if core::mem::size_of_val(self.inner.as_ref()) == 0 { - panic!( - "setting event listener on a zero-sized service is not supported for now" - ); - } - let service_ptr = self.inner_ptr as usize; - let listener: Box = Box::new(listener); - let listener = Box::new(listener); - let listener_ptr = Box::into_raw(listener) as usize; - sails_rs::gstd::events::EventListenerGuard::new(service_ptr, listener_ptr) - } } -impl<'a, T> sails_rs::gstd::services::Exposure -for MyGenericEventsServiceExposure> +impl<'a, T> sails_rs::gstd::services::ServiceHandle for MyGenericEventsService<'a, T> where T: Clone, { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: my_generic_events_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + _ => None, + } } } impl<'a, T> sails_rs::gstd::services::Service for MyGenericEventsService<'a, T> where T: Clone, { - type Exposure = MyGenericEventsServiceExposure>; + type Exposure = sails_rs::gstd::services::ServiceExposure< + MyGenericEventsService<'a, T>, + (), + >; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl<'a, T> sails_rs::meta::ServiceMeta for MyGenericEventsService<'a, T> diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_generics.snap b/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_generics.snap index d2e68177..a75873fe 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_generics.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_lifetimes_and_generics.snap @@ -11,83 +11,41 @@ where 42 } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait<'a, 'b> { + fn do_this(&mut self) -> u32; } -impl<'a, 'b, T, U> SomeServiceExposure> +impl<'a, 'b, T, U> SomeServiceImplTrait<'a, 'b> +for sails_rs::gstd::services::ServiceExposure, ()> where T: Clone, U: Iterator, { - pub fn do_this(&mut self) -> u32 { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn do_this(&mut self) -> u32 { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this() } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.do_this(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } } -impl<'a, 'b, T, U> sails_rs::gstd::services::Exposure -for SomeServiceExposure> +impl<'a, 'b, T, U> sails_rs::gstd::services::ServiceHandle for SomeService<'a, 'b, T, U> where T: Clone, U: Iterator, { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.do_this(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + _ => None, + } } } impl<'a, 'b, T, U> sails_rs::gstd::services::Service for SomeService<'a, 'b, T, U> @@ -95,28 +53,18 @@ where T: Clone, U: Iterator, { - type Exposure = SomeServiceExposure>; + type Exposure = sails_rs::gstd::services::ServiceExposure< + SomeService<'a, 'b, T, U>, + (), + >; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl<'a, 'b, T, U> sails_rs::meta::ServiceMeta for SomeService<'a, 'b, T, U> diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_methods_with_lifetimes.snap b/rs/macros/core/tests/snapshots/gservice__works_with_methods_with_lifetimes.snap index c23e54d5..2828e48c 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_methods_with_lifetimes.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_methods_with_lifetimes.snap @@ -25,206 +25,101 @@ impl ReferenceService { unsafe { BYTES.last() } } } -pub struct ReferenceServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait ReferenceServiceImplTrait { + fn add_byte(&mut self, byte: u8) -> &'static [u8]; + fn baked(&self) -> &'static str; + async fn first_byte<'a>(&self) -> Option<&'a u8>; + fn incr(&mut self) -> &'static ReferenceCount; + async fn last_byte<'a>(&self) -> Option<&'a u8>; } -impl ReferenceServiceExposure { - pub fn add_byte(&mut self, byte: u8) -> &'static [u8] { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl ReferenceServiceImplTrait +for sails_rs::gstd::services::ServiceExposure { + fn add_byte(&mut self, byte: u8) -> &'static [u8] { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.add_byte(byte) } - pub fn baked(&self) -> &'static str { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn baked(&self) -> &'static str { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.baked() } - pub async fn first_byte<'a>(&self) -> Option<&'a u8> { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + async fn first_byte<'a>(&self) -> Option<&'a u8> { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.first_byte().await } - pub fn incr(&mut self) -> &'static ReferenceCount { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn incr(&mut self) -> &'static ReferenceCount { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.incr() } - pub async fn last_byte<'a>(&self) -> Option<&'a u8> { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + async fn last_byte<'a>(&self) -> Option<&'a u8> { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.last_byte().await } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[28u8, 65u8, 100u8, 100u8, 66u8, 121u8, 116u8, 101u8]) { - let (output, value) = self.__add_byte(&input[8usize..]).await; - static INVOCATION_ROUTE: [u8; 8usize] = [ - 28u8, - 65u8, - 100u8, - 100u8, - 66u8, - 121u8, - 116u8, - 101u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[20u8, 66u8, 97u8, 107u8, 101u8, 100u8]) { - let (output, value) = self.__baked(&input[6usize..]).await; - static INVOCATION_ROUTE: [u8; 6usize] = [ - 20u8, - 66u8, - 97u8, - 107u8, - 101u8, - 100u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input - .starts_with( - &[36u8, 70u8, 105u8, 114u8, 115u8, 116u8, 66u8, 121u8, 116u8, 101u8], - ) - { - let (output, value) = self.__first_byte(&input[10usize..]).await; - static INVOCATION_ROUTE: [u8; 10usize] = [ - 36u8, - 70u8, - 105u8, - 114u8, - 115u8, - 116u8, - 66u8, - 121u8, - 116u8, - 101u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 73u8, 110u8, 99u8, 114u8]) { - let (output, value) = self.__incr(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 73u8, 110u8, 99u8, 114u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input - .starts_with(&[32u8, 76u8, 97u8, 115u8, 116u8, 66u8, 121u8, 116u8, 101u8]) - { - let (output, value) = self.__last_byte(&input[9usize..]).await; - static INVOCATION_ROUTE: [u8; 9usize] = [ - 32u8, - 76u8, - 97u8, - 115u8, - 116u8, - 66u8, - 121u8, - 116u8, - 101u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __add_byte(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: reference_service_meta::__AddByteParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.add_byte(request.byte); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __baked(&self, mut input: &[u8]) -> (Vec, u128) { - let request: reference_service_meta::__BakedParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.baked(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __first_byte(&self, mut input: &[u8]) -> (Vec, u128) { - let request: reference_service_meta::__FirstByteParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.first_byte().await; - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __incr(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: reference_service_meta::__IncrParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.incr(); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } - async fn __last_byte(&self, mut input: &[u8]) -> (Vec, u128) { - let request: reference_service_meta::__LastByteParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.last_byte().await; - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } } -impl sails_rs::gstd::services::Exposure for ReferenceServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for ReferenceService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "AddByte" => { + let request: reference_service_meta::__AddByteParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.add_byte(request.byte); + let value = 0u128; + Some((sails_rs::Encode::encode(&("AddByte", &result)), value)) + } + "Baked" => { + let request: reference_service_meta::__BakedParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.baked(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("Baked", &result)), value)) + } + "FirstByte" => { + let request: reference_service_meta::__FirstByteParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.first_byte().await; + let value = 0u128; + Some((sails_rs::Encode::encode(&("FirstByte", &result)), value)) + } + "Incr" => { + let request: reference_service_meta::__IncrParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.incr(); + let value = 0u128; + Some((sails_rs::Encode::encode(&("Incr", &result)), value)) + } + "LastByte" => { + let request: reference_service_meta::__LastByteParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.last_byte().await; + let value = 0u128; + Some((sails_rs::Encode::encode(&("LastByte", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for ReferenceService { - type Exposure = ReferenceServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for ReferenceService { diff --git a/rs/macros/core/tests/snapshots/gservice__works_with_reply_with_value.snap b/rs/macros/core/tests/snapshots/gservice__works_with_reply_with_value.snap index c9833bc1..7df2033b 100644 --- a/rs/macros/core/tests/snapshots/gservice__works_with_reply_with_value.snap +++ b/rs/macros/core/tests/snapshots/gservice__works_with_reply_with_value.snap @@ -10,120 +10,62 @@ impl SomeService { p1 } } -pub struct SomeServiceExposure { - message_id: sails_rs::MessageId, - route: &'static [u8], - #[cfg(not(target_arch = "wasm32"))] - inner: Box, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: *const T, - #[cfg(target_arch = "wasm32")] - inner: T, +#[allow(async_fn_in_trait)] +pub trait SomeServiceImplTrait { + async fn do_this(&mut self, p1: u32, p2: String) -> CommandReply; + fn this(&self, p1: bool) -> bool; } -impl SomeServiceExposure { - pub async fn do_this(&mut self, p1: u32, p2: String) -> CommandReply { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); +impl SomeServiceImplTrait +for sails_rs::gstd::services::ServiceExposure { + async fn do_this(&mut self, p1: u32, p2: String) -> CommandReply { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.do_this(p1, p2).await } - pub fn this(&self, p1: bool) -> bool { - let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new(self); + fn this(&self, p1: bool) -> bool { + let exposure_scope = sails_rs::gstd::services::ExposureCallScope::new2(self); self.inner.this(p1) } - pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) { - self.try_handle(input) - .await - .unwrap_or_else(|| { - { - let mut __input = input; - let input: String = sails_rs::Decode::decode(&mut __input) - .unwrap_or_else(|_| { - if input.len() <= 8 { - format!("0x{}", sails_rs::hex::encode(input)) - } else { - format!( - "0x{}..{}", sails_rs::hex::encode(& input[..4]), - sails_rs::hex::encode(& input[input.len() - 4..]) - ) - } - }); - panic!("Unknown request: {}", input) - } - }) - } - pub async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { - if input.starts_with(&[24u8, 68u8, 111u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__do_this(&input[7usize..]).await; - static INVOCATION_ROUTE: [u8; 7usize] = [ - 24u8, - 68u8, - 111u8, - 84u8, - 104u8, - 105u8, - 115u8, - ]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - if input.starts_with(&[16u8, 84u8, 104u8, 105u8, 115u8]) { - let (output, value) = self.__this(&input[5usize..]).await; - static INVOCATION_ROUTE: [u8; 5usize] = [16u8, 84u8, 104u8, 105u8, 115u8]; - return Some(([INVOCATION_ROUTE.as_ref(), &output].concat(), value)); - } - None - } - async fn __do_this(&mut self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let command_reply: CommandReply = self - .do_this(request.p1, request.p2) - .await - .into(); - let (result, value) = command_reply.to_tuple(); - return (sails_rs::Encode::encode(&result), value); - } - async fn __this(&self, mut input: &[u8]) -> (Vec, u128) { - let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( - &mut input, - ) - .expect("Failed to decode request"); - let result = self.this(request.p1); - let value = 0u128; - return (sails_rs::Encode::encode(&result), value); - } } -impl sails_rs::gstd::services::Exposure for SomeServiceExposure { - fn message_id(&self) -> sails_rs::MessageId { - self.message_id - } - fn route(&self) -> &'static [u8] { - self.route +impl sails_rs::gstd::services::ServiceHandle for SomeService { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + let mut __input = input; + let route: String = sails_rs::Decode::decode(&mut __input).ok()?; + match route.as_str() { + "DoThis" => { + let request: some_service_meta::__DoThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let command_reply: CommandReply = self + .do_this(request.p1, request.p2) + .await + .into(); + let (result, value) = command_reply.to_tuple(); + Some((sails_rs::Encode::encode(&("DoThis", &result)), value)) + } + "This" => { + let request: some_service_meta::__ThisParams = sails_rs::Decode::decode( + &mut __input, + ) + .expect("Failed to decode request"); + let result = self.this(request.p1); + let value = 0u128; + Some((sails_rs::Encode::encode(&("This", &result)), value)) + } + _ => None, + } } } impl sails_rs::gstd::services::Service for SomeService { - type Exposure = SomeServiceExposure; + type Exposure = sails_rs::gstd::services::ServiceExposure; + type Extend = (); fn expose( self, message_id: sails_rs::MessageId, route: &'static [u8], ) -> Self::Exposure { - #[cfg(not(target_arch = "wasm32"))] - let inner_box = Box::new(self); - #[cfg(not(target_arch = "wasm32"))] - let inner = inner_box.as_ref(); - #[cfg(target_arch = "wasm32")] - let inner = &self; - Self::Exposure { - message_id, - route, - #[cfg(not(target_arch = "wasm32"))] - inner_ptr: inner_box.as_ref() as *const Self, - #[cfg(not(target_arch = "wasm32"))] - inner: inner_box, - #[cfg(target_arch = "wasm32")] - inner: self, - } + let extend = (); + Self::Exposure::new(message_id, route, self, extend) } } impl sails_rs::meta::ServiceMeta for SomeService { diff --git a/rs/macros/tests/gservice_tests.rs b/rs/macros/tests/gservice_tests.rs index 57c40c96..26edd273 100644 --- a/rs/macros/tests/gservice_tests.rs +++ b/rs/macros/tests/gservice_tests.rs @@ -1,4 +1,4 @@ -use sails_rs::gstd::services::Service; +use sails_rs::gstd::services::*; use sails_rs::{Decode, Encode, MessageId}; mod gservice_with_basics; @@ -46,7 +46,7 @@ async fn gservice_with_basics() { async fn gservice_with_extends() { use gservice_with_extends::{ base::{Base, BASE_NAME_RESULT}, - extended::{Extended, EXTENDED_NAME_RESULT, NAME_RESULT}, + extended::{Extended, ExtendedImplTrait, EXTENDED_NAME_RESULT, NAME_RESULT}, }; const NAME_METHOD: &str = "Name"; @@ -155,13 +155,14 @@ async fn gservice_panic_on_unexpected_input_double_encoded() { #[test] fn gservice_with_events() { - use gservice_with_events::{MyEvents, MyServiceWithEvents}; + use gservice_with_events::{MyEvents, MyServiceWithEvents, MyServiceWithEventsImplTrait}; let mut exposure = MyServiceWithEvents(0).expose(MessageId::from(142), &[1, 4, 2]); let mut events = Vec::new(); { - let _event_listener_guard = exposure.set_event_listener(|event| events.push(event.clone())); + let _event_listener_guard = + exposure.set_event_listener(|event: &MyEvents| events.push(event.clone())); exposure.my_method(); } @@ -181,7 +182,8 @@ async fn gservice_with_lifetimes_and_events() { let mut events = Vec::new(); { - let _event_listener_guard = exposure.set_event_listener(|event| events.push(event.clone())); + let _event_listener_guard = + exposure.set_event_listener(|event: &MyEvents| events.push(event.clone())); let (output, _value) = exposure.handle(&DO_THIS.encode()).await; @@ -203,7 +205,9 @@ async fn gservice_with_lifetimes_and_events() { async fn gservice_with_extends_and_lifetimes() { use gservice_with_extends_and_lifetimes::{ base::{BaseWithLifetime, BASE_NAME_RESULT}, - extended::{ExtendedWithLifetime, EXTENDED_NAME_RESULT, NAME_RESULT}, + extended::{ + ExtendedWithLifetime, ExtendedWithLifetimeImplTrait, EXTENDED_NAME_RESULT, NAME_RESULT, + }, }; const NAME_METHOD: &str = "Name"; diff --git a/rs/src/gstd/services.rs b/rs/src/gstd/services.rs index 955dc2a4..6eb7f57b 100644 --- a/rs/src/gstd/services.rs +++ b/rs/src/gstd/services.rs @@ -1,3 +1,6 @@ +#[cfg(not(target_arch = "wasm32"))] +use crate::boxed::Box; +use crate::prelude::*; use crate::{collections::BTreeMap, MessageId, Vec}; use core::ops::DerefMut; @@ -25,12 +28,157 @@ fn get_message_id_to_service_route_map( } } +pub struct ServiceExposure { + message_id: MessageId, + route: &'static [u8], + #[cfg(not(target_arch = "wasm32"))] + inner_ptr: *const T, // Prevent exposure being Send + Sync + #[cfg(not(target_arch = "wasm32"))] + pub inner: Box, + #[cfg(target_arch = "wasm32")] + pub inner: T, + pub extend: E, +} + +impl ServiceExposure { + pub fn new(message_id: MessageId, route: &'static [u8], inner: T, extend: E) -> Self { + #[cfg(not(target_arch = "wasm32"))] + let inner = Box::new(inner); + + Self { + message_id, + route, + #[cfg(not(target_arch = "wasm32"))] + inner_ptr: inner.as_ref() as *const T, + inner, + extend, + } + } + + pub async fn handle(&mut self, input: &[u8]) -> (Vec, u128) + where + T: ServiceHandle + Service, + E: ServiceHandle, + { + if let Some(result) = self.try_handle_inner(input).await { + result + } else if let Some(result) = self.extend.try_handle(input).await { + result + } else { + let mut __input = input; + let input: String = Decode::decode(&mut __input).unwrap_or_else(|_| { + if input.len() <= 8 { + format!("0x{}", hex::encode(input)) + } else { + format!( + "0x{}..{}", + hex::encode(&input[..4]), + hex::encode(&input[input.len() - 4..]) + ) + } + }); + panic!("Unknown request: {}", input) + } + } + + async fn try_handle_inner(&mut self, input: &[u8]) -> Option<(Vec, u128)> + where + T: ServiceHandle + Service, + { + let _scope = ExposureCallScope::new2(self); + self.inner.try_handle(input).await + } + + // async fn call_scoped(&mut self, f: F) -> P + // where + // F: FnOnce(&mut T) -> R, + // R: IntoFuture, + // T: Service2, + // { + // let _scope = ExposureCallScope::new2(self); + // let inner = &mut self.inner; + // let future = f(inner).into_future(); + // future.await + // } + + pub fn extend(&self) -> &E { + &self.extend + } + + #[cfg(not(target_arch = "wasm32"))] + pub fn set_event_listener<'e, V>( + &self, + listener: impl FnMut(&V) + 'e, + ) -> crate::gstd::events::EventListenerGuard<'e> { + if core::mem::size_of_val(self.inner.as_ref()) == 0 { + panic!("setting event listener on a zero-sized service is not supported for now"); + } + let service_ptr = self.inner_ptr as usize; + let listener: Box = Box::new(listener); + let listener = Box::new(listener); + let listener_ptr = Box::into_raw(listener) as usize; + crate::gstd::events::EventListenerGuard::new(service_ptr, listener_ptr) + } +} + +#[cfg(not(target_arch = "wasm32"))] +impl Drop for ServiceExposure { + fn drop(&mut self) { + let service_ptr = self.inner_ptr as usize; + let mut event_listeners = crate::gstd::events::event_listeners().lock(); + if event_listeners.remove(&service_ptr).is_some() { + panic!("there should be no any event listeners left by this time"); + } + } +} + +// pub trait Service { +// type Exposure: Exposure; + +// fn expose(self, message_id: MessageId, route: &'static [u8]) -> Self::Exposure; +// } + pub trait Service { - type Exposure: Exposure; + type Exposure: Exposure2; + type Extend; fn expose(self, message_id: MessageId, route: &'static [u8]) -> Self::Exposure; } +#[allow(async_fn_in_trait)] +pub trait ServiceHandle { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)>; +} + +#[allow(async_fn_in_trait)] +pub trait Exposure2 { + type Service; + + fn message_id(&self) -> MessageId; + fn route(&self) -> &'static [u8]; +} + +impl Exposure2 for ServiceExposure { + type Service = T; + + fn message_id(&self) -> MessageId { + self.message_id + } + + fn route(&self) -> &'static [u8] { + self.route + } +} + +impl ServiceHandle for ServiceExposure +where + T: ServiceHandle + Service, +{ + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + self.try_handle_inner(input).await + } +} + pub trait Exposure { fn message_id(&self) -> MessageId; fn route(&self) -> &'static [u8]; @@ -81,6 +229,16 @@ impl ExposureCallScope { route: exposure.route(), } } + + pub fn new2(exposure: &impl Exposure2) -> Self { + let mut map = get_message_id_to_service_route_map(); + let routes = map.entry(exposure.message_id()).or_default(); + routes.push(exposure.route()); + Self { + message_id: exposure.message_id(), + route: exposure.route(), + } + } } impl Drop for ExposureCallScope { @@ -100,3 +258,32 @@ impl Drop for ExposureCallScope { } } } + +impl ServiceHandle for () { + async fn try_handle(&mut self, _input: &[u8]) -> Option<(Vec, u128)> { + None + } +} + +impl ServiceHandle for (T1, T2) { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + if let Some(result) = self.0.try_handle(input).await { + Some(result) + } else { + self.1.try_handle(input).await + } + } +} + +// todo: make macro_rules +impl ServiceHandle for (T1, T2, T3) { + async fn try_handle(&mut self, input: &[u8]) -> Option<(Vec, u128)> { + if let Some(result) = self.0.try_handle(input).await { + Some(result) + } else if let Some(result) = self.1.try_handle(input).await { + Some(result) + } else { + self.2.try_handle(input).await + } + } +}