@@ -180,10 +180,19 @@ pub use sp_std;
180180/// None => self.clear_storage(&[1, 2, 3, 4]),
181181/// }
182182/// }
183+ ///
184+ /// /// A function can be gated behind a configuration (`cfg`) attribute.
185+ /// /// To prevent ambiguity and confusion about what will be the final exposed host
186+ /// /// functions list, conditionally compiled functions can't be versioned.
187+ /// /// That is, conditionally compiled functions with `version`s greater than 1
188+ /// /// are not allowed.
189+ /// #[cfg(feature = "experimental-function")]
190+ /// fn gated_call(data: &[u8]) -> Vec<u8> {
191+ /// [42].to_vec()
192+ /// }
183193/// }
184194/// ```
185195///
186- ///
187196/// The given example will generate roughly the following code for native:
188197///
189198/// ```
@@ -197,6 +206,8 @@ pub use sp_std;
197206/// fn call_version_2(data: &[u8]) -> Vec<u8>;
198207/// fn call_version_3(data: &[u8]) -> Vec<u8>;
199208/// fn set_or_clear_version_1(&mut self, optional: Option<Vec<u8>>);
209+ /// #[cfg(feature = "experimental-function")]
210+ /// fn gated_call_version_1(data: &[u8]) -> Vec<u8>;
200211/// }
201212///
202213/// impl Interface for &mut dyn sp_externalities::Externalities {
@@ -209,6 +220,8 @@ pub use sp_std;
209220/// None => self.clear_storage(&[1, 2, 3, 4]),
210221/// }
211222/// }
223+ /// #[cfg(feature = "experimental-function")]
224+ /// fn gated_call_version_1(data: &[u8]) -> Vec<u8> { [42].to_vec() }
212225/// }
213226///
214227/// pub fn call(data: &[u8]) -> Vec<u8> {
@@ -237,6 +250,16 @@ pub use sp_std;
237250/// .expect("`set_or_clear` called outside of an Externalities-provided environment.")
238251/// }
239252///
253+ /// #[cfg(feature = "experimental-function")]
254+ /// pub fn gated_call(data: &[u8]) -> Vec<u8> {
255+ /// gated_call_version_1(data)
256+ /// }
257+ ///
258+ /// #[cfg(feature = "experimental-function")]
259+ /// fn gated_call_version_1(data: &[u8]) -> Vec<u8> {
260+ /// <&mut dyn sp_externalities::Externalities as Interface>::gated_call_version_1(data)
261+ /// }
262+ ///
240263/// /// This type implements the `HostFunctions` trait (from `sp-wasm-interface`) and
241264/// /// provides the host implementation for the wasm side. The host implementation converts the
242265/// /// arguments from wasm to native and calls the corresponding native function.
@@ -247,28 +270,43 @@ pub use sp_std;
247270/// }
248271/// ```
249272///
250- ///
251273/// The given example will generate roughly the following code for wasm:
252274///
253275/// ```
254276/// mod interface {
255277/// mod extern_host_functions_impls {
256- /// extern "C" {
257- /// /// Every function is exported as `ext_TRAIT_NAME_FUNCTION_NAME_version_VERSION`.
258- /// ///
259- /// /// `TRAIT_NAME` is converted into snake case.
260- /// ///
261- /// /// The type for each argument of the exported function depends on
262- /// /// `<ARGUMENT_TYPE as RIType>::FFIType`.
263- /// ///
264- /// /// `data` holds the pointer and the length to the `[u8]` slice.
265- /// pub fn ext_Interface_call_version_1(data: u64) -> u64;
266- /// /// `optional` holds the pointer and the length of the encoded value.
267- /// pub fn ext_Interface_set_or_clear_version_1(optional: u64);
278+ /// /// Every function is exported by the native code as `ext_FUNCTION_NAME_version_VERSION`.
279+ /// ///
280+ /// /// The type for each argument of the exported function depends on
281+ /// /// `<ARGUMENT_TYPE as RIType>::FFIType`.
282+ /// ///
283+ /// /// `key` holds the pointer and the length to the `data` slice.
284+ /// pub fn call(data: &[u8]) -> Vec<u8> {
285+ /// extern "C" { pub fn ext_call_version_2(key: u64); }
286+ /// // Should call into extenal `ext_call_version_2(<[u8] as IntoFFIValue>::into_ffi_value(key))`
287+ /// // But this is too much to replicate in a doc test so here we just return a dummy vector.
288+ /// // Note that we jump into the latest version not marked as `register_only` (i.e. version 2).
289+ /// Vec::new()
290+ /// }
291+ ///
292+ /// /// `key` holds the pointer and the length of the `option` value.
293+ /// pub fn set_or_clear(option: Option<Vec<u8>>) {
294+ /// extern "C" { pub fn ext_set_or_clear_version_1(key: u64); }
295+ /// // Same as above
296+ /// }
297+ ///
298+ /// /// `key` holds the pointer and the length to the `data` slice.
299+ /// #[cfg(feature = "experimental-function")]
300+ /// pub fn gated_call(data: &[u8]) -> Vec<u8> {
301+ /// extern "C" { pub fn ext_gated_call_version_1(key: u64); }
302+ /// /// Same as above
303+ /// Vec::new()
268304/// }
269305/// }
270306///
271- /// /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`).
307+ /// /// The type is actually `ExchangeableFunction` (from `sp-runtime-interface`) and
308+ /// /// by default this is initialized to jump into the corresponding function in
309+ /// /// `extern_host_functions_impls`.
272310/// ///
273311/// /// This can be used to replace the implementation of the `call` function.
274312/// /// Instead of calling into the host, the callee will automatically call the other
@@ -279,6 +317,8 @@ pub use sp_std;
279317/// /// `host_call.replace_implementation(some_other_impl)`
280318/// pub static host_call: () = ();
281319/// pub static host_set_or_clear: () = ();
320+ /// #[cfg(feature = "experimental-feature")]
321+ /// pub static gated_call: () = ();
282322///
283323/// pub fn call(data: &[u8]) -> Vec<u8> {
284324/// // This is the actual call: `host_call.get()(data)`
@@ -291,6 +331,12 @@ pub use sp_std;
291331/// pub fn set_or_clear(optional: Option<Vec<u8>>) {
292332/// // Same as above
293333/// }
334+ ///
335+ /// #[cfg(feature = "experimental-feature")]
336+ /// pub fn gated_call(data: &[u8]) -> Vec<u8> {
337+ /// // Same as above
338+ /// Vec::new()
339+ /// }
294340/// }
295341/// ```
296342///
0 commit comments