use super::runtime_api_type_info::{RuntimeApiInfo, RuntimeApiInfoError, RuntimeApiTypeInfo};
use crate::utils::{DecodeErrorTrace, decode_with_error_tracing};
use scale_type_resolver::TypeResolver;
#[non_exhaustive]
#[allow(missing_docs)]
#[derive(Clone, Debug, thiserror::Error)]
pub enum RuntimeApiDecodeError<TypeId> {
#[error("Cannot get Runtime API info: {0}")]
CannotGetInfo(RuntimeApiInfoError<'static>),
#[error("Cannot decode Runtime API response: {reason}")]
CannotDecodeValue {
ty: TypeId,
reason: DecodeErrorTrace,
},
}
pub fn decode_runtime_api_response<'scale, 'resolver, Info, Resolver, V>(
trait_name: &str,
method_name: &str,
cursor: &mut &'scale [u8],
info: &Info,
type_resolver: &'resolver Resolver,
visitor: V,
) -> Result<V::Value<'scale, 'resolver>, RuntimeApiDecodeError<Info::TypeId>>
where
Info: RuntimeApiTypeInfo,
Info::TypeId: Clone + core::fmt::Debug,
Resolver: TypeResolver<TypeId = Info::TypeId>,
V: scale_decode::Visitor<TypeResolver = Resolver>,
V::Error: core::fmt::Debug,
{
let runtime_api_info = info
.runtime_api_info(trait_name, method_name)
.map_err(|e| RuntimeApiDecodeError::CannotGetInfo(e.into_owned()))?;
decode_runtime_api_response_with_info(cursor, &runtime_api_info, type_resolver, visitor)
}
pub fn decode_runtime_api_response_with_info<'scale, 'resolver, V>(
cursor: &mut &'scale [u8],
runtime_api_info: &RuntimeApiInfo<<V::TypeResolver as TypeResolver>::TypeId>,
type_resolver: &'resolver V::TypeResolver,
visitor: V,
) -> Result<
V::Value<'scale, 'resolver>,
RuntimeApiDecodeError<<V::TypeResolver as TypeResolver>::TypeId>,
>
where
V: scale_decode::Visitor,
V::Error: core::fmt::Debug,
{
let response_id = runtime_api_info.output_id.clone();
decode_with_error_tracing(cursor, response_id.clone(), type_resolver, visitor).map_err(|e| {
RuntimeApiDecodeError::CannotDecodeValue {
ty: response_id,
reason: e,
}
})
}