Skip to content

Commit 0b2c31e

Browse files
cmichiascjones
andauthored
Add conversion and default functions for NumberOrHex (paritytech#636)
* Add conversion and default functions for `NumberOrHex` * Update subxt/src/rpc.rs Co-authored-by: Andrew Jones <ascjones@gmail.com> * Derive `Debug` with `thiserror::Error` * Remove unnecessary `#[cfg(test)]` * Add `#[error(…)]` * Remove `()` Co-authored-by: Andrew Jones <ascjones@gmail.com>
1 parent 2076cc8 commit 0b2c31e

File tree

1 file changed

+103
-0
lines changed

1 file changed

+103
-0
lines changed

subxt/src/rpc.rs

+103
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,87 @@ impl From<NumberOrHex> for BlockNumber {
135135
}
136136
}
137137

138+
impl Default for NumberOrHex {
139+
fn default() -> Self {
140+
Self::Number(Default::default())
141+
}
142+
}
143+
144+
impl NumberOrHex {
145+
/// Converts this number into an U256.
146+
pub fn into_u256(self) -> U256 {
147+
match self {
148+
NumberOrHex::Number(n) => n.into(),
149+
NumberOrHex::Hex(h) => h,
150+
}
151+
}
152+
}
153+
154+
impl From<u32> for NumberOrHex {
155+
fn from(n: u32) -> Self {
156+
NumberOrHex::Number(n.into())
157+
}
158+
}
159+
160+
impl From<u64> for NumberOrHex {
161+
fn from(n: u64) -> Self {
162+
NumberOrHex::Number(n)
163+
}
164+
}
165+
166+
impl From<u128> for NumberOrHex {
167+
fn from(n: u128) -> Self {
168+
NumberOrHex::Hex(n.into())
169+
}
170+
}
171+
172+
impl From<U256> for NumberOrHex {
173+
fn from(n: U256) -> Self {
174+
NumberOrHex::Hex(n)
175+
}
176+
}
177+
178+
/// An error type that signals an out-of-range conversion attempt.
179+
#[derive(Debug, thiserror::Error)]
180+
#[error("Out-of-range conversion attempt")]
181+
pub struct TryFromIntError;
182+
183+
impl TryFrom<NumberOrHex> for u32 {
184+
type Error = TryFromIntError;
185+
fn try_from(num_or_hex: NumberOrHex) -> Result<u32, Self::Error> {
186+
num_or_hex
187+
.into_u256()
188+
.try_into()
189+
.map_err(|_| TryFromIntError)
190+
}
191+
}
192+
193+
impl TryFrom<NumberOrHex> for u64 {
194+
type Error = TryFromIntError;
195+
fn try_from(num_or_hex: NumberOrHex) -> Result<u64, Self::Error> {
196+
num_or_hex
197+
.into_u256()
198+
.try_into()
199+
.map_err(|_| TryFromIntError)
200+
}
201+
}
202+
203+
impl TryFrom<NumberOrHex> for u128 {
204+
type Error = TryFromIntError;
205+
fn try_from(num_or_hex: NumberOrHex) -> Result<u128, Self::Error> {
206+
num_or_hex
207+
.into_u256()
208+
.try_into()
209+
.map_err(|_| TryFromIntError)
210+
}
211+
}
212+
213+
impl From<NumberOrHex> for U256 {
214+
fn from(num_or_hex: NumberOrHex) -> U256 {
215+
num_or_hex.into_u256()
216+
}
217+
}
218+
138219
// All unsigned ints can be converted into a BlockNumber:
139220
macro_rules! into_block_number {
140221
($($t: ty)+) => {
@@ -639,6 +720,18 @@ fn to_hex(bytes: impl AsRef<[u8]>) -> String {
639720
mod test {
640721
use super::*;
641722

723+
/// A util function to assert the result of serialization and deserialization is the same.
724+
pub(crate) fn assert_deser<T>(s: &str, expected: T)
725+
where
726+
T: std::fmt::Debug
727+
+ serde::ser::Serialize
728+
+ serde::de::DeserializeOwned
729+
+ PartialEq,
730+
{
731+
assert_eq!(serde_json::from_str::<T>(s).unwrap(), expected);
732+
assert_eq!(serde_json::to_string(&expected).unwrap(), s);
733+
}
734+
642735
#[test]
643736
fn test_deser_runtime_version() {
644737
let val: RuntimeVersion = serde_json::from_str(
@@ -664,4 +757,14 @@ mod test {
664757
}
665758
);
666759
}
760+
761+
#[test]
762+
fn should_serialize_and_deserialize() {
763+
assert_deser(r#""0x1234""#, NumberOrHex::Hex(0x1234.into()));
764+
assert_deser(r#""0x0""#, NumberOrHex::Hex(0.into()));
765+
assert_deser(r#"5"#, NumberOrHex::Number(5));
766+
assert_deser(r#"10000"#, NumberOrHex::Number(10000));
767+
assert_deser(r#"0"#, NumberOrHex::Number(0));
768+
assert_deser(r#"1000000000000"#, NumberOrHex::Number(1000000000000));
769+
}
667770
}

0 commit comments

Comments
 (0)