diff --git a/benchmarks/ping-pong/app/src/ping_pong_client.rs b/benchmarks/ping-pong/app/src/ping_pong_client.rs index 523c84aea..40931a73f 100644 --- a/benchmarks/ping-pong/app/src/ping_pong_client.rs +++ b/benchmarks/ping-pong/app/src/ping_pong_client.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct PingPongProgram; +impl PingPongProgram { + pub const PING_PONG_SERVICE_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for PingPongProgram {} pub trait PingPong { type Env: sails_rs::client::GearEnv; @@ -14,7 +17,7 @@ impl PingPong for sails_rs::client::Actor sails_rs::client::Service { - self.service(stringify!(PingPongService)) + self.service(PingPongProgram::PING_PONG_SERVICE_ROUTE_ID) } } pub trait PingPongCtors { @@ -36,7 +39,7 @@ impl PingPongCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(NewForBench () -> ()); + sails_rs::io_struct_impl!(NewForBench () -> (), 0); } pub mod ping_pong_service { @@ -59,6 +62,10 @@ pub mod ping_pong_service { ) -> sails_rs::client::PendingCall; } pub struct PingPongServiceImpl; + impl sails_rs::client::Identifiable for PingPongServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([106, 114, 150, 138, 76, 98, 231, 215]); + } impl PingPongService for sails_rs::client::Service { @@ -73,6 +80,6 @@ pub mod ping_pong_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(Ping (payload: super::PingPongPayload) -> super::PingPongPayload); + sails_rs::io_struct_impl!(Ping (payload: super::PingPongPayload) -> super::PingPongPayload, 0, ::INTERFACE_ID); } } diff --git a/benchmarks/src/alloc_stress_program.rs b/benchmarks/src/alloc_stress_program.rs index 8413a96a7..dd5913627 100644 --- a/benchmarks/src/alloc_stress_program.rs +++ b/benchmarks/src/alloc_stress_program.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct AllocStressProgram; +impl AllocStressProgram { + pub const ALLOC_STRESS_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for AllocStressProgram {} pub trait AllocStress { type Env: sails_rs::client::GearEnv; @@ -10,7 +13,7 @@ pub trait AllocStress { impl AllocStress for sails_rs::client::Actor { type Env = E; fn alloc_stress(&self) -> sails_rs::client::Service { - self.service(stringify!(AllocStress)) + self.service(AllocStressProgram::ALLOC_STRESS_ROUTE_ID) } } pub trait AllocStressCtors { @@ -32,7 +35,7 @@ impl AllocStressCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(NewForBench () -> ()); + sails_rs::io_struct_impl!(NewForBench () -> (), 0); } pub mod alloc_stress { @@ -52,6 +55,10 @@ pub mod alloc_stress { ) -> sails_rs::client::PendingCall; } pub struct AllocStressImpl; + impl sails_rs::client::Identifiable for AllocStressImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([9, 48, 193, 195, 84, 117, 173, 52]); + } impl AllocStress for sails_rs::client::Service { type Env = E; fn alloc_stress( @@ -64,6 +71,6 @@ pub mod alloc_stress { pub mod io { use super::*; - sails_rs::io_struct_impl!(AllocStress (n: u32) -> super::AllocStressResult); + sails_rs::io_struct_impl!(AllocStress (n: u32) -> super::AllocStressResult, 0, ::INTERFACE_ID); } } diff --git a/benchmarks/src/benchmarks.rs b/benchmarks/src/benchmarks.rs index e9da1f802..dfe92c1d6 100644 --- a/benchmarks/src/benchmarks.rs +++ b/benchmarks/src/benchmarks.rs @@ -18,15 +18,23 @@ //! ``` use crate::clients::{ - alloc_stress_client::{AllocStress as _, AllocStressCtors, alloc_stress::*}, - compute_stress_client::{ComputeStress as _, ComputeStressCtors, compute_stress::*}, - counter_bench_client::{CounterBench as _, CounterBenchCtors, counter_bench::*}, + alloc_stress_client::{ + AllocStress as _, AllocStressCtors, AllocStressProgram, alloc_stress::*, + }, + compute_stress_client::{ + ComputeStress as _, ComputeStressCtors, ComputeStressProgram, compute_stress::*, + }, + counter_bench_client::{ + CounterBench as _, CounterBenchCtors, CounterBenchProgram, counter_bench::*, + }, }; use gtest::{System, constants::DEFAULT_USER_ALICE}; use itertools::{Either, Itertools}; -use ping_pong_bench_app::client::{PingPong, PingPongCtors, ping_pong_service::*}; +use ping_pong_bench_app::client::{PingPong, PingPongCtors, PingPongProgram, ping_pong_service::*}; use redirect_client::{RedirectClient, RedirectClientCtors, redirect::*}; -use redirect_proxy_client::{RedirectProxyClient, RedirectProxyClientCtors, proxy::*}; +use redirect_proxy_client::{ + RedirectProxyClient, RedirectProxyClientCtors, RedirectProxyClientProgram, proxy::*, +}; use sails_rs::{client::*, prelude::*}; use std::{collections::BTreeMap, sync::atomic::AtomicU64}; @@ -67,11 +75,10 @@ async fn compute_stress_bench() { .map(|_| { let message_id = service.compute_stress(input_value).send_one_way().unwrap(); let (payload, gas) = extract_reply_and_gas(env.system(), message_id); - let stress_resp = crate::clients::compute_stress_client::compute_stress::io::ComputeStress::decode_reply_with_prefix( - "ComputeStress", - payload.as_slice(), - ) - .unwrap(); + // Low-level approach: decoding using generated io module + let stress_resp = + crate::clients::compute_stress_client::compute_stress::io::ComputeStress::decode_reply(ComputeStressProgram::COMPUTE_STRESS_ROUTE_ID, payload.as_slice()) + .unwrap(); assert_eq!(stress_resp.res, expected_sum); gas }) @@ -99,8 +106,9 @@ async fn counter_bench() { let gas = if is_sync { let message_id = service.inc().send_one_way().unwrap(); let (payload, gas) = extract_reply_and_gas(env.system(), message_id); - let stress_resp = crate::clients::counter_bench_client::counter_bench::io::Inc::decode_reply_with_prefix( - "CounterBench", + // Low-level approach: decoding using generated io module + let stress_resp = crate::clients::counter_bench_client::counter_bench::io::Inc::decode_reply( + CounterBenchProgram::COUNTER_BENCH_ROUTE_ID, payload.as_slice(), ) .unwrap(); @@ -111,8 +119,9 @@ async fn counter_bench() { } else { let message_id = service.inc_async().send_one_way().unwrap(); let (payload, gas) = extract_reply_and_gas(env.system(), message_id); - let stress_resp = crate::clients::counter_bench_client::counter_bench::io::IncAsync::decode_reply_with_prefix( - "CounterBench", + // Low-level approach: decoding using generated io module + let stress_resp = crate::clients::counter_bench_client::counter_bench::io::IncAsync::decode_reply( + CounterBenchProgram::COUNTER_BENCH_ROUTE_ID, payload.as_slice(), ) .unwrap(); @@ -158,9 +167,10 @@ async fn cross_program_bench() { .send_one_way() .unwrap(); let (payload, gas) = extract_reply_and_gas(env.system(), message_id); + // Low-level approach: decoding using generated io module let stress_resp = - ping_pong_bench_app::client::ping_pong_service::io::Ping::decode_reply_with_prefix( - "PingPongService", + ping_pong_bench_app::client::ping_pong_service::io::Ping::decode_reply( + PingPongProgram::PING_PONG_SERVICE_ROUTE_ID, payload.as_slice(), ) .unwrap(); @@ -199,8 +209,9 @@ async fn redirect_bench() { .send_one_way() .unwrap(); let (payload, _gas) = extract_reply_and_gas(env.system(), message_id); - let resp = redirect_proxy_client::proxy::io::GetProgramId::decode_reply_with_prefix( - "Proxy", + // Low-level approach: decoding using generated io module + let resp = redirect_proxy_client::proxy::io::GetProgramId::decode_reply( + RedirectProxyClientProgram::PROXY_ROUTE_ID, payload.as_slice(), ) .unwrap(); @@ -223,8 +234,9 @@ async fn redirect_bench() { .send_one_way() .unwrap(); let (payload, gas) = extract_reply_and_gas(env.system(), message_id); - let resp = redirect_proxy_client::proxy::io::GetProgramId::decode_reply_with_prefix( - "Proxy", + // Low-level approach: decoding using generated io module + let resp = redirect_proxy_client::proxy::io::GetProgramId::decode_reply( + RedirectProxyClientProgram::PROXY_ROUTE_ID, payload.as_slice(), ) .unwrap(); @@ -269,11 +281,13 @@ async fn alloc_stress_test(n: u32) -> (usize, u64) { let mut service = program.alloc_stress(); let message_id = service.alloc_stress(n).send_one_way().unwrap(); let (payload, gas) = extract_reply_and_gas(env.system(), message_id); - let stress_resp = crate::clients::alloc_stress_client::alloc_stress::io::AllocStress::decode_reply_with_prefix( - "AllocStress", - payload.as_slice(), - ) - .unwrap(); + // Low-level approach: decoding using generated io module + let stress_resp = + crate::clients::alloc_stress_client::alloc_stress::io::AllocStress::decode_reply( + AllocStressProgram::ALLOC_STRESS_ROUTE_ID, + payload.as_slice(), + ) + .unwrap(); let expected_len = alloc_stress::fibonacci_sum(n) as usize; assert_eq!(stress_resp.inner.len(), expected_len); diff --git a/benchmarks/src/compute_stress_program.rs b/benchmarks/src/compute_stress_program.rs index 0dab756e6..a66504c61 100644 --- a/benchmarks/src/compute_stress_program.rs +++ b/benchmarks/src/compute_stress_program.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct ComputeStressProgram; +impl ComputeStressProgram { + pub const COMPUTE_STRESS_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for ComputeStressProgram {} pub trait ComputeStress { type Env: sails_rs::client::GearEnv; @@ -16,7 +19,7 @@ impl ComputeStress fn compute_stress( &self, ) -> sails_rs::client::Service { - self.service(stringify!(ComputeStress)) + self.service(ComputeStressProgram::COMPUTE_STRESS_ROUTE_ID) } } pub trait ComputeStressCtors { @@ -38,7 +41,7 @@ impl ComputeStressCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(NewForBench () -> ()); + sails_rs::io_struct_impl!(NewForBench () -> (), 0); } pub mod compute_stress { @@ -58,6 +61,10 @@ pub mod compute_stress { ) -> sails_rs::client::PendingCall; } pub struct ComputeStressImpl; + impl sails_rs::client::Identifiable for ComputeStressImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([254, 138, 70, 56, 122, 195, 121, 54]); + } impl ComputeStress for sails_rs::client::Service { @@ -72,6 +79,6 @@ pub mod compute_stress { pub mod io { use super::*; - sails_rs::io_struct_impl!(ComputeStress (n: u32) -> super::ComputeStressResult); + sails_rs::io_struct_impl!(ComputeStress (n: u32) -> super::ComputeStressResult, 0, ::INTERFACE_ID); } } diff --git a/benchmarks/src/counter_bench_program.rs b/benchmarks/src/counter_bench_program.rs index 50560441e..1dbd46b27 100644 --- a/benchmarks/src/counter_bench_program.rs +++ b/benchmarks/src/counter_bench_program.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct CounterBenchProgram; +impl CounterBenchProgram { + pub const COUNTER_BENCH_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for CounterBenchProgram {} pub trait CounterBench { type Env: sails_rs::client::GearEnv; @@ -16,7 +19,7 @@ impl CounterBench fn counter_bench( &self, ) -> sails_rs::client::Service { - self.service(stringify!(CounterBench)) + self.service(CounterBenchProgram::COUNTER_BENCH_ROUTE_ID) } } pub trait CounterBenchCtors { @@ -38,7 +41,7 @@ impl CounterBenchCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(NewForBench () -> ()); + sails_rs::io_struct_impl!(NewForBench () -> (), 0); } pub mod counter_bench { @@ -49,6 +52,10 @@ pub mod counter_bench { fn inc_async(&mut self) -> sails_rs::client::PendingCall; } pub struct CounterBenchImpl; + impl sails_rs::client::Identifiable for CounterBenchImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([149, 170, 24, 82, 218, 19, 238, 13]); + } impl CounterBench for sails_rs::client::Service { type Env = E; fn inc(&mut self) -> sails_rs::client::PendingCall { @@ -61,7 +68,7 @@ pub mod counter_bench { pub mod io { use super::*; - sails_rs::io_struct_impl!(Inc () -> u64); - sails_rs::io_struct_impl!(IncAsync () -> u64); + sails_rs::io_struct_impl!(Inc () -> u64, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(IncAsync () -> u64, 1, ::INTERFACE_ID); } } diff --git a/examples/demo/app/tests/gclient.rs b/examples/demo/app/tests/gclient.rs index 70e153368..8fa824e4e 100644 --- a/examples/demo/app/tests/gclient.rs +++ b/examples/demo/app/tests/gclient.rs @@ -112,7 +112,7 @@ async fn ping_pong_works() { // Use generated `io` module for encoding/decoding calls and replies // and send/receive bytes using `gclient` native means (env is just a wrapper) let ping_call_payload = - ping_pong::io::Ping::encode_params_with_prefix("PingPong", "ping".into()); + ping_pong::io::Ping::encode_call(DemoClientProgram::PING_PONG_ROUTE_ID, "ping".into()); // Act let ping_reply_payload = env @@ -124,8 +124,11 @@ async fn ping_pong_works() { .await .unwrap(); - let ping_reply = - ping_pong::io::Ping::decode_reply_with_prefix("PingPong", ping_reply_payload).unwrap(); + let ping_reply = ping_pong::io::Ping::decode_reply( + DemoClientProgram::PING_PONG_ROUTE_ID, + ping_reply_payload, + ) + .unwrap(); // Assert diff --git a/examples/demo/app/tests/gtest.rs b/examples/demo/app/tests/gtest.rs index d613e8899..297cd007e 100644 --- a/examples/demo/app/tests/gtest.rs +++ b/examples/demo/app/tests/gtest.rs @@ -177,7 +177,7 @@ async fn ping_pong_low_level_works() { // Use generated `io` module for encoding/decoding calls and replies // and send/receive bytes using `gtest` native means - let ping_call_payload = Ping::encode_params_with_prefix("PingPong", "ping".into()); + let ping_call_payload = Ping::encode_call(DemoClientProgram::PING_PONG_ROUTE_ID, "ping".into()); let message_id = demo_program.send_bytes(ACTOR_ID, ping_call_payload); let run_result = system.run_next_block(); @@ -190,7 +190,8 @@ async fn ping_pong_low_level_works() { let ping_reply_payload = reply_log_record.payload(); - let ping_reply = Ping::decode_reply_with_prefix("PingPong", ping_reply_payload).unwrap(); + let ping_reply = + Ping::decode_reply(DemoClientProgram::PING_PONG_ROUTE_ID, ping_reply_payload).unwrap(); assert_eq!(ping_reply, Ok("pong".to_string())); @@ -455,7 +456,7 @@ fn counter_add_low_level_works() { // Use generated `io` module for encoding/decoding calls and replies // and send/receive bytes using `gtest` native means - let call_payload = Add::encode_params_with_prefix("Counter", 10); + let call_payload = Add::encode_call(DemoClientProgram::COUNTER_ROUTE_ID, 10); let message_id = demo_program.send_bytes(ACTOR_ID, call_payload); let run_result = system.run_next_block(); @@ -468,7 +469,7 @@ fn counter_add_low_level_works() { let reply_payload = reply_log_record.payload(); - let reply = Add::decode_reply_with_prefix("Counter", reply_payload).unwrap(); + let reply = Add::decode_reply(DemoClientProgram::COUNTER_ROUTE_ID, reply_payload).unwrap(); assert_eq!(reply, 10); @@ -547,7 +548,7 @@ async fn program_value_transfer_works() { #[test] fn chaos_service_panic_after_wait_works() { - use demo_client::io::Default; + use demo_client::{chaos::io::PanicAfterWait, io::Default}; use gstd::errors::{ErrorReplyReason, SimpleExecutionError}; use sails_rs::gtest::{Log, Program, System}; @@ -557,7 +558,10 @@ fn chaos_service_panic_after_wait_works() { let program = Program::from_file(&system, DEMO_WASM_PATH); program.send_bytes(ACTOR_ID, Default::encode_params()); - let msg_id = program.send_bytes(ACTOR_ID, ("Chaos", "PanicAfterWait").encode()); + let msg_id = program.send_bytes( + ACTOR_ID, + PanicAfterWait::encode_call(DemoClientProgram::CHAOS_ROUTE_ID), + ); system.run_next_block(); let log = Log::builder().source(program.id()).dest(ACTOR_ID); @@ -577,8 +581,10 @@ fn chaos_service_panic_after_wait_works() { #[test] fn chaos_service_timeout_wait() { - use demo_client::chaos::io::ReplyHookCounter; - use demo_client::io::Default; + use demo_client::{ + chaos::io::{ReplyHookCounter, TimeoutWait}, + io::Default, + }; use sails_rs::gtest::{Log, Program, System}; let system = System::new(); @@ -587,7 +593,10 @@ fn chaos_service_timeout_wait() { let program = Program::from_file(&system, DEMO_WASM_PATH); program.send_bytes(ACTOR_ID, Default::encode_params()); - program.send_bytes(ACTOR_ID, ("Chaos", "TimeoutWait").encode()); + program.send_bytes( + ACTOR_ID, + TimeoutWait::encode_call(DemoClientProgram::CHAOS_ROUTE_ID), + ); //#1 system.run_next_block(); //#2 @@ -603,12 +612,15 @@ fn chaos_service_timeout_wait() { decode(payload) }; - let msg_id = program.send_bytes(ACTOR_ID, ("Chaos", "ReplyHookCounter").encode()); + let msg_id = program.send_bytes( + ACTOR_ID, + ReplyHookCounter::encode_call(DemoClientProgram::CHAOS_ROUTE_ID), + ); let run = system.run_next_block(); let val = extract_reply(&run, msg_id, |p| { - ReplyHookCounter::decode_reply_with_prefix("Chaos", p).unwrap() + ReplyHookCounter::decode_reply(DemoClientProgram::CHAOS_ROUTE_ID, p).unwrap() }); assert_eq!(val, 0, "handle_reply should not trigger before reply"); @@ -619,10 +631,13 @@ fn chaos_service_timeout_wait() { .unwrap(); system.run_next_block(); - let msg_id = program.send_bytes(ACTOR_ID, ("Chaos", "ReplyHookCounter").encode()); + let msg_id = program.send_bytes( + ACTOR_ID, + ReplyHookCounter::encode_call(DemoClientProgram::CHAOS_ROUTE_ID), + ); let run = system.run_next_block(); let val = extract_reply(&run, msg_id, |p| { - ReplyHookCounter::decode_reply_with_prefix("Chaos", p).unwrap() + ReplyHookCounter::decode_reply(DemoClientProgram::CHAOS_ROUTE_ID, p).unwrap() }); assert_eq!( val, 1, diff --git a/examples/demo/client/src/demo_client.rs b/examples/demo/client/src/demo_client.rs index 5824ba919..c43389324 100644 --- a/examples/demo/client/src/demo_client.rs +++ b/examples/demo/client/src/demo_client.rs @@ -9,6 +9,15 @@ use core::num::NonZeroU32; #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct DemoClientProgram; +impl DemoClientProgram { + pub const PING_PONG_ROUTE_ID: u8 = 1; + pub const COUNTER_ROUTE_ID: u8 = 2; + pub const DOG_ROUTE_ID: u8 = 3; + pub const REFERENCES_ROUTE_ID: u8 = 4; + pub const THIS_THAT_ROUTE_ID: u8 = 5; + pub const VALUE_FEE_ROUTE_ID: u8 = 6; + pub const CHAOS_ROUTE_ID: u8 = 7; +} impl sails_rs::client::Program for DemoClientProgram {} pub trait DemoClient { type Env: sails_rs::client::GearEnv; @@ -23,25 +32,25 @@ pub trait DemoClient { impl DemoClient for sails_rs::client::Actor { type Env = E; fn ping_pong(&self) -> sails_rs::client::Service { - self.service(stringify!(PingPong)) + self.service(DemoClientProgram::PING_PONG_ROUTE_ID) } fn counter(&self) -> sails_rs::client::Service { - self.service(stringify!(Counter)) + self.service(DemoClientProgram::COUNTER_ROUTE_ID) } fn dog(&self) -> sails_rs::client::Service { - self.service(stringify!(Dog)) + self.service(DemoClientProgram::DOG_ROUTE_ID) } fn references(&self) -> sails_rs::client::Service { - self.service(stringify!(References)) + self.service(DemoClientProgram::REFERENCES_ROUTE_ID) } fn this_that(&self) -> sails_rs::client::Service { - self.service(stringify!(ThisThat)) + self.service(DemoClientProgram::THIS_THAT_ROUTE_ID) } fn value_fee(&self) -> sails_rs::client::Service { - self.service(stringify!(ValueFee)) + self.service(DemoClientProgram::VALUE_FEE_ROUTE_ID) } fn chaos(&self) -> sails_rs::client::Service { - self.service(stringify!(Chaos)) + self.service(DemoClientProgram::CHAOS_ROUTE_ID) } } pub trait DemoClientCtors { @@ -75,8 +84,8 @@ impl DemoClientCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(Default () -> ()); - sails_rs::io_struct_impl!(New (counter: super::Option, dog_position: super::Option<(i32, i32, ), >) -> ()); + sails_rs::io_struct_impl!(Default () -> (), 0); + sails_rs::io_struct_impl!(New (counter: super::Option, dog_position: super::Option<(i32, i32, ), >) -> (), 1); } pub mod ping_pong { @@ -86,6 +95,10 @@ pub mod ping_pong { fn ping(&mut self, input: String) -> sails_rs::client::PendingCall; } pub struct PingPongImpl; + impl sails_rs::client::Identifiable for PingPongImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([33, 189, 154, 154, 165, 29, 162, 100]); + } impl PingPong for sails_rs::client::Service { type Env = E; fn ping(&mut self, input: String) -> sails_rs::client::PendingCall { @@ -95,7 +108,7 @@ pub mod ping_pong { pub mod io { use super::*; - sails_rs::io_struct_impl!(Ping (input: String) -> super::Result); + sails_rs::io_struct_impl!(Ping (input: String) -> super::Result, 0, ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] @@ -119,6 +132,10 @@ pub mod counter { fn value(&self) -> sails_rs::client::PendingCall; } pub struct CounterImpl; + impl sails_rs::client::Identifiable for CounterImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([87, 157, 109, 171, 164, 27, 125, 130]); + } impl Counter for sails_rs::client::Service { type Env = E; fn add(&mut self, value: u32) -> sails_rs::client::PendingCall { @@ -134,9 +151,9 @@ pub mod counter { pub mod io { use super::*; - sails_rs::io_struct_impl!(Add (value: u32) -> u32); - sails_rs::io_struct_impl!(Sub (value: u32) -> u32); - sails_rs::io_struct_impl!(Value () -> u32); + sails_rs::io_struct_impl!(Add (value: u32) -> u32, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Sub (value: u32) -> u32, 1, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Value () -> u32, 2, ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -147,12 +164,16 @@ pub mod counter { #[reflect_hash(crate = sails_rs)] pub enum CounterEvents { /// Emitted when a new value is added to the counter + #[codec(index = 0)] Added(u32), /// Emitted when a value is subtracted from the counter + #[codec(index = 1)] Subtracted(u32), } - impl sails_rs::client::Event for CounterEvents { - const EVENT_NAMES: &'static [Route] = &["Added", "Subtracted"]; + impl sails_rs::client::Event for CounterEvents {} + impl sails_rs::client::Identifiable for CounterEvents { + const INTERFACE_ID: sails_rs::InterfaceId = + ::INTERFACE_ID; } impl sails_rs::client::ServiceWithEvents for CounterImpl { type Event = CounterEvents; @@ -176,6 +197,10 @@ pub mod walker_service { fn position(&self) -> sails_rs::client::PendingCall; } pub struct WalkerServiceImpl; + impl sails_rs::client::Identifiable for WalkerServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([238, 21, 54, 181, 81, 112, 191, 10]); + } impl WalkerService for sails_rs::client::Service { @@ -190,8 +215,8 @@ pub mod walker_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(Walk (dx: i32, dy: i32) -> ()); - sails_rs::io_struct_impl!(Position () -> (i32, i32, )); + sails_rs::io_struct_impl!(Walk (dx: i32, dy: i32) -> (), 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Position () -> (i32, i32, ), 1, ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -201,10 +226,13 @@ pub mod walker_service { #[codec(crate = sails_rs::scale_codec)] #[reflect_hash(crate = sails_rs)] pub enum WalkerServiceEvents { + #[codec(index = 0)] Walked { from: (i32, i32), to: (i32, i32) }, } - impl sails_rs::client::Event for WalkerServiceEvents { - const EVENT_NAMES: &'static [Route] = &["Walked"]; + impl sails_rs::client::Event for WalkerServiceEvents {} + impl sails_rs::client::Identifiable for WalkerServiceEvents { + const INTERFACE_ID: sails_rs::InterfaceId = + ::INTERFACE_ID; } impl sails_rs::client::ServiceWithEvents for WalkerServiceImpl { type Event = WalkerServiceEvents; @@ -228,6 +256,10 @@ pub mod mammal_service { fn avg_weight(&self) -> sails_rs::client::PendingCall; } pub struct MammalServiceImpl; + impl sails_rs::client::Identifiable for MammalServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([255, 107, 147, 225, 150, 16, 38, 254]); + } impl MammalService for sails_rs::client::Service { @@ -242,8 +274,8 @@ pub mod mammal_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(MakeSound () -> String); - sails_rs::io_struct_impl!(AvgWeight () -> u32); + sails_rs::io_struct_impl!(MakeSound () -> String, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(AvgWeight () -> u32, 1, ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] @@ -268,6 +300,10 @@ pub mod dog { ) -> sails_rs::client::Service; } pub struct DogImpl; + impl sails_rs::client::Identifiable for DogImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([24, 102, 110, 103, 162, 25, 23, 161]); + } impl Dog for sails_rs::client::Service { type Env = E; fn make_sound(&mut self) -> sails_rs::client::PendingCall { @@ -289,7 +325,7 @@ pub mod dog { pub mod io { use super::*; - sails_rs::io_struct_impl!(MakeSound () -> String); + sails_rs::io_struct_impl!(MakeSound () -> String, 0, ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -299,10 +335,13 @@ pub mod dog { #[codec(crate = sails_rs::scale_codec)] #[reflect_hash(crate = sails_rs)] pub enum DogEvents { + #[codec(index = 0)] Barked, } - impl sails_rs::client::Event for DogEvents { - const EVENT_NAMES: &'static [Route] = &["Barked"]; + impl sails_rs::client::Event for DogEvents {} + impl sails_rs::client::Identifiable for DogEvents { + const INTERFACE_ID: sails_rs::InterfaceId = + ::INTERFACE_ID; } impl sails_rs::client::ServiceWithEvents for DogImpl { type Event = DogEvents; @@ -340,6 +379,10 @@ pub mod references { fn message(&self) -> sails_rs::client::PendingCall; } pub struct ReferencesImpl; + impl sails_rs::client::Identifiable for ReferencesImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([61, 171, 145, 177, 150, 71, 129, 98]); + } impl References for sails_rs::client::Service { type Env = E; fn add(&mut self, v: u32) -> sails_rs::client::PendingCall { @@ -373,14 +416,14 @@ pub mod references { pub mod io { use super::*; - sails_rs::io_struct_impl!(Add (v: u32) -> u32); - sails_rs::io_struct_impl!(AddByte (byte: u8) -> Vec); - sails_rs::io_struct_impl!(GuessNum (number: u8) -> super::Result); - sails_rs::io_struct_impl!(Incr () -> super::ReferenceCount); - sails_rs::io_struct_impl!(SetNum (number: u8) -> super::Result<(), String>); - sails_rs::io_struct_impl!(Baked () -> String); - sails_rs::io_struct_impl!(LastByte () -> super::Option); - sails_rs::io_struct_impl!(Message () -> super::Option); + sails_rs::io_struct_impl!(Add (v: u32) -> u32, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(AddByte (byte: u8) -> Vec, 1, ::INTERFACE_ID); + sails_rs::io_struct_impl!(GuessNum (number: u8) -> super::Result, 2, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Incr () -> super::ReferenceCount, 3, ::INTERFACE_ID); + sails_rs::io_struct_impl!(SetNum (number: u8) -> super::Result<(), String>, 4, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Baked () -> String, 5, ::INTERFACE_ID); + sails_rs::io_struct_impl!(LastByte () -> super::Option, 6, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Message () -> super::Option, 7, ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] @@ -450,6 +493,10 @@ pub mod this_that { fn this(&self) -> sails_rs::client::PendingCall; } pub struct ThisThatImpl; + impl sails_rs::client::Identifiable for ThisThatImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([68, 91, 237, 110, 251, 232, 230, 221]); + } impl ThisThat for sails_rs::client::Service { type Env = E; fn do_that( @@ -480,11 +527,11 @@ pub mod this_that { pub mod io { use super::*; - sails_rs::io_struct_impl!(DoThat (param: super::DoThatParam) -> super::Result<(ActorId, super::NonZeroU32, super::ManyVariantsReply, ), (String, )>); - sails_rs::io_struct_impl!(DoThis (p1: u32, p2: String, p3: (super::Option, super::NonZeroU8, ), p4: super::TupleStruct) -> (String, u32, )); - sails_rs::io_struct_impl!(Noop () -> ()); - sails_rs::io_struct_impl!(That () -> super::Result); - sails_rs::io_struct_impl!(This () -> u32); + sails_rs::io_struct_impl!(DoThat (param: super::DoThatParam) -> super::Result<(ActorId, super::NonZeroU32, super::ManyVariantsReply, ), (String, )>, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(DoThis (p1: u32, p2: String, p3: (super::Option, super::NonZeroU8, ), p4: super::TupleStruct) -> (String, u32, ), 1, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Noop () -> (), 2, ::INTERFACE_ID); + sails_rs::io_struct_impl!(That () -> super::Result, 3, ::INTERFACE_ID); + sails_rs::io_struct_impl!(This () -> u32, 4, ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] @@ -507,6 +554,10 @@ pub mod value_fee { ) -> sails_rs::client::PendingCall; } pub struct ValueFeeImpl; + impl sails_rs::client::Identifiable for ValueFeeImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([65, 193, 8, 11, 78, 30, 141, 197]); + } impl ValueFee for sails_rs::client::Service { type Env = E; fn do_something_and_take_fee( @@ -518,7 +569,7 @@ pub mod value_fee { pub mod io { use super::*; - sails_rs::io_struct_impl!(DoSomethingAndTakeFee () -> bool); + sails_rs::io_struct_impl!(DoSomethingAndTakeFee () -> bool, 0, ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -528,10 +579,13 @@ pub mod value_fee { #[codec(crate = sails_rs::scale_codec)] #[reflect_hash(crate = sails_rs)] pub enum ValueFeeEvents { + #[codec(index = 0)] Withheld(u128), } - impl sails_rs::client::Event for ValueFeeEvents { - const EVENT_NAMES: &'static [Route] = &["Withheld"]; + impl sails_rs::client::Event for ValueFeeEvents {} + impl sails_rs::client::Identifiable for ValueFeeEvents { + const INTERFACE_ID: sails_rs::InterfaceId = + ::INTERFACE_ID; } impl sails_rs::client::ServiceWithEvents for ValueFeeImpl { type Event = ValueFeeEvents; @@ -558,6 +612,10 @@ pub mod chaos { fn timeout_wait(&self) -> sails_rs::client::PendingCall; } pub struct ChaosImpl; + impl sails_rs::client::Identifiable for ChaosImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([240, 200, 200, 13, 250, 191, 114, 213]); + } impl Chaos for sails_rs::client::Service { type Env = E; fn panic_after_wait(&self) -> sails_rs::client::PendingCall { @@ -575,9 +633,9 @@ pub mod chaos { pub mod io { use super::*; - sails_rs::io_struct_impl!(PanicAfterWait () -> ()); - sails_rs::io_struct_impl!(ReplyHookCounter () -> u32); - sails_rs::io_struct_impl!(TimeoutWait () -> ()); + sails_rs::io_struct_impl!(PanicAfterWait () -> (), 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(ReplyHookCounter () -> u32, 1, ::INTERFACE_ID); + sails_rs::io_struct_impl!(TimeoutWait () -> (), 2, ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] diff --git a/examples/demo/client/src/lib.rs b/examples/demo/client/src/lib.rs index bc81cfaf6..ee212f512 100644 --- a/examples/demo/client/src/lib.rs +++ b/examples/demo/client/src/lib.rs @@ -11,8 +11,10 @@ mod tests { fn test_io_module_encode() { use this_that::*; - let bytes = io::DoThat::encode_params_with_prefix( - "ThisThat", + // Use the new simplified encode_call method + // It automatically uses the InterfaceId from the service module + let bytes = io::DoThat::encode_call( + 0, DoThatParam { p1: NonZeroU32::MAX, p2: 123.into(), @@ -20,35 +22,46 @@ mod tests { }, ); - assert_eq!( - bytes, - vec![ - 32, 84, 104, 105, 115, 84, 104, 97, 116, // ThisThat - 24, 68, 111, 84, 104, 97, 116, // DoThat - 255, 255, 255, 255, // p1 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, // p2 - 0, // p3 - ] - ); + let mut expected = vec![ + 0x47, 0x4D, 0x01, 0x10, // Magic, Version, Header Length + 68, 91, 237, 110, 251, 232, 230, 221, // Interface ID + 0, 0, // Entry ID + 0, // Route Index + 0, // Reserved + ]; + expected.extend_from_slice(&[ + 255, 255, 255, 255, // p1 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, // p2 + 0, // p3 + ]); + + assert_eq!(bytes, expected); } #[test] fn test_io_module_decode_reply() { use this_that::*; - let bytes = vec![ - 32, 84, 104, 105, 115, 84, 104, 97, 116, // ThisThat - 24, 68, 111, 84, 104, 97, 116, // DoThat - 0, // Ok + // We don't need manual InterfaceId anymore, it's inside decode_reply + let mut bytes = vec![ + 0x47, 0x4D, 0x01, 0x10, // Magic, Version, Header Length + 68, 91, 237, 110, 251, 232, 230, 221, // Interface ID + 0, 0, // Entry ID + 0, // Route Index + 0, // Reserved + ]; + bytes.extend_from_slice(&[ + 0, // Ok 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 123 255, 255, 255, 255, // NonZeroU32::MAX 0, // ManyVariantsReply::One - ]; + ]); + // Use the simplified method let reply: Result<(ActorId, NonZeroU32, ManyVariantsReply), (String,)> = - io::DoThat::decode_reply_with_prefix("ThisThat", bytes).unwrap(); + io::DoThat::decode_reply(0, bytes).unwrap(); assert_eq!( reply, diff --git a/examples/no-svcs-prog/wasm/src/no_svcs_prog.rs b/examples/no-svcs-prog/wasm/src/no_svcs_prog.rs index 6c09a717f..b85ac55f0 100644 --- a/examples/no-svcs-prog/wasm/src/no_svcs_prog.rs +++ b/examples/no-svcs-prog/wasm/src/no_svcs_prog.rs @@ -2,6 +2,7 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct NoSvcsProgProgram; +impl NoSvcsProgProgram {} impl sails_rs::client::Program for NoSvcsProgProgram {} pub trait NoSvcsProg { type Env: sails_rs::client::GearEnv; @@ -24,5 +25,5 @@ impl NoSvcsProgCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(Create () -> ()); + sails_rs::io_struct_impl!(Create () -> (), 0); } diff --git a/examples/ping-pong-stack/src/ping_pong_stack.rs b/examples/ping-pong-stack/src/ping_pong_stack.rs index 19a4ea4a5..100dfa0b9 100644 --- a/examples/ping-pong-stack/src/ping_pong_stack.rs +++ b/examples/ping-pong-stack/src/ping_pong_stack.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct PingPongStackProgram; +impl PingPongStackProgram { + pub const PING_PONG_STACK_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for PingPongStackProgram {} pub trait PingPongStack { type Env: sails_rs::client::GearEnv; @@ -16,7 +19,7 @@ impl PingPongStack fn ping_pong_stack( &self, ) -> sails_rs::client::Service { - self.service(stringify!(PingPongStack)) + self.service(PingPongStackProgram::PING_PONG_STACK_ROUTE_ID) } } pub trait PingPongStackCtors { @@ -48,8 +51,8 @@ impl PingPongStackCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(CreatePing (code_id: CodeId) -> ()); - sails_rs::io_struct_impl!(CreatePong () -> ()); + sails_rs::io_struct_impl!(CreatePing (code_id: CodeId) -> (), 0); + sails_rs::io_struct_impl!(CreatePong () -> (), 1); } pub mod ping_pong_stack { @@ -60,6 +63,10 @@ pub mod ping_pong_stack { fn start(&mut self, limit: u32) -> sails_rs::client::PendingCall; } pub struct PingPongStackImpl; + impl sails_rs::client::Identifiable for PingPongStackImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([48, 181, 231, 61, 179, 133, 133, 236]); + } impl PingPongStack for sails_rs::client::Service { @@ -74,7 +81,7 @@ pub mod ping_pong_stack { pub mod io { use super::*; - sails_rs::io_struct_impl!(Ping (countdown: u32) -> ()); - sails_rs::io_struct_impl!(Start (limit: u32) -> ()); + sails_rs::io_struct_impl!(Ping (countdown: u32) -> (), 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Start (limit: u32) -> (), 1, ::INTERFACE_ID); } } diff --git a/examples/redirect/client/src/redirect_client.rs b/examples/redirect/client/src/redirect_client.rs index 186b12318..b9058bc89 100644 --- a/examples/redirect/client/src/redirect_client.rs +++ b/examples/redirect/client/src/redirect_client.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct RedirectClientProgram; +impl RedirectClientProgram { + pub const REDIRECT_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for RedirectClientProgram {} pub trait RedirectClient { type Env: sails_rs::client::GearEnv; @@ -12,7 +15,7 @@ impl RedirectClient { type Env = E; fn redirect(&self) -> sails_rs::client::Service { - self.service(stringify!(Redirect)) + self.service(RedirectClientProgram::REDIRECT_ROUTE_ID) } } pub trait RedirectClientCtors { @@ -32,7 +35,7 @@ impl RedirectClientCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(New () -> ()); + sails_rs::io_struct_impl!(New () -> (), 0); } pub mod redirect { @@ -48,6 +51,10 @@ pub mod redirect { fn get_program_id(&self) -> sails_rs::client::PendingCall; } pub struct RedirectImpl; + impl sails_rs::client::Identifiable for RedirectImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([186, 88, 222, 225, 203, 117, 81, 30]); + } impl Redirect for sails_rs::client::Service { type Env = E; fn exit( @@ -63,7 +70,7 @@ pub mod redirect { pub mod io { use super::*; - sails_rs::io_struct_impl!(Exit (inheritor_id: ActorId) -> ()); - sails_rs::io_struct_impl!(GetProgramId () -> ActorId); + sails_rs::io_struct_impl!(Exit (inheritor_id: ActorId) -> (), 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(GetProgramId () -> ActorId, 1, ::INTERFACE_ID); } } diff --git a/examples/redirect/proxy-client/src/redirect_proxy_client.rs b/examples/redirect/proxy-client/src/redirect_proxy_client.rs index c880a7542..5a6fd160f 100644 --- a/examples/redirect/proxy-client/src/redirect_proxy_client.rs +++ b/examples/redirect/proxy-client/src/redirect_proxy_client.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct RedirectProxyClientProgram; +impl RedirectProxyClientProgram { + pub const PROXY_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for RedirectProxyClientProgram {} pub trait RedirectProxyClient { type Env: sails_rs::client::GearEnv; @@ -12,7 +15,7 @@ impl RedirectProxyClient { type Env = E; fn proxy(&self) -> sails_rs::client::Service { - self.service(stringify!(Proxy)) + self.service(RedirectProxyClientProgram::PROXY_ROUTE_ID) } } pub trait RedirectProxyClientCtors { @@ -39,7 +42,7 @@ impl RedirectProxyClientCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(New (target: ActorId) -> ()); + sails_rs::io_struct_impl!(New (target: ActorId) -> (), 0); } pub mod proxy { @@ -50,6 +53,10 @@ pub mod proxy { fn get_program_id(&self) -> sails_rs::client::PendingCall; } pub struct ProxyImpl; + impl sails_rs::client::Identifiable for ProxyImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([115, 132, 52, 118, 255, 19, 124, 126]); + } impl Proxy for sails_rs::client::Service { type Env = E; fn get_program_id(&self) -> sails_rs::client::PendingCall { @@ -59,6 +66,6 @@ pub mod proxy { pub mod io { use super::*; - sails_rs::io_struct_impl!(GetProgramId () -> ActorId); + sails_rs::io_struct_impl!(GetProgramId () -> ActorId, 0, ::INTERFACE_ID); } } diff --git a/examples/rmrk/resource/app/src/rmrk_catalog.rs b/examples/rmrk/resource/app/src/rmrk_catalog.rs index fc847ad85..f5ff1c229 100644 --- a/examples/rmrk/resource/app/src/rmrk_catalog.rs +++ b/examples/rmrk/resource/app/src/rmrk_catalog.rs @@ -5,6 +5,9 @@ extern crate std; #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct RmrkCatalogProgram; +impl RmrkCatalogProgram { + pub const RMRK_CATALOG_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for RmrkCatalogProgram {} pub trait RmrkCatalog { type Env: sails_rs::client::GearEnv; @@ -13,7 +16,7 @@ pub trait RmrkCatalog { impl RmrkCatalog for sails_rs::client::Actor { type Env = E; fn rmrk_catalog(&self) -> sails_rs::client::Service { - self.service(stringify!(RmrkCatalog)) + self.service(RmrkCatalogProgram::RMRK_CATALOG_ROUTE_ID) } } pub trait RmrkCatalogCtors { @@ -33,7 +36,7 @@ impl RmrkCatalogCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(New () -> ()); + sails_rs::io_struct_impl!(New () -> (), 0); } pub mod rmrk_catalog { @@ -121,6 +124,10 @@ pub mod rmrk_catalog { fn part(&self, part_id: u32) -> sails_rs::client::PendingCall; } pub struct RmrkCatalogImpl; + impl sails_rs::client::Identifiable for RmrkCatalogImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([219, 242, 106, 161, 165, 87, 3, 164]); + } impl RmrkCatalog for sails_rs::client::Service { type Env = E; fn add_equippables( @@ -175,14 +182,14 @@ pub mod rmrk_catalog { pub mod io { use super::*; - sails_rs::io_struct_impl!(AddEquippables (part_id: u32, collection_ids: Vec) -> super::Result<(u32, Vec, ), super::Error>); - sails_rs::io_struct_impl!(AddParts (parts: Vec<(u32, super::Part, )>) -> super::Result, super::Error>); - sails_rs::io_struct_impl!(RemoveEquippable (part_id: u32, collection_id: ActorId) -> super::Result<(u32, ActorId, ), super::Error>); - sails_rs::io_struct_impl!(RemoveParts (part_ids: Vec) -> super::Result, super::Error>); - sails_rs::io_struct_impl!(ResetEquippables (part_id: u32) -> super::Result<(), super::Error>); - sails_rs::io_struct_impl!(SetEquippablesToAll (part_id: u32) -> super::Result<(), super::Error>); - sails_rs::io_struct_impl!(Equippable (part_id: u32, collection_id: ActorId) -> super::Result); - sails_rs::io_struct_impl!(Part (part_id: u32) -> super::Option); + sails_rs::io_struct_impl!(AddEquippables (part_id: u32, collection_ids: Vec) -> super::Result<(u32, Vec, ), super::Error>, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(AddParts (parts: Vec<(u32, super::Part, )>) -> super::Result, super::Error>, 1, ::INTERFACE_ID); + sails_rs::io_struct_impl!(RemoveEquippable (part_id: u32, collection_id: ActorId) -> super::Result<(u32, ActorId, ), super::Error>, 2, ::INTERFACE_ID); + sails_rs::io_struct_impl!(RemoveParts (part_ids: Vec) -> super::Result, super::Error>, 3, ::INTERFACE_ID); + sails_rs::io_struct_impl!(ResetEquippables (part_id: u32) -> super::Result<(), super::Error>, 4, ::INTERFACE_ID); + sails_rs::io_struct_impl!(SetEquippablesToAll (part_id: u32) -> super::Result<(), super::Error>, 5, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Equippable (part_id: u32, collection_id: ActorId) -> super::Result, 6, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Part (part_id: u32) -> super::Option, 7, ::INTERFACE_ID); } #[cfg(feature = "mockall")] diff --git a/examples/rmrk/resource/wasm/src/rmrk_resource.rs b/examples/rmrk/resource/wasm/src/rmrk_resource.rs index a221a716a..d9d886e48 100644 --- a/examples/rmrk/resource/wasm/src/rmrk_resource.rs +++ b/examples/rmrk/resource/wasm/src/rmrk_resource.rs @@ -2,6 +2,9 @@ #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct RmrkResourceProgram; +impl RmrkResourceProgram { + pub const RMRK_RESOURCE_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for RmrkResourceProgram {} pub trait RmrkResource { type Env: sails_rs::client::GearEnv; @@ -16,7 +19,7 @@ impl RmrkResource fn rmrk_resource( &self, ) -> sails_rs::client::Service { - self.service(stringify!(RmrkResource)) + self.service(RmrkResourceProgram::RMRK_RESOURCE_ROUTE_ID) } } pub trait RmrkResourceCtors { @@ -36,7 +39,7 @@ impl RmrkResourceCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(New () -> ()); + sails_rs::io_struct_impl!(New () -> (), 0); } pub mod rmrk_resource { @@ -124,6 +127,10 @@ pub mod rmrk_resource { ) -> sails_rs::client::PendingCall; } pub struct RmrkResourceImpl; + impl sails_rs::client::Identifiable for RmrkResourceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([215, 56, 96, 51, 70, 205, 63, 27]); + } impl RmrkResource for sails_rs::client::Service { type Env = E; fn add_part_to_resource( @@ -150,9 +157,9 @@ pub mod rmrk_resource { pub mod io { use super::*; - sails_rs::io_struct_impl!(AddPartToResource (resource_id: u8, part_id: u32) -> super::Result); - sails_rs::io_struct_impl!(AddResourceEntry (resource_id: u8, resource: super::Resource) -> super::Result<(u8, super::Resource, ), super::Error, >); - sails_rs::io_struct_impl!(Resource (resource_id: u8) -> super::Result); + sails_rs::io_struct_impl!(AddPartToResource (resource_id: u8, part_id: u32) -> super::Result, 0, ::INTERFACE_ID); + sails_rs::io_struct_impl!(AddResourceEntry (resource_id: u8, resource: super::Resource) -> super::Result<(u8, super::Resource, ), super::Error, >, 1, ::INTERFACE_ID); + sails_rs::io_struct_impl!(Resource (resource_id: u8) -> super::Result, 2, ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -162,11 +169,15 @@ pub mod rmrk_resource { #[codec(crate = sails_rs::scale_codec)] #[reflect_hash(crate = sails_rs)] pub enum RmrkResourceEvents { + #[codec(index = 0)] PartAdded { resource_id: u8, part_id: u32 }, + #[codec(index = 1)] ResourceAdded { resource_id: u8 }, } - impl sails_rs::client::Event for RmrkResourceEvents { - const EVENT_NAMES: &'static [Route] = &["PartAdded", "ResourceAdded"]; + impl sails_rs::client::Event for RmrkResourceEvents {} + impl sails_rs::client::Identifiable for RmrkResourceEvents { + const INTERFACE_ID: sails_rs::InterfaceId = + ::INTERFACE_ID; } impl sails_rs::client::ServiceWithEvents for RmrkResourceImpl { type Event = RmrkResourceEvents; diff --git a/rs/client-gen/src/ctor_generators.rs b/rs/client-gen/src/ctor_generators.rs index 9da4056c2..d0a7e7031 100644 --- a/rs/client-gen/src/ctor_generators.rs +++ b/rs/client-gen/src/ctor_generators.rs @@ -3,6 +3,7 @@ use convert_case::{Case, Casing}; use genco::prelude::*; use rust::Tokens; use sails_idl_parser_v2::{ast, visitor::Visitor}; +use std::collections::HashMap; pub(crate) struct CtorGenerator<'ast> { program_name: &'ast str, @@ -10,6 +11,7 @@ pub(crate) struct CtorGenerator<'ast> { ctor_tokens: Tokens, io_tokens: Tokens, trait_ctors_tokens: Tokens, + entry_ids: HashMap<&'ast str, u16>, } impl<'ast> CtorGenerator<'ast> { @@ -20,6 +22,7 @@ impl<'ast> CtorGenerator<'ast> { ctor_tokens: Tokens::new(), io_tokens: Tokens::new(), trait_ctors_tokens: Tokens::new(), + entry_ids: HashMap::new(), } } @@ -45,6 +48,14 @@ impl<'ast> CtorGenerator<'ast> { } impl<'ast> Visitor<'ast> for CtorGenerator<'ast> { + fn visit_program_unit(&mut self, program: &'ast ast::ProgramUnit) { + for (idx, ctor) in program.ctors.iter().enumerate() { + self.entry_ids.insert(&ctor.name, idx as u16); + } + + sails_idl_parser_v2::visitor::accept_program_unit(program, self); + } + fn visit_ctor_func(&mut self, func: &'ast ast::CtorFunc) { let fn_name = &func.name; let fn_name_snake = &fn_name.to_case(Case::Snake); @@ -74,8 +85,9 @@ impl<'ast> Visitor<'ast> for CtorGenerator<'ast> { }; let params_with_types_super = &fn_args_with_types_path(&func.params, "super"); + let entry_id = self.entry_ids.get(func.name.as_str()).copied().unwrap_or(0); quote_in! { self.io_tokens => - $(self.sails_path)::io_struct_impl!($fn_name ($params_with_types_super) -> ()); + $(self.sails_path)::io_struct_impl!($fn_name ($params_with_types_super) -> (), $entry_id); }; } } diff --git a/rs/client-gen/src/events_generator.rs b/rs/client-gen/src/events_generator.rs index fba560f32..a81f7a459 100644 --- a/rs/client-gen/src/events_generator.rs +++ b/rs/client-gen/src/events_generator.rs @@ -1,5 +1,6 @@ use genco::prelude::*; use sails_idl_parser_v2::{ast, visitor, visitor::Visitor}; +use std::collections::HashMap; use crate::helpers::generate_doc_comments; @@ -7,14 +8,20 @@ pub(crate) struct EventsModuleGenerator<'ast> { service_name: &'ast str, sails_path: &'ast str, tokens: rust::Tokens, + entry_ids: HashMap<&'ast str, u16>, } impl<'ast> EventsModuleGenerator<'ast> { - pub(crate) fn new(service_name: &'ast str, sails_path: &'ast str) -> Self { + pub(crate) fn new( + service_name: &'ast str, + sails_path: &'ast str, + entry_ids: HashMap<&'ast str, u16>, + ) -> Self { Self { service_name, sails_path, tokens: rust::Tokens::new(), + entry_ids, } } @@ -26,12 +33,6 @@ impl<'ast> EventsModuleGenerator<'ast> { impl<'ast> Visitor<'ast> for EventsModuleGenerator<'ast> { fn visit_service_unit(&mut self, service: &'ast ast::ServiceUnit) { let events_name = &format!("{}Events", self.service_name); - let event_names = service - .events - .iter() - .map(|e| format!("\"{}\"", e.name)) - .collect::>() - .join(", "); quote_in! { self.tokens => $['\n'] @@ -51,8 +52,10 @@ impl<'ast> Visitor<'ast> for EventsModuleGenerator<'ast> { }; quote_in! { self.tokens => - impl $(self.sails_path)::client::Event for $events_name { - const EVENT_NAMES: &'static [Route] = &[$event_names]; + impl $(self.sails_path)::client::Event for $events_name {} + + impl $(self.sails_path)::client::Identifiable for $events_name { + const INTERFACE_ID: $(self.sails_path)::InterfaceId = <$(self.service_name)Impl as $(self.sails_path)::client::Identifiable>::INTERFACE_ID; } impl $(self.sails_path)::client::ServiceWithEvents for $(self.service_name)Impl { @@ -69,14 +72,19 @@ impl<'ast> Visitor<'ast> for EventsModuleGenerator<'ast> { generate_doc_comments(&mut self.tokens, &event.docs); let variant_name = &event.name; + let entry_id = self + .entry_ids + .get(event.name.as_str()) + .copied() + .unwrap_or(0); if event.def.is_unit() { - // Unit variant: `Variant,` quote_in! { self.tokens => - $['\r'] $variant_name, + $['\r'] + #[codec(index = $entry_id)] + $variant_name, }; } else if event.def.is_tuple() { - // Tuple variant: `Variant(Type1, Type2),` let mut field_tokens = rust::Tokens::new(); for field in &event.def.fields { let type_code = @@ -85,10 +93,11 @@ impl<'ast> Visitor<'ast> for EventsModuleGenerator<'ast> { field_tokens.append(", "); } quote_in! { self.tokens => - $['\r'] $variant_name($field_tokens), + $['\r'] + #[codec(index = $entry_id)] + $variant_name($field_tokens), }; } else { - // Struct variant: `Variant { field1: Type1, ... },` let mut field_tokens = rust::Tokens::new(); for field in &event.def.fields { generate_doc_comments(&mut field_tokens, &field.docs); @@ -100,7 +109,9 @@ impl<'ast> Visitor<'ast> for EventsModuleGenerator<'ast> { }; } quote_in! { self.tokens => - $['\r'] $variant_name { + $['\r'] + #[codec(index = $entry_id)] + $variant_name { $(field_tokens) $['\r'] }, }; diff --git a/rs/client-gen/src/root_generator.rs b/rs/client-gen/src/root_generator.rs index 8a8dedec9..23cc86034 100644 --- a/rs/client-gen/src/root_generator.rs +++ b/rs/client-gen/src/root_generator.rs @@ -12,12 +12,12 @@ pub(crate) struct RootGenerator<'ast> { tokens: Tokens, service_impl_tokens: Tokens, service_trait_tokens: Tokens, + program_meta_tokens: Tokens, program_name: Option<&'ast str>, mocks_feature_name: Option<&'ast str>, sails_path: &'ast str, external_types: HashMap<&'ast str, &'ast str>, no_derive_traits: bool, - program_exported_services: Vec<&'ast str>, program_types: HashSet<&'ast str>, } @@ -32,12 +32,12 @@ impl<'ast> RootGenerator<'ast> { tokens: Tokens::new(), service_impl_tokens: Tokens::new(), service_trait_tokens: Tokens::new(), + program_meta_tokens: Tokens::new(), program_name: None, mocks_feature_name, sails_path, external_types, no_derive_traits, - program_exported_services: Vec::new(), program_types: HashSet::new(), } } @@ -70,6 +70,10 @@ impl<'ast> RootGenerator<'ast> { quote_in! { tokens => pub struct $(program_name)Program; + impl $(program_name)Program { + $(self.program_meta_tokens) + } + impl $(self.sails_path)::client::Program for $(program_name)Program {} pub trait $program_name { @@ -109,14 +113,6 @@ impl<'ast> Visitor<'ast> for RootGenerator<'ast> { ctor_gen.visit_program_unit(program); self.tokens.extend(ctor_gen.finalize()); - for service_item in &program.services { - let service_name = service_item - .route - .as_ref() - .unwrap_or(&service_item.name.name); - self.program_exported_services.push(service_name); - } - sails_idl_parser_v2::visitor::accept_program_unit(program, self); } @@ -126,6 +122,10 @@ impl<'ast> Visitor<'ast> for RootGenerator<'ast> { self.sails_path, &self.external_types, self.mocks_feature_name, + service + .name + .interface_id + .expect("Service must have an interface ID"), self.no_derive_traits, ); client_gen.visit_service_unit(service); @@ -151,16 +151,24 @@ impl<'ast> Visitor<'ast> for RootGenerator<'ast> { let method_name = service_route.to_case(Case::Snake); let name_pascal_case = service_item.name.name.to_case(Case::Pascal); let name_snake_case = service_item.name.name.to_case(Case::Snake); + let program_name = self.program_name.unwrap(); + let program_program_name = format!("{program_name}Program"); generate_doc_comments(&mut self.service_trait_tokens, &service_item.docs); + let route_id_const_name = format!("{}_ROUTE_ID", service_route.to_case(Case::UpperSnake)); + + quote_in!(self.program_meta_tokens => + pub const $(&route_id_const_name): u8 = $(service_item.route_idx); + ); + quote_in!(self.service_trait_tokens => $['\r'] fn $(&method_name)(&self) -> $(self.sails_path)::client::Service<$(&name_snake_case)::$(&name_pascal_case)Impl, Self::Env>; ); quote_in!(self.service_impl_tokens => $['\r'] fn $(&method_name)(&self) -> $(self.sails_path)::client::Service<$(&name_snake_case)::$(&name_pascal_case)Impl, Self::Env> { - self.service(stringify!($(&name_pascal_case))) + self.service($(&program_program_name)::$(&route_id_const_name)) } ); } diff --git a/rs/client-gen/src/service_generators.rs b/rs/client-gen/src/service_generators.rs index 2f5131de6..eb4378ed3 100644 --- a/rs/client-gen/src/service_generators.rs +++ b/rs/client-gen/src/service_generators.rs @@ -5,7 +5,6 @@ use crate::type_generators::{TopLevelTypeGenerator, generate_type_decl_with_path use convert_case::{Case, Casing}; use genco::prelude::*; use rust::Tokens; -use sails_idl_meta::ServiceIdent; use sails_idl_parser_v2::{ast, visitor, visitor::Visitor}; use std::collections::HashMap; @@ -21,6 +20,8 @@ pub(crate) struct ServiceGenerator<'ast> { events_tokens: Tokens, types_tokens: Tokens, mocks_tokens: Tokens, + interface_id: sails_idl_meta::InterfaceId, + entry_ids: HashMap<&'ast str, u16>, no_derive_traits: bool, } @@ -30,6 +31,7 @@ impl<'ast> ServiceGenerator<'ast> { sails_path: &'ast str, external_types: &'ast HashMap<&'ast str, &'ast str>, mocks_feature_name: Option<&'ast str>, + interface_id: sails_idl_meta::InterfaceId, no_derive_traits: bool, ) -> Self { Self { @@ -43,6 +45,8 @@ impl<'ast> ServiceGenerator<'ast> { events_tokens: Tokens::new(), types_tokens: Tokens::new(), mocks_tokens: Tokens::new(), + interface_id, + entry_ids: HashMap::new(), no_derive_traits, } } @@ -63,6 +67,12 @@ impl<'ast> ServiceGenerator<'ast> { } else { quote!() }; + + let bytes = self.interface_id.as_bytes().iter().copied(); + let interface_id_tokens = quote! { + const INTERFACE_ID: $(self.sails_path)::InterfaceId = $(self.sails_path)::InterfaceId::from_bytes_8([ $(for b in bytes join (, ) => $b) ]); + }; + quote! { $['\n'] pub mod $service_name_snake { @@ -77,6 +87,10 @@ impl<'ast> ServiceGenerator<'ast> { pub struct $(self.service_name)Impl; + impl $(self.sails_path)::client::Identifiable for $(self.service_name)Impl { + $interface_id_tokens + } + impl $(self.service_name) for $(self.sails_path)::client::Service<$(self.service_name)Impl, E> { type Env = E; $(self.impl_tokens) @@ -99,13 +113,26 @@ impl<'ast> ServiceGenerator<'ast> { // using quote_in instead of tokens.append impl<'ast> Visitor<'ast> for ServiceGenerator<'ast> { fn visit_service_unit(&mut self, service: &'ast ast::ServiceUnit) { + let (mut commands, mut queries): (Vec<_>, Vec<_>) = service + .funcs + .iter() + .partition(|f| f.kind != ast::FunctionKind::Query); + + commands.sort_by_key(|f| f.name.to_lowercase()); + queries.sort_by_key(|f| f.name.to_lowercase()); + + for (entry_id, func) in commands.into_iter().chain(queries.into_iter()).enumerate() { + self.entry_ids.insert(func.name.as_str(), entry_id as u16); + } + + for (idx, event) in service.events.iter().enumerate() { + self.entry_ids.insert(event.name.as_str(), idx as u16); + } + visitor::accept_service_unit(service, self); - for ServiceIdent { - name, - interface_id: _, - } in &service.extends - { + for service_ident in &service.extends { + let name = &service_ident.name; let method_name = name.to_case(Case::Snake); let impl_name = name.to_case(Case::Pascal); let mod_name = name.to_case(Case::Snake); @@ -126,7 +153,11 @@ impl<'ast> Visitor<'ast> for ServiceGenerator<'ast> { self.mocks_tokens.extend(mock_gen.finalize()); if !service.events.is_empty() { - let mut events_mod_gen = EventsModuleGenerator::new(self.service_name, self.sails_path); + let mut events_mod_gen = EventsModuleGenerator::new( + self.service_name, + self.sails_path, + self.entry_ids.clone(), + ); events_mod_gen.visit_service_unit(service); self.events_tokens = events_mod_gen.finalize(); } @@ -176,8 +207,10 @@ impl<'ast> Visitor<'ast> for ServiceGenerator<'ast> { }; let params_with_types_super = &fn_args_with_types_path(&func.params, "super"); + let entry_id = self.entry_ids.get(func.name.as_str()).copied().unwrap_or(0); + quote_in! { self.io_tokens => - $(self.sails_path)::io_struct_impl!($fn_name ($params_with_types_super) -> $output_type_decl_code); + $(self.sails_path)::io_struct_impl!($fn_name ($params_with_types_super) -> $output_type_decl_code, $entry_id, ::INTERFACE_ID); }; } } diff --git a/rs/client-gen/tests/snapshots/generator__basic_works.snap b/rs/client-gen/tests/snapshots/generator__basic_works.snap index a2dd46c1a..2fb272402 100644 --- a/rs/client-gen/tests/snapshots/generator__basic_works.snap +++ b/rs/client-gen/tests/snapshots/generator__basic_works.snap @@ -44,6 +44,10 @@ pub mod basic { ) -> sails_rs::client::PendingCall; } pub struct BasicImpl; + impl sails_rs::client::Identifiable for BasicImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([82, 241, 49, 169, 231, 31, 0, 230]); + } impl Basic for sails_rs::client::Service { type Env = E; fn do_that( @@ -63,8 +67,8 @@ pub mod basic { pub mod io { use super::*; - sails_rs::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8); - sails_rs::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16); + sails_rs::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8, 0 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16, 1 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] diff --git a/rs/client-gen/tests/snapshots/generator__complex_type_generation_works.snap b/rs/client-gen/tests/snapshots/generator__complex_type_generation_works.snap index a0c1fd137..5514b9b1f 100644 --- a/rs/client-gen/tests/snapshots/generator__complex_type_generation_works.snap +++ b/rs/client-gen/tests/snapshots/generator__complex_type_generation_works.snap @@ -9,6 +9,10 @@ extern crate std; #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct ComplexTypesProgramProgram; +impl ComplexTypesProgramProgram { + pub const MY_COMPLEX_SERVICE_ROUTE_ID: u8 = 1; + pub const ANOTHER_SERVICE_ROUTE_ID: u8 = 2; +} impl sails_rs::client::Program for ComplexTypesProgramProgram {} pub trait ComplexTypesProgram { type Env: sails_rs::client::GearEnv; @@ -26,12 +30,12 @@ impl ComplexTypesProgram fn my_complex_service( &self, ) -> sails_rs::client::Service { - self.service(stringify!(MyComplexService)) + self.service(ComplexTypesProgramProgram::MY_COMPLEX_SERVICE_ROUTE_ID) } fn another_service( &self, ) -> sails_rs::client::Service { - self.service(stringify!(AnotherService)) + self.service(ComplexTypesProgramProgram::ANOTHER_SERVICE_ROUTE_ID) } } pub trait ComplexTypesProgramCtors { @@ -57,7 +61,7 @@ impl ComplexTypesProgramCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(NewProgram (initial_count: u32, id_prefix: String) -> ()); + sails_rs::io_struct_impl!(NewProgram (initial_count: u32, id_prefix: String) -> (), 0); } pub mod my_complex_service { @@ -174,6 +178,10 @@ pub mod my_complex_service { fn get_info(&self) -> sails_rs::client::PendingCall; } pub struct MyComplexServiceImpl; + impl sails_rs::client::Identifiable for MyComplexServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([125, 102, 14, 174, 143, 201, 77, 154]); + } impl MyComplexService for sails_rs::client::Service { @@ -220,12 +228,12 @@ pub mod my_complex_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(GetData (key: String) -> super::Result); - sails_rs::io_struct_impl!(Initialize (start_data: super::ProgramGlobalInfo, max_size: super::NonZeroU32) -> super::Result<(), super::ErrorType, >); - sails_rs::io_struct_impl!(ProcessGenericData (input_data: super::GenericData, list_of_generics: Vec>, optional_generic_result: super::Option, >) -> super::GenericData); - sails_rs::io_struct_impl!(UpdateStatus (id: u64, new_status: super::ServiceStatus, metadata: super::Option) -> super::GenericResult); - sails_rs::io_struct_impl!(GetActorIds (count: u32) -> Vec); - sails_rs::io_struct_impl!(GetInfo () -> super::ProgramGlobalInfo); + sails_rs::io_struct_impl!(GetData (key: String) -> super::Result, 0 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(Initialize (start_data: super::ProgramGlobalInfo, max_size: super::NonZeroU32) -> super::Result<(), super::ErrorType, >, 1 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(ProcessGenericData (input_data: super::GenericData, list_of_generics: Vec>, optional_generic_result: super::Option, >) -> super::GenericData, 2 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(UpdateStatus (id: u64, new_status: super::ServiceStatus, metadata: super::Option) -> super::GenericResult, 3 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(GetActorIds (count: u32) -> Vec, 4 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(GetInfo () -> super::ProgramGlobalInfo, 5 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] @@ -257,6 +265,10 @@ pub mod another_service { ) -> sails_rs::client::PendingCall; } pub struct AnotherServiceImpl; + impl sails_rs::client::Identifiable for AnotherServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([155, 46, 27, 116, 89, 52, 232, 187]); + } impl AnotherService for sails_rs::client::Service { @@ -274,8 +286,8 @@ pub mod another_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(Ping () -> String); - sails_rs::io_struct_impl!(ProcessValues (data: Vec) -> super::Result<(), super::ErrorType, >); + sails_rs::io_struct_impl!(Ping () -> String, 0 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(ProcessValues (data: Vec) -> super::Result<(), super::ErrorType, >, 1 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] diff --git a/rs/client-gen/tests/snapshots/generator__events_works.snap b/rs/client-gen/tests/snapshots/generator__events_works.snap index 034f80a46..953caf35d 100644 --- a/rs/client-gen/tests/snapshots/generator__events_works.snap +++ b/rs/client-gen/tests/snapshots/generator__events_works.snap @@ -29,6 +29,10 @@ pub mod service_with_events { ) -> sails_rs::client::PendingCall; } pub struct ServiceWithEventsImpl; + impl sails_rs::client::Identifiable for ServiceWithEventsImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([186, 231, 26, 185, 242, 135, 49, 106]); + } impl ServiceWithEvents for sails_rs::client::Service { @@ -44,7 +48,7 @@ pub mod service_with_events { pub mod io { use super::*; - sails_rs::io_struct_impl!(DoThis (p1: U256, p2: super::MyParam) -> u64); + sails_rs::io_struct_impl!(DoThis (p1: U256, p2: super::MyParam) -> u64, 0 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -54,13 +58,19 @@ pub mod service_with_events { #[codec(crate = sails_rs::scale_codec)] #[reflect_hash(crate = sails_rs)] pub enum ServiceWithEventsEvents { + #[codec(index = 0)] One(u64), + #[codec(index = 1)] Reset, + #[codec(index = 2)] Three(MyParam), + #[codec(index = 3)] Two { id: u8, reference: u64 }, } - impl sails_rs::client::Event for ServiceWithEventsEvents { - const EVENT_NAMES: &'static [Route] = &["One", "Reset", "Three", "Two"]; + impl sails_rs::client::Event for ServiceWithEventsEvents {} + impl sails_rs::client::Identifiable for ServiceWithEventsEvents { + const INTERFACE_ID: sails_rs::InterfaceId = + ::INTERFACE_ID; } impl sails_rs::client::ServiceWithEvents for ServiceWithEventsImpl { type Event = ServiceWithEventsEvents; diff --git a/rs/client-gen/tests/snapshots/generator__external_types.snap b/rs/client-gen/tests/snapshots/generator__external_types.snap index ca2920289..55fb38ac9 100644 --- a/rs/client-gen/tests/snapshots/generator__external_types.snap +++ b/rs/client-gen/tests/snapshots/generator__external_types.snap @@ -34,6 +34,10 @@ pub mod service { ) -> my_crate::sails::client::PendingCall; } pub struct ServiceImpl; + impl my_crate::sails::client::Identifiable for ServiceImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([82, 241, 49, 169, 231, 31, 0, 230]); + } impl Service for my_crate::sails::client::Service { @@ -55,7 +59,7 @@ pub mod service { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8); - my_crate::sails::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16); + my_crate::sails::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16, 1 , ::INTERFACE_ID); } } diff --git a/rs/client-gen/tests/snapshots/generator__full_with_sails_path.snap b/rs/client-gen/tests/snapshots/generator__full_with_sails_path.snap index 3276deb75..9e751adca 100644 --- a/rs/client-gen/tests/snapshots/generator__full_with_sails_path.snap +++ b/rs/client-gen/tests/snapshots/generator__full_with_sails_path.snap @@ -6,6 +6,20 @@ expression: code #[allow(unused_imports)] use my_crate::sails::{client::*, collections::*, prelude::*}; pub struct FullCoverageProgramProgram; +impl FullCoverageProgramProgram { + pub const CANVAS_ROUTE_ID: u8 = 1; + pub const PING_PONG_ROUTE_ID: u8 = 2; + pub const COUNTER_ROUTE_ID: u8 = 3; + pub const REFERENCES_ROUTE_ID: u8 = 4; + pub const THIS_THAT_ROUTE_ID: u8 = 5; + pub const VALUE_FEE_ROUTE_ID: u8 = 6; + pub const RMRK_CATALOG_ROUTE_ID: u8 = 7; + pub const NON_ZERO_PARAMS_ROUTE_ID: u8 = 8; + pub const SERVICE_WITH_EVENTS_ROUTE_ID: u8 = 9; + pub const BASIC_ROUTE_ID: u8 = 10; + pub const ANOTHER_SERVICE_ROUTE_ID: u8 = 11; + pub const MY_COMPLEX_SERVICE_ROUTE_ID: u8 = 12; +} impl my_crate::sails::client::Program for FullCoverageProgramProgram {} pub trait FullCoverageProgram { type Env: my_crate::sails::client::GearEnv; @@ -50,53 +64,53 @@ impl FullCoverageProgram { type Env = E; fn canvas(&self) -> my_crate::sails::client::Service { - self.service(stringify!(Canvas)) + self.service(FullCoverageProgramProgram::CANVAS_ROUTE_ID) } fn ping_pong(&self) -> my_crate::sails::client::Service { - self.service(stringify!(PingPong)) + self.service(FullCoverageProgramProgram::PING_PONG_ROUTE_ID) } fn counter(&self) -> my_crate::sails::client::Service { - self.service(stringify!(Counter)) + self.service(FullCoverageProgramProgram::COUNTER_ROUTE_ID) } fn references( &self, ) -> my_crate::sails::client::Service { - self.service(stringify!(References)) + self.service(FullCoverageProgramProgram::REFERENCES_ROUTE_ID) } fn this_that(&self) -> my_crate::sails::client::Service { - self.service(stringify!(ThisThat)) + self.service(FullCoverageProgramProgram::THIS_THAT_ROUTE_ID) } fn value_fee(&self) -> my_crate::sails::client::Service { - self.service(stringify!(ValueFee)) + self.service(FullCoverageProgramProgram::VALUE_FEE_ROUTE_ID) } fn rmrk_catalog( &self, ) -> my_crate::sails::client::Service { - self.service(stringify!(RmrkCatalog)) + self.service(FullCoverageProgramProgram::RMRK_CATALOG_ROUTE_ID) } fn non_zero_params( &self, ) -> my_crate::sails::client::Service { - self.service(stringify!(NonZeroParams)) + self.service(FullCoverageProgramProgram::NON_ZERO_PARAMS_ROUTE_ID) } fn service_with_events( &self, ) -> my_crate::sails::client::Service { - self.service(stringify!(ServiceWithEvents)) + self.service(FullCoverageProgramProgram::SERVICE_WITH_EVENTS_ROUTE_ID) } fn basic(&self) -> my_crate::sails::client::Service { - self.service(stringify!(Basic)) + self.service(FullCoverageProgramProgram::BASIC_ROUTE_ID) } fn another_service( &self, ) -> my_crate::sails::client::Service { - self.service(stringify!(AnotherService)) + self.service(FullCoverageProgramProgram::ANOTHER_SERVICE_ROUTE_ID) } fn my_complex_service( &self, ) -> my_crate::sails::client::Service { - self.service(stringify!(MyComplexService)) + self.service(FullCoverageProgramProgram::MY_COMPLEX_SERVICE_ROUTE_ID) } } pub trait FullCoverageProgramCtors { @@ -134,8 +148,8 @@ impl FullCoverageProgramCtors pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Default () -> ()); - my_crate::sails::io_struct_impl!(WithOwner (owner: ActorId, initial_config: super::ProgramConfig) -> ()); + my_crate::sails::io_struct_impl!(Default () -> (), 0); + my_crate::sails::io_struct_impl!(WithOwner (owner: ActorId, initial_config: super::ProgramConfig) -> (), 1); } #[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo, ReflectHash)] #[codec(crate = my_crate::sails::scale_codec)] @@ -233,6 +247,10 @@ pub mod canvas { ) -> my_crate::sails::client::Service; } pub struct CanvasImpl; + impl my_crate::sails::client::Identifiable for CanvasImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([159, 96, 48, 64, 97, 141, 24, 70]); + } impl Canvas for my_crate::sails::client::Service { @@ -282,10 +300,10 @@ pub mod canvas { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(ColorPoint (point: super::Point, color: super::Color) -> super::Result<(), super::ColorError>); - my_crate::sails::io_struct_impl!(KillPoint (point: super::Point) -> super::Result); - my_crate::sails::io_struct_impl!(Points (offset: u32, len: u32) -> super::Result, super::PointStatus, )>, String>); - my_crate::sails::io_struct_impl!(PointStatus (point: super::Point) -> super::Option); + my_crate::sails::io_struct_impl!(ColorPoint (point: super::Point, color: super::Color) -> super::Result<(), super::ColorError>, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(KillPoint (point: super::Point) -> super::Result, 1 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Points (offset: u32, len: u32) -> super::Result, super::PointStatus, )>, String>, 2 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(PointStatus (point: super::Point) -> super::Option, 3 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -295,16 +313,21 @@ pub mod canvas { #[codec(crate = my_crate::sails::scale_codec)] #[reflect_hash(crate = my_crate::sails)] pub enum CanvasEvents { + #[codec(index = 0)] E1, + #[codec(index = 1)] Jubilee { /// Amount of alive points. amount: u64, bits: Vec, }, + #[codec(index = 2)] StatusChanged(Point), } - impl my_crate::sails::client::Event for CanvasEvents { - const EVENT_NAMES: &'static [Route] = &["E1", "Jubilee", "StatusChanged"]; + impl my_crate::sails::client::Event for CanvasEvents {} + impl my_crate::sails::client::Identifiable for CanvasEvents { + const INTERFACE_ID: my_crate::sails::InterfaceId = + ::INTERFACE_ID; } impl my_crate::sails::client::ServiceWithEvents for CanvasImpl { type Event = CanvasEvents; @@ -322,6 +345,10 @@ pub mod ping_pong { ) -> my_crate::sails::client::PendingCall; } pub struct PingPongImpl; + impl my_crate::sails::client::Identifiable for PingPongImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([33, 189, 154, 154, 165, 29, 162, 100]); + } impl PingPong for my_crate::sails::client::Service { @@ -336,7 +363,7 @@ pub mod ping_pong { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Ping (input: String) -> super::Result); + my_crate::sails::io_struct_impl!(Ping (input: String) -> super::Result, 0 , ::INTERFACE_ID); } } @@ -352,6 +379,10 @@ pub mod counter { fn value(&self) -> my_crate::sails::client::PendingCall; } pub struct CounterImpl; + impl my_crate::sails::client::Identifiable for CounterImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([87, 157, 109, 171, 164, 27, 125, 130]); + } impl Counter for my_crate::sails::client::Service { @@ -369,9 +400,9 @@ pub mod counter { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Add (value: u32) -> u32); - my_crate::sails::io_struct_impl!(Sub (value: u32) -> u32); - my_crate::sails::io_struct_impl!(Value () -> u32); + my_crate::sails::io_struct_impl!(Add (value: u32) -> u32, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Sub (value: u32) -> u32, 1 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Value () -> u32, 2 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -382,12 +413,16 @@ pub mod counter { #[reflect_hash(crate = my_crate::sails)] pub enum CounterEvents { /// Emitted when a new value is added to the counter + #[codec(index = 0)] Added(u32), /// Emitted when a value is subtracted from the counter + #[codec(index = 1)] Subtracted(u32), } - impl my_crate::sails::client::Event for CounterEvents { - const EVENT_NAMES: &'static [Route] = &["Added", "Subtracted"]; + impl my_crate::sails::client::Event for CounterEvents {} + impl my_crate::sails::client::Identifiable for CounterEvents { + const INTERFACE_ID: my_crate::sails::InterfaceId = + ::INTERFACE_ID; } impl my_crate::sails::client::ServiceWithEvents for CounterImpl { type Event = CounterEvents; @@ -409,6 +444,10 @@ pub mod dog { fn position(&self) -> my_crate::sails::client::PendingCall; } pub struct DogImpl; + impl my_crate::sails::client::Identifiable for DogImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([75, 2, 200, 107, 128, 2, 138, 218]); + } impl Dog for my_crate::sails::client::Service { type Env = E; fn make_sound(&mut self) -> my_crate::sails::client::PendingCall { @@ -431,10 +470,10 @@ pub mod dog { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(MakeSound () -> String); - my_crate::sails::io_struct_impl!(Walk (dx: i32, dy: i32) -> ()); - my_crate::sails::io_struct_impl!(AvgWeight () -> u32); - my_crate::sails::io_struct_impl!(Position () -> (i32, i32, )); + my_crate::sails::io_struct_impl!(MakeSound () -> String, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Walk (dx: i32, dy: i32) -> (), 1 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(AvgWeight () -> u32, 2 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Position () -> (i32, i32, ), 3 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -444,11 +483,15 @@ pub mod dog { #[codec(crate = my_crate::sails::scale_codec)] #[reflect_hash(crate = my_crate::sails)] pub enum DogEvents { + #[codec(index = 0)] Barked, + #[codec(index = 1)] Walked { from: (i32, i32), to: (i32, i32) }, } - impl my_crate::sails::client::Event for DogEvents { - const EVENT_NAMES: &'static [Route] = &["Barked", "Walked"]; + impl my_crate::sails::client::Event for DogEvents {} + impl my_crate::sails::client::Identifiable for DogEvents { + const INTERFACE_ID: my_crate::sails::InterfaceId = + ::INTERFACE_ID; } impl my_crate::sails::client::ServiceWithEvents for DogImpl { type Event = DogEvents; @@ -484,6 +527,10 @@ pub mod references { fn message(&self) -> my_crate::sails::client::PendingCall; } pub struct ReferencesImpl; + impl my_crate::sails::client::Identifiable for ReferencesImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([61, 171, 145, 177, 150, 71, 129, 98]); + } impl References for my_crate::sails::client::Service { @@ -525,14 +572,14 @@ pub mod references { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Add (v: u32) -> u32); - my_crate::sails::io_struct_impl!(AddByte (byte: u8) -> Vec); - my_crate::sails::io_struct_impl!(GuessNum (number: u8) -> super::Result); - my_crate::sails::io_struct_impl!(Incr () -> super::ReferenceCount); - my_crate::sails::io_struct_impl!(SetNum (number: u8) -> super::Result<(), String>); - my_crate::sails::io_struct_impl!(Baked () -> String); - my_crate::sails::io_struct_impl!(LastByte () -> super::Option); - my_crate::sails::io_struct_impl!(Message () -> super::Option); + my_crate::sails::io_struct_impl!(Add (v: u32) -> u32, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(AddByte (byte: u8) -> Vec, 1 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(GuessNum (number: u8) -> super::Result, 2 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Incr () -> super::ReferenceCount, 3 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(SetNum (number: u8) -> super::Result<(), String>, 4 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Baked () -> String, 5 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(LastByte () -> super::Option, 6 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Message () -> super::Option, 7 , ::INTERFACE_ID); } } @@ -594,6 +641,10 @@ pub mod this_that { fn this(&self) -> my_crate::sails::client::PendingCall; } pub struct ThisThatImpl; + impl my_crate::sails::client::Identifiable for ThisThatImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([220, 131, 135, 131, 19, 27, 44, 105]); + } impl ThisThat for my_crate::sails::client::Service { @@ -626,11 +677,11 @@ pub mod this_that { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(DoThat (param: super::DoThatParam) -> super::Result<(ActorId, u32, super::ManyVariantsReply, ), (String, )>); - my_crate::sails::io_struct_impl!(DoThis (p1: u32, p2: String, p3: (super::Option, u8, ), p4: super::TupleStruct) -> (String, u32, )); - my_crate::sails::io_struct_impl!(Noop () -> ()); - my_crate::sails::io_struct_impl!(That () -> super::Result); - my_crate::sails::io_struct_impl!(This () -> u32); + my_crate::sails::io_struct_impl!(DoThat (param: super::DoThatParam) -> super::Result<(ActorId, u32, super::ManyVariantsReply, ), (String, )>, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(DoThis (p1: u32, p2: String, p3: (super::Option, u8, ), p4: super::TupleStruct) -> (String, u32, ), 1 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Noop () -> (), 2 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(That () -> super::Result, 3 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(This () -> u32, 4 , ::INTERFACE_ID); } } @@ -645,6 +696,10 @@ pub mod value_fee { ) -> my_crate::sails::client::PendingCall; } pub struct ValueFeeImpl; + impl my_crate::sails::client::Identifiable for ValueFeeImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([65, 193, 8, 11, 78, 30, 141, 197]); + } impl ValueFee for my_crate::sails::client::Service { @@ -658,7 +713,7 @@ pub mod value_fee { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(DoSomethingAndTakeFee () -> bool); + my_crate::sails::io_struct_impl!(DoSomethingAndTakeFee () -> bool, 0 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -668,10 +723,13 @@ pub mod value_fee { #[codec(crate = my_crate::sails::scale_codec)] #[reflect_hash(crate = my_crate::sails)] pub enum ValueFeeEvents { + #[codec(index = 0)] Withheld(u128), } - impl my_crate::sails::client::Event for ValueFeeEvents { - const EVENT_NAMES: &'static [Route] = &["Withheld"]; + impl my_crate::sails::client::Event for ValueFeeEvents {} + impl my_crate::sails::client::Identifiable for ValueFeeEvents { + const INTERFACE_ID: my_crate::sails::InterfaceId = + ::INTERFACE_ID; } impl my_crate::sails::client::ServiceWithEvents for ValueFeeImpl { type Event = ValueFeeEvents; @@ -692,6 +750,10 @@ pub mod pausable { fn unpause(&mut self) -> my_crate::sails::client::PendingCall; } pub struct PausableImpl; + impl my_crate::sails::client::Identifiable for PausableImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([119, 153, 244, 54, 223, 215, 83, 198]); + } impl Pausable for my_crate::sails::client::Service { @@ -706,8 +768,8 @@ pub mod pausable { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Pause () -> ()); - my_crate::sails::io_struct_impl!(Unpause () -> ()); + my_crate::sails::io_struct_impl!(Pause () -> (), 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Unpause () -> (), 1 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -717,11 +779,15 @@ pub mod pausable { #[codec(crate = my_crate::sails::scale_codec)] #[reflect_hash(crate = my_crate::sails)] pub enum PausableEvents { + #[codec(index = 0)] Paused, + #[codec(index = 1)] Unpaused, } - impl my_crate::sails::client::Event for PausableEvents { - const EVENT_NAMES: &'static [Route] = &["Paused", "Unpaused"]; + impl my_crate::sails::client::Event for PausableEvents {} + impl my_crate::sails::client::Identifiable for PausableEvents { + const INTERFACE_ID: my_crate::sails::InterfaceId = + ::INTERFACE_ID; } impl my_crate::sails::client::ServiceWithEvents for PausableImpl { type Event = PausableEvents; @@ -736,6 +802,10 @@ pub mod ownable { fn get_owner(&mut self) -> my_crate::sails::client::PendingCall; } pub struct OwnableImpl; + impl my_crate::sails::client::Identifiable for OwnableImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([45, 223, 161, 186, 121, 8, 187, 243]); + } impl Ownable for my_crate::sails::client::Service { @@ -747,7 +817,7 @@ pub mod ownable { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(GetOwner () -> ActorId); + my_crate::sails::io_struct_impl!(GetOwner () -> ActorId, 0 , ::INTERFACE_ID); } } @@ -759,6 +829,10 @@ pub mod tippable { -> my_crate::sails::client::PendingCall; } pub struct TippableImpl; + impl my_crate::sails::client::Identifiable for TippableImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([237, 182, 209, 207, 204, 160, 182, 70]); + } impl Tippable for my_crate::sails::client::Service { @@ -773,7 +847,7 @@ pub mod tippable { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Tip (amount: u128) -> ()); + my_crate::sails::io_struct_impl!(Tip (amount: u128) -> (), 0 , ::INTERFACE_ID); } } @@ -797,6 +871,10 @@ pub mod non_zero_params { ) -> my_crate::sails::client::PendingCall; } pub struct NonZeroParamsImpl; + impl my_crate::sails::client::Identifiable for NonZeroParamsImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([247, 238, 3, 214, 44, 137, 30, 3]); + } impl NonZeroParams for my_crate::sails::client::Service { @@ -812,7 +890,7 @@ pub mod non_zero_params { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(DoThis (p1: U256, p2: super::MyParam) -> u64); + my_crate::sails::io_struct_impl!(DoThis (p1: U256, p2: super::MyParam) -> u64, 0 , ::INTERFACE_ID); } } @@ -836,6 +914,10 @@ pub mod service_with_events { ) -> my_crate::sails::client::PendingCall; } pub struct ServiceWithEventsImpl; + impl my_crate::sails::client::Identifiable for ServiceWithEventsImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([192, 205, 152, 45, 145, 112, 193, 0]); + } impl ServiceWithEvents for my_crate::sails::client::Service { @@ -851,7 +933,7 @@ pub mod service_with_events { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(DoThis (p1: U256, p2: super::MyParam) -> u64); + my_crate::sails::io_struct_impl!(DoThis (p1: U256, p2: super::MyParam) -> u64, 0 , ::INTERFACE_ID); } #[cfg(not(target_arch = "wasm32"))] @@ -861,11 +943,15 @@ pub mod service_with_events { #[codec(crate = my_crate::sails::scale_codec)] #[reflect_hash(crate = my_crate::sails)] pub enum ServiceWithEventsEvents { + #[codec(index = 0)] Event1(u32), + #[codec(index = 1)] Event2 { field1: String, field2: u64 }, } - impl my_crate::sails::client::Event for ServiceWithEventsEvents { - const EVENT_NAMES: &'static [Route] = &["Event1", "Event2"]; + impl my_crate::sails::client::Event for ServiceWithEventsEvents {} + impl my_crate::sails::client::Identifiable for ServiceWithEventsEvents { + const INTERFACE_ID: my_crate::sails::InterfaceId = + ::INTERFACE_ID; } impl my_crate::sails::client::ServiceWithEvents for ServiceWithEventsImpl { type Event = ServiceWithEventsEvents; @@ -908,6 +994,10 @@ pub mod basic { ) -> my_crate::sails::client::PendingCall; } pub struct BasicImpl; + impl my_crate::sails::client::Identifiable for BasicImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([82, 241, 49, 169, 231, 31, 0, 230]); + } impl Basic for my_crate::sails::client::Service { type Env = E; fn do_that( @@ -927,8 +1017,8 @@ pub mod basic { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8); - my_crate::sails::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16); + my_crate::sails::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16, 1 , ::INTERFACE_ID); } } @@ -951,6 +1041,10 @@ pub mod another_service { ) -> my_crate::sails::client::PendingCall; } pub struct AnotherServiceImpl; + impl my_crate::sails::client::Identifiable for AnotherServiceImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([98, 254, 176, 83, 233, 74, 173, 234]); + } impl AnotherService for my_crate::sails::client::Service { @@ -968,8 +1062,8 @@ pub mod another_service { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(Ping () -> String); - my_crate::sails::io_struct_impl!(ProcessValues (data: Vec) -> super::Result<(), super::ProgramError>); + my_crate::sails::io_struct_impl!(Ping () -> String, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(ProcessValues (data: Vec) -> super::Result<(), super::ProgramError>, 1 , ::INTERFACE_ID); } } @@ -1080,6 +1174,10 @@ pub mod my_complex_service { ) -> my_crate::sails::client::PendingCall; } pub struct MyComplexServiceImpl; + impl my_crate::sails::client::Identifiable for MyComplexServiceImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([86, 209, 202, 3, 195, 8, 232, 253]); + } impl MyComplexService for my_crate::sails::client::Service { @@ -1126,12 +1224,12 @@ pub mod my_complex_service { pub mod io { use super::*; - my_crate::sails::io_struct_impl!(GetActorIds (count: u32) -> Vec); - my_crate::sails::io_struct_impl!(GetData (key: String) -> super::Result); - my_crate::sails::io_struct_impl!(GetInfo () -> super::ProgramGlobalInfo); - my_crate::sails::io_struct_impl!(Initialize (start_data: super::ProgramGlobalInfo, max_size: u32) -> super::Result<(), super::ProgramError>); - my_crate::sails::io_struct_impl!(ProcessGenericData (input_data: super::GenericData, list_of_generics: Vec>, optional_generic_result: super::Option, >) -> super::GenericData); - my_crate::sails::io_struct_impl!(UpdateStatus (id: u64, new_status: super::ServiceStatus, metadata: super::Option) -> super::GenericResult); + my_crate::sails::io_struct_impl!(GetActorIds (count: u32) -> Vec, 0 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(GetData (key: String) -> super::Result, 1 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(GetInfo () -> super::ProgramGlobalInfo, 2 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(Initialize (start_data: super::ProgramGlobalInfo, max_size: u32) -> super::Result<(), super::ProgramError>, 3 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(ProcessGenericData (input_data: super::GenericData, list_of_generics: Vec>, optional_generic_result: super::Option, >) -> super::GenericData, 4 , ::INTERFACE_ID); + my_crate::sails::io_struct_impl!(UpdateStatus (id: u64, new_status: super::ServiceStatus, metadata: super::Option) -> super::GenericResult, 5 , ::INTERFACE_ID); } } @@ -1141,6 +1239,10 @@ pub mod rmrk_catalog { type Env: my_crate::sails::client::GearEnv; } pub struct RmrkCatalogImpl; + impl my_crate::sails::client::Identifiable for RmrkCatalogImpl { + const INTERFACE_ID: my_crate::sails::InterfaceId = + my_crate::sails::InterfaceId::from_bytes_8([197, 210, 70, 1, 134, 247, 35, 60]); + } impl RmrkCatalog for my_crate::sails::client::Service { diff --git a/rs/client-gen/tests/snapshots/generator__multiple_services.snap b/rs/client-gen/tests/snapshots/generator__multiple_services.snap index 15013c31d..e0a2bbe6d 100644 --- a/rs/client-gen/tests/snapshots/generator__multiple_services.snap +++ b/rs/client-gen/tests/snapshots/generator__multiple_services.snap @@ -31,6 +31,10 @@ pub mod multiple { ) -> sails_rs::client::PendingCall; } pub struct MultipleImpl; + impl sails_rs::client::Identifiable for MultipleImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([2, 24, 22, 148, 109, 93, 75, 194]); + } impl Multiple for sails_rs::client::Service { type Env = E; fn do_that( @@ -50,8 +54,8 @@ pub mod multiple { pub mod io { use super::*; - sails_rs::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8); - sails_rs::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16); + sails_rs::io_struct_impl!(DoThat (p1: (u8, u32, )) -> u8, 0 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(DoThis (p1: u32, p2: super::MyParam) -> u16, 1 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] @@ -70,6 +74,10 @@ pub mod named { fn that(&self, p1: u32) -> sails_rs::client::PendingCall; } pub struct NamedImpl; + impl sails_rs::client::Identifiable for NamedImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([81, 188, 228, 30, 50, 153, 227, 193]); + } impl Named for sails_rs::client::Service { type Env = E; fn that(&self, p1: u32) -> sails_rs::client::PendingCall { @@ -79,7 +87,7 @@ pub mod named { pub mod io { use super::*; - sails_rs::io_struct_impl!(That (p1: u32) -> String); + sails_rs::io_struct_impl!(That (p1: u32) -> String, 0 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] diff --git a/rs/client-gen/tests/snapshots/generator__rmrk_works.snap b/rs/client-gen/tests/snapshots/generator__rmrk_works.snap index f19b699ad..368a2e0bd 100644 --- a/rs/client-gen/tests/snapshots/generator__rmrk_works.snap +++ b/rs/client-gen/tests/snapshots/generator__rmrk_works.snap @@ -9,6 +9,9 @@ extern crate std; #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct RmrkCatalogProgram; +impl RmrkCatalogProgram { + pub const RMRK_CATALOG_SERVICE_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for RmrkCatalogProgram {} pub trait RmrkCatalog { type Env: sails_rs::client::GearEnv; @@ -21,7 +24,7 @@ impl RmrkCatalog for sails_rs::client::Actor sails_rs::client::Service { - self.service(stringify!(RmrkCatalogService)) + self.service(RmrkCatalogProgram::RMRK_CATALOG_SERVICE_ROUTE_ID) } } pub trait RmrkCatalogCtors { @@ -41,7 +44,7 @@ impl RmrkCatalogCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(New () -> ()); + sails_rs::io_struct_impl!(New () -> (), 0); } pub mod rmrk_catalog_service { @@ -128,6 +131,10 @@ pub mod rmrk_catalog_service { fn part(&self, part_id: u32) -> sails_rs::client::PendingCall; } pub struct RmrkCatalogServiceImpl; + impl sails_rs::client::Identifiable for RmrkCatalogServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([55, 233, 20, 71, 187, 19, 237, 60]); + } impl RmrkCatalogService for sails_rs::client::Service { @@ -184,14 +191,14 @@ pub mod rmrk_catalog_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(AddEquippables (part_id: u32, collection_ids: Vec) -> super::Result<(u32, Vec, ), super::Error, >); - sails_rs::io_struct_impl!(AddParts (parts: Vec<(u32, super::Part, )>) -> super::Result, super::Error, >); - sails_rs::io_struct_impl!(RemoveEquippable (part_id: u32, collection_id: ActorId) -> super::Result<(u32, ActorId, ), super::Error, >); - sails_rs::io_struct_impl!(RemoveParts (part_ids: Vec) -> super::Result, super::Error, >); - sails_rs::io_struct_impl!(ResetEquippables (part_id: u32) -> super::Result<(), super::Error, >); - sails_rs::io_struct_impl!(SetEquippablesToAll (part_id: u32) -> super::Result<(), super::Error, >); - sails_rs::io_struct_impl!(Equippable (part_id: u32, collection_id: ActorId) -> super::Result); - sails_rs::io_struct_impl!(Part (part_id: u32) -> super::Option); + sails_rs::io_struct_impl!(AddEquippables (part_id: u32, collection_ids: Vec) -> super::Result<(u32, Vec, ), super::Error, >, 0 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(AddParts (parts: Vec<(u32, super::Part, )>) -> super::Result, super::Error, >, 1 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(RemoveEquippable (part_id: u32, collection_id: ActorId) -> super::Result<(u32, ActorId, ), super::Error, >, 2 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(RemoveParts (part_ids: Vec) -> super::Result, super::Error, >, 3 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(ResetEquippables (part_id: u32) -> super::Result<(), super::Error, >, 4 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(SetEquippablesToAll (part_id: u32) -> super::Result<(), super::Error, >, 5 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(Equippable (part_id: u32, collection_id: ActorId) -> super::Result, 6 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(Part (part_id: u32) -> super::Option, 7 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] diff --git a/rs/client-gen/tests/snapshots/generator__scope_resolution.snap b/rs/client-gen/tests/snapshots/generator__scope_resolution.snap index 156eb409e..2aeabe381 100644 --- a/rs/client-gen/tests/snapshots/generator__scope_resolution.snap +++ b/rs/client-gen/tests/snapshots/generator__scope_resolution.snap @@ -9,6 +9,9 @@ extern crate std; #[allow(unused_imports)] use sails_rs::{client::*, collections::*, prelude::*}; pub struct MyProgramProgram; +impl MyProgramProgram { + pub const MY_SERVICE_ROUTE_ID: u8 = 1; +} impl sails_rs::client::Program for MyProgramProgram {} pub trait MyProgram { type Env: sails_rs::client::GearEnv; @@ -17,7 +20,7 @@ pub trait MyProgram { impl MyProgram for sails_rs::client::Actor { type Env = E; fn my_service(&self) -> sails_rs::client::Service { - self.service(stringify!(MyService)) + self.service(MyProgramProgram::MY_SERVICE_ROUTE_ID) } } pub trait MyProgramCtors { @@ -35,7 +38,7 @@ impl MyProgramCtors pub mod io { use super::*; - sails_rs::io_struct_impl!(Init () -> ()); + sails_rs::io_struct_impl!(Init () -> (), 0); } #[derive(PartialEq, Clone, Debug, Encode, Decode, TypeInfo, ReflectHash)] #[codec(crate = sails_rs::scale_codec)] @@ -94,6 +97,10 @@ pub mod my_service { ) -> sails_rs::client::PendingCall; } pub struct MyServiceImpl; + impl sails_rs::client::Identifiable for MyServiceImpl { + const INTERFACE_ID: sails_rs::InterfaceId = + sails_rs::InterfaceId::from_bytes_8([253, 255, 66, 173, 41, 217, 46, 249]); + } impl MyService for sails_rs::client::Service { type Env = E; fn another_action( @@ -118,9 +125,9 @@ pub mod my_service { pub mod io { use super::*; - sails_rs::io_struct_impl!(AnotherAction (input: super::ServiceCommonType) -> u32); - sails_rs::io_struct_impl!(DoSomething (input: super::CommonType) -> u32); - sails_rs::io_struct_impl!(UseProgramType (input: super::ProgramOnlyType) -> bool); + sails_rs::io_struct_impl!(AnotherAction (input: super::ServiceCommonType) -> u32, 0 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(DoSomething (input: super::CommonType) -> u32, 1 , ::INTERFACE_ID); + sails_rs::io_struct_impl!(UseProgramType (input: super::ProgramOnlyType) -> bool, 2 , ::INTERFACE_ID); } #[cfg(feature = "with_mocks")] diff --git a/rs/src/header.rs b/rs/idl-meta/src/header.rs similarity index 99% rename from rs/src/header.rs rename to rs/idl-meta/src/header.rs index ff777dc58..83edc1d1f 100644 --- a/rs/src/header.rs +++ b/rs/idl-meta/src/header.rs @@ -1,8 +1,5 @@ -use crate::{ - Vec, - meta::InterfaceId, - scale_codec::{Decode, Encode, Error, Input, Output}, -}; +use crate::{InterfaceId, Vec}; +use parity_scale_codec::{Decode, Encode, Error, Input, Output}; /// Sails protocol highest supported version. pub const HIGHEST_SUPPORTED_VERSION: u8 = 1; diff --git a/rs/idl-meta/src/lib.rs b/rs/idl-meta/src/lib.rs index 01c2aa2ac..c78874eff 100644 --- a/rs/idl-meta/src/lib.rs +++ b/rs/idl-meta/src/lib.rs @@ -16,6 +16,9 @@ pub use ast::*; use parity_scale_codec::{Decode, Encode, Error}; use scale_info::{MetaType, StaticTypeInfo, prelude::vec::Vec}; +mod header; +pub use header::*; + pub type AnyServiceMetaFn = fn() -> AnyServiceMeta; /// Unique identifier for a service (or "interface" in terms of sails binary protocol). diff --git a/rs/src/client/gclient_env.rs b/rs/src/client/gclient_env.rs index 33ba49ec4..aab672459 100644 --- a/rs/src/client/gclient_env.rs +++ b/rs/src/client/gclient_env.rs @@ -88,7 +88,7 @@ impl GearEnv for GclientEnv { type MessageState = Pin), GclientError>>>>; } -impl PendingCall { +impl PendingCall { pub async fn send_one_way(&mut self) -> Result { let (payload, params) = self.take_encoded_args_and_params(); self.env @@ -112,12 +112,12 @@ impl PendingCall { query_calculate_reply(&self.env.api, self.destination, payload, params).await?; // Decode reply - T::decode_reply_with_prefix(self.route, reply_bytes) + T::decode_reply_with_header(self.route_idx, reply_bytes) .map_err(|err| gclient::Error::Codec(err).into()) } } -impl Future for PendingCall { +impl Future for PendingCall { type Output = Result::Error>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -136,7 +136,7 @@ impl Future for PendingCall { .unwrap_or_else(|| panic!("{PENDING_CALL_INVALID_STATE}")); // Poll message future match ready!(message_future.poll(cx)) { - Ok((_, payload)) => match T::decode_reply_with_prefix(self.route, payload) { + Ok((_, payload)) => match T::decode_reply_with_header(self.route_idx, payload) { Ok(decoded) => Poll::Ready(Ok(decoded)), Err(err) => Poll::Ready(Err(gclient::Error::Codec(err).into())), }, diff --git a/rs/src/client/gstd_env.rs b/rs/src/client/gstd_env.rs index b4515e72a..3d564ac85 100644 --- a/rs/src/client/gstd_env.rs +++ b/rs/src/client/gstd_env.rs @@ -43,7 +43,7 @@ impl GstdParams { } } -impl PendingCall { +impl PendingCall { /// Set `redirect_on_exit` flag to `true`` /// /// This flag is used to redirect a message to a new program when the target program exits @@ -103,7 +103,7 @@ impl GstdEnv { } } -impl PendingCall { +impl PendingCall { pub fn send_one_way(&mut self) -> Result { let (payload, params) = self.take_encoded_args_and_params(); self.env.send_one_way(self.destination, payload, params) @@ -181,7 +181,7 @@ const _: () = { } } - impl Future for PendingCall { + impl Future for PendingCall { type Output = Result::Error>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -190,7 +190,7 @@ const _: () = { .args .as_ref() .unwrap_or_else(|| panic!("{PENDING_CALL_INVALID_STATE}")); - let payload = T::encode_params_with_prefix(self.route, &args); + let payload = T::encode_params_with_header(self.route_idx, &args); let destination = self.destination; let params = self.params.get_or_insert_default(); // Send message @@ -211,8 +211,8 @@ const _: () = { match output { // ok reply Ok(payload) => { - let res = - T::decode_reply_with_prefix(self.route, payload).map_err(Error::Decode)?; + let res = T::decode_reply_with_header(self.route_idx, payload) + .map_err(Error::Decode)?; Poll::Ready(Ok(res)) } // reply with ProgramExited @@ -349,7 +349,7 @@ pin_project_lite::pin_project! { #[cfg(not(target_arch = "wasm32"))] const _: () = { - impl PendingCall + impl PendingCall where T::Reply: Encode + Decode, { @@ -365,7 +365,7 @@ const _: () = { PendingCall { env: GstdEnv, destination: ActorId::zero(), - route: "", + route_idx: 0, params: None, args: None, state: Some(future::ready(res.map(|v| v.encode()))), @@ -373,7 +373,7 @@ const _: () = { } } - impl, O> From for PendingCall + impl, O> From for PendingCall where O: Encode + Decode, { @@ -382,7 +382,7 @@ const _: () = { } } - impl Future for PendingCall { + impl Future for PendingCall { type Output = Result::Error>; fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { diff --git a/rs/src/client/gtest_env.rs b/rs/src/client/gtest_env.rs index 24f910f30..91eff06f1 100644 --- a/rs/src/client/gtest_env.rs +++ b/rs/src/client/gtest_env.rs @@ -274,7 +274,7 @@ impl GearEnv for GtestEnv { type MessageState = ReplyReceiver; } -impl PendingCall { +impl PendingCall { pub fn send_one_way(&mut self) -> Result { if self.state.is_some() { panic!("{PENDING_CALL_INVALID_STATE}"); @@ -298,12 +298,12 @@ impl PendingCall { let reply_bytes = self.env.query(self.destination, payload, params)?; // Decode reply - T::decode_reply_with_prefix(self.route, reply_bytes) + T::decode_reply_with_header(self.route_idx, reply_bytes) .map_err(|err| TestError::ScaleCodecError(err).into()) } } -impl Future for PendingCall { +impl Future for PendingCall { type Output = Result::Error>; fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { @@ -330,7 +330,7 @@ impl Future for PendingCall { // Poll reply receiver match ready!(reply_receiver.poll(cx)) { Ok(res) => match res { - Ok(payload) => match T::decode_reply_with_prefix(self.route, payload) { + Ok(payload) => match T::decode_reply_with_header(self.route_idx, payload) { Ok(reply) => Poll::Ready(Ok(reply)), Err(err) => Poll::Ready(Err(TestError::ScaleCodecError(err).into())), }, diff --git a/rs/src/client/mod.rs b/rs/src/client/mod.rs index 359a1d593..37dd7902b 100644 --- a/rs/src/client/mod.rs +++ b/rs/src/client/mod.rs @@ -1,3 +1,4 @@ +use crate::meta::SailsMessageHeader; use crate::prelude::*; use core::{ any::TypeId, @@ -7,6 +8,7 @@ use core::{ task::{Context, Poll}, }; use futures::Stream; +pub use sails_idl_meta::InterfaceId; #[cfg(feature = "gtest")] #[cfg(not(target_arch = "wasm32"))] @@ -50,8 +52,6 @@ pub trait Program: Sized { } } -pub type Route = &'static str; - #[derive(Debug, Clone)] pub struct Deployment { env: E, @@ -128,25 +128,29 @@ impl Actor { self } - pub fn service(&self, route: Route) -> Service { - Service::new(self.env.clone(), self.id, route) + pub fn service(&self, route_idx: u8) -> Service { + Service::new(self.env.clone(), self.id, route_idx) } } +pub trait Identifiable { + const INTERFACE_ID: InterfaceId; +} + #[derive(Debug, Clone)] pub struct Service { env: E, actor_id: ActorId, - route: Route, + route_idx: u8, _phantom: PhantomData, } impl Service { - pub fn new(env: E, actor_id: ActorId, route: Route) -> Self { + pub fn new(env: E, actor_id: ActorId, route_idx: u8) -> Self { Service { env, actor_id, - route, + route_idx, _phantom: PhantomData, } } @@ -155,8 +159,15 @@ impl Service { self.actor_id } - pub fn route(&self) -> Route { - self.route + pub fn interface_id(&self) -> InterfaceId + where + S: Identifiable, + { + S::INTERFACE_ID + } + + pub fn route_idx(&self) -> u8 { + self.route_idx } pub fn with_actor_id(mut self, actor_id: ActorId) -> Self { @@ -164,12 +175,27 @@ impl Service { self } - pub fn pending_call(&self, args: T::Params) -> PendingCall { - PendingCall::new(self.env.clone(), self.actor_id, self.route, args) + pub fn pending_call(&self, args: T::Params) -> PendingCall { + PendingCall::new(self.env.clone(), self.actor_id, self.route_idx, args) } pub fn base_service(&self) -> Service { - Service::new(self.env.clone(), self.actor_id, self.route) + Service::new(self.env.clone(), self.actor_id, self.route_idx) + } + + pub fn decode_reply( + &self, + payload: impl AsRef<[u8]>, + ) -> Result { + T::decode_reply_with_header(self.route_idx, payload) + } + + #[cfg(not(target_arch = "wasm32"))] + pub fn decode_event( + &self, + payload: impl AsRef<[u8]>, + ) -> Result { + Ev::decode_event(self.route_idx, payload) } #[cfg(not(target_arch = "wasm32"))] @@ -177,7 +203,7 @@ impl Service { where S: ServiceWithEvents, { - ServiceListener::new(self.env.clone(), self.actor_id, self.route) + ServiceListener::new(self.env.clone(), self.actor_id, self.route_idx) } } @@ -190,17 +216,17 @@ pub trait ServiceWithEvents { pub struct ServiceListener { env: E, actor_id: ActorId, - route: Route, + route_idx: u8, _phantom: PhantomData, } #[cfg(not(target_arch = "wasm32"))] impl ServiceListener { - pub fn new(env: E, actor_id: ActorId, route: Route) -> Self { + pub fn new(env: E, actor_id: ActorId, route_idx: u8) -> Self { ServiceListener { env, actor_id, - route, + route_idx, _phantom: PhantomData, } } @@ -212,23 +238,25 @@ impl ServiceListener { E: Listener::Error>, { let self_id = self.actor_id; - let prefix = self.route; + let route_idx = self.route_idx; self.env .listen(move |(actor_id, payload)| { if actor_id != self_id { return None; } - D::decode_event(prefix, payload).ok().map(|e| (actor_id, e)) + D::decode_event(route_idx, payload) + .ok() + .map(|e| (actor_id, e)) }) .await } } pin_project_lite::pin_project! { - pub struct PendingCall { + pub struct PendingCall { env: E, destination: ActorId, - route: Route, + route_idx: u8, params: Option, args: Option, #[pin] @@ -236,12 +264,12 @@ pin_project_lite::pin_project! { } } -impl PendingCall { - pub fn new(env: E, destination: ActorId, route: Route, args: T::Params) -> Self { +impl PendingCall { + pub fn new(env: E, destination: ActorId, route_idx: u8, args: T::Params) -> Self { PendingCall { env, destination, - route, + route_idx, params: None, args: Some(args), state: None, @@ -258,13 +286,18 @@ impl PendingCall { self } + pub fn encode_call(mut self) -> Vec { + let (payload, _) = self.take_encoded_args_and_params(); + payload + } + #[inline] fn take_encoded_args_and_params(&mut self) -> (Vec, E::Params) { let args = self .args .take() .unwrap_or_else(|| panic!("{PENDING_CALL_INVALID_STATE}")); - let payload = T::encode_params_with_prefix(self.route, &args); + let payload = T::encode_params_with_header(self.route_idx, &args); let params = self.params.take().unwrap_or_default(); (payload, params) } @@ -302,30 +335,23 @@ impl PendingCtor { self.params = Some(f(self.params.unwrap_or_default())); self } + + pub fn encode_params(mut self) -> Vec { + let args = self + .args + .take() + .unwrap_or_else(|| panic!("{PENDING_CTOR_INVALID_STATE}")); + T::encode_params(&args) + } } pub trait CallCodec { - const ROUTE: Route; + const ENTRY_ID: u16; type Params: Encode; type Reply: Decode + 'static; fn encode_params(value: &Self::Params) -> Vec { - let size = Encode::encoded_size(Self::ROUTE) + Encode::encoded_size(value); - let mut result = Vec::with_capacity(size); - Encode::encode_to(Self::ROUTE, &mut result); - Encode::encode_to(value, &mut result); - result - } - - fn encode_params_with_prefix(prefix: Route, value: &Self::Params) -> Vec { - let size = Encode::encoded_size(prefix) - + Encode::encoded_size(Self::ROUTE) - + Encode::encoded_size(value); - let mut result = Vec::with_capacity(size); - Encode::encode_to(prefix, &mut result); - Encode::encode_to(Self::ROUTE, &mut result); - Encode::encode_to(value, &mut result); - result + value.encode() } fn decode_reply(payload: impl AsRef<[u8]>) -> Result { @@ -333,54 +359,73 @@ pub trait CallCodec { if Self::is_empty_tuple::() { return Decode::decode(&mut value); } - // Decode payload as `(String, Self::Reply)` - let route = String::decode(&mut value)?; - if route != Self::ROUTE { - return Err("Invalid reply prefix".into()); + let header = SailsMessageHeader::decode(&mut value)?; + if header.entry_id() != Self::ENTRY_ID { + return Err("Invalid reply entry_id".into()); } Decode::decode(&mut value) } - fn decode_reply_with_prefix( - prefix: Route, + fn is_empty_tuple() -> bool { + TypeId::of::() == TypeId::of::<()>() + } +} + +pub trait ServiceCall: CallCodec + Identifiable { + fn encode_params_with_header(route_idx: u8, value: &Self::Params) -> Vec { + let header = SailsMessageHeader::new( + crate::meta::Version::v1(), + crate::meta::HeaderLength::new(crate::meta::MINIMAL_HLEN).unwrap(), + Self::INTERFACE_ID, + route_idx, + Self::ENTRY_ID, + ); + let mut result = header.to_bytes(); + value.encode_to(&mut result); + result + } + + fn decode_reply_with_header( + route_idx: u8, payload: impl AsRef<[u8]>, ) -> Result { let mut value = payload.as_ref(); if Self::is_empty_tuple::() { return Decode::decode(&mut value); } - // Decode payload as `(String, String, Self::Reply)` - let route = String::decode(&mut value)?; - if route != prefix { - return Err("Invalid reply prefix".into()); + let header = SailsMessageHeader::decode(&mut value)?; + if header.interface_id() != Self::INTERFACE_ID { + return Err("Invalid reply interface_id".into()); } - let route = String::decode(&mut value)?; - if route != Self::ROUTE { - return Err("Invalid reply prefix".into()); + if header.route_id() != route_idx { + return Err("Invalid reply route_idx".into()); + } + if header.entry_id() != Self::ENTRY_ID { + return Err("Invalid reply entry_id".into()); } Decode::decode(&mut value) } fn with_optimized_encode( - prefix: Route, + route_idx: u8, value: &Self::Params, f: impl FnOnce(&[u8]) -> R, ) -> R { - let size = Encode::encoded_size(prefix) - + Encode::encoded_size(Self::ROUTE) - + Encode::encoded_size(value); + let header = SailsMessageHeader::new( + crate::meta::Version::v1(), + crate::meta::HeaderLength::new(crate::meta::MINIMAL_HLEN).unwrap(), + Self::INTERFACE_ID, + route_idx, + Self::ENTRY_ID, + ); + let size = (crate::meta::MINIMAL_HLEN as usize) + Encode::encoded_size(value); gcore::stack_buffer::with_byte_buffer(size, |buffer| { let mut buffer_writer = crate::utils::MaybeUninitBufferWriter::new(buffer); - Encode::encode_to(prefix, &mut buffer_writer); - Encode::encode_to(Self::ROUTE, &mut buffer_writer); + header.encode_to(&mut buffer_writer); Encode::encode_to(value, &mut buffer_writer); buffer_writer.with_buffer(f) }) } - - fn is_empty_tuple() -> bool { - TypeId::of::() == TypeId::of::<()>() - } } #[macro_export] @@ -419,7 +464,7 @@ macro_rules! params_struct_impl { )* } - impl PendingCall { + impl PendingCall { $( paste::paste! { $(#[$attr])* @@ -461,7 +506,7 @@ macro_rules! params_for_pending_impl { )* } - impl PendingCall { + impl PendingCall { $( paste::paste! { $(#[$attr])* @@ -477,19 +522,45 @@ macro_rules! params_for_pending_impl { #[macro_export] macro_rules! io_struct_impl { ( - $name:ident ( $( $param:ident : $ty:ty ),* ) -> $reply:ty + $name:ident ( $( $param:ident : $ty:ty ),* ) -> $reply:ty, $entry_id:expr, $interface_id:expr ) => { pub struct $name(()); impl $name { + /// Encodes the parameters only (without Sails header). pub fn encode_params($( $param: $ty, )* ) -> Vec { <$name as CallCodec>::encode_params(&( $( $param, )* )) } - pub fn encode_params_with_prefix(prefix: Route, $( $param: $ty, )* ) -> Vec { - <$name as CallCodec>::encode_params_with_prefix(prefix, &( $( $param, )* )) + /// Encodes the full call with the correct Sails header (Interface ID + Route Index + Entry ID). + pub fn encode_call(route_idx: u8, $( $param: $ty, )* ) -> Vec { + <$name as ServiceCall>::encode_params_with_header(route_idx, &( $( $param, )* )) + } + /// Decodes the reply checking against the correct Sails header (Interface ID + Route Index + Entry ID). + pub fn decode_reply(route_idx: u8, payload: impl AsRef<[u8]>) -> Result<$reply, $crate::scale_codec::Error> { + <$name as ServiceCall>::decode_reply_with_header(route_idx, payload) } } + impl Identifiable for $name { + const INTERFACE_ID: InterfaceId = $interface_id; + } impl CallCodec for $name { - const ROUTE: &'static str = stringify!($name); + const ENTRY_ID: u16 = $entry_id; + type Params = ( $( $ty, )* ); + type Reply = $reply; + } + impl ServiceCall for $name {} + }; + ( + $name:ident ( $( $param:ident : $ty:ty ),* ) -> $reply:ty, $entry_id:expr + ) => { + pub struct $name(()); + impl $name { + /// Encodes the parameters only (without Sails header). + pub fn encode_params($( $param: $ty, )* ) -> Vec { + <$name as CallCodec>::encode_params(&( $( $param, )* )) + } + } + impl CallCodec for $name { + const ENTRY_ID: u16 = $entry_id; type Params = ( $( $ty, )* ); type Reply = $reply; } @@ -530,69 +601,131 @@ pub trait Listener { ) -> Result + Unpin, Self::Error>; } -#[cfg(not(target_arch = "wasm32"))] -pub trait Event: Decode { - const EVENT_NAMES: &'static [Route]; +struct EventInput<'a> { + idx: u8, + payload: &'a [u8], + first: bool, +} + +impl<'a> parity_scale_codec::Input for EventInput<'a> { + fn remaining_len(&mut self) -> Result, parity_scale_codec::Error> { + Ok(Some(1 + self.payload.len())) + } + + fn read(&mut self, into: &mut [u8]) -> Result<(), parity_scale_codec::Error> { + if into.is_empty() { + return Ok(()); + } + let (head, tail) = into.split_at_mut(if self.first { 1 } else { 0 }); + if self.first { + head[0] = self.idx; + self.first = false; + } + if tail.is_empty() { + return Ok(()); + } + if tail.len() > self.payload.len() { + return Err("Not enough data to fill buffer".into()); + } + tail.copy_from_slice(&self.payload[..tail.len()]); + self.payload = &self.payload[tail.len()..]; + Ok(()) + } + + fn read_byte(&mut self) -> Result { + if self.first { + self.first = false; + Ok(self.idx) + } else { + let b = *self.payload.first().ok_or("Not enough data to read byte")?; + self.payload = &self.payload[1..]; + Ok(b) + } + } +} +#[cfg(not(target_arch = "wasm32"))] +pub trait Event: Decode + Identifiable { fn decode_event( - prefix: Route, + route_idx: u8, payload: impl AsRef<[u8]>, ) -> Result { let mut payload = payload.as_ref(); - let route = String::decode(&mut payload)?; - if route != prefix { - return Err("Invalid event prefix".into()); - } - let evt_name = String::decode(&mut payload)?; - for (idx, &name) in Self::EVENT_NAMES.iter().enumerate() { - if evt_name == name { - let idx = idx as u8; - let bytes = [&[idx], payload].concat(); - let mut event_bytes = &bytes[..]; - return Decode::decode(&mut event_bytes); - } + + let header = SailsMessageHeader::decode(&mut payload)?; + if header.interface_id() != Self::INTERFACE_ID { + return Err("Invalid event interface_id".into()); + } + if header.route_id() != route_idx { + return Err("Invalid event route_idx".into()); + } + + let entry_id = header.entry_id(); + if entry_id > 255 { + return Err("Entry ID exceeds u8 limit for SCALE enum".into()); } - Err("Invalid event name".into()) + + // Reconstruct the standard SCALE enum encoding. + // The network payload only contains the event data (arguments), omitting the variant index + // because the `entry_id` in the header already serves as the identifier. + // However, the standard Rust `Decode` implementation for enums expects a leading index byte. + // Therefore, we use a custom Input to prepend the `entry_id` (as u8) to the payload without allocation. + let variant_index = entry_id as u8; + let mut input = EventInput { + idx: variant_index, + payload, + first: true, + }; + Decode::decode(&mut input) } } #[cfg(test)] mod tests { use super::*; - io_struct_impl!(Add (value: u32) -> u32); - io_struct_impl!(Value () -> u32); - - #[test] - fn test_str_encode() { - const ADD: &[u8] = str_scale_encode!(Add); - assert_eq!(ADD, &[12, 65, 100, 100]); - - const VALUE: &[u8] = str_scale_encode!(Value); - assert_eq!(VALUE, &[20, 86, 97, 108, 117, 101]); - } + // Define Add with InterfaceId to test 3-arg macro (Service mode) + io_struct_impl!(Add (value: u32) -> u32, 0, InterfaceId::from_bytes_8([1, 2, 3, 4, 5, 6, 7, 8])); + // Define Value with 2-arg macro (Ctor/Legacy mode) + io_struct_impl!(Value () -> u32, 1); #[test] fn test_io_struct_impl() { - let add = Add::encode_params(42); - assert_eq!(add, &[12, 65, 100, 100, 42, 0, 0, 0]); - - let value = Add::encode_params_with_prefix("Counter", 42); - assert_eq!( - value, - &[ - 28, 67, 111, 117, 110, 116, 101, 114, 12, 65, 100, 100, 42, 0, 0, 0 - ] - ); - - let value = Value::encode_params(); - assert_eq!(value, &[20, 86, 97, 108, 117, 101]); - - let value = Value::encode_params_with_prefix("Counter"); - assert_eq!( - value, - &[ - 28, 67, 111, 117, 110, 116, 101, 114, 20, 86, 97, 108, 117, 101 - ] - ); + // Add is now a "Service" method, so encode takes route_idx + let route_idx = 5; + let add_specific = Add::encode_call(route_idx, 42); + + let expected_header_add = [ + 0x47, 0x4D, // magic ("GM") + 1, // version + 16, // hlen + 1, 2, 3, 4, 5, 6, 7, 8, // interface_id + 0, 0, // entry_id (0 for Add) + 5, // route_id + 0, // reserved + ]; + let expected_add_payload = [42, 0, 0, 0]; // 42u32 LE + + let mut expected_add_specific = Vec::new(); + expected_add_specific.extend_from_slice(&expected_header_add); + expected_add_specific.extend_from_slice(&expected_add_payload); + + assert_eq!(add_specific, expected_add_specific); + + let reply_payload = [42, 0, 0, 0]; + let mut reply_with_header = expected_add_specific.clone(); + reply_with_header.truncate(16); + reply_with_header.extend_from_slice(&reply_payload); + + // Decode uses the new helper method + let decoded = Add::decode_reply(route_idx, &reply_with_header).unwrap(); + assert_eq!(decoded, 42); + + // Add::encode_params should return raw bytes without header even for service methods + let add_params_only = Add::encode_params(42); + assert_eq!(add_params_only, expected_add_payload); + + // Value is "Ctor" mode, encode takes no route_idx and returns raw bytes + let value_encoded = Value::encode_params(); + assert_eq!(value_encoded, Vec::::new()); } } diff --git a/rs/src/lib.rs b/rs/src/lib.rs index 61fb7ba52..d03913294 100644 --- a/rs/src/lib.rs +++ b/rs/src/lib.rs @@ -21,7 +21,6 @@ pub use spin; mod builder; pub mod client; pub mod errors; -pub mod header; #[cfg(feature = "gclient")] #[cfg(not(target_arch = "wasm32"))] pub use gclient; diff --git a/rs/src/types.rs b/rs/src/types.rs index c6fc549a1..9100979b5 100644 --- a/rs/src/types.rs +++ b/rs/src/types.rs @@ -2,6 +2,7 @@ pub use core::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128}; pub use gprimitives::{ActorId, CodeId, H160, H256, MessageId, NonZeroU256, U256}; #[cfg(feature = "gstd")] pub use gstd::BlockCount; +pub use sails_idl_meta::InterfaceId; pub type ValueUnit = u128;