contract_transcode/
env_types.rs1use crate::{
18 AccountId32,
19 Hex,
20 Value,
21 assert_not_shortened_hex,
22};
23use anyhow::{
24 Context,
25 Result,
26};
27use primitive_types::U128;
28use scale::{
29 Decode,
30 Encode,
31 Output,
32};
33use scale_info::{
34 IntoPortable,
35 Path,
36 TypeInfo,
37 form::PortableForm,
38};
39use std::{
40 boxed::Box,
41 collections::HashMap,
42 convert::TryFrom,
43 str::FromStr,
44};
45
46#[derive(Default)]
48pub struct EnvTypesTranscoder {
49 encoders: HashMap<u32, Box<dyn CustomTypeEncoder>>,
50 decoders: HashMap<u32, Box<dyn CustomTypeDecoder>>,
51}
52
53impl EnvTypesTranscoder {
54 pub fn new(
56 encoders: HashMap<u32, Box<dyn CustomTypeEncoder>>,
57 decoders: HashMap<u32, Box<dyn CustomTypeDecoder>>,
58 ) -> Self {
59 Self { encoders, decoders }
60 }
61
62 pub fn try_encode<O>(
69 &self,
70 type_id: u32,
71 value: &Value,
72 output: &mut O,
73 ) -> Result<bool>
74 where
75 O: Output,
76 {
77 match self.encoders.get(&type_id) {
78 Some(encoder) => {
79 tracing::debug!("Encoding type {:?} with custom encoder", type_id);
80 let encoded_env_type = encoder
81 .encode_value(value)
82 .context("Error encoding custom type")?;
83 output.write(&encoded_env_type);
84 Ok(true)
85 }
86 None => Ok(false),
87 }
88 }
89
90 pub fn try_decode(&self, type_id: u32, input: &mut &[u8]) -> Result<Option<Value>> {
98 match self.decoders.get(&type_id) {
99 Some(decoder) => {
100 tracing::debug!("Decoding type {:?} with custom decoder", type_id);
101 let decoded = decoder.decode_value(input)?;
102 Ok(Some(decoded))
103 }
104 None => {
105 tracing::debug!("No custom decoder found for type {:?}", type_id);
106 Ok(None)
107 }
108 }
109 }
110}
111
112#[derive(Clone, Debug, Eq, PartialEq, Hash)]
113pub struct PathKey(Vec<String>);
114
115impl PathKey {
116 pub fn from_type<T>() -> Self
117 where
118 T: TypeInfo,
119 {
120 let type_info = T::type_info();
121 let path = type_info.path.into_portable(&mut Default::default());
122 PathKey::from(&path)
123 }
124}
125
126impl From<&Path<PortableForm>> for PathKey {
127 fn from(path: &Path<PortableForm>) -> Self {
128 PathKey(path.segments.to_vec())
129 }
130}
131
132pub type TypesByPath = HashMap<PathKey, u32>;
133
134pub trait CustomTypeEncoder: Send + Sync {
137 fn encode_value(&self, value: &Value) -> Result<Vec<u8>>;
138}
139
140pub trait CustomTypeDecoder: Send + Sync {
143 fn decode_value(&self, input: &mut &[u8]) -> Result<Value>;
144}
145
146#[derive(Clone)]
151pub struct AccountId;
152
153impl CustomTypeEncoder for AccountId {
154 fn encode_value(&self, value: &Value) -> Result<Vec<u8>> {
155 let account_id = match value {
156 Value::Literal(literal) => {
157 AccountId32::from_str(literal).map_err(|e| {
158 anyhow::anyhow!(
159 "Error parsing AccountId from literal `{literal}`: {e}"
160 )
161 })?
162 }
163 Value::String(string) => {
164 AccountId32::from_str(string).map_err(|e| {
165 anyhow::anyhow!("Error parsing AccountId from string '{string}': {e}")
166 })?
167 }
168 Value::Hex(hex) => {
169 AccountId32::try_from(hex.bytes()).map_err(|_| {
170 anyhow::anyhow!(
171 "Error converting hex bytes `{:?}` to AccountId",
172 hex.bytes()
173 )
174 })?
175 }
176 _ => {
177 return Err(anyhow::anyhow!(
178 "Expected a string, literal, or hex for an AccountId"
179 ))
180 }
181 };
182 Ok(account_id.encode())
183 }
184}
185
186impl CustomTypeDecoder for AccountId {
187 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
188 let account_id = AccountId32::decode(input)?;
189 Ok(Value::Literal(account_id.to_ss58check()))
190 }
191}
192
193#[derive(Clone)]
196pub struct Hash;
197
198impl CustomTypeEncoder for Hash {
199 fn encode_value(&self, value: &Value) -> Result<Vec<u8>> {
200 let h256 = match value {
202 Value::Literal(literal) => {
203 primitive_types::H256::from_str(literal).map_err(|e| {
204 anyhow::anyhow!("Error parsing H256 from literal `{literal}`: {e}")
205 })?
206 }
207 Value::String(string) => {
208 primitive_types::H256::from_str(string).map_err(|e| {
209 anyhow::anyhow!("Error parsing H256 from string '{string}': {e}")
210 })?
211 }
212 Value::Hex(hex) => primitive_types::H256::from_slice(hex.bytes()),
213 _ => {
214 return Err(anyhow::anyhow!(
215 "Expected a string, hex, uint, or literal for a U256"
216 ))
217 }
218 };
219 Ok(h256.encode())
220 }
221}
222
223impl CustomTypeDecoder for Hash {
224 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
225 let hash = primitive_types::H256::decode(input)?;
226 Ok(Value::Hex(Hex::from_str(&format!("{hash:?}"))?))
227 }
228}
229
230#[derive(Clone)]
233pub struct H160;
234
235impl CustomTypeDecoder for H160 {
236 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
237 let h160 = primitive_types::H160::decode(input)?;
238 Ok(Value::Hex(Hex::from_str(&format!("{h160:?}"))?))
239 }
240}
241
242impl CustomTypeEncoder for H160 {
243 fn encode_value(&self, value: &Value) -> Result<Vec<u8>> {
244 let h160 = match value {
245 Value::Literal(literal) => {
246 primitive_types::H160::from_str(literal).map_err(|e| {
247 anyhow::anyhow!("Error parsing H160 from literal `{literal}`: {e}")
248 })?
249 }
250 Value::String(string) => {
251 assert_not_shortened_hex(string);
252 primitive_types::H160::from_str(string).map_err(|e| {
253 anyhow::anyhow!("Error parsing H160 from string '{string}': {e}")
254 })?
255 }
256 Value::Hex(hex) => primitive_types::H160::from_slice(hex.bytes()),
257 _ => {
258 return Err(anyhow::anyhow!(
259 "Expected a string, literal, or hex for an H160"
260 ))
261 }
262 };
263 Ok(h160.encode())
264 }
265}
266
267#[derive(Clone)]
270pub struct U256;
271
272impl CustomTypeDecoder for U256 {
273 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
274 let u256 = primitive_types::U256::decode(input)?;
275 Ok(Value::Literal(format!("{u256}")))
276 }
277}
278
279impl CustomTypeEncoder for U256 {
280 fn encode_value(&self, value: &Value) -> Result<Vec<u8>> {
281 let u256 = match value {
282 Value::Literal(literal) => {
283 primitive_types::U256::from_str(literal).map_err(|e| {
284 anyhow::anyhow!("Error parsing U256 from literal `{literal}`: {e}")
285 })?
286 }
287 Value::String(string) => {
288 primitive_types::U256::from_str(string).map_err(|e| {
289 anyhow::anyhow!("Error parsing U256 from string '{string}': {e}")
290 })?
291 }
292 Value::UInt(uint128) => {
293 let u_128 = U128::from(*uint128);
294 primitive_types::U256::from(u_128)
295 }
296 Value::Hex(hex) => primitive_types::U256::from_little_endian(hex.bytes()),
298 _ => {
299 return Err(anyhow::anyhow!(
300 "Expected a string, hex, uint, or literal for a U256"
301 ))
302 }
303 };
304 let ret = u256.encode();
305 Ok(ret)
306 }
307}
308
309#[derive(Clone)]
312pub struct H256;
313
314impl CustomTypeDecoder for H256 {
315 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
316 let h256 = primitive_types::H256::decode(input)?;
317 Ok(Value::Hex(Hex::from_str(&format!("{h256:?}"))?))
318 }
319}
320
321impl CustomTypeEncoder for H256 {
322 fn encode_value(&self, value: &Value) -> Result<Vec<u8>> {
323 let h256 = match value {
324 Value::Literal(literal) => {
325 primitive_types::H256::from_str(literal).map_err(|e| {
326 anyhow::anyhow!("Error parsing H256 from literal `{literal}`: {e}")
327 })?
328 }
329 Value::String(string) => {
330 primitive_types::H256::from_str(string).map_err(|e| {
331 anyhow::anyhow!("Error parsing H256 from string '{string}': {e}")
332 })?
333 }
334 Value::Hex(hex) => primitive_types::H256::from_slice(hex.bytes()),
335 _ => {
336 return Err(anyhow::anyhow!(
337 "Expected a string, hex, uint, or literal for a H256"
338 ))
339 }
340 };
341 Ok(h256.encode())
342 }
343}
344
345