1#[cfg(feature = "std")]
21use crate::host::*;
22#[cfg(not(feature = "std"))]
23use crate::wasm::*;
24use crate::{
25 pass_by::{Codec, Enum, Inner, PassBy, PassByInner},
26 util::{pack_ptr_and_len, unpack_ptr_and_len},
27 Pointer, RIType,
28};
29
30#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
31use static_assertions::assert_eq_size;
32
33#[cfg(feature = "std")]
34use sp_wasm_interface::{FunctionContext, Result};
35
36use codec::{Decode, Encode};
37
38use sp_std::{any::TypeId, mem, vec::Vec};
39
40#[cfg(feature = "std")]
41use sp_std::borrow::Cow;
42
43#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
45assert_eq_size!(usize, u32);
46#[cfg(all(not(feature = "std"), not(feature = "disable_target_static_assertions")))]
47assert_eq_size!(*const u8, u32);
48
49macro_rules! impl_traits_for_primitives {
51 (
52 $(
53 $rty:ty, $fty:ty,
54 )*
55 ) => {
56 $(
57 impl RIType for $rty {
59 type FFIType = $fty;
60 }
61
62 #[cfg(not(feature = "std"))]
63 impl IntoFFIValue for $rty {
64 type Owned = ();
65
66 fn into_ffi_value(&self) -> WrappedFFIValue<$fty> {
67 (*self as $fty).into()
68 }
69 }
70
71 #[cfg(not(feature = "std"))]
72 impl FromFFIValue for $rty {
73 fn from_ffi_value(arg: $fty) -> $rty {
74 arg as $rty
75 }
76 }
77
78 #[cfg(feature = "std")]
79 impl FromFFIValue for $rty {
80 type SelfInstance = $rty;
81
82 fn from_ffi_value(_: &mut dyn FunctionContext, arg: $fty) -> Result<$rty> {
83 Ok(arg as $rty)
84 }
85 }
86
87 #[cfg(feature = "std")]
88 impl IntoFFIValue for $rty {
89 fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<$fty> {
90 Ok(self as $fty)
91 }
92 }
93 )*
94 }
95}
96
97impl_traits_for_primitives! {
98 u8, u32,
99 u16, u32,
100 u32, u32,
101 u64, u64,
102 i8, i32,
103 i16, i32,
104 i32, i32,
105 i64, i64,
106}
107
108impl RIType for bool {
113 type FFIType = u32;
114}
115
116#[cfg(not(feature = "std"))]
117impl IntoFFIValue for bool {
118 type Owned = ();
119
120 fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
121 if *self { 1 } else { 0 }.into()
122 }
123}
124
125#[cfg(not(feature = "std"))]
126impl FromFFIValue for bool {
127 fn from_ffi_value(arg: u32) -> bool {
128 arg == 1
129 }
130}
131
132#[cfg(feature = "std")]
133impl FromFFIValue for bool {
134 type SelfInstance = bool;
135
136 fn from_ffi_value(_: &mut dyn FunctionContext, arg: u32) -> Result<bool> {
137 Ok(arg == 1)
138 }
139}
140
141#[cfg(feature = "std")]
142impl IntoFFIValue for bool {
143 fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<u32> {
144 Ok(if self { 1 } else { 0 })
145 }
146}
147
148impl<T> RIType for Vec<T> {
155 type FFIType = u64;
156}
157
158#[cfg(feature = "std")]
159impl<T: 'static + Encode> IntoFFIValue for Vec<T> {
160 fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u64> {
161 let vec: Cow<'_, [u8]> = if TypeId::of::<T>() == TypeId::of::<u8>() {
162 unsafe { Cow::Borrowed(mem::transmute(&self[..])) }
163 } else {
164 Cow::Owned(self.encode())
165 };
166
167 let ptr = context.allocate_memory(vec.as_ref().len() as u32)?;
168 context.write_memory(ptr, &vec)?;
169
170 Ok(pack_ptr_and_len(ptr.into(), vec.len() as u32))
171 }
172}
173
174#[cfg(feature = "std")]
175impl<T: 'static + Decode> FromFFIValue for Vec<T> {
176 type SelfInstance = Vec<T>;
177
178 fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<Vec<T>> {
179 <[T] as FromFFIValue>::from_ffi_value(context, arg)
180 }
181}
182
183#[cfg(not(feature = "std"))]
184impl<T: 'static + Encode> IntoFFIValue for Vec<T> {
185 type Owned = Vec<u8>;
186
187 fn into_ffi_value(&self) -> WrappedFFIValue<u64, Vec<u8>> {
188 self[..].into_ffi_value()
189 }
190}
191
192#[cfg(not(feature = "std"))]
193impl<T: 'static + Decode> FromFFIValue for Vec<T> {
194 fn from_ffi_value(arg: u64) -> Vec<T> {
195 let (ptr, len) = unpack_ptr_and_len(arg);
196 let len = len as usize;
197
198 if len == 0 {
199 return Vec::new()
200 }
201
202 let data = unsafe { Vec::from_raw_parts(ptr as *mut u8, len, len) };
203
204 if TypeId::of::<T>() == TypeId::of::<u8>() {
205 unsafe { mem::transmute(data) }
206 } else {
207 Self::decode(&mut &data[..]).expect("Host to wasm values are encoded correctly; qed")
208 }
209 }
210}
211
212impl<T> RIType for [T] {
219 type FFIType = u64;
220}
221
222#[cfg(feature = "std")]
223impl<T: 'static + Decode> FromFFIValue for [T] {
224 type SelfInstance = Vec<T>;
225
226 fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<Vec<T>> {
227 let (ptr, len) = unpack_ptr_and_len(arg);
228
229 let vec = context.read_memory(Pointer::new(ptr), len)?;
230
231 if TypeId::of::<T>() == TypeId::of::<u8>() {
232 Ok(unsafe { mem::transmute(vec) })
233 } else {
234 Ok(Vec::<T>::decode(&mut &vec[..])
235 .expect("Wasm to host values are encoded correctly; qed"))
236 }
237 }
238}
239
240#[cfg(feature = "std")]
241impl IntoPreallocatedFFIValue for [u8] {
242 type SelfInstance = Vec<u8>;
243
244 fn into_preallocated_ffi_value(
245 self_instance: Self::SelfInstance,
246 context: &mut dyn FunctionContext,
247 allocated: u64,
248 ) -> Result<()> {
249 let (ptr, len) = unpack_ptr_and_len(allocated);
250
251 if (len as usize) < self_instance.len() {
252 Err(format!(
253 "Preallocated buffer is not big enough (given {} vs needed {})!",
254 len,
255 self_instance.len()
256 ))
257 } else {
258 context.write_memory(Pointer::new(ptr), &self_instance)
259 }
260 }
261}
262
263#[cfg(not(feature = "std"))]
264impl<T: 'static + Encode> IntoFFIValue for [T] {
265 type Owned = Vec<u8>;
266
267 fn into_ffi_value(&self) -> WrappedFFIValue<u64, Vec<u8>> {
268 if TypeId::of::<T>() == TypeId::of::<u8>() {
269 let slice = unsafe { mem::transmute::<&[T], &[u8]>(self) };
270 pack_ptr_and_len(slice.as_ptr() as u32, slice.len() as u32).into()
271 } else {
272 let data = self.encode();
273 let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32);
274 (ffi_value, data).into()
275 }
276 }
277}
278
279impl<const N: usize> RIType for [u8; N] {
283 type FFIType = u32;
284}
285
286#[cfg(not(feature = "std"))]
287impl<const N: usize> IntoFFIValue for [u8; N] {
288 type Owned = ();
289
290 fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
291 (self.as_ptr() as u32).into()
292 }
293}
294
295#[cfg(not(feature = "std"))]
296impl<const N: usize> FromFFIValue for [u8; N] {
297 fn from_ffi_value(arg: u32) -> [u8; N] {
298 let mut res = [0u8; N];
299 let data = unsafe { Vec::from_raw_parts(arg as *mut u8, N, N) };
300
301 res.copy_from_slice(&data);
302
303 res
304 }
305}
306
307#[cfg(feature = "std")]
308impl<const N: usize> FromFFIValue for [u8; N] {
309 type SelfInstance = [u8; N];
310
311 fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<[u8; N]> {
312 let mut res = [0u8; N];
313 context.read_memory_into(Pointer::new(arg), &mut res)?;
314 Ok(res)
315 }
316}
317
318#[cfg(feature = "std")]
319impl<const N: usize> IntoFFIValue for [u8; N] {
320 fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u32> {
321 let addr = context.allocate_memory(N as u32)?;
322 context.write_memory(addr, &self)?;
323 Ok(addr.into())
324 }
325}
326
327#[cfg(feature = "std")]
328impl<const N: usize> IntoPreallocatedFFIValue for [u8; N] {
329 type SelfInstance = [u8; N];
330
331 fn into_preallocated_ffi_value(
332 self_instance: Self::SelfInstance,
333 context: &mut dyn FunctionContext,
334 allocated: u32,
335 ) -> Result<()> {
336 context.write_memory(Pointer::new(allocated), &self_instance)
337 }
338}
339
340impl<T: codec::Codec, E: codec::Codec> PassBy for sp_std::result::Result<T, E> {
341 type PassBy = Codec<Self>;
342}
343
344impl<T: codec::Codec> PassBy for Option<T> {
345 type PassBy = Codec<Self>;
346}
347
348#[impl_trait_for_tuples::impl_for_tuples(30)]
349#[tuple_types_no_default_trait_bound]
350impl PassBy for Tuple
351where
352 Self: codec::Codec,
353{
354 type PassBy = Codec<Self>;
355}
356
357macro_rules! for_primitive_types {
359 { $( $hash:ident $n:expr ),* $(,)? } => {
360 $(
361 impl PassBy for primitive_types::$hash {
362 type PassBy = Inner<Self, [u8; $n]>;
363 }
364
365 impl PassByInner for primitive_types::$hash {
366 type Inner = [u8; $n];
367
368 fn inner(&self) -> &Self::Inner {
369 &self.0
370 }
371
372 fn into_inner(self) -> Self::Inner {
373 self.0
374 }
375
376 fn from_inner(inner: Self::Inner) -> Self {
377 Self(inner)
378 }
379 }
380 )*
381 }
382}
383
384for_primitive_types! {
385 H160 20,
386 H256 32,
387 H512 64,
388}
389
390impl RIType for str {
396 type FFIType = u64;
397}
398
399#[cfg(feature = "std")]
400impl FromFFIValue for str {
401 type SelfInstance = String;
402
403 fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<String> {
404 let (ptr, len) = unpack_ptr_and_len(arg);
405
406 let vec = context.read_memory(Pointer::new(ptr), len)?;
407
408 String::from_utf8(vec).map_err(|_| "Invalid utf8 data provided".into())
410 }
411}
412
413#[cfg(not(feature = "std"))]
414impl IntoFFIValue for str {
415 type Owned = ();
416
417 fn into_ffi_value(&self) -> WrappedFFIValue<u64, ()> {
418 let bytes = self.as_bytes();
419 pack_ptr_and_len(bytes.as_ptr() as u32, bytes.len() as u32).into()
420 }
421}
422
423#[cfg(feature = "std")]
424impl<T: sp_wasm_interface::PointerType> RIType for Pointer<T> {
425 type FFIType = u32;
426}
427
428#[cfg(not(feature = "std"))]
430impl<T> RIType for Pointer<T> {
431 type FFIType = u32;
432}
433
434#[cfg(not(feature = "std"))]
435impl<T> IntoFFIValue for Pointer<T> {
436 type Owned = ();
437
438 fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
439 (*self as u32).into()
440 }
441}
442
443#[cfg(not(feature = "std"))]
444impl<T> FromFFIValue for Pointer<T> {
445 fn from_ffi_value(arg: u32) -> Self {
446 arg as _
447 }
448}
449
450#[cfg(feature = "std")]
451impl<T: sp_wasm_interface::PointerType> FromFFIValue for Pointer<T> {
452 type SelfInstance = Self;
453
454 fn from_ffi_value(_: &mut dyn FunctionContext, arg: u32) -> Result<Self> {
455 Ok(Pointer::new(arg))
456 }
457}
458
459#[cfg(feature = "std")]
460impl<T: sp_wasm_interface::PointerType> IntoFFIValue for Pointer<T> {
461 fn into_ffi_value(self, _: &mut dyn FunctionContext) -> Result<u32> {
462 Ok(self.into())
463 }
464}
465
466macro_rules! for_u128_i128 {
468 ($type:ty) => {
469 impl RIType for $type {
473 type FFIType = u32;
474 }
475
476 #[cfg(not(feature = "std"))]
477 impl IntoFFIValue for $type {
478 type Owned = ();
479
480 fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
481 unsafe { (mem::transmute::<&Self, *const u8>(self) as u32).into() }
482 }
483 }
484
485 #[cfg(not(feature = "std"))]
486 impl FromFFIValue for $type {
487 fn from_ffi_value(arg: u32) -> $type {
488 <$type>::from_le_bytes(<[u8; mem::size_of::<$type>()]>::from_ffi_value(arg))
489 }
490 }
491
492 #[cfg(feature = "std")]
493 impl FromFFIValue for $type {
494 type SelfInstance = $type;
495
496 fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<$type> {
497 let mut res = [0u8; mem::size_of::<$type>()];
498 context.read_memory_into(Pointer::new(arg), &mut res)?;
499 Ok(<$type>::from_le_bytes(res))
500 }
501 }
502
503 #[cfg(feature = "std")]
504 impl IntoFFIValue for $type {
505 fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u32> {
506 let addr = context.allocate_memory(mem::size_of::<$type>() as u32)?;
507 context.write_memory(addr, &self.to_le_bytes())?;
508 Ok(addr.into())
509 }
510 }
511 };
512}
513
514for_u128_i128!(u128);
515for_u128_i128!(i128);
516
517impl PassBy for sp_wasm_interface::ValueType {
518 type PassBy = Enum<sp_wasm_interface::ValueType>;
519}
520
521impl PassBy for sp_wasm_interface::Value {
522 type PassBy = Codec<sp_wasm_interface::Value>;
523}
524
525impl PassBy for sp_storage::TrackedStorageKey {
526 type PassBy = Codec<Self>;
527}
528
529impl PassBy for sp_storage::StateVersion {
530 type PassBy = Enum<Self>;
531}
532
533impl PassBy for sp_externalities::MultiRemovalResults {
534 type PassBy = Codec<Self>;
535}