pub fn unpack_ptr_and_len(val: u64) -> (u32, u32)
Expand description

Unpacks an u64 into the pointer and length.

Runtime API functions return a 64-bit value which encodes a pointer in the least-significant 32-bits and a length in the most-significant 32 bits. This interprets the returned value as a pointer, length tuple.

Examples found in repository?
src/pass_by.rs (line 230)
229
230
231
232
233
	fn from_ffi_value(context: &mut dyn FunctionContext, arg: Self::FFIType) -> Result<T> {
		let (ptr, len) = unpack_ptr_and_len(arg);
		let vec = context.read_memory(Pointer::new(ptr), len)?;
		T::decode(&mut &vec[..]).map_err(|e| format!("Could not decode value from wasm: {}", e))
	}
More examples
Hide additional examples
src/impls.rs (line 227)
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<Vec<T>> {
		let (ptr, len) = unpack_ptr_and_len(arg);

		let vec = context.read_memory(Pointer::new(ptr), len)?;

		if TypeId::of::<T>() == TypeId::of::<u8>() {
			Ok(unsafe { mem::transmute(vec) })
		} else {
			Ok(Vec::<T>::decode(&mut &vec[..])
				.expect("Wasm to host values are encoded correctly; qed"))
		}
	}
}

#[cfg(feature = "std")]
impl IntoPreallocatedFFIValue for [u8] {
	type SelfInstance = Vec<u8>;

	fn into_preallocated_ffi_value(
		self_instance: Self::SelfInstance,
		context: &mut dyn FunctionContext,
		allocated: u64,
	) -> Result<()> {
		let (ptr, len) = unpack_ptr_and_len(allocated);

		if (len as usize) < self_instance.len() {
			Err(format!(
				"Preallocated buffer is not big enough (given {} vs needed {})!",
				len,
				self_instance.len()
			))
		} else {
			context.write_memory(Pointer::new(ptr), &self_instance)
		}
	}
}

#[cfg(not(feature = "std"))]
impl<T: 'static + Encode> IntoFFIValue for [T] {
	type Owned = Vec<u8>;

	fn into_ffi_value(&self) -> WrappedFFIValue<u64, Vec<u8>> {
		if TypeId::of::<T>() == TypeId::of::<u8>() {
			let slice = unsafe { mem::transmute::<&[T], &[u8]>(self) };
			pack_ptr_and_len(slice.as_ptr() as u32, slice.len() as u32).into()
		} else {
			let data = self.encode();
			let ffi_value = pack_ptr_and_len(data.as_ptr() as u32, data.len() as u32);
			(ffi_value, data).into()
		}
	}
}

/// Implement the traits for the `[u8; N]` arrays, where `N` is the input to this macro.
macro_rules! impl_traits_for_arrays {
	(
		$(
			$n:expr
		),*
		$(,)?
	) => {
		$(
			/// The type is passed as `u32`.
			///
			/// The `u32` is the pointer to the array.
			impl RIType for [u8; $n] {
				type FFIType = u32;
			}

			#[cfg(not(feature = "std"))]
			impl IntoFFIValue for [u8; $n] {
				type Owned = ();

				fn into_ffi_value(&self) -> WrappedFFIValue<u32> {
					(self.as_ptr() as u32).into()
				}
			}

			#[cfg(not(feature = "std"))]
			impl FromFFIValue for [u8; $n] {
				fn from_ffi_value(arg: u32) -> [u8; $n] {
					let mut res = [0u8; $n];
					let data = unsafe { Vec::from_raw_parts(arg as *mut u8, $n, $n) };

					res.copy_from_slice(&data);

					res
				}
			}

			#[cfg(feature = "std")]
			impl FromFFIValue for [u8; $n] {
				type SelfInstance = [u8; $n];

				fn from_ffi_value(context: &mut dyn FunctionContext, arg: u32) -> Result<[u8; $n]> {
					let mut res = [0u8; $n];
					context.read_memory_into(Pointer::new(arg), &mut res)?;
					Ok(res)
				}
			}

			#[cfg(feature = "std")]
			impl IntoFFIValue for [u8; $n] {
				fn into_ffi_value(self, context: &mut dyn FunctionContext) -> Result<u32> {
					let addr = context.allocate_memory($n)?;
					context.write_memory(addr, &self)?;
					Ok(addr.into())
				}
			}

			#[cfg(feature = "std")]
			impl IntoPreallocatedFFIValue for [u8; $n] {
				type SelfInstance = [u8; $n];

				fn into_preallocated_ffi_value(
					self_instance: Self::SelfInstance,
					context: &mut dyn FunctionContext,
					allocated: u32,
				) -> Result<()> {
					context.write_memory(Pointer::new(allocated), &self_instance)
				}
			}
		)*
	}
}

impl_traits_for_arrays! {
	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,
	27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50,
	51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
	75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
}

impl<T: codec::Codec, E: codec::Codec> PassBy for sp_std::result::Result<T, E> {
	type PassBy = Codec<Self>;
}

impl<T: codec::Codec> PassBy for Option<T> {
	type PassBy = Codec<Self>;
}

#[impl_trait_for_tuples::impl_for_tuples(30)]
#[tuple_types_no_default_trait_bound]
impl PassBy for Tuple
where
	Self: codec::Codec,
{
	type PassBy = Codec<Self>;
}

/// Implement `PassBy` with `Inner` for the given fixed sized hash types.
macro_rules! for_primitive_types {
	{ $( $hash:ident $n:expr ),* $(,)? } => {
		$(
			impl PassBy for primitive_types::$hash {
				type PassBy = Inner<Self, [u8; $n]>;
			}

			impl PassByInner for primitive_types::$hash {
				type Inner = [u8; $n];

				fn inner(&self) -> &Self::Inner {
					&self.0
				}

				fn into_inner(self) -> Self::Inner {
					self.0
				}

				fn from_inner(inner: Self::Inner) -> Self {
					Self(inner)
				}
			}
		)*
	}
}

for_primitive_types! {
	H160 20,
	H256 32,
	H512 64,
}

/// The type is passed as `u64`.
///
/// The `u64` value is build by `length 32bit << 32 | pointer 32bit`
///
/// The length and the pointer are taken directly from `Self`.
impl RIType for str {
	type FFIType = u64;
}

#[cfg(feature = "std")]
impl FromFFIValue for str {
	type SelfInstance = String;

	fn from_ffi_value(context: &mut dyn FunctionContext, arg: u64) -> Result<String> {
		let (ptr, len) = unpack_ptr_and_len(arg);

		let vec = context.read_memory(Pointer::new(ptr), len)?;

		// The data is valid utf8, as it is stored as `&str` in wasm.
		String::from_utf8(vec).map_err(|_| "Invalid utf8 data provided".into())
	}