Fix cycle dependency in sp-runtime-interface (#4353)

* Fix cycle dependency in `sp-runtime-interface`

* Fixes tests
This commit is contained in:
Bastian Köcher
2019-12-11 09:32:11 +01:00
committed by GitHub
parent 1ff41742bd
commit 6500b33df3
19 changed files with 218 additions and 224 deletions
@@ -72,6 +72,8 @@
#![cfg_attr(not(feature = "std"), no_std)]
extern crate self as sp_runtime_interface;
#[doc(hidden)]
#[cfg(feature = "std")]
pub use wasm_interface;
@@ -79,6 +81,148 @@ pub use wasm_interface;
#[doc(hidden)]
pub use sp_std;
/// Attribute macro for transforming a trait declaration into a runtime interface.
///
/// A runtime interface is a fixed interface between a Substrate compatible runtime and the native
/// node. This interface is callable from a native and a wasm runtime. The macro will generate the
/// corresponding code for the native implementation and the code for calling from the wasm
/// side to the native implementation.
///
/// The macro expects the runtime interface declaration as trait declaration:
///
/// ```
/// # use sp_runtime_interface::runtime_interface;
///
/// #[runtime_interface]
/// trait Interface {
/// /// A function that can be called from native/wasm.
/// ///
/// /// The implementation given to this function is only compiled on native.
/// fn call_some_complex_code(data: &[u8]) -> Vec<u8> {
/// // Here you could call some rather complex code that only compiles on native or
/// // is way faster in native than executing it in wasm.
/// Vec::new()
/// }
///
/// /// A function can take a `&self` or `&mut self` argument to get access to the
/// /// `Externalities`. (The generated method does not require
/// /// this argument, so the function can be called just with the `optional` argument)
/// fn set_or_clear(&mut self, optional: Option<Vec<u8>>) {
/// match optional {
/// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value),
/// None => self.clear_storage(&[1, 2, 3, 4]),
/// }
/// }
/// }
/// ```
///
///
/// The given example will generate roughly the following code for native:
///
/// ```
/// // The name of the trait is converted to snake case and used as mod name.
/// //
/// // Be aware that this module is not `public`, the visibility of the module is determined based
/// // on the visibility of the trait declaration.
/// mod interface {
/// trait Interface {
/// fn call_some_complex_code(data: &[u8]) -> Vec<u8>;
/// fn set_or_clear(&mut self, optional: Option<Vec<u8>>);
/// }
///
/// impl Interface for &mut dyn externalities::Externalities {
/// fn call_some_complex_code(data: &[u8]) -> Vec<u8> { Vec::new() }
/// fn set_or_clear(&mut self, optional: Option<Vec<u8>>) {
/// match optional {
/// Some(value) => self.set_storage([1, 2, 3, 4].to_vec(), value),
/// None => self.clear_storage(&[1, 2, 3, 4]),
/// }
/// }
/// }
///
/// pub fn call_some_complex_code(data: &[u8]) -> Vec<u8> {
/// <&mut dyn externalities::Externalities as Interface>::call_some_complex_code(data)
/// }
///
/// pub fn set_or_clear(optional: Option<Vec<u8>>) {
/// externalities::with_externalities(|mut ext| Interface::set_or_clear(&mut ext, optional))
/// .expect("`set_or_clear` called outside of an Externalities-provided environment.")
/// }
///
/// /// This type implements the `HostFunctions` trait (from `sp-wasm-interface`) and
/// /// provides the host implementation for the wasm side. The host implementation converts the
/// /// arguments from wasm to native and calls the corresponding native function.
/// ///
/// /// This type needs to be passed to the wasm executor, so that the host functions will be
/// /// registered in the executor.
/// pub struct HostFunctions;
/// }
/// ```
///
///
/// The given example will generate roughly the following code for wasm:
///
/// ```
/// mod interface {
/// mod extern_host_functions_impls {
/// extern "C" {
/// /// Every function is exported as `ext_TRAIT_NAME_FUNCTION_NAME_version_VERSION`.
/// ///
/// /// `TRAIT_NAME` is converted into snake case.
/// ///
/// /// The type for each argument of the exported function depends on
/// /// `<ARGUMENT_TYPE as RIType>::FFIType`.
/// ///
/// /// `data` holds the pointer and the length to the `[u8]` slice.
/// pub fn ext_Interface_call_some_complex_code_version_1(data: u64) -> u64;
/// /// `optional` holds the pointer and the length of the encoded value.
/// pub fn ext_Interface_set_or_clear_version_1(optional: u64);
/// }
/// }
///
/// /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`).
/// ///
/// /// This can be used to replace the implementation of the `call_some_complex_code` function.
/// /// Instead of calling into the host, the callee will automatically call the other
/// /// implementation.
/// ///
/// /// To replace the implementation:
/// ///
/// /// `host_call_some_complex_code.replace_implementation(some_other_impl)`
/// pub static host_call_some_complex_code: () = ();
/// pub static host_set_or_clear: () = ();
///
/// pub fn call_some_complex_code(data: &[u8]) -> Vec<u8> {
/// // This is the actual call: `host_call_some_complex_code.get()(data)`
/// //
/// // But that does not work for several reasons in this example, so we just return an
/// // empty vector.
/// Vec::new()
/// }
///
/// pub fn set_or_clear(optional: Option<Vec<u8>>) {
/// // Same as above
/// }
/// }
/// ```
///
/// # Argument types
///
/// The macro supports any kind of argument type, as long as it implements [`RIType`] and the
/// required `FromFFIValue`/`IntoFFIValue`. The macro will convert each
/// argument to the corresponding FFI representation and will call into the host using this FFI
/// representation. On the host each argument is converted back to the native representation and
/// the native implementation is called. Any return value is handled in the same way.
///
/// # Wasm only interfaces
///
/// Some interfaces are only required from within the wasm runtime e.g. the allocator interface.
/// To support this, the macro can be called like `#[runtime_interface(wasm_only)]`. This instructs
/// the macro to make two significant changes to the generated code:
///
/// 1. The generated functions are not callable from the native side.
/// 2. The trait as shown above is not implemented for `Externalities` and is instead implemented
/// for `FunctionExecutor` (from `sp-wasm-interface`).
pub use sp_runtime_interface_proc_macro::runtime_interface;
#[doc(hidden)]