-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathserde.rs
142 lines (113 loc) · 4.07 KB
/
serde.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Custom serde serialization helpers
/// Serialization shim for arbitrary arrays that is consistent with `polkadot-js`'s implementation.
///
/// `polkadot-js` sends us a `0x01020304`, but the default rust implementation for arrays expects a
/// `[0x01, 0x02, 0x03, 0x04]`. Here, we use a similar serialization as substrate uses for `vec`,
/// but we transform it to an array before returning.
pub mod serialize_array {
use impl_serde::serialize::{deserialize_check_len, ExpectedLen};
use serde::Deserializer;
// default serialize is fine
pub use impl_serde::serialize::serialize;
pub use deserialize_array as deserialize;
pub fn deserialize_array<'de, D, const T: usize>(deserializer: D) -> Result<[u8; T], D::Error>
where
D: Deserializer<'de>,
{
// All hail the stable const generics!
let mut arr = [0u8; T];
deserialize_check_len(deserializer, ExpectedLen::Exact(&mut arr[..]))?;
Ok(arr)
}
}
/// Serialization shim for fixed point numbers that is consistent with `polkadot-js`'s implementation.
///
/// This is needed in particular for fixed point types that map to a i-/u128, as serde has problems
/// with it: https://github.com/paritytech/substrate/issues/4641
pub mod serialize_fixed {
use fixed::traits::Fixed;
use serde::{de::Error, Deserializer};
use impl_serde::serde::Deserialize;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::string::ToString;
pub use deserialize_fixed as deserialize;
pub use serialize_fixed as serialize;
pub fn serialize_fixed<S, F: Fixed>(f: &F, s: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
s.serialize_str(&f.to_string())
}
pub fn deserialize_fixed<'de, D, F: Fixed>(d: D) -> Result<F, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(d)?;
F::from_str(&s).map_err(D::Error::custom)
}
}
#[cfg(test)]
mod tests {
use super::{serialize_array, serialize_fixed};
use fixed::{traits::Fixed, types::I64F64};
fn deserialize_array<const T: usize>(arr: &str) -> [u8; T] {
let mut der = serde_json::Deserializer::new(serde_json::de::StrRead::new(arr));
serialize_array::deserialize(&mut der).unwrap()
}
fn serialize_array<const T: usize>(arr: [u8; T]) -> String {
let mut v = vec![];
let mut ser = serde_json::Serializer::new(std::io::Cursor::new(&mut v));
serialize_array::serialize(&arr, &mut ser).unwrap();
String::from_utf8(v).unwrap()
}
fn serialize_fixed_point<F: Fixed>(f: F) -> String {
let mut v = vec![];
let mut ser = serde_json::Serializer::new(std::io::Cursor::new(&mut v));
serialize_fixed::serialize(&f, &mut ser).unwrap();
String::from_utf8(v).unwrap()
}
fn deserialize_fixed_point<F: Fixed>(f: &str) -> F {
let mut der = serde_json::Deserializer::new(serde_json::de::StrRead::new(f));
serialize_fixed::deserialize(&mut der).unwrap()
}
#[test]
fn deserialize_array_works() {
assert_eq!(deserialize_array("\"0x0000\""), [0x00, 0x00]);
assert_eq!(deserialize_array("\"0x0100\""), [0x01, 0x00]);
assert_eq!(deserialize_array("\"0x0010\""), [0x00, 0x10]);
}
#[test]
fn serialize_array_works() {
assert_eq!(serialize_array([0x00, 0x00]), "\"0x0000\"".to_owned());
assert_eq!(serialize_array([0x01, 0x00]), "\"0x0100\"".to_owned());
assert_eq!(serialize_array([0x00, 0x10]), "\"0x0010\"".to_owned());
}
#[test]
fn serialize_fixed_works() {
assert_eq!(
serialize_fixed_point(I64F64::from_num(18.6808776855468714473)),
"\"18.6808776855468714473\"".to_owned()
);
assert_eq!(
serialize_fixed_point(I64F64::from_num(0.6808776855468714473)),
"\"0.6808776855468714473\"".to_owned()
);
assert_eq!(serialize_fixed_point(I64F64::from_num(1)), "\"1\"".to_owned());
}
#[test]
fn deserialize_fixed_works() {
assert_eq!(
deserialize_fixed_point::<I64F64>("\"18.6808776855468714473\""),
I64F64::from_num(18.6808776855468714473)
);
assert_eq!(
deserialize_fixed_point::<I64F64>("\"0.6808776855468714473\""),
I64F64::from_num(0.6808776855468714473)
);
assert_eq!(deserialize_fixed_point::<I64F64>("\"1\""), I64F64::from_num(1));
}
}