From 26a60183f8cdabbc07c800609bfd6b27be0559e8 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Tue, 31 Oct 2023 12:05:42 +0000 Subject: [PATCH] Get compiling with scale-value and scale-decode --- Cargo.lock | 162 ++- Cargo.toml | 2 + desub-current/Cargo.toml | 2 + desub-current/src/decoder/decode_storage.rs | 15 +- desub-current/src/decoder/decode_value.rs | 461 ------- desub-current/src/decoder/mod.rs | 16 +- desub-current/src/lib.rs | 8 +- desub-current/src/metadata/mod.rs | 2 +- desub-current/src/type_id.rs | 51 - desub-current/src/value/deserialize.rs | 669 --------- desub-current/src/value/deserializer.rs | 1361 ------------------- desub-current/src/value/mod.rs | 298 ---- desub-current/src/value/serialize.rs | 190 --- desub-current/tests/decode_extrinsics.rs | 47 +- desub-current/tests/decode_storage.rs | 24 +- 15 files changed, 216 insertions(+), 3092 deletions(-) delete mode 100644 desub-current/src/decoder/decode_value.rs delete mode 100644 desub-current/src/type_id.rs delete mode 100644 desub-current/src/value/deserialize.rs delete mode 100644 desub-current/src/value/deserializer.rs delete mode 100644 desub-current/src/value/mod.rs delete mode 100644 desub-current/src/value/serialize.rs diff --git a/Cargo.lock b/Cargo.lock index e569e156..e0569c2f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -442,6 +442,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" +[[package]] +name = "base58" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6107fe1be6682a68940da878d9e9f5e90ca5745b3dec9fd1bb393c8777d4f581" + [[package]] name = "base64" version = "0.13.1" @@ -665,7 +671,7 @@ dependencies = [ "ansi_term", "atty", "bitflags 1.3.2", - "strsim", + "strsim 0.8.0", "textwrap", "unicode-width", "vec_map", @@ -959,6 +965,41 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "der" version = "0.7.8" @@ -1001,7 +1042,7 @@ dependencies = [ "desub-current", "desub-json-resolver", "desub-legacy", - "frame-metadata", + "frame-metadata 16.0.0", "parity-scale-codec", "serde_json", "thiserror", @@ -1023,11 +1064,13 @@ dependencies = [ "bitvec", "derive_more", "desub-common", - "frame-metadata", + "frame-metadata 16.0.0", "hex", "log", "parity-scale-codec", + "scale-decode", "scale-info", + "scale-value", "serde", "serde_json", "sp-core", @@ -1058,7 +1101,7 @@ dependencies = [ "derive_more", "desub-common", "dyn-clone", - "frame-metadata", + "frame-metadata 16.0.0", "hex", "log", "onig", @@ -1400,6 +1443,12 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.2.0" @@ -1435,6 +1484,17 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "frame-metadata" +version = "15.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "878babb0b136e731cc77ec2fd883ff02745ff21e6fb662729953d44923df009c" +dependencies = [ + "cfg-if", + "parity-scale-codec", + "scale-info", +] + [[package]] name = "frame-metadata" version = "16.0.0" @@ -1457,7 +1517,7 @@ dependencies = [ "bitflags 1.3.2", "docify", "environmental", - "frame-metadata", + "frame-metadata 16.0.0", "frame-support-procedural", "impl-trait-for-tuples", "k256", @@ -1938,6 +1998,12 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.4.0" @@ -3271,6 +3337,58 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-bits" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "036575c29af9b6e4866ffb7fa055dbf623fe7a9cc159b33786de6013a6969d89" +dependencies = [ + "parity-scale-codec", + "scale-info", + "serde", +] + +[[package]] +name = "scale-decode" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7789f5728e4e954aaa20cadcc370b99096fb8645fca3c9333ace44bb18f30095" +dependencies = [ + "derive_more", + "parity-scale-codec", + "primitive-types", + "scale-bits", + "scale-decode-derive", + "scale-info", + "smallvec", +] + +[[package]] +name = "scale-decode-derive" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27873eb6005868f8cc72dcfe109fae664cf51223d35387bc2f28be4c28d94c47" +dependencies = [ + "darling", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "scale-encode" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d70cb4b29360105483fac1ed567ff95d65224a14dd275b6303ed0a654c78de5" +dependencies = [ + "derive_more", + "parity-scale-codec", + "scale-bits", + "scale-info", + "smallvec", +] + [[package]] name = "scale-info" version = "2.10.0" @@ -3297,6 +3415,26 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "scale-value" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6538d1cc1af9c0baf401c57da8a6d4730ef582db0d330d2efa56ec946b5b0283" +dependencies = [ + "base58", + "blake2", + "derive_more", + "either", + "frame-metadata 15.1.0", + "parity-scale-codec", + "scale-bits", + "scale-decode", + "scale-encode", + "scale-info", + "serde", + "yap", +] + [[package]] name = "schnellru" version = "0.2.1" @@ -3802,7 +3940,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb0dec8af38c68358600da59cf14424e1230fe9ae1d4b4f64a098288145c0775" dependencies = [ - "frame-metadata", + "frame-metadata 16.0.0", "parity-scale-codec", "scale-info", "sp-std", @@ -4192,6 +4330,12 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "structopt" version = "0.3.26" @@ -5143,6 +5287,12 @@ dependencies = [ "tap", ] +[[package]] +name = "yap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff4524214bc4629eba08d78ceb1d6507070cc0bcbbed23af74e19e6e924a24cf" + [[package]] name = "zerocopy" version = "0.7.20" diff --git a/Cargo.toml b/Cargo.toml index 84a04acd..41d6dfd7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,8 @@ edition = "2021" [workspace.dependencies] parity-scale-codec = "3.6.5" scale-info = "2.10.0" +scale-value = "0.12.0" +scale-decode = "0.9" frame-metadata = "16" bitvec = "1" diff --git a/desub-current/Cargo.toml b/desub-current/Cargo.toml index 19700e4e..f12d9f8b 100644 --- a/desub-current/Cargo.toml +++ b/desub-current/Cargo.toml @@ -23,6 +23,8 @@ derive_more = "0.99.16" scale-info = { workspace = true, features = ["bit-vec", "derive"] } bitvec = { workspace = true, features = ["serde", "alloc"] } desub-common = { version = "0.1.0", path = "../desub-common" } +scale-value = { workspace = true } +scale-decode = { workspace = true } sp-core = { workspace = true } sp-runtime = { workspace = true } diff --git a/desub-current/src/decoder/decode_storage.rs b/desub-current/src/decoder/decode_storage.rs index d17b4eef..973c35da 100644 --- a/desub-current/src/decoder/decode_storage.rs +++ b/desub-current/src/decoder/decode_storage.rs @@ -23,7 +23,7 @@ struct StorageEntries { entry_by_hashed_name: HashMap<[u8; 16], usize>, } -#[derive(thiserror::Error, Debug, Clone, PartialEq)] +#[derive(thiserror::Error, Debug)] pub enum StorageDecodeError { #[error("Not enough bytes in the input data to decode the storage prefix and name; got {0} bytes but expected 32")] NotEnoughBytesForPrefixAndName(usize), @@ -87,7 +87,7 @@ impl StorageDecoder { Ok(StorageEntry { prefix: prefix_str.into(), name: name_str.into(), - ty: ty.into(), + ty: ty.id, details: StorageEntryType::Plain, }) } @@ -155,7 +155,7 @@ impl StorageDecoder { Ok(StorageEntry { prefix: prefix_str.into(), name: name_str.into(), - ty: value.into(), + ty: value.id, details: StorageEntryType::Map(storage_keys), }) } @@ -190,16 +190,17 @@ impl StorageDecoder { // See https://github.com/paritytech/subxt/blob/793c945fbd2de022f523c39a84ee02609ba423a9/codegen/src/api/storage.rs#L105 // for another example of this being handled in code. fn storage_map_key_to_type_id_vec(metadata: &Metadata, key: &ScaleInfoTypeId) -> Vec { - let ty = match metadata.resolve(key) { + let ty_id = key.id; + let ty = match metadata.resolve(ty_id) { Some(ty) => ty, - None => panic!("Metadata inconsistency: type #{} not found", key.id), + None => panic!("Metadata inconsistency: type #{} not found", ty_id), }; match &ty.type_def { // Multiple keys: - scale_info::TypeDef::Tuple(vals) => vals.fields.iter().map(|f| TypeId::from_u32(f.id)).collect(), + scale_info::TypeDef::Tuple(vals) => vals.fields.iter().map(|f| f.id).collect(), // Single key: - _ => vec![key.into()], + _ => vec![ty_id], } } diff --git a/desub-current/src/decoder/decode_value.rs b/desub-current/src/decoder/decode_value.rs deleted file mode 100644 index 53c18e9a..00000000 --- a/desub-current/src/decoder/decode_value.rs +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of substrate-desub. -// -// substrate-desub is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// substrate-desub is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with substrate-desub. If not, see . - -use crate::value::{BitSequence, Composite, Primitive, Value, ValueDef, Variant}; -use crate::{Type, TypeId}; -use parity_scale_codec::{Compact, Decode}; -use scale_info::{ - form::PortableForm, Field, PortableRegistry, TypeDefArray, TypeDefBitSequence, TypeDefCompact, TypeDefComposite, - TypeDefPrimitive, TypeDefSequence, TypeDefTuple, TypeDefVariant, -}; - -// This is used in several places below. -type TypeDef = scale_info::TypeDef; - -#[derive(Debug, Clone, thiserror::Error, PartialEq)] -pub enum DecodeValueError { - #[error("{0}")] - CodecError(#[from] parity_scale_codec::Error), - #[error("{0} is expected to be a valid char, but is not")] - InvalidChar(u32), - #[error("Cannot find type with ID {0}")] - TypeIdNotFound(u32), - #[error("Ran out of data during decoding")] - Eof, - #[error("Could not find variant with index {0} in {1:?}")] - VariantNotFound(u8, scale_info::TypeDefVariant), - #[error("Could not decode compact encoded type into {0:?}")] - CannotDecodeCompactIntoType(Type), -} - -/// Decode data according to the [`TypeId`] provided. -/// The provided pointer to the data slice will be moved forwards as needed -/// depending on what was decoded. -pub fn decode_value_by_id>( - data: &mut &[u8], - ty_id: Id, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - let ty_id = ty_id.into(); - let ty = types.resolve(ty_id.id()).ok_or_else(|| DecodeValueError::TypeIdNotFound(ty_id.id()))?; - - let value = match &ty.type_def { - TypeDef::Composite(inner) => decode_composite_value(data, inner, types).map(ValueDef::Composite), - TypeDef::Sequence(inner) => decode_sequence_value(data, inner, types).map(ValueDef::Composite), - TypeDef::Array(inner) => decode_array_value(data, inner, types).map(ValueDef::Composite), - TypeDef::Tuple(inner) => decode_tuple_value(data, inner, types).map(ValueDef::Composite), - TypeDef::Variant(inner) => decode_variant_value(data, inner, types).map(ValueDef::Variant), - TypeDef::Primitive(inner) => decode_primitive_value(data, inner).map(ValueDef::Primitive), - TypeDef::Compact(inner) => decode_compact_value(data, inner, types), - TypeDef::BitSequence(inner) => decode_bit_sequence_value(data, inner, types).map(ValueDef::BitSequence), - }?; - - Ok(Value { value, context: ty_id }) -} - -fn decode_composite_value( - data: &mut &[u8], - ty: &TypeDefComposite, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - decode_fields(data, &ty.fields, types) -} - -fn decode_variant_value( - data: &mut &[u8], - ty: &TypeDefVariant, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - let index = *data.get(0).ok_or(DecodeValueError::Eof)?; - *data = &data[1..]; - - // Does a variant exist with the index we're looking for? - let variant = ty - .variants - .iter() - .find(|v| v.index == index) - .ok_or_else(|| DecodeValueError::VariantNotFound(index, ty.clone()))?; - - let fields = decode_fields(data, &variant.fields, types)?; - Ok(Variant { name: variant.name.clone(), values: fields }) -} - -/// Variant and Composite types both have fields; this will decode them into values. -fn decode_fields( - data: &mut &[u8], - fields: &[Field], - types: &PortableRegistry, -) -> Result, DecodeValueError> { - let are_named = fields.iter().any(|f| f.name.is_some()); - let named_field_vals = fields.iter().map(|f| { - let name = f.name.as_ref().cloned().unwrap_or_default(); - decode_value_by_id(data, f.ty, types).map(|val| (name, val)) - }); - - if are_named { - let vals = named_field_vals.collect::>()?; - Ok(Composite::Named(vals)) - } else { - let vals = named_field_vals.map(|r| r.map(|(_, v)| v)).collect::>()?; - Ok(Composite::Unnamed(vals)) - } -} - -fn decode_sequence_value( - data: &mut &[u8], - ty: &TypeDefSequence, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - // We assume that the sequence is preceeded by a compact encoded length, so that - // we know how many values to try pulling out of the data. - let len = Compact::::decode(data)?; - let values: Vec<_> = - (0..len.0).map(|_| decode_value_by_id(data, &ty.type_param, types)).collect::>()?; - - Ok(Composite::Unnamed(values)) -} - -fn decode_array_value( - data: &mut &[u8], - ty: &TypeDefArray, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - // The length is known based on the type we want to decode into, so we pull out the number of items according - // to that, and don't need a length to exist in the SCALE encoded bytes - let values: Vec<_> = - (0..ty.len).map(|_| decode_value_by_id(data, &ty.type_param, types)).collect::>()?; - - Ok(Composite::Unnamed(values)) -} - -fn decode_tuple_value( - data: &mut &[u8], - ty: &TypeDefTuple, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - let values: Vec<_> = ty.fields.iter().map(|f| decode_value_by_id(data, f, types)).collect::>()?; - - Ok(Composite::Unnamed(values)) -} - -fn decode_primitive_value(data: &mut &[u8], ty: &TypeDefPrimitive) -> Result { - let val = match ty { - TypeDefPrimitive::Bool => Primitive::Bool(bool::decode(data)?), - TypeDefPrimitive::Char => { - // [jsdw] TODO: There isn't a `char::decode`. Why? Is it wrong to use u32 or is there a more "proper" way? - let val = u32::decode(data)?; - Primitive::Char(char::from_u32(val).ok_or(DecodeValueError::InvalidChar(val))?) - } - TypeDefPrimitive::Str => Primitive::Str(String::decode(data)?), - TypeDefPrimitive::U8 => Primitive::U8(u8::decode(data)?), - TypeDefPrimitive::U16 => Primitive::U16(u16::decode(data)?), - TypeDefPrimitive::U32 => Primitive::U32(u32::decode(data)?), - TypeDefPrimitive::U64 => Primitive::U64(u64::decode(data)?), - TypeDefPrimitive::U128 => Primitive::U128(u128::decode(data)?), - TypeDefPrimitive::U256 => Primitive::U256(<[u8; 32]>::decode(data)?), - TypeDefPrimitive::I8 => Primitive::I8(i8::decode(data)?), - TypeDefPrimitive::I16 => Primitive::I16(i16::decode(data)?), - TypeDefPrimitive::I32 => Primitive::I32(i32::decode(data)?), - TypeDefPrimitive::I64 => Primitive::I64(i64::decode(data)?), - TypeDefPrimitive::I128 => Primitive::I128(i128::decode(data)?), - TypeDefPrimitive::I256 => Primitive::I256(<[u8; 32]>::decode(data)?), - }; - Ok(val) -} - -fn decode_compact_value( - data: &mut &[u8], - ty: &TypeDefCompact, - types: &PortableRegistry, -) -> Result, DecodeValueError> { - fn decode_compact( - data: &mut &[u8], - inner: &Type, - types: &PortableRegistry, - ) -> Result, DecodeValueError> { - use TypeDefPrimitive::*; - let val = match &inner.type_def { - // It's obvious how to decode basic primitive unsigned types, since we have impls for them. - TypeDef::Primitive(U8) => ValueDef::Primitive(Primitive::U8(Compact::::decode(data)?.0)), - TypeDef::Primitive(U16) => ValueDef::Primitive(Primitive::U16(Compact::::decode(data)?.0)), - TypeDef::Primitive(U32) => ValueDef::Primitive(Primitive::U32(Compact::::decode(data)?.0)), - TypeDef::Primitive(U64) => ValueDef::Primitive(Primitive::U64(Compact::::decode(data)?.0)), - TypeDef::Primitive(U128) => ValueDef::Primitive(Primitive::U128(Compact::::decode(data)?.0)), - // A struct with exactly 1 field containing one of the above types can be sensibly compact encoded/decoded. - TypeDef::Composite(composite) => { - if composite.fields.len() != 1 { - return Err(DecodeValueError::CannotDecodeCompactIntoType(inner.clone())); - } - - // What type is the 1 field that we are able to decode? - let field = &composite.fields[0]; - let field_type_id = field.ty.id; - let inner_ty = types.resolve(field_type_id).ok_or(DecodeValueError::TypeIdNotFound(field_type_id))?; - - // Decode this inner type via compact decoding. This can recurse, in case - // the inner type is also a 1-field composite type. - let inner_value = Value { value: decode_compact(data, inner_ty, types)?, context: field.ty.into() }; - - // Wrap the inner type in a representation of this outer composite type. - let composite = match &field.name { - Some(name) => Composite::Named(vec![(name.clone(), inner_value)]), - None => Composite::Unnamed(vec![inner_value]), - }; - - ValueDef::Composite(composite) - } - // For now, we give up if we have been asked for any other type: - _cannot_decode_from => return Err(DecodeValueError::CannotDecodeCompactIntoType(inner.clone())), - }; - - Ok(val) - } - - // Pluck the inner type out and run it through our compact decoding logic. - let inner = - types.resolve(ty.type_param.id).ok_or_else(|| DecodeValueError::TypeIdNotFound(ty.type_param.id))?; - decode_compact(data, inner, types) -} - -fn decode_bit_sequence_value( - data: &mut &[u8], - _ty: &TypeDefBitSequence, - _types: &PortableRegistry, -) -> Result { - // [jsdw] TODO: might be worth checking the bit_store and bit_order types - // and trying to work out whether they look like Lsb0 and u8, which is what - // we assume here. - let bit_vec: BitSequence = Decode::decode(data)?; - Ok(bit_vec) -} - -#[cfg(test)] -mod test { - - use super::*; - use parity_scale_codec::Encode; - - /// Given a type definition, return the PortableType and PortableRegistry - /// that our decode functions expect. - fn make_type() -> (TypeId, PortableRegistry) { - let m = scale_info::MetaType::new::(); - let mut types = scale_info::Registry::new(); - let id = types.register_type(&m); - let portable_registry: PortableRegistry = types.into(); - - (id.into(), portable_registry) - } - - /// Given a value to encode, and a representation of the decoded value, check that our decode functions - /// successfully decodes the type to the expected value, based on the implicit SCALE type info that the type - /// carries - fn encode_decode_check(val: T, exp: Value<()>) { - encode_decode_check_explicit_info::(val, exp) - } - - /// Given a value to encode, a type to decode it back into, and a representation of - /// the decoded value, check that our decode functions successfully decodes as expected. - fn encode_decode_check_explicit_info(val: T, ex: Value<()>) { - let encoded = val.encode(); - let encoded = &mut &*encoded; - - let (id, portable_registry) = make_type::(); - - // Can we decode? - let val = decode_value_by_id(encoded, id, &portable_registry).expect("decoding failed"); - // Is the decoded value what we expected? - assert_eq!(val.without_context(), ex, "decoded value does not look like what we expected"); - // Did decoding consume all of the encoded bytes, as expected? - assert_eq!(encoded.len(), 0, "decoding did not consume all of the encoded bytes"); - } - - #[test] - fn decode_primitives() { - encode_decode_check(true, Value::bool(true)); - encode_decode_check(false, Value::bool(false)); - encode_decode_check_explicit_info::('a' as u32, Value::char('a')); - encode_decode_check("hello", Value::str("hello".into())); - encode_decode_check( - "hello".to_string(), // String or &str (above) decode OK - Value::str("hello".into()), - ); - encode_decode_check(123u8, Value::u8(123)); - encode_decode_check(123u16, Value::u16(123)); - encode_decode_check(123u32, Value::u32(123)); - encode_decode_check(123u64, Value::u64(123)); - //// Todo [jsdw]: Can we test this if we need a TypeInfo param?: - // encode_decode_check_explicit_info( - // [123u8; 32], // Anything 32 bytes long will do here - // Value::u256([123u8; 32]), - // ); - encode_decode_check(123i8, Value::i8(123)); - encode_decode_check(123i16, Value::i16(123)); - encode_decode_check(123i32, Value::i32(123)); - encode_decode_check(123i64, Value::i64(123)); - //// Todo [jsdw]: Can we test this if we need a TypeInfo param?: - // encode_decode_check_explicit_info( - // [123u8; 32], // Anything 32 bytes long will do here - // Value::i256([123u8; 32]), - // ); - } - - #[test] - fn decode_compact_primitives() { - encode_decode_check(Compact(123u8), Value::u8(123)); - encode_decode_check(Compact(123u16), Value::u16(123)); - encode_decode_check(Compact(123u32), Value::u32(123)); - encode_decode_check(Compact(123u64), Value::u64(123)); - encode_decode_check(Compact(123u128), Value::u128(123)); - } - - #[test] - fn decode_compact_named_wrapper_struct() { - // A struct that can be compact encoded: - #[derive(Encode, scale_info::TypeInfo)] - struct MyWrapper { - inner: u32, - } - impl From> for MyWrapper { - fn from(val: Compact) -> MyWrapper { - val.0 - } - } - impl parity_scale_codec::CompactAs for MyWrapper { - type As = u32; - - fn encode_as(&self) -> &Self::As { - &self.inner - } - fn decode_from(inner: Self::As) -> Result { - Ok(MyWrapper { inner }) - } - } - - encode_decode_check( - Compact(MyWrapper { inner: 123 }), - Value::named_composite(vec![("inner".to_string(), Value::u32(123))]), - ); - } - - #[test] - fn decode_compact_unnamed_wrapper_struct() { - // A struct that can be compact encoded: - #[derive(Encode, scale_info::TypeInfo)] - struct MyWrapper(u32); - impl From> for MyWrapper { - fn from(val: Compact) -> MyWrapper { - val.0 - } - } - impl parity_scale_codec::CompactAs for MyWrapper { - type As = u32; - - // Node the requirement to return something with a lifetime tied - // to self here. This means that we can't implement this for things - // more complex than wrapper structs (eg `Foo(u32,u32,u32,u32)`) without - // shenanigans, meaning that (hopefully) supporting wrapper struct - // decoding and nothing fancier is sufficient. - fn encode_as(&self) -> &Self::As { - &self.0 - } - fn decode_from(inner: Self::As) -> Result { - Ok(MyWrapper(inner)) - } - } - - encode_decode_check(Compact(MyWrapper(123)), Value::unnamed_composite(vec![Value::u32(123)])); - } - - #[test] - fn decode_sequence_array_tuple_types() { - encode_decode_check( - vec![1i32, 2, 3], - Value::unnamed_composite(vec![Value::i32(1), Value::i32(2), Value::i32(3)]), - ); - encode_decode_check( - [1i32, 2, 3], //compile-time length known - Value::unnamed_composite(vec![Value::i32(1), Value::i32(2), Value::i32(3)]), - ); - encode_decode_check( - (1i32, true, 123456u128), - Value::unnamed_composite(vec![Value::i32(1), Value::bool(true), Value::u128(123456)]), - ); - } - - #[test] - fn decode_variant_types() { - #[derive(Encode, scale_info::TypeInfo)] - enum MyEnum { - Foo(bool), - Bar { hi: String, other: u128 }, - } - - encode_decode_check( - MyEnum::Foo(true), - Value::variant("Foo".to_string(), Composite::Unnamed(vec![Value::bool(true)])), - ); - encode_decode_check( - MyEnum::Bar { hi: "hello".to_string(), other: 123 }, - Value::variant( - "Bar".to_string(), - Composite::Named(vec![ - ("hi".to_string(), Value::str("hello".to_string())), - ("other".to_string(), Value::u128(123)), - ]), - ), - ); - } - - #[test] - fn decode_composite_types() { - #[derive(Encode, scale_info::TypeInfo)] - struct Unnamed(bool, String, Vec); - - #[derive(Encode, scale_info::TypeInfo)] - struct Named { - is_valid: bool, - name: String, - bytes: Vec, - } - - encode_decode_check( - Unnamed(true, "James".into(), vec![1, 2, 3]), - Value::unnamed_composite(vec![ - Value::bool(true), - Value::str("James".to_string()), - Value::unnamed_composite(vec![Value::u8(1), Value::u8(2), Value::u8(3)]), - ]), - ); - encode_decode_check( - Named { is_valid: true, name: "James".into(), bytes: vec![1, 2, 3] }, - Value::named_composite(vec![ - ("is_valid".into(), Value::bool(true)), - ("name".into(), Value::str("James".to_string())), - ("bytes".into(), Value::unnamed_composite(vec![Value::u8(1), Value::u8(2), Value::u8(3)])), - ]), - ); - } - - #[test] - fn decode_bit_sequence() { - use bitvec::{bitvec, order::Lsb0}; - - encode_decode_check( - bitvec![u8, Lsb0; 0, 1, 1, 0, 1, 0], - Value::bit_sequence(bitvec![u8, Lsb0; 0, 1, 1, 0, 1, 0]), - ); - } -} diff --git a/desub-current/src/decoder/mod.rs b/desub-current/src/decoder/mod.rs index 94eae320..0b3fe523 100644 --- a/desub-current/src/decoder/mod.rs +++ b/desub-current/src/decoder/mod.rs @@ -23,12 +23,12 @@ //! See [`decode_storage()`] and then the documentation on [`StorageDecoder`] to decode storage lookups. mod decode_storage; -mod decode_value; mod extrinsic_bytes; use crate::metadata::Metadata; -use crate::value::Value; use crate::TypeId; +use scale_decode::DecodeAsType; +use scale_value::Value; use parity_scale_codec::{Compact, Decode}; use extrinsic_bytes::{AllExtrinsicBytes, ExtrinsicBytesError}; use serde::Serialize; @@ -36,7 +36,7 @@ use sp_runtime::{AccountId32, MultiAddress, MultiSignature}; use std::borrow::Cow; // Re-export the DecodeValueError here, which we expose in our global `DecodeError` enum. -pub use decode_value::DecodeValueError; +pub use scale_decode::Error as DecodeValueError; // Re-export storage related types that are part of our public interface. pub use decode_storage::{ @@ -45,7 +45,7 @@ pub use decode_storage::{ /// An enum of the possible errors that can be returned from attempting to decode bytes /// using the functions in this module. -#[derive(Clone, Debug, thiserror::Error)] +#[derive(Debug, thiserror::Error)] pub enum DecodeError { #[error("Failed to parse the provided vector of extrinsics: {0}")] UnexpectedExtrinsicsShape(#[from] ExtrinsicBytesError), @@ -72,7 +72,7 @@ pub fn decode_value_by_id<'a, Id: Into>( ty: Id, data: &mut &[u8], ) -> Result, DecodeValueError> { - decode_value::decode_value_by_id(data, ty, metadata.types()) + Value::decode_as_type(data, ty.into(), metadata.types()) } /// Generate a [`StorageDecoder`] struct which is capable of decoding SCALE encoded storage keys. It's advisable @@ -348,7 +348,7 @@ pub fn decode_call_data<'a>(metadata: &'a Metadata, data: &mut &[u8]) -> Result< .iter() .map(|field| { let id = field.ty.id; - decode_value_by_id(metadata, TypeId::from_u32(id), data).map_err(DecodeError::DecodeValueError) + decode_value_by_id(metadata, id, data).map_err(DecodeError::DecodeValueError) }) .collect::, _>>()?; @@ -394,7 +394,7 @@ pub fn decode_signed_extensions<'a>( .signed_extensions() .iter() .map(|ext| { - let val = decode_value_by_id(metadata, &ext.ty, data)?; + let val = decode_value_by_id(metadata, ext.ty.id, data)?; let name = Cow::Borrowed(&*ext.identifier); Ok((name, val)) }) @@ -414,7 +414,7 @@ pub fn decode_additional_signed<'a>( .signed_extensions() .iter() .map(|ext| { - let val = decode_value_by_id(metadata, &ext.additional_signed, data)?; + let val = decode_value_by_id(metadata, ext.additional_signed.id, data)?; let name = Cow::Borrowed(&*ext.identifier); Ok((name, val)) }) diff --git a/desub-current/src/lib.rs b/desub-current/src/lib.rs index 6ce9bd6a..2df435f8 100644 --- a/desub-current/src/lib.rs +++ b/desub-current/src/lib.rs @@ -17,16 +17,14 @@ //! A crate to decode extrinsics, signer payloads and storage keys for substrate nodes using V14+ metadata. //! See [`decoder`] for more information. -mod type_id; - pub mod decoder; pub mod metadata; -pub mod value; pub use metadata::Metadata; -pub use value::{Value, ValueDef}; +pub use scale_value::{Value, ValueDef}; -pub use type_id::TypeId; +/// An ID that represents a type in a [`scale_info::PortableRegistry`]. +pub type TypeId = u32; /// A re-export of the [`scale_info`] crate, since we delegate much of the type inspection to it. pub use scale_info; diff --git a/desub-current/src/metadata/mod.rs b/desub-current/src/metadata/mod.rs index 8db852ac..c923b56a 100644 --- a/desub-current/src/metadata/mod.rs +++ b/desub-current/src/metadata/mod.rs @@ -106,7 +106,7 @@ impl Metadata { /// Given a [`crate::TypeId`], return the corresponding type from the type registry, if possible. pub fn resolve>(&self, id: Id) -> Option<&Type> { - self.types.resolve(id.into().id()) + self.types.resolve(id.into()) } /// Return a reference to the [`scale_info`] type registry. diff --git a/desub-current/src/type_id.rs b/desub-current/src/type_id.rs deleted file mode 100644 index 55df9218..00000000 --- a/desub-current/src/type_id.rs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of substrate-desub. -// -// substrate-desub is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// substrate-desub is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with substrate-desub. If not, see . - -use crate::ScaleInfoTypeId; - -/// This represents the ID of a type found in the metadata. A scale info type representation can -/// be converted into this, and we get this back directly when decoding types into Values. -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize)] -pub struct TypeId(u32); - -impl TypeId { - /// Create a new `TypeId` from a `u32`. - pub(crate) fn from_u32(id: u32) -> TypeId { - TypeId(id) - } - /// Return the u32 ID expected by a PortableRegistry. - pub(crate) fn id(self) -> u32 { - self.0 - } -} - -impl From for TypeId { - fn from(id: ScaleInfoTypeId) -> Self { - TypeId(id.id) - } -} - -impl From<&ScaleInfoTypeId> for TypeId { - fn from(id: &ScaleInfoTypeId) -> Self { - TypeId(id.id) - } -} - -impl From<&TypeId> for TypeId { - fn from(id: &TypeId) -> Self { - *id - } -} diff --git a/desub-current/src/value/deserialize.rs b/desub-current/src/value/deserialize.rs deleted file mode 100644 index 9b9743fd..00000000 --- a/desub-current/src/value/deserialize.rs +++ /dev/null @@ -1,669 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of substrate-desub. -// -// substrate-desub is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// substrate-desub is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with substrate-desub. If not, see . - -use super::{Composite, Primitive, Value, ValueDef, Variant}; -use serde::{ - self, - de::{Error, Visitor}, - Deserialize, Deserializer, -}; -use std::convert::TryInto; - -/* -This module implements the [`Deserialize`] (no R!) trait on our [`Value`] enum. -====================================================================== - -See deserializer.rs for more of a description. - -The Deserialize trait is responsible for describing how some other value (or at least, -the repreentastion of it in terms of the serde data model) can be turned into our `Value` -enum. - -One thing we aim for is to be able to losslessly deserialize a [`Value`] into a -[`Value`]. This would allow for partial type deserialization, for instance we might want to turn -only part of our input into a struct, say, and leave the rest as [`Value`] types until we know what -to do with them. -*/ - -impl<'de> Deserialize<'de> for Value<()> { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let value = deserializer.deserialize_any(ValueDefVisitor)?; - Ok(Value { value, context: () }) - } -} - -impl<'de> Deserialize<'de> for ValueDef<()> { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(ValueDefVisitor) - } -} - -impl<'de> Deserialize<'de> for Primitive { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(PrimitiveVisitor) - } -} - -impl<'de> Deserialize<'de> for Composite<()> { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(CompositeVisitor) - } -} - -impl<'de> Deserialize<'de> for Variant<()> { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_any(VariantVisitor) - } -} - -struct PrimitiveVisitor; - -macro_rules! visit_prim { - ($name:ident $ty:ident $variant:ident) => { - fn $name(self, v: $ty) -> Result - where - E: serde::de::Error, - { - Ok(Primitive::$variant(v)) - } - } -} - -impl<'de> Visitor<'de> for PrimitiveVisitor { - type Value = Primitive; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a type that can be decoded into a Primitive value") - } - - visit_prim!(visit_bool bool Bool); - visit_prim!(visit_i8 i8 I8); - visit_prim!(visit_i16 i16 I16); - visit_prim!(visit_i32 i32 I32); - visit_prim!(visit_i64 i64 I64); - visit_prim!(visit_i128 i128 I128); - visit_prim!(visit_u8 u8 U8); - visit_prim!(visit_u16 u16 U16); - visit_prim!(visit_u32 u32 U32); - visit_prim!(visit_u64 u64 U64); - visit_prim!(visit_u128 u128 U128); - visit_prim!(visit_char char Char); - - fn visit_str(self, v: &str) -> Result - where - E: serde::de::Error, - { - Ok(Primitive::Str(v.into())) - } - - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, - { - Ok(Primitive::Str(v)) - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: serde::de::Error, - { - let val = v.try_into().map_err(|_| serde::de::Error::invalid_type(serde::de::Unexpected::Bytes(v), &self))?; - Ok(Primitive::U256(val)) - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - let mut vals = Vec::new(); - while let Some(el) = seq.next_element()? { - vals.push(el) - } - let len = vals.len(); - let arr = vals.try_into().map_err(|_| serde::de::Error::invalid_length(len, &"exactly 32 bytes"))?; - Ok(Primitive::U256(arr)) - } - - fn visit_some(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - Primitive::deserialize(deserializer) - } -} - -struct CompositeVisitor; - -impl<'de> Visitor<'de> for CompositeVisitor { - type Value = Composite<()>; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a type that can be decoded into a Composite value") - } - - fn visit_bytes(self, v: &[u8]) -> Result - where - E: serde::de::Error, - { - let byte_values = v.iter().map(|&b| Value::u8(b)).collect(); - Ok(Composite::Unnamed(byte_values)) - } - - fn visit_none(self) -> Result - where - E: serde::de::Error, - { - Ok(Composite::Unnamed(Vec::new())) - } - - fn visit_some(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Composite::deserialize(deserializer) - } - - fn visit_unit(self) -> Result - where - E: serde::de::Error, - { - Ok(Composite::Unnamed(Vec::new())) - } - - fn visit_newtype_struct(self, deserializer: D) -> Result - where - D: Deserializer<'de>, - { - Composite::deserialize(deserializer) - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - let mut values = Vec::with_capacity(seq.size_hint().unwrap_or(0)); - while let Some(value) = seq.next_element()? { - values.push(value); - } - Ok(Composite::Unnamed(values)) - } - - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - let mut values = Vec::with_capacity(map.size_hint().unwrap_or(0)); - while let Some(key_val) = map.next_entry()? { - values.push(key_val); - } - Ok(Composite::Named(values)) - } -} - -struct VariantVisitor; - -impl<'de> Visitor<'de> for VariantVisitor { - type Value = Variant<()>; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a type that can be decoded into an enum Variant") - } - - fn visit_enum(self, data: A) -> Result - where - A: serde::de::EnumAccess<'de>, - { - data.variant().and_then(|(name, variant_access)| { - use serde::de::VariantAccess; - // We have to ask for a particular enum type, but we don't know what type - // of enum to expect (we support anything!). So, we just call the visitor method - // that doesn't require any extra fields, and we know that this will just give back - // whatever it can based on our impl (who knows about other impls though). - let values = variant_access.newtype_variant()?; - Ok(Variant { name, values }) - }) - } - - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - // We support deserializing from a map that looks like - // { name: "VariantName", values: [1,2,3] } into Variant + Composite::Unnamed, or - // { name: "VariantName", values: { "a": 1, "b": 2 }} into Variant + Composite::Named - // to line up with our Serialize impl for the Value types. - let mut name = None; - let mut values = None; - - while let Some(k) = map.next_key::()? { - match &*k { - "name" => { - name = Some(map.next_value()?); - } - "values" => { - values = Some(map.next_value()?); - } - other => return Err(A::Error::unknown_field(other, &["name", "values"])), - } - } - - if let (Some(name), Some(values)) = (name, values) { - Ok(Variant { name, values }) - } else { - Err(A::Error::custom("map must contain 'name' and 'values' to deserialize to a Variant")) - } - } -} - -struct ValueDefVisitor; - -// It gets repetitive writing out the visitor impls to delegate to the Value subtypes; -// this helper makes that a little easier: -macro_rules! delegate_visitor_fn { - ( - $visitor:ident $mapping:path, - $( $name:ident($($ty:ty)?) )+ - ) => { - $( - fn $name(self, $(v: $ty)?) -> Result - where E: serde::de::Error { - $visitor.$name($(v as $ty)?).map($mapping) - } - )+ - } -} - -impl<'de> Visitor<'de> for ValueDefVisitor { - type Value = ValueDef<()>; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("a type that can be decoded into a Value") - } - - delegate_visitor_fn!( - PrimitiveVisitor ValueDef::Primitive, - visit_bool(bool) - visit_i8(i8) - visit_i16(i16) - visit_i32(i32) - visit_i64(i64) - visit_i128(i128) - visit_u8(u8) - visit_u16(u16) - visit_u32(u32) - visit_u64(u64) - visit_u128(u128) - visit_char(char) - visit_str(&str) - visit_string(String) - ); - - delegate_visitor_fn!( - CompositeVisitor ValueDef::Composite, - visit_none() - visit_unit() - visit_bytes(&[u8]) - ); - - fn visit_some(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - ValueDef::deserialize(deserializer) - } - - fn visit_newtype_struct(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - ValueDef::deserialize(deserializer) - } - - fn visit_seq(self, seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - CompositeVisitor.visit_seq(seq).map(ValueDef::Composite) - } - - fn visit_map(self, map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - CompositeVisitor.visit_map(map).map(ValueDef::Composite) - } - - fn visit_enum(self, data: A) -> Result - where - A: serde::de::EnumAccess<'de>, - { - VariantVisitor.visit_enum(data).map(ValueDef::Variant) - } -} - -#[cfg(test)] -mod test { - - use super::*; - use crate::value::DeserializeError; - - /// Does a value deserialize to itself? - fn assert_value_isomorphic<'de, V: Deserializer<'de> + Deserialize<'de> + PartialEq + std::fmt::Debug + Clone>( - val: V, - ) { - assert_value_to_value(val.clone(), val) - } - - /// Does a value `a` deserialize to the expected value `b`? - fn assert_value_to_value<'de, V1, V2>(a: V1, b: V2) - where - V1: Deserializer<'de>, - V2: Deserialize<'de> + PartialEq + std::fmt::Debug + Clone, - { - let new_val = V2::deserialize(a).expect("Can deserialize"); - assert_eq!(b, new_val); - } - - #[test] - fn deserialize_primitives_isomorphic() { - assert_value_isomorphic(Value::u8(123)); - assert_value_isomorphic(Value::u16(123)); - assert_value_isomorphic(Value::u32(123)); - assert_value_isomorphic(Value::u64(123)); - assert_value_isomorphic(Value::u128(123)); - assert_value_isomorphic(Value::i8(123)); - assert_value_isomorphic(Value::i16(123)); - assert_value_isomorphic(Value::i32(123)); - assert_value_isomorphic(Value::i64(123)); - assert_value_isomorphic(Value::i128(123)); - assert_value_isomorphic(Value::bool(true)); - assert_value_isomorphic(Value::char('a')); - assert_value_isomorphic(Value::str("Hello!".into())); - - // Alas, I256 and U256 are both a sequence of bytes, which could equally be represented - // by a composite sequence (as other sequences-of-things are). We could have a special case where - // precisely 32 u8's is deserialized to one of U256 or I256, but for now we use our more general - // composite type as the sequence catch-all: - assert_value_to_value( - ValueDef::<()>::Primitive(Primitive::I256([1; 32])), - Value::unnamed_composite(vec![1; 32].into_iter().map(|b| Value::u8(b)).collect()), - ); - assert_value_to_value( - ValueDef::<()>::Primitive(Primitive::U256([1; 32])), - Value::unnamed_composite(vec![1; 32].into_iter().map(|b| Value::u8(b)).collect()), - ); - - // .. that said; if you want a primitive value back, you can use that type directly to get it - // (as long as we are given exactly 32 bytes): - - assert_value_to_value(ValueDef::<()>::Primitive(Primitive::I256([1; 32])), Primitive::U256([1; 32])); - assert_value_to_value(ValueDef::<()>::Primitive(Primitive::U256([1; 32])), Primitive::U256([1; 32])); - - // Unwrapped versions also work: - - assert_value_isomorphic(Primitive::U8(123)); - assert_value_isomorphic(Primitive::U16(123)); - assert_value_isomorphic(Primitive::U32(123)); - assert_value_isomorphic(Primitive::U64(123)); - assert_value_isomorphic(Primitive::U128(123)); - assert_value_isomorphic(Primitive::U256([1; 32])); - assert_value_isomorphic(Primitive::I8(123)); - assert_value_isomorphic(Primitive::I16(123)); - assert_value_isomorphic(Primitive::I32(123)); - assert_value_isomorphic(Primitive::I64(123)); - assert_value_isomorphic(Primitive::I128(123)); - assert_value_isomorphic(Primitive::Bool(true)); - assert_value_isomorphic(Primitive::Char('a')); - assert_value_isomorphic(Primitive::Str("Hello!".into())); - assert_value_to_value(Primitive::I256([1; 32]), Primitive::U256([1; 32])); - - // We can also go from wrapped to unwrapped: - - assert_value_to_value(Value::u8(123), Primitive::U8(123)); - assert_value_to_value(Value::u16(123), Primitive::U16(123)); - assert_value_to_value(Value::u32(123), Primitive::U32(123)); - assert_value_to_value(Value::u64(123), Primitive::U64(123)); - - // Or vice versa: - - assert_value_to_value(Primitive::U8(123), Value::u8(123)); - assert_value_to_value(Primitive::U16(123), Value::u16(123)); - assert_value_to_value(Primitive::U32(123), Value::u32(123)); - assert_value_to_value(Primitive::U64(123), Value::u64(123)); - } - - #[test] - fn deserialize_composites_isomorphic() { - assert_value_isomorphic(Value::unnamed_composite(vec![Value::u64(123), Value::bool(true)])); - assert_value_isomorphic(Value::named_composite(vec![])); - assert_value_isomorphic(Value::named_composite(vec![ - ("a".into(), Value::u64(123)), - ("b".into(), Value::bool(true)), - ])); - assert_value_isomorphic(Value::named_composite(vec![ - ("a".into(), Value::u64(123)), - ( - "b".into(), - Value::named_composite(vec![("c".into(), Value::u128(123)), ("d".into(), Value::str("hello".into()))]), - ), - ])); - - // unwrapped: - - assert_value_isomorphic(Composite::Unnamed(vec![Value::u64(123), Value::bool(true)])); - assert_value_isomorphic(Composite::Unnamed(vec![])); - assert_value_isomorphic(Composite::Named(vec![("a".into(), Value::u64(123)), ("b".into(), Value::bool(true))])); - assert_value_isomorphic(Composite::Named(vec![ - ("a".into(), Value::u64(123)), - ( - "b".into(), - Value::named_composite(vec![("c".into(), Value::u128(123)), ("d".into(), Value::str("hello".into()))]), - ), - ])); - } - - #[test] - fn deserialize_variants_isomorphic() { - assert_value_isomorphic(ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::u64(123), Value::bool(true)]), - })); - assert_value_isomorphic(ValueDef::Variant(Variant { name: "Foo".into(), values: Composite::Unnamed(vec![]) })); - assert_value_isomorphic(ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Named(vec![("a".into(), Value::u64(123)), ("b".into(), Value::bool(true))]), - })); - - // unwrapped work as well: - - assert_value_isomorphic(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::u64(123), Value::bool(true)]), - }); - assert_value_isomorphic(Variant { name: "Foo".into(), values: Composite::Unnamed(vec![]) }); - assert_value_isomorphic(Variant { - name: "Foo".into(), - values: Composite::Named(vec![("a".into(), Value::u64(123)), ("b".into(), Value::bool(true))]), - }); - } - - #[test] - fn sequence_to_value() { - use serde::de::{value::SeqDeserializer, IntoDeserializer}; - - let de: SeqDeserializer<_, DeserializeError> = vec![1u8, 2, 3, 4].into_deserializer(); - - assert_value_to_value( - de.clone(), - Value::unnamed_composite(vec![Value::u8(1), Value::u8(2), Value::u8(3), Value::u8(4)]), - ); - assert_value_to_value(de, Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3), Value::u8(4)])); - } - - #[test] - fn sequence_to_primitive() { - use serde::de::{value::SeqDeserializer, IntoDeserializer}; - - let de: SeqDeserializer<_, DeserializeError> = vec![1u8; 32].into_deserializer(); - - assert_value_to_value(de, Primitive::U256([1; 32])); - } - - #[test] - fn map_to_value() { - use serde::de::{value::MapDeserializer, IntoDeserializer}; - use std::collections::HashMap; - - let map = { - let mut map = HashMap::<&'static str, i32>::new(); - map.insert("a", 1i32); - map.insert("b", 2i32); - map.insert("c", 3i32); - map - }; - - let de: MapDeserializer<_, DeserializeError> = map.into_deserializer(); - - let value = ValueDef::deserialize(de).expect("should deserialize OK"); - if let ValueDef::Composite(Composite::Named(vals)) = value { - // These could come back in any order so we need to search for them: - assert!(vals.contains(&("a".into(), Value::i32(1)))); - assert!(vals.contains(&("b".into(), Value::i32(2)))); - assert!(vals.contains(&("c".into(), Value::i32(3)))); - } else { - panic!("Map should deserialize into Composite::Named value but we have {:?}", value); - } - } - - #[test] - fn partially_deserialize_value() { - let value = Value::named_composite(vec![ - ("a".into(), Value::u64(123)), - ( - "b".into(), - Value::named_composite(vec![ - ("c".into(), Value::u128(123)), - ("d".into(), Value::str("hello".into())), - ("e".into(), Value::named_composite(vec![])), - ]), - ), - ]); - - #[derive(Deserialize, Debug, PartialEq)] - struct Partial { - a: Value<()>, - b: PartialB, - } - - #[derive(Deserialize, Debug, PartialEq)] - struct PartialB { - c: u128, - d: String, - e: Value<()>, - } - - let partial: Partial = crate::value::from_value(value).expect("should work"); - - assert_eq!( - partial, - Partial { - a: Value::u64(123), - b: PartialB { c: 123, d: "hello".into(), e: Value::named_composite(vec![]) } - } - ) - } - - #[test] - fn deserialize_well_formed_map_to_unnamed_variant() { - let v: Variant<()> = Variant::deserialize(serde_json::json!({ - "name": "Hello", - "values": [1, 2, true] - })) - .unwrap(); - - assert_eq!(v.name, "Hello".to_string()); - assert_eq!( - v.values, - Composite::Unnamed(vec![ - // All JSON numbers deserialize to U64 or I64 or F64 as necessary: - Value::u64(1), - Value::u64(2), - Value::bool(true), - ]) - ) - } - - #[test] - fn deserialize_well_formed_map_to_named_variant() { - let v: Variant<()> = Variant::deserialize(serde_json::json!({ - "name": "Hello", - "values": { "a": 1, "b": 2, "c": true } - })) - .unwrap(); - - assert_eq!(v.name, "Hello".to_string()); - assert_eq!( - v.values, - Composite::Named(vec![ - // All JSON numbers deserialize to U64 or I64 or F64 as necessary: - ("a".into(), Value::u64(1)), - ("b".into(), Value::u64(2)), - ("c".into(), Value::bool(true)), - ]) - ) - } - - #[test] - fn cannot_deserialize_malformed_map_to_variant() { - assert!(matches!( - Variant::deserialize(serde_json::json!({ - "names": "Hello", // "names", not "name". - "values": [1, 2, true] - })), - Err(..) - )); - assert!(matches!( - Variant::deserialize(serde_json::json!({ - "name": "Hello", - "values": [1, 2, true], - "other": true // unexpected third prop. - })), - Err(..) - )); - assert!(matches!( - Variant::deserialize(serde_json::json!({ - "names": "Hello", - "values": 1 // incorrect type of values - })), - Err(..) - )); - } -} diff --git a/desub-current/src/value/deserializer.rs b/desub-current/src/value/deserializer.rs deleted file mode 100644 index b50a4305..00000000 --- a/desub-current/src/value/deserializer.rs +++ /dev/null @@ -1,1361 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of substrate-desub. -// -// substrate-desub is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// substrate-desub is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with substrate-desub. If not, see . - -use super::{BitSequence, Composite, Primitive, Value, ValueDef, Variant}; -use serde::{ - de::{self, EnumAccess, IntoDeserializer, SeqAccess, VariantAccess}, - forward_to_deserialize_any, ser, Deserialize, Deserializer, Serialize, Serializer, -}; -use std::borrow::Cow; -use std::fmt::Display; - -/* -This module implements the Deserializer trait on our Value enum -=============================================================== - -Deserializing using Serde is a bit weird to wrap your head around at first (at least, it was for me). -I'd def recommend checking out the serde book, and inparticular https://serde.rs/impl-deserializer.html, -but here's a very quick explainer on how things work: - -We have a `Deserialize` trait (commonly automatically implemented via `#[derive(Deserialize)]`). This trait -(and the `Visitor` trait which I'll talk about in a moment) is concerned with getting the right values needed to -create an instance of the data type (struct, enum, whatever it is) in question. - -We also have a `Deserializer` trait (note the R at the end). this guy is responsible for plucking values out of some -format (could be JSON or TOML or, as we have here, another rust data type!) and handing them to a Deserialize impl. -That way, the Deserialize impl doesn't have to care about any particular format; only what it wants to be given back). - -So, how it works is that the `Deserialize` impl asks this guy for data of a certain type by calling methods like -`deserializer.deserialize_bool` or `deserializer.deserialize_i32` or whatever. (the actual methods available define -the "serde data model"; that is; the known types that can be passed between a Deserialize and Deserializer). - -But! Calling methods like `deserialize_bool` or `deserialize_i32` is really just the Deserialize impls way of -hinting to the Deserializer what it wants to be given back. In reality, the Deserializer might want to give -back something different (maybe it is being asked for a u8 but it knows it only has a u16 to give back, say). - -How? Well, the Deserialize impl calls something like `deserializer.deserialize_i32(visitor)`; it says "I want an i32, but -here's this visitor thing where you can give me back whatever you have, and I'll try and handle it if I can". So maybe -when the Deserialize impl calls `deserializer.deserialize_i32(visitor)`, the Deserializer impl for `deserialize_i32` -actually calls `visitor.visit_i64`. Who knows! - -It's basically a negotiation. The Deserialize impl asks for a value of a certain type, and it provides a visitor that will -try to accept as many types as it can. The Deserializer impl then does it's best to give back what it's asked for. If -the visitor can't handle the type given back, we are given back an error trying to deserialize; we can't convert a map -into an i32 for instance, or whatever. - -Here, we want to allow people to deserialize a `Value` type into some arbitrary struct or enum. So we implement the -Deserializer trait, and do our best to hand the visitor we're given back the data it's asking for. Since we know exactly -what data we actually have, we can often just give it back whatever we have and hgope the visitor will accept it! We have -various "special cases" though (like newtype wrapper structs) where we try to be more accomodating. -*/ - -/// An opaque error to describe in human terms what went wrong. -/// Many internal serialization/deserialization errors are relayed -/// to this in string form, and so we use basic strings for custom -/// errors as well for simplicity. -#[derive(thiserror::Error, Debug, Clone, PartialEq)] -#[error("{0}")] -pub struct Error(Cow<'static, str>); - -impl Error { - fn from_string>(s: S) -> Error { - Error(Cow::Owned(s.into())) - } - fn from_str(s: &'static str) -> Error { - Error(Cow::Borrowed(s)) - } -} - -impl de::Error for Error { - fn custom(msg: T) -> Self { - Error::from_string(msg.to_string()) - } -} -impl ser::Error for Error { - fn custom(msg: T) -> Self { - Error::from_string(msg.to_string()) - } -} - -/// Spit out the simple deserialize methods to avoid loads of repetition. -macro_rules! deserialize_x { - ($fn_name:ident) => { - fn $fn_name(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.value.$fn_name(visitor) - } - } -} - -// Our Value type has some context, which we ignore, and some definition, whose deserializer -// impl we forward to. -impl<'de, T> Deserializer<'de> for Value { - type Error = Error; - - deserialize_x!(deserialize_any); - deserialize_x!(deserialize_bool); - deserialize_x!(deserialize_i8); - deserialize_x!(deserialize_i16); - deserialize_x!(deserialize_i32); - deserialize_x!(deserialize_i64); - deserialize_x!(deserialize_i128); - deserialize_x!(deserialize_u8); - deserialize_x!(deserialize_u16); - deserialize_x!(deserialize_u32); - deserialize_x!(deserialize_u64); - deserialize_x!(deserialize_u128); - deserialize_x!(deserialize_f32); - deserialize_x!(deserialize_f64); - deserialize_x!(deserialize_char); - deserialize_x!(deserialize_str); - deserialize_x!(deserialize_string); - deserialize_x!(deserialize_bytes); - deserialize_x!(deserialize_byte_buf); - deserialize_x!(deserialize_option); - deserialize_x!(deserialize_unit); - deserialize_x!(deserialize_seq); - deserialize_x!(deserialize_map); - deserialize_x!(deserialize_identifier); - deserialize_x!(deserialize_ignored_any); - - fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.value.deserialize_unit_struct(name, visitor) - } - - fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.value.deserialize_newtype_struct(name, visitor) - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.value.deserialize_tuple(len, visitor) - } - - fn deserialize_tuple_struct(self, name: &'static str, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.value.deserialize_tuple_struct(name, len, visitor) - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - self.value.deserialize_struct(name, fields, visitor) - } - - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - self.value.deserialize_enum(name, variants, visitor) - } -} - -// Our ValueDef deserializer needs to handle BitSeq itself, but otherwise delegates to -// the inner implementations of things to handle. This macro makes that less repetitive -// to write by only requiring a bitseq impl. -macro_rules! delegate_except_bitseq { - ( - $name:ident ( $self:ident, $($arg:ident),* ), - $seq:pat => $expr:expr - ) => { - match $self { - ValueDef::BitSequence($seq) => { - $expr - }, - ValueDef::Composite(composite) => { - composite.$name( $($arg),* ) - }, - ValueDef::Variant(variant) => { - variant.$name( $($arg),* ) - }, - ValueDef::Primitive(prim) => { - prim.$name( $($arg),* ) - }, - } - } -} - -// The goal here is simply to forward deserialization methods of interest to -// the relevant subtype. The exception is our BitSequence type, which doesn't -// have a sub type to forward to and so is handled here. -impl<'de, T> Deserializer<'de> for ValueDef { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_any(self, visitor), - seq => { - BitVecPieces::new(seq)?.deserialize_any(visitor) - } - } - } - - fn deserialize_newtype_struct(self, name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_newtype_struct(self, name, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into a newtype struct")) - } - } - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_tuple(self, len, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into a tuple")) - } - } - } - - fn deserialize_tuple_struct(self, name: &'static str, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_tuple_struct(self, name, len, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into a tuple struct")) - } - } - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_unit(self, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into a ()")) - } - } - } - - fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_unit_struct(self, name, visitor), - _ => { - Err(Error::from_string(format!("Cannot deserialize BitSequence into the unit struct {}", name))) - } - } - } - - fn deserialize_enum( - self, - name: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_enum(self, name, variants, visitor), - _ => { - Err(Error::from_string(format!("Cannot deserialize BitSequence into the enum {}", name))) - } - } - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_bytes(self, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into raw bytes")) - } - } - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_byte_buf(self, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into raw bytes")) - } - } - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_seq(self, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into a sequence")) - } - } - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_map(self, visitor), - _ => { - Err(Error::from_str("Cannot deserialize BitSequence into a map")) - } - } - } - - // None of the sub types particularly care about these, so we just allow them to forward to - // deserialize_any and go from there. - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - option struct identifier ignored_any - } -} - -impl<'de, T> IntoDeserializer<'de, Error> for Value { - type Deserializer = Value; - fn into_deserializer(self) -> Self::Deserializer { - self - } -} - -impl<'de, T> Deserializer<'de> for Composite { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - match self { - Composite::Named(values) => visitor.visit_map(de::value::MapDeserializer::new(values.into_iter())), - Composite::Unnamed(values) => visitor.visit_seq(de::value::SeqDeserializer::new(values.into_iter())), - } - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - match self { - Composite::Named(values) => { - visitor.visit_seq(de::value::SeqDeserializer::new(values.into_iter().map(|(_, v)| v))) - } - Composite::Unnamed(values) => visitor.visit_seq(de::value::SeqDeserializer::new(values.into_iter())), - } - } - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - match self { - // A sequence of named values? just ignores the names: - Composite::Named(values) => { - if values.len() != len { - return Err(Error::from_string(format!( - "Cannot deserialize composite of length {} into tuple of length {}", - values.len(), - len - ))); - } - visitor.visit_seq(de::value::SeqDeserializer::new(values.into_iter().map(|(_, v)| v))) - } - // A sequence of unnamed values is ideal: - Composite::Unnamed(values) => { - if values.len() != len { - return Err(Error::from_string(format!( - "Cannot deserialize composite of length {} into tuple of length {}", - values.len(), - len - ))); - } - visitor.visit_seq(de::value::SeqDeserializer::new(values.into_iter())) - } - } - } - - fn deserialize_tuple_struct(self, _name: &'static str, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.deserialize_tuple(len, visitor) - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - // 0 length composite types can be treated as the unit type: - if self.is_empty() { - visitor.visit_unit() - } else { - Err(Error::from_str("Cannot deserialize non-empty Composite into a unit value")) - } - } - - fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.deserialize_unit(visitor) - } - - fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_seq(de::value::SeqDeserializer::new(Some(self).into_iter())) - } - - fn deserialize_byte_buf(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - match self { - Composite::Named(values) => { - let bytes = values - .into_iter() - .map(|(_n, v)| { - if let ValueDef::Primitive(Primitive::U8(byte)) = v.value { - Ok(byte) - } else { - Err(Error::from_str("Cannot deserialize composite that is not entirely U8's into bytes")) - } - }) - .collect::>()?; - visitor.visit_byte_buf(bytes) - } - Composite::Unnamed(values) => { - let bytes = values - .into_iter() - .map(|v| { - if let ValueDef::Primitive(Primitive::U8(byte)) = v.value { - Ok(byte) - } else { - Err(Error::from_str("Cannot deserialize composite that is not entirely U8's into bytes")) - } - }) - .collect::>()?; - visitor.visit_byte_buf(bytes) - } - } - } - - fn deserialize_bytes(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.deserialize_byte_buf(visitor) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - option struct map - enum identifier ignored_any - } -} - -impl<'de, T> IntoDeserializer<'de, Error> for Composite { - type Deserializer = Composite; - fn into_deserializer(self) -> Self::Deserializer { - self - } -} - -// Because composite types are used to represent variant fields, we allow -// variant accesses to be called on it, which just delegate to methods defined above. -impl<'de, T> VariantAccess<'de> for Composite { - type Error = Error; - - fn unit_variant(self) -> Result<(), Self::Error> { - Deserialize::deserialize(self) - } - - fn newtype_variant_seed(self, seed: S) -> Result - where - S: de::DeserializeSeed<'de>, - { - seed.deserialize(self) - } - - fn tuple_variant(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.deserialize_tuple(len, visitor) - } - - fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.deserialize_any(visitor) - } -} - -impl<'de, T> Deserializer<'de> for Variant { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - visitor.visit_enum(self) - } - - fn deserialize_enum( - self, - _name: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_enum(self) - } - - fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_seq(de::value::SeqDeserializer::new(Some(self).into_iter())) - } - - // All of the below functions delegate to the Composite deserializing methods using the enum values. - - fn deserialize_tuple(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_tuple(len, visitor) - } - - fn deserialize_tuple_struct(self, name: &'static str, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_tuple_struct(name, len, visitor) - } - - fn deserialize_unit_struct(self, name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_unit_struct(name, visitor) - } - - fn deserialize_unit(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_unit(visitor) - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_struct(name, fields, visitor) - } - - fn deserialize_map(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_map(visitor) - } - - fn deserialize_seq(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.values.deserialize_seq(visitor) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option identifier ignored_any - } -} - -impl<'de, T> IntoDeserializer<'de, Error> for Variant { - type Deserializer = Variant; - fn into_deserializer(self) -> Self::Deserializer { - self - } -} - -// Variant types can be treated as serde enums. Here we just hand back -// the pair of name and values, where values is a composite type that impls -// VariantAccess to actually allow deserializing of those values. -impl<'de, T> EnumAccess<'de> for Variant { - type Error = Error; - - type Variant = Composite; - - fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> - where - V: de::DeserializeSeed<'de>, - { - let name = self.name.into_deserializer(); - let values = self.values; - seed.deserialize(name).map(|name| (name, values)) - } -} - -impl<'de> Deserializer<'de> for Primitive { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - match self { - Primitive::Bool(v) => visitor.visit_bool(v), - Primitive::Char(v) => visitor.visit_char(v), - Primitive::Str(v) => visitor.visit_string(v), - Primitive::U8(v) => visitor.visit_u8(v), - Primitive::U16(v) => visitor.visit_u16(v), - Primitive::U32(v) => visitor.visit_u32(v), - Primitive::U64(v) => visitor.visit_u64(v), - Primitive::U128(v) => visitor.visit_u128(v), - Primitive::U256(v) => visitor.visit_bytes(&v), - Primitive::I8(v) => visitor.visit_i8(v), - Primitive::I16(v) => visitor.visit_i16(v), - Primitive::I32(v) => visitor.visit_i32(v), - Primitive::I64(v) => visitor.visit_i64(v), - Primitive::I128(v) => visitor.visit_i128(v), - Primitive::I256(v) => visitor.visit_bytes(&v), - } - } - - fn deserialize_newtype_struct(self, _name: &'static str, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_seq(de::value::SeqDeserializer::new(Some(self).into_iter())) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } -} - -impl<'de> IntoDeserializer<'de, Error> for Primitive { - type Deserializer = Primitive; - fn into_deserializer(self) -> Self::Deserializer { - self - } -} - -/// This is a somewhat insane approach to extracting the data that we need from a -/// BitVec and allowing it to be deserialized from as part of the [`Value`] enum. -/// First, we serialize the BitVec, which grabs the relevant data out of it (that isn't -/// otherwise publically accessible), and then we implement a Deserializer that aligns -/// with what the Deserialize impl for BitVec expects. -/// -/// See for the Serialize/Deserialize -/// impls we are aligning with. -struct BitVecPieces { - head: u8, - bits: u64, - data: Vec, - // Track which field we're currently deserializing: - current_field: Option, -} - -#[derive(PartialEq, Copy, Clone)] -enum Field { - Head, - Bits, - Data, -} - -impl<'de> Deserializer<'de> for BitVecPieces { - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - // We hand back each field in order as part of a sequence, just because - // it's the least verbose approach: - visitor.visit_seq(self) - } - - forward_to_deserialize_any! { - bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string - bytes byte_buf option unit unit_struct newtype_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } -} - -impl<'de> SeqAccess<'de> for BitVecPieces { - type Error = Error; - - fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: de::DeserializeSeed<'de>, - { - match self.current_field { - Some(Field::Head) => { - let res = seed.deserialize(self.head.into_deserializer()).map(Some); - self.current_field = Some(Field::Bits); - res - } - Some(Field::Bits) => { - let res = seed.deserialize(self.bits.into_deserializer()).map(Some); - self.current_field = Some(Field::Data); - res - } - Some(Field::Data) => { - let bytes = std::mem::take(&mut self.data); - let res = seed.deserialize(bytes.into_deserializer()).map(Some); - self.current_field = None; - res - } - None => Ok(None), - } - } -} - -impl BitVecPieces { - fn new(bit_vec: BitSequence) -> Result { - // Step 1. "Serialize" the bitvec into this struct. Essentially, - // we are just writing out the values we need for deserializing, - // but with a silly amount of boilerplate/indirection.. - struct BitVecSerializer { - head: Option, - bits: Option, - data: Vec, - current_field: Option, - } - - // Make note of what field we're trying to serialize and - // delegate back to the main impl to actually do the work. - impl ser::SerializeStruct for &mut BitVecSerializer { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - match key { - "head" => { - self.current_field = Some(Field::Head); - } - "bits" => { - self.current_field = Some(Field::Bits); - } - "data" => { - self.current_field = Some(Field::Data); - } - _ => { - return Err(Error::from_string(format!( - "BitVec serialization encountered unexpected field '{}'", - key - ))) - } - } - value.serialize(&mut **self) - } - fn end(self) -> Result { - self.current_field = None; - Ok(()) - } - } - - // This is only expected to be called for serializing the data. We delegate - // straight back to our main impl which should know what to do already, since - // we know what struct field we're trying to serialize. - impl ser::SerializeSeq for &mut BitVecSerializer { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> { - value.serialize(&mut **self) - } - fn end(self) -> Result { - Ok(()) - } - } - - // A slightly insane serializer impl whose only purpose is to be called by - // the BitVec serialize impl, which itself only calls `serialize_struct` and - // passes relevant data to that (so we only implement that method..) - impl Serializer for &mut BitVecSerializer { - type Ok = (); - type Error = Error; - - type SerializeStruct = Self; - type SerializeSeq = Self; - - type SerializeTuple = serde::ser::Impossible<(), Error>; - type SerializeTupleStruct = serde::ser::Impossible<(), Error>; - type SerializeTupleVariant = serde::ser::Impossible<(), Error>; - type SerializeMap = serde::ser::Impossible<(), Error>; - type SerializeStructVariant = serde::ser::Impossible<(), Error>; - - fn serialize_struct(self, _: &'static str, _: usize) -> Result { - Ok(self) - } - fn serialize_seq(self, _: Option) -> Result { - match self.current_field { - Some(Field::Data) => Ok(self), - _ => Err(Error::from_str( - "BitVec serialization only expects serialize_seq to be called for 'data' prop", - )), - } - } - fn serialize_u8(self, v: u8) -> Result { - match self.current_field { - Some(Field::Head) => { - self.head = Some(v); - Ok(()) - } - Some(Field::Data) => { - self.data.push(v); - Ok(()) - } - _ => Err(Error::from_str( - "BitVec serialization only expects serialize_u8 to be called for 'head' prop", - )), - } - } - fn serialize_u64(self, v: u64) -> Result { - match self.current_field { - Some(Field::Bits) => { - self.bits = Some(v); - Ok(()) - } - _ => Err(Error::from_str( - "BitVec serialization only expects serialize_u64 to be called for 'len' prop", - )), - } - } - - // All of the below are never expected to be called when serializing a BitVec, - // so we just return an error since we'd have no idea what to do! - fn serialize_bool(self, _v: bool) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_i8(self, _v: i8) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_i16(self, _v: i16) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_i32(self, _v: i32) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_i64(self, _v: i64) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_u16(self, _v: u16) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_u32(self, _v: u32) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_f32(self, _v: f32) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_f64(self, _v: f64) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_char(self, _v: char) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_str(self, _v: &str) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_bytes(self, _v: &[u8]) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_none(self) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_some(self, _: &T) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_unit(self) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_unit_struct(self, _: &'static str) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_newtype_struct( - self, - _: &'static str, - _: &T, - ) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_newtype_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: &T, - ) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_tuple(self, _: usize) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_tuple_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_tuple_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_map(self, _: Option) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - fn serialize_struct_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - Err(Error::from_str("Unsupported BitVec serialization method")) - } - } - - // Serialize the BitVec based on our above serializer: this basically - // extracts the data out of it that we'll need for deserialization. - let mut se = BitVecSerializer { head: None, bits: None, data: Vec::new(), current_field: None }; - bit_vec.serialize(&mut se)?; - - match se { - BitVecSerializer { data, bits: Some(bits), head: Some(head), .. } => { - Ok(BitVecPieces { data, bits, head, current_field: Some(Field::Head) }) - } - _ => Err(Error::from_str("Could not gather together the BitVec pieces required during serialization")), - } - } -} - -// We want to make sure that we can transform our various Value types into the sorts of output we'd expect. -#[cfg(test)] -mod test { - - use crate::value::BitSequence; - use serde::Deserialize; - - use super::*; - - #[test] - fn de_into_struct() { - #[derive(Deserialize, Debug, PartialEq)] - struct Foo { - a: u8, - b: bool, - } - - let val = ValueDef::Composite(Composite::Named(vec![ - // Order shouldn't matter; match on names: - ("b".into(), Value::bool(true)), - ("a".into(), Value::u8(123)), - ])); - - assert_eq!(Foo::deserialize(val), Ok(Foo { a: 123, b: true })) - } - - #[test] - fn de_unwrapped_into_struct() { - #[derive(Deserialize, Debug, PartialEq)] - struct Foo { - a: u8, - b: bool, - } - - let val = Composite::Named(vec![ - // Order shouldn't matter; match on names: - ("b".into(), Value::bool(true)), - ("a".into(), Value::u8(123)), - ]); - - assert_eq!(Foo::deserialize(val), Ok(Foo { a: 123, b: true })) - } - - #[test] - fn de_into_tuple_struct() { - #[derive(Deserialize, Debug, PartialEq)] - struct Foo(u8, bool, String); - - let val = ValueDef::Composite(Composite::Unnamed(vec![ - Value::u8(123), - Value::bool(true), - Value::str("hello".into()), - ])); - - assert_eq!(Foo::deserialize(val), Ok(Foo(123, true, "hello".into()))) - } - - #[test] - fn de_unwrapped_into_tuple_struct() { - #[derive(Deserialize, Debug, PartialEq)] - struct Foo(u8, bool, String); - - let val = Composite::Unnamed(vec![Value::u8(123), Value::bool(true), Value::str("hello".into())]); - - assert_eq!(Foo::deserialize(val), Ok(Foo(123, true, "hello".into()))) - } - - #[test] - fn de_into_newtype_struct() { - #[derive(Deserialize, Debug, PartialEq)] - struct FooStr(String); - let val = ValueDef::<()>::Primitive(Primitive::Str("hello".into())); - assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); - let val = Value::str("hello".into()); - assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); - - #[derive(Deserialize, Debug, PartialEq)] - struct FooVecU8(Vec); - let val = ValueDef::Composite(Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)])); - assert_eq!(FooVecU8::deserialize(val), Ok(FooVecU8(vec![1, 2, 3]))); - - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum { - Foo(u8, u8, u8), - } - #[derive(Deserialize, Debug, PartialEq)] - struct FooVar(MyEnum); - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)]), - }); - assert_eq!(FooVar::deserialize(val), Ok(FooVar(MyEnum::Foo(1, 2, 3)))); - } - - #[test] - fn de_unwrapped_into_newtype_struct() { - #[derive(Deserialize, Debug, PartialEq)] - struct FooStr(String); - let val = Primitive::Str("hello".into()); - assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); - - #[derive(Deserialize, Debug, PartialEq)] - struct FooVecU8(Vec); - let val = Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)]); - assert_eq!(FooVecU8::deserialize(val), Ok(FooVecU8(vec![1, 2, 3]))); - - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum { - Foo(u8, u8, u8), - } - #[derive(Deserialize, Debug, PartialEq)] - struct FooVar(MyEnum); - let val = - Variant { name: "Foo".into(), values: Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)]) }; - assert_eq!(FooVar::deserialize(val), Ok(FooVar(MyEnum::Foo(1, 2, 3)))); - } - - #[test] - fn de_into_vec() { - let val = ValueDef::Composite(Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)])); - assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); - - let val = ValueDef::Composite(Composite::Unnamed(vec![ - Value::str("a".into()), - Value::str("b".into()), - Value::str("c".into()), - ])); - assert_eq!(>::deserialize(val), Ok(vec!["a".into(), "b".into(), "c".into()])); - } - - #[test] - fn de_unwrapped_into_vec() { - let val = Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)]); - assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); - - let val = - Composite::Named(vec![("a".into(), Value::u8(1)), ("b".into(), Value::u8(2)), ("c".into(), Value::u8(3))]); - assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); - - let val = Composite::Unnamed(vec![Value::str("a".into()), Value::str("b".into()), Value::str("c".into())]); - assert_eq!(>::deserialize(val), Ok(vec!["a".into(), "b".into(), "c".into()])); - } - - #[test] - fn de_into_map() { - use std::collections::HashMap; - - let val = ValueDef::Composite(Composite::Named(vec![ - ("a".into(), Value::u8(1)), - ("b".into(), Value::u8(2)), - ("c".into(), Value::u8(3)), - ])); - assert_eq!( - >::deserialize(val), - Ok(vec![("a".into(), 1), ("b".into(), 2), ("c".into(), 3)].into_iter().collect()) - ); - - let val = ValueDef::Composite(Composite::Unnamed(vec![Value::u8(1), Value::u8(2), Value::u8(3)])); - >::deserialize(val).expect_err("no names; can't be map"); - } - - #[test] - fn de_into_tuple() { - let val = ValueDef::Composite(Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true)])); - assert_eq!(<(String, bool)>::deserialize(val), Ok(("hello".into(), true))); - - // names will just be ignored: - let val = ValueDef::Composite(Composite::Named(vec![ - ("a".into(), Value::str("hello".into())), - ("b".into(), Value::bool(true)), - ])); - assert_eq!(<(String, bool)>::deserialize(val), Ok(("hello".into(), true))); - - // Enum variants are allowed! The variant name will be ignored: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true)]), - }); - assert_eq!(<(String, bool)>::deserialize(val), Ok(("hello".into(), true))); - - // Enum variants with names values are allowed! The variant name will be ignored: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Named(vec![("a".into(), Value::str("hello".into())), ("b".into(), Value::bool(true))]), - }); - assert_eq!(<(String, bool)>::deserialize(val), Ok(("hello".into(), true))); - - // Wrong number of values should fail: - let val = ValueDef::Composite(Composite::Unnamed(vec![ - Value::str("hello".into()), - Value::bool(true), - Value::u8(123), - ])); - <(String, bool)>::deserialize(val).expect_err("Wrong length, should err"); - } - - #[test] - fn de_unwrapped_into_tuple() { - let val = Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true)]); - assert_eq!(<(String, bool)>::deserialize(val), Ok(("hello".into(), true))); - - // names will just be ignored: - let val = Composite::Named(vec![("a".into(), Value::str("hello".into())), ("b".into(), Value::bool(true))]); - assert_eq!(<(String, bool)>::deserialize(val), Ok(("hello".into(), true))); - - // Wrong number of values should fail: - let val = Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true), Value::u8(123)]); - <(String, bool)>::deserialize(val).expect_err("Wrong length, should err"); - } - - #[test] - fn de_bitvec() { - use bitvec::{ bitvec, order::Lsb0 }; - - let val = Value::bit_sequence(bitvec![u8, Lsb0; 0, 1, 1, 0, 1, 0, 1, 0]); - assert_eq!(BitSequence::deserialize(val), Ok(bitvec![u8, Lsb0; 0, 1, 1, 0, 1, 0, 1, 0])); - - let val = Value::bit_sequence(bitvec![u8, Lsb0; 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0]); - assert_eq!( - BitSequence::deserialize(val), - Ok(bitvec![u8, Lsb0; 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0]) - ); - } - - #[test] - fn de_into_tuple_variant() { - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum { - Foo(String, bool, u8), - } - - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true), Value::u8(123)]), - }); - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo("hello".into(), true, 123))); - - // it's fine to name the fields; we'll just ignore the names - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Named(vec![ - ("a".into(), Value::str("hello".into())), - ("b".into(), Value::bool(true)), - ("c".into(), Value::u8(123)), - ]), - }); - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo("hello".into(), true, 123))); - } - - #[test] - fn de_unwrapped_into_tuple_variant() { - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum { - Foo(String, bool, u8), - } - - let val = Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true), Value::u8(123)]), - }; - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo("hello".into(), true, 123))); - - // it's fine to name the fields; we'll just ignore the names - let val = Variant { - name: "Foo".into(), - values: Composite::Named(vec![ - ("a".into(), Value::str("hello".into())), - ("b".into(), Value::bool(true)), - ("c".into(), Value::u8(123)), - ]), - }; - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo("hello".into(), true, 123))); - } - - #[test] - fn de_into_struct_variant() { - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum { - Foo { hi: String, a: bool, b: u8 }, - } - - // If names given, order doesn't matter: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Named(vec![ - // Deliberately out of order: names should ensure alignment: - ("b".into(), Value::u8(123)), - ("a".into(), Value::bool(true)), - ("hi".into(), Value::str("hello".into())), - ]), - }); - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo { hi: "hello".into(), a: true, b: 123 })); - - // No names needed if order is OK: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::str("hello".into()), Value::bool(true), Value::u8(123)]), - }); - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo { hi: "hello".into(), a: true, b: 123 })); - - // Wrong order won't work if no names: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Unnamed(vec![Value::bool(true), Value::u8(123), Value::str("hello".into())]), - }); - MyEnum::deserialize(val).expect_err("Wrong order shouldn't work"); - - // Wrong names won't work: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Named(vec![ - ("b".into(), Value::u8(123)), - // Whoops; wrong name: - ("c".into(), Value::bool(true)), - ("hi".into(), Value::str("hello".into())), - ]), - }); - MyEnum::deserialize(val).expect_err("Wrong names shouldn't work"); - - // Too many names is OK; we can ignore fields we don't care about: - let val = ValueDef::Variant(Variant { - name: "Foo".into(), - values: Composite::Named(vec![ - ("foo".into(), Value::u8(40)), - ("b".into(), Value::u8(123)), - ("a".into(), Value::bool(true)), - ("bar".into(), Value::bool(false)), - ("hi".into(), Value::str("hello".into())), - ]), - }); - assert_eq!(MyEnum::deserialize(val), Ok(MyEnum::Foo { hi: "hello".into(), a: true, b: 123 })); - } - - #[test] - fn de_into_unit_variants() { - let val = Value::variant("Foo".into(), Composite::Named(vec![])); - let unwrapped_val = Variant::<()> { name: "Foo".into(), values: Composite::Named(vec![]) }; - - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum { - Foo, - } - assert_eq!(MyEnum::deserialize(val.clone()), Ok(MyEnum::Foo)); - assert_eq!(MyEnum::deserialize(unwrapped_val.clone()), Ok(MyEnum::Foo)); - - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum2 { - Foo(), - } - assert_eq!(MyEnum2::deserialize(val.clone()), Ok(MyEnum2::Foo())); - assert_eq!(MyEnum2::deserialize(unwrapped_val.clone()), Ok(MyEnum2::Foo())); - - #[derive(Deserialize, Debug, PartialEq)] - enum MyEnum3 { - Foo {}, - } - assert_eq!(MyEnum3::deserialize(val), Ok(MyEnum3::Foo {})); - assert_eq!(MyEnum3::deserialize(unwrapped_val), Ok(MyEnum3::Foo {})); - } -} diff --git a/desub-current/src/value/mod.rs b/desub-current/src/value/mod.rs deleted file mode 100644 index dd96927c..00000000 --- a/desub-current/src/value/mod.rs +++ /dev/null @@ -1,298 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of substrate-desub. -// -// substrate-desub is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// substrate-desub is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with substrate-desub. If not, see . - -/*! -This module exposes the [`Value`] type and related subtypes, which are used as the runtime -representations of SCALE encoded data (much like `serde_json::Value` is a runtime representation -of JSON data). -*/ - -mod deserialize; -mod deserializer; -mod serialize; - -use bitvec::{order::Lsb0, vec::BitVec}; -use serde::Deserialize; -use std::convert::From; -use std::fmt::Debug; - -/// [`Value`] holds a representation of some value that has been decoded, as well as some arbitrary context. -/// -/// Not all SCALE encoded types have an similar-named value; for instance, the values corresponding to -/// sequence, array and composite types can all be represented with [`Composite`]. Only enough information -/// is preserved here to construct a valid value for any type that we know about, and be able to verify -/// that a given value is compatible with some type (see the [`scale_info`] crate), if we have both. -#[derive(Debug, Clone, PartialEq)] -pub struct Value { - /// The shape and associated values for this Value - pub value: ValueDef, - /// Some additional arbitrary context that can be associated with a value. - pub context: T, -} - -macro_rules! value_prim_method { - ($name:ident $variant:ident) => { - #[doc = concat!("Create a new `", stringify!($name), "` value without additional context")] - pub fn $name(val: $name) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::$variant(val)), context: () } - } - } -} - -impl Value<()> { - /// Create a new named composite value without additional context. - pub fn named_composite(values: Vec<(String, Value<()>)>) -> Value<()> { - Value { value: ValueDef::Composite(Composite::Named(values)), context: () } - } - /// Create a new unnamed composite value without additional context. - pub fn unnamed_composite(values: Vec>) -> Value<()> { - Value { value: ValueDef::Composite(Composite::Unnamed(values)), context: () } - } - /// Create a new variant value without additional context. - pub fn variant(name: String, values: Composite<()>) -> Value<()> { - Value { value: ValueDef::Variant(Variant { name, values }), context: () } - } - /// Create a new bit sequence value without additional context. - pub fn bit_sequence(bitseq: BitSequence) -> Value<()> { - Value { value: ValueDef::BitSequence(bitseq), context: () } - } - /// Create a new primitive value without additional context. - pub fn primitive(primitive: Primitive) -> Value<()> { - Value { value: ValueDef::Primitive(primitive), context: () } - } - /// Create a new string value without additional context. - pub fn str(val: String) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::Str(val)), context: () } - } - - value_prim_method!(bool Bool); - value_prim_method!(char Char); - value_prim_method!(u8 U8); - value_prim_method!(u16 U16); - value_prim_method!(u32 U32); - value_prim_method!(u64 U64); - value_prim_method!(u128 U128); - value_prim_method!(i8 I8); - value_prim_method!(i16 I16); - value_prim_method!(i32 I32); - value_prim_method!(i64 I64); - value_prim_method!(i128 I128); -} - -impl Value { - /// Create a new value with some associated context. - pub fn with_context(value: ValueDef, context: T) -> Value { - Value { value, context } - } - /// Remove the context. - pub fn without_context(self) -> Value<()> { - self.map_context(|_| ()) - } - /// Map the context to some different type. - pub fn map_context(self, mut f: F) -> Value - where - F: Clone + FnMut(T) -> U, - { - Value { context: f(self.context), value: self.value.map_context(f) } - } -} - -/// The underlying shape of a given value. -#[derive(Clone, PartialEq)] -pub enum ValueDef { - /// A named or unnamed struct-like, array-like or tuple-like set of values. - Composite(Composite), - /// An enum variant. - Variant(Variant), - /// A sequence of bits (which is more compactly encoded using [`bitvec`]) - BitSequence(BitSequence), - /// Any of the primitive values we can have. - Primitive(Primitive), -} - -impl ValueDef { - /// Map the context to some different type. - pub fn map_context(self, f: F) -> ValueDef - where - F: Clone + FnMut(T) -> U, - { - match self { - ValueDef::Composite(val) => ValueDef::Composite(val.map_context(f)), - ValueDef::Variant(val) => ValueDef::Variant(val.map_context(f)), - ValueDef::BitSequence(val) => ValueDef::BitSequence(val), - ValueDef::Primitive(val) => ValueDef::Primitive(val), - } - } -} - -impl Debug for ValueDef { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Composite(val) => Debug::fmt(val, f), - Self::Variant(val) => Debug::fmt(val, f), - Self::Primitive(val) => Debug::fmt(val, f), - Self::BitSequence(val) => Debug::fmt(val, f), - } - } -} - -/// A named or unnamed struct-like, array-like or tuple-like set of values. -/// This is used to represent a range of composite values on their own, or -/// as values for a specific [`Variant`]. -#[derive(Clone, PartialEq)] -pub enum Composite { - /// Eg `{ foo: 2, bar: false }` - Named(Vec<(String, Value)>), - /// Eg `(2, false)` - Unnamed(Vec>), -} - -impl Composite { - /// Return the number of values stored in this composite type. - pub fn len(&self) -> usize { - match self { - Composite::Named(values) => values.len(), - Composite::Unnamed(values) => values.len(), - } - } - - /// Is the composite type empty? - pub fn is_empty(&self) -> bool { - match self { - Composite::Named(values) => values.is_empty(), - Composite::Unnamed(values) => values.is_empty(), - } - } - - /// Map the context to some different type. - pub fn map_context(self, f: F) -> Composite - where - F: Clone + FnMut(T) -> U, - { - match self { - Composite::Named(values) => { - // Note: Optimally I'd pass `&mut f` into each iteration to avoid cloning, - // but this leads to a type recusion error because F becomes `&mut F`, which can - // (at type level) recurse here again and become `&mut &mut F` and so on. Since - // that's no good; just require `Clone` to avoid altering the type. - let vals = values.into_iter().map(move |(k, v)| (k, v.map_context(f.clone()))).collect(); - Composite::Named(vals) - } - Composite::Unnamed(values) => { - let vals = values.into_iter().map(move |v| v.map_context(f.clone())).collect(); - Composite::Unnamed(vals) - } - } - } -} - -impl Debug for Composite { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Composite::Named(fields) => { - let mut struc = f.debug_struct(""); - for (name, val) in fields { - struc.field(name, val); - } - struc.finish() - } - Composite::Unnamed(fields) => { - let mut struc = f.debug_tuple(""); - for val in fields { - struc.field(val); - } - struc.finish() - } - } - } -} - -impl From> for ValueDef { - fn from(val: Composite) -> Self { - ValueDef::Composite(val) - } -} - -/// This represents the value of a specific variant from an enum, and contains -/// the name of the variant, and the named/unnamed values associated with it. -#[derive(Clone, PartialEq)] -pub struct Variant { - /// The name of the variant. - pub name: String, - /// Values for each of the named or unnamed fields associated with this variant. - pub values: Composite, -} - -impl Variant { - /// Map the context to some different type. - pub fn map_context(self, f: F) -> Variant - where - F: Clone + FnMut(T) -> U, - { - Variant { name: self.name, values: self.values.map_context(f) } - } -} - -impl Debug for Variant { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str(&self.name)?; - f.write_str(" ")?; - Debug::fmt(&self.values, f) - } -} - -impl From> for ValueDef { - fn from(val: Variant) -> Self { - ValueDef::Variant(val) - } -} - -/// A "primitive" value (this includes strings). -#[derive(Debug, Clone, PartialEq)] -pub enum Primitive { - Bool(bool), - Char(char), - Str(String), - U8(u8), - U16(u16), - U32(u32), - U64(u64), - U128(u128), - U256([u8; 32]), - I8(i8), - I16(i16), - I32(i32), - I64(i64), - I128(i128), - I256([u8; 32]), -} - -impl From for ValueDef { - fn from(val: Primitive) -> Self { - ValueDef::Primitive(val) - } -} - -/// A sequence of bits. -pub type BitSequence = BitVec; - -/// An opaque error that is returned if we cannot deserialize the [`Value`] type. -pub use deserializer::Error as DeserializeError; - -/// Attempt to deserialize a [`Value`] into some type that has [`serde::Deserialize`] implemented on it. -pub fn from_value<'de, Ctx, T: Deserialize<'de>>(value: Value) -> Result { - T::deserialize(value) -} diff --git a/desub-current/src/value/serialize.rs b/desub-current/src/value/serialize.rs deleted file mode 100644 index 63b02843..00000000 --- a/desub-current/src/value/serialize.rs +++ /dev/null @@ -1,190 +0,0 @@ -// Copyright 2019-2021 Parity Technologies (UK) Ltd. -// This file is part of substrate-desub. -// -// substrate-desub is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// substrate-desub is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with substrate-desub. If not, see . - -use super::{Composite, Primitive, Value, ValueDef, Variant}; -use serde::{ - ser::{SerializeMap, SerializeSeq}, - Serialize, -}; - -impl Serialize for Value { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - self.value.serialize(serializer) - } -} - -impl Serialize for ValueDef { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self { - ValueDef::Composite(val) => val.serialize(serializer), - ValueDef::Variant(val) => val.serialize(serializer), - ValueDef::BitSequence(val) => val.serialize(serializer), - ValueDef::Primitive(val) => val.serialize(serializer), - } - } -} - -impl Serialize for Composite { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - match self { - Composite::Named(vals) => { - let mut map = serializer.serialize_map(Some(vals.len()))?; - for (key, val) in vals { - map.serialize_entry(key, val)?; - } - map.end() - } - Composite::Unnamed(vals) => { - let mut seq = serializer.serialize_seq(Some(vals.len()))?; - for val in vals { - seq.serialize_element(val)?; - } - seq.end() - } - } - } -} - -impl Serialize for Primitive { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - // Delegate to the serialization strategy used by the primitive types. - match self { - Primitive::Bool(v) => v.serialize(serializer), - Primitive::Char(v) => v.serialize(serializer), - Primitive::Str(v) => v.serialize(serializer), - Primitive::U8(v) => v.serialize(serializer), - Primitive::U16(v) => v.serialize(serializer), - Primitive::U32(v) => v.serialize(serializer), - Primitive::U64(v) => v.serialize(serializer), - Primitive::U128(v) => v.serialize(serializer), - Primitive::U256(v) => v.serialize(serializer), - Primitive::I8(v) => v.serialize(serializer), - Primitive::I16(v) => v.serialize(serializer), - Primitive::I32(v) => v.serialize(serializer), - Primitive::I64(v) => v.serialize(serializer), - Primitive::I128(v) => v.serialize(serializer), - Primitive::I256(v) => v.serialize(serializer), - } - } -} - -impl Serialize for Variant { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - // We can't use the enum serializing in the serde data model because that requires static - // strs and enum indexes, which we don't have (since this is a runtime value), so we serialize - // as a map with a type and a value, and make sure that we allow this format when attempting to - // deserialize into a `Variant` type for a bit of symmetry (although note that if you try to deserialize - // this into a `Value` type it'll have no choice but to deserialize straight into a `Composite::Named` map). - let mut map = serializer.serialize_map(Some(2))?; - map.serialize_entry("name", &self.name)?; - map.serialize_entry("values", &self.values)?; - map.end() - } -} - -#[cfg(test)] -mod test { - - use super::*; - use serde_json::json; - - fn assert_value(value: Value<()>, expected: serde_json::Value) { - let val = serde_json::to_value(&value).expect("can serialize to serde_json::Value"); - assert_eq!(val, expected); - } - - #[test] - fn serialize_primitives() { - // a subset of the primitives to sanity check that they are unwrapped: - assert_value(Value::u8(1), json!(1)); - assert_value(Value::u16(1), json!(1)); - assert_value(Value::u32(1), json!(1)); - assert_value(Value::u64(1), json!(1)); - assert_value(Value::bool(true), json!(true)); - assert_value(Value::bool(false), json!(false)); - } - - #[test] - fn serialize_composites() { - assert_value( - Value::named_composite(vec![ - ("a".into(), Value::bool(true)), - ("b".into(), Value::str("hello".into())), - ("c".into(), Value::char('c')), - ]), - json!({ - "a": true, - "b": "hello", - "c": 'c' - }), - ); - assert_value( - Value::unnamed_composite(vec![Value::bool(true), Value::str("hello".into()), Value::char('c')]), - json!([true, "hello", 'c']), - ) - } - - #[test] - fn serialize_variants() { - assert_value( - Value::variant( - "Foo".into(), - Composite::Named(vec![ - ("a".into(), Value::bool(true)), - ("b".into(), Value::str("hello".into())), - ("c".into(), Value::char('c')), - ]), - ), - json!({ - "name": "Foo", - "values": { - "a": true, - "b": "hello", - "c": 'c' - } - }), - ); - assert_value( - Value::variant( - "Bar".into(), - Composite::Unnamed(vec![Value::bool(true), Value::str("hello".into()), Value::char('c')]), - ), - json!({ - "name": "Bar", - "values": [ - true, - "hello", - 'c' - ] - }), - ) - } -} diff --git a/desub-current/tests/decode_extrinsics.rs b/desub-current/tests/decode_extrinsics.rs index 75c354c3..26a3511d 100644 --- a/desub-current/tests/decode_extrinsics.rs +++ b/desub-current/tests/decode_extrinsics.rs @@ -16,8 +16,9 @@ use desub_current::{ decoder::{self, SignedExtensionWithAdditional}, - value, Metadata, Value, ValueDef, + Metadata, Value, ValueDef }; +use scale_value::{Composite, Variant}; static V14_METADATA_POLKADOT_SCALE: &[u8] = include_bytes!("data/v14_metadata_polkadot.scale"); @@ -39,11 +40,11 @@ fn singleton_value(x: Value<()>) -> Value<()> { } fn hash_value(xs: Vec) -> Value<()> { - singleton_value(Value::unnamed_composite(xs.iter().map(|x| Value::u8(*x)).collect())) + singleton_value(Value::from_bytes(&xs)) } fn assert_args_equal(args: &[Value], expected: Vec>) { - let args: Vec<_> = args.into_iter().map(|v| v.clone().without_context()).collect(); + let args: Vec<_> = args.into_iter().map(|v| v.clone().remove_context()).collect(); assert_eq!(&args, &expected); } @@ -87,7 +88,7 @@ fn balance_transfer_signed() { assert_eq!(ext.call_data.pallet_name, "Balances"); assert_eq!(&*ext.call_data.ty.name, "transfer"); assert_eq!(ext.call_data.arguments.len(), 2); - assert_eq!(ext.call_data.arguments[1].clone().without_context(), Value::u128(12345)); + assert_eq!(ext.call_data.arguments[1].clone().remove_context(), Value::u128(12345)); } #[test] @@ -102,7 +103,7 @@ fn balance_transfer_all_signed() { assert_eq!(ext.call_data.pallet_name, "Balances"); assert_eq!(&*ext.call_data.ty.name, "transfer_all"); assert_eq!(ext.call_data.arguments.len(), 2); - assert_eq!(ext.call_data.arguments[1].clone().without_context(), Value::bool(false)); + assert_eq!(ext.call_data.arguments[1].clone().remove_context(), Value::bool(false)); } /// This test is interesting because: @@ -123,7 +124,7 @@ fn auctions_bid_unsigned() { assert_args_equal( &ext.call_data.arguments, - vec![singleton_value(Value::u32(1)), Value::u32(2), Value::u32(3), Value::u32(4), Value::u128(5)], + vec![singleton_value(Value::u128(1)), Value::u128(2), Value::u128(3), Value::u128(4), Value::u128(5)], ); } @@ -155,7 +156,7 @@ fn system_fill_block_unsigned() { assert_eq!(&*ext.call_data.ty.name, "fill_block"); assert_eq!(ext.call_data.arguments.len(), 1); - assert_args_equal(&ext.call_data.arguments, vec![singleton_value(Value::u32(1234))]); + assert_args_equal(&ext.call_data.arguments, vec![singleton_value(Value::u128(1234))]); } /// This test is interesting because you provide a nested enum representing a call @@ -177,14 +178,14 @@ fn technical_committee_execute_unsigned() { // It's a bit hard matching the entire thing, so we just verify that the first arg looks like // a variant representing a call to "Balances.transfer". assert!(matches!(&ext.call_data.arguments[0], - Value { value: ValueDef::Variant(value::Variant { + Value { value: ValueDef::Variant(Variant { name, - values: value::Composite::Unnamed(args) + values: Composite::Unnamed(args) }), .. } if &*name == "Balances" - && matches!(&args[0], Value { value: ValueDef::Variant(value::Variant { name, ..}), .. } if &*name == "transfer") + && matches!(&args[0], Value { value: ValueDef::Variant(Variant { name, ..}), .. } if &*name == "transfer") )); - assert_eq!(ext.call_data.arguments[1].clone().without_context(), Value::u32(500)); + assert_eq!(ext.call_data.arguments[1].clone().remove_context(), Value::u128(500)); } #[test] @@ -201,8 +202,8 @@ fn tips_report_awesome_unsigned() { assert_eq!(ext.call_data.arguments.len(), 2); assert_eq!( - ext.call_data.arguments[0].clone().without_context(), - Value::unnamed_composite("This person rocks!".bytes().map(Value::u8).collect()) + ext.call_data.arguments[0].clone().remove_context(), + Value::from_bytes("This person rocks!") ); } @@ -221,11 +222,11 @@ fn vesting_force_vested_transfer_unsigned() { assert_eq!(ext.call_data.arguments.len(), 3); assert_eq!( - ext.call_data.arguments[2].clone().without_context(), + ext.call_data.arguments[2].clone().remove_context(), Value::named_composite(vec![ - ("locked".into(), Value::u128(1)), - ("per_block".into(), Value::u128(2)), - ("starting_block".into(), Value::u32(3)), + ("locked", Value::u128(1)), + ("per_block", Value::u128(2)), + ("starting_block", Value::u128(3)), ]) ); } @@ -263,8 +264,8 @@ fn can_decode_signer_payload() { // Expected tuples of name, extension, additional. let expected = vec![ - ("CheckSpecVersion", empty_value(), Value::u32(9110)), - ("CheckTxVersion", empty_value(), Value::u32(8)), + ("CheckSpecVersion", empty_value(), Value::u128(9110)), + ("CheckTxVersion", empty_value(), Value::u128(8)), ( "CheckGenesis", empty_value(), @@ -272,10 +273,10 @@ fn can_decode_signer_payload() { ), ( "CheckMortality", - singleton_value(Value::variant("Mortal185".to_string(), value::Composite::Unnamed(vec![Value::u8(52)]))), + singleton_value(Value::variant("Mortal185", Composite::Unnamed(vec![Value::u128(52)]))), hash_value(to_bytes("0x1c81d421f68281950ad2901291603b5e49fc5c872f129e75433f4b55f07ca072")), ), - ("CheckNonce", singleton_value(Value::u32(0)), empty_value()), + ("CheckNonce", singleton_value(Value::u128(0)), empty_value()), ("CheckWeight", empty_value(), empty_value()), ("ChargeTransactionPayment", singleton_value(Value::u128(0)), empty_value()), ("PrevalidateAttests", empty_value(), empty_value()), @@ -286,7 +287,7 @@ fn can_decode_signer_payload() { let (expected_name, expected_extension, expected_additional) = expected; assert_eq!(&*name, expected_name); - assert_eq!(extension.without_context(), expected_extension); - assert_eq!(additional.without_context(), expected_additional); + assert_eq!(extension.remove_context(), expected_extension); + assert_eq!(additional.remove_context(), expected_additional); } } diff --git a/desub-current/tests/decode_storage.rs b/desub-current/tests/decode_storage.rs index d54b355f..110968da 100644 --- a/desub-current/tests/decode_storage.rs +++ b/desub-current/tests/decode_storage.rs @@ -27,13 +27,13 @@ fn metadata() -> Metadata { } fn account_id_to_value>(account_id_bytes: A) -> Value<()> { - Value::unnamed_composite(vec![Value::unnamed_composite(account_id_bytes.as_ref().iter().map(|&b| Value::u8(b)).collect())]) + Value::unnamed_composite(vec![Value::from_bytes(account_id_bytes)]) } macro_rules! assert_hasher_eq { ($actual:expr, $hasher:path, $value:expr) => { if let $hasher(val) = &$actual { - assert_eq!(val.clone().without_context(), $value); + assert_eq!(val.clone().remove_context(), $value); } else { panic!("Passed {:?}, but expected hasher {}", $actual, stringify!($hasher)); } @@ -64,8 +64,8 @@ fn timestamp_now() { // We can decode values at this location, now: let bytes = 123u64.encode(); - let val = decoder::decode_value_by_id(&meta, &entry.ty, &mut &*bytes).unwrap(); - assert_eq!(val.without_context(), Value::u64(123)); + let val = decoder::decode_value_by_id(&meta, entry.ty, &mut &*bytes).unwrap(); + assert_eq!(val.remove_context(), Value::u128(123)); } // A simple map lookup with an Identity hash (ie just the key itself) @@ -89,7 +89,7 @@ fn democracy_blacklist() { assert_hasher_eq!( keys[0].hasher, StorageHasher::Identity, - Value::unnamed_composite(vec![Value::unnamed_composite(vec![Value::u8(1); 32])]) + Value::unnamed_composite(vec![Value::unnamed_composite(vec![Value::u128(1); 32])]) ); assert!(matches!(keys[0].hasher, StorageHasher::Identity(..))); } @@ -112,15 +112,15 @@ fn system_blockhash() { // Because the hasher is Twox64Concat, we can even see the decoded original map key: assert_eq!(keys.len(), 1); - assert_hasher_eq!(keys[0].hasher, StorageHasher::Twox64Concat, Value::u32(1000)); + assert_hasher_eq!(keys[0].hasher, StorageHasher::Twox64Concat, Value::u128(1000)); // We can decode values at this location: let bytes = [1u8; 32].encode(); - let val = decoder::decode_value_by_id(&meta, &entry.ty, &mut &*bytes).unwrap(); + let val = decoder::decode_value_by_id(&meta, entry.ty, &mut &*bytes).unwrap(); assert_eq!( - val.without_context(), + val.remove_context(), // The Type appears to take the form of a newtype-wrapped [u8; 32]: - Value::unnamed_composite(vec![Value::unnamed_composite(vec![Value::u8(1); 32])]) + Value::unnamed_composite(vec![Value::unnamed_composite(vec![Value::u128(1); 32])]) ); } @@ -168,11 +168,11 @@ fn imonline_authoredblocks() { // Because the hashers are Twox64Concat, we can check the keys we provided: assert_eq!(keys.len(), 2); - assert_hasher_eq!(keys[0].hasher, StorageHasher::Twox64Concat, Value::u32(1234)); + assert_hasher_eq!(keys[0].hasher, StorageHasher::Twox64Concat, Value::u128(1234)); assert_hasher_eq!(keys[1].hasher, StorageHasher::Twox64Concat, bobs_value); // We can decode values at this location: let bytes = 5678u32.encode(); - let val = decoder::decode_value_by_id(&meta, &entry.ty, &mut &*bytes).unwrap(); - assert_eq!(val.without_context(), Value::u32(5678)); + let val = decoder::decode_value_by_id(&meta, entry.ty, &mut &*bytes).unwrap(); + assert_eq!(val.remove_context(), Value::u128(5678)); }