frame_decode/methods/
view_function_decoder.rs

1// Copyright (C) 2022-2025 Parity Technologies (UK) Ltd. (admin@parity.io)
2// This file is a part of the frame-decode crate.
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8//         http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16// Copyright (C) 2022-2025 Parity Technologies (UK) Ltd. (admin@parity.io)
17// This file is a part of the frame-decode crate.
18//
19// Licensed under the Apache License, Version 2.0 (the "License");
20// you may not use this file except in compliance with the License.
21// You may obtain a copy of the License at
22//
23//         http://www.apache.org/licenses/LICENSE-2.0
24//
25// Unless required by applicable law or agreed to in writing, software
26// distributed under the License is distributed on an "AS IS" BASIS,
27// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
28// See the License for the specific language governing permissions and
29// limitations under the License.
30
31use super::view_function_type_info::{
32    ViewFunctionInfo, ViewFunctionInfoError, ViewFunctionTypeInfo,
33};
34use crate::utils::{DecodeErrorTrace, decode_with_error_tracing};
35use scale_type_resolver::TypeResolver;
36
37/// An error returned trying to decode a View Function responses.
38#[non_exhaustive]
39#[allow(missing_docs)]
40#[derive(Clone, Debug, thiserror::Error)]
41pub enum ViewFunctionDecodeError<TypeId> {
42    #[error("Cannot get View Function info: {0}")]
43    CannotGetInfo(ViewFunctionInfoError<'static>),
44    #[error("Cannot decode View Function response: {reason}")]
45    CannotDecodeValue {
46        ty: TypeId,
47        reason: DecodeErrorTrace,
48    },
49}
50
51/// Decode a View Function response.
52pub fn decode_view_function_response<'scale, 'resolver, Info, Resolver, V>(
53    pallet_name: &str,
54    function_name: &str,
55    cursor: &mut &'scale [u8],
56    info: &Info,
57    type_resolver: &'resolver Resolver,
58    visitor: V,
59) -> Result<V::Value<'scale, 'resolver>, ViewFunctionDecodeError<Info::TypeId>>
60where
61    Info: ViewFunctionTypeInfo,
62    Info::TypeId: Clone + core::fmt::Debug,
63    Resolver: TypeResolver<TypeId = Info::TypeId>,
64    V: scale_decode::Visitor<TypeResolver = Resolver>,
65    V::Error: core::fmt::Debug,
66{
67    let view_function_info = info
68        .view_function_info(pallet_name, function_name)
69        .map_err(|e| ViewFunctionDecodeError::CannotGetInfo(e.into_owned()))?;
70
71    decode_view_function_response_with_info(cursor, &view_function_info, type_resolver, visitor)
72}
73
74/// Decode a View Function response.
75///
76/// Unlike [`decode_view_function_response`], which obtains the View Function information internally given the trait and
77/// method names, this function takes the View Function info as an argument. This is useful if you already have the
78/// View Function info available, for exampel if you are making multiple calls to the same API and wish to decode each one.
79pub fn decode_view_function_response_with_info<'scale, 'resolver, V>(
80    cursor: &mut &'scale [u8],
81    view_function_info: &ViewFunctionInfo<<V::TypeResolver as TypeResolver>::TypeId>,
82    type_resolver: &'resolver V::TypeResolver,
83    visitor: V,
84) -> Result<
85    V::Value<'scale, 'resolver>,
86    ViewFunctionDecodeError<<V::TypeResolver as TypeResolver>::TypeId>,
87>
88where
89    V: scale_decode::Visitor,
90    V::Error: core::fmt::Debug,
91{
92    let response_id = view_function_info.output_id.clone();
93
94    decode_with_error_tracing(cursor, response_id.clone(), type_resolver, visitor).map_err(|e| {
95        ViewFunctionDecodeError::CannotDecodeValue {
96            ty: response_id,
97            reason: e,
98        }
99    })
100}