diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 16e1de5..3bb453d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -136,6 +136,12 @@ jobs: command: test args: --all-targets --workspace + - name: Cargo test docs + uses: actions-rs/cargo@v1.0.3 + with: + command: test + args: --doc --workspace + clippy: name: Cargo clippy runs-on: ubuntu-latest diff --git a/.rustfmt.toml b/.rustfmt.toml index bf689c3..2d98c68 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,4 +1,5 @@ -hard_tabs = true +hard_tabs = false +tab_spaces = 4 max_width = 100 use_small_heuristics = "Max" edition = "2021" \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000..4af6a28 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,5 @@ +# main codeowner @paritytech/tools-team +* @paritytech/tools-team + +# CI +/.github/ @paritytech/ci @paritytech/tools-team \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 626cc1f..8234c46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,8 @@ serde = { version = "1.0.124", features = ["derive"], optional = true } frame-metadata = { version = "15.0.0", default-features = false, features = ["v14"] } thiserror = "1.0.24" scale-info = { version = "2.0.0", default-features = false, features = ["std"] } -scale-decode = "0.4.0" +scale-decode = { version = "0.5.0", default-features = false } +scale-encode = { version = "0.1.0", default-features = false, features = ["bits"] } scale-bits = "0.3.0" either = "1.6.1" yap = { version = "0.7.2", optional = true } diff --git a/RELEASING.md b/RELEASING.md index 3476f99..6aa121f 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -41,9 +41,12 @@ These steps assume that you've checked out the `scale-value` repository and are Checkout `main`, ensuring we're looking at that latest merge (`git pull`). - Next, do a dry run to make sure that things seem sane: + Next, do a final sanity check to make sure there are no new issues: ``` - cargo publish --dry-run + cargo fmt + cargo clippy --all-targets + cargo test --all-targets + cargo test --doc ``` If we're happy with everything, proceed with the release: diff --git a/src/at.rs b/src/at.rs index 93aa1a0..ef73bd5 100644 --- a/src/at.rs +++ b/src/at.rs @@ -56,61 +56,61 @@ use super::{Composite, Value, ValueDef, Variant}; /// assert_eq!(val.at("wibble").at("wobble").at("nope"), None); /// ``` pub trait At: private::Sealed { - /// Index into a value, returning a reference to the value if one - /// exists, or [`None`] if not. - fn at(&self, loc: L) -> Option<&Value>; + /// Index into a value, returning a reference to the value if one + /// exists, or [`None`] if not. + fn at(&self, loc: L) -> Option<&Value>; } // Prevent users from implementing the At trait. mod private { - use super::*; - pub trait Sealed {} - impl Sealed for Value {} - impl Sealed for Composite {} - impl Sealed for Variant {} - impl Sealed for Option<&T> {} + use super::*; + pub trait Sealed {} + impl Sealed for Value {} + impl Sealed for Composite {} + impl Sealed for Variant {} + impl Sealed for Option<&T> {} } impl At for Composite { - fn at(&self, loc: L) -> Option<&Value> { - match loc.as_location().inner { - LocationInner::Str(s) => match self { - Composite::Named(vals) => { - vals.iter().find_map(|(n, v)| if s == n { Some(v) } else { None }) - } - _ => None, - }, - LocationInner::Usize(n) => match self { - Composite::Named(vals) => { - let val = vals.get(n); - val.map(|v| &v.1) - } - Composite::Unnamed(vals) => vals.get(n), - }, - } - } + fn at(&self, loc: L) -> Option<&Value> { + match loc.as_location().inner { + LocationInner::Str(s) => match self { + Composite::Named(vals) => { + vals.iter().find_map(|(n, v)| if s == n { Some(v) } else { None }) + } + _ => None, + }, + LocationInner::Usize(n) => match self { + Composite::Named(vals) => { + let val = vals.get(n); + val.map(|v| &v.1) + } + Composite::Unnamed(vals) => vals.get(n), + }, + } + } } impl At for Variant { - fn at(&self, loc: L) -> Option<&Value> { - self.values.at(loc) - } + fn at(&self, loc: L) -> Option<&Value> { + self.values.at(loc) + } } impl At for Value { - fn at(&self, loc: L) -> Option<&Value> { - match &self.value { - ValueDef::Composite(c) => c.at(loc), - ValueDef::Variant(v) => v.at(loc), - _ => None, - } - } + fn at(&self, loc: L) -> Option<&Value> { + match &self.value { + ValueDef::Composite(c) => c.at(loc), + ValueDef::Variant(v) => v.at(loc), + _ => None, + } + } } impl> At for Option<&T> { - fn at(&self, loc: L) -> Option<&Value> { - self.as_ref().and_then(|v| v.at(loc)) - } + fn at(&self, loc: L) -> Option<&Value> { + self.as_ref().and_then(|v| v.at(loc)) + } } /// Types which can be used as a lookup location with [`At::at`] @@ -119,122 +119,125 @@ impl> At for Option<&T> { /// Users cannot implement this as the [`Location`] type internals /// are opaque and subject to change. pub trait AsLocation { - fn as_location(&self) -> Location<'_>; + fn as_location(&self) -> Location<'_>; } impl AsLocation for usize { - fn as_location(&self) -> Location<'_> { - Location { inner: LocationInner::Usize(*self) } - } + fn as_location(&self) -> Location<'_> { + Location { inner: LocationInner::Usize(*self) } + } } impl AsLocation for &str { - fn as_location(&self) -> Location<'_> { - Location { inner: LocationInner::Str(self) } - } + fn as_location(&self) -> Location<'_> { + Location { inner: LocationInner::Str(self) } + } } impl AsLocation for String { - fn as_location(&self) -> Location<'_> { - Location { inner: LocationInner::Str(&**self) } - } + fn as_location(&self) -> Location<'_> { + Location { inner: LocationInner::Str(self) } + } } impl AsLocation for &T { - fn as_location(&self) -> Location<'_> { - (*self).as_location() - } + fn as_location(&self) -> Location<'_> { + (*self).as_location() + } } /// A struct representing a location to access in a [`Value`]. #[derive(Copy, Clone)] pub struct Location<'a> { - inner: LocationInner<'a>, + inner: LocationInner<'a>, } #[derive(Copy, Clone)] enum LocationInner<'a> { - Usize(usize), - Str(&'a str), + Usize(usize), + Str(&'a str), } #[cfg(test)] mod test { - use super::*; - - // This is basically the doc example with a little extra. - #[test] - fn nested_accessing() { - let val = Value::named_composite([( - "hello", - Value::unnamed_composite([ - Value::u128(1), - Value::bool(true), - Value::named_composite([ - ("wibble", Value::bool(false)), - ("foo", Value::named_composite([("bar", Value::u128(123))])), - ]), - ]), - )]); - - assert_eq!(val.at("hello").at(0), Some(&Value::u128(1))); - assert_eq!(val.at("hello").at(1), Some(&Value::bool(true))); - assert_eq!(val.at("hello").at(2).at("wibble"), Some(&Value::bool(false))); - assert_eq!(val.at("hello").at(2).at("foo").at("bar"), Some(&Value::u128(123))); - - assert_eq!(val.at("wibble").at(3), None); - assert_eq!(val.at("wibble").at("wobble").at("nope"), None); - - // Strings can be used: - assert_eq!(val.at("hello").at(0), Some(&Value::u128(1))); - // References to valid locations are fine too: - assert_eq!(val.at(&&"hello").at(&&&0), Some(&Value::u128(1))); - } - - #[test] - fn accessing_variants() { - let val = Value::named_variant( - "TheVariant", - [("foo", Value::u128(12345)), ("bar", Value::char('c'))], - ); - - assert_eq!(val.at("foo").unwrap().as_u128().unwrap(), 12345); - assert_eq!(val.at("bar").unwrap().as_char().unwrap(), 'c'); - - let val = Value::unnamed_variant("TheVariant", [Value::u128(12345), Value::char('c')]); - - assert_eq!(val.at(0).unwrap().as_u128().unwrap(), 12345); - assert_eq!(val.at(1).unwrap().as_char().unwrap(), 'c'); - - // We can use `at()` on the variant directly, too: - - let val = Variant::named_fields( - "TheVariant", - [("foo", Value::u128(12345)), ("bar", Value::char('c'))], - ); - - assert_eq!(val.at("foo").unwrap().as_u128().unwrap(), 12345); - assert_eq!(val.at("bar").unwrap().as_char().unwrap(), 'c'); - - let val = Variant::unnamed_fields("TheVariant", [Value::u128(12345), Value::char('c')]); - - assert_eq!(val.at(0).unwrap().as_u128().unwrap(), 12345); - assert_eq!(val.at(1).unwrap().as_char().unwrap(), 'c'); - } - - #[test] - fn accessing_composites() { - // We already test accessing composite Values. This also checks that `at` works on - // the Composite type, too.. - - let val = Composite::named([("foo", Value::u128(12345)), ("bar", Value::char('c'))]); - - assert_eq!(val.at("foo").unwrap().as_u128().unwrap(), 12345); - assert_eq!(val.at("bar").unwrap().as_char().unwrap(), 'c'); - - let val = Composite::unnamed([Value::u128(12345), Value::char('c')]); - - assert_eq!(val.at(0).unwrap().as_u128().unwrap(), 12345); - assert_eq!(val.at(1).unwrap().as_char().unwrap(), 'c'); - } + use super::*; + + // This is basically the doc example with a little extra. + #[test] + fn nested_accessing() { + let val = Value::named_composite([( + "hello", + Value::unnamed_composite([ + Value::u128(1), + Value::bool(true), + Value::named_composite([ + ("wibble", Value::bool(false)), + ("foo", Value::named_composite([("bar", Value::u128(123))])), + ]), + ]), + )]); + + assert_eq!(val.at("hello").at(0), Some(&Value::u128(1))); + assert_eq!(val.at("hello").at(1), Some(&Value::bool(true))); + assert_eq!(val.at("hello").at(2).at("wibble"), Some(&Value::bool(false))); + assert_eq!(val.at("hello").at(2).at("foo").at("bar"), Some(&Value::u128(123))); + + assert_eq!(val.at("wibble").at(3), None); + assert_eq!(val.at("wibble").at("wobble").at("nope"), None); + + // Strings can be used: + assert_eq!(val.at("hello".to_string()).at(0), Some(&Value::u128(1))); + // References to valid locations are fine too: + #[allow(clippy::needless_borrow)] + { + assert_eq!(val.at(&"hello").at(&0), Some(&Value::u128(1))); + } + } + + #[test] + fn accessing_variants() { + let val = Value::named_variant( + "TheVariant", + [("foo", Value::u128(12345)), ("bar", Value::char('c'))], + ); + + assert_eq!(val.at("foo").unwrap().as_u128().unwrap(), 12345); + assert_eq!(val.at("bar").unwrap().as_char().unwrap(), 'c'); + + let val = Value::unnamed_variant("TheVariant", [Value::u128(12345), Value::char('c')]); + + assert_eq!(val.at(0).unwrap().as_u128().unwrap(), 12345); + assert_eq!(val.at(1).unwrap().as_char().unwrap(), 'c'); + + // We can use `at()` on the variant directly, too: + + let val = Variant::named_fields( + "TheVariant", + [("foo", Value::u128(12345)), ("bar", Value::char('c'))], + ); + + assert_eq!(val.at("foo").unwrap().as_u128().unwrap(), 12345); + assert_eq!(val.at("bar").unwrap().as_char().unwrap(), 'c'); + + let val = Variant::unnamed_fields("TheVariant", [Value::u128(12345), Value::char('c')]); + + assert_eq!(val.at(0).unwrap().as_u128().unwrap(), 12345); + assert_eq!(val.at(1).unwrap().as_char().unwrap(), 'c'); + } + + #[test] + fn accessing_composites() { + // We already test accessing composite Values. This also checks that `at` works on + // the Composite type, too.. + + let val = Composite::named([("foo", Value::u128(12345)), ("bar", Value::char('c'))]); + + assert_eq!(val.at("foo").unwrap().as_u128().unwrap(), 12345); + assert_eq!(val.at("bar").unwrap().as_char().unwrap(), 'c'); + + let val = Composite::unnamed([Value::u128(12345), Value::char('c')]); + + assert_eq!(val.at(0).unwrap().as_u128().unwrap(), 12345); + assert_eq!(val.at(1).unwrap().as_char().unwrap(), 'c'); + } } diff --git a/src/lib.rs b/src/lib.rs index 9064e9f..48a6098 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,17 +13,21 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! This crate 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). -//! -//! Use the [`crate::scale`] module to encode and decode [`Value`]s to SCALE bytes. In most cases, you'll -//! use this module in conjunction with node metadata so that you have access to a type registry and know -//! which type you'll want to try and encode or decode your [`Value`] into. -//! -//! With the serde feature enabled, you can also use the [`crate::serde`] module to convert rust types to -//! and from [`Value`]s, or serialize/deserialize them to/from other formats like JSON. +/*! +This crate 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). +[`Value`]'s can be: + +- Encoded and decoded from SCALE bytes via [`scale_encode::EncodeAsType`] and [`scale_decode::DecodeAsType`] + traits (or by calling [`crate::scale::decode_as_type`] and [`crate::scale::encode_as_type`]). +- Parsed to and from strings by calling [`crate::stringify::from_str`] and [`crate::stringify::to_string`]). + Parsing from strings requires the `from_string` feature to be enabled. +- Serialized and deserialized via `serde` traits (for example, to and from JSON). They can also be serialized + from and to other types with the relevant serde derives on. These require the `serde` feature to be enabled. +- Accessed ergonomically via the [`At`] trait. +*/ #![deny(missing_docs)] mod at; @@ -42,107 +46,107 @@ pub use value::{BitSequence, Composite, Primitive, Value, ValueDef, Variant}; /// Serializing and deserializing a [`crate::Value`] into/from other types via serde. #[cfg(feature = "serde")] pub mod serde { - pub use crate::serde_impls::{DeserializerError, SerializerError, ValueSerializer}; + pub use crate::serde_impls::{DeserializerError, SerializerError, ValueSerializer}; - /// Attempt to convert a [`crate::Value`] into another type via serde. - /// - /// # Examples - /// - /// Use serde to convert a value into a built-in type: - /// - /// ```rust - /// use scale_value::Value; - /// - /// let value = Value::unnamed_composite(vec![ - /// Value::u128(1), - /// Value::u128(2), - /// Value::u128(3), - /// ]); - /// - /// let arr: [u8; 3] = scale_value::serde::from_value(value).unwrap(); - /// ``` - /// - /// Converting values to a custom type: - /// - /// ```rust - /// use scale_value::Value; - /// use serde::{ Serialize, Deserialize }; - /// - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum Foo { - /// A { is_valid: bool, name: String }, - /// B(u8, bool) - /// } - /// - /// let value1 = Value::named_variant("A", [ - /// ("name", Value::string("James")), - /// ("is_valid", Value::bool(true)), - /// ]); - /// let foo1: Foo = scale_value::serde::from_value(value1).unwrap(); - /// assert_eq!(foo1, Foo::A { is_valid: true, name: "James".into() }); - /// - /// let value2 = Value::unnamed_variant("B", [ - /// Value::u128(123), - /// Value::bool(true), - /// ]); - /// let foo2: Foo = scale_value::serde::from_value(value2).unwrap(); - /// assert_eq!(foo2, Foo::B(123, true)); - /// ``` - pub fn from_value<'de, Ctx, T: serde::Deserialize<'de>>( - value: crate::Value, - ) -> Result { - T::deserialize(value) - } + /// Attempt to convert a [`crate::Value`] into another type via serde. + /// + /// # Examples + /// + /// Use serde to convert a value into a built-in type: + /// + /// ```rust + /// use scale_value::Value; + /// + /// let value = Value::unnamed_composite(vec![ + /// Value::u128(1), + /// Value::u128(2), + /// Value::u128(3), + /// ]); + /// + /// let arr: [u8; 3] = scale_value::serde::from_value(value).unwrap(); + /// ``` + /// + /// Converting values to a custom type: + /// + /// ```rust + /// use scale_value::Value; + /// use serde::{ Serialize, Deserialize }; + /// + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum Foo { + /// A { is_valid: bool, name: String }, + /// B(u8, bool) + /// } + /// + /// let value1 = Value::named_variant("A", [ + /// ("name", Value::string("James")), + /// ("is_valid", Value::bool(true)), + /// ]); + /// let foo1: Foo = scale_value::serde::from_value(value1).unwrap(); + /// assert_eq!(foo1, Foo::A { is_valid: true, name: "James".into() }); + /// + /// let value2 = Value::unnamed_variant("B", [ + /// Value::u128(123), + /// Value::bool(true), + /// ]); + /// let foo2: Foo = scale_value::serde::from_value(value2).unwrap(); + /// assert_eq!(foo2, Foo::B(123, true)); + /// ``` + pub fn from_value<'de, Ctx, T: serde::Deserialize<'de>>( + value: crate::Value, + ) -> Result { + T::deserialize(value) + } - /// Attempt to convert some type into a [`crate::Value`] via serde. - /// - /// # Examples - /// - /// Convert a built-in array of values into a [`crate::Value`]: - /// - /// ```rust - /// use scale_value::Value; - /// - /// let arr = [1u8, 2u8, 3u8]; - /// - /// let val = scale_value::serde::to_value(arr).unwrap(); - /// assert_eq!(val, Value::unnamed_composite([ - /// Value::u128(1), - /// Value::u128(2), - /// Value::u128(3), - /// ])); - /// ``` - /// - /// Converting some custom type to a [`crate::Value`]: - /// - /// ```rust - /// use scale_value::Value; - /// use serde::{ Serialize, Deserialize }; - /// - /// #[derive(Serialize, Deserialize, PartialEq, Debug)] - /// enum Foo { - /// A { is_valid: bool, name: String }, - /// B(u8, bool) - /// } - /// - /// let foo = Foo::A { is_valid: true, name: "James".into() }; - /// - /// let value = scale_value::serde::to_value(foo).unwrap(); - /// assert_eq!(value, Value::named_variant("A", [ - /// ("is_valid", Value::bool(true)), - /// ("name", Value::string("James")), - /// ])); - /// ``` - pub fn to_value(ty: T) -> Result, SerializerError> { - ty.serialize(ValueSerializer) - } + /// Attempt to convert some type into a [`crate::Value`] via serde. + /// + /// # Examples + /// + /// Convert a built-in array of values into a [`crate::Value`]: + /// + /// ```rust + /// use scale_value::Value; + /// + /// let arr = [1u8, 2u8, 3u8]; + /// + /// let val = scale_value::serde::to_value(arr).unwrap(); + /// assert_eq!(val, Value::unnamed_composite([ + /// Value::u128(1), + /// Value::u128(2), + /// Value::u128(3), + /// ])); + /// ``` + /// + /// Converting some custom type to a [`crate::Value`]: + /// + /// ```rust + /// use scale_value::Value; + /// use serde::{ Serialize, Deserialize }; + /// + /// #[derive(Serialize, Deserialize, PartialEq, Debug)] + /// enum Foo { + /// A { is_valid: bool, name: String }, + /// B(u8, bool) + /// } + /// + /// let foo = Foo::A { is_valid: true, name: "James".into() }; + /// + /// let value = scale_value::serde::to_value(foo).unwrap(); + /// assert_eq!(value, Value::named_variant("A", [ + /// ("is_valid", Value::bool(true)), + /// ("name", Value::string("James")), + /// ])); + /// ``` + pub fn to_value(ty: T) -> Result, SerializerError> { + ty.serialize(ValueSerializer) + } } /// Encoding and decoding SCALE bytes into a [`crate::Value`]. /// /// # Exmaple /// -/// Given some known metadata type ID, encode and desome some [`crate::Value`] +/// Given some known metadata type ID, encode and decode some [`crate::Value`] /// to SCALE bytes. /// /// ```rust @@ -181,55 +185,115 @@ pub mod serde { /// assert_eq!(value, new_value.remove_context()); /// ``` pub mod scale { - pub use crate::scale_impls::{DecodeError, EncodeError, TypeId}; - pub use scale_info::PortableRegistry; + pub use crate::scale_impls::{DecodeError, TypeId}; + use scale_encode::EncodeAsType; + pub use scale_encode::Error as EncodeError; + pub use scale_info::PortableRegistry; - /// Attempt to decode some SCALE encoded bytes into a value, by providing a pointer - /// to the bytes (which will be moved forwards as bytes are used in the decoding), - /// a type ID, and a type registry from which we'll look up the relevant type information. - pub fn decode_as_type>( - data: &mut &[u8], - ty_id: Id, - types: &PortableRegistry, - ) -> Result, DecodeError> { - crate::scale_impls::decode_value_as_type(data, ty_id, types) - } + /// Attempt to decode some SCALE encoded bytes into a value, by providing a pointer + /// to the bytes (which will be moved forwards as bytes are used in the decoding), + /// a type ID, and a type registry from which we'll look up the relevant type information. + pub fn decode_as_type( + data: &mut &[u8], + ty_id: TypeId, + types: &PortableRegistry, + ) -> Result, DecodeError> { + crate::scale_impls::decode_value_as_type(data, ty_id, types) + } - /// Attempt to encode some [`crate::Value`] into SCALE bytes, by providing a pointer to the - /// type ID that we'd like to encode it as, a type registry from which we'll look - /// up the relevant type information, and a buffer to encode the bytes to. - pub fn encode_as_type>( - value: &crate::Value, - ty_id: Id, - types: &PortableRegistry, - buf: &mut Vec, - ) -> Result<(), EncodeError> { - crate::scale_impls::encode_value_as_type(value, ty_id, types, buf) - } + /// Attempt to encode some [`crate::Value`] into SCALE bytes, by providing a pointer to the + /// type ID that we'd like to encode it as, a type registry from which we'll look + /// up the relevant type information, and a buffer to encode the bytes to. + pub fn encode_as_type( + value: &crate::Value, + ty_id: TypeId, + types: &PortableRegistry, + buf: &mut Vec, + ) -> Result<(), EncodeError> { + value.encode_as_type_to(ty_id, types, buf) + } } /// Converting a [`crate::Value`] to or from strings. pub mod stringify { - #[cfg(feature = "from_string")] - pub use crate::string_impls::ParseError; + #[cfg(feature = "from_string")] + pub use crate::string_impls::ParseError; - /// Attempt to parse a string into a [`crate::Value<()>`], returning a tuple - /// consisting of a result (either the value or a [`ParseError`] containing - /// location and error information) and the remainder of the string that wasn't - /// parsed. - #[cfg(feature = "from_string")] - pub fn from_str(s: &str) -> (Result, ParseError>, &str) { - crate::string_impls::from_str(s) - } + /// Attempt to parse a string into a [`crate::Value<()>`], returning a tuple + /// consisting of a result (either the value or a [`ParseError`] containing + /// location and error information) and the remainder of the string that wasn't + /// parsed. + /// + /// # Examples + /// + /// ```rust + /// use scale_value::Value; + /// + /// fn to_value(str: &str) -> Value { + /// scale_value::stringify::from_str(str).0.unwrap() + /// } + /// + /// // Primitive values: + /// assert_eq!(to_value("1"), Value::u128(1)); + /// assert_eq!(to_value("-1"), Value::i128(-1)); + /// assert_eq!(to_value("true"), Value::bool(true)); + /// assert_eq!(to_value("'a'"), Value::char('a')); + /// assert_eq!(to_value("\"hi\""), Value::string("hi")); + /// + /// // Named composite values look a bit like rust structs: + /// let value = to_value("{ a: true, b: \"hello\" }"); + /// assert_eq!( + /// value, + /// Value::named_composite(vec![ + /// ("a", Value::bool(true)), + /// ("b", Value::string("hello")) + /// ]) + /// ); + /// + /// // Unnamed composite values look a bit like rust tuples: + /// let value = to_value("(true, \"hello\")"); + /// assert_eq!( + /// value, + /// Value::unnamed_composite(vec![ + /// Value::bool(true), + /// Value::string("hello") + /// ]) + /// ); + /// + /// // Variant values (named or unnamed) are just the above with a variant name + /// // prefixed: + /// let value = to_value("MyVariant { a: true, b: \"hello\" }"); + /// assert_eq!( + /// value, + /// Value::named_variant( + /// "MyVariant", + /// vec![ + /// ("a", Value::bool(true)), + /// ("b", Value::string("hello")) + /// ] + /// ) + /// ); + /// + /// // Bit sequences can be encoded from unnamed composites, but we have a + /// // compact syntax for them too: + /// assert_eq!( + /// to_value("<0101>"), + /// Value::bit_sequence(scale_bits::Bits::from_iter([false, true, false, true])) + /// ); + /// ``` + #[cfg(feature = "from_string")] + pub fn from_str(s: &str) -> (Result, ParseError>, &str) { + crate::string_impls::from_str(s) + } - /// Identical to calling `to_string()` on the [`crate::Value`], but here just - /// to make it a little more obvious that this is the inverse of [`from_str`]. - /// - /// # Panics - /// - /// Panics if a `Primitive::U256`/`Primitive::I256` are a part of the value, - /// since we cannot properly format and parse those at the moment. - pub fn to_string(v: &crate::Value) -> String { - v.to_string() - } + /// Identical to calling `to_string()` on the [`crate::Value`], but here just + /// to make it a little more obvious that this is the inverse of [`from_str`]. + /// + /// # Panics + /// + /// Panics if a `Primitive::U256`/`Primitive::I256` are a part of the value, + /// since we cannot properly format and parse those at the moment. + pub fn to_string(v: &crate::Value) -> String { + v.to_string() + } } diff --git a/src/scale_impls/decode.rs b/src/scale_impls/decode.rs index 3852fcd..50ce12a 100644 --- a/src/scale_impls/decode.rs +++ b/src/scale_impls/decode.rs @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::type_id::TypeId; +use super::TypeId; use crate::value::{Composite, Primitive, Value, ValueDef, Variant}; use scale_info::PortableRegistry; @@ -23,424 +23,473 @@ pub use scale_decode::visitor::DecodeError; /// 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_as_type>( - data: &mut &[u8], - ty_id: Id, - types: &PortableRegistry, +pub fn decode_value_as_type( + data: &mut &[u8], + ty_id: TypeId, + types: &PortableRegistry, ) -> Result, DecodeError> { - scale_decode::decode(data, ty_id.into().id(), types, ValueVisitor) + scale_decode::visitor::decode_with_visitor(data, ty_id, types, DecodeValueVisitor) } // Sequences, Tuples and Arrays all have the same methods, so decode them in the same way: macro_rules! to_unnamed_composite { - ($value:ident, $type_id:ident) => {{ - let mut vals = Vec::with_capacity($value.len()); - while let Some(val) = $value.decode_item(ValueVisitor)? { - vals.push(val); - } - Ok(Value { value: ValueDef::Composite(Composite::Unnamed(vals)), context: $type_id.into() }) - }}; + ($value:ident, $type_id:ident) => {{ + let mut vals = Vec::with_capacity($value.remaining()); + while let Some(val) = $value.decode_item(DecodeValueVisitor) { + let val = val?; + vals.push(val); + } + Ok(Value { value: ValueDef::Composite(Composite::Unnamed(vals)), context: $type_id.0 }) + }}; } -struct ValueVisitor; - -impl scale_decode::visitor::Visitor for ValueVisitor { - type Value = Value; - type Error = DecodeError; - - fn visit_bool( - self, - value: bool, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value::bool(value).map_context(|_| type_id.into())) - } - fn visit_char( - self, - value: char, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value::char(value).map_context(|_| type_id.into())) - } - fn visit_u8( - self, - value: u8, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_u128(value as u128, type_id) - } - fn visit_u16( - self, - value: u16, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_u128(value as u128, type_id) - } - fn visit_u32( - self, - value: u32, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_u128(value as u128, type_id) - } - fn visit_u64( - self, - value: u64, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_u128(value as u128, type_id) - } - fn visit_u128( - self, - value: u128, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value::u128(value as u128).map_context(|_| type_id.into())) - } - fn visit_u256( - self, - value: &[u8; 32], - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value { value: ValueDef::Primitive(Primitive::U256(*value)), context: type_id.into() }) - } - fn visit_i8( - self, - value: i8, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_i128(value as i128, type_id) - } - fn visit_i16( - self, - value: i16, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_i128(value as i128, type_id) - } - fn visit_i32( - self, - value: i32, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_i128(value as i128, type_id) - } - fn visit_i64( - self, - value: i64, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - self.visit_i128(value as i128, type_id) - } - fn visit_i128( - self, - value: i128, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value::i128(value as i128).map_context(|_| type_id.into())) - } - fn visit_i256( - self, - value: &[u8; 32], - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value { value: ValueDef::Primitive(Primitive::U256(*value)), context: type_id.into() }) - } - fn visit_sequence( - self, - value: &mut scale_decode::visitor::Sequence, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - to_unnamed_composite!(value, type_id) - } - fn visit_tuple( - self, - value: &mut scale_decode::visitor::Tuple, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - to_unnamed_composite!(value, type_id) - } - fn visit_array( - self, - value: &mut scale_decode::visitor::Array, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - to_unnamed_composite!(value, type_id) - } - fn visit_bitsequence( - self, - value: &mut scale_decode::visitor::BitSequence, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - let bits: Result<_, _> = value.decode()?.collect(); - Ok(Value { value: ValueDef::BitSequence(bits?), context: type_id.into() }) - } - fn visit_str( - self, - value: scale_decode::visitor::Str, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value::string(value.as_str()?).map_context(|_| type_id.into())) - } - fn visit_variant( - self, - value: &mut scale_decode::visitor::Variant, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - let values = visit_composite(value.fields())?; - Ok(Value { - value: ValueDef::Variant(Variant { name: value.name().to_owned(), values }), - context: type_id.into(), - }) - } - fn visit_composite( - self, - value: &mut scale_decode::visitor::Composite, - type_id: scale_decode::visitor::TypeId, - ) -> Result { - Ok(Value { value: ValueDef::Composite(visit_composite(value)?), context: type_id.into() }) - } +// We can't implement this on `Value` because we have no TypeId to assign to the value. +impl scale_decode::DecodeAsFields for Composite { + fn decode_as_fields( + input: &mut &[u8], + fields: &[scale_decode::PortableField], + types: &PortableRegistry, + ) -> Result { + // Build a Composite type to pass to a one-off visitor: + let path = Default::default(); + let mut composite = + scale_decode::visitor::types::Composite::new(input, &path, fields, types); + // Decode into a Composite value from this: + let val = visit_composite(&mut composite); + // Consume remaining bytes and update input cursor: + composite.skip_decoding()?; + *input = composite.bytes_from_undecoded(); + + val.map_err(From::from) + } +} + +/// A [`scale_decode::Visitor`] implementation for decoding into [`Value`]s. +pub struct DecodeValueVisitor; + +impl scale_decode::IntoVisitor for Value { + type Visitor = DecodeValueVisitor; + fn into_visitor() -> Self::Visitor { + DecodeValueVisitor + } +} + +impl scale_decode::visitor::Visitor for DecodeValueVisitor { + type Value<'scale, 'info> = Value; + type Error = DecodeError; + + fn visit_bool<'scale, 'info>( + self, + value: bool, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value::bool(value).map_context(|_| type_id.0)) + } + fn visit_char<'scale, 'info>( + self, + value: char, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value::char(value).map_context(|_| type_id.0)) + } + fn visit_u8<'scale, 'info>( + self, + value: u8, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_u128(value as u128, type_id) + } + fn visit_u16<'scale, 'info>( + self, + value: u16, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_u128(value as u128, type_id) + } + fn visit_u32<'scale, 'info>( + self, + value: u32, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_u128(value as u128, type_id) + } + fn visit_u64<'scale, 'info>( + self, + value: u64, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_u128(value as u128, type_id) + } + fn visit_u128<'scale, 'info>( + self, + value: u128, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value::u128(value).map_context(|_| type_id.0)) + } + fn visit_u256<'info>( + self, + value: &'_ [u8; 32], + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value { value: ValueDef::Primitive(Primitive::U256(*value)), context: type_id.0 }) + } + fn visit_i8<'scale, 'info>( + self, + value: i8, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_i128(value as i128, type_id) + } + fn visit_i16<'scale, 'info>( + self, + value: i16, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_i128(value as i128, type_id) + } + fn visit_i32<'scale, 'info>( + self, + value: i32, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_i128(value as i128, type_id) + } + fn visit_i64<'scale, 'info>( + self, + value: i64, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + self.visit_i128(value as i128, type_id) + } + fn visit_i128<'scale, 'info>( + self, + value: i128, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value::i128(value).map_context(|_| type_id.0)) + } + fn visit_i256<'info>( + self, + value: &'_ [u8; 32], + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value { value: ValueDef::Primitive(Primitive::U256(*value)), context: type_id.0 }) + } + fn visit_sequence<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::Sequence<'scale, 'info>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + to_unnamed_composite!(value, type_id) + } + fn visit_tuple<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::Tuple<'scale, 'info>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + to_unnamed_composite!(value, type_id) + } + fn visit_array<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::Array<'scale, 'info>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + to_unnamed_composite!(value, type_id) + } + fn visit_bitsequence<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::BitSequence<'scale>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + let bits: Result<_, _> = value.decode()?.collect(); + Ok(Value { value: ValueDef::BitSequence(bits?), context: type_id.0 }) + } + fn visit_str<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::Str<'scale>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value::string(value.as_str()?).map_context(|_| type_id.0)) + } + fn visit_variant<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::Variant<'scale, 'info>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + let values = visit_composite(value.fields())?; + Ok(Value { + value: ValueDef::Variant(Variant { name: value.name().to_owned(), values }), + context: type_id.0, + }) + } + fn visit_composite<'scale, 'info>( + self, + value: &mut scale_decode::visitor::types::Composite<'scale, 'info>, + type_id: scale_decode::visitor::TypeId, + ) -> Result, Self::Error> { + Ok(Value { value: ValueDef::Composite(visit_composite(value)?), context: type_id.0 }) + } } /// Extract a named/unnamed Composite type out of scale_decode's Composite. fn visit_composite( - value: &mut scale_decode::visitor::Composite, + value: &mut scale_decode::visitor::types::Composite, ) -> Result, DecodeError> { - let len = value.fields().len(); - let named = value.fields().get(0).map(|f| f.name().is_some()).unwrap_or(false); - - if named { - let mut vals = Vec::with_capacity(len); - while let Some((name, v)) = value.decode_item_with_name(ValueVisitor)? { - vals.push((name.to_owned(), v)); - } - Ok(Composite::Named(vals)) - } else { - let mut vals = Vec::with_capacity(len); - while let Some(v) = value.decode_item(ValueVisitor)? { - vals.push(v); - } - Ok(Composite::Unnamed(vals)) - } + let len = value.fields().len(); + // if no fields, we'll always assume unnamed. + let named = len > 0 && !value.has_unnamed_fields(); + + if named { + let mut vals = Vec::with_capacity(len); + let mut name = value.peek_name(); + while let Some(v) = value.decode_item(DecodeValueVisitor) { + let v = v?; + vals.push((name.expect("all fields should be named; we have checked").to_owned(), v)); + // get the next field name now we've decoded one. + name = value.peek_name(); + } + Ok(Composite::Named(vals)) + } else { + let mut vals = Vec::with_capacity(len); + while let Some(v) = value.decode_item(DecodeValueVisitor) { + let v = v?; + vals.push(v); + } + Ok(Composite::Unnamed(vals)) + } } #[cfg(test)] mod test { - use super::*; - use codec::{Compact, 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_as_type(encoded, id, &portable_registry).expect("decoding failed"); - // Is the decoded value what we expected? - assert_eq!(val.remove_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::string("hello")); - encode_decode_check( - "hello".to_string(), // String or &str (above) decode OK - Value::string("hello"), - ); - encode_decode_check(123u8, Value::u128(123)); - encode_decode_check(123u16, Value::u128(123)); - encode_decode_check(123u32, Value::u128(123)); - encode_decode_check(123u64, Value::u128(123)); - encode_decode_check(123u128, Value::u128(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::i128(123)); - encode_decode_check(123i16, Value::i128(123)); - encode_decode_check(123i32, Value::i128(123)); - encode_decode_check(123i64, Value::i128(123)); - encode_decode_check(123i128, Value::i128(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::u128(123)); - encode_decode_check(Compact(123u16), Value::u128(123)); - encode_decode_check(Compact(123u32), Value::u128(123)); - encode_decode_check(Compact(123u64), Value::u128(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 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::u128(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 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::u128(123)); - } - - #[test] - fn decode_sequence_array_tuple_types() { - encode_decode_check( - vec![1i32, 2, 3], - Value::unnamed_composite(vec![Value::i128(1), Value::i128(2), Value::i128(3)]), - ); - encode_decode_check( - [1i32, 2, 3], // compile-time length known - Value::unnamed_composite(vec![Value::i128(1), Value::i128(2), Value::i128(3)]), - ); - encode_decode_check( - (1i32, true, 123456u128), - Value::unnamed_composite(vec![Value::i128(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::unnamed_variant("Foo", vec![Value::bool(true)]), - ); - encode_decode_check( - MyEnum::Bar { hi: "hello".to_string(), other: 123 }, - Value::named_variant( - "Bar", - vec![ - ("hi".to_string(), Value::string("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::string("James".to_string()), - Value::unnamed_composite(vec![Value::u128(1), Value::u128(2), Value::u128(3)]), - ]), - ); - encode_decode_check( - Named { is_valid: true, name: "James".into(), bytes: vec![1, 2, 3] }, - Value::named_composite(vec![ - ("is_valid", Value::bool(true)), - ("name", Value::string("James".to_string())), - ( - "bytes", - Value::unnamed_composite(vec![Value::u128(1), Value::u128(2), Value::u128(3)]), - ), - ]), - ); - } - - #[test] - fn decode_bit_sequence() { - use scale_bits::bits; - - // scale-decode already tests this more thoroughly: - encode_decode_check(bits![0, 1, 1, 0, 1, 0], Value::bit_sequence(bits![0, 1, 1, 0, 1, 0])); - } + use super::*; + use codec::{Compact, 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.id(), 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_as_type(encoded, id, &portable_registry).expect("decoding failed"); + // Is the decoded value what we expected? + assert_eq!(val.remove_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::string("hello")); + encode_decode_check( + "hello".to_string(), // String or &str (above) decode OK + Value::string("hello"), + ); + encode_decode_check(123u8, Value::u128(123)); + encode_decode_check(123u16, Value::u128(123)); + encode_decode_check(123u32, Value::u128(123)); + encode_decode_check(123u64, Value::u128(123)); + encode_decode_check(123u128, Value::u128(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::i128(123)); + encode_decode_check(123i16, Value::i128(123)); + encode_decode_check(123i32, Value::i128(123)); + encode_decode_check(123i64, Value::i128(123)); + encode_decode_check(123i128, Value::i128(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::u128(123)); + encode_decode_check(Compact(123u16), Value::u128(123)); + encode_decode_check(Compact(123u32), Value::u128(123)); + encode_decode_check(Compact(123u64), Value::u128(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 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::u128(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 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::u128(123)); + } + + #[test] + fn decode_sequence_array_tuple_types() { + encode_decode_check( + vec![1i32, 2, 3], + Value::unnamed_composite(vec![Value::i128(1), Value::i128(2), Value::i128(3)]), + ); + encode_decode_check( + [1i32, 2, 3], // compile-time length known + Value::unnamed_composite(vec![Value::i128(1), Value::i128(2), Value::i128(3)]), + ); + encode_decode_check( + (1i32, true, 123456u128), + Value::unnamed_composite(vec![Value::i128(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::unnamed_variant("Foo", vec![Value::bool(true)]), + ); + encode_decode_check( + MyEnum::Bar { hi: "hello".to_string(), other: 123 }, + Value::named_variant( + "Bar", + vec![ + ("hi".to_string(), Value::string("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::string("James".to_string()), + Value::unnamed_composite(vec![Value::u128(1), Value::u128(2), Value::u128(3)]), + ]), + ); + encode_decode_check( + Named { is_valid: true, name: "James".into(), bytes: vec![1, 2, 3] }, + Value::named_composite(vec![ + ("is_valid", Value::bool(true)), + ("name", Value::string("James".to_string())), + ( + "bytes", + Value::unnamed_composite(vec![Value::u128(1), Value::u128(2), Value::u128(3)]), + ), + ]), + ); + } + + #[test] + fn decoding_zero_length_composites_always_unnamed() { + // The scale-info repr is just a composite, so we don't really track + // whether the thing was named or not. either Value will convert back ok anyway. + #[derive(Encode, scale_info::TypeInfo)] + struct Named {} + #[derive(Encode, scale_info::TypeInfo)] + struct Unnamed(); + + encode_decode_check(Unnamed(), Value::unnamed_composite(vec![])); + encode_decode_check(Named {}, Value::unnamed_composite(vec![])); + } + + #[test] + fn decode_bit_sequence() { + use scale_bits::bits; + + // scale-decode already tests this more thoroughly: + encode_decode_check(bits![0, 1, 1, 0, 1, 0], Value::bit_sequence(bits![0, 1, 1, 0, 1, 0])); + } } diff --git a/src/scale_impls/encode.rs b/src/scale_impls/encode.rs index 388f7f1..d30fc14 100644 --- a/src/scale_impls/encode.rs +++ b/src/scale_impls/encode.rs @@ -13,793 +13,531 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{type_id::TypeId, ScaleTypeDef as TypeDef}; use crate::value::{Composite, Primitive, Value, ValueDef, Variant}; use codec::{Compact, Encode}; -use scale_info::{ - form::PortableForm, Field, PortableRegistry, TypeDefArray, TypeDefBitSequence, TypeDefCompact, - TypeDefComposite, TypeDefPrimitive, TypeDefSequence, TypeDefTuple, TypeDefVariant, -}; - -/// An error encoding a [`Value`] into SCALE bytes. -#[derive(Debug, Clone, thiserror::Error, PartialEq, Eq)] -pub enum EncodeError { - /// The composite type we're trying to encode is the wrong length for the type we're trying to encode it into. - #[error("Composite type is the wrong length; expected length is {expected_len}, but got {}", actual.len())] - CompositeIsWrongLength { - /// The composite value that is the wrong length. - actual: Composite, - /// The type we're trying to encode it into. - expected: TypeId, - /// The length we're expecting our composite type to be to encode properly. - expected_len: usize, - }, - /// The variant we're trying to encode was not found in the type we're encoding into. - #[error("Variant {} was not found", actual.name)] - VariantNotFound { - /// The variant type we're trying to encode. - actual: Variant, - /// The type we're trying to encode it into. - expected: TypeId, - }, - /// The variant or composite field we're trying to encode is not present in the type we're encoding into. - #[error("The field {missing_field_name} is present on the type we're trying to encode to but hasn't been provided")] - CompositeFieldIsMissing { - /// The name of the composite field we can't find. - missing_field_name: String, - /// The type we're trying to encode this into. - expected: TypeId, - }, - /// The type we're trying to encode into cannot be found in the type registry provided. - #[error("Cannot find type with ID {0}")] - TypeIdNotFound(TypeId), - /// The [`Value`] type we're trying to encode is not the correct shape for the type we're trying to encode it into. - #[error("Value shape is wrong; expected type ID {expected}, but got value {actual:?}, which could not be coerced into it")] - WrongShape { - /// The value we're trying to encode. - actual: Value, - /// The type we're trying to encode it into. - expected: TypeId, - }, - /// There was an error trying to encode the bit sequence provided. - #[error("Cannot encode bit sequence: {0}")] - BitSequenceError(BitSequenceError), - /// The type ID given is supposed to be compact encoded, but this is not possible to do automatically. - #[error("The type {0} cannot be compact encoded")] - CannotCompactEncode(TypeId), +use scale_bits::Bits; +use scale_encode::error::ErrorKind; +use scale_encode::{error::Kind, EncodeAsFields, EncodeAsType, Error}; +use scale_encode::{Composite as EncodeComposite, Variant as EncodeVariant}; +use scale_info::form::PortableForm; +use scale_info::{PortableRegistry, TypeDef, TypeDefBitSequence}; + +pub use scale_encode::Error as EncodeError; + +impl EncodeAsType for Value { + fn encode_as_type_to( + &self, + type_id: u32, + types: &PortableRegistry, + out: &mut Vec, + ) -> Result<(), Error> { + match &self.value { + ValueDef::Composite(val) => encode_composite(val, type_id, types, out), + ValueDef::Variant(val) => encode_variant(val, type_id, types, out), + ValueDef::Primitive(val) => encode_primitive(val, type_id, types, out), + ValueDef::BitSequence(val) => encode_bitsequence(val, type_id, types, out), + } + } } -/// An error that can occur attempting to encode a bit sequence. -pub type BitSequenceError = scale_bits::scale::format::FromMetadataError; - -/// Attempt to SCALE Encode a Value according to the [`TypeId`] and -/// [`PortableRegistry`] provided. -pub fn encode_value_as_type>( - value: &Value, - ty_id: Id, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - let ty_id = ty_id.into(); - let ty = types.resolve(ty_id.id()).ok_or(EncodeError::TypeIdNotFound(ty_id))?; - - match ty.type_def() { - TypeDef::Composite(inner) => encode_composite_value(value, ty_id, inner, types, bytes), - TypeDef::Sequence(inner) => encode_sequence_value(value, ty_id, inner, types, bytes), - TypeDef::Array(inner) => encode_array_value(value, ty_id, inner, types, bytes), - TypeDef::Tuple(inner) => encode_tuple_value(value, ty_id, inner, types, bytes), - TypeDef::Variant(inner) => encode_variant_value(value, ty_id, inner, types, bytes), - TypeDef::Primitive(inner) => encode_primitive_value(value, ty_id, inner, bytes), - TypeDef::Compact(inner) => encode_compact_value(value, ty_id, inner, types, bytes), - TypeDef::BitSequence(inner) => encode_bitsequence_value(value, ty_id, inner, types, bytes), - }?; - - Ok(()) +impl EncodeAsFields for Value { + fn encode_as_fields_to( + &self, + fields: &[scale_encode::PortableField], + types: &PortableRegistry, + out: &mut Vec, + ) -> Result<(), Error> { + match &self.value { + ValueDef::Composite(composite) => composite.encode_as_fields_to(fields, types, out), + _ => Err(Error::custom("Cannot encode non-composite Value shape into fields")), + } + } } -fn encode_composite_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefComposite, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - match &value.value { - ValueDef::Composite(composite) => { - if ty.fields().len() == 1 && composite.len() != 1 { - // The composite we've provided doesn't have 1 field; it has many. - // perhaps the type we're encoding to is a wrapper type then; let's - // jump in and try to encode our composite to the contents of it (1 - // field composites are transparent anyway in SCALE terms). - encode_value_as_type(value, ty.fields()[0].ty(), types, bytes) - } else { - encode_composite_fields(composite, ty.fields(), type_id, types, bytes) - } - } - _ => { - if ty.fields().len() == 1 { - // We didn't provide a composite type, but the composite type we're - // aiming for has exactly 1 field. Perhaps it's a wrapper type, so let's - // aim to encode to the contents of it instead (1 field composites are - // transparent anyway in SCALE terms). - encode_value_as_type(value, ty.fields()[0].ty(), types, bytes) - } else { - Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }) - } - } - } +impl EncodeAsFields for Composite { + fn encode_as_fields_to( + &self, + fields: &[scale_encode::PortableField], + types: &PortableRegistry, + out: &mut Vec, + ) -> Result<(), Error> { + match self { + Composite::Named(vals) => { + let keyvals = + vals.iter().map(|(key, val)| (Some(&**key), val as &dyn EncodeAsType)); + EncodeComposite(keyvals).encode_as_fields_to(fields, types, out) + } + Composite::Unnamed(vals) => { + let vals = vals.iter().map(|val| (None, val as &dyn EncodeAsType)); + EncodeComposite(vals).encode_as_fields_to(fields, types, out) + } + } + } } -fn encode_sequence_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefSequence, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - match &value.value { - // Let's see whether our composite type is the right length, - // and try to encode each inner value into what the sequence wants. - ValueDef::Composite(c) => { - // Compact encoded length comes first - Compact(c.len() as u64).encode_to(bytes); - let ty = ty.type_param(); - for value in c.values() { - encode_value_as_type(value, ty, types, bytes)?; - } - } - // As a special case, primitive U256/I256s are arrays, and may be compatible - // with the sequence type being asked for, too. - ValueDef::Primitive(Primitive::I256(a) | Primitive::U256(a)) => { - // Compact encoded length comes first - Compact(a.len() as u64).encode_to(bytes); - let ty = ty.type_param(); - for val in a { - if encode_value_as_type(&Value::u128(*val as u128), ty, types, bytes).is_err() { - return Err(EncodeError::WrongShape { - actual: value.clone(), - expected: type_id, - }); - } - } - } - _ => return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }), - }; - Ok(()) +// A scale-value composite type can represent sequences, arrays, composites and tuples. `scale_encode`'s Composite helper +// can't handle encoding to sequences/arrays. However, we can encode safely into sequences here because we can inspect the +// values we have and more safely skip newtype wrappers without also skipping through types that might represent 1-value +// sequences/arrays for instance. +fn encode_composite( + value: &Composite, + type_id: u32, + types: &PortableRegistry, + out: &mut Vec, +) -> Result<(), Error> { + let type_id = find_single_entry_with_same_repr(type_id, types); + let ty = types.resolve(type_id).ok_or_else(|| Error::new(ErrorKind::TypeNotFound(type_id)))?; + + match ty.type_def() { + // Our scale_encode Composite helper can encode to these types without issue: + TypeDef::Tuple(_) | TypeDef::Composite(_) => match value { + Composite::Named(vals) => { + let keyvals = + vals.iter().map(|(key, val)| (Some(&**key), val as &dyn EncodeAsType)); + EncodeComposite(keyvals).encode_as_type_to(type_id, types, out) + } + Composite::Unnamed(vals) => { + let vals = vals.iter().map(|val| (None, val as &dyn EncodeAsType)); + EncodeComposite(vals).encode_as_type_to(type_id, types, out) + } + }, + // For sequence types, let's skip our Value until we hit a Composite type containing + // a non-composite type or more than 1 entry. This is the best candidate we have for a sequence. + TypeDef::Sequence(seq) => { + let seq_ty = seq.type_param().id(); + let value = find_sequence_candidate(value); + + // sequences start with compact encoded length: + Compact(value.len() as u32).encode_to(out); + match value { + Composite::Named(named_vals) => { + for (name, val) in named_vals { + val.encode_as_type_to(seq_ty, types, out) + .map_err(|e| e.at_field(name.to_string()))?; + } + } + Composite::Unnamed(vals) => { + for (idx, val) in vals.iter().enumerate() { + val.encode_as_type_to(seq_ty, types, out).map_err(|e| e.at_idx(idx))?; + } + } + } + Ok(()) + } + // For arrays we can dig into our composite type much like for sequences, but bail + // if the length doesn't align. + TypeDef::Array(array) => { + let arr_ty = array.type_param().id(); + let value = find_sequence_candidate(value); + + if value.len() != array.len() as usize { + return Err(Error::new(ErrorKind::WrongLength { + actual_len: value.len(), + expected_len: array.len() as usize, + })); + } + + for (idx, val) in value.values().enumerate() { + val.encode_as_type_to(arr_ty, types, out).map_err(|e| e.at_idx(idx))?; + } + Ok(()) + } + // Similar to sequence types, we want to find a sequence of values and then try to encode + // them as a bit_sequence. + TypeDef::BitSequence(seq) => { + let value = find_sequence_candidate(value); + encode_vals_to_bitsequence(value.values(), seq, types, out) + } + // For other types, skip our value past a 1-value composite and try again, else error. + _ => { + let mut values = value.values(); + match (values.next(), values.next()) { + // Exactly one value: + (Some(value), None) => value.encode_as_type_to(type_id, types, out), + // Some other number of values: + _ => Err(Error::new(ErrorKind::WrongShape { + actual: Kind::Tuple, + expected: type_id, + })), + } + } + } } -fn encode_array_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefArray, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - match &value.value { - // Let's see whether our composite type is the right length, - // and try to encode each inner value into what the array wants. - ValueDef::Composite(c) => { - let arr_len = ty.len() as usize; - if c.len() != arr_len { - return Err(EncodeError::CompositeIsWrongLength { - actual: c.clone(), - expected: type_id, - expected_len: arr_len, - }); - } - - let ty = ty.type_param(); - for value in c.values() { - encode_value_as_type(value, ty, types, bytes)?; - } - } - // As a special case, primitive U256/I256s are arrays, and may be compatible - // with the array type being asked for, too. - ValueDef::Primitive(Primitive::I256(a) | Primitive::U256(a)) => { - let arr_len = ty.len() as usize; - if a.len() != arr_len { - return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }); - } - - let ty = ty.type_param(); - for val in a { - if encode_value_as_type(&Value::u128(*val as u128), ty, types, bytes).is_err() { - return Err(EncodeError::WrongShape { - actual: value.clone(), - expected: type_id, - }); - } - } - } - _ => return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }), - }; - Ok(()) +// skip into the target type past any newtype wrapper like things: +fn find_single_entry_with_same_repr(type_id: u32, types: &PortableRegistry) -> u32 { + let Some(ty) = types.resolve(type_id) else { + return type_id + }; + match ty.type_def() { + TypeDef::Tuple(tuple) if tuple.fields().len() == 1 => { + find_single_entry_with_same_repr(tuple.fields()[0].id(), types) + } + TypeDef::Composite(composite) if composite.fields().len() == 1 => { + find_single_entry_with_same_repr(composite.fields()[0].ty().id(), types) + } + _ => type_id, + } } -fn encode_tuple_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefTuple, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - match &value.value { - ValueDef::Composite(composite) => { - if composite.len() != ty.fields().len() { - return Err(EncodeError::CompositeIsWrongLength { - actual: composite.clone(), - expected: type_id, - expected_len: ty.fields().len(), - }); - } - // We don't care whether the fields are named or unnamed - // as long as we have the number of them that we expect.. - let field_value_pairs = ty.fields().iter().zip(composite.values()); - for (ty, value) in field_value_pairs { - encode_value_as_type(value, ty, types, bytes)?; - } - Ok(()) - } - _ => { - if ty.fields().len() == 1 { - // A 1-field tuple? try encoding inner content then. - encode_value_as_type(value, ty.fields()[0], types, bytes) - } else { - Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }) - } - } - } +// dig into a composite type and find a composite that is a candidate +// for being encoded into a sequence. +fn find_sequence_candidate(value: &'_ Composite) -> &'_ Composite { + let mut values = value.values(); + match (values.next(), values.next()) { + // A single composite value is found inside: + (Some(Value { value: ValueDef::Composite(inner_composite), .. }), None) => { + find_sequence_candidate(inner_composite) + } + // Anything else? Just return the value passed in: + _ => value, + } } -fn encode_variant_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefVariant, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - let variant = match &value.value { - ValueDef::Variant(variant) => variant, - _ => return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }), - }; - - let variant_type = ty.variants().iter().find(|v| v.name() == &variant.name); - - let variant_type = match variant_type { - None => { - return Err(EncodeError::VariantNotFound { actual: variant.clone(), expected: type_id }) - } - Some(v) => v, - }; - - variant_type.index().encode_to(bytes); - encode_composite_fields(&variant.values, variant_type.fields(), type_id, types, bytes) +// It's likely that people will use a composite to represen bit sequences, +// so support encoding to them in this way too. +fn encode_vals_to_bitsequence<'a, T: 'a>( + vals: impl ExactSizeIterator>, + bits: &TypeDefBitSequence, + types: &PortableRegistry, + out: &mut Vec, +) -> Result<(), Error> { + let format = scale_bits::Format::from_metadata(bits, types).map_err(Error::custom)?; + let mut bools = Vec::with_capacity(vals.len()); + for (idx, value) in vals.enumerate() { + if let Some(v) = value.as_bool() { + // support turning (true, false, true, true, false) into a bit sequence. + bools.push(v); + } else if let Some(v) = value.as_u128() { + // support turning (1, 0, 1, 1, 0) into a bit sequence. + if v == 0 || v == 1 { + bools.push(v == 1) + } else { + return Err(Error::custom( + "Cannot encode non-boolean/0/1 value into a bit sequence entry", + ) + .at_idx(idx)); + } + } else if let Some(v) = value.as_i128() { + // support turning (1, 0, 1, 1, 0) into a bit sequence (if the number's are not unsigned it's still fine). + if v == 0 || v == 1 { + bools.push(v == 1) + } else { + return Err(Error::custom( + "Cannot encode non-boolean/0/1 value into a bit sequence entry", + ) + .at_idx(idx)); + } + } else { + // anything else is an error. + return Err(Error::custom( + "Cannot encode non-boolean/0/1 value into a bit sequence entry", + ) + .at_idx(idx)); + } + } + + scale_bits::encode_using_format_to(bools.into_iter(), format, out); + Ok(()) } -fn encode_composite_fields( - composite: &Composite, - fields: &[Field], - type_id: TypeId, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - if fields.len() != composite.len() { - return Err(EncodeError::CompositeIsWrongLength { - actual: composite.clone(), - expected: type_id, - expected_len: fields.len(), - }); - } - - // 0 length? Nothing more to do! - if composite.is_empty() { - return Ok(()); - } - - // Does the type we're encoding to have named fields or not? - let is_named = fields[0].name().is_some(); - - match (composite, is_named) { - // If we provide named fields, and named fields are present on the target - // type, then we encode according to the names. - (Composite::Named(values), true) => { - // Match up named values with those of the type we're encoding to. - for field in fields.iter() { - let field_name = field.name().expect("field should be named; checked above"); - let value = values.iter().find(|(n, _)| field_name == n).map(|(_, value)| value); - - match value { - Some(value) => { - encode_value_as_type(value, field.ty(), types, bytes)?; - } - None => { - return Err(EncodeError::CompositeFieldIsMissing { - expected: type_id, - missing_field_name: field_name.clone(), - }) - } - } - } - Ok(()) - } - // If we provide named fields, and the target is unnamed fields, we'll just - // try to line them up in the order that they were given. - (Composite::Named(values), false) => { - for (field, (_name, value)) in fields.iter().zip(values) { - encode_value_as_type(value, field.ty(), types, bytes)?; - } - Ok(()) - } - // If we provide unnamed fields, we don't care whether the target fields are - // named or not; we'll just line them up. - (Composite::Unnamed(values), _) => { - for (field, value) in fields.iter().zip(values) { - encode_value_as_type(value, field.ty(), types, bytes)?; - } - Ok(()) - } - } +fn encode_variant( + value: &Variant, + type_id: u32, + types: &PortableRegistry, + out: &mut Vec, +) -> Result<(), Error> { + match &value.values { + Composite::Named(vals) => { + let keyvals = vals.iter().map(|(key, val)| (Some(&**key), val as &dyn EncodeAsType)); + EncodeVariant { name: &value.name, fields: EncodeComposite(keyvals) } + .encode_as_type_to(type_id, types, out) + } + Composite::Unnamed(vals) => { + let vals = vals.iter().map(|val| (None, val as &dyn EncodeAsType)); + EncodeVariant { name: &value.name, fields: EncodeComposite(vals) } + .encode_as_type_to(type_id, types, out) + } + } } -// Attempt to convert a given primitive value into the integer type -// required, failing with an appropriate EncodeValueError if not successful. -macro_rules! primitive_to_integer { - ($id:ident, $prim:ident, $value:expr => $ty:ident) => {{ - macro_rules! err { - () => { - EncodeError::WrongShape { actual: $value.clone(), expected: $id } - }; - } - let out: Result<$ty, _> = match $prim { - Primitive::U128(v) => v.clone().try_into().map_err(|_| err!()), - Primitive::I128(v) => v.clone().try_into().map_err(|_| err!()), - // Treat chars as u32s to mirror what we do for decoding: - Primitive::Char(v) => (v.clone() as u32).try_into().map_err(|_| err!()), - _ => Err(err!()), - }; - out - }}; +fn encode_primitive( + value: &Primitive, + type_id: u32, + types: &PortableRegistry, + bytes: &mut Vec, +) -> Result<(), Error> { + match value { + Primitive::Bool(val) => val.encode_as_type_to(type_id, types, bytes), + Primitive::Char(val) => val.encode_as_type_to(type_id, types, bytes), + Primitive::String(val) => val.encode_as_type_to(type_id, types, bytes), + Primitive::U128(val) => val.encode_as_type_to(type_id, types, bytes), + Primitive::I128(val) => val.encode_as_type_to(type_id, types, bytes), + Primitive::U256(val) => val.encode_as_type_to(type_id, types, bytes), + Primitive::I256(val) => val.encode_as_type_to(type_id, types, bytes), + } } -fn encode_primitive_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefPrimitive, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - let primitive = match &value.value { - ValueDef::Primitive(primitive) => primitive, - _ => return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }), - }; - - // Attempt to encode our value type into the expected shape. - match (ty, primitive) { - (TypeDefPrimitive::Bool, Primitive::Bool(bool)) => { - bool.encode_to(bytes); - } - (TypeDefPrimitive::Char, Primitive::Char(c)) => { - // Treat chars as u32's - (*c as u32).encode_to(bytes); - } - (TypeDefPrimitive::Str, Primitive::String(s)) => { - s.encode_to(bytes); - } - (TypeDefPrimitive::I256, Primitive::I256(a)) => { - a.encode_to(bytes); - } - (TypeDefPrimitive::U256, Primitive::U256(a)) => { - a.encode_to(bytes); - } - (TypeDefPrimitive::U8, primitive) => { - primitive_to_integer!(type_id, primitive, value => u8)?.encode_to(bytes); - } - (TypeDefPrimitive::U16, primitive) => { - primitive_to_integer!(type_id, primitive, value => u16)?.encode_to(bytes); - } - (TypeDefPrimitive::U32, primitive) => { - primitive_to_integer!(type_id, primitive, value => u32)?.encode_to(bytes); - } - (TypeDefPrimitive::U64, primitive) => { - primitive_to_integer!(type_id, primitive, value => u64)?.encode_to(bytes); - } - (TypeDefPrimitive::U128, primitive) => { - primitive_to_integer!(type_id, primitive, value => u128)?.encode_to(bytes); - } - (TypeDefPrimitive::I8, primitive) => { - primitive_to_integer!(type_id, primitive, value => i8)?.encode_to(bytes); - } - (TypeDefPrimitive::I16, primitive) => { - primitive_to_integer!(type_id, primitive, value => i16)?.encode_to(bytes); - } - (TypeDefPrimitive::I32, primitive) => { - primitive_to_integer!(type_id, primitive, value => i32)?.encode_to(bytes); - } - (TypeDefPrimitive::I64, primitive) => { - primitive_to_integer!(type_id, primitive, value => i64)?.encode_to(bytes); - } - (TypeDefPrimitive::I128, primitive) => { - primitive_to_integer!(type_id, primitive, value => i128)?.encode_to(bytes); - } - _ => { - return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }); - } - } - Ok(()) -} - -fn encode_compact_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefCompact, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - // Types that are compact encodable: - enum CompactTy { - U8, - U16, - U32, - U64, - U128, - } - - // Resolve to a primitive type inside the compact encoded type (or fail if - // we hit some type we wouldn't know how to work with). - let mut inner_ty_id = ty.type_param().id(); - let inner_ty = loop { - let inner_ty = types - .resolve(inner_ty_id) - .ok_or_else(|| EncodeError::TypeIdNotFound(inner_ty_id.into()))? - .type_def(); - - match inner_ty { - TypeDef::Composite(c) => { - if c.fields().len() == 1 { - inner_ty_id = c.fields()[0].ty().id(); - } else { - return Err(EncodeError::CannotCompactEncode(inner_ty_id.into())); - } - } - TypeDef::Tuple(t) => { - if t.fields().len() == 1 { - inner_ty_id = t.fields()[0].id(); - } else { - return Err(EncodeError::CannotCompactEncode(inner_ty_id.into())); - } - } - TypeDef::Primitive(primitive) => { - break match primitive { - // These are the primitives that we can compact encode: - TypeDefPrimitive::U8 => CompactTy::U8, - TypeDefPrimitive::U16 => CompactTy::U16, - TypeDefPrimitive::U32 => CompactTy::U32, - TypeDefPrimitive::U64 => CompactTy::U64, - TypeDefPrimitive::U128 => CompactTy::U128, - _ => return Err(EncodeError::CannotCompactEncode(inner_ty_id.into())), - }; - } - TypeDef::Variant(_) - | TypeDef::Sequence(_) - | TypeDef::Array(_) - | TypeDef::Compact(_) - | TypeDef::BitSequence(_) => return Err(EncodeError::CannotCompactEncode(inner_ty_id.into())), - } - }; - - // resolve to the innermost value that we have in the same way, expecting to get out - // a single primitive value. - let mut value = value; - let inner_primitive = { - loop { - match &value.value { - ValueDef::Composite(c) => { - if c.len() == 1 { - value = c.values().next().expect("length of 1; value should exist"); - } else { - return Err(EncodeError::WrongShape { - actual: value.clone(), - expected: inner_ty_id.into(), - }); - } - } - ValueDef::Primitive(primitive) => break primitive, - ValueDef::Variant(_) | ValueDef::BitSequence(_) => { - return Err(EncodeError::WrongShape { - actual: value.clone(), - expected: inner_ty_id.into(), - }) - } - } - } - }; - - // Try to compact encode the primitive type we have into the type asked for: - match inner_ty { - CompactTy::U8 => { - let val = primitive_to_integer!(type_id, inner_primitive, value => u8)?; - Compact(val).encode_to(bytes); - } - CompactTy::U16 => { - let val = primitive_to_integer!(type_id, inner_primitive, value => u16)?; - Compact(val).encode_to(bytes); - } - CompactTy::U32 => { - let val = primitive_to_integer!(type_id, inner_primitive, value => u32)?; - Compact(val).encode_to(bytes); - } - CompactTy::U64 => { - let val = primitive_to_integer!(type_id, inner_primitive, value => u64)?; - Compact(val).encode_to(bytes); - } - CompactTy::U128 => { - let val = primitive_to_integer!(type_id, inner_primitive, value => u128)?; - Compact(val).encode_to(bytes); - } - }; - - Ok(()) -} - -fn encode_bitsequence_value( - value: &Value, - type_id: TypeId, - ty: &TypeDefBitSequence, - types: &PortableRegistry, - bytes: &mut Vec, -) -> Result<(), EncodeError> { - let format = - scale_bits::Format::from_metadata(ty, types).map_err(EncodeError::BitSequenceError)?; - - match &value.value { - ValueDef::BitSequence(bits) => { - // Bits can be encoded easily enough: - scale_bits::encode_using_format_to(bits.iter(), format, bytes) - } - ValueDef::Composite(Composite::Unnamed(vals)) => { - // For composite bools we need to find and store them first: - let mut bools = Vec::with_capacity(vals.len()); - for val in vals { - match val.value { - ValueDef::Primitive(Primitive::Bool(b)) => bools.push(b), - _ => { - return Err(EncodeError::WrongShape { - actual: val.clone(), - expected: type_id, - }) - } - } - } - // And then we can encode them: - scale_bits::encode_using_format_to(bools.into_iter(), format, bytes) - } - _ => return Err(EncodeError::WrongShape { actual: value.clone(), expected: type_id }), - }; - - Ok(()) +fn encode_bitsequence( + value: &Bits, + type_id: u32, + types: &PortableRegistry, + bytes: &mut Vec, +) -> Result<(), Error> { + value.encode_as_type_to(type_id, types, bytes) } #[cfg(test)] mod test { - use super::*; - - /// 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) - } - - // Attempt to SCALE encode a Value and expect it to match the standard Encode impl for the second param given. - fn assert_can_encode_to_type( - value: Value<()>, - ty: T, - ) { - let expected = ty.encode(); - let mut buf = Vec::new(); - - let (ty_id, types) = make_type::(); - - encode_value_as_type(&value, ty_id, &types, &mut buf) - .expect("error encoding value as type"); - assert_eq!(expected, buf); - } - - #[test] - fn can_encode_basic_primitive_values() { - assert_can_encode_to_type(Value::i128(123), 123i8); - assert_can_encode_to_type(Value::i128(123), 123i16); - assert_can_encode_to_type(Value::i128(123), 123i32); - assert_can_encode_to_type(Value::i128(123), 123i64); - assert_can_encode_to_type(Value::i128(123), 123i128); - - assert_can_encode_to_type(Value::u128(123), 123u8); - assert_can_encode_to_type(Value::u128(123), 123u16); - assert_can_encode_to_type(Value::u128(123), 123u32); - assert_can_encode_to_type(Value::u128(123), 123u64); - assert_can_encode_to_type(Value::u128(123), 123u128); - - assert_can_encode_to_type(Value::bool(true), true); - assert_can_encode_to_type(Value::bool(false), false); - - assert_can_encode_to_type(Value::string("Hello"), "Hello"); - assert_can_encode_to_type(Value::string("Hello"), "Hello".to_string()); - } - - #[test] - fn chars_encoded_like_numbers() { - assert_can_encode_to_type(Value::char('j'), 'j' as u32); - assert_can_encode_to_type(Value::char('j'), b'j'); - } - - #[test] - fn can_encode_primitive_arrs_to_array() { - use crate::Primitive; - - assert_can_encode_to_type(Value::primitive(Primitive::U256([12u8; 32])), [12u8; 32]); - assert_can_encode_to_type(Value::primitive(Primitive::I256([12u8; 32])), [12u8; 32]); - } - - #[test] - fn can_encode_primitive_arrs_to_vecs() { - use crate::Primitive; - - assert_can_encode_to_type(Value::primitive(Primitive::U256([12u8; 32])), vec![12u8; 32]); - assert_can_encode_to_type(Value::primitive(Primitive::I256([12u8; 32])), vec![12u8; 32]); - } - - #[test] - fn can_encode_arrays() { - let value = Value::unnamed_composite(vec![ - Value::u128(1), - Value::u128(2), - Value::u128(3), - Value::u128(4), - ]); - assert_can_encode_to_type(value, [1u16, 2, 3, 4]); - } - - #[test] - fn can_encode_variants() { - #[derive(Encode, scale_info::TypeInfo)] - enum Foo { - Named { hello: String, foo: bool }, - Unnamed(u64, Vec), - } - - let named_value = Value::named_variant( - "Named", - [ - // Deliverately a different order; order shouldn't matter: - ("foo", Value::bool(true)), - ("hello", Value::string("world")), - ], - ); - assert_can_encode_to_type(named_value, Foo::Named { hello: "world".into(), foo: true }); - - let unnamed_value = Value::unnamed_variant( - "Unnamed", - [ - Value::u128(123), - Value::unnamed_composite(vec![ - Value::bool(true), - Value::bool(false), - Value::bool(true), - ]), - ], - ); - assert_can_encode_to_type(unnamed_value, Foo::Unnamed(123, vec![true, false, true])); - } - - #[test] - fn can_encode_structs() { - #[derive(Encode, scale_info::TypeInfo)] - struct Foo { - hello: String, - foo: bool, - } - - let named_value = Value::named_composite([ - // Deliverately a different order; order shouldn't matter: - ("foo", Value::bool(true)), - ("hello", Value::string("world")), - ]); - assert_can_encode_to_type(named_value, Foo { hello: "world".into(), foo: true }); - } - - #[test] - fn can_encode_tuples_from_named_composite() { - let named_value = - Value::named_composite([("hello", Value::string("world")), ("foo", Value::bool(true))]); - assert_can_encode_to_type(named_value, ("world", true)); - } - - #[test] - fn can_encode_tuples_from_unnamed_composite() { - let unnamed_value = Value::unnamed_composite([Value::string("world"), Value::bool(true)]); - assert_can_encode_to_type(unnamed_value, ("world", true)); - } - - #[test] - fn can_encode_unnamed_composite_to_named_struct() { - #[derive(Encode, scale_info::TypeInfo)] - struct Foo { - hello: String, - foo: bool, - } - - // This is useful because things like transaction calls are often named composites, but - // we just want to be able to provide the correct values as simply as possible without - // necessarily knowing the names. - let unnamed_value = Value::unnamed_composite([Value::string("world"), Value::bool(true)]); - assert_can_encode_to_type(unnamed_value, Foo { hello: "world".to_string(), foo: true }); - } - - #[test] - fn can_encode_bitvecs() { - use scale_bits::bits; - - // We have more thorough tests of bitvec encoding in scale-bits. - // Here we just do a basic confirmation that bool composites or - // bitsequences encode to the bits we'd expect. - assert_can_encode_to_type( - Value::bit_sequence(bits![0, 1, 1, 0, 0, 1]), - bits![0, 1, 1, 0, 0, 1], - ); - assert_can_encode_to_type( - Value::unnamed_composite(vec![ - Value::bool(false), - Value::bool(true), - Value::bool(true), - Value::bool(false), - Value::bool(false), - Value::bool(true), - ]), - bits![0, 1, 1, 0, 0, 1], - ); - } - - #[test] - fn can_encode_to_compact_types() { - assert_can_encode_to_type(Value::u128(123), Compact(123u64)); - assert_can_encode_to_type(Value::u128(123), Compact(123u64)); - assert_can_encode_to_type(Value::u128(123), Compact(123u64)); - assert_can_encode_to_type(Value::u128(123), Compact(123u64)); - - // As a special case, as long as ultimately we have a primitive value, we can compact encode it: - assert_can_encode_to_type(Value::unnamed_composite([Value::u128(123)]), Compact(123u64)); - assert_can_encode_to_type( - Value::unnamed_composite([Value::named_composite([( - "foo".to_string(), - Value::u128(123), - )])]), - Compact(123u64), - ); - } - - #[test] - fn can_encode_skipping_newtype_wrappers() { - // One layer of "newtype" can be ignored: - #[derive(Encode, scale_info::TypeInfo)] - struct Foo { - inner: u32, - } - assert_can_encode_to_type(Value::u128(32), Foo { inner: 32 }); - - // Two layers can be ignored: - #[derive(Encode, scale_info::TypeInfo)] - struct Bar(Foo); - assert_can_encode_to_type(Value::u128(32), Bar(Foo { inner: 32 })); - - // Encoding a Composite to a Composite(Composite) shape is fine too: - #[derive(Encode, scale_info::TypeInfo)] - struct SomeBytes(Vec); - assert_can_encode_to_type( - Value::from_bytes(&[1, 2, 3, 4, 5]), - SomeBytes(vec![1, 2, 3, 4, 5]), - ); - } + use super::*; + use codec::{Compact, Encode}; + + /// Given a type definition, return the PortableType and PortableRegistry + /// that our decode functions expect. + fn make_type() -> (u32, 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.id(), portable_registry) + } + + // Attempt to SCALE encode a Value and expect it to match the standard Encode impl for the second param given. + fn assert_can_encode_to_type( + value: Value<()>, + ty: T, + ) { + let expected = ty.encode(); + let mut buf = Vec::new(); + + let (ty_id, types) = make_type::(); + + value.encode_as_type_to(ty_id, &types, &mut buf).expect("error encoding value as type"); + assert_eq!(expected, buf); + } + + #[test] + fn can_encode_basic_primitive_values() { + assert_can_encode_to_type(Value::i128(123), 123i8); + assert_can_encode_to_type(Value::i128(123), 123i16); + assert_can_encode_to_type(Value::i128(123), 123i32); + assert_can_encode_to_type(Value::i128(123), 123i64); + assert_can_encode_to_type(Value::i128(123), 123i128); + + assert_can_encode_to_type(Value::u128(123), 123u8); + assert_can_encode_to_type(Value::u128(123), 123u16); + assert_can_encode_to_type(Value::u128(123), 123u32); + assert_can_encode_to_type(Value::u128(123), 123u64); + assert_can_encode_to_type(Value::u128(123), 123u128); + + assert_can_encode_to_type(Value::bool(true), true); + assert_can_encode_to_type(Value::bool(false), false); + + assert_can_encode_to_type(Value::string("Hello"), "Hello"); + assert_can_encode_to_type(Value::string("Hello"), "Hello".to_string()); + } + + #[test] + fn chars_encoded_like_numbers() { + assert_can_encode_to_type(Value::char('j'), 'j' as u32); + assert_can_encode_to_type(Value::char('j'), b'j'); + } + + #[test] + fn can_encode_primitive_arrs_to_array() { + use crate::Primitive; + + assert_can_encode_to_type(Value::primitive(Primitive::U256([12u8; 32])), [12u8; 32]); + assert_can_encode_to_type(Value::primitive(Primitive::I256([12u8; 32])), [12u8; 32]); + } + + #[test] + fn can_encode_primitive_arrs_to_vecs() { + use crate::Primitive; + + assert_can_encode_to_type(Value::primitive(Primitive::U256([12u8; 32])), vec![12u8; 32]); + assert_can_encode_to_type(Value::primitive(Primitive::I256([12u8; 32])), vec![12u8; 32]); + } + + #[test] + fn can_encode_arrays() { + let value = Value::unnamed_composite(vec![ + Value::u128(1), + Value::u128(2), + Value::u128(3), + Value::u128(4), + ]); + assert_can_encode_to_type(value, [1u16, 2, 3, 4]); + } + + #[test] + fn can_encode_variants() { + #[derive(Encode, scale_info::TypeInfo)] + enum Foo { + Named { hello: String, foo: bool }, + Unnamed(u64, Vec), + } + + let named_value = Value::named_variant( + "Named", + [ + // Deliverately a different order; order shouldn't matter: + ("foo", Value::bool(true)), + ("hello", Value::string("world")), + ], + ); + assert_can_encode_to_type(named_value, Foo::Named { hello: "world".into(), foo: true }); + + let unnamed_value = Value::unnamed_variant( + "Unnamed", + [ + Value::u128(123), + Value::unnamed_composite(vec![ + Value::bool(true), + Value::bool(false), + Value::bool(true), + ]), + ], + ); + assert_can_encode_to_type(unnamed_value, Foo::Unnamed(123, vec![true, false, true])); + } + + #[test] + fn can_encode_structs() { + #[derive(Encode, scale_info::TypeInfo)] + struct Foo { + hello: String, + foo: bool, + } + + let named_value = Value::named_composite([ + // Deliverately a different order; order shouldn't matter: + ("foo", Value::bool(true)), + ("hello", Value::string("world")), + ]); + assert_can_encode_to_type(named_value, Foo { hello: "world".into(), foo: true }); + } + + #[test] + fn can_encode_tuples_from_named_composite() { + let named_value = + Value::named_composite([("hello", Value::string("world")), ("foo", Value::bool(true))]); + assert_can_encode_to_type(named_value, ("world", true)); + } + + #[test] + fn can_encode_tuples_from_unnamed_composite() { + let unnamed_value = Value::unnamed_composite([Value::string("world"), Value::bool(true)]); + assert_can_encode_to_type(unnamed_value, ("world", true)); + } + + #[test] + fn can_encode_unnamed_composite_to_named_struct() { + #[derive(Encode, scale_info::TypeInfo)] + struct Foo { + hello: String, + foo: bool, + } + + // This is useful because things like transaction calls are often named composites, but + // we just want to be able to provide the correct values as simply as possible without + // necessarily knowing the names. + let unnamed_value = Value::unnamed_composite([Value::string("world"), Value::bool(true)]); + assert_can_encode_to_type(unnamed_value, Foo { hello: "world".to_string(), foo: true }); + } + + #[test] + fn can_encode_bitvecs() { + use scale_bits::bits; + + // We have more thorough tests of bitvec encoding in scale-bits. + // Here we just do a basic confirmation that bool composites or + // bitsequences encode to the bits we'd expect. + assert_can_encode_to_type( + Value::bit_sequence(bits![0, 1, 1, 0, 0, 1]), + bits![0, 1, 1, 0, 0, 1], + ); + // a single value should still encode OK: + assert_can_encode_to_type(Value::unnamed_composite(vec![Value::bool(false)]), bits![0]); + assert_can_encode_to_type( + Value::unnamed_composite(vec![ + Value::bool(false), + Value::bool(true), + Value::bool(true), + Value::bool(false), + Value::bool(false), + Value::bool(true), + ]), + bits![0, 1, 1, 0, 0, 1], + ); + assert_can_encode_to_type( + Value::unnamed_composite(vec![ + Value::u128(0), + Value::u128(1), + Value::u128(1), + Value::u128(0), + Value::u128(0), + Value::u128(1), + ]), + bits![0, 1, 1, 0, 0, 1], + ); + assert_can_encode_to_type( + Value::unnamed_composite(vec![ + Value::i128(0), + Value::i128(1), + Value::i128(1), + Value::i128(0), + Value::i128(0), + Value::i128(1), + ]), + bits![0, 1, 1, 0, 0, 1], + ); + } + + #[test] + fn can_encode_to_compact_types() { + assert_can_encode_to_type(Value::u128(123), Compact(123u64)); + assert_can_encode_to_type(Value::u128(123), Compact(123u64)); + assert_can_encode_to_type(Value::u128(123), Compact(123u64)); + assert_can_encode_to_type(Value::u128(123), Compact(123u64)); + + // As a special case, as long as ultimately we have a primitive value, we can compact encode it: + assert_can_encode_to_type(Value::unnamed_composite([Value::u128(123)]), Compact(123u64)); + assert_can_encode_to_type( + Value::unnamed_composite([Value::named_composite([( + "foo".to_string(), + Value::u128(123), + )])]), + Compact(123u64), + ); + } + + #[test] + fn can_encode_skipping_newtype_wrappers() { + // One layer of "newtype" can be ignored: + #[derive(Encode, scale_info::TypeInfo)] + struct Foo { + inner: u32, + } + assert_can_encode_to_type(Value::u128(32), Foo { inner: 32 }); + + // Two layers can be ignored: + #[derive(Encode, scale_info::TypeInfo)] + struct Bar(Foo); + assert_can_encode_to_type(Value::u128(32), Bar(Foo { inner: 32 })); + assert_can_encode_to_type( + Value::unnamed_composite([Value::u128(32)]), + Bar(Foo { inner: 32 }), + ); + + // Encoding a Composite to a Composite(Composite) shape is fine too: + #[derive(Encode, scale_info::TypeInfo)] + struct SomeBytes(Vec); + assert_can_encode_to_type( + Value::from_bytes([1, 2, 3, 4, 5]), + SomeBytes(vec![1, 2, 3, 4, 5]), + ); + assert_can_encode_to_type(Value::from_bytes([1]), SomeBytes(vec![1])); + } } diff --git a/src/scale_impls/mod.rs b/src/scale_impls/mod.rs index abf2df3..9ee2d5c 100644 --- a/src/scale_impls/mod.rs +++ b/src/scale_impls/mod.rs @@ -15,15 +15,9 @@ mod decode; mod encode; -mod type_id; -/// The portable version of a [`scale_info`] type ID. -type ScaleTypeId = scale_info::interner::UntrackedSymbol; // equivalent to: ::Type; +pub use decode::{decode_value_as_type, DecodeError, DecodeValueVisitor}; +pub use encode::EncodeError; -/// The portable version of [`scale_info::TypeDef`] -type ScaleTypeDef = scale_info::TypeDef; - -pub use decode::{decode_value_as_type, DecodeError}; -pub use encode::{encode_value_as_type, EncodeError}; - -pub use type_id::TypeId; +/// A type ID which can be resolved into a type given a [`scale_info::PortableRegistry`]. +pub type TypeId = u32; diff --git a/src/scale_impls/type_id.rs b/src/scale_impls/type_id.rs deleted file mode 100644 index d165bb2..0000000 --- a/src/scale_impls/type_id.rs +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright (C) 2022 Parity Technologies (UK) Ltd. (admin@parity.io) -// This file is a part of the scale-value crate. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use std::fmt::Display; - -use super::ScaleTypeId; - -/// 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)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct TypeId(u32); - -impl TypeId { - /// Return the u32 ID expected by a PortableRegistry. - pub(crate) fn id(self) -> u32 { - self.0 - } -} - -impl Display for TypeId { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl From for TypeId { - fn from(id: ScaleTypeId) -> Self { - TypeId(id.id()) - } -} - -impl From<&ScaleTypeId> for TypeId { - fn from(id: &ScaleTypeId) -> Self { - TypeId(id.id()) - } -} - -impl From<&TypeId> for TypeId { - fn from(id: &TypeId) -> Self { - *id - } -} - -impl From for TypeId { - fn from(id: u32) -> Self { - TypeId(id) - } -} - -impl From for TypeId { - fn from(id: scale_decode::visitor::TypeId) -> Self { - TypeId(id.0) - } -} diff --git a/src/serde_impls/bitvec_helpers.rs b/src/serde_impls/bitvec_helpers.rs index 250d385..27fdea9 100644 --- a/src/serde_impls/bitvec_helpers.rs +++ b/src/serde_impls/bitvec_helpers.rs @@ -25,9 +25,9 @@ use super::deserializer::DeserializerError; use crate::{BitSequence, Composite, ValueDef}; use serde::{ - de::{value::MapDeserializer, MapAccess, Visitor}, - ser::SerializeMap, - Serializer, + de::{value::MapDeserializer, MapAccess, Visitor}, + ser::SerializeMap, + Serializer, }; /// We use this identifier in a map to uniquely identify a bitvec payload, so that it can @@ -37,17 +37,17 @@ pub static BITVEC_SERDE_IDENT: &str = "__bitvec__values__"; /// Serialize a bitvec so that the special deserializing is compatible with it. pub fn serialize_bitvec(seq: &BitSequence, serializer: S) -> Result where - S: Serializer, + S: Serializer, { - let mut map = serializer.serialize_map(Some(1))?; - map.serialize_entry(BITVEC_SERDE_IDENT, seq)?; - map.end() + let mut map = serializer.serialize_map(Some(1))?; + map.serialize_entry(BITVEC_SERDE_IDENT, seq)?; + map.end() } /// Turn a [`BitSequence`] into a [`MapAccess`] impl that can be handed to a visitor to be consumed. pub fn map_access<'de>(seq: BitSequence) -> impl MapAccess<'de, Error = DeserializerError> { - let bools: Vec = seq.iter().collect(); - MapDeserializer::new([(BITVEC_SERDE_IDENT, bools)].into_iter()) + let bools: Vec = seq.iter().collect(); + MapDeserializer::new([(BITVEC_SERDE_IDENT, bools)].into_iter()) } /// This visits a map, and will extract from that either a [`ValueDef::Composite`] or a @@ -55,45 +55,45 @@ pub fn map_access<'de>(seq: BitSequence) -> impl MapAccess<'de, Error = Deserial pub struct MapOrBitSeqVisitor; impl<'de> Visitor<'de> for MapOrBitSeqVisitor { - type Value = ValueDef<()>; + type Value = ValueDef<()>; - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str( - "a map-like type that can be decoded into a Value::BitSequence or Value::Composite", - ) - } + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str( + "a map-like type that can be decoded into a Value::BitSequence or Value::Composite", + ) + } - fn visit_map(self, mut map: A) -> Result - where - A: MapAccess<'de>, - { - // get the first key from the map: - let first_key = match map.next_key::()? { - Some(key) => key, - // No errors but the map appears to be empty; return an empty named composite. - None => return Ok(ValueDef::Composite(Composite::Named(Vec::new()))), - }; + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, + { + // get the first key from the map: + let first_key = match map.next_key::()? { + Some(key) => key, + // No errors but the map appears to be empty; return an empty named composite. + None => return Ok(ValueDef::Composite(Composite::Named(Vec::new()))), + }; - // See whether the key identifies a bitvec payload: - if first_key == BITVEC_SERDE_IDENT { - // We should be able to decode a vec of bools as the value, then: - let bits = map.next_value::>()?; - // .. and we turn that into a bitvec to return: - let mut bitvec = BitSequence::new(); - for bit in bits { - bitvec.push(bit); - } - return Ok(ValueDef::BitSequence(bitvec)); - } + // See whether the key identifies a bitvec payload: + if first_key == BITVEC_SERDE_IDENT { + // We should be able to decode a vec of bools as the value, then: + let bits = map.next_value::>()?; + // .. and we turn that into a bitvec to return: + let mut bitvec = BitSequence::new(); + for bit in bits { + bitvec.push(bit); + } + return Ok(ValueDef::BitSequence(bitvec)); + } - // That didn't work, so decode the first value as a Value<()> instead: - let mut values = Vec::with_capacity(map.size_hint().unwrap_or(0)); - values.push((first_key, map.next_value()?)); + // That didn't work, so decode the first value as a Value<()> instead: + let mut values = Vec::with_capacity(map.size_hint().unwrap_or(0)); + values.push((first_key, map.next_value()?)); - // .. and then decode all of the other key-value pairs and add them too: - while let Some(key_val) = map.next_entry()? { - values.push(key_val); - } - Ok(ValueDef::Composite(Composite::Named(values))) - } + // .. and then decode all of the other key-value pairs and add them too: + while let Some(key_val) = map.next_entry()? { + values.push(key_val); + } + Ok(ValueDef::Composite(Composite::Named(values))) + } } diff --git a/src/serde_impls/deserialize.rs b/src/serde_impls/deserialize.rs index 81f2892..a7c4165 100644 --- a/src/serde_impls/deserialize.rs +++ b/src/serde_impls/deserialize.rs @@ -30,259 +30,259 @@ use super::bitvec_helpers; use crate::{Composite, Primitive, Value, ValueDef, Variant}; use serde::{ - self, - de::{Error, Visitor}, - Deserialize, Deserializer, + self, + de::{Error, Visitor}, + Deserialize, Deserializer, }; use std::convert::TryInto; 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: () }) - } + 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) - } + 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) - } + 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) - } + 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) - } + 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.into())) - } - }; + ($name:ident $ty:ident $variant:ident) => { + fn $name(self, v: $ty) -> Result + where + E: serde::de::Error, + { + Ok(Primitive::$variant(v.into())) + } + }; } 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 I128); - visit_prim!(visit_i16 i16 I128); - visit_prim!(visit_i32 i32 I128); - visit_prim!(visit_i64 i64 I128); - visit_prim!(visit_i128 i128 I128); - visit_prim!(visit_u8 u8 U128); - visit_prim!(visit_u16 u16 U128); - visit_prim!(visit_u32 u32 U128); - visit_prim!(visit_u64 u64 U128); - 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::String(v.into())) - } - - fn visit_string(self, v: String) -> Result - where - E: serde::de::Error, - { - Ok(Primitive::String(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)) - } + 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 I128); + visit_prim!(visit_i16 i16 I128); + visit_prim!(visit_i32 i32 I128); + visit_prim!(visit_i64 i64 I128); + visit_prim!(visit_i128 i128 I128); + visit_prim!(visit_u8 u8 U128); + visit_prim!(visit_u16 u16 U128); + visit_prim!(visit_u32 u32 U128); + visit_prim!(visit_u64 u64 U128); + 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::String(v.into())) + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Ok(Primitive::String(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)) + } } 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::u128(b as u128)).collect(); - Ok(Composite::Unnamed(byte_values)) - } - - 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)) - } + 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::u128(b as u128)).collect(); + Ok(Composite::Unnamed(byte_values)) + } + + 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_some(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - // Wrap "Some"-like things in a Some variant. - // This aligns with how we serialize these back to optionals. - let inner = Value::deserialize(deserializer)?; - Ok(Variant { name: "Some".to_string(), values: Composite::Unnamed(vec![inner]) }) - } - - fn visit_none(self) -> Result - where - E: Error, - { - // If the thing is "none", wrap it in a None variant. - // This aligns with how we serialize these back to optionals. - Ok(Variant { name: "None".to_string(), values: Composite::Unnamed(Vec::new()) }) - } - - 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", - )) - } - } + 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_some(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + // Wrap "Some"-like things in a Some variant. + // This aligns with how we serialize these back to optionals. + let inner = Value::deserialize(deserializer)?; + Ok(Variant { name: "Some".to_string(), values: Composite::Unnamed(vec![inner]) }) + } + + fn visit_none(self) -> Result + where + E: Error, + { + // If the thing is "none", wrap it in a None variant. + // This aligns with how we serialize these back to optionals. + Ok(Variant { name: "None".to_string(), values: Composite::Unnamed(Vec::new()) }) + } + + 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; @@ -290,428 +290,428 @@ 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) - } - )+ - } + ( + $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_unit() - visit_bytes(&[u8]) - ); - - fn visit_none(self) -> Result - where - E: Error, - { - VariantVisitor.visit_none().map(ValueDef::Variant) - } - - fn visit_some(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - VariantVisitor.visit_some(deserializer).map(ValueDef::Variant) - } - - 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>, - { - // Return a bitvec or a composite type depending on the map values. - bitvec_helpers::MapOrBitSeqVisitor.visit_map(map) - } - - fn visit_enum(self, data: A) -> Result - where - A: serde::de::EnumAccess<'de>, - { - VariantVisitor.visit_enum(data).map(ValueDef::Variant) - } + 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_unit() + visit_bytes(&[u8]) + ); + + fn visit_none(self) -> Result + where + E: Error, + { + VariantVisitor.visit_none().map(ValueDef::Variant) + } + + fn visit_some(self, deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + VariantVisitor.visit_some(deserializer).map(ValueDef::Variant) + } + + 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>, + { + // Return a bitvec or a composite type depending on the map values. + bitvec_helpers::MapOrBitSeqVisitor.visit_map(map) + } + + 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 serde_json::json; - - use super::{super::DeserializerError, *}; - - /// 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::u128(123)); - assert_value_isomorphic(Value::i128(123)); - assert_value_isomorphic(Value::bool(true)); - assert_value_isomorphic(Value::char('a')); - assert_value_isomorphic(Value::string("Hello!")); - - // 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![1u8; 32].into_iter().map(|b| Value::u128(b.into()))), - ); - assert_value_to_value( - ValueDef::<()>::Primitive(Primitive::U256([1; 32])), - Value::unnamed_composite(vec![1u8; 32].into_iter().map(|b| Value::u128(b.into()))), - ); - - // .. 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::U128(123)); - assert_value_isomorphic(Primitive::U256([1; 32])); - assert_value_isomorphic(Primitive::I128(123)); - assert_value_isomorphic(Primitive::Bool(true)); - assert_value_isomorphic(Primitive::Char('a')); - assert_value_isomorphic(Primitive::String("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::u128(123), Primitive::u128(123)); - assert_value_to_value(Value::i128(123), Primitive::i128(123)); - - // Or vice versa: - - assert_value_to_value(Primitive::u128(123), Value::u128(123)); - assert_value_to_value(Primitive::i128(123), Value::i128(123)); - } - - #[test] - fn deserialize_composites_isomorphic() { - assert_value_isomorphic(Value::unnamed_composite(vec![ - Value::u128(123), - Value::bool(true), - ])); - assert_value_isomorphic(Value::named_composite::(vec![])); - assert_value_isomorphic(Value::named_composite(vec![ - ("a", Value::u128(123)), - ("b", Value::bool(true)), - ])); - assert_value_isomorphic(Value::named_composite(vec![ - ("a", Value::u128(123)), - ( - "b", - Value::named_composite(vec![ - ("c", Value::u128(123)), - ("d", Value::string("hello")), - ]), - ), - ])); - - // unwrapped: - - assert_value_isomorphic(Composite::unnamed(vec![Value::u128(123), Value::bool(true)])); - assert_value_isomorphic(Composite::unnamed(vec![])); - assert_value_isomorphic(Composite::named(vec![ - ("a", Value::u128(123)), - ("b", Value::bool(true)), - ])); - assert_value_isomorphic(Composite::named(vec![ - ("a", Value::u128(123)), - ( - "b", - Value::named_composite(vec![ - ("c", Value::u128(123)), - ("d", Value::string("hello")), - ]), - ), - ])); - } - - #[test] - fn deserialize_variants_isomorphic() { - assert_value_isomorphic(ValueDef::Variant(Variant::unnamed_fields( - "Foo", - [Value::u128(123), Value::bool(true)], - ))); - assert_value_isomorphic(ValueDef::Variant(Variant::unnamed_fields("Foo", []))); - assert_value_isomorphic(ValueDef::Variant(Variant::named_fields( - "Foo", - [("a", Value::u128(123)), ("b", Value::bool(true))], - ))); - - // unwrapped work as well: - - assert_value_isomorphic(Variant::unnamed_fields( - "Foo", - [Value::u128(123), Value::bool(true)], - )); - assert_value_isomorphic(Variant::unnamed_fields("Foo", vec![])); - assert_value_isomorphic(Variant::named_fields( - "Foo", - [("a", Value::u128(123)), ("b", Value::bool(true))], - )); - } - - #[test] - fn deserialize_bitsequences_isomorphic() { - use scale_bits::bits; - assert_value_isomorphic(ValueDef::BitSequence(bits![])); - assert_value_isomorphic(ValueDef::BitSequence(bits![0])); - assert_value_isomorphic(ValueDef::BitSequence(bits![0, 1, 1, 0, 1, 0, 1, 1, 1])); - } - - #[test] - fn deserialize_bitsequence_from_json() { - use scale_bits::bits; - - let bits_json = json!({ - "__bitvec__values__": [true, false, true, true, false] - }); - - let val: Value = serde_json::from_value(bits_json).unwrap(); - assert_eq!(val.value, ValueDef::BitSequence(bits![true, false, true, true, false])); - } - - #[test] - fn sequence_to_value() { - use serde::de::{value::SeqDeserializer, IntoDeserializer}; - - let de: SeqDeserializer<_, DeserializerError> = vec![1u8, 2, 3, 4].into_deserializer(); - - assert_value_to_value( - de.clone(), - Value::unnamed_composite(vec![ - Value::u128(1), - Value::u128(2), - Value::u128(3), - Value::u128(4), - ]), - ); - assert_value_to_value( - de, - Composite::Unnamed(vec![ - Value::u128(1), - Value::u128(2), - Value::u128(3), - Value::u128(4), - ]), - ); - } - - #[test] - fn sequence_to_primitive() { - use serde::de::{value::SeqDeserializer, IntoDeserializer}; - - let de: SeqDeserializer<_, DeserializerError> = 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<_, DeserializerError> = 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::i128(1)))); - assert!(vals.contains(&("b".into(), Value::i128(2)))); - assert!(vals.contains(&("c".into(), Value::i128(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", Value::u128(123)), - ( - "b", - Value::named_composite(vec![ - ("c", Value::u128(123)), - ("d", Value::string("hello")), - ("e", Value::named_composite::([])), - ]), - ), - ]); - - #[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::deserialize(value).expect("should work"); - - assert_eq!( - partial, - Partial { - a: Value::u128(123), - b: PartialB { - c: 123, - d: "hello".into(), - e: Value::named_composite::([]) - } - } - ) - } - - #[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::u128(1), - Value::u128(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::u128(1)), - ("b".into(), Value::u128(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(..) - )); - } + use serde_json::json; + + use super::{super::DeserializerError, *}; + + /// 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::u128(123)); + assert_value_isomorphic(Value::i128(123)); + assert_value_isomorphic(Value::bool(true)); + assert_value_isomorphic(Value::char('a')); + assert_value_isomorphic(Value::string("Hello!")); + + // 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![1u8; 32].into_iter().map(|b| Value::u128(b.into()))), + ); + assert_value_to_value( + ValueDef::<()>::Primitive(Primitive::U256([1; 32])), + Value::unnamed_composite(vec![1u8; 32].into_iter().map(|b| Value::u128(b.into()))), + ); + + // .. 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::U128(123)); + assert_value_isomorphic(Primitive::U256([1; 32])); + assert_value_isomorphic(Primitive::I128(123)); + assert_value_isomorphic(Primitive::Bool(true)); + assert_value_isomorphic(Primitive::Char('a')); + assert_value_isomorphic(Primitive::String("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::u128(123), Primitive::u128(123)); + assert_value_to_value(Value::i128(123), Primitive::i128(123)); + + // Or vice versa: + + assert_value_to_value(Primitive::u128(123), Value::u128(123)); + assert_value_to_value(Primitive::i128(123), Value::i128(123)); + } + + #[test] + fn deserialize_composites_isomorphic() { + assert_value_isomorphic(Value::unnamed_composite(vec![ + Value::u128(123), + Value::bool(true), + ])); + assert_value_isomorphic(Value::named_composite::(vec![])); + assert_value_isomorphic(Value::named_composite(vec![ + ("a", Value::u128(123)), + ("b", Value::bool(true)), + ])); + assert_value_isomorphic(Value::named_composite(vec![ + ("a", Value::u128(123)), + ( + "b", + Value::named_composite(vec![ + ("c", Value::u128(123)), + ("d", Value::string("hello")), + ]), + ), + ])); + + // unwrapped: + + assert_value_isomorphic(Composite::unnamed(vec![Value::u128(123), Value::bool(true)])); + assert_value_isomorphic(Composite::unnamed(vec![])); + assert_value_isomorphic(Composite::named(vec![ + ("a", Value::u128(123)), + ("b", Value::bool(true)), + ])); + assert_value_isomorphic(Composite::named(vec![ + ("a", Value::u128(123)), + ( + "b", + Value::named_composite(vec![ + ("c", Value::u128(123)), + ("d", Value::string("hello")), + ]), + ), + ])); + } + + #[test] + fn deserialize_variants_isomorphic() { + assert_value_isomorphic(ValueDef::Variant(Variant::unnamed_fields( + "Foo", + [Value::u128(123), Value::bool(true)], + ))); + assert_value_isomorphic(ValueDef::Variant(Variant::unnamed_fields("Foo", []))); + assert_value_isomorphic(ValueDef::Variant(Variant::named_fields( + "Foo", + [("a", Value::u128(123)), ("b", Value::bool(true))], + ))); + + // unwrapped work as well: + + assert_value_isomorphic(Variant::unnamed_fields( + "Foo", + [Value::u128(123), Value::bool(true)], + )); + assert_value_isomorphic(Variant::unnamed_fields("Foo", vec![])); + assert_value_isomorphic(Variant::named_fields( + "Foo", + [("a", Value::u128(123)), ("b", Value::bool(true))], + )); + } + + #[test] + fn deserialize_bitsequences_isomorphic() { + use scale_bits::bits; + assert_value_isomorphic(ValueDef::BitSequence(bits![])); + assert_value_isomorphic(ValueDef::BitSequence(bits![0])); + assert_value_isomorphic(ValueDef::BitSequence(bits![0, 1, 1, 0, 1, 0, 1, 1, 1])); + } + + #[test] + fn deserialize_bitsequence_from_json() { + use scale_bits::bits; + + let bits_json = json!({ + "__bitvec__values__": [true, false, true, true, false] + }); + + let val: Value = serde_json::from_value(bits_json).unwrap(); + assert_eq!(val.value, ValueDef::BitSequence(bits![true, false, true, true, false])); + } + + #[test] + fn sequence_to_value() { + use serde::de::{value::SeqDeserializer, IntoDeserializer}; + + let de: SeqDeserializer<_, DeserializerError> = vec![1u8, 2, 3, 4].into_deserializer(); + + assert_value_to_value( + de.clone(), + Value::unnamed_composite(vec![ + Value::u128(1), + Value::u128(2), + Value::u128(3), + Value::u128(4), + ]), + ); + assert_value_to_value( + de, + Composite::Unnamed(vec![ + Value::u128(1), + Value::u128(2), + Value::u128(3), + Value::u128(4), + ]), + ); + } + + #[test] + fn sequence_to_primitive() { + use serde::de::{value::SeqDeserializer, IntoDeserializer}; + + let de: SeqDeserializer<_, DeserializerError> = 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<_, DeserializerError> = 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::i128(1)))); + assert!(vals.contains(&("b".into(), Value::i128(2)))); + assert!(vals.contains(&("c".into(), Value::i128(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", Value::u128(123)), + ( + "b", + Value::named_composite(vec![ + ("c", Value::u128(123)), + ("d", Value::string("hello")), + ("e", Value::named_composite::([])), + ]), + ), + ]); + + #[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::deserialize(value).expect("should work"); + + assert_eq!( + partial, + Partial { + a: Value::u128(123), + b: PartialB { + c: 123, + d: "hello".into(), + e: Value::named_composite::([]) + } + } + ) + } + + #[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::u128(1), + Value::u128(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::u128(1)), + ("b".into(), Value::u128(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/src/serde_impls/deserializer.rs b/src/serde_impls/deserializer.rs index 627ba4a..d7acbf6 100644 --- a/src/serde_impls/deserializer.rs +++ b/src/serde_impls/deserializer.rs @@ -25,8 +25,8 @@ use super::bitvec_helpers; use crate::{Composite, Primitive, Value, ValueDef, Variant}; use serde::{ - de::{self, EnumAccess, IntoDeserializer, VariantAccess}, - forward_to_deserialize_any, ser, Deserialize, Deserializer, + de::{self, EnumAccess, IntoDeserializer, VariantAccess}, + forward_to_deserialize_any, ser, Deserialize, Deserializer, }; use std::{borrow::Cow, fmt::Display}; @@ -39,132 +39,132 @@ use std::{borrow::Cow, fmt::Display}; pub struct DeserializerError(Cow<'static, str>); impl DeserializerError { - fn from_string>(s: S) -> DeserializerError { - DeserializerError(Cow::Owned(s.into())) - } - fn from_str(s: &'static str) -> DeserializerError { - DeserializerError(Cow::Borrowed(s)) - } + fn from_string>(s: S) -> DeserializerError { + DeserializerError(Cow::Owned(s.into())) + } + fn from_str(s: &'static str) -> DeserializerError { + DeserializerError(Cow::Borrowed(s)) + } } impl de::Error for DeserializerError { - fn custom(msg: T) -> Self { - DeserializerError::from_string(msg.to_string()) - } + fn custom(msg: T) -> Self { + DeserializerError::from_string(msg.to_string()) + } } impl ser::Error for DeserializerError { - fn custom(msg: T) -> Self { - DeserializerError::from_string(msg.to_string()) - } + fn custom(msg: T) -> Self { + DeserializerError::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) - } - }; + ($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 = DeserializerError; - - 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) - } + type Error = DeserializerError; + + 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 @@ -193,1017 +193,1017 @@ macro_rules! delegate_except_bitseq { } macro_rules! delegate_method { - ($name:ident $ty:ident) => { - fn $name(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - delegate_except_bitseq! { $name(self, visitor), - seq => { - let map = bitvec_helpers::map_access(seq); - visitor.visit_map(map) - } - } - } - }; + ($name:ident $ty:ident) => { + fn $name(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + delegate_except_bitseq! { $name(self, visitor), + seq => { + let map = bitvec_helpers::map_access(seq); + visitor.visit_map(map) + } + } + } + }; } // 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 = DeserializerError; - - fn deserialize_any(self, visitor: V) -> Result - where - V: serde::de::Visitor<'de>, - { - delegate_except_bitseq! { deserialize_any(self, visitor), - seq => { - let map = bitvec_helpers::map_access(seq); - visitor.visit_map(map) - } - } - } - - delegate_method!(deserialize_u8 u8); - delegate_method!(deserialize_u16 u16); - delegate_method!(deserialize_u32 u32); - delegate_method!(deserialize_u64 u64); - delegate_method!(deserialize_u128 u128); - delegate_method!(deserialize_i8 i8); - delegate_method!(deserialize_i16 i16); - delegate_method!(deserialize_i32 i32); - delegate_method!(deserialize_i64 i64); - delegate_method!(deserialize_i128 i128); - delegate_method!(deserialize_bool bool); - delegate_method!(deserialize_f32 f32); - delegate_method!(deserialize_f64 f64); - delegate_method!(deserialize_char char); - delegate_method!(deserialize_str str); - delegate_method!(deserialize_string String); - - 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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::from_str("Cannot deserialize BitSequence into a map")) - } - } - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - // Special handling to turn a variant value of "Some" or "None" into an option. - if let ValueDef::Variant(Variant { name, values: Composite::Unnamed(mut vs) }) = self { - if name == "Some" && vs.len() == 1 { - visitor.visit_some(vs.pop().expect("length checked")) - } else if name == "None" && vs.is_empty() { - visitor.visit_none() - } else { - // Reconstruct the variant and try to deserialize without the option hint: - ValueDef::Variant(Variant { name, values: Composite::Unnamed(vs) }) - .deserialize_any(visitor) - } - } else { - // fall back to deserializing based on the value type if it doesn't look like an Option: - self.deserialize_any(visitor) - } - } - - // 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! { - struct identifier ignored_any - } + type Error = DeserializerError; + + fn deserialize_any(self, visitor: V) -> Result + where + V: serde::de::Visitor<'de>, + { + delegate_except_bitseq! { deserialize_any(self, visitor), + seq => { + let map = bitvec_helpers::map_access(seq); + visitor.visit_map(map) + } + } + } + + delegate_method!(deserialize_u8 u8); + delegate_method!(deserialize_u16 u16); + delegate_method!(deserialize_u32 u32); + delegate_method!(deserialize_u64 u64); + delegate_method!(deserialize_u128 u128); + delegate_method!(deserialize_i8 i8); + delegate_method!(deserialize_i16 i16); + delegate_method!(deserialize_i32 i32); + delegate_method!(deserialize_i64 i64); + delegate_method!(deserialize_i128 i128); + delegate_method!(deserialize_bool bool); + delegate_method!(deserialize_f32 f32); + delegate_method!(deserialize_f64 f64); + delegate_method!(deserialize_char char); + delegate_method!(deserialize_str str); + delegate_method!(deserialize_string String); + + 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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::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(DeserializerError::from_str("Cannot deserialize BitSequence into a map")) + } + } + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + // Special handling to turn a variant value of "Some" or "None" into an option. + if let ValueDef::Variant(Variant { name, values: Composite::Unnamed(mut vs) }) = self { + if name == "Some" && vs.len() == 1 { + visitor.visit_some(vs.pop().expect("length checked")) + } else if name == "None" && vs.is_empty() { + visitor.visit_none() + } else { + // Reconstruct the variant and try to deserialize without the option hint: + ValueDef::Variant(Variant { name, values: Composite::Unnamed(vs) }) + .deserialize_any(visitor) + } + } else { + // fall back to deserializing based on the value type if it doesn't look like an Option: + self.deserialize_any(visitor) + } + } + + // 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! { + struct identifier ignored_any + } } impl<'de, T> IntoDeserializer<'de, DeserializerError> for Value { - type Deserializer = Value; - fn into_deserializer(self) -> Self::Deserializer { - self - } + type Deserializer = Value; + fn into_deserializer(self) -> Self::Deserializer { + self + } } impl<'de, T> Deserializer<'de> for Composite { - type Error = DeserializerError; - - 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(DeserializerError::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(DeserializerError::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(DeserializerError::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>, - { - let mut bytes: Vec = Vec::new(); - for v in self.into_values() { - if let ValueDef::Primitive(Primitive::U128(n)) = v.value { - let byte = n - .try_into() - .map_err(|_| DeserializerError::from_str("Cannot deserialize composite that is not entirely U8's into bytes (number out of range)"))?; - bytes.push(byte); - } else { - return Err(DeserializerError::from_str( - "Cannot deserialize composite that is not entirely U8's into bytes (non-numeric values encountered)", - )); - } - } - 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 - } + type Error = DeserializerError; + + 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(DeserializerError::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(DeserializerError::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(DeserializerError::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>, + { + let bytes = self.into_values().map(|v| { + match v.value { + ValueDef::Primitive(Primitive::U128(n)) => { + n.try_into() + .map_err(|_| DeserializerError::from_str("Cannot deserialize composite that is not entirely U8's into bytes (number out of range)")) + }, + _ => { + Err(DeserializerError::from_str( + "Cannot deserialize composite that is not entirely U8's into bytes (non-numeric values encountered)", + )) + } + } + }).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, DeserializerError> for Composite { - type Deserializer = Composite; - fn into_deserializer(self) -> Self::Deserializer { - self - } + 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 = DeserializerError; - - 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) - } + type Error = DeserializerError; + + 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 = DeserializerError; - - 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 - } + type Error = DeserializerError; + + 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, DeserializerError> for Variant { - type Deserializer = Variant; - fn into_deserializer(self) -> Self::Deserializer { - self - } + 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 = DeserializerError; - - 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)) - } + type Error = DeserializerError; + + 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)) + } } macro_rules! deserialize_number { - ($name:ident $visit_fn:ident) => { - fn $name(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - match self { - Primitive::U128(n) => match n.try_into() { - Ok(val) => visitor.$visit_fn(val), - Err(_) => self.deserialize_any(visitor), - }, - Primitive::I128(n) => match n.try_into() { - Ok(val) => visitor.$visit_fn(val), - Err(_) => self.deserialize_any(visitor), - }, - _ => self.deserialize_any(visitor), - } - } - }; + ($name:ident $visit_fn:ident) => { + fn $name(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match self { + Primitive::U128(n) => match n.try_into() { + Ok(val) => visitor.$visit_fn(val), + Err(_) => self.deserialize_any(visitor), + }, + Primitive::I128(n) => match n.try_into() { + Ok(val) => visitor.$visit_fn(val), + Err(_) => self.deserialize_any(visitor), + }, + _ => self.deserialize_any(visitor), + } + } + }; } impl<'de> Deserializer<'de> for Primitive { - type Error = DeserializerError; - - 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::String(v) => visitor.visit_string(v), - Primitive::U128(v) => visitor.visit_u128(v), - Primitive::U256(v) => visitor.visit_bytes(&v), - Primitive::I128(v) => visitor.visit_i128(v), - Primitive::I256(v) => visitor.visit_bytes(&v), - } - } - - // if we're asked to deserialize into some numeric type, - // we do our best to visit that same type with a value, but - // if we can't coerce our value to it, we fall back to - // deserialize_any. - deserialize_number!(deserialize_u8 visit_u8); - deserialize_number!(deserialize_u16 visit_u16); - deserialize_number!(deserialize_u32 visit_u32); - deserialize_number!(deserialize_u64 visit_u64); - deserialize_number!(deserialize_u128 visit_u128); - deserialize_number!(deserialize_i8 visit_i8); - deserialize_number!(deserialize_i16 visit_i16); - deserialize_number!(deserialize_i32 visit_i32); - deserialize_number!(deserialize_i64 visit_i64); - deserialize_number!(deserialize_i128 visit_i128); - - 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 f32 f64 char str string - bytes byte_buf option unit unit_struct seq tuple - tuple_struct map struct enum identifier ignored_any - } + type Error = DeserializerError; + + 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::String(v) => visitor.visit_string(v), + Primitive::U128(v) => visitor.visit_u128(v), + Primitive::U256(v) => visitor.visit_bytes(&v), + Primitive::I128(v) => visitor.visit_i128(v), + Primitive::I256(v) => visitor.visit_bytes(&v), + } + } + + // if we're asked to deserialize into some numeric type, + // we do our best to visit that same type with a value, but + // if we can't coerce our value to it, we fall back to + // deserialize_any. + deserialize_number!(deserialize_u8 visit_u8); + deserialize_number!(deserialize_u16 visit_u16); + deserialize_number!(deserialize_u32 visit_u32); + deserialize_number!(deserialize_u64 visit_u64); + deserialize_number!(deserialize_u128 visit_u128); + deserialize_number!(deserialize_i8 visit_i8); + deserialize_number!(deserialize_i16 visit_i16); + deserialize_number!(deserialize_i32 visit_i32); + deserialize_number!(deserialize_i64 visit_i64); + deserialize_number!(deserialize_i128 visit_i128); + + 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 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, DeserializerError> for Primitive { - type Deserializer = Primitive; - fn into_deserializer(self) -> Self::Deserializer { - self - } + type Deserializer = Primitive; + fn into_deserializer(self) -> Self::Deserializer { + self + } } #[cfg(test)] mod test { - use super::*; - use serde::Deserialize; - - #[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::u128(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::u128(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::u128(123), - Value::bool(true), - Value::string("hello"), - ])); - - 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::u128(123), Value::bool(true), Value::string("hello")]); - - 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::String("hello".into())); - assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); - let val = Value::string("hello"); - assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); - - #[derive(Deserialize, Debug, PartialEq)] - struct FooVecU8(Vec); - let val = ValueDef::Composite(Composite::Unnamed(vec![ - Value::u128(1), - Value::u128(2), - Value::u128(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::u128(1), Value::u128(2), Value::u128(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::String("hello".into()); - assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); - - #[derive(Deserialize, Debug, PartialEq)] - struct FooVecU8(Vec); - let val = Composite::Unnamed(vec![Value::u128(1), Value::u128(2), Value::u128(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::u128(1), Value::u128(2), Value::u128(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::u128(1), - Value::u128(2), - Value::u128(3), - ])); - assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); - - let val = ValueDef::Composite(Composite::Unnamed(vec![ - Value::string("a"), - Value::string("b"), - Value::string("c"), - ])); - assert_eq!(>::deserialize(val), Ok(vec!["a".into(), "b".into(), "c".into()])); - } - - #[test] - fn de_unwrapped_into_vec() { - let val = Composite::Unnamed(vec![Value::u128(1), Value::u128(2), Value::u128(3)]); - assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); - - let val = Composite::Named(vec![ - ("a".into(), Value::u128(1)), - ("b".into(), Value::u128(2)), - ("c".into(), Value::u128(3)), - ]); - assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); - - let val = - Composite::Unnamed(vec![Value::string("a"), Value::string("b"), Value::string("c")]); - 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::u128(1)), - ("b".into(), Value::u128(2)), - ("c".into(), Value::u128(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::u128(1), - Value::u128(2), - Value::u128(3), - ])); - >::deserialize(val).expect_err("no names; can't be map"); - } - - #[test] - fn de_into_tuple() { - let val = ValueDef::Composite(Composite::Unnamed(vec![ - Value::string("hello"), - 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::string("hello")), - ("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::unnamed_fields( - "Foo", - vec![Value::string("hello"), 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::named_fields( - "Foo", - [("a", Value::string("hello")), ("b", 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::string("hello"), - Value::bool(true), - Value::u128(123), - ])); - <(String, bool)>::deserialize(val).expect_err("Wrong length, should err"); - } - - #[test] - fn de_unwrapped_into_tuple() { - let val = Composite::Unnamed(vec![Value::string("hello"), 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::string("hello")), - ("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::string("hello"), Value::bool(true), Value::u128(123)]); - <(String, bool)>::deserialize(val).expect_err("Wrong length, should err"); - } - - #[test] - fn de_bitvec() { - use scale_bits::bits; - - // If we deserialize a bitvec value into a value, it should come back out the same. - let val = Value::bit_sequence(bits![0, 1, 1, 0, 1, 0, 1, 0, 1]); - assert_eq!(Value::deserialize(val.clone()), Ok(val.clone())); - - // We can serialize a bitvec Value to something like JSON and deserialize it again, too. - let json_val = serde_json::to_value(&val).expect("can encode to json"); - let new_val: Value<()> = - serde_json::from_value(json_val).expect("can decode back from json"); - assert_eq!(new_val, val); - } - - #[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::string("hello"), - Value::bool(true), - Value::u128(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::string("hello")), - ("b".into(), Value::bool(true)), - ("c".into(), Value::u128(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::string("hello"), - Value::bool(true), - Value::u128(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::string("hello")), - ("b".into(), Value::bool(true)), - ("c".into(), Value::u128(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::u128(123)), - ("a".into(), Value::bool(true)), - ("hi".into(), Value::string("hello")), - ]), - }); - 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::string("hello"), - Value::bool(true), - Value::u128(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::u128(123), - Value::string("hello"), - ]), - }); - 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::u128(123)), - // Whoops; wrong name: - ("c".into(), Value::bool(true)), - ("hi".into(), Value::string("hello")), - ]), - }); - 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::u128(40)), - ("b".into(), Value::u128(123)), - ("a".into(), Value::bool(true)), - ("bar".into(), Value::bool(false)), - ("hi".into(), Value::string("hello")), - ]), - }); - 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", 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 {})); - } + use super::*; + use serde::Deserialize; + + #[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::u128(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::u128(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::u128(123), + Value::bool(true), + Value::string("hello"), + ])); + + 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::u128(123), Value::bool(true), Value::string("hello")]); + + 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::String("hello".into())); + assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); + let val = Value::string("hello"); + assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); + + #[derive(Deserialize, Debug, PartialEq)] + struct FooVecU8(Vec); + let val = ValueDef::Composite(Composite::Unnamed(vec![ + Value::u128(1), + Value::u128(2), + Value::u128(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::u128(1), Value::u128(2), Value::u128(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::String("hello".into()); + assert_eq!(FooStr::deserialize(val), Ok(FooStr("hello".into()))); + + #[derive(Deserialize, Debug, PartialEq)] + struct FooVecU8(Vec); + let val = Composite::Unnamed(vec![Value::u128(1), Value::u128(2), Value::u128(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::u128(1), Value::u128(2), Value::u128(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::u128(1), + Value::u128(2), + Value::u128(3), + ])); + assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); + + let val = ValueDef::Composite(Composite::Unnamed(vec![ + Value::string("a"), + Value::string("b"), + Value::string("c"), + ])); + assert_eq!(>::deserialize(val), Ok(vec!["a".into(), "b".into(), "c".into()])); + } + + #[test] + fn de_unwrapped_into_vec() { + let val = Composite::Unnamed(vec![Value::u128(1), Value::u128(2), Value::u128(3)]); + assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); + + let val = Composite::Named(vec![ + ("a".into(), Value::u128(1)), + ("b".into(), Value::u128(2)), + ("c".into(), Value::u128(3)), + ]); + assert_eq!(>::deserialize(val), Ok(vec![1, 2, 3])); + + let val = + Composite::Unnamed(vec![Value::string("a"), Value::string("b"), Value::string("c")]); + 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::u128(1)), + ("b".into(), Value::u128(2)), + ("c".into(), Value::u128(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::u128(1), + Value::u128(2), + Value::u128(3), + ])); + >::deserialize(val).expect_err("no names; can't be map"); + } + + #[test] + fn de_into_tuple() { + let val = ValueDef::Composite(Composite::Unnamed(vec![ + Value::string("hello"), + 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::string("hello")), + ("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::unnamed_fields( + "Foo", + vec![Value::string("hello"), 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::named_fields( + "Foo", + [("a", Value::string("hello")), ("b", 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::string("hello"), + Value::bool(true), + Value::u128(123), + ])); + <(String, bool)>::deserialize(val).expect_err("Wrong length, should err"); + } + + #[test] + fn de_unwrapped_into_tuple() { + let val = Composite::Unnamed(vec![Value::string("hello"), 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::string("hello")), + ("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::string("hello"), Value::bool(true), Value::u128(123)]); + <(String, bool)>::deserialize(val).expect_err("Wrong length, should err"); + } + + #[test] + fn de_bitvec() { + use scale_bits::bits; + + // If we deserialize a bitvec value into a value, it should come back out the same. + let val = Value::bit_sequence(bits![0, 1, 1, 0, 1, 0, 1, 0, 1]); + assert_eq!(Value::deserialize(val.clone()), Ok(val.clone())); + + // We can serialize a bitvec Value to something like JSON and deserialize it again, too. + let json_val = serde_json::to_value(&val).expect("can encode to json"); + let new_val: Value<()> = + serde_json::from_value(json_val).expect("can decode back from json"); + assert_eq!(new_val, val); + } + + #[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::string("hello"), + Value::bool(true), + Value::u128(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::string("hello")), + ("b".into(), Value::bool(true)), + ("c".into(), Value::u128(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::string("hello"), + Value::bool(true), + Value::u128(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::string("hello")), + ("b".into(), Value::bool(true)), + ("c".into(), Value::u128(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::u128(123)), + ("a".into(), Value::bool(true)), + ("hi".into(), Value::string("hello")), + ]), + }); + 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::string("hello"), + Value::bool(true), + Value::u128(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::u128(123), + Value::string("hello"), + ]), + }); + 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::u128(123)), + // Whoops; wrong name: + ("c".into(), Value::bool(true)), + ("hi".into(), Value::string("hello")), + ]), + }); + 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::u128(40)), + ("b".into(), Value::u128(123)), + ("a".into(), Value::bool(true)), + ("bar".into(), Value::bool(false)), + ("hi".into(), Value::string("hello")), + ]), + }); + 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", 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/src/serde_impls/serialize.rs b/src/serde_impls/serialize.rs index 94056f7..5d99b05 100644 --- a/src/serde_impls/serialize.rs +++ b/src/serde_impls/serialize.rs @@ -22,208 +22,208 @@ use super::bitvec_helpers; use crate::{Composite, Primitive, Value, ValueDef, Variant}; use serde::{ - ser::{SerializeMap, SerializeSeq}, - Serialize, Serializer, + ser::{SerializeMap, SerializeSeq}, + Serialize, Serializer, }; impl Serialize for Value { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - self.value.serialize(serializer) - } + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.value.serialize(serializer) + } } impl Serialize for ValueDef { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - match self { - ValueDef::Composite(val) => val.serialize(serializer), - ValueDef::Variant(val) => val.serialize(serializer), - ValueDef::Primitive(val) => val.serialize(serializer), - ValueDef::BitSequence(val) => bitvec_helpers::serialize_bitvec(val, serializer), - } - } + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + match self { + ValueDef::Composite(val) => val.serialize(serializer), + ValueDef::Variant(val) => val.serialize(serializer), + ValueDef::Primitive(val) => val.serialize(serializer), + ValueDef::BitSequence(val) => bitvec_helpers::serialize_bitvec(val, serializer), + } + } } impl Serialize for Composite { - fn serialize(&self, serializer: S) -> Result - where - S: 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() - } - } - } + fn serialize(&self, serializer: S) -> Result + where + S: 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() + } + } + } } macro_rules! serialize_as_first_ok_type { - ($serializer:ident $val:ident; $first:ident $($rest:ident)*) => {{ - let n: Result<$first,_> = $val.try_into(); - match n { - Ok(n) => n.serialize($serializer), - Err(_) => serialize_as_first_ok_type!($serializer $val; $($rest)*) - } - }}; - ($serializer:ident $val:ident;) => {{ - $val.serialize($serializer) - }}; + ($serializer:ident $val:ident; $first:ident $($rest:ident)*) => {{ + let n: Result<$first,_> = $val.try_into(); + match n { + Ok(n) => n.serialize($serializer), + Err(_) => serialize_as_first_ok_type!($serializer $val; $($rest)*) + } + }}; + ($serializer:ident $val:ident;) => {{ + $val.serialize($serializer) + }}; } impl Serialize for Primitive { - fn serialize(&self, serializer: S) -> Result - where - S: 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::String(v) => v.serialize(serializer), - Primitive::U128(v) => { - // Serialize into the smallest type that fits, since formats like - // JSON don't like u128's by default. - let v = *v; - serialize_as_first_ok_type!(serializer v; u8 u16 u32 u64 u128) - } - Primitive::U256(v) => v.serialize(serializer), - Primitive::I128(v) => { - // Serialize into the smallest type that fits, since formats like - // JSON don't like i128's by default. - let v = *v; - serialize_as_first_ok_type!(serializer v; i8 i16 i32 i64 i128) - } - Primitive::I256(v) => v.serialize(serializer), - } - } + fn serialize(&self, serializer: S) -> Result + where + S: 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::String(v) => v.serialize(serializer), + Primitive::U128(v) => { + // Serialize into the smallest type that fits, since formats like + // JSON don't like u128's by default. + let v = *v; + serialize_as_first_ok_type!(serializer v; u8 u16 u32 u64 u128) + } + Primitive::U256(v) => v.serialize(serializer), + Primitive::I128(v) => { + // Serialize into the smallest type that fits, since formats like + // JSON don't like i128's by default. + let v = *v; + serialize_as_first_ok_type!(serializer v; i8 i16 i32 i64 i128) + } + Primitive::I256(v) => v.serialize(serializer), + } + } } impl Serialize for Variant { - fn serialize(&self, serializer: S) -> Result - where - S: 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() - } + fn serialize(&self, serializer: S) -> Result + where + S: 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; + 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); - } + 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::u128(1), json!(1)); - assert_value(Value::bool(true), json!(true)); - assert_value(Value::bool(false), json!(false)); - } + #[test] + fn serialize_primitives() { + // a subset of the primitives to sanity check that they are unwrapped: + assert_value(Value::u128(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([ - ("a", Value::bool(true)), - ("b", Value::string("hello")), - ("c", Value::char('c')), - ]), - json!({ - "a": true, - "b": "hello", - "c": 'c' - }), - ); - assert_value( - Value::unnamed_composite([Value::bool(true), Value::string("hello"), Value::char('c')]), - json!([true, "hello", 'c']), - ) - } + #[test] + fn serialize_composites() { + assert_value( + Value::named_composite([ + ("a", Value::bool(true)), + ("b", Value::string("hello")), + ("c", Value::char('c')), + ]), + json!({ + "a": true, + "b": "hello", + "c": 'c' + }), + ); + assert_value( + Value::unnamed_composite([Value::bool(true), Value::string("hello"), Value::char('c')]), + json!([true, "hello", 'c']), + ) + } - #[test] - fn serialize_variants() { - assert_value( - Value::variant( - "Foo", - Composite::Named(vec![ - ("a".into(), Value::bool(true)), - ("b".into(), Value::string("hello")), - ("c".into(), Value::char('c')), - ]), - ), - json!({ - "name": "Foo", - "values": { - "a": true, - "b": "hello", - "c": 'c' - } - }), - ); - assert_value( - Value::variant( - "Bar", - Composite::Unnamed(vec![ - Value::bool(true), - Value::string("hello"), - Value::char('c'), - ]), - ), - json!({ - "name": "Bar", - "values": [ - true, - "hello", - 'c' - ] - }), - ) - } + #[test] + fn serialize_variants() { + assert_value( + Value::variant( + "Foo", + Composite::Named(vec![ + ("a".into(), Value::bool(true)), + ("b".into(), Value::string("hello")), + ("c".into(), Value::char('c')), + ]), + ), + json!({ + "name": "Foo", + "values": { + "a": true, + "b": "hello", + "c": 'c' + } + }), + ); + assert_value( + Value::variant( + "Bar", + Composite::Unnamed(vec![ + Value::bool(true), + Value::string("hello"), + Value::char('c'), + ]), + ), + json!({ + "name": "Bar", + "values": [ + true, + "hello", + 'c' + ] + }), + ) + } - #[test] - fn serialize_bitsequences() { - use scale_bits::bits; + #[test] + fn serialize_bitsequences() { + use scale_bits::bits; - assert_value( - Value::bit_sequence(bits![]), - json!({ - "__bitvec__values__": [] - }), - ); - assert_value( - Value::bit_sequence(bits![0, 1, 1, 0, 1]), - json!({ - "__bitvec__values__": [false, true, true, false, true] - }), - ); - } + assert_value( + Value::bit_sequence(bits![]), + json!({ + "__bitvec__values__": [] + }), + ); + assert_value( + Value::bit_sequence(bits![0, 1, 1, 0, 1]), + json!({ + "__bitvec__values__": [false, true, true, false, true] + }), + ); + } } diff --git a/src/serde_impls/serializer.rs b/src/serde_impls/serializer.rs index 8eaf2d0..58fae33 100644 --- a/src/serde_impls/serializer.rs +++ b/src/serde_impls/serializer.rs @@ -18,11 +18,11 @@ use crate::{Composite, Primitive, Value, ValueDef}; use serde::{ - ser::{ - SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, - SerializeTupleStruct, SerializeTupleVariant, - }, - Serializer, + ser::{ + SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, SerializeTuple, + SerializeTupleStruct, SerializeTupleVariant, + }, + Serializer, }; /// This struct implements [`Serializer`] and knows how to map from the serde data model to a [`Value`] type. @@ -31,560 +31,560 @@ pub struct ValueSerializer; /// An error that can occur when attempting to serialize a type into a [`Value`]. #[derive(thiserror::Error, Debug, Clone, PartialEq, Eq)] pub enum SerializerError { - /// Some custom error string. - #[error("{0}")] - Custom(String), - /// SCALE does not support floating point values, and so we'll hit this error if we try to - /// encode any floats. - #[error("Floats do not have a SCALE compatible representation, and so cannot be serialized to Values")] - CannotSerializeFloats, - /// SCALE encoding is only designed to map from statically known structs to bytes. We use field names - /// to figure out this mapping between named composite types and structs, so we don't support encoding - /// maps with non-string keys into [`Value`]s. - #[error("Map keys must be strings or string-like")] - MapKeyMustBeStringlike, + /// Some custom error string. + #[error("{0}")] + Custom(String), + /// SCALE does not support floating point values, and so we'll hit this error if we try to + /// encode any floats. + #[error("Floats do not have a SCALE compatible representation, and so cannot be serialized to Values")] + CannotSerializeFloats, + /// SCALE encoding is only designed to map from statically known structs to bytes. We use field names + /// to figure out this mapping between named composite types and structs, so we don't support encoding + /// maps with non-string keys into [`Value`]s. + #[error("Map keys must be strings or string-like")] + MapKeyMustBeStringlike, } impl serde::ser::Error for SerializerError { - fn custom(msg: T) -> Self - where - T: std::fmt::Display, - { - SerializerError::Custom(msg.to_string()) - } + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + SerializerError::Custom(msg.to_string()) + } } macro_rules! serialize_prim { - ($name:ident => $method:ident($ty:ident)) => { - fn $name(self, v: $ty) -> Result { - Ok(Value::$method(v.into())) - } - }; + ($name:ident => $method:ident($ty:ident)) => { + fn $name(self, v: $ty) -> Result { + Ok(Value::$method(v.into())) + } + }; } impl Serializer for ValueSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - type SerializeSeq = UnnamedCompositeSerializer; - type SerializeTuple = UnnamedCompositeSerializer; - type SerializeTupleStruct = UnnamedCompositeSerializer; - type SerializeTupleVariant = UnnamedCompositeSerializer; - type SerializeMap = NamedCompositeSerializer; - type SerializeStruct = NamedCompositeSerializer; - type SerializeStructVariant = NamedCompositeSerializer; - - serialize_prim!(serialize_bool => bool(bool)); - serialize_prim!(serialize_i8 => i128(i8)); - serialize_prim!(serialize_i16 => i128(i16)); - serialize_prim!(serialize_i32 => i128(i32)); - serialize_prim!(serialize_i64 => i128(i64)); - serialize_prim!(serialize_i128 => i128(i128)); - serialize_prim!(serialize_u8 => u128(u8)); - serialize_prim!(serialize_u16 => u128(u16)); - serialize_prim!(serialize_u32 => u128(u32)); - serialize_prim!(serialize_u64 => u128(u64)); - serialize_prim!(serialize_u128 => u128(u128)); - serialize_prim!(serialize_char => char(char)); - - fn serialize_f32(self, _v: f32) -> Result { - Err(SerializerError::CannotSerializeFloats) - } - fn serialize_f64(self, _v: f64) -> Result { - Err(SerializerError::CannotSerializeFloats) - } - - fn serialize_str(self, v: &str) -> Result { - Ok(Value::string(v.to_string())) - } - - fn serialize_bytes(self, v: &[u8]) -> Result { - let bytes = v.iter().map(|&b| Value::u128(b as u128)); - Ok(Value::unnamed_composite(bytes)) - } - - fn serialize_none(self) -> Result { - Ok(Value::variant("None".to_string(), Composite::Unnamed(Vec::new()))) - } - - fn serialize_some(self, value: &T) -> Result - where - T: serde::Serialize, - { - let inner = value.serialize(ValueSerializer)?; - Ok(Value::variant("Some".to_string(), Composite::Unnamed(vec![inner]))) - } - - fn serialize_unit(self) -> Result { - Ok(Value::unnamed_composite(Vec::new())) - } - - fn serialize_unit_struct(self, _name: &'static str) -> Result { - Ok(Value::unnamed_composite(Vec::new())) - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result { - Ok(Value::variant(variant.to_string(), Composite::Unnamed(Vec::new()))) - } - - fn serialize_newtype_struct( - self, - _name: &'static str, - value: &T, - ) -> Result - where - T: serde::Serialize, - { - let inner = value.serialize(ValueSerializer)?; - Ok(Value::unnamed_composite(vec![inner])) - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result - where - T: serde::Serialize, - { - let inner = value.serialize(ValueSerializer)?; - Ok(Value::variant(variant.to_string(), Composite::Unnamed(vec![inner]))) - } - - fn serialize_seq(self, _len: Option) -> Result { - Ok(Self::SerializeSeq::new_composite()) - } - - fn serialize_tuple(self, _len: usize) -> Result { - Ok(Self::SerializeTuple::new_composite()) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - Ok(Self::SerializeTupleStruct::new_composite()) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - Ok(Self::SerializeTupleVariant::new_variant(variant.into())) - } - - fn serialize_map(self, _len: Option) -> Result { - Ok(Self::SerializeMap::new_composite()) - } - - fn serialize_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - Ok(Self::SerializeStruct::new_composite()) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - Ok(Self::SerializeStructVariant::new_variant(variant.into())) - } + type Ok = Value<()>; + type Error = SerializerError; + + type SerializeSeq = UnnamedCompositeSerializer; + type SerializeTuple = UnnamedCompositeSerializer; + type SerializeTupleStruct = UnnamedCompositeSerializer; + type SerializeTupleVariant = UnnamedCompositeSerializer; + type SerializeMap = NamedCompositeSerializer; + type SerializeStruct = NamedCompositeSerializer; + type SerializeStructVariant = NamedCompositeSerializer; + + serialize_prim!(serialize_bool => bool(bool)); + serialize_prim!(serialize_i8 => i128(i8)); + serialize_prim!(serialize_i16 => i128(i16)); + serialize_prim!(serialize_i32 => i128(i32)); + serialize_prim!(serialize_i64 => i128(i64)); + serialize_prim!(serialize_i128 => i128(i128)); + serialize_prim!(serialize_u8 => u128(u8)); + serialize_prim!(serialize_u16 => u128(u16)); + serialize_prim!(serialize_u32 => u128(u32)); + serialize_prim!(serialize_u64 => u128(u64)); + serialize_prim!(serialize_u128 => u128(u128)); + serialize_prim!(serialize_char => char(char)); + + fn serialize_f32(self, _v: f32) -> Result { + Err(SerializerError::CannotSerializeFloats) + } + fn serialize_f64(self, _v: f64) -> Result { + Err(SerializerError::CannotSerializeFloats) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(Value::string(v.to_string())) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + let bytes = v.iter().map(|&b| Value::u128(b as u128)); + Ok(Value::unnamed_composite(bytes)) + } + + fn serialize_none(self) -> Result { + Ok(Value::variant("None".to_string(), Composite::Unnamed(Vec::new()))) + } + + fn serialize_some(self, value: &T) -> Result + where + T: serde::Serialize, + { + let inner = value.serialize(ValueSerializer)?; + Ok(Value::variant("Some".to_string(), Composite::Unnamed(vec![inner]))) + } + + fn serialize_unit(self) -> Result { + Ok(Value::unnamed_composite(Vec::new())) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Ok(Value::unnamed_composite(Vec::new())) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(Value::variant(variant.to_string(), Composite::Unnamed(Vec::new()))) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result + where + T: serde::Serialize, + { + let inner = value.serialize(ValueSerializer)?; + Ok(Value::unnamed_composite(vec![inner])) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result + where + T: serde::Serialize, + { + let inner = value.serialize(ValueSerializer)?; + Ok(Value::variant(variant.to_string(), Composite::Unnamed(vec![inner]))) + } + + fn serialize_seq(self, _len: Option) -> Result { + Ok(Self::SerializeSeq::new_composite()) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Ok(Self::SerializeTuple::new_composite()) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(Self::SerializeTupleStruct::new_composite()) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(Self::SerializeTupleVariant::new_variant(variant.into())) + } + + fn serialize_map(self, _len: Option) -> Result { + Ok(Self::SerializeMap::new_composite()) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Ok(Self::SerializeStruct::new_composite()) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + Ok(Self::SerializeStructVariant::new_variant(variant.into())) + } } // Serializes anything that should end up as an unnamed composite value: pub struct UnnamedCompositeSerializer { - // Only present if the thing should be a variant: - variant_name: Option, - values: Vec>, + // Only present if the thing should be a variant: + variant_name: Option, + values: Vec>, } impl UnnamedCompositeSerializer { - fn new_composite() -> UnnamedCompositeSerializer { - UnnamedCompositeSerializer { variant_name: None, values: Vec::new() } - } - - fn new_variant(variant_name: String) -> UnnamedCompositeSerializer { - UnnamedCompositeSerializer { variant_name: Some(variant_name), values: Vec::new() } - } - - fn serialize_element(&mut self, value: &T) -> Result<(), SerializerError> - where - T: serde::Serialize, - { - let inner = value.serialize(ValueSerializer)?; - self.values.push(inner); - Ok(()) - } - - fn end(self) -> Result, SerializerError> { - match self.variant_name { - Some(name) => Ok(Value::variant(name, Composite::Unnamed(self.values))), - None => Ok(Value::unnamed_composite(self.values)), - } - } + fn new_composite() -> UnnamedCompositeSerializer { + UnnamedCompositeSerializer { variant_name: None, values: Vec::new() } + } + + fn new_variant(variant_name: String) -> UnnamedCompositeSerializer { + UnnamedCompositeSerializer { variant_name: Some(variant_name), values: Vec::new() } + } + + fn serialize_element(&mut self, value: &T) -> Result<(), SerializerError> + where + T: serde::Serialize, + { + let inner = value.serialize(ValueSerializer)?; + self.values.push(inner); + Ok(()) + } + + fn end(self) -> Result, SerializerError> { + match self.variant_name { + Some(name) => Ok(Value::variant(name, Composite::Unnamed(self.values))), + None => Ok(Value::unnamed_composite(self.values)), + } + } } impl SerializeSeq for UnnamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - self.serialize_element(value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.serialize_element(value) + } + + fn end(self) -> Result { + self.end() + } } impl SerializeTuple for UnnamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - self.serialize_element(value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.serialize_element(value) + } + + fn end(self) -> Result { + self.end() + } } impl SerializeTupleStruct for UnnamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - self.serialize_element(value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.serialize_element(value) + } + + fn end(self) -> Result { + self.end() + } } impl SerializeTupleVariant for UnnamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - self.serialize_element(value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.serialize_element(value) + } + + fn end(self) -> Result { + self.end() + } } // Serializes things into named composite types. pub struct NamedCompositeSerializer { - // Only present if the thing should be a variant: - variant_name: Option, - values: Vec<(String, Value<()>)>, - key: Option, + // Only present if the thing should be a variant: + variant_name: Option, + values: Vec<(String, Value<()>)>, + key: Option, } impl NamedCompositeSerializer { - fn new_composite() -> Self { - NamedCompositeSerializer { variant_name: None, values: Vec::new(), key: None } - } - - fn new_variant(variant_name: String) -> Self { - NamedCompositeSerializer { variant_name: Some(variant_name), values: Vec::new(), key: None } - } - - fn serialize_field(&mut self, key: &str, value: &T) -> Result<(), SerializerError> - where - T: serde::Serialize, - { - let key = key.to_string(); - let inner = value.serialize(ValueSerializer)?; - self.values.push((key, inner)); - Ok(()) - } - - fn end(self) -> Result, SerializerError> { - match self.variant_name { - Some(name) => Ok(Value::variant(name, Composite::Named(self.values))), - None => Ok(Value::named_composite(self.values)), - } - } + fn new_composite() -> Self { + NamedCompositeSerializer { variant_name: None, values: Vec::new(), key: None } + } + + fn new_variant(variant_name: String) -> Self { + NamedCompositeSerializer { variant_name: Some(variant_name), values: Vec::new(), key: None } + } + + fn serialize_field(&mut self, key: &str, value: &T) -> Result<(), SerializerError> + where + T: serde::Serialize, + { + let key = key.to_string(); + let inner = value.serialize(ValueSerializer)?; + self.values.push((key, inner)); + Ok(()) + } + + fn end(self) -> Result, SerializerError> { + match self.variant_name { + Some(name) => Ok(Value::variant(name, Composite::Named(self.values))), + None => Ok(Value::named_composite(self.values)), + } + } } impl SerializeMap for NamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - let inner = key.serialize(ValueSerializer)?; - // Map keys must be stringish, because named composite values are strings - // and will be matched with the corresponding field names on struct types - // to SCALE encode/decode. - let key = match inner.value { - ValueDef::Primitive(Primitive::String(s)) => s, - ValueDef::Primitive(Primitive::Char(c)) => c.to_string(), - _ => return Err(SerializerError::MapKeyMustBeStringlike), - }; - self.key = Some(key); - Ok(()) - } - - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - let key = self.key.take().expect("serialize_key must be called prior to serialize_value"); - self.serialize_field(&key, value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + let inner = key.serialize(ValueSerializer)?; + // Map keys must be stringish, because named composite values are strings + // and will be matched with the corresponding field names on struct types + // to SCALE encode/decode. + let key = match inner.value { + ValueDef::Primitive(Primitive::String(s)) => s, + ValueDef::Primitive(Primitive::Char(c)) => c.to_string(), + _ => return Err(SerializerError::MapKeyMustBeStringlike), + }; + self.key = Some(key); + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + let key = self.key.take().expect("serialize_key must be called prior to serialize_value"); + self.serialize_field(&key, value) + } + + fn end(self) -> Result { + self.end() + } } impl SerializeStruct for NamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - self.serialize_field(key, value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.serialize_field(key, value) + } + + fn end(self) -> Result { + self.end() + } } impl SerializeStructVariant for NamedCompositeSerializer { - type Ok = Value<()>; - type Error = SerializerError; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> - where - T: serde::Serialize, - { - self.serialize_field(key, value) - } - - fn end(self) -> Result { - self.end() - } + type Ok = Value<()>; + type Error = SerializerError; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: serde::Serialize, + { + self.serialize_field(key, value) + } + + fn end(self) -> Result { + self.end() + } } #[cfg(test)] mod test { - use super::ValueSerializer; - use crate::{Composite, Value}; - use serde::{Deserialize, Serialize}; - use std::fmt::Debug; - - // Make sure that things can serialize and deserialize back losslessly. - fn assert_ser_de + Debug + PartialEq>(val: T) { - let actual = val.serialize(ValueSerializer).expect("can serialize"); - let actual = T::deserialize(actual).expect("can deserialize again"); - assert_eq!(val, actual, "value did not come deserialize back to the same"); - } - - // Make sure that things can serialize and deserialize back losslessly and to the expected Value. - fn assert_ser_de_eq + Debug + PartialEq>( - val: T, - value: Value<()>, - ) { - // serialize and compare: - let actual = val.serialize(ValueSerializer).expect("can serialize"); - assert_eq!(value, actual, "serializing mismatch"); - // deserialize back and check we get the same thing back out: - let actual = T::deserialize(actual).expect("can deserialize again"); - assert_eq!(val, actual, "deserialing mismatch"); - } - - #[test] - fn ser_de_primitives() { - assert_ser_de_eq(123u8, Value::u128(123)); - assert_ser_de_eq(123u16, Value::u128(123)); - assert_ser_de_eq(123u32, Value::u128(123)); - assert_ser_de_eq(123u64, Value::u128(123)); - assert_ser_de_eq(123u128, Value::u128(123)); - - assert_ser_de_eq(123i8, Value::i128(123)); - assert_ser_de_eq(123i16, Value::i128(123)); - assert_ser_de_eq(123i32, Value::i128(123)); - assert_ser_de_eq(123i64, Value::i128(123)); - assert_ser_de_eq(123i128, Value::i128(123)); - - assert_ser_de_eq(true, Value::bool(true)); - assert_ser_de_eq(false, Value::bool(false)); - - assert_ser_de_eq("hello".to_string(), Value::string("hello")); - assert_ser_de_eq('a', Value::char('a')); - } - - #[test] - fn ser_de_optionals() { - let val = Value::variant("Some".to_string(), Composite::Unnamed(vec![Value::u128(123)])); - assert_ser_de_eq(Some(123u8), val); - - let val = Value::variant("None".to_string(), Composite::Unnamed(Vec::new())); - assert_ser_de_eq(None as Option, val); - } - - #[test] - fn ser_de_unit_struct() { - #[derive(Deserialize, Serialize, Debug, PartialEq)] - struct Foo; - - let val = Value::unnamed_composite([]); - - assert_ser_de_eq(Foo, val); - } - - #[test] - fn ser_de_named_struct() { - #[derive(Deserialize, Serialize, Debug, PartialEq)] - struct Foo { - a: u8, - b: bool, - } - - let val = Value::named_composite([("a", Value::u128(123)), ("b", Value::bool(true))]); - - assert_ser_de_eq(Foo { a: 123, b: true }, val); - } - - #[test] - fn ser_de_tuple_struct() { - #[derive(Deserialize, Serialize, Debug, PartialEq)] - struct Foo(u8, bool); - - let val = Value::unnamed_composite(vec![Value::u128(123), Value::bool(true)]); - - assert_ser_de_eq(Foo(123, true), val); - } - - #[test] - fn ser_de_sequences() { - assert_ser_de_eq( - vec![1, 2, 3, 4, 5u8], - Value::unnamed_composite(vec![ - Value::u128(1), - Value::u128(2), - Value::u128(3), - Value::u128(4), - Value::u128(5), - ]), - ); - - assert_ser_de_eq( - [1, 2, 3, 4, 5u8], - Value::unnamed_composite(vec![ - Value::u128(1), - Value::u128(2), - Value::u128(3), - Value::u128(4), - Value::u128(5), - ]), - ); - - assert_ser_de_eq( - (1u8, true, 'a', "hello".to_string()), - Value::unnamed_composite(vec![ - Value::u128(1), - Value::bool(true), - Value::char('a'), - Value::string("hello"), - ]), - ); - } - - #[test] - fn ser_de_variants() { - #[derive(Debug, PartialEq, Serialize, Deserialize)] - enum Foo { - A(bool, u8), - B, - C { hello: String, value: i64 }, - } - - assert_ser_de_eq( - Foo::A(true, 123), - Value::variant("A", Composite::Unnamed(vec![Value::bool(true), Value::u128(123)])), - ); - assert_ser_de_eq(Foo::B, Value::variant("B", Composite::Unnamed(vec![]))); - assert_ser_de_eq( - Foo::C { hello: "World".to_string(), value: 123 }, - Value::variant( - "C", - Composite::Named(vec![ - ("hello".to_string(), Value::string("World")), - ("value".to_string(), Value::i128(123)), - ]), - ), - ); - } - - #[test] - fn ser_de_maps() { - use std::collections::HashMap; - - let m = { - let mut m = HashMap::new(); - m.insert("a".to_string(), 1u8); - m.insert("b".to_string(), 2u8); - m.insert("c".to_string(), 3u8); - m - }; - assert_ser_de(m); - - // chars as keys are fine, too: - let m = { - let mut m = HashMap::new(); - m.insert('a', 1u8); - m.insert('b', 2u8); - m.insert('c', 3u8); - m - }; - assert_ser_de(m); - } + use super::ValueSerializer; + use crate::{Composite, Value}; + use serde::{Deserialize, Serialize}; + use std::fmt::Debug; + + // Make sure that things can serialize and deserialize back losslessly. + fn assert_ser_de + Debug + PartialEq>(val: T) { + let actual = val.serialize(ValueSerializer).expect("can serialize"); + let actual = T::deserialize(actual).expect("can deserialize again"); + assert_eq!(val, actual, "value did not come deserialize back to the same"); + } + + // Make sure that things can serialize and deserialize back losslessly and to the expected Value. + fn assert_ser_de_eq + Debug + PartialEq>( + val: T, + value: Value<()>, + ) { + // serialize and compare: + let actual = val.serialize(ValueSerializer).expect("can serialize"); + assert_eq!(value, actual, "serializing mismatch"); + // deserialize back and check we get the same thing back out: + let actual = T::deserialize(actual).expect("can deserialize again"); + assert_eq!(val, actual, "deserialing mismatch"); + } + + #[test] + fn ser_de_primitives() { + assert_ser_de_eq(123u8, Value::u128(123)); + assert_ser_de_eq(123u16, Value::u128(123)); + assert_ser_de_eq(123u32, Value::u128(123)); + assert_ser_de_eq(123u64, Value::u128(123)); + assert_ser_de_eq(123u128, Value::u128(123)); + + assert_ser_de_eq(123i8, Value::i128(123)); + assert_ser_de_eq(123i16, Value::i128(123)); + assert_ser_de_eq(123i32, Value::i128(123)); + assert_ser_de_eq(123i64, Value::i128(123)); + assert_ser_de_eq(123i128, Value::i128(123)); + + assert_ser_de_eq(true, Value::bool(true)); + assert_ser_de_eq(false, Value::bool(false)); + + assert_ser_de_eq("hello".to_string(), Value::string("hello")); + assert_ser_de_eq('a', Value::char('a')); + } + + #[test] + fn ser_de_optionals() { + let val = Value::variant("Some".to_string(), Composite::Unnamed(vec![Value::u128(123)])); + assert_ser_de_eq(Some(123u8), val); + + let val = Value::variant("None".to_string(), Composite::Unnamed(Vec::new())); + assert_ser_de_eq(None as Option, val); + } + + #[test] + fn ser_de_unit_struct() { + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct Foo; + + let val = Value::unnamed_composite([]); + + assert_ser_de_eq(Foo, val); + } + + #[test] + fn ser_de_named_struct() { + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct Foo { + a: u8, + b: bool, + } + + let val = Value::named_composite([("a", Value::u128(123)), ("b", Value::bool(true))]); + + assert_ser_de_eq(Foo { a: 123, b: true }, val); + } + + #[test] + fn ser_de_tuple_struct() { + #[derive(Deserialize, Serialize, Debug, PartialEq)] + struct Foo(u8, bool); + + let val = Value::unnamed_composite(vec![Value::u128(123), Value::bool(true)]); + + assert_ser_de_eq(Foo(123, true), val); + } + + #[test] + fn ser_de_sequences() { + assert_ser_de_eq( + vec![1, 2, 3, 4, 5u8], + Value::unnamed_composite(vec![ + Value::u128(1), + Value::u128(2), + Value::u128(3), + Value::u128(4), + Value::u128(5), + ]), + ); + + assert_ser_de_eq( + [1, 2, 3, 4, 5u8], + Value::unnamed_composite(vec![ + Value::u128(1), + Value::u128(2), + Value::u128(3), + Value::u128(4), + Value::u128(5), + ]), + ); + + assert_ser_de_eq( + (1u8, true, 'a', "hello".to_string()), + Value::unnamed_composite(vec![ + Value::u128(1), + Value::bool(true), + Value::char('a'), + Value::string("hello"), + ]), + ); + } + + #[test] + fn ser_de_variants() { + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum Foo { + A(bool, u8), + B, + C { hello: String, value: i64 }, + } + + assert_ser_de_eq( + Foo::A(true, 123), + Value::variant("A", Composite::Unnamed(vec![Value::bool(true), Value::u128(123)])), + ); + assert_ser_de_eq(Foo::B, Value::variant("B", Composite::Unnamed(vec![]))); + assert_ser_de_eq( + Foo::C { hello: "World".to_string(), value: 123 }, + Value::variant( + "C", + Composite::Named(vec![ + ("hello".to_string(), Value::string("World")), + ("value".to_string(), Value::i128(123)), + ]), + ), + ); + } + + #[test] + fn ser_de_maps() { + use std::collections::HashMap; + + let m = { + let mut m = HashMap::new(); + m.insert("a".to_string(), 1u8); + m.insert("b".to_string(), 2u8); + m.insert("c".to_string(), 3u8); + m + }; + assert_ser_de(m); + + // chars as keys are fine, too: + let m = { + let mut m = HashMap::new(); + m.insert('a', 1u8); + m.insert('b', 2u8); + m.insert('c', 3u8); + m + }; + assert_ser_de(m); + } } diff --git a/src/string_impls/from_string.rs b/src/string_impls/from_string.rs index a3fd2e0..18c14d2 100644 --- a/src/string_impls/from_string.rs +++ b/src/string_impls/from_string.rs @@ -21,158 +21,158 @@ use std::num::ParseIntError; use yap::{IntoTokens, TokenLocation, Tokens}; pub fn from_str(s: &str) -> (Result, ParseError>, &str) { - let mut toks = s.into_tokens(); - let res = parse_value(&mut toks); - let remaining = toks.remaining(); - (res, remaining) + let mut toks = s.into_tokens(); + let res = parse_value(&mut toks); + let remaining = toks.remaining(); + (res, remaining) } /// An error parsing the provided string into a Value #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub struct ParseError { - /// Byte offset into the provided string that the error begins. - pub start_loc: usize, - /// Byte offset into the provided string that the error ends. Many errors begin at some - /// point but do not have a known end position. - pub end_loc: Option, - /// Details about the error that occurred. - pub err: ParseErrorKind, + /// Byte offset into the provided string that the error begins. + pub start_loc: usize, + /// Byte offset into the provided string that the error ends. Many errors begin at some + /// point but do not have a known end position. + pub end_loc: Option, + /// Details about the error that occurred. + pub err: ParseErrorKind, } impl ParseError { - fn new_at(err: ParseErrorKind, loc: usize) -> Self { - Self { start_loc: loc, end_loc: None, err } - } - fn new_between(err: ParseErrorKind, start: usize, end: usize) -> Self { - Self { start_loc: start, end_loc: Some(end), err } - } + fn new_at(err: ParseErrorKind, loc: usize) -> Self { + Self { start_loc: loc, end_loc: None, err } + } + fn new_between(err: ParseErrorKind, start: usize, end: usize) -> Self { + Self { start_loc: start, end_loc: Some(end), err } + } } impl std::fmt::Display for ParseError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if let Some(end_loc) = self.end_loc { - write!(f, "Error from char {} to {}: {}", self.start_loc, end_loc, self.err) - } else { - write!(f, "Error at char {}: {}", self.start_loc, self.err) - } - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if let Some(end_loc) = self.end_loc { + write!(f, "Error from char {} to {}: {}", self.start_loc, end_loc, self.err) + } else { + write!(f, "Error at char {}: {}", self.start_loc, self.err) + } + } } /// Details about the error that occurred. #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum ParseErrorKind { - #[error("Expected a value")] - ExpectedValue, - #[error("{0}")] - Complex(#[from] ParseComplexError), - #[error("{0}")] - Char(#[from] ParseCharError), - #[error("{0}")] - String(#[from] ParseStringError), - #[error("{0}")] - Number(#[from] ParseNumberError), - #[error("{0}")] - BitSequence(#[from] ParseBitSequenceError), + #[error("Expected a value")] + ExpectedValue, + #[error("{0}")] + Complex(#[from] ParseComplexError), + #[error("{0}")] + Char(#[from] ParseCharError), + #[error("{0}")] + String(#[from] ParseStringError), + #[error("{0}")] + Number(#[from] ParseNumberError), + #[error("{0}")] + BitSequence(#[from] ParseBitSequenceError), } // Add handy helper methods to sub-error-kinds macro_rules! at_between { - ($ty:ident) => { - impl $ty { - /// Error at a specific location with no specific end - #[allow(unused)] - fn at(self, loc: usize) -> ParseError { - let e: ParseErrorKind = self.into(); - ParseError::new_at(e, loc) - } - /// Error at a specific location for the next character - #[allow(unused)] - fn at_one(self, loc: usize) -> ParseError { - let e: ParseErrorKind = self.into(); - ParseError::new_between(e, loc, loc + 1) - } - /// Error between two locations. - #[allow(unused)] - fn between(self, start: usize, end: usize) -> ParseError { - let e: ParseErrorKind = self.into(); - ParseError::new_between(e, start, end) - } - } - }; + ($ty:ident) => { + impl $ty { + /// Error at a specific location with no specific end + #[allow(unused)] + fn at(self, loc: usize) -> ParseError { + let e: ParseErrorKind = self.into(); + ParseError::new_at(e, loc) + } + /// Error at a specific location for the next character + #[allow(unused)] + fn at_one(self, loc: usize) -> ParseError { + let e: ParseErrorKind = self.into(); + ParseError::new_between(e, loc, loc + 1) + } + /// Error between two locations. + #[allow(unused)] + fn between(self, start: usize, end: usize) -> ParseError { + let e: ParseErrorKind = self.into(); + ParseError::new_between(e, start, end) + } + } + }; } #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum ParseComplexError { - #[error("The first character in a field name should be alphabetic")] - InvalidStartingCharacterInIdent, - #[error("Field name is not valid (it should begin with an alphabetical char and then consist only of alphanumeric chars)")] - InvalidFieldName, - #[error("Missing field separator; expected {0}")] - MissingFieldSeparator(char), - #[error("Missing closing '{0}'")] - ExpectedCloserToMatch(char, usize), + #[error("The first character in a field name should be alphabetic")] + InvalidStartingCharacterInIdent, + #[error("Field name is not valid (it should begin with an alphabetical char and then consist only of alphanumeric chars)")] + InvalidFieldName, + #[error("Missing field separator; expected {0}")] + MissingFieldSeparator(char), + #[error("Missing closing '{0}'")] + ExpectedCloserToMatch(char, usize), } at_between!(ParseComplexError); #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum ParseCharError { - #[error("Expected a single character")] - ExpectedValidCharacter, - #[error("Expected an escape code to follow the '\\'")] - ExpectedValidEscapeCode, - #[error("Expected a closing quote to match the opening quote at position {0}")] - ExpectedClosingQuoteToMatch(usize), + #[error("Expected a single character")] + ExpectedValidCharacter, + #[error("Expected an escape code to follow the '\\'")] + ExpectedValidEscapeCode, + #[error("Expected a closing quote to match the opening quote at position {0}")] + ExpectedClosingQuoteToMatch(usize), } at_between!(ParseCharError); #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum ParseStringError { - #[error("Expected a closing quote to match the opening quote at position {0}")] - ExpectedClosingQuoteToMatch(usize), - #[error("Expected an escape code to follow the '\\'")] - ExpectedValidEscapeCode, + #[error("Expected a closing quote to match the opening quote at position {0}")] + ExpectedClosingQuoteToMatch(usize), + #[error("Expected an escape code to follow the '\\'")] + ExpectedValidEscapeCode, } at_between!(ParseStringError); #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum ParseNumberError { - #[error("Expected one or more digits")] - ExpectedDigit, - #[error("Failed to parse digits into an integer: {0}")] - ParsingFailed(ParseIntError), + #[error("Expected one or more digits")] + ExpectedDigit, + #[error("Failed to parse digits into an integer: {0}")] + ParsingFailed(ParseIntError), } at_between!(ParseNumberError); #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)] pub enum ParseBitSequenceError { - #[error("Expected a closing bracket ('>') to match the opening one at position {0}")] - ExpectedClosingBracketToMatch(usize), - #[error("Invalid character; expecting a 0 or 1")] - InvalidCharacter, + #[error("Expected a closing bracket ('>') to match the opening one at position {0}")] + ExpectedClosingBracketToMatch(usize), + #[error("Invalid character; expecting a 0 or 1")] + InvalidCharacter, } at_between!(ParseBitSequenceError); // Parse a value. fn parse_value(t: &mut impl Tokens) -> Result, ParseError> { - // Our parsers return `Result>`, but in order to know - // whether to try the next item, `one_of` expects `Option`, so we transpose_err - // to convert to the right shape. - let val = yap::one_of!(t; - transpose_err(parse_bool(t).map(Value::bool).ok_or(None)), - transpose_err(parse_char(t).map(Value::char)), - transpose_err(parse_string(t).map(Value::string)), - transpose_err(parse_number(t).map(Value::primitive)), - transpose_err(parse_named_composite(t).map(|v| v.into())), - transpose_err(parse_unnamed_composite(t).map(|v| v.into())), - transpose_err(parse_bit_sequence(t).map(Value::bit_sequence)), - transpose_err(parse_variant(t).map(|v| v.into())), - ); - - match val { - Some(Ok(val)) => Ok(val), - Some(Err(e)) => Err(e), - None => Err(ParseError::new_at(ParseErrorKind::ExpectedValue, t.offset())), - } + // Our parsers return `Result>`, but in order to know + // whether to try the next item, `one_of` expects `Option`, so we transpose_err + // to convert to the right shape. + let val = yap::one_of!(t; + transpose_err(parse_bool(t).map(Value::bool).ok_or(None)), + transpose_err(parse_char(t).map(Value::char)), + transpose_err(parse_string(t).map(Value::string)), + transpose_err(parse_number(t).map(Value::primitive)), + transpose_err(parse_named_composite(t).map(|v| v.into())), + transpose_err(parse_unnamed_composite(t).map(|v| v.into())), + transpose_err(parse_bit_sequence(t).map(Value::bit_sequence)), + transpose_err(parse_variant(t).map(|v| v.into())), + ); + + match val { + Some(Ok(val)) => Ok(val), + Some(Err(e)) => Err(e), + None => Err(ParseError::new_at(ParseErrorKind::ExpectedValue, t.offset())), + } } // Parse a named composite value like `{ foo: 123 }`. @@ -182,264 +182,264 @@ fn parse_value(t: &mut impl Tokens) -> Result, ParseError // that we can see up front that the characters we're parsing aren't going to be the right shape, // and can attempt to parse the characters into a different thing if we wish. fn parse_named_composite( - t: &mut impl Tokens, + t: &mut impl Tokens, ) -> Result, Option> { - let start = t.offset(); - if !t.token('{') { - return Err(None); - } - skip_whitespace(t); - - // No values? bail early. - if t.token('}') { - return Ok(Composite::Named(vec![])); - } - - let vals = t - .sep_by_err(|t| parse_field_name_and_value(t), |t| skip_spaced_separator(t, ',')) - .collect::>()?; - - skip_whitespace(t); - if !t.token('}') { - return Err(Some(ParseComplexError::ExpectedCloserToMatch('}', start).at_one(t.offset()))); - } - Ok(Composite::Named(vals)) + let start = t.offset(); + if !t.token('{') { + return Err(None); + } + skip_whitespace(t); + + // No values? bail early. + if t.token('}') { + return Ok(Composite::Named(vec![])); + } + + let vals = t + .sep_by_err(|t| parse_field_name_and_value(t), |t| skip_spaced_separator(t, ',')) + .collect::>()?; + + skip_whitespace(t); + if !t.token('}') { + return Err(Some(ParseComplexError::ExpectedCloserToMatch('}', start).at_one(t.offset()))); + } + Ok(Composite::Named(vals)) } // Parse an unnamed composite value like `(true, 123)` fn parse_unnamed_composite( - t: &mut impl Tokens, + t: &mut impl Tokens, ) -> Result, Option> { - let start = t.offset(); - if !t.token('(') { - return Err(None); - } - skip_whitespace(t); - - // No values? bail early. - if t.token(')') { - return Ok(Composite::Unnamed(vec![])); - } - - let vals = t - .sep_by_err(|t| parse_value(t), |t| skip_spaced_separator(t, ',')) - .collect::>()?; - - skip_whitespace(t); - if !t.token(')') { - return Err(Some(ParseComplexError::ExpectedCloserToMatch(')', start).at_one(t.offset()))); - } - Ok(Composite::Unnamed(vals)) + let start = t.offset(); + if !t.token('(') { + return Err(None); + } + skip_whitespace(t); + + // No values? bail early. + if t.token(')') { + return Ok(Composite::Unnamed(vec![])); + } + + let vals = t + .sep_by_err(|t| parse_value(t), |t| skip_spaced_separator(t, ',')) + .collect::>()?; + + skip_whitespace(t); + if !t.token(')') { + return Err(Some(ParseComplexError::ExpectedCloserToMatch(')', start).at_one(t.offset()))); + } + Ok(Composite::Unnamed(vals)) } // Parse a variant like `Variant { hello: "there" }` or `Foo (123, true)` fn parse_variant(t: &mut impl Tokens) -> Result, Option> { - let ident = match parse_optional_variant_ident(t) { - Some(ident) => ident, - None => return Err(None), - }; - - skip_whitespace(t); - - let composite = yap::one_of!(t; - transpose_err(parse_named_composite(t)), - transpose_err(parse_unnamed_composite(t)) - ); - - match composite { - Some(Ok(values)) => Ok(Variant { name: ident, values }), - Some(Err(e)) => Err(Some(e)), - None => Err(None), - } + let ident = match parse_optional_variant_ident(t) { + Some(ident) => ident, + None => return Err(None), + }; + + skip_whitespace(t); + + let composite = yap::one_of!(t; + transpose_err(parse_named_composite(t)), + transpose_err(parse_unnamed_composite(t)) + ); + + match composite { + Some(Ok(values)) => Ok(Variant { name: ident, values }), + Some(Err(e)) => Err(Some(e)), + None => Err(None), + } } // Parse a sequence of bits like `<01101>` or `<>` into a bit sequence. fn parse_bit_sequence(t: &mut impl Tokens) -> Result> { - let start = t.offset(); - if !t.token('<') { - return Err(None); - } - let bits = t.tokens_while(|&c| c == '0' || c == '1').map(|c| c == '1'); - let mut seq = BitSequence::new(); - for bit in bits { - seq.push(bit); - } - if !t.token('>') { - return Err(Some( - ParseBitSequenceError::ExpectedClosingBracketToMatch(start) - .between(t.offset(), t.offset() + 1), - )); - } - Ok(seq) + let start = t.offset(); + if !t.token('<') { + return Err(None); + } + let bits = t.tokens_while(|&c| c == '0' || c == '1').map(|c| c == '1'); + let mut seq = BitSequence::new(); + for bit in bits { + seq.push(bit); + } + if !t.token('>') { + return Err(Some( + ParseBitSequenceError::ExpectedClosingBracketToMatch(start) + .between(t.offset(), t.offset() + 1), + )); + } + Ok(seq) } // Parse a bool (`true` or `false`) fn parse_bool(t: &mut impl Tokens) -> Option { - if t.tokens("true".chars()) { - Some(true) - } else if t.tokens("false".chars()) { - Some(false) - } else { - None - } + if t.tokens("true".chars()) { + Some(true) + } else if t.tokens("false".chars()) { + Some(false) + } else { + None + } } // Parse a char like `'a'` fn parse_char(t: &mut impl Tokens) -> Result> { - let start = t.offset(); - if !t.token('\'') { - return Err(None); - } - let char = match t.next() { - None => return Err(Some(ParseCharError::ExpectedValidCharacter.at_one(t.offset()))), - Some(c) => c, - }; - - // If char is a backslash, it's an escape code and we - // need to unescape it to find our inner char: - let char = if char == '\\' { - let escape_code = match t.next() { - None => return Err(Some(ParseCharError::ExpectedValidEscapeCode.at_one(t.offset()))), - Some(c) => c, - }; - match string_helpers::from_escape_code(escape_code) { - None => return Err(Some(ParseCharError::ExpectedValidEscapeCode.at_one(t.offset()))), - Some(c) => c, - } - } else { - char - }; - - if !t.token('\'') { - return Err(Some(ParseCharError::ExpectedClosingQuoteToMatch(start).at_one(t.offset()))); - } - Ok(char) + let start = t.offset(); + if !t.token('\'') { + return Err(None); + } + let char = match t.next() { + None => return Err(Some(ParseCharError::ExpectedValidCharacter.at_one(t.offset()))), + Some(c) => c, + }; + + // If char is a backslash, it's an escape code and we + // need to unescape it to find our inner char: + let char = if char == '\\' { + let escape_code = match t.next() { + None => return Err(Some(ParseCharError::ExpectedValidEscapeCode.at_one(t.offset()))), + Some(c) => c, + }; + match string_helpers::from_escape_code(escape_code) { + None => return Err(Some(ParseCharError::ExpectedValidEscapeCode.at_one(t.offset()))), + Some(c) => c, + } + } else { + char + }; + + if !t.token('\'') { + return Err(Some(ParseCharError::ExpectedClosingQuoteToMatch(start).at_one(t.offset()))); + } + Ok(char) } // Parse a number like `-123_456` or `234` or `+1234_5` fn parse_number(t: &mut impl Tokens) -> Result> { - let start_loc = t.offset(); - let is_positive = t.token('+') || !t.token('-'); - - // When we iterate numeric digits, prefix a sign as needed: - let sign = if is_positive { "".chars() } else { "-".chars() }; - - // Now, we expect a digit and then a mix of digits and underscores: - let mut seen_n = false; - let digits = t - .tokens_while(|c| { - if c.is_ascii_digit() { - seen_n = true; - true - } else { - seen_n && *c == '_' - } - }) - .filter(|c| c.is_ascii_digit()); - - // Chain sign to digits and attempt to parse into a number. - let n_str: String = sign.chain(digits).collect(); - let end_loc = t.offset(); - - // Nothing was parsed; Return None. - if end_loc == start_loc { - return Err(None); - } - - // No digits were parsed but a sign was; err. - if !seen_n { - return Err(Some(ParseNumberError::ExpectedDigit.between(end_loc, end_loc + 1))); - } - - // Parse into a number as best we can: - if is_positive { - n_str - .parse::() - .map(Primitive::u128) - .map_err(|e| Some(ParseNumberError::ParsingFailed(e).between(start_loc, end_loc))) - } else { - n_str - .parse::() - .map(Primitive::i128) - .map_err(|e| Some(ParseNumberError::ParsingFailed(e).between(start_loc, end_loc))) - } + let start_loc = t.offset(); + let is_positive = t.token('+') || !t.token('-'); + + // When we iterate numeric digits, prefix a sign as needed: + let sign = if is_positive { "".chars() } else { "-".chars() }; + + // Now, we expect a digit and then a mix of digits and underscores: + let mut seen_n = false; + let digits = t + .tokens_while(|c| { + if c.is_ascii_digit() { + seen_n = true; + true + } else { + seen_n && *c == '_' + } + }) + .filter(|c| c.is_ascii_digit()); + + // Chain sign to digits and attempt to parse into a number. + let n_str: String = sign.chain(digits).collect(); + let end_loc = t.offset(); + + // Nothing was parsed; Return None. + if end_loc == start_loc { + return Err(None); + } + + // No digits were parsed but a sign was; err. + if !seen_n { + return Err(Some(ParseNumberError::ExpectedDigit.between(end_loc, end_loc + 1))); + } + + // Parse into a number as best we can: + if is_positive { + n_str + .parse::() + .map(Primitive::u128) + .map_err(|e| Some(ParseNumberError::ParsingFailed(e).between(start_loc, end_loc))) + } else { + n_str + .parse::() + .map(Primitive::i128) + .map_err(|e| Some(ParseNumberError::ParsingFailed(e).between(start_loc, end_loc))) + } } // Parse a string like `"hello\n there"` fn parse_string(t: &mut impl Tokens) -> Result> { - let start = t.offset(); - if !t.token('"') { - return Err(None); - } - - let mut out: String = String::new(); - let mut next_is_escaped = false; - loop { - let pos = t.offset(); - let char = match t.next() { - Some(c) => c, - None => { - return Err(Some( - ParseStringError::ExpectedClosingQuoteToMatch(start).at_one(t.offset()), - )) - } - }; - - match char { - // Escape a char: - '\\' if !next_is_escaped => { - next_is_escaped = true; - } - // Handle escaped chars: - c if next_is_escaped => match string_helpers::from_escape_code(c) { - Some(c) => { - out.push(c); - next_is_escaped = false; - } - None => { - return Err(Some( - ParseStringError::ExpectedValidEscapeCode.between(pos, pos + 1), - )) - } - }, - // String has closed - '"' => { - break; // closing quote seen; done! - } - // All other chars pushed as-is. - c => { - out.push(c); - } - } - } - - Ok(out) + let start = t.offset(); + if !t.token('"') { + return Err(None); + } + + let mut out: String = String::new(); + let mut next_is_escaped = false; + loop { + let pos = t.offset(); + let char = match t.next() { + Some(c) => c, + None => { + return Err(Some( + ParseStringError::ExpectedClosingQuoteToMatch(start).at_one(t.offset()), + )) + } + }; + + match char { + // Escape a char: + '\\' if !next_is_escaped => { + next_is_escaped = true; + } + // Handle escaped chars: + c if next_is_escaped => match string_helpers::from_escape_code(c) { + Some(c) => { + out.push(c); + next_is_escaped = false; + } + None => { + return Err(Some( + ParseStringError::ExpectedValidEscapeCode.between(pos, pos + 1), + )) + } + }, + // String has closed + '"' => { + break; // closing quote seen; done! + } + // All other chars pushed as-is. + c => { + out.push(c); + } + } + } + + Ok(out) } // Parse a field in a named composite like `foo: 123` or `"hello there": 123` fn parse_field_name_and_value( - t: &mut impl Tokens, + t: &mut impl Tokens, ) -> Result<(String, Value<()>), ParseError> { - let name = parse_field_name(t)?; - if !skip_spaced_separator(t, ':') { - return Err(ParseComplexError::MissingFieldSeparator(':').at_one(t.offset())); - } - let value = parse_value(t)?; - Ok((name, value)) + let name = parse_field_name(t)?; + if !skip_spaced_separator(t, ':') { + return Err(ParseComplexError::MissingFieldSeparator(':').at_one(t.offset())); + } + let value = parse_value(t)?; + Ok((name, value)) } // Parse a field name in a named composite like `foo` or `"hello there"` fn parse_field_name(t: &mut impl Tokens) -> Result { - let field_name = yap::one_of!(t; - transpose_err(parse_string(t)), - Some(parse_ident(t)), - ); - - match field_name { - Some(Ok(name)) => Ok(name), - Some(Err(e)) => Err(e), - None => Err(ParseComplexError::InvalidFieldName.at(t.offset())), - } + let field_name = yap::one_of!(t; + transpose_err(parse_string(t)), + Some(parse_ident(t)), + ); + + match field_name { + Some(Ok(name)) => Ok(name), + Some(Err(e)) => Err(e), + None => Err(ParseComplexError::InvalidFieldName.at(t.offset())), + } } // Parse an ident used for the variant name, like `MyVariant` or the special case @@ -447,190 +447,190 @@ fn parse_field_name(t: &mut impl Tokens) -> Result) -> Option { - fn parse_i_string(t: &mut impl Tokens) -> Option { - if t.next()? != 'v' { - return None; - } - parse_string(t).ok() - } - - yap::one_of!(t; - parse_i_string(t), - parse_ident(t).ok() - ) + fn parse_i_string(t: &mut impl Tokens) -> Option { + if t.next()? != 'v' { + return None; + } + parse_string(t).ok() + } + + yap::one_of!(t; + parse_i_string(t), + parse_ident(t).ok() + ) } // Parse an ident like `foo` or `MyVariant` fn parse_ident(t: &mut impl Tokens) -> Result { - let start = t.location(); - if t.skip_tokens_while(|c| c.is_alphabetic()) == 0 { - return Err(ParseComplexError::InvalidStartingCharacterInIdent.at_one(start.offset())); - } - t.skip_tokens_while(|c| c.is_alphanumeric() || *c == '_'); - let end = t.location(); - - let ident_str = t.slice(start, end).collect(); - Ok(ident_str) + let start = t.location(); + if t.skip_tokens_while(|c| c.is_alphabetic()) == 0 { + return Err(ParseComplexError::InvalidStartingCharacterInIdent.at_one(start.offset())); + } + t.skip_tokens_while(|c| c.is_alphanumeric() || *c == '_'); + let end = t.location(); + + let ident_str = t.slice(start, end).collect(); + Ok(ident_str) } // Skip any whitespace characters fn skip_whitespace(t: &mut impl Tokens) { - t.skip_tokens_while(|c| c.is_whitespace()); + t.skip_tokens_while(|c| c.is_whitespace()); } // Skip a provided separator, with optional spaces on either side fn skip_spaced_separator(t: &mut impl Tokens, s: char) -> bool { - skip_whitespace(t); - let is_sep = t.token(s); - skip_whitespace(t); - is_sep + skip_whitespace(t); + let is_sep = t.token(s); + skip_whitespace(t); + is_sep } // Turn a ` Result>` into `Option>`. fn transpose_err(r: Result>) -> Option> { - match r { - Ok(val) => Some(Ok(val)), - Err(Some(e)) => Some(Err(e)), - Err(None) => None, - } + match r { + Ok(val) => Some(Ok(val)), + Err(Some(e)) => Some(Err(e)), + Err(None) => None, + } } #[cfg(test)] mod test { - use super::*; - - fn from(s: &str) -> Result, ParseError> { - let (res, remaining) = from_str(s); - if res.is_ok() { - // all successful parse tests fully consume the input string: - assert_eq!(remaining.len(), 0, "was not expecting any unparsed output"); - } - res - } - - #[test] - fn parse_bools() { - assert_eq!(from("true"), Ok(Value::bool(true))); - assert_eq!(from("false"), Ok(Value::bool(false))); - } - - #[test] - fn parse_numbers() { - assert_eq!(from("123"), Ok(Value::u128(123))); - assert_eq!(from("1_234_56"), Ok(Value::u128(123_456))); - assert_eq!(from("+1_234_56"), Ok(Value::u128(123_456))); - assert_eq!(from("-123_4"), Ok(Value::i128(-1234))); - assert_eq!(from("-abc"), Err(ParseNumberError::ExpectedDigit.between(1, 2))); - } - - #[test] - fn parse_chars() { - assert_eq!(from("'a'"), Ok(Value::char('a'))); - assert_eq!(from("'😀'"), Ok(Value::char('😀'))); - assert_eq!(from("'\\n'"), Ok(Value::char('\n'))); - assert_eq!(from("'\\t'"), Ok(Value::char('\t'))); - assert_eq!(from("'\\\"'"), Ok(Value::char('"'))); - assert_eq!(from("'\\\''"), Ok(Value::char('\''))); - assert_eq!(from("'\\r'"), Ok(Value::char('\r'))); - assert_eq!(from("'\\\\'"), Ok(Value::char('\\'))); - assert_eq!(from("'\\0'"), Ok(Value::char('\0'))); - assert_eq!(from("'a"), Err(ParseCharError::ExpectedClosingQuoteToMatch(0).at_one(2))); - } - - #[test] - fn parse_strings() { - assert_eq!(from("\"\\n \\r \\t \\0 \\\"\""), Ok(Value::string("\n \r \t \0 \""))); - assert_eq!(from("\"Hello there 😀\""), Ok(Value::string("Hello there 😀"))); - assert_eq!(from("\"Hello\\n\\t there\""), Ok(Value::string("Hello\n\t there"))); - assert_eq!(from("\"Hello\\\\ there\""), Ok(Value::string("Hello\\ there"))); - assert_eq!( - from("\"Hello\\p there\""), - Err(ParseStringError::ExpectedValidEscapeCode.between(7, 8)) - ); - assert_eq!(from("\"Hi"), Err(ParseStringError::ExpectedClosingQuoteToMatch(0).at_one(3))); - } - - #[test] - fn parse_unnamed_composites() { - assert_eq!( - from("( true, 1234 ,\t\n\t \"Hello!\" )"), - Ok(Value::unnamed_composite(vec![ - Value::bool(true), - Value::u128(1234), - Value::string("Hello!") - ])) - ); - assert_eq!(from("()"), Ok(Value::unnamed_composite([]))); - assert_eq!(from("(\n\n\t\t\n)"), Ok(Value::unnamed_composite([]))); - } - - #[test] - fn parse_named_composites() { - assert_eq!( - from( - "{ + use super::*; + + fn from(s: &str) -> Result, ParseError> { + let (res, remaining) = from_str(s); + if res.is_ok() { + // all successful parse tests fully consume the input string: + assert_eq!(remaining.len(), 0, "was not expecting any unparsed output"); + } + res + } + + #[test] + fn parse_bools() { + assert_eq!(from("true"), Ok(Value::bool(true))); + assert_eq!(from("false"), Ok(Value::bool(false))); + } + + #[test] + fn parse_numbers() { + assert_eq!(from("123"), Ok(Value::u128(123))); + assert_eq!(from("1_234_56"), Ok(Value::u128(123_456))); + assert_eq!(from("+1_234_56"), Ok(Value::u128(123_456))); + assert_eq!(from("-123_4"), Ok(Value::i128(-1234))); + assert_eq!(from("-abc"), Err(ParseNumberError::ExpectedDigit.between(1, 2))); + } + + #[test] + fn parse_chars() { + assert_eq!(from("'a'"), Ok(Value::char('a'))); + assert_eq!(from("'😀'"), Ok(Value::char('😀'))); + assert_eq!(from("'\\n'"), Ok(Value::char('\n'))); + assert_eq!(from("'\\t'"), Ok(Value::char('\t'))); + assert_eq!(from("'\\\"'"), Ok(Value::char('"'))); + assert_eq!(from("'\\\''"), Ok(Value::char('\''))); + assert_eq!(from("'\\r'"), Ok(Value::char('\r'))); + assert_eq!(from("'\\\\'"), Ok(Value::char('\\'))); + assert_eq!(from("'\\0'"), Ok(Value::char('\0'))); + assert_eq!(from("'a"), Err(ParseCharError::ExpectedClosingQuoteToMatch(0).at_one(2))); + } + + #[test] + fn parse_strings() { + assert_eq!(from("\"\\n \\r \\t \\0 \\\"\""), Ok(Value::string("\n \r \t \0 \""))); + assert_eq!(from("\"Hello there 😀\""), Ok(Value::string("Hello there 😀"))); + assert_eq!(from("\"Hello\\n\\t there\""), Ok(Value::string("Hello\n\t there"))); + assert_eq!(from("\"Hello\\\\ there\""), Ok(Value::string("Hello\\ there"))); + assert_eq!( + from("\"Hello\\p there\""), + Err(ParseStringError::ExpectedValidEscapeCode.between(7, 8)) + ); + assert_eq!(from("\"Hi"), Err(ParseStringError::ExpectedClosingQuoteToMatch(0).at_one(3))); + } + + #[test] + fn parse_unnamed_composites() { + assert_eq!( + from("( true, 1234 ,\t\n\t \"Hello!\" )"), + Ok(Value::unnamed_composite(vec![ + Value::bool(true), + Value::u128(1234), + Value::string("Hello!") + ])) + ); + assert_eq!(from("()"), Ok(Value::unnamed_composite([]))); + assert_eq!(from("(\n\n\t\t\n)"), Ok(Value::unnamed_composite([]))); + } + + #[test] + fn parse_named_composites() { + assert_eq!( + from( + "{ hello: true, foo: 1234, \"Hello there 😀\": \"Hello!\" }" - ), - Ok(Value::named_composite([ - ("hello", Value::bool(true)), - ("foo", Value::u128(1234)), - ("Hello there 😀", Value::string("Hello!")) - ])) - ); - } - - #[test] - fn parse_variants() { - assert_eq!( - from( - "MyVariant { + ), + Ok(Value::named_composite([ + ("hello", Value::bool(true)), + ("foo", Value::u128(1234)), + ("Hello there 😀", Value::string("Hello!")) + ])) + ); + } + + #[test] + fn parse_variants() { + assert_eq!( + from( + "MyVariant { hello: true, foo: 1234, \"Hello there 😀\": \"Hello!\" }" - ), - Ok(Value::named_variant( - "MyVariant", - [ - ("hello", Value::bool(true)), - ("foo", Value::u128(1234)), - ("Hello there 😀", Value::string("Hello!")) - ] - )) - ); - - assert_eq!( - from("Foo ( true, 1234 ,\t\n\t \"Hello!\" )"), - Ok(Value::unnamed_variant( - "Foo", - vec![Value::bool(true), Value::u128(1234), Value::string("Hello!")] - )) - ); - - assert_eq!(from("Foo()"), Ok(Value::unnamed_variant("Foo", []))); - assert_eq!(from("Foo{}"), Ok(Value::named_variant::<_, String, _>("Foo", []))); - assert_eq!(from("Foo( \t)"), Ok(Value::unnamed_variant("Foo", []))); - assert_eq!(from("Foo{ }"), Ok(Value::named_variant::<_, String, _>("Foo", []))); - - // Parsing special "v" strings: - assert_eq!( - from("v\"variant name\" { }"), - Ok(Value::named_variant::<_, String, _>("variant name", [])) - ); - } - - #[test] - fn parse_bit_sequences() { - use scale_bits::bits; - assert_eq!( - from("<011010110101101>"), - Ok(Value::bit_sequence(bits![0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1])) - ); - assert_eq!(from("<01101>"), Ok(Value::bit_sequence(bits![0, 1, 1, 0, 1]))); - assert_eq!(from("<0>"), Ok(Value::bit_sequence(bits![0]))); - assert_eq!(from("<>"), Ok(Value::bit_sequence(bits![]))); - } + ), + Ok(Value::named_variant( + "MyVariant", + [ + ("hello", Value::bool(true)), + ("foo", Value::u128(1234)), + ("Hello there 😀", Value::string("Hello!")) + ] + )) + ); + + assert_eq!( + from("Foo ( true, 1234 ,\t\n\t \"Hello!\" )"), + Ok(Value::unnamed_variant( + "Foo", + vec![Value::bool(true), Value::u128(1234), Value::string("Hello!")] + )) + ); + + assert_eq!(from("Foo()"), Ok(Value::unnamed_variant("Foo", []))); + assert_eq!(from("Foo{}"), Ok(Value::named_variant::<_, String, _>("Foo", []))); + assert_eq!(from("Foo( \t)"), Ok(Value::unnamed_variant("Foo", []))); + assert_eq!(from("Foo{ }"), Ok(Value::named_variant::<_, String, _>("Foo", []))); + + // Parsing special "v" strings: + assert_eq!( + from("v\"variant name\" { }"), + Ok(Value::named_variant::<_, String, _>("variant name", [])) + ); + } + + #[test] + fn parse_bit_sequences() { + use scale_bits::bits; + assert_eq!( + from("<011010110101101>"), + Ok(Value::bit_sequence(bits![0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1])) + ); + assert_eq!(from("<01101>"), Ok(Value::bit_sequence(bits![0, 1, 1, 0, 1]))); + assert_eq!(from("<0>"), Ok(Value::bit_sequence(bits![0]))); + assert_eq!(from("<>"), Ok(Value::bit_sequence(bits![]))); + } } diff --git a/src/string_impls/string_helpers.rs b/src/string_impls/string_helpers.rs index d8f9652..c1d293a 100644 --- a/src/string_impls/string_helpers.rs +++ b/src/string_impls/string_helpers.rs @@ -16,17 +16,17 @@ /// Return the escape code for a given char, or None /// if there is no escape code for it. pub fn to_escape_code(c: char) -> Option { - let escaped = match c { - '\n' => 'n', - '\t' => 't', - '"' => '"', - '\'' => '\'', - '\r' => 'r', - '\\' => '\\', - '\0' => '0', - _ => return None, - }; - Some(escaped) + let escaped = match c { + '\n' => 'n', + '\t' => 't', + '"' => '"', + '\'' => '\'', + '\r' => 'r', + '\\' => '\\', + '\0' => '0', + _ => return None, + }; + Some(escaped) } /// Given some escape code (char following a '\'), return the @@ -34,15 +34,15 @@ pub fn to_escape_code(c: char) -> Option { /// valid escape code. #[cfg(feature = "from_string")] pub fn from_escape_code(c: char) -> Option { - let unescaped = match c { - 'n' => '\n', - 't' => '\t', - '"' => '"', - '\'' => '\'', - 'r' => '\r', - '\\' => '\\', - '0' => '\0', - _ => return None, - }; - Some(unescaped) + let unescaped = match c { + 'n' => '\n', + 't' => '\t', + '"' => '"', + '\'' => '\'', + 'r' => '\r', + '\\' => '\\', + '0' => '\0', + _ => return None, + }; + Some(unescaped) } diff --git a/src/string_impls/to_string.rs b/src/string_impls/to_string.rs index 71799b8..8d0d709 100644 --- a/src/string_impls/to_string.rs +++ b/src/string_impls/to_string.rs @@ -18,211 +18,211 @@ use crate::value::{BitSequence, Composite, Primitive, Value, ValueDef, Variant}; use std::fmt::{Display, Write}; impl Display for Value { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.value.fmt(f) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.value.fmt(f) + } } impl Display for ValueDef { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - ValueDef::Composite(c) => c.fmt(f), - ValueDef::Variant(v) => v.fmt(f), - ValueDef::BitSequence(b) => fmt_bitsequence(b, f), - ValueDef::Primitive(p) => p.fmt(f), - } - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ValueDef::Composite(c) => c.fmt(f), + ValueDef::Variant(v) => v.fmt(f), + ValueDef::BitSequence(b) => fmt_bitsequence(b, f), + ValueDef::Primitive(p) => p.fmt(f), + } + } } impl Display for Composite { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Composite::Named(vals) => { - f.write_str("{ ")?; - for (idx, (name, val)) in vals.iter().enumerate() { - if idx != 0 { - f.write_str(", ")?; - } - if is_ident(name) { - f.write_str(name)?; - } else { - fmt_string(name, f)?; - } - f.write_str(": ")?; - val.fmt(f)?; - } - f.write_str(" }")?; - } - Composite::Unnamed(vals) => { - f.write_char('(')?; - for (idx, val) in vals.iter().enumerate() { - if idx != 0 { - f.write_str(", ")?; - } - val.fmt(f)?; - } - f.write_char(')')?; - } - } - Ok(()) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Composite::Named(vals) => { + f.write_str("{ ")?; + for (idx, (name, val)) in vals.iter().enumerate() { + if idx != 0 { + f.write_str(", ")?; + } + if is_ident(name) { + f.write_str(name)?; + } else { + fmt_string(name, f)?; + } + f.write_str(": ")?; + val.fmt(f)?; + } + f.write_str(" }")?; + } + Composite::Unnamed(vals) => { + f.write_char('(')?; + for (idx, val) in vals.iter().enumerate() { + if idx != 0 { + f.write_str(", ")?; + } + val.fmt(f)?; + } + f.write_char(')')?; + } + } + Ok(()) + } } impl Display for Variant { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if is_ident(&self.name) { - f.write_str(&self.name)?; - } else { - // If the variant name isn't a valid ident, we parse it into - // a special "v" prefixed string to allow arbitrary content while - // keeping it easy to parse variant names with minimal lookahead. - // Most use cases should never see or care about this. - f.write_char('v')?; - fmt_string(&self.name, f)?; - } - self.values.fmt(f) - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if is_ident(&self.name) { + f.write_str(&self.name)?; + } else { + // If the variant name isn't a valid ident, we parse it into + // a special "v" prefixed string to allow arbitrary content while + // keeping it easy to parse variant names with minimal lookahead. + // Most use cases should never see or care about this. + f.write_char('v')?; + fmt_string(&self.name, f)?; + } + self.values.fmt(f) + } } impl Display for Primitive { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Primitive::Bool(true) => f.write_str("true"), - Primitive::Bool(false) => f.write_str("false"), - Primitive::Char(c) => fmt_char(*c, f), - Primitive::I128(n) => n.fmt(f), - Primitive::U128(n) => n.fmt(f), - Primitive::String(s) => fmt_string(s, f), - // We don't currently have a sane way to parse into these or - // format out of them: - Primitive::U256(_) | Primitive::I256(_) => Err(std::fmt::Error), - } - } + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Primitive::Bool(true) => f.write_str("true"), + Primitive::Bool(false) => f.write_str("false"), + Primitive::Char(c) => fmt_char(*c, f), + Primitive::I128(n) => n.fmt(f), + Primitive::U128(n) => n.fmt(f), + Primitive::String(s) => fmt_string(s, f), + // We don't currently have a sane way to parse into these or + // format out of them: + Primitive::U256(_) | Primitive::I256(_) => Err(std::fmt::Error), + } + } } fn fmt_string(s: &str, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_char('"')?; - for char in s.chars() { - match string_helpers::to_escape_code(char) { - Some(escaped) => { - f.write_char('\\')?; - f.write_char(escaped)? - } - None => f.write_char(char)?, - } - } - f.write_char('"') + f.write_char('"')?; + for char in s.chars() { + match string_helpers::to_escape_code(char) { + Some(escaped) => { + f.write_char('\\')?; + f.write_char(escaped)? + } + None => f.write_char(char)?, + } + } + f.write_char('"') } fn fmt_char(c: char, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_char('\'')?; - match string_helpers::to_escape_code(c) { - Some(escaped) => { - f.write_char('\\')?; - f.write_char(escaped)? - } - None => f.write_char(c)?, - } - f.write_char('\'') + f.write_char('\'')?; + match string_helpers::to_escape_code(c) { + Some(escaped) => { + f.write_char('\\')?; + f.write_char(escaped)? + } + None => f.write_char(c)?, + } + f.write_char('\'') } fn fmt_bitsequence(b: &BitSequence, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_char('<')?; - for bit in b.iter() { - match bit { - true => f.write_char('1')?, - false => f.write_char('0')?, - } - } - f.write_char('>') + f.write_char('<')?; + for bit in b.iter() { + match bit { + true => f.write_char('1')?, + false => f.write_char('0')?, + } + } + f.write_char('>') } /// Is the string provided a valid ident (as per from_string::parse_ident). fn is_ident(s: &str) -> bool { - for (idx, c) in s.chars().enumerate() { - if (idx == 0 && !c.is_alphabetic()) || !c.is_alphanumeric() || c != '_' { - return false; - } - } - true + for (idx, c) in s.chars().enumerate() { + if (idx == 0 && !c.is_alphabetic()) || !c.is_alphanumeric() || c != '_' { + return false; + } + } + true } #[cfg(test)] // These tests only work with from_string enabled, because we go back and forth from both. #[cfg(feature = "from_string")] mod test { - use super::*; - - fn assert_from_to(val: Value) { - let s = val.to_string(); - match crate::stringify::from_str(&s) { - (Err(e), _) => { - panic!("'{s}' cannot be parsed back into the value {val:?}: {e}"); - } - (Ok(new_val), rest) => { - assert_eq!( - val.remove_context(), - new_val, - "value should be the same after parsing to/from a string" - ); - assert_eq!(rest.len(), 0, "there should be no unparsed string but got '{rest}'"); - } - } - } - - #[test] - fn primitives() { - assert_from_to(Value::bool(true)); - assert_from_to(Value::bool(false)); - - assert_from_to(Value::char('\n')); - assert_from_to(Value::char('😀')); - assert_from_to(Value::char('a')); - assert_from_to(Value::char('\0')); - assert_from_to(Value::char('\t')); - - assert_from_to(Value::i128(-123_456)); - assert_from_to(Value::u128(0)); - assert_from_to(Value::u128(123456)); - - assert_from_to(Value::string("hello \"you\",\n\n\t How are you??")); - assert_from_to(Value::string("")); - } - - #[test] - fn composites() { - assert_from_to(Value::named_composite([ - ("foo", Value::u128(12345)), - ("bar", Value::bool(true)), - ("a \"weird\" name", Value::string("Woop!")), - ])); - assert_from_to(Value::unnamed_composite([ - Value::u128(12345), - Value::bool(true), - Value::string("Woop!"), - ])); - } - - #[test] - fn variants() { - assert_from_to(Value::named_variant( - "A weird variant name", - [ - ("foo", Value::u128(12345)), - ("bar", Value::bool(true)), - ("a \"weird\" name", Value::string("Woop!")), - ], - )); - assert_from_to(Value::unnamed_variant( - "MyVariant", - [Value::u128(12345), Value::bool(true), Value::string("Woop!")], - )); - } - - #[test] - fn bit_sequences() { - use scale_bits::bits; - assert_from_to(Value::bit_sequence(bits![0, 1, 1, 0, 1, 1, 0])); - assert_from_to(Value::bit_sequence(bits![])); - } + use super::*; + + fn assert_from_to(val: Value) { + let s = val.to_string(); + match crate::stringify::from_str(&s) { + (Err(e), _) => { + panic!("'{s}' cannot be parsed back into the value {val:?}: {e}"); + } + (Ok(new_val), rest) => { + assert_eq!( + val.remove_context(), + new_val, + "value should be the same after parsing to/from a string" + ); + assert_eq!(rest.len(), 0, "there should be no unparsed string but got '{rest}'"); + } + } + } + + #[test] + fn primitives() { + assert_from_to(Value::bool(true)); + assert_from_to(Value::bool(false)); + + assert_from_to(Value::char('\n')); + assert_from_to(Value::char('😀')); + assert_from_to(Value::char('a')); + assert_from_to(Value::char('\0')); + assert_from_to(Value::char('\t')); + + assert_from_to(Value::i128(-123_456)); + assert_from_to(Value::u128(0)); + assert_from_to(Value::u128(123456)); + + assert_from_to(Value::string("hello \"you\",\n\n\t How are you??")); + assert_from_to(Value::string("")); + } + + #[test] + fn composites() { + assert_from_to(Value::named_composite([ + ("foo", Value::u128(12345)), + ("bar", Value::bool(true)), + ("a \"weird\" name", Value::string("Woop!")), + ])); + assert_from_to(Value::unnamed_composite([ + Value::u128(12345), + Value::bool(true), + Value::string("Woop!"), + ])); + } + + #[test] + fn variants() { + assert_from_to(Value::named_variant( + "A weird variant name", + [ + ("foo", Value::u128(12345)), + ("bar", Value::bool(true)), + ("a \"weird\" name", Value::string("Woop!")), + ], + )); + assert_from_to(Value::unnamed_variant( + "MyVariant", + [Value::u128(12345), Value::bool(true), Value::string("Woop!")], + )); + } + + #[test] + fn bit_sequences() { + use scale_bits::bits; + assert_from_to(Value::bit_sequence(bits![0, 1, 1, 0, 1, 1, 0])); + assert_from_to(Value::bit_sequence(bits![])); + } } diff --git a/src/value.rs b/src/value.rs index b715323..a52c765 100644 --- a/src/value.rs +++ b/src/value.rs @@ -27,184 +27,184 @@ pub use scale_bits::Bits as BitSequence; /// losslessly. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Value { - /// The shape and associated data for this Value - pub value: ValueDef, - /// Some additional arbitrary context that can be associated with a value. - pub context: T, + /// The shape and associated data for this Value + pub value: ValueDef, + /// Some additional arbitrary context that can be associated with a value. + pub context: T, } impl Value<()> { - /// Construct a named composite type from any type which produces a tuple of keys and values - /// when iterated over. - pub fn named_composite(vals: Vals) -> Self - where - S: Into, - Vals: IntoIterator)>, - { - Value { value: ValueDef::Composite(Composite::named(vals)), context: () } - } - /// Construct an unnamed composite type from any type which produces values - /// when iterated over. - pub fn unnamed_composite(vals: Vals) -> Self - where - Vals: IntoIterator>, - { - Value { value: ValueDef::Composite(Composite::unnamed(vals)), context: () } - } - /// Create a new variant value without additional context. - pub fn variant>(name: S, values: Composite<()>) -> Value<()> { - Value { value: ValueDef::Variant(Variant { name: name.into(), values }), context: () } - } - /// Create a new variant value with named fields and without additional context. - pub fn named_variant(name: S, fields: Vals) -> Value<()> - where - S: Into, - F: Into, - Vals: IntoIterator)>, - { - Value { value: ValueDef::Variant(Variant::named_fields(name, fields)), context: () } - } - /// Create a new variant value with tuple-like fields and without additional context. - pub fn unnamed_variant(name: S, fields: Vals) -> Value<()> - where - S: Into, - Vals: IntoIterator>, - { - Value { value: ValueDef::Variant(Variant::unnamed_fields(name, fields)), context: () } - } - /// Create a new bit sequence value without additional context. - pub fn bit_sequence(bits: BitSequence) -> Value<()> { - Value { value: ValueDef::BitSequence(bits), 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 string>(val: S) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::String(val.into())), context: () } - } - /// Create a new boolean value without additional context. - pub fn bool(val: bool) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::Bool(val)), context: () } - } - /// Create a new char without additional context. - pub fn char(val: char) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::Char(val)), context: () } - } - /// Create a new unsigned integer without additional context. - pub fn u128(val: u128) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::u128(val)), context: () } - } - /// Create a new signed integer without additional context. - pub fn i128(val: i128) -> Value<()> { - Value { value: ValueDef::Primitive(Primitive::i128(val)), context: () } - } - /// Create a new Value from a set of bytes; useful for converting things like AccountIds. - pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Value<()> { - let vals: Vec<_> = bytes.as_ref().iter().map(|&b| Value::u128(b as u128)).collect(); - Value::unnamed_composite(vals) - } + /// Construct a named composite type from any type which produces a tuple of keys and values + /// when iterated over. + pub fn named_composite(vals: Vals) -> Self + where + S: Into, + Vals: IntoIterator)>, + { + Value { value: ValueDef::Composite(Composite::named(vals)), context: () } + } + /// Construct an unnamed composite type from any type which produces values + /// when iterated over. + pub fn unnamed_composite(vals: Vals) -> Self + where + Vals: IntoIterator>, + { + Value { value: ValueDef::Composite(Composite::unnamed(vals)), context: () } + } + /// Create a new variant value without additional context. + pub fn variant>(name: S, values: Composite<()>) -> Value<()> { + Value { value: ValueDef::Variant(Variant { name: name.into(), values }), context: () } + } + /// Create a new variant value with named fields and without additional context. + pub fn named_variant(name: S, fields: Vals) -> Value<()> + where + S: Into, + F: Into, + Vals: IntoIterator)>, + { + Value { value: ValueDef::Variant(Variant::named_fields(name, fields)), context: () } + } + /// Create a new variant value with tuple-like fields and without additional context. + pub fn unnamed_variant(name: S, fields: Vals) -> Value<()> + where + S: Into, + Vals: IntoIterator>, + { + Value { value: ValueDef::Variant(Variant::unnamed_fields(name, fields)), context: () } + } + /// Create a new bit sequence value without additional context. + pub fn bit_sequence(bits: BitSequence) -> Value<()> { + Value { value: ValueDef::BitSequence(bits), 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 string>(val: S) -> Value<()> { + Value { value: ValueDef::Primitive(Primitive::String(val.into())), context: () } + } + /// Create a new boolean value without additional context. + pub fn bool(val: bool) -> Value<()> { + Value { value: ValueDef::Primitive(Primitive::Bool(val)), context: () } + } + /// Create a new char without additional context. + pub fn char(val: char) -> Value<()> { + Value { value: ValueDef::Primitive(Primitive::Char(val)), context: () } + } + /// Create a new unsigned integer without additional context. + pub fn u128(val: u128) -> Value<()> { + Value { value: ValueDef::Primitive(Primitive::u128(val)), context: () } + } + /// Create a new signed integer without additional context. + pub fn i128(val: i128) -> Value<()> { + Value { value: ValueDef::Primitive(Primitive::i128(val)), context: () } + } + /// Create a new Value from a set of bytes; useful for converting things like AccountIds. + pub fn from_bytes(bytes: impl AsRef<[u8]>) -> Value<()> { + let vals: Vec<_> = bytes.as_ref().iter().map(|&b| Value::u128(b as u128)).collect(); + Value::unnamed_composite(vals) + } } impl Value<()> { - /// Create a new value with no associated context. - pub fn without_context(value: ValueDef<()>) -> Value<()> { - Value { value, context: () } - } + /// Create a new value with no associated context. + pub fn without_context(value: ValueDef<()>) -> Value<()> { + Value { value, context: () } + } } 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 remove_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) } - } - /// If the value is a boolean value, return it. - pub fn as_bool(&self) -> Option { - match &self.value { - ValueDef::Primitive(p) => p.as_bool(), - _ => None, - } - } - /// If the value is a char, return it. - pub fn as_char(&self) -> Option { - match &self.value { - ValueDef::Primitive(p) => p.as_char(), - _ => None, - } - } - /// If the value is a u128, return it. - pub fn as_u128(&self) -> Option { - match &self.value { - ValueDef::Primitive(p) => p.as_u128(), - _ => None, - } - } - /// If the value is an i128, return it. - pub fn as_i128(&self) -> Option { - match &self.value { - ValueDef::Primitive(p) => p.as_i128(), - _ => None, - } - } - /// If the value is a string, return it. - pub fn as_str(&self) -> Option<&str> { - match &self.value { - ValueDef::Primitive(p) => p.as_str(), - _ => None, - } - } + /// 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 remove_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) } + } + /// If the value is a boolean value, return it. + pub fn as_bool(&self) -> Option { + match &self.value { + ValueDef::Primitive(p) => p.as_bool(), + _ => None, + } + } + /// If the value is a char, return it. + pub fn as_char(&self) -> Option { + match &self.value { + ValueDef::Primitive(p) => p.as_char(), + _ => None, + } + } + /// If the value is a u128, return it. + pub fn as_u128(&self) -> Option { + match &self.value { + ValueDef::Primitive(p) => p.as_u128(), + _ => None, + } + } + /// If the value is an i128, return it. + pub fn as_i128(&self) -> Option { + match &self.value { + ValueDef::Primitive(p) => p.as_i128(), + _ => None, + } + } + /// If the value is a string, return it. + pub fn as_str(&self) -> Option<&str> { + match &self.value { + ValueDef::Primitive(p) => p.as_str(), + _ => None, + } + } } /// The underlying shape of a given value. #[derive(Clone, Debug, PartialEq, Eq)] 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. - BitSequence(BitSequence), - /// Any of the primitive values we can have. - Primitive(Primitive), + /// 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. + 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), - } - } + /// 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 From for ValueDef { - fn from(val: BitSequence) -> Self { - ValueDef::BitSequence(val) - } + fn from(val: BitSequence) -> Self { + ValueDef::BitSequence(val) + } } impl From for Value<()> { - fn from(val: BitSequence) -> Self { - Value::without_context(val.into()) - } + fn from(val: BitSequence) -> Self { + Value::without_context(val.into()) + } } /// A named or unnamed struct-like, array-like or tuple-like set of values. @@ -212,246 +212,246 @@ impl From for Value<()> { /// as values for a specific [`Variant`]. #[derive(Clone, Debug, PartialEq, Eq)] pub enum Composite { - /// Eg `{ foo: 2, bar: false }` - Named(Vec<(String, Value)>), - /// Eg `(2, false)` - Unnamed(Vec>), + /// Eg `{ foo: 2, bar: false }` + Named(Vec<(String, Value)>), + /// Eg `(2, false)` + Unnamed(Vec>), } impl Composite { - /// Construct a named composite type from any type which produces a tuple of keys and values - /// when iterated over. - pub fn named, Vals: IntoIterator)>>(vals: Vals) -> Self { - Composite::Named(vals.into_iter().map(|(n, v)| (n.into(), v)).collect()) - } - /// Construct an unnamed composite type from any type which produces values - /// when iterated over. - pub fn unnamed>>(vals: Vals) -> Self { - Composite::Unnamed(vals.into_iter().collect()) - } - /// 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(), - } - } - - /// Iterate over the values stored in this composite type. - pub fn values(&self) -> impl Iterator> { - match self { - Composite::Named(values) => Either::Left(values.iter().map(|(_k, v)| v)), - Composite::Unnamed(values) => Either::Right(values.iter()), - } - } - - /// Iterate over the values stored in this composite type. - pub fn into_values(self) -> impl Iterator> { - match self { - Composite::Named(values) => Either::Left(values.into_iter().map(|(_k, v)| v)), - Composite::Unnamed(values) => Either::Right(values.into_iter()), - } - } - - /// 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) - } - } - } + /// Construct a named composite type from any type which produces a tuple of keys and values + /// when iterated over. + pub fn named, Vals: IntoIterator)>>(vals: Vals) -> Self { + Composite::Named(vals.into_iter().map(|(n, v)| (n.into(), v)).collect()) + } + /// Construct an unnamed composite type from any type which produces values + /// when iterated over. + pub fn unnamed>>(vals: Vals) -> Self { + Composite::Unnamed(vals.into_iter().collect()) + } + /// 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(), + } + } + + /// Iterate over the values stored in this composite type. + pub fn values(&self) -> impl ExactSizeIterator> { + match self { + Composite::Named(values) => Either::Left(values.iter().map(|(_k, v)| v)), + Composite::Unnamed(values) => Either::Right(values.iter()), + } + } + + /// Iterate over the values stored in this composite type. + pub fn into_values(self) -> impl ExactSizeIterator> { + match self { + Composite::Named(values) => Either::Left(values.into_iter().map(|(_k, v)| v)), + Composite::Unnamed(values) => Either::Right(values.into_iter()), + } + } + + /// 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>> From> for Composite<()> { - fn from(vals: Vec) -> Self { - let vals = vals.into_iter().map(|v| v.into()).collect(); - Composite::Unnamed(vals) - } + fn from(vals: Vec) -> Self { + let vals = vals.into_iter().map(|v| v.into()).collect(); + Composite::Unnamed(vals) + } } impl>> From> for ValueDef<()> { - fn from(vals: Vec) -> Self { - ValueDef::Composite(vals.into()) - } + fn from(vals: Vec) -> Self { + ValueDef::Composite(vals.into()) + } } impl>> From> for Value<()> { - fn from(vals: Vec) -> Self { - Value::without_context(vals.into()) - } + fn from(vals: Vec) -> Self { + Value::without_context(vals.into()) + } } impl, V: Into>> From> for Composite<()> { - fn from(vals: Vec<(K, V)>) -> Self { - let vals = vals.into_iter().map(|(k, v)| (k.into(), v.into())).collect(); - Composite::Named(vals) - } + fn from(vals: Vec<(K, V)>) -> Self { + let vals = vals.into_iter().map(|(k, v)| (k.into(), v.into())).collect(); + Composite::Named(vals) + } } impl, V: Into>> From> for ValueDef<()> { - fn from(vals: Vec<(K, V)>) -> Self { - ValueDef::Composite(vals.into()) - } + fn from(vals: Vec<(K, V)>) -> Self { + ValueDef::Composite(vals.into()) + } } impl, V: Into>> From> for Value<()> { - fn from(vals: Vec<(K, V)>) -> Self { - Value::without_context(vals.into()) - } + fn from(vals: Vec<(K, V)>) -> Self { + Value::without_context(vals.into()) + } } impl From> for ValueDef { - fn from(val: Composite) -> Self { - ValueDef::Composite(val) - } + fn from(val: Composite) -> Self { + ValueDef::Composite(val) + } } impl From> for Value<()> { - fn from(val: Composite<()>) -> Self { - Value::without_context(ValueDef::Composite(val)) - } + fn from(val: Composite<()>) -> Self { + Value::without_context(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, Debug, PartialEq, Eq)] 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, + /// 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 { - /// Construct a variant with named fields. - pub fn named_fields(name: S, fields: Vals) -> Variant - where - S: Into, - K: Into, - Vals: IntoIterator)>, - { - Variant { name: name.into(), values: Composite::named(fields) } - } - /// Construct a variant with tuple-like fields. - pub fn unnamed_fields(name: S, fields: Vals) -> Variant - where - S: Into, - Vals: IntoIterator>, - { - Variant { name: name.into(), values: Composite::unnamed(fields) } - } - /// 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) } - } + /// Construct a variant with named fields. + pub fn named_fields(name: S, fields: Vals) -> Variant + where + S: Into, + K: Into, + Vals: IntoIterator)>, + { + Variant { name: name.into(), values: Composite::named(fields) } + } + /// Construct a variant with tuple-like fields. + pub fn unnamed_fields(name: S, fields: Vals) -> Variant + where + S: Into, + Vals: IntoIterator>, + { + Variant { name: name.into(), values: Composite::unnamed(fields) } + } + /// 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 From> for ValueDef { - fn from(val: Variant) -> Self { - ValueDef::Variant(val) - } + fn from(val: Variant) -> Self { + ValueDef::Variant(val) + } } impl From> for Value<()> { - fn from(val: Variant<()>) -> Self { - Value::without_context(ValueDef::Variant(val)) - } + fn from(val: Variant<()>) -> Self { + Value::without_context(ValueDef::Variant(val)) + } } /// A "primitive" value (this includes strings). #[derive(Debug, Clone, PartialEq, Eq)] pub enum Primitive { - /// A boolean value. - Bool(bool), - /// A single character. - Char(char), - /// A string. - String(String), - /// A u128 value. - U128(u128), - /// An i128 value. - I128(i128), - /// An unsigned 256 bit number (internally represented as a 32 byte array). - U256([u8; 32]), - /// A signed 256 bit number (internally represented as a 32 byte array). - I256([u8; 32]), + /// A boolean value. + Bool(bool), + /// A single character. + Char(char), + /// A string. + String(String), + /// A u128 value. + U128(u128), + /// An i128 value. + I128(i128), + /// An unsigned 256 bit number (internally represented as a 32 byte array). + U256([u8; 32]), + /// A signed 256 bit number (internally represented as a 32 byte array). + I256([u8; 32]), } impl Primitive { - /// Create a new unsigned integer without additional context. - pub fn u128(val: u128) -> Primitive { - Primitive::U128(val) - } - /// Create a new signed integer without additional context. - pub fn i128(val: i128) -> Primitive { - Primitive::I128(val) - } - /// If the primitive type is a boolean value, return it. - pub fn as_bool(&self) -> Option { - match self { - Primitive::Bool(b) => Some(*b), - _ => None, - } - } - /// If the primitive type is a char, return it. - pub fn as_char(&self) -> Option { - match self { - Primitive::Char(c) => Some(*c), - _ => None, - } - } - /// If the primitive type is a u128, return it. - pub fn as_u128(&self) -> Option { - match self { - Primitive::U128(n) => Some(*n), - _ => None, - } - } - /// If the primitive type is an i128, return it. - pub fn as_i128(&self) -> Option { - match self { - Primitive::I128(n) => Some(*n), - _ => None, - } - } - /// If the primitive type is a string, return it. - pub fn as_str(&self) -> Option<&str> { - match self { - Primitive::String(s) => Some(&**s), - _ => None, - } - } + /// Create a new unsigned integer without additional context. + pub fn u128(val: u128) -> Primitive { + Primitive::U128(val) + } + /// Create a new signed integer without additional context. + pub fn i128(val: i128) -> Primitive { + Primitive::I128(val) + } + /// If the primitive type is a boolean value, return it. + pub fn as_bool(&self) -> Option { + match self { + Primitive::Bool(b) => Some(*b), + _ => None, + } + } + /// If the primitive type is a char, return it. + pub fn as_char(&self) -> Option { + match self { + Primitive::Char(c) => Some(*c), + _ => None, + } + } + /// If the primitive type is a u128, return it. + pub fn as_u128(&self) -> Option { + match self { + Primitive::U128(n) => Some(*n), + _ => None, + } + } + /// If the primitive type is an i128, return it. + pub fn as_i128(&self) -> Option { + match self { + Primitive::I128(n) => Some(*n), + _ => None, + } + } + /// If the primitive type is a string, return it. + pub fn as_str(&self) -> Option<&str> { + match self { + Primitive::String(s) => Some(&**s), + _ => None, + } + } } impl From for ValueDef { - fn from(val: Primitive) -> Self { - ValueDef::Primitive(val) - } + fn from(val: Primitive) -> Self { + ValueDef::Primitive(val) + } } macro_rules! impl_primitive_type {