diff --git a/ffi/derive/src/convert.rs b/ffi/derive/src/convert.rs index 0ca6abc1c9e..d442f7b8038 100644 --- a/ffi/derive/src/convert.rs +++ b/ffi/derive/src/convert.rs @@ -86,7 +86,8 @@ fn variant_discriminants(enum_: &syn::DataEnum) -> Vec { } fn derive_try_from_repr_c_for_opaque_item_wrapper(name: &Ident) -> TokenStream2 { - let opaque_item_slice_try_from_repr_c_derive = derive_try_from_repr_c_for_opaque_item_slice(name); + let opaque_item_slice_try_from_repr_c_derive = + derive_try_from_repr_c_for_opaque_item_slice(name); let opaque_item_vec_try_from_repr_c_derive = derive_try_from_repr_c_for_opaque_item_vec(name); quote! { @@ -146,7 +147,8 @@ fn derive_try_from_repr_c_for_opaque_item_wrapper(name: &Ident) -> TokenStream2 } fn derive_try_from_repr_c_for_opaque_item(name: &Ident) -> TokenStream2 { - let opaque_item_slice_try_from_repr_c_derive = derive_try_from_repr_c_for_opaque_item_slice(name); + let opaque_item_slice_try_from_repr_c_derive = + derive_try_from_repr_c_for_opaque_item_slice(name); let opaque_item_vec_try_from_repr_c_derive = derive_try_from_repr_c_for_opaque_item_vec(name); quote! { @@ -460,7 +462,7 @@ fn derive_into_ffi_for_fieldless_enum(enum_name: &Ident, repr: &[syn::NestedMeta quote! { impl iroha_ffi::IntoFfi for #enum_name { type Target = <#ffi_type as iroha_ffi::IntoFfi>::Target; - + fn into_ffi(self) -> Self::Target { (self as #ffi_type).into_ffi() } diff --git a/ffi/src/handle.rs b/ffi/src/handle.rs index ce0779561f5..4a262eec450 100644 --- a/ffi/src/handle.rs +++ b/ffi/src/handle.rs @@ -113,6 +113,7 @@ macro_rules! def_ffi_fn { handle_id: $crate::handle::Id, left_handle_ptr: *const core::ffi::c_void, right_handle_ptr: *const core::ffi::c_void, + // Pointer to FFI-safe representation of `bool` (u8 or u32 if `wasm` feature is active) output_ptr: *mut ::Target, ) -> $crate::FfiReturn { $crate::def_ffi_fn!(@catch_unwind { @@ -152,6 +153,7 @@ macro_rules! def_ffi_fn { handle_id: $crate::handle::Id, left_handle_ptr: *const core::ffi::c_void, right_handle_ptr: *const core::ffi::c_void, + // Pointer to FFI-safe representation of `Ordering` (i8 or i32 if `wasm` feature is active) output_ptr: *mut ::Target, ) -> $crate::FfiReturn { $crate::def_ffi_fn!(@catch_unwind { diff --git a/ffi/src/lib.rs b/ffi/src/lib.rs index ba5c47dc5dc..d13a7f7a2f6 100644 --- a/ffi/src/lib.rs +++ b/ffi/src/lib.rs @@ -109,6 +109,8 @@ pub trait Output: Sized { #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(i8)] pub enum FfiReturn { + /// The input argument provided to FFI function can't be converted into inner rust representation. + ConversionFailed = -7, /// The input argument provided to FFI function has a trap representation. TrapRepresentation = -6, /// FFI function execution panicked. diff --git a/ffi/src/owned.rs b/ffi/src/owned.rs index 0caa2262ee0..2d939bd6b1c 100644 --- a/ffi/src/owned.rs +++ b/ffi/src/owned.rs @@ -5,7 +5,7 @@ use alloc::{borrow::ToOwned, boxed::Box, string::String, vec::Vec}; use crate::{ slice::{OutBoxedSlice, SliceRef}, - AsReprCRef, FfiReturn, IntoFfi, Output, ReprC, TryFromReprC, Result + AsReprCRef, FfiReturn, IntoFfi, Output, ReprC, Result, TryFromReprC, }; /// Trait that facilitates the implementation of [`IntoFfi`] for vectors of foreign types @@ -31,9 +31,9 @@ pub trait TryFromReprCVec<'slice>: Sized { /// /// # Errors /// - /// * [`FfiResult::ArgIsNull`] - given pointer is null - /// * [`FfiResult::UnknownHandle`] - given id doesn't identify any known handle - /// * [`FfiResult::TrapRepresentation`] - given value contains trap representation + /// * [`FfiReturn::ArgIsNull`] - given pointer is null + /// * [`FfiReturn::UnknownHandle`] - given id doesn't identify any known handle + /// * [`FfiReturn::TrapRepresentation`] - given value contains trap representation /// /// # Safety /// @@ -192,10 +192,7 @@ impl<'itm> TryFromReprC<'itm> for String { type Source = as TryFromReprC<'itm>>::Source; type Store = (); - unsafe fn try_from_repr_c( - source: Self::Source, - _: &mut Self::Store, - ) -> Result { + unsafe fn try_from_repr_c(source: Self::Source, _: &mut Self::Store) -> Result { String::from_utf8(source.into_rust().ok_or(FfiReturn::ArgIsNull)?.to_owned()) .map_err(|_e| FfiReturn::Utf8Error) } @@ -204,10 +201,7 @@ impl<'itm> TryFromReprC<'itm> for &'itm str { type Source = <&'itm [u8] as TryFromReprC<'itm>>::Source; type Store = (); - unsafe fn try_from_repr_c( - source: Self::Source, - _: &mut Self::Store, - ) -> Result { + unsafe fn try_from_repr_c(source: Self::Source, _: &mut Self::Store) -> Result { core::str::from_utf8(source.into_rust().ok_or(FfiReturn::ArgIsNull)?) .map_err(|_e| FfiReturn::Utf8Error) } diff --git a/ffi/src/primitives.rs b/ffi/src/primitives.rs index 7cdd34b03e7..a1954315df1 100644 --- a/ffi/src/primitives.rs +++ b/ffi/src/primitives.rs @@ -217,7 +217,7 @@ macro_rules! primitive_impls { type Store = (); unsafe fn try_from_repr_c(source: Self::Source, _: &mut Self::Store) -> Result { - source.try_into().map_err(|_| FfiReturn::TrapRepresentation) + source.try_into().map_err(|_| FfiReturn::ConversionFailed) } } diff --git a/ffi/tests/ffi_export.rs b/ffi/tests/ffi_export.rs index 52403c3764d..4e4a70908a3 100644 --- a/ffi/tests/ffi_export.rs +++ b/ffi/tests/ffi_export.rs @@ -89,6 +89,12 @@ impl FfiStruct { } } +#[ffi_export] +/// Return byte +pub fn simple(byte: u8) -> u8 { + byte +} + fn get_new_struct() -> FfiStruct { let name = Name(String::from("X")); @@ -296,3 +302,17 @@ fn return_result() { assert_eq!(42, output.assume_init()); } } + +#[cfg(feature = "wasm")] +#[test] +fn conversion_failed() { + let byte: u32 = u32::MAX; + let mut output = MaybeUninit::new(0); + + unsafe { + assert_eq!( + FfiReturn::ConversionFailed, + __simple(byte, output.as_mut_ptr()) + ) + } +} diff --git a/ffi/tests/gen_shared_fns.rs b/ffi/tests/gen_shared_fns.rs index 17b3d41c3c5..bbdfe4c0592 100644 --- a/ffi/tests/gen_shared_fns.rs +++ b/ffi/tests/gen_shared_fns.rs @@ -72,7 +72,6 @@ fn gen_shared_fns() { TryFromReprC::try_from_repr_c(is_equal.assume_init(), &mut ()).unwrap(); assert!(is_equal); - // TODO: Fix let mut ordering = MaybeUninit::new(1); __ord( FfiStruct1::ID,