mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-31 14:31:02 +00:00
subxt-historic: prep 0.0.8 release: expose type resolver that can be used with visitors (#2140)
* subxt-historic: prep 0.0.8 release: expose type resolver that can be used with visitors * clippy * Fix example * Fix docs test
This commit is contained in:
@@ -48,7 +48,8 @@ async fn main() -> Result<(), Box<dyn core::error::Error + Send + Sync + 'static
|
||||
.unwrap_or_default();
|
||||
|
||||
// When visiting fields we can also decode into a custom shape like so:
|
||||
let _custom_value = field.visit(value::GetValue::new())?;
|
||||
let _custom_value =
|
||||
field.visit(value::GetValue::new(&client_at_block.resolver()))?;
|
||||
|
||||
// We can also obtain and decode things without the complexity of the above:
|
||||
println!(
|
||||
@@ -183,7 +184,8 @@ mod value {
|
||||
I256([u8; 32]),
|
||||
U256([u8; 32]),
|
||||
Struct(HashMap<String, Value>),
|
||||
Variant(String, VariantFields),
|
||||
VariantWithoutData(String),
|
||||
VariantWithData(String, VariantFields),
|
||||
}
|
||||
|
||||
pub enum VariantFields {
|
||||
@@ -198,23 +200,23 @@ mod value {
|
||||
Decode(#[from] scale_decode::visitor::DecodeError),
|
||||
#[error("Cannot decode bit sequence: {0}")]
|
||||
CannotDecodeBitSequence(codec::Error),
|
||||
#[error("Cannot resolve variant type information: {0}")]
|
||||
CannotResolveVariantType(String),
|
||||
}
|
||||
|
||||
/// This is a visitor which obtains type names.
|
||||
pub struct GetValue<R> {
|
||||
marker: core::marker::PhantomData<R>,
|
||||
pub struct GetValue<'r, R> {
|
||||
resolver: &'r R,
|
||||
}
|
||||
|
||||
impl<R> GetValue<R> {
|
||||
impl<'r, R> GetValue<'r, R> {
|
||||
/// Construct our TypeName visitor.
|
||||
pub fn new() -> Self {
|
||||
GetValue {
|
||||
marker: core::marker::PhantomData,
|
||||
}
|
||||
pub fn new(resolver: &'r R) -> Self {
|
||||
GetValue { resolver }
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: TypeResolver> Visitor for GetValue<R> {
|
||||
impl<'r, R: TypeResolver> Visitor for GetValue<'r, R> {
|
||||
type Value<'scale, 'resolver> = Value;
|
||||
type Error = ValueError;
|
||||
type TypeResolver = R;
|
||||
@@ -346,7 +348,11 @@ mod value {
|
||||
values: &mut Array<'scale, 'resolver, Self::TypeResolver>,
|
||||
_type_id: TypeIdFor<Self>,
|
||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||
Ok(Value::Array(to_array(values.remaining(), values)?))
|
||||
Ok(Value::Array(to_array(
|
||||
self.resolver,
|
||||
values.remaining(),
|
||||
values,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn visit_sequence<'scale, 'resolver>(
|
||||
@@ -354,7 +360,11 @@ mod value {
|
||||
values: &mut Sequence<'scale, 'resolver, Self::TypeResolver>,
|
||||
_type_id: TypeIdFor<Self>,
|
||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||
Ok(Value::Array(to_array(values.remaining(), values)?))
|
||||
Ok(Value::Array(to_array(
|
||||
self.resolver,
|
||||
values.remaining(),
|
||||
values,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn visit_str<'scale, 'resolver>(
|
||||
@@ -370,7 +380,11 @@ mod value {
|
||||
values: &mut Tuple<'scale, 'resolver, Self::TypeResolver>,
|
||||
_type_id: TypeIdFor<Self>,
|
||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||
Ok(Value::Array(to_array(values.remaining(), values)?))
|
||||
Ok(Value::Array(to_array(
|
||||
self.resolver,
|
||||
values.remaining(),
|
||||
values,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn visit_bitsequence<'scale, 'resolver>(
|
||||
@@ -401,7 +415,7 @@ mod value {
|
||||
}
|
||||
|
||||
// Reuse logic for decoding variant fields:
|
||||
match to_variant_fieldish(value)? {
|
||||
match to_variant_fieldish(self.resolver, value)? {
|
||||
VariantFields::Named(s) => Ok(Value::Struct(s)),
|
||||
VariantFields::Unnamed(a) => Ok(Value::Array(a)),
|
||||
}
|
||||
@@ -410,20 +424,50 @@ mod value {
|
||||
fn visit_variant<'scale, 'resolver>(
|
||||
self,
|
||||
value: &mut Variant<'scale, 'resolver, Self::TypeResolver>,
|
||||
_type_id: TypeIdFor<Self>,
|
||||
type_id: TypeIdFor<Self>,
|
||||
) -> Result<Self::Value<'scale, 'resolver>, Self::Error> {
|
||||
// Because we have access to a type resolver on self, we can
|
||||
// look up the type IDs we're given back and base decode decisions
|
||||
// on them. here we see whether the enum type has any data attached:
|
||||
let has_data_visitor = scale_type_resolver::visitor::new((), |_, _| false)
|
||||
.visit_variant(|_, _, variants| {
|
||||
for mut variant in variants {
|
||||
if variant.fields.next().is_some() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
});
|
||||
|
||||
// Do any variants have data in this enum type?
|
||||
let has_data = self
|
||||
.resolver
|
||||
.resolve_type(type_id, has_data_visitor)
|
||||
.map_err(|e| ValueError::CannotResolveVariantType(e.to_string()))?;
|
||||
|
||||
let name = value.name().to_owned();
|
||||
let fields = to_variant_fieldish(value.fields())?;
|
||||
Ok(Value::Variant(name, fields))
|
||||
|
||||
// base our decoding on whether any data in enum type.
|
||||
if has_data {
|
||||
let fields = to_variant_fieldish(self.resolver, value.fields())?;
|
||||
Ok(Value::VariantWithData(name, fields))
|
||||
} else {
|
||||
Ok(Value::VariantWithoutData(name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn to_variant_fieldish<'scale, 'resolver, R: TypeResolver>(
|
||||
fn to_variant_fieldish<'r, 'scale, 'resolver, R: TypeResolver>(
|
||||
resolver: &'r R,
|
||||
value: &mut Composite<'scale, 'resolver, R>,
|
||||
) -> Result<VariantFields, ValueError> {
|
||||
// If fields are unnamed, treat as array:
|
||||
if value.fields().iter().all(|f| f.name.is_none()) {
|
||||
return Ok(VariantFields::Unnamed(to_array(value.remaining(), value)?));
|
||||
return Ok(VariantFields::Unnamed(to_array(
|
||||
resolver,
|
||||
value.remaining(),
|
||||
value,
|
||||
)?));
|
||||
}
|
||||
|
||||
// Otherwise object:
|
||||
@@ -431,18 +475,19 @@ mod value {
|
||||
for field in value {
|
||||
let field = field?;
|
||||
let name = field.name().unwrap().to_string();
|
||||
let value = field.decode_with_visitor(GetValue::new())?;
|
||||
let value = field.decode_with_visitor(GetValue::new(resolver))?;
|
||||
out.insert(name, value);
|
||||
}
|
||||
Ok(VariantFields::Named(out))
|
||||
}
|
||||
|
||||
fn to_array<'scale, 'resolver, R: TypeResolver>(
|
||||
fn to_array<'r, 'scale, 'resolver, R: TypeResolver>(
|
||||
resolver: &'r R,
|
||||
len: usize,
|
||||
mut values: impl scale_decode::visitor::DecodeItemIterator<'scale, 'resolver, R>,
|
||||
) -> Result<Vec<Value>, ValueError> {
|
||||
let mut out = Vec::with_capacity(len);
|
||||
while let Some(value) = values.decode_item(GetValue::new()) {
|
||||
while let Some(value) = values.decode_item(GetValue::new(resolver)) {
|
||||
out.push(value?);
|
||||
}
|
||||
Ok(out)
|
||||
|
||||
Reference in New Issue
Block a user