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