pezframe_support/view_functions.rs
1// This file is part of Bizinikiwi.
2
3// Copyright (C) Parity Technologies (UK) Ltd. and Dijital Kurdistan Tech Institute
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License fsor the specific language governing permissions and
16// limitations under the License.
17
18//! Traits for querying pezpallet view functions.
19
20use alloc::vec::Vec;
21use codec::{Decode, DecodeAll, Encode, Output};
22use pezsp_runtime::RuntimeDebug;
23use scale_info::TypeInfo;
24
25/// The unique identifier for a view function.
26#[derive(Clone, Encode, Decode, RuntimeDebug, TypeInfo)]
27pub struct ViewFunctionId {
28 /// The part of the id for dispatching view functions from the top level of the runtime.
29 ///
30 /// Specifies which view function grouping this view function belongs to. This could be a group
31 /// of view functions associated with a pezpallet, or a pezpallet agnostic group of view
32 /// functions.
33 pub prefix: [u8; 16],
34 /// The part of the id for dispatching to a view function within a group.
35 pub suffix: [u8; 16],
36}
37
38impl From<ViewFunctionId> for [u8; 32] {
39 fn from(value: ViewFunctionId) -> Self {
40 let mut output = [0u8; 32];
41 output[..16].copy_from_slice(&value.prefix);
42 output[16..].copy_from_slice(&value.suffix);
43 output
44 }
45}
46
47/// Error type for view function dispatching.
48#[derive(Encode, Decode, RuntimeDebug, TypeInfo)]
49pub enum ViewFunctionDispatchError {
50 /// View functions are not implemented for this runtime.
51 NotImplemented,
52 /// A view function with the given `ViewFunctionId` was not found
53 NotFound(ViewFunctionId),
54 /// Failed to decode the view function input.
55 Codec,
56}
57
58impl From<codec::Error> for ViewFunctionDispatchError {
59 fn from(_: codec::Error) -> Self {
60 ViewFunctionDispatchError::Codec
61 }
62}
63
64/// Implemented by both pallets and the runtime. The runtime is dispatching by prefix using the
65/// pezpallet implementation of `ViewFunctionIdPrefix` then the pezpallet is dispatching by suffix
66/// using the methods implementation of `ViewFunctionIdSuffix`.
67///
68/// In more details, `ViewFunctionId` = `ViewFunctionIdPrefix` ++ `ViewFunctionIdSuffix`, where
69/// `ViewFunctionIdPrefix=twox_128(pezpallet_name)` and
70/// `ViewFunctionIdSuffix=twox_128("fn_name(fnarg_types) -> return_ty")`. The prefix is the same as
71/// the storage prefix for pallets. The suffix is generated from the view function method type
72/// signature, so is guaranteed to be unique for that pezpallet implementation.
73pub trait DispatchViewFunction {
74 fn dispatch_view_function<O: Output>(
75 id: &ViewFunctionId,
76 input: &mut &[u8],
77 output: &mut O,
78 ) -> Result<(), ViewFunctionDispatchError>;
79}
80
81impl DispatchViewFunction for () {
82 fn dispatch_view_function<O: Output>(
83 _id: &ViewFunctionId,
84 _input: &mut &[u8],
85 _output: &mut O,
86 ) -> Result<(), ViewFunctionDispatchError> {
87 Err(ViewFunctionDispatchError::NotImplemented)
88 }
89}
90
91/// Automatically implemented for each pezpallet by the macro [`pezpallet`](crate::pezpallet).
92pub trait ViewFunctionIdPrefix {
93 fn prefix() -> [u8; 16];
94}
95
96/// Automatically implemented for each pezpallet view function method by the macro
97/// [`pezpallet`](crate::pezpallet).
98pub trait ViewFunctionIdSuffix {
99 const SUFFIX: [u8; 16];
100}
101
102/// Automatically implemented for each pezpallet view function method by the macro
103/// [`pezpallet`](crate::pezpallet).
104pub trait ViewFunction: DecodeAll {
105 fn id() -> ViewFunctionId;
106 type ReturnType: Encode;
107
108 fn invoke(self) -> Self::ReturnType;
109
110 fn execute<O: Output>(
111 input: &mut &[u8],
112 output: &mut O,
113 ) -> Result<(), ViewFunctionDispatchError> {
114 let view_function = Self::decode_all(input)?;
115 let result = view_function.invoke();
116 Encode::encode_to(&result, output);
117 Ok(())
118 }
119}
120
121pub mod runtime_api {
122 use super::*;
123
124 pezsp_api::decl_runtime_apis! {
125 #[api_version(1)]
126 /// Runtime API for executing view functions
127 pub trait RuntimeViewFunction {
128 /// Execute a view function query.
129 fn execute_view_function(
130 query_id: ViewFunctionId,
131 input: Vec<u8>,
132 ) -> Result<Vec<u8>, ViewFunctionDispatchError>;
133 }
134 }
135}