diff --git a/CHANGELOG.md b/CHANGELOG.md index 442c8be..4ce94eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ The format is based on [Keep a Changelog]. [Keep a Changelog]: http://keepachangelog.com/en/1.0.0/ +## 0.12.1 (2025-11-12) + +- Add `map_ids()` functions to `RuntimeApiInfo`, `StorageInfo` and `ViewFunctionInfo` to make translating the `TypeId` parameter simpler. + This adds a `'static` bound to `StorageInfo` type IDs, but it is not expected that this will break anything as this is already the case for `u32` and `LookupName` IDs (and is required in many other places). + ## 0.12.0 (2025-11-10) - Bump to scale-info-legacy 0.3.0. diff --git a/Cargo.lock b/Cargo.lock index fb69f44..e15bda5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -161,7 +161,7 @@ checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" [[package]] name = "frame-decode" -version = "0.12.0" +version = "0.12.1" dependencies = [ "frame-metadata", "hex", diff --git a/Cargo.toml b/Cargo.toml index a987851..7b6972c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "frame-decode" -version = "0.12.0" +version = "0.12.1" edition = "2024" description = "Decode extrinsics and storage from Substrate based chains" license = "Apache-2.0" diff --git a/src/methods/runtime_api_type_info.rs b/src/methods/runtime_api_type_info.rs index ecaeae4..d88a3da 100644 --- a/src/methods/runtime_api_type_info.rs +++ b/src/methods/runtime_api_type_info.rs @@ -17,7 +17,8 @@ use super::Entry; use crate::utils::Either; use alloc::borrow::Cow; use alloc::borrow::ToOwned; -use alloc::string::String; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; /// This can be implemented for anything capable of providing Runtime API type information. /// It is implemented for newer versions of frame-metadata (V15 and above). @@ -93,6 +94,42 @@ impl<'info, TypeId: Clone + 'static> RuntimeApiInfo<'info, TypeId> { output_id: self.output_id, } } + + /// Map the type IDs in this [`RuntimeApiInfo`], returning a new one or bailing early with an error if something goes wrong. + /// This also takes ownership of the [`RuntimeApiInfo`], turning the lifetime to static. + pub fn map_ids Result>( + self, + mut f: F, + ) -> Result, E> { + let new_output_id = f(self.output_id)?; + let mut new_inputs = Vec::with_capacity(self.inputs.len()); + + match self.inputs { + Cow::Borrowed(inputs) => { + for input in inputs { + new_inputs.push(RuntimeApiInput { + // We always have to allocate if inputs is borrowed: + name: Cow::Owned(input.name.to_string()), + id: f(input.id.clone())?, + }); + } + } + Cow::Owned(inputs) => { + for input in inputs { + new_inputs.push(RuntimeApiInput { + // If inputs is owned, we only allocate if name is borrowed: + name: Cow::Owned(input.name.into_owned()), + id: f(input.id.clone())?, + }); + } + } + } + + Ok(RuntimeApiInfo { + inputs: Cow::Owned(new_inputs), + output_id: new_output_id, + }) + } } /// Information about a specific input value to a Runtime API. diff --git a/src/methods/storage_type_info.rs b/src/methods/storage_type_info.rs index b2278fe..bbf462b 100644 --- a/src/methods/storage_type_info.rs +++ b/src/methods/storage_type_info.rs @@ -131,7 +131,7 @@ pub struct StorageInfo<'info, TypeId: Clone> { pub default_value: Option>, } -impl<'info, TypeId: Clone> StorageInfo<'info, TypeId> { +impl<'info, TypeId: Clone + 'static> StorageInfo<'info, TypeId> { /// Take ownership of this [`StorageInfo`], turning any lifetimes to `'static`. pub fn into_owned(self) -> StorageInfo<'static, TypeId> { StorageInfo { @@ -140,6 +140,29 @@ impl<'info, TypeId: Clone> StorageInfo<'info, TypeId> { default_value: self.default_value.map(|v| Cow::Owned(v.into_owned())), } } + + /// Map the type IDs in this [`StorageInfo`], returning a new one or bailing early with an error if something goes wrong. + /// This also takes ownership of the [`StorageInfo`], turning the lifetime to static. + pub fn map_ids Result>( + self, + mut f: F, + ) -> Result, E> { + let new_value_id = f(self.value_id)?; + let mut new_keys = Vec::with_capacity(self.keys.len()); + + for k in self.keys.iter() { + new_keys.push(StorageKeyInfo { + hasher: k.hasher, + key_id: f(k.key_id.clone())?, + }); + } + + Ok(StorageInfo { + keys: Cow::Owned(new_keys), + value_id: new_value_id, + default_value: self.default_value.map(|d| Cow::Owned(d.into_owned())), + }) + } } /// Information about a single key within a storage entry. diff --git a/src/methods/view_function_type_info.rs b/src/methods/view_function_type_info.rs index 901edfc..f33e7b3 100644 --- a/src/methods/view_function_type_info.rs +++ b/src/methods/view_function_type_info.rs @@ -17,7 +17,8 @@ use super::Entry; use crate::utils::Either; use alloc::borrow::Cow; use alloc::borrow::ToOwned; -use alloc::string::String; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; /// This is implemented for anything capable of providing information about view functions /// (primarily metadata V16 and onwards). @@ -96,6 +97,43 @@ impl<'info, TypeId: Clone> ViewFunctionInfo<'info, TypeId> { output_id: self.output_id, } } + + /// Map the type IDs in this [`ViewFunctionInfo`], returning a new one or bailing early with an error if something goes wrong. + /// This also takes ownership of the [`ViewFunctionInfo`], turning the lifetime to static. + pub fn map_ids Result>( + self, + mut f: F, + ) -> Result, E> { + let new_output_id = f(self.output_id)?; + let mut new_inputs = Vec::with_capacity(self.inputs.len()); + + match self.inputs { + Cow::Borrowed(inputs) => { + for input in inputs { + new_inputs.push(ViewFunctionInput { + // We always have to allocate if inputs is borrowed: + name: Cow::Owned(input.name.to_string()), + id: f(input.id.clone())?, + }); + } + } + Cow::Owned(inputs) => { + for input in inputs { + new_inputs.push(ViewFunctionInput { + // If inputs is owned, we only allocate if name is borrowed: + name: Cow::Owned(input.name.into_owned()), + id: f(input.id.clone())?, + }); + } + } + } + + Ok(ViewFunctionInfo { + query_id: self.query_id, + inputs: Cow::Owned(new_inputs), + output_id: new_output_id, + }) + } } /// Information about a specific input value to a View Function.