Skip to content

Commit fd9ec55

Browse files
committed
Add conversions module / errors
Add to_u32() helper
1 parent 5b2da18 commit fd9ec55

File tree

3 files changed

+146
-0
lines changed

3 files changed

+146
-0
lines changed

packages/std/src/conversion.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use std::any::type_name;
2+
use std::convert::TryInto;
3+
4+
use crate::errors::{StdError, StdResult};
5+
6+
pub fn to_u32<T: TryInto<u32> + ToString + Copy>(input: T) -> StdResult<u32> {
7+
input.try_into().map_err(|_| {
8+
StdError::conversion_err(type_name::<T>(), type_name::<u32>(), input.to_string())
9+
})
10+
}
11+
12+
#[cfg(test)]
13+
mod tests {
14+
use super::*;
15+
16+
#[test]
17+
fn to_u32_works_for_usize() {
18+
assert_eq!(to_u32(0usize).unwrap(), 0);
19+
assert_eq!(to_u32(1usize).unwrap(), 1);
20+
assert_eq!(to_u32(2147483647usize).unwrap(), 2147483647);
21+
assert_eq!(to_u32(2147483648usize).unwrap(), 2147483648);
22+
assert_eq!(to_u32(4294967295usize).unwrap(), 4294967295);
23+
24+
match to_u32(4294967296usize) {
25+
Err(StdError::ConversionErr {
26+
from_type,
27+
to_type,
28+
input,
29+
..
30+
}) => {
31+
assert_eq!(from_type, "usize");
32+
assert_eq!(to_type, "u32");
33+
assert_eq!(input, "4294967296");
34+
}
35+
Err(err) => panic!("unexpected error: {:?}", err),
36+
Ok(_) => panic!("must not succeed"),
37+
};
38+
}
39+
40+
#[test]
41+
fn to_u32_works_for_u64() {
42+
assert_eq!(to_u32(0u64).unwrap(), 0);
43+
assert_eq!(to_u32(1u64).unwrap(), 1);
44+
assert_eq!(to_u32(2147483647u64).unwrap(), 2147483647);
45+
assert_eq!(to_u32(2147483648u64).unwrap(), 2147483648);
46+
assert_eq!(to_u32(4294967295u64).unwrap(), 4294967295);
47+
48+
match to_u32(4294967296u64) {
49+
Err(StdError::ConversionErr {
50+
from_type,
51+
to_type,
52+
input,
53+
..
54+
}) => {
55+
assert_eq!(from_type, "u64");
56+
assert_eq!(to_type, "u32");
57+
assert_eq!(input, "4294967296");
58+
}
59+
Err(err) => panic!("unexpected error: {:?}", err),
60+
Ok(_) => panic!("must not succeed"),
61+
};
62+
}
63+
64+
#[test]
65+
fn to_u32_works_for_i32() {
66+
assert_eq!(to_u32(0i32).unwrap(), 0);
67+
assert_eq!(to_u32(1i32).unwrap(), 1);
68+
assert_eq!(to_u32(2147483647i32).unwrap(), 2147483647);
69+
70+
match to_u32(-1i32) {
71+
Err(StdError::ConversionErr {
72+
from_type,
73+
to_type,
74+
input,
75+
..
76+
}) => {
77+
assert_eq!(from_type, "i32");
78+
assert_eq!(to_type, "u32");
79+
assert_eq!(input, "-1");
80+
}
81+
Err(err) => panic!("unexpected error: {:?}", err),
82+
Ok(_) => panic!("must not succeed"),
83+
};
84+
}
85+
}

packages/std/src/errors/std_error.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ pub enum StdError {
3333
#[cfg(feature = "backtraces")]
3434
backtrace: Backtrace,
3535
},
36+
#[error("Couldn't convert from {} to {}. Input: {}", from_type, to_type, input)]
37+
ConversionErr {
38+
from_type: String,
39+
to_type: String,
40+
input: String,
41+
#[cfg(feature = "backtraces")]
42+
backtrace: Backtrace,
43+
},
3644
/// Whenever there is no specific error type available
3745
#[error("Generic error: {msg}")]
3846
GenericErr {
@@ -108,6 +116,20 @@ impl StdError {
108116
}
109117
}
110118

119+
pub fn conversion_err<S: Into<String>, T: Into<String>, U: Into<String>>(
120+
from_type: S,
121+
to_type: T,
122+
input: U,
123+
) -> Self {
124+
StdError::ConversionErr {
125+
from_type: from_type.into(),
126+
to_type: to_type.into(),
127+
input: input.into(),
128+
#[cfg(feature = "backtraces")]
129+
backtrace: Backtrace::capture(),
130+
}
131+
}
132+
111133
pub fn generic_err<S: Into<String>>(msg: S) -> Self {
112134
StdError::GenericErr {
113135
msg: msg.into(),
@@ -213,6 +235,26 @@ impl PartialEq<StdError> for StdError {
213235
false
214236
}
215237
}
238+
StdError::ConversionErr {
239+
from_type,
240+
to_type,
241+
input,
242+
#[cfg(feature = "backtraces")]
243+
backtrace: _,
244+
} => {
245+
if let StdError::ConversionErr {
246+
from_type: rhs_from_type,
247+
to_type: rhs_to_type,
248+
input: rhs_input,
249+
#[cfg(feature = "backtraces")]
250+
backtrace: _,
251+
} = rhs
252+
{
253+
from_type == rhs_from_type && to_type == rhs_to_type && input == rhs_input
254+
} else {
255+
false
256+
}
257+
}
216258
StdError::GenericErr {
217259
msg,
218260
#[cfg(feature = "backtraces")]
@@ -414,6 +456,24 @@ mod tests {
414456
}
415457
}
416458

459+
#[test]
460+
fn conversion_err_works() {
461+
let error = StdError::conversion_err("i32", "u32", "-9");
462+
match error {
463+
StdError::ConversionErr {
464+
from_type,
465+
to_type,
466+
input,
467+
..
468+
} => {
469+
assert_eq!(from_type, "i32");
470+
assert_eq!(to_type, "u32");
471+
assert_eq!(input, "-9");
472+
}
473+
e => panic!("Unexpected error: {:?}", e),
474+
}
475+
}
476+
417477
#[test]
418478
fn invalid_base64_works_for_strings() {
419479
let error = StdError::invalid_base64("my text");

packages/std/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
mod addresses;
77
mod binary;
88
mod coins;
9+
mod conversion;
910
mod deps;
1011
mod entry_points;
1112
mod errors;

0 commit comments

Comments
 (0)