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