From f5dd552036cf28b7d7975c3bc37b0d8308a2500d Mon Sep 17 00:00:00 2001 From: Adrian Taylor Date: Mon, 13 Apr 2020 16:50:14 -0700 Subject: [PATCH 1/2] Adding &[u8] support. This change adds specifically, support for &[u8] with a corresponding rust::Slice type. No other types of slice are permitted. The rationale is that it may be common to pass binary data back and forth across the FFI boundary, so it's more urgent to get this in place sooner. Broader support for other slices can wait for the future. But, both C++ and Rust-side bindings should allow the existing support to be broadened to other Slice types in future without code changes. A few specific notes: * The name "rust::Slice" might be better as "rust::SliceRef" but I'm following the precedent of "rust::Str". * It would be good to add constructors from std::span but as that's a C++20 feature, that may have to wait until C++ feature detection is resolved. * Internally, this follows the pattern of &str, where the parser will initially recognize this as Type::Ref (of Type::Slice) but then will replace that with Type::SliceRefU8. Type::Slice should not persist through later stages. As we later come to support other types of slice, we would probably want to remove Type::SliceRefU8. --- README.md | 2 +- gen/write.rs | 22 +++++++++++++++++----- include/cxx.h | 37 +++++++++++++++++++++++++++++++++++++ macro/src/expand.rs | 6 ++++++ src/lib.rs | 2 ++ src/rust_sliceu8.rs | 26 ++++++++++++++++++++++++++ syntax/check.rs | 2 ++ syntax/impls.rs | 32 +++++++++++++++++++++++++++++++- syntax/mod.rs | 9 ++++++++- syntax/parse.rs | 29 ++++++++++++++++++++++++++--- syntax/tokens.rs | 13 +++++++++++-- syntax/types.rs | 3 ++- tests/ffi/lib.rs | 9 +++++++++ tests/ffi/tests.cc | 16 ++++++++++++++++ tests/ffi/tests.h | 3 +++ tests/test.rs | 1 + 16 files changed, 198 insertions(+), 14 deletions(-) create mode 100644 src/rust_sliceu8.rs diff --git a/README.md b/README.md index 0b3aab317..ad14b574f 100644 --- a/README.md +++ b/README.md @@ -299,6 +299,7 @@ returns of functions. name in Rustname in C++restrictions Stringrust::String &strrust::Str +&[u8]rust::Slice<uint8_t>(no other slice types currently supported) CxxStringstd::stringcannot be passed by value Box<T>rust::Box<T>cannot hold opaque C++ type UniquePtr<T>std::unique_ptr<T>cannot hold opaque Rust type @@ -316,7 +317,6 @@ matter of designing a nice API for each in its non-native language. - diff --git a/gen/write.rs b/gen/write.rs index 4eed1b40a..3f3cf4b65 100644 --- a/gen/write.rs +++ b/gen/write.rs @@ -365,6 +365,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) { match &efn.ret { Some(Type::Ref(_)) => write!(out, "&"), Some(Type::Str(_)) if !indirect_return => write!(out, "::rust::Str::Repr("), + Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, "::rust::Slice::Repr("), _ => {} } write!(out, "{}$(", efn.ident); @@ -395,7 +396,7 @@ fn write_cxx_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) { match &efn.ret { Some(Type::RustBox(_)) => write!(out, ".into_raw()"), Some(Type::UniquePtr(_)) => write!(out, ".release()"), - Some(Type::Str(_)) if !indirect_return => write!(out, ")"), + Some(Type::Str(_)) | Some(Type::SliceRefU8(_)) if !indirect_return => write!(out, ")"), _ => {} } if indirect_return { @@ -566,6 +567,7 @@ fn write_rust_function_shim_impl( } match &arg.ty { Type::Str(_) => write!(out, "::rust::Str::Repr("), + Type::SliceRefU8(_) => write!(out, "::rust::Slice::Repr("), ty if types.needs_indirect_abi(ty) => write!(out, "&"), _ => {} } @@ -573,7 +575,7 @@ fn write_rust_function_shim_impl( match &arg.ty { Type::RustBox(_) => write!(out, ".into_raw()"), Type::UniquePtr(_) => write!(out, ".release()"), - Type::Str(_) => write!(out, ")"), + Type::Str(_) | Type::SliceRefU8(_) => write!(out, ")"), ty if ty != RustString && types.needs_indirect_abi(ty) => write!(out, "$.value"), _ => {} } @@ -637,6 +639,7 @@ fn write_indirect_return_type(out: &mut OutFile, ty: &Type) { write!(out, " *"); } Type::Str(_) => write!(out, "::rust::Str::Repr"), + Type::SliceRefU8(_) => write!(out, "::rust::Slice::Repr"), _ => write_type(out, ty), } } @@ -645,7 +648,7 @@ fn write_indirect_return_type_space(out: &mut OutFile, ty: &Type) { write_indirect_return_type(out, ty); match ty { Type::RustBox(_) | Type::UniquePtr(_) | Type::Ref(_) => {} - Type::Str(_) => write!(out, " "), + Type::Str(_) | Type::SliceRefU8(_) => write!(out, " "), _ => write_space_after_type(out, ty), } } @@ -664,6 +667,7 @@ fn write_extern_return_type_space(out: &mut OutFile, ty: &Option, types: & write!(out, " *"); } Some(Type::Str(_)) => write!(out, "::rust::Str::Repr "), + Some(Type::SliceRefU8(_)) => write!(out, "::rust::Slice::Repr "), Some(ty) if types.needs_indirect_abi(ty) => write!(out, "void "), _ => write_return_type(out, ty), } @@ -676,6 +680,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) { write!(out, "*"); } Type::Str(_) => write!(out, "::rust::Str::Repr "), + Type::SliceRefU8(_) => write!(out, "::rust::Slice::Repr "), _ => write_type_space(out, &arg.ty), } if types.needs_indirect_abi(&arg.ty) { @@ -721,9 +726,16 @@ fn write_type(out: &mut OutFile, ty: &Type) { write_type(out, &r.inner); write!(out, " &"); } + Type::Slice(_) => { + // For now, only U8 slices are supported, which are covered separately below + unreachable!() + } Type::Str(_) => { write!(out, "::rust::Str"); } + Type::SliceRefU8(_) => { + write!(out, "::rust::Slice"); + } Type::Fn(f) => { write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" }); match &f.ret { @@ -750,11 +762,11 @@ fn write_type_space(out: &mut OutFile, ty: &Type) { fn write_space_after_type(out: &mut OutFile, ty: &Type) { match ty { - Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::Fn(_) => { + Type::Ident(_) | Type::RustBox(_) | Type::UniquePtr(_) | Type::Str(_) | Type::SliceRefU8(_) | Type::Fn(_) => { write!(out, " ") } Type::Ref(_) => {} - Type::Void(_) => unreachable!(), + Type::Void(_) | Type::Slice(_) => unreachable!(), } } diff --git a/include/cxx.h b/include/cxx.h index a8239a122..57a6e24b7 100644 --- a/include/cxx.h +++ b/include/cxx.h @@ -16,6 +16,43 @@ inline namespace cxxbridge02 { struct unsafe_bitcopy_t; +#ifndef CXXBRIDGE02_RUST_SLICE +#define CXXBRIDGE02_RUST_SLICE +template +class Slice final { +public: + Slice() noexcept : repr(Repr{reinterpret_cast(this), 0}) {} + Slice(const Slice &) noexcept = default; + + Slice(const T* s, size_t size) : repr(Repr{s, size}) {} + + Slice &operator=(Slice other) noexcept { + this->repr = other.repr; + return *this; + } + + const T *data() const noexcept { return this->repr.ptr; } + size_t size() const noexcept { return this->repr.len; } + size_t length() const noexcept { return this->repr.len; } + + // Repr is PRIVATE; must not be used other than by our generated code. + // + // At present this class is only used for &[u8] slices. + // Not necessarily ABI compatible with &[u8]. Codegen will translate to + // cxx::rust_slice_u8::RustSlice which matches this layout. + struct Repr { + const T *ptr; + size_t len; + }; + Slice(Repr repr_) noexcept : repr(repr_) {} + explicit operator Repr() noexcept { return this->repr; } + +private: + Repr repr; +}; + +#endif // CXXBRIDGE02_RUST_SLICE + #ifndef CXXBRIDGE02_RUST_STRING #define CXXBRIDGE02_RUST_STRING class String final { diff --git a/macro/src/expand.rs b/macro/src/expand.rs index 67c34e5f5..146d21b10 100644 --- a/macro/src/expand.rs +++ b/macro/src/expand.rs @@ -184,6 +184,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types _ => quote!(#var), }, Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)), + Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)), ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()), _ => quote!(#var), } @@ -255,6 +256,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types _ => None, }, Type::Str(_) => Some(quote!(#call.map(|r| r.as_str()))), + Type::SliceRefU8(_) => Some(quote!(#call.map(|r| r.as_slice()))), _ => None, }) } else { @@ -267,6 +269,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types _ => None, }, Type::Str(_) => Some(quote!(#call.as_str())), + Type::SliceRefU8(_) => Some(quote!(#call.as_slice())), _ => None, }) } @@ -375,6 +378,7 @@ fn expand_rust_function_shim_impl( _ => quote!(#ident), }, Type::Str(_) => quote!(#ident.as_str()), + Type::SliceRefU8(_) => quote!(#ident.as_slice()), ty if types.needs_indirect_abi(ty) => quote!(::std::ptr::read(#ident)), _ => quote!(#ident), } @@ -402,6 +406,7 @@ fn expand_rust_function_shim_impl( _ => None, }, Type::Str(_) => Some(quote!(::cxx::private::RustStr::from(#call))), + Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from(#call))), _ => None, }) .unwrap_or(call); @@ -572,6 +577,7 @@ fn expand_extern_type(ty: &Type) -> TokenStream { _ => quote!(#ty), }, Type::Str(_) => quote!(::cxx::private::RustStr), + Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8), _ => quote!(#ty), } } diff --git a/src/lib.rs b/src/lib.rs index f918b298d..60750fbe7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -367,6 +367,7 @@ mod gen; mod opaque; mod paths; mod result; +mod rust_sliceu8; mod rust_str; mod rust_string; mod syntax; @@ -384,6 +385,7 @@ pub mod private { pub use crate::function::FatFunction; pub use crate::opaque::Opaque; pub use crate::result::{r#try, Result}; + pub use crate::rust_sliceu8::RustSliceU8; pub use crate::rust_str::RustStr; pub use crate::rust_string::RustString; pub use crate::unique_ptr::UniquePtrTarget; diff --git a/src/rust_sliceu8.rs b/src/rust_sliceu8.rs new file mode 100644 index 000000000..56d37b3d6 --- /dev/null +++ b/src/rust_sliceu8.rs @@ -0,0 +1,26 @@ +use std::mem; +use std::slice; +use std::ptr::NonNull; + +// Not necessarily ABI compatible with &[u8]. Codegen performs the translation. +#[repr(C)] +#[derive(Copy, Clone)] +pub struct RustSliceU8 { + pub(crate) ptr: NonNull, + pub(crate) len: usize, +} + +impl RustSliceU8 { + pub fn from(s: &[u8]) -> Self { + RustSliceU8 { + ptr: NonNull::from(s).cast::(), + len: s.len(), + } + } + + pub unsafe fn as_slice<'a>(self) -> &'a [u8] { + slice::from_raw_parts(self.ptr.as_ptr(), self.len) + } +} + +const_assert!(mem::size_of::>() == mem::size_of::()); diff --git a/syntax/check.rs b/syntax/check.rs index 2826a8528..c71295e85 100644 --- a/syntax/check.rs +++ b/syntax/check.rs @@ -245,6 +245,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String { Type::UniquePtr(_) => "unique_ptr".to_owned(), Type::Ref(_) => "reference".to_owned(), Type::Str(_) => "&str".to_owned(), + Type::Slice(_) => "slice".to_owned(), + Type::SliceRefU8(_) => "&[u8]".to_owned(), Type::Fn(_) => "function pointer".to_owned(), Type::Void(_) => "()".to_owned(), } diff --git a/syntax/impls.rs b/syntax/impls.rs index 34fb851a4..b04075316 100644 --- a/syntax/impls.rs +++ b/syntax/impls.rs @@ -1,4 +1,4 @@ -use crate::syntax::{ExternFn, Receiver, Ref, Signature, Ty1, Type}; +use crate::syntax::{ExternFn, Receiver, Ref, Signature, Slice, Ty1, Type}; use std::hash::{Hash, Hasher}; use std::mem; use std::ops::Deref; @@ -21,6 +21,8 @@ impl Hash for Type { Type::Ref(t) => t.hash(state), Type::Str(t) => t.hash(state), Type::Fn(t) => t.hash(state), + Type::Slice(t) => t.hash(state), + Type::SliceRefU8(t) => t.hash(state), Type::Void(_) => {} } } @@ -37,6 +39,8 @@ impl PartialEq for Type { (Type::Ref(lhs), Type::Ref(rhs)) => lhs == rhs, (Type::Str(lhs), Type::Str(rhs)) => lhs == rhs, (Type::Fn(lhs), Type::Fn(rhs)) => lhs == rhs, + (Type::Slice(lhs), Type::Slice(rhs)) => lhs == rhs, + (Type::SliceRefU8(lhs), Type::SliceRefU8(rhs)) => lhs == rhs, (Type::Void(_), Type::Void(_)) => true, (_, _) => false, } @@ -106,6 +110,32 @@ impl Hash for Ref { } } +impl Eq for Slice {} + +impl PartialEq for Slice { + fn eq(&self, other: &Slice) -> bool { + let Slice { + bracket: _, + inner, + } = self; + let Slice { + bracket: _, + inner: inner2, + } = other; + inner == inner2 + } +} + +impl Hash for Slice { + fn hash(&self, state: &mut H) { + let Slice { + bracket: _, + inner, + } = self; + inner.hash(state); + } +} + impl Eq for Signature {} impl PartialEq for Signature { diff --git a/syntax/mod.rs b/syntax/mod.rs index 0d0328b45..4eaf81e22 100644 --- a/syntax/mod.rs +++ b/syntax/mod.rs @@ -15,7 +15,7 @@ pub mod types; use self::parse::kw; use proc_macro2::{Ident, Span}; use syn::punctuated::Punctuated; -use syn::token::{Brace, Paren}; +use syn::token::{Brace, Bracket, Paren}; use syn::{LitStr, Token}; pub use self::atom::Atom; @@ -84,6 +84,8 @@ pub enum Type { Str(Box), Fn(Box), Void(Span), + Slice(Box), + SliceRefU8(Box), } pub struct Ty1 { @@ -99,6 +101,11 @@ pub struct Ref { pub inner: Type, } +pub struct Slice { + pub bracket: Bracket, + pub inner: Type, +} + #[derive(Copy, Clone, PartialEq)] pub enum Lang { Cxx, diff --git a/syntax/parse.rs b/syntax/parse.rs index 8e674bde1..6156a69d1 100644 --- a/syntax/parse.rs +++ b/syntax/parse.rs @@ -1,6 +1,6 @@ use crate::syntax::{ - attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Struct, - Ty1, Type, Var, + attrs, error, Api, Atom, Doc, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice, + Struct, Ty1, Type, Var, }; use proc_macro2::Ident; use quote::{format_ident, quote}; @@ -8,7 +8,7 @@ use syn::punctuated::Punctuated; use syn::{ Abi, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType, GenericArgument, Item, ItemForeignMod, ItemStruct, Pat, PathArguments, Result, ReturnType, Token, Type as RustType, - TypeBareFn, TypePath, TypeReference, + TypeBareFn, TypePath, TypeReference, TypeSlice, }; pub mod kw { @@ -222,10 +222,25 @@ fn parse_type(ty: &RustType) -> Result { RustType::Path(ty) => parse_type_path(ty), RustType::BareFn(ty) => parse_type_fn(ty), RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)), + RustType::Slice(ty) => parse_type_slice(ty), _ => Err(Error::new_spanned(ty, "unsupported type")), } } +fn parse_type_slice(ty: &TypeSlice) -> Result { + let inner = parse_type(&ty.elem)?; + let which = match &inner { + Type::Ident(ident) if ident == "u8" => { + Type::Slice + }, + _ => return Err(Error::new_spanned(ty, "unsupported type")) + }; + Ok(which(Box::new(Slice { + bracket: ty.bracket_token, + inner + }))) +} + fn parse_type_reference(ty: &TypeReference) -> Result { let inner = parse_type(&ty.elem)?; let which = match &inner { @@ -236,6 +251,14 @@ fn parse_type_reference(ty: &TypeReference) -> Result { Type::Str } } + Type::Slice(inner2) => { + match &inner2.inner { + Type::Ident(ident) if ident == "u8" => { + Type::SliceRefU8 + } + _ => return Err(Error::new_spanned(ty, "unsupported type")) + } + } _ => Type::Ref, }; Ok(which(Box::new(Ref { diff --git a/syntax/tokens.rs b/syntax/tokens.rs index 51592dd86..df11852ca 100644 --- a/syntax/tokens.rs +++ b/syntax/tokens.rs @@ -1,5 +1,5 @@ use crate::syntax::atom::Atom::*; -use crate::syntax::{Derive, ExternFn, Ref, Signature, Ty1, Type, Var}; +use crate::syntax::{Derive, ExternFn, Ref, Signature, Slice, Ty1, Type, Var}; use proc_macro2::{Ident, Span, TokenStream}; use quote::{quote_spanned, ToTokens}; use syn::Token; @@ -15,7 +15,8 @@ impl ToTokens for Type { ident.to_tokens(tokens); } Type::RustBox(ty) | Type::UniquePtr(ty) => ty.to_tokens(tokens), - Type::Ref(r) | Type::Str(r) => r.to_tokens(tokens), + Type::Ref(r) | Type::Str(r) | Type::SliceRefU8(r) => r.to_tokens(tokens), + Type::Slice(s) => s.to_tokens(tokens), Type::Fn(f) => f.to_tokens(tokens), Type::Void(span) => tokens.extend(quote_spanned!(*span=> ())), } @@ -51,6 +52,14 @@ impl ToTokens for Ref { } } +impl ToTokens for Slice { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.bracket.surround(tokens, |tokens| { + self.inner.to_tokens(tokens); + }); + } +} + impl ToTokens for Derive { fn to_tokens(&self, tokens: &mut TokenStream) { let name = match self { diff --git a/syntax/types.rs b/syntax/types.rs index f65b12fdc..6f3af09d7 100644 --- a/syntax/types.rs +++ b/syntax/types.rs @@ -23,9 +23,10 @@ impl<'a> Types<'a> { fn visit<'a>(all: &mut Set<'a, Type>, ty: &'a Type) { all.insert(ty); match ty { - Type::Ident(_) | Type::Str(_) | Type::Void(_) => {} + Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {} Type::RustBox(ty) | Type::UniquePtr(ty) => visit(all, &ty.inner), Type::Ref(r) => visit(all, &r.inner), + Type::Slice(s) => visit(all, &s.inner), Type::Fn(f) => { if let Some(ret) = &f.ret { visit(all, ret); diff --git a/tests/ffi/lib.rs b/tests/ffi/lib.rs index 68651ea70..adcd4fc26 100644 --- a/tests/ffi/lib.rs +++ b/tests/ffi/lib.rs @@ -24,6 +24,7 @@ pub mod ffi { fn c_return_unique_ptr() -> UniquePtr; fn c_return_ref(shared: &Shared) -> &usize; fn c_return_str(shared: &Shared) -> &str; + fn c_return_sliceu8(shared: &Shared) -> &[u8]; fn c_return_rust_string() -> String; fn c_return_unique_ptr_string() -> UniquePtr; @@ -34,6 +35,7 @@ pub mod ffi { fn c_take_ref_r(r: &R); fn c_take_ref_c(c: &C); fn c_take_str(s: &str); + fn c_take_sliceu8(s: &[u8]); fn c_take_rust_string(s: String); fn c_take_unique_ptr_string(s: UniquePtr); fn c_take_callback(callback: fn(String) -> usize); @@ -44,6 +46,7 @@ pub mod ffi { fn c_try_return_box() -> Result>; fn c_try_return_ref(s: &String) -> Result<&String>; fn c_try_return_str(s: &str) -> Result<&str>; + fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>; fn c_try_return_rust_string() -> Result; fn c_try_return_unique_ptr_string() -> Result>; } @@ -67,6 +70,7 @@ pub mod ffi { fn r_take_ref_r(r: &R); fn r_take_ref_c(c: &C); fn r_take_str(s: &str); + fn r_take_sliceu8(s: &[u8]); fn r_take_rust_string(s: String); fn r_take_unique_ptr_string(s: UniquePtr); @@ -160,6 +164,11 @@ fn r_take_rust_string(s: String) { assert_eq!(s, "2020"); } +fn r_take_sliceu8(s: &[u8]) { + assert_eq!(s.len(), 5); + assert_eq!(std::str::from_utf8(s).unwrap(), "2020\u{0}"); +} + fn r_take_unique_ptr_string(s: UniquePtr) { assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020"); } diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index 4aad3a2e9..307b7e5dc 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -9,6 +9,8 @@ extern "C" bool cxx_test_suite_r_is_correct(const tests::R *) noexcept; namespace tests { +const char* SLICE_DATA = "2020"; + C::C(size_t n) : n(n) {} size_t C::get() const { return this->n; } @@ -32,6 +34,11 @@ rust::Str c_return_str(const Shared &shared) { return "2020"; } +rust::Slice c_return_sliceu8(const Shared& shared) { + (void)shared; + return rust::Slice((const unsigned char*)SLICE_DATA, 5); +} + rust::String c_return_rust_string() { return "2020"; } std::unique_ptr c_return_unique_ptr_string() { @@ -80,6 +87,12 @@ void c_take_str(rust::Str s) { } } +void c_take_sliceu8(rust::Slice s) { + if (std::string((const char*)s.data(), s.size()) == "2020") { + cxx_test_suite_set_correct(); + } +} + void c_take_rust_string(rust::String s) { if (std::string(s) == "2020") { cxx_test_suite_set_correct(); @@ -108,6 +121,8 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; } rust::Str c_try_return_str(rust::Str s) { return s; } +rust::Slice c_try_return_sliceU8(rust::Slice s) { return s; } + rust::String c_try_return_rust_string() { return c_return_rust_string(); } std::unique_ptr c_try_return_unique_ptr_string() { @@ -146,6 +161,7 @@ extern "C" const char *cxx_run_test() noexcept { r_take_unique_ptr(std::unique_ptr(new C{2020})); r_take_ref_c(C{2020}); r_take_str(rust::Str("2020")); + r_take_sliceu8(rust::Slice((const unsigned char*)SLICE_DATA, 5)); r_take_rust_string(rust::String("2020")); r_take_unique_ptr_string( std::unique_ptr(new std::string("2020"))); diff --git a/tests/ffi/tests.h b/tests/ffi/tests.h index 67136147b..a68be5cce 100644 --- a/tests/ffi/tests.h +++ b/tests/ffi/tests.h @@ -23,6 +23,7 @@ rust::Box c_return_box(); std::unique_ptr c_return_unique_ptr(); const size_t &c_return_ref(const Shared &shared); rust::Str c_return_str(const Shared &shared); +rust::Slice c_return_sliceu8(const Shared &shared); rust::String c_return_rust_string(); std::unique_ptr c_return_unique_ptr_string(); @@ -33,6 +34,7 @@ void c_take_unique_ptr(std::unique_ptr c); void c_take_ref_r(const R &r); void c_take_ref_c(const C &c); void c_take_str(rust::Str s); +void c_take_sliceu8(rust::Slice s); void c_take_rust_string(rust::String s); void c_take_unique_ptr_string(std::unique_ptr s); void c_take_callback(rust::Fn callback); @@ -43,6 +45,7 @@ size_t c_fail_return_primitive(); rust::Box c_try_return_box(); const rust::String &c_try_return_ref(const rust::String &); rust::Str c_try_return_str(rust::Str); +rust::Slice c_try_return_sliceu8(rust::Slice); rust::String c_try_return_rust_string(); std::unique_ptr c_try_return_unique_ptr_string(); diff --git a/tests/test.rs b/tests/test.rs index f8e9ca824..ae2fc0c34 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -71,6 +71,7 @@ fn test_c_take() { check!(ffi::c_take_ref_c(unique_ptr.as_ref().unwrap())); check!(ffi::c_take_unique_ptr(unique_ptr)); check!(ffi::c_take_str("2020")); + check!(ffi::c_take_sliceu8(b"2020")); check!(ffi::c_take_rust_string("2020".to_owned())); check!(ffi::c_take_unique_ptr_string( ffi::c_return_unique_ptr_string() From ec9430e6576655464b3835372d23f4a1e03f4bf0 Mon Sep 17 00:00:00 2001 From: Adrian Taylor Date: Tue, 14 Apr 2020 16:09:58 -0700 Subject: [PATCH 2/2] Adding missing tests; fixing typo. --- tests/ffi/tests.cc | 2 +- tests/test.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/ffi/tests.cc b/tests/ffi/tests.cc index 307b7e5dc..bf5e76ddc 100644 --- a/tests/ffi/tests.cc +++ b/tests/ffi/tests.cc @@ -121,7 +121,7 @@ const rust::String &c_try_return_ref(const rust::String &s) { return s; } rust::Str c_try_return_str(rust::Str s) { return s; } -rust::Slice c_try_return_sliceU8(rust::Slice s) { return s; } +rust::Slice c_try_return_sliceu8(rust::Slice s) { return s; } rust::String c_try_return_rust_string() { return c_return_rust_string(); } diff --git a/tests/test.rs b/tests/test.rs index ae2fc0c34..511c52bfc 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -29,6 +29,7 @@ fn test_c_return() { ffi::c_return_unique_ptr(); assert_eq!(2020, *ffi::c_return_ref(&shared)); assert_eq!("2020", ffi::c_return_str(&shared)); + assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared)); assert_eq!("2020", ffi::c_return_rust_string()); assert_eq!( "2020", @@ -51,6 +52,7 @@ fn test_c_try_return() { assert_eq!(2020, *ffi::c_try_return_box().unwrap()); assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap()); assert_eq!("2020", ffi::c_try_return_str("2020").unwrap()); + assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap()); assert_eq!("2020", ffi::c_try_return_rust_string().unwrap()); assert_eq!( "2020",
name in Rustname in C++
&[T]tbd
Vec<T>tbd
BTreeMap<K, V>tbd
HashMap<K, V>tbd