sails_rs/gstd/
mod.rs

1#[doc(hidden)]
2#[cfg(feature = "ethexe")]
3pub use ethexe::{EthEvent, EthEventExpo};
4#[doc(hidden)]
5pub use events::{EventEmitter, SailsEvent};
6#[cfg(not(feature = "ethexe"))]
7#[doc(hidden)]
8pub use gstd::handle_signal;
9#[doc(hidden)]
10pub use gstd::{async_init, async_main, handle_reply_with_hook, message_loop};
11pub use gstd::{debug, exec, msg};
12#[doc(hidden)]
13pub use sails_macros::{event, export, program, service};
14pub use syscalls::Syscall;
15
16use crate::{
17    errors::{Error, Result, RtlError},
18    prelude::{any::TypeId, *},
19    utils::MaybeUninitBufferWriter,
20};
21use gcore::stack_buffer;
22
23pub mod calls;
24#[cfg(feature = "ethexe")]
25mod ethexe;
26mod events;
27mod message_future;
28pub mod services;
29mod syscalls;
30
31pub struct CommandReply<T>(T, ValueUnit);
32
33impl<T> CommandReply<T> {
34    pub fn new(result: T) -> Self {
35        Self(result, 0)
36    }
37
38    pub fn with_value(self, value: ValueUnit) -> Self {
39        Self(self.0, value)
40    }
41
42    pub fn to_tuple(self) -> (T, ValueUnit) {
43        (self.0, self.1)
44    }
45}
46
47impl<T> From<T> for CommandReply<T> {
48    fn from(result: T) -> Self {
49        Self(result, 0)
50    }
51}
52
53impl<T> From<(T, ValueUnit)> for CommandReply<T> {
54    fn from(value: (T, ValueUnit)) -> Self {
55        Self(value.0, value.1)
56    }
57}
58
59pub fn unknown_input_panic(message: &str, input: &[u8]) -> ! {
60    let mut __input = input;
61    match String::decode(&mut __input) {
62        Ok(s) => panic!("{}: {}", message, s),
63        Err(_) => panic!("{}: {}", message, HexSlice(input)),
64    }
65}
66
67struct HexSlice<T: AsRef<[u8]>>(T);
68
69impl<T: AsRef<[u8]>> core::fmt::Display for HexSlice<T> {
70    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
71        let slice = self.0.as_ref();
72        let len = slice.len();
73        let precision = f.precision().unwrap_or(4);
74
75        f.write_str("0x")?;
76        if len <= precision * 2 {
77            for byte in slice {
78                write!(f, "{byte:02x}")?;
79            }
80        } else {
81            for byte in &slice[..precision] {
82                write!(f, "{byte:02x}")?;
83            }
84            f.write_str("..")?;
85            for byte in &slice[len - precision..] {
86                write!(f, "{byte:02x}")?;
87            }
88        }
89        Ok(())
90    }
91}
92
93impl<T: AsRef<[u8]>> core::fmt::Debug for HexSlice<T> {
94    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
95        core::fmt::Display::fmt(self, f)
96    }
97}
98
99pub trait InvocationIo {
100    const ROUTE: &'static [u8];
101    type Params: Decode;
102    const ASYNC: bool;
103
104    fn check_asyncness(payload: impl AsRef<[u8]>) -> Result<bool> {
105        let value = payload.as_ref();
106        if !value.starts_with(Self::ROUTE) {
107            return Err(Error::Rtl(RtlError::InvocationPrefixMismatches));
108        }
109
110        Ok(Self::ASYNC)
111    }
112
113    fn decode_params(payload: impl AsRef<[u8]>) -> Result<Self::Params> {
114        let mut value = payload.as_ref();
115        if !value.starts_with(Self::ROUTE) {
116            return Err(Error::Rtl(RtlError::InvocationPrefixMismatches));
117        }
118        value = &value[Self::ROUTE.len()..];
119        Decode::decode(&mut value).map_err(Error::Codec)
120    }
121
122    fn with_optimized_encode<T: Encode, R>(
123        value: &T,
124        prefix: &[u8],
125        f: impl FnOnce(&[u8]) -> R,
126    ) -> R {
127        let size = prefix.len() + Self::ROUTE.len() + Encode::encoded_size(value);
128        stack_buffer::with_byte_buffer(size, |buffer| {
129            let mut buffer_writer = MaybeUninitBufferWriter::new(buffer);
130
131            buffer_writer.write(prefix);
132            buffer_writer.write(Self::ROUTE);
133            Encode::encode_to(value, &mut buffer_writer);
134
135            buffer_writer.with_buffer(f)
136        })
137    }
138
139    fn is_empty_tuple<T: 'static>() -> bool {
140        TypeId::of::<T>() == TypeId::of::<()>()
141    }
142}