Allow batch query for block hash. (#4210)

This commit is contained in:
Tomasz Drwięga
2019-11-26 18:07:31 +01:00
committed by Gavin Wood
parent 70bc6eaed6
commit cfb590ac4b
8 changed files with 159 additions and 20 deletions
+17
View File
@@ -19,3 +19,20 @@
#![warn(missing_docs)]
pub mod number;
pub mod list;
/// A util function to assert the result of serialization and deserialization is the same.
#[cfg(test)]
pub(crate) fn assert_deser<T>(s: &str, expected: T) where
T: std::fmt::Debug + serde::ser::Serialize + serde::de::DeserializeOwned + PartialEq
{
assert_eq!(
serde_json::from_str::<T>(s).unwrap(),
expected
);
assert_eq!(
serde_json::to_string(&expected).unwrap(),
s
);
}
+75
View File
@@ -0,0 +1,75 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! RPC a lenient list or value type.
use serde::{Serialize, Deserialize};
/// RPC list or value wrapper.
///
/// For some RPCs it's convenient to call them with either
/// a single value or a whole list of values to get a proper response.
/// In theory you could do a batch query, but it's:
/// 1. Less convient in client libraries
/// 2. If the response value is small, the protocol overhead might be dominant.
///
/// Also it's nice to be able to maintain backward compatibility for methods that
/// were initially taking a value and now we want to expand them to take a list.
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum ListOrValue<T> {
/// A list of values of given type.
List(Vec<T>),
/// A single value of given type.
Value(T),
}
impl<T> ListOrValue<T> {
/// Map every contained value using function `F`.
///
/// This allows to easily convert all values in any of the variants.
pub fn map<F: Fn(T) -> X, X>(self, f: F) -> ListOrValue<X> {
match self {
ListOrValue::List(v) => ListOrValue::List(v.into_iter().map(f).collect()),
ListOrValue::Value(v) => ListOrValue::Value(f(v)),
}
}
}
impl<T> From<T> for ListOrValue<T> {
fn from(n: T) -> Self {
ListOrValue::Value(n)
}
}
impl<T> From<Vec<T>> for ListOrValue<T> {
fn from(n: Vec<T>) -> Self {
ListOrValue::List(n)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::assert_deser;
#[test]
fn should_serialize_and_deserialize() {
assert_deser(r#"5"#, ListOrValue::Value(5_u64));
assert_deser(r#""str""#, ListOrValue::Value("str".to_string()));
assert_deser(r#"[1,2,3]"#, ListOrValue::List(vec![1_u64, 2_u64, 3_u64]));
}
}
+16 -1
View File
@@ -27,7 +27,7 @@ use primitives::U256;
/// or we attempt to parse given hex value.
/// We do that for consistency with the returned type, default generic header
/// serializes block number as hex to avoid overflows in JavaScript.
#[derive(Serialize, Deserialize)]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
#[serde(untagged)]
pub enum NumberOrHex<Number> {
/// The original header number type of block.
@@ -72,3 +72,18 @@ impl<Number> From<U256> for NumberOrHex<Number> {
NumberOrHex::Hex(n)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::assert_deser;
#[test]
fn should_serialize_and_deserialize() {
assert_deser(r#""0x1234""#, NumberOrHex::<u128>::Hex(0x1234.into()));
assert_deser(r#""0x0""#, NumberOrHex::<u64>::Hex(0.into()));
assert_deser(r#"5"#, NumberOrHex::Number(5_u64));
assert_deser(r#"10000"#, NumberOrHex::Number(10000_u32));
assert_deser(r#"0"#, NumberOrHex::Number(0_u16));
}
}