diff --git a/substrate/core/rpc/src/state/tests.rs b/substrate/core/rpc/src/state/tests.rs index 6b4ddc9b920bc9b0dbf9eb0c219e9c4cb3a4aef7..0bb6d40e24c69e9a151de3064a3fd5da329911f5 100644 --- a/substrate/core/rpc/src/state/tests.rs +++ b/substrate/core/rpc/src/state/tests.rs @@ -262,10 +262,12 @@ fn should_return_runtime_version() { [\"0xc6e9a76309f39b09\",1],[\"0xdd718d5cc53262d4\",1],[\"0xcbca25e39f142387\",1],\ [\"0xf78b278be53f454c\",1],[\"0xab3c0572291feb8b\",1]]}"; - assert_eq!( - serde_json::to_string(&api.runtime_version(None.into()).unwrap()).unwrap(), - result, - ); + let runtime_version = api.runtime_version(None.into()).unwrap(); + let serialized = serde_json::to_string(&runtime_version).unwrap(); + assert_eq!(serialized, result); + + let deserialized: RuntimeVersion = serde_json::from_str(result).unwrap(); + assert_eq!(deserialized, runtime_version); } #[test] diff --git a/substrate/core/sr-version/src/lib.rs b/substrate/core/sr-version/src/lib.rs index 731c5b63c7137cf9d00c3253c9021d0e4af35e1d..f787d8dd7ebfb112b64442eea53f0adbfa46f63a 100644 --- a/substrate/core/sr-version/src/lib.rs +++ b/substrate/core/sr-version/src/lib.rs @@ -96,7 +96,13 @@ pub struct RuntimeVersion { pub impl_version: u32, /// List of supported API "features" along with their versions. - #[cfg_attr(feature = "std", serde(serialize_with = "apis_serialize::serialize"))] + #[cfg_attr( + feature = "std", + serde( + serialize_with = "apis_serialize::serialize", + deserialize_with = "apis_serialize::deserialize", + ) + )] pub apis: ApisVec, } @@ -163,7 +169,7 @@ impl NativeVersion { mod apis_serialize { use super::*; use impl_serde::serialize as bytes; - use serde::{Serializer, ser::SerializeTuple}; + use serde::{Serializer, de, ser::SerializeTuple}; #[derive(Serialize)] struct ApiId<'a>( @@ -187,4 +193,44 @@ mod apis_serialize { { bytes::serialize(*apis, ser) } + + #[derive(Deserialize)] + struct ApiIdOwned( + #[serde(deserialize_with="deserialize_bytes")] + super::ApiId, + u32, + ); + + pub fn deserialize<'de, D>(deserializer: D) -> Result<ApisVec, D::Error> where + D: de::Deserializer<'de>, + { + struct Visitor; + impl<'de> de::Visitor<'de> for Visitor { + type Value = ApisVec; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a sequence of api id and version tuples") + } + + fn visit_seq<V>(self, mut visitor: V) -> Result<Self::Value, V::Error> where + V: de::SeqAccess<'de>, + { + let mut apis = Vec::new(); + while let Some(value) = visitor.next_element::<ApiIdOwned>()? { + apis.push((value.0, value.1)); + } + Ok(apis.into()) + } + } + deserializer.deserialize_seq(Visitor) + } + + pub fn deserialize_bytes<'de, D>(d: D) -> Result<super::ApiId, D::Error> where + D: de::Deserializer<'de> + { + let bytes = bytes::deserialize_check_len(d, bytes::ExpectedLen::Exact(8))?; + let mut arr = [0; 8]; + arr.copy_from_slice(&bytes); + Ok(arr) + } }