1use std::str::FromStr;
2
3use num_bigint::{BigInt, BigUint};
4use primitive_types::H256;
5use sp_arithmetic::{PerU16, Perbill, Percent, Permill, Perquintill};
6use substrate_crypto_light::{
7 common::AccountId32,
8 ecdsa::{Public as PublicEcdsa, Signature as SignatureEcdsa},
9 ed25519::{Public as PublicEd25519, Signature as SignatureEd25519},
10 sr25519::{Public as PublicSr25519, Signature as SignatureSr25519},
11};
12
13use crate::{
14 fill_prepare::{
15 ArrayU8ToFill, EraToFill, RegularPrimitiveToFill, SequenceU8ToFill, SpecialTypeToFill,
16 UnsignedToFill,
17 },
18 traits::Unsigned,
19};
20
21pub trait TryFill {
22 fn upd_from_str(&mut self, source: &str);
23}
24
25macro_rules! primitive_str {
26 ($ty:ty, $old:tt, $source:tt) => {
27 if let Ok(value) = <$ty>::from_str($source) {
28 *$old = Some(value)
29 }
30 };
31}
32
33impl TryFill for UnsignedToFill {
34 fn upd_from_str(&mut self, source: &str) {
35 match self {
36 UnsignedToFill::U8(ref mut old) => primitive_str!(u8, old, source),
37 UnsignedToFill::U16(ref mut old) => primitive_str!(u16, old, source),
38 UnsignedToFill::U32(ref mut old) => primitive_str!(u32, old, source),
39 UnsignedToFill::U64(ref mut old) => primitive_str!(u64, old, source),
40 UnsignedToFill::U128(ref mut old) => primitive_str!(u128, old, source),
41 }
42 }
43}
44
45macro_rules! unsigned {
46 ($variant:ident, $old:tt, $source:tt) => {
47 if let Unsigned::$variant(value) = $source {
48 *$old = Some(*value)
49 }
50 };
51}
52
53macro_rules! unsigned_fit {
54 ($ty:ty, $old:tt, $source:tt) => {
55 if let Ok(value) = <$ty>::try_from($source) {
56 *$old = Some(value)
57 }
58 };
59}
60
61impl UnsignedToFill {
62 pub fn upd_from_unsigned(&mut self, source: &Unsigned) {
63 match self {
64 UnsignedToFill::U8(ref mut old) => unsigned!(U8, old, source),
65 UnsignedToFill::U16(ref mut old) => unsigned!(U16, old, source),
66 UnsignedToFill::U32(ref mut old) => unsigned!(U32, old, source),
67 UnsignedToFill::U64(ref mut old) => unsigned!(U64, old, source),
68 UnsignedToFill::U128(ref mut old) => unsigned!(U128, old, source),
69 }
70 }
71
72 #[allow(irrefutable_let_patterns)]
73 pub fn upd_from_u8(&mut self, source: u8) {
74 match self {
75 UnsignedToFill::U8(ref mut old) => unsigned_fit!(u8, old, source),
76 UnsignedToFill::U16(ref mut old) => unsigned_fit!(u16, old, source),
77 UnsignedToFill::U32(ref mut old) => unsigned_fit!(u32, old, source),
78 UnsignedToFill::U64(ref mut old) => unsigned_fit!(u64, old, source),
79 UnsignedToFill::U128(ref mut old) => unsigned_fit!(u128, old, source),
80 }
81 }
82
83 #[allow(irrefutable_let_patterns)]
84 pub fn upd_from_u32(&mut self, source: u32) {
85 match self {
86 UnsignedToFill::U8(ref mut old) => unsigned_fit!(u8, old, source),
87 UnsignedToFill::U16(ref mut old) => unsigned_fit!(u16, old, source),
88 UnsignedToFill::U32(ref mut old) => unsigned_fit!(u32, old, source),
89 UnsignedToFill::U64(ref mut old) => unsigned_fit!(u64, old, source),
90 UnsignedToFill::U128(ref mut old) => unsigned_fit!(u128, old, source),
91 }
92 }
93}
94
95impl TryFill for RegularPrimitiveToFill {
96 fn upd_from_str(&mut self, source: &str) {
97 match self {
98 RegularPrimitiveToFill::Bool(ref mut old) => primitive_str!(bool, old, source),
99 RegularPrimitiveToFill::Char(ref mut old) => primitive_str!(char, old, source),
100 RegularPrimitiveToFill::I8(ref mut old) => primitive_str!(i8, old, source),
101 RegularPrimitiveToFill::I16(ref mut old) => primitive_str!(i16, old, source),
102 RegularPrimitiveToFill::I32(ref mut old) => primitive_str!(i32, old, source),
103 RegularPrimitiveToFill::I64(ref mut old) => primitive_str!(i64, old, source),
104 RegularPrimitiveToFill::I128(ref mut old) => primitive_str!(i128, old, source),
105 RegularPrimitiveToFill::I256(ref mut old) => primitive_str!(BigInt, old, source),
106 RegularPrimitiveToFill::Str(ref mut old) => source.clone_into(old),
107 RegularPrimitiveToFill::U256(ref mut old) => primitive_str!(BigUint, old, source),
108 }
109 }
110}
111
112macro_rules! array_from_hex {
113 ($ty:expr, $old:tt, $source:tt) => {
114 if let Ok(value) = hex::decode($source) {
115 if let Ok(array) = value.try_into() {
116 *$old = Some($ty(array))
117 }
118 }
119 };
120}
121
122macro_rules! perthing_from_str {
123 ($ty:ty, $inner_ty:ty, $old:tt, $source:tt) => {
124 if let Ok(parts) = <$inner_ty>::from_str($source) {
125 *$old = Some(<$ty>::from_parts(parts))
126 }
127 };
128}
129
130impl TryFill for SpecialTypeToFill {
131 fn upd_from_str(&mut self, source: &str) {
132 match self {
133 SpecialTypeToFill::AccountId32(ref mut old) => {
134 array_from_hex!(AccountId32, old, source)
135 }
136 SpecialTypeToFill::Era(ref mut old) => {
137 let possibly_mortal: Vec<&str> = source.split(' ').collect();
138 if possibly_mortal.len() == 2 {
139 if let Ok(period_entry) = u64::from_str(possibly_mortal[0]) {
140 if let Ok(block_number_entry) = u64::from_str(possibly_mortal[1]) {
141 *old = EraToFill::Mortal {
142 period_entry,
143 block_number_entry: Some(block_number_entry),
144 };
145 }
146 }
147 }
148 }
149 SpecialTypeToFill::H256 {
150 hash: ref mut old,
151 specialty: _,
152 } => array_from_hex!(H256, old, source),
153 SpecialTypeToFill::PerU16 {
154 value: ref mut old,
155 is_compact: _,
156 } => perthing_from_str!(PerU16, u16, old, source),
157 SpecialTypeToFill::Perbill {
158 value: ref mut old,
159 is_compact: _,
160 } => perthing_from_str!(Perbill, u32, old, source),
161 SpecialTypeToFill::Percent {
162 value: ref mut old,
163 is_compact: _,
164 } => perthing_from_str!(Percent, u8, old, source),
165 SpecialTypeToFill::Permill {
166 value: ref mut old,
167 is_compact: _,
168 } => perthing_from_str!(Permill, u32, old, source),
169 SpecialTypeToFill::Perquintill {
170 value: ref mut old,
171 is_compact: _,
172 } => perthing_from_str!(Perquintill, u64, old, source),
173 SpecialTypeToFill::PublicEd25519(ref mut old) => {
174 array_from_hex!(PublicEd25519, old, source)
175 }
176 SpecialTypeToFill::PublicSr25519(ref mut old) => {
177 array_from_hex!(PublicSr25519, old, source)
178 }
179 SpecialTypeToFill::PublicEcdsa(ref mut old) => {
180 array_from_hex!(PublicEcdsa, old, source)
181 }
182 SpecialTypeToFill::SignatureEd25519(ref mut old) => {
183 array_from_hex!(SignatureEd25519, old, source)
184 }
185 SpecialTypeToFill::SignatureSr25519(ref mut old) => {
186 array_from_hex!(SignatureSr25519, old, source)
187 }
188 SpecialTypeToFill::SignatureEcdsa(ref mut old) => {
189 array_from_hex!(SignatureEcdsa, old, source)
190 }
191 }
192 }
193}
194
195pub trait TryBytesFill {
196 fn upd_from_single_byte(&mut self, source: &str);
197 fn upd_from_hex(&mut self, source: &str);
198 fn upd_from_utf8(&mut self, source: &str);
199}
200
201impl TryBytesFill for ArrayU8ToFill {
202 fn upd_from_single_byte(&mut self, source: &str) {
203 if let Ok(addition) = u8::from_str(source) {
204 if (self.content.len() as u32) < self.len {
205 self.content.push(addition)
206 }
207 }
208 }
209 fn upd_from_hex(&mut self, source: &str) {
210 if let Ok(value) = hex::decode(source) {
211 if value.len() as u32 == self.len {
212 self.content = value;
213 }
214 }
215 }
216 fn upd_from_utf8(&mut self, source: &str) {
217 let value = source.as_bytes().to_vec();
218 if value.len() as u32 == self.len {
219 self.content = value;
220 }
221 }
222}
223
224impl TryBytesFill for SequenceU8ToFill {
225 fn upd_from_single_byte(&mut self, source: &str) {
226 if let Ok(addition) = u8::from_str(source) {
227 self.content.push(addition)
228 }
229 }
230 fn upd_from_hex(&mut self, source: &str) {
231 if let Ok(value) = hex::decode(source) {
232 self.content = value;
233 }
234 }
235 fn upd_from_utf8(&mut self, source: &str) {
236 self.content = source.as_bytes().to_vec();
237 }
238}