mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 15:47:58 +00:00
Reorganising the repository - external renames and moves (#4074)
* Adding first rough ouline of the repository structure * Remove old CI stuff * add title * formatting fixes * move node-exits job's script to scripts dir * Move docs into subdir * move to bin * move maintainence scripts, configs and helpers into its own dir * add .local to ignore * move core->client * start up 'test' area * move test client * move test runtime * make test move compile * Add dependencies rule enforcement. * Fix indexing. * Update docs to reflect latest changes * Moving /srml->/paint * update docs * move client/sr-* -> primitives/ * clean old readme * remove old broken code in rhd * update lock * Step 1. * starting to untangle client * Fix after merge. * start splitting out client interfaces * move children and blockchain interfaces * Move trie and state-machine to primitives. * Fix WASM builds. * fixing broken imports * more interface moves * move backend and light to interfaces * move CallExecutor * move cli off client * moving around more interfaces * re-add consensus crates into the mix * fix subkey path * relieve client from executor * starting to pull out client from grandpa * move is_decendent_of out of client * grandpa still depends on client directly * lemme tests pass * rename srml->paint * Make it compile. * rename interfaces->client-api * Move keyring to primitives. * fixup libp2p dep * fix broken use * allow dependency enforcement to fail * move fork-tree * Moving wasm-builder * make env * move build-script-utils * fixup broken crate depdencies and names * fix imports for authority discovery * fix typo * update cargo.lock * fixing imports * Fix paths and add missing crates * re-add missing crates
This commit is contained in:
committed by
Bastian Köcher
parent
becc3b0a4f
commit
60e5011c72
@@ -0,0 +1,384 @@
|
||||
// Copyright 2019 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Substrate.
|
||||
|
||||
// Substrate is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Substrate is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Provides the [`PassBy`](pass_by::PassBy) trait to simplify the implementation of the
|
||||
//! runtime interface traits for custom types.
|
||||
//!
|
||||
//! [`Codec`](pass_by::Codec), [`Inner`](pass_by::Inner) and [`Enum`](pass_by::Enum) are the
|
||||
//! provided strategy implementations.
|
||||
|
||||
use crate::{RIType, impls::{pointer_and_len_from_u64, pointer_and_len_to_u64}};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use crate::host::*;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use crate::wasm::*;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use wasm_interface::{FunctionContext, Pointer, Result};
|
||||
|
||||
use rstd::{marker::PhantomData, convert::TryFrom};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use rstd::{slice, vec::Vec};
|
||||
|
||||
pub use substrate_runtime_interface_proc_macro::{PassByCodec, PassByInner, PassByEnum};
|
||||
|
||||
/// Something that should be passed between wasm and the host using the given strategy.
|
||||
///
|
||||
/// See [`Codec`], [`Inner`] or [`Enum`] for more information about the provided strategies.
|
||||
pub trait PassBy: Sized {
|
||||
/// The strategy that should be used to pass the type.
|
||||
type PassBy: PassByImpl<Self>;
|
||||
}
|
||||
|
||||
/// Something that provides a strategy for passing a type between wasm and the host.
|
||||
///
|
||||
/// This trait exposes the same functionality as [`crate::host::IntoFFIValue`] and
|
||||
/// [`crate::host::FromFFIValue`] to delegate the implementation for a type to a different type.
|
||||
///
|
||||
/// This trait is used for the host implementation.
|
||||
#[cfg(feature = "std")]
|
||||
pub trait PassByImpl<T>: RIType {
|
||||
/// Convert the given instance to the ffi value.
|
||||
///
|
||||
/// For more information see: [`crate::host::IntoFFIValue::into_ffi_value`]
|
||||
fn into_ffi_value(
|
||||
instance: T,
|
||||
context: &mut dyn FunctionContext,
|
||||
) -> Result<Self::FFIType>;
|
||||
|
||||
/// Create `T` from the given ffi value.
|
||||
///
|
||||
/// For more information see: [`crate::host::FromFFIValue::from_ffi_value`]
|
||||
fn from_ffi_value(
|
||||
context: &mut dyn FunctionContext,
|
||||
arg: Self::FFIType,
|
||||
) -> Result<T>;
|
||||
}
|
||||
|
||||
/// Something that provides a strategy for passing a type between wasm and the host.
|
||||
///
|
||||
/// This trait exposes the same functionality as [`crate::wasm::IntoFFIValue`] and
|
||||
/// [`crate::wasm::FromFFIValue`] to delegate the implementation for a type to a different type.
|
||||
///
|
||||
/// This trait is used for the wasm implementation.
|
||||
#[cfg(not(feature = "std"))]
|
||||
pub trait PassByImpl<T>: RIType {
|
||||
/// The owned rust type that is stored with the ffi value in [`crate::wasm::WrappedFFIValue`].
|
||||
type Owned;
|
||||
|
||||
/// Convert the given `instance` into [`crate::wasm::WrappedFFIValue`].
|
||||
///
|
||||
/// For more information see: [`crate::wasm::IntoFFIValue::into_ffi_value`]
|
||||
fn into_ffi_value(instance: &T) -> WrappedFFIValue<Self::FFIType, Self::Owned>;
|
||||
|
||||
/// Create `T` from the given ffi value.
|
||||
///
|
||||
/// For more information see: [`crate::wasm::FromFFIValue::from_ffi_value`]
|
||||
fn from_ffi_value(arg: Self::FFIType) -> T;
|
||||
}
|
||||
|
||||
impl<T: PassBy> RIType for T {
|
||||
type FFIType = <T::PassBy as RIType>::FFIType;
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: PassBy> IntoFFIValue for T {
|
||||
fn into_ffi_value(
|
||||
self,
|
||||
context: &mut dyn FunctionContext,
|
||||
) -> Result<<T::PassBy as RIType>::FFIType> {
|
||||
T::PassBy::into_ffi_value(self, context)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: PassBy> FromFFIValue for T {
|
||||
type SelfInstance = Self;
|
||||
|
||||
fn from_ffi_value(
|
||||
context: &mut dyn FunctionContext,
|
||||
arg: <T::PassBy as RIType>::FFIType,
|
||||
) -> Result<Self> {
|
||||
T::PassBy::from_ffi_value(context, arg)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: PassBy> IntoFFIValue for T {
|
||||
type Owned = <T::PassBy as PassByImpl<T>>::Owned;
|
||||
|
||||
fn into_ffi_value(&self) -> WrappedFFIValue<<T::PassBy as RIType>::FFIType, Self::Owned> {
|
||||
T::PassBy::into_ffi_value(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: PassBy> FromFFIValue for T {
|
||||
fn from_ffi_value(arg: <T::PassBy as RIType>::FFIType) -> Self {
|
||||
T::PassBy::from_ffi_value(arg)
|
||||
}
|
||||
}
|
||||
|
||||
/// The implementation of the pass by codec strategy. This strategy uses a SCALE encoded
|
||||
/// representation of the type between wasm and the host.
|
||||
///
|
||||
/// Use this type as associated type for [`PassBy`] to implement this strategy for a type.
|
||||
///
|
||||
/// This type expects the type that wants to implement this strategy as generic parameter.
|
||||
///
|
||||
/// [`PassByCodec`](derive.PassByCodec.html) is a derive macro to implement this strategy.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use substrate_runtime_interface::pass_by::{PassBy, Codec};
|
||||
/// #[derive(codec::Encode, codec::Decode)]
|
||||
/// struct Test;
|
||||
///
|
||||
/// impl PassBy for Test {
|
||||
/// type PassBy = Codec<Self>;
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Codec<T: codec::Codec>(PhantomData<T>);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: codec::Codec> PassByImpl<T> for Codec<T> {
|
||||
fn into_ffi_value(
|
||||
instance: T,
|
||||
context: &mut dyn FunctionContext,
|
||||
) -> Result<Self::FFIType> {
|
||||
let vec = instance.encode();
|
||||
let ptr = context.allocate_memory(vec.len() as u32)?;
|
||||
context.write_memory(ptr, &vec)?;
|
||||
|
||||
Ok(pointer_and_len_to_u64(ptr.into(), vec.len() as u32))
|
||||
}
|
||||
|
||||
fn from_ffi_value(
|
||||
context: &mut dyn FunctionContext,
|
||||
arg: Self::FFIType,
|
||||
) -> Result<T> {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let vec = context.read_memory(Pointer::new(ptr), len)?;
|
||||
T::decode(&mut &vec[..])
|
||||
.map_err(|e| format!("Could not decode value from wasm: {}", e.what()))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: codec::Codec> PassByImpl<T> for Codec<T> {
|
||||
type Owned = Vec<u8>;
|
||||
|
||||
fn into_ffi_value(instance: &T) -> WrappedFFIValue<Self::FFIType, Self::Owned> {
|
||||
let data = instance.encode();
|
||||
let ffi_value = pointer_and_len_to_u64(data.as_ptr() as u32, data.len() as u32);
|
||||
(ffi_value, data).into()
|
||||
}
|
||||
|
||||
fn from_ffi_value(arg: Self::FFIType) -> T {
|
||||
let (ptr, len) = pointer_and_len_from_u64(arg);
|
||||
let len = len as usize;
|
||||
|
||||
let slice = unsafe { slice::from_raw_parts(ptr as *const u8, len) };
|
||||
T::decode(&mut &slice[..]).expect("Host to wasm values are encoded correctly; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// The type is passed as `u64`.
|
||||
///
|
||||
/// The `u64` value is build by `length 32bit << 32 | pointer 32bit`
|
||||
///
|
||||
/// `Self` is encoded and the length and the pointer are taken from the encoded vector.
|
||||
impl<T: codec::Codec> RIType for Codec<T> {
|
||||
type FFIType = u64;
|
||||
}
|
||||
|
||||
/// Trait that needs to be implemented by a type that should be passed between wasm and the host,
|
||||
/// by using the inner type. See [`Inner`] for more information.
|
||||
pub trait PassByInner: Sized {
|
||||
/// The inner type that is wrapped by `Self`.
|
||||
type Inner: RIType;
|
||||
|
||||
/// Consumes `self` and returns the inner type.
|
||||
fn into_inner(self) -> Self::Inner;
|
||||
|
||||
/// Returns the reference to the inner type.
|
||||
fn inner(&self) -> &Self::Inner;
|
||||
|
||||
/// Construct `Self` from the given `inner`.
|
||||
fn from_inner(inner: Self::Inner) -> Self;
|
||||
}
|
||||
|
||||
/// The implementation of the pass by inner type strategy. The type that uses this strategy will be
|
||||
/// passed between wasm and the host by using the wrapped inner type. So, this strategy is only
|
||||
/// usable by newtype structs.
|
||||
///
|
||||
/// Use this type as associated type for [`PassBy`] to implement this strategy for a type. Besides
|
||||
/// that the `PassByInner` trait need to be implemented as well.
|
||||
///
|
||||
/// This type expects the type that wants to use this strategy as generic parameter `T` and the
|
||||
/// inner type as generic parameter `I`.
|
||||
///
|
||||
/// [`PassByInner`](derive.PassByInner.html) is a derive macro to implement this strategy.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use substrate_runtime_interface::pass_by::{PassBy, Inner, PassByInner};
|
||||
/// struct Test([u8; 32]);
|
||||
///
|
||||
/// impl PassBy for Test {
|
||||
/// type PassBy = Inner<Self, [u8; 32]>;
|
||||
/// }
|
||||
///
|
||||
/// impl PassByInner for Test {
|
||||
/// type Inner = [u8; 32];
|
||||
///
|
||||
/// fn into_inner(self) -> [u8; 32] {
|
||||
/// self.0
|
||||
/// }
|
||||
/// fn inner(&self) -> &[u8; 32] {
|
||||
/// &self.0
|
||||
/// }
|
||||
/// fn from_inner(inner: [u8; 32]) -> Self {
|
||||
/// Self(inner)
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Inner<T: PassByInner<Inner = I>, I: RIType>(PhantomData<(T, I)>);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: PassByInner<Inner = I>, I: RIType> PassByImpl<T> for Inner<T, I>
|
||||
where I: IntoFFIValue + FromFFIValue<SelfInstance=I>
|
||||
{
|
||||
fn into_ffi_value(
|
||||
instance: T,
|
||||
context: &mut dyn FunctionContext,
|
||||
) -> Result<Self::FFIType> {
|
||||
instance.into_inner().into_ffi_value(context)
|
||||
}
|
||||
|
||||
fn from_ffi_value(
|
||||
context: &mut dyn FunctionContext,
|
||||
arg: Self::FFIType,
|
||||
) -> Result<T> {
|
||||
I::from_ffi_value(context, arg).map(T::from_inner)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: PassByInner<Inner = I>, I: RIType> PassByImpl<T> for Inner<T, I>
|
||||
where I: IntoFFIValue + FromFFIValue
|
||||
{
|
||||
type Owned = I::Owned;
|
||||
|
||||
fn into_ffi_value(instance: &T) -> WrappedFFIValue<Self::FFIType, Self::Owned> {
|
||||
instance.inner().into_ffi_value()
|
||||
}
|
||||
|
||||
fn from_ffi_value(arg: Self::FFIType) -> T {
|
||||
T::from_inner(I::from_ffi_value(arg))
|
||||
}
|
||||
}
|
||||
|
||||
/// The type is passed as the inner type.
|
||||
impl<T: PassByInner<Inner = I>, I: RIType> RIType for Inner<T, I> {
|
||||
type FFIType = I::FFIType;
|
||||
}
|
||||
|
||||
/// The implementation of the pass by enum strategy. This strategy uses an `u8` internally to pass
|
||||
/// the enum between wasm and the host. So, this strategy only supports enums with unit variants.
|
||||
///
|
||||
/// Use this type as associated type for [`PassBy`] to implement this strategy for a type.
|
||||
///
|
||||
/// This type expects the type that wants to implement this strategy as generic parameter. Besides
|
||||
/// that the type needs to implement `TryFrom<u8>` and `From<Self> for u8`.
|
||||
///
|
||||
/// [`PassByEnum`](derive.PassByEnum.html) is a derive macro to implement this strategy.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use substrate_runtime_interface::pass_by::{PassBy, Enum};
|
||||
/// #[derive(Clone, Copy)]
|
||||
/// enum Test {
|
||||
/// Test1,
|
||||
/// Test2,
|
||||
/// }
|
||||
///
|
||||
/// impl From<Test> for u8 {
|
||||
/// fn from(val: Test) -> u8 {
|
||||
/// match val {
|
||||
/// Test::Test1 => 0,
|
||||
/// Test::Test2 => 1,
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl std::convert::TryFrom<u8> for Test {
|
||||
/// type Error = ();
|
||||
///
|
||||
/// fn try_from(val: u8) -> Result<Test, ()> {
|
||||
/// match val {
|
||||
/// 0 => Ok(Test::Test1),
|
||||
/// 1 => Ok(Test::Test2),
|
||||
/// _ => Err(()),
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl PassBy for Test {
|
||||
/// type PassBy = Enum<Self>;
|
||||
/// }
|
||||
/// ```
|
||||
pub struct Enum<T: Copy + Into<u8> + TryFrom<u8>>(PhantomData<T>);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<T: Copy + Into<u8> + TryFrom<u8>> PassByImpl<T> for Enum<T> {
|
||||
fn into_ffi_value(
|
||||
instance: T,
|
||||
_: &mut dyn FunctionContext,
|
||||
) -> Result<Self::FFIType> {
|
||||
Ok(instance.into())
|
||||
}
|
||||
|
||||
fn from_ffi_value(
|
||||
_: &mut dyn FunctionContext,
|
||||
arg: Self::FFIType,
|
||||
) -> Result<T> {
|
||||
T::try_from(arg).map_err(|_| format!("Invalid enum discriminant: {}", arg))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
impl<T: Copy + Into<u8> + TryFrom<u8, Error = ()>> PassByImpl<T> for Enum<T> {
|
||||
type Owned = ();
|
||||
|
||||
fn into_ffi_value(instance: &T) -> WrappedFFIValue<Self::FFIType, Self::Owned> {
|
||||
let value: u8 = (*instance).into();
|
||||
value.into()
|
||||
}
|
||||
|
||||
fn from_ffi_value(arg: Self::FFIType) -> T {
|
||||
T::try_from(arg).expect("Host to wasm provides a valid enum discriminant; qed")
|
||||
}
|
||||
}
|
||||
|
||||
/// The type is passed as `u8`.
|
||||
///
|
||||
/// The value is corresponds to the discriminant of the variant.
|
||||
impl<T: Copy + Into<u8> + TryFrom<u8>> RIType for Enum<T> {
|
||||
type FFIType = u8;
|
||||
}
|
||||
Reference in New Issue
Block a user