contract_transcode/
env_types.rs1use crate::{
18 AccountId32,
19 Hex,
20 Value,
21};
22use anyhow::{
23 Context,
24 Result,
25};
26use scale::{
27 Decode,
28 Encode,
29 Output,
30};
31use scale_info::{
32 form::PortableForm,
33 IntoPortable,
34 Path,
35 TypeInfo,
36};
37use std::{
38 boxed::Box,
39 collections::HashMap,
40 convert::TryFrom,
41 str::FromStr,
42};
43
44#[derive(Default)]
46pub struct EnvTypesTranscoder {
47 encoders: HashMap<u32, Box<dyn CustomTypeEncoder>>,
48 decoders: HashMap<u32, Box<dyn CustomTypeDecoder>>,
49}
50
51impl EnvTypesTranscoder {
52 pub fn new(
54 encoders: HashMap<u32, Box<dyn CustomTypeEncoder>>,
55 decoders: HashMap<u32, Box<dyn CustomTypeDecoder>>,
56 ) -> Self {
57 Self { encoders, decoders }
58 }
59
60 pub fn try_encode<O>(
67 &self,
68 type_id: u32,
69 value: &Value,
70 output: &mut O,
71 ) -> Result<bool>
72 where
73 O: Output,
74 {
75 match self.encoders.get(&type_id) {
76 Some(encoder) => {
77 tracing::debug!("Encoding type {:?} with custom encoder", type_id);
78 let encoded_env_type = encoder
79 .encode_value(value)
80 .context("Error encoding custom type")?;
81 output.write(&encoded_env_type);
82 Ok(true)
83 }
84 None => Ok(false),
85 }
86 }
87
88 pub fn try_decode(&self, type_id: u32, input: &mut &[u8]) -> Result<Option<Value>> {
96 match self.decoders.get(&type_id) {
97 Some(decoder) => {
98 tracing::debug!("Decoding type {:?} with custom decoder", type_id);
99 let decoded = decoder.decode_value(input)?;
100 Ok(Some(decoded))
101 }
102 None => {
103 tracing::debug!("No custom decoder found for type {:?}", type_id);
104 Ok(None)
105 }
106 }
107 }
108}
109
110#[derive(Clone, Debug, Eq, PartialEq, Hash)]
111pub struct PathKey(Vec<String>);
112
113impl PathKey {
114 pub fn from_type<T>() -> Self
115 where
116 T: TypeInfo,
117 {
118 let type_info = T::type_info();
119 let path = type_info.path.into_portable(&mut Default::default());
120 PathKey::from(&path)
121 }
122}
123
124impl From<&Path<PortableForm>> for PathKey {
125 fn from(path: &Path<PortableForm>) -> Self {
126 PathKey(path.segments.to_vec())
127 }
128}
129
130pub type TypesByPath = HashMap<PathKey, u32>;
131
132pub trait CustomTypeEncoder: Send + Sync {
135 fn encode_value(&self, value: &Value) -> Result<Vec<u8>>;
136}
137
138pub trait CustomTypeDecoder: Send + Sync {
141 fn decode_value(&self, input: &mut &[u8]) -> Result<Value>;
142}
143
144#[derive(Clone)]
149pub struct AccountId;
150
151impl CustomTypeEncoder for AccountId {
152 fn encode_value(&self, value: &Value) -> Result<Vec<u8>> {
153 let account_id = match value {
154 Value::Literal(literal) => {
155 AccountId32::from_str(literal).map_err(|e| {
156 anyhow::anyhow!(
157 "Error parsing AccountId from literal `{}`: {}",
158 literal,
159 e
160 )
161 })?
162 }
163 Value::String(string) => {
164 AccountId32::from_str(string).map_err(|e| {
165 anyhow::anyhow!(
166 "Error parsing AccountId from string '{}': {}",
167 string,
168 e
169 )
170 })?
171 }
172 Value::Hex(hex) => {
173 AccountId32::try_from(hex.bytes()).map_err(|_| {
174 anyhow::anyhow!(
175 "Error converting hex bytes `{:?}` to AccountId",
176 hex.bytes()
177 )
178 })?
179 }
180 _ => {
181 return Err(anyhow::anyhow!(
182 "Expected a string or a literal for an AccountId"
183 ))
184 }
185 };
186 Ok(account_id.encode())
187 }
188}
189
190impl CustomTypeDecoder for AccountId {
191 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
192 let account_id = AccountId32::decode(input)?;
193 Ok(Value::Literal(account_id.to_ss58check()))
194 }
195}
196
197pub struct Hash;
200
201impl CustomTypeDecoder for Hash {
202 fn decode_value(&self, input: &mut &[u8]) -> Result<Value> {
203 let hash = primitive_types::H256::decode(input)?;
204 Ok(Value::Hex(Hex::from_str(&format!("{hash:?}"))?))
205 }
206}