Как вы конвертируете между специфическими типами субстратов и примитивными типами Rust?
Используя каркас цепочки блоков субстратов, как я могу конвертировать между специфическими типами субстратов и примитивными типами Rust и наоборот?
Например:
- Конвертировать время (
T::Moment
) кu64
- Конвертировать U64 в
T::Balance
так далее...
2 ответа
Для последних в субстрат мастер
Субстрат удален As
в пользу From
/ Into
, Предполагается, что все типы по крайней мере u32
,
Из черты SimpleArithmatic
, реализовано следующее:
From
:u8
,u16
,u32
TryFrom
:u64
,u128
,usize
TryInto
:u8
,u16
,u32
,u64
,u128
,usize
Еще одна черта также обеспечивает эргономическое безошибочное преобразование, когда вам все равно, насыщает ли значение.
UniqueSaturatedInto
:u8
,u16
,u32
,u64
,u128
UniqueSaturatedFrom
:u64
,u128
ПРИМЕЧАНИЕ на
SaturatedConversion
из Гав
SaturatedConversion
(saturated_into
а такжеsaturated_from
) не должны использоваться, если вы не знаете, что делаете, продумали и рассмотрели все варианты, а ваш сценарий использования подразумевает, что насыщение является в основном правильным. Единственный раз, когда я представляю, что это так, глубоко в арифметике времени выполнения, где вы логически уверены, что она не будет переполнена, но не можете предоставить доказательства, потому что это будет зависеть от согласованного ранее существовавшего состояния.
Это означает, что работа от u32
Подчеркнуть конкретные типы должно быть легко:
pub fn u32_to_balance(input: u32) -> T::Balance {
input.into()
}
Для более крупных типов вам нужно обработать случай, когда Balance
Тип для времени выполнения меньше, чем то, что доступно:
pub fn u64_to_balance_option(input: u64) -> Option<T::Balance> {
input.try_into().ok()
}
// Note the warning above about saturated conversions
pub fn u64_to_balance_saturated(input: u64) -> T::Balance {
input.saturated_into()
}
При конвертации из T::Balance
в примитив ржавчины необходимо также обрабатывать преобразования между несовместимыми типами:
pub fn balance_to_u64(input: T::Balance) -> Option<u64> {
TryInto::<u64>::try_into(input).ok()
}
// Note the warning above about saturated conversions
pub fn balance_to_u64_saturated(input: T::Balance) -> u64 {
input.saturated_into::<u64>()
}
Для субстрата v1.0
Субстрат обеспечивает pub trait As<T>
в sr-primitives
ящик:
/// Simple trait similar to `Into`, except that it can be used to convert numerics between each
/// other.
pub trait As<T> {
/// Convert forward (ala `Into::into`).
fn as_(self) -> T;
/// Convert backward (ala `From::from`).
fn sa(_: T) -> Self;
}
Вот несколько рабочих примеров того, как это можно использовать:
impl<T: Trait> Module<T> {
// `as_` will turn T::Balance into a u64
pub fn balance_to_u64(input: T::Balance) -> u64 {
input.as_()
}
// Being explicit, you can convert a `u64` to a T::Balance
// using the `As` trait, with `T: u64`, and then calling `sa`
pub fn u64_to_balance(input: u64) -> T::Balance {
<T::Balance as As<u64>>::sa(input)
}
// You can also let Rust figure out what `T` is
pub fn u64_to_balance_implied(input: u64) -> T::Balance {
<T::Balance as As<_>>::sa(input)
}
// You can also let Rust figure out where `sa` is implemented
pub fn u64_to_balance_implied_more(input: u64) -> T::Balance {
T::Balance::sa(input)
}
}
вот несколько примеров, которые должны помочь в преобразовании числа в тип баланса:
//declare following import
use frame_support::sp_runtime::traits::Zero;
use frame_support::sp_runtime::SaturatedConversion;
//then saturated_into can be used to convert number into Balance type as follows
let cost_in_u64: u64 = 250; //or expression like 200 + 50;
let cost: BalanceOf<T> = cost_in_u64.saturated_into::<BalanceOf<T>>();
//convert 1010 of type u32 into Balance
let cost2: BalanceOf<T> = 1010u32.into();
//set zero balance
let cost3 = BalanceOf::<T>::zero();
где BalanceOf определяется в cfg следующим образом
#[cfg(feature = "std")]
type BalanceOf<T> =
<<T as Config>::Currency as Currency<<T as frame_system::Config>::AccountId>>::Balance;