Skip to content

Commit a2a3ab0

Browse files
committed
&mut [u8] support
1 parent bf1000f commit a2a3ab0

File tree

9 files changed

+84
-20
lines changed

9 files changed

+84
-20
lines changed

gen/src/write.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -430,10 +430,14 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
430430
out.builtin.rust_str_repr = true;
431431
write!(out, "::rust::impl<::rust::Str>::repr(");
432432
}
433-
Some(Type::SliceRefU8(_)) if !indirect_return => {
433+
Some(Type::SliceRefU8(ty)) if !indirect_return && ty.mutability.is_none() => {
434434
out.builtin.rust_slice_repr = true;
435435
write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(")
436436
}
437+
Some(Type::SliceRefU8(_)) if !indirect_return => {
438+
out.builtin.rust_slice_repr = true;
439+
write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(")
440+
}
437441
_ => {}
438442
}
439443
match &efn.receiver {
@@ -468,12 +472,19 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) {
468472
out.builtin.unsafe_bitcopy = true;
469473
write_type(out, &arg.ty);
470474
write!(out, "(::rust::unsafe_bitcopy, *{})", arg.ident);
471-
} else if let Type::SliceRefU8(_) = arg.ty {
472-
write!(
473-
out,
474-
"::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
475-
arg.ident,
476-
);
475+
} else if let Type::SliceRefU8(ref ty) = arg.ty {
476+
match ty.mutability {
477+
None => write!(
478+
out,
479+
"::rust::Slice<const uint8_t>(static_cast<const uint8_t *>({0}.ptr), {0}.len)",
480+
arg.ident,
481+
),
482+
Some(_) => write!(
483+
out,
484+
"::rust::Slice<uint8_t>(static_cast<uint8_t *>({0}.ptr), {0}.len)",
485+
arg.ident,
486+
)
487+
}
477488
} else if out.types.needs_indirect_abi(&arg.ty) {
478489
out.include.utility = true;
479490
write!(out, "::std::move(*{})", arg.ident);
@@ -712,9 +723,13 @@ fn write_rust_function_shim_impl(
712723
out.builtin.rust_str_repr = true;
713724
write!(out, "::rust::impl<::rust::Str>::repr(");
714725
}
715-
Type::SliceRefU8(_) => {
726+
Type::SliceRefU8(ty) => {
716727
out.builtin.rust_slice_repr = true;
717-
write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
728+
if ty.mutability.is_none() {
729+
write!(out, "::rust::impl<::rust::Slice<const uint8_t>>::repr(");
730+
} else {
731+
write!(out, "::rust::impl<::rust::Slice<uint8_t>>::repr(");
732+
}
718733
}
719734
ty if out.types.needs_indirect_abi(ty) => write!(out, "&"),
720735
_ => {}
@@ -884,9 +899,12 @@ fn write_type(out: &mut OutFile, ty: &Type) {
884899
Type::Str(_) => {
885900
write!(out, "::rust::Str");
886901
}
887-
Type::SliceRefU8(_) => {
902+
Type::SliceRefU8(ty) if ty.mutability.is_none() => {
888903
write!(out, "::rust::Slice<const uint8_t>");
889904
}
905+
Type::SliceRefU8(_) => {
906+
write!(out, "::rust::Slice<uint8_t>");
907+
}
890908
Type::Fn(f) => {
891909
write!(out, "::rust::{}<", if f.throws { "TryFn" } else { "Fn" });
892910
match &f.ret {

include/cxx.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,6 @@ class Str final {
9090
#ifndef CXXBRIDGE1_RUST_SLICE
9191
template <typename T>
9292
class Slice final {
93-
static_assert(std::is_const<T>::value,
94-
"&[T] needs to be written as rust::Slice<const T> in C++");
95-
9693
public:
9794
Slice() noexcept;
9895
Slice(T *, size_t count) noexcept;

macro/src/expand.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
330330
_ => quote!(#var),
331331
},
332332
Type::Str(_) => quote!(::cxx::private::RustStr::from(#var)),
333-
Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8::from(#var)),
333+
Type::SliceRefU8(ty) if ty.mutability.is_none() => quote!(::cxx::private::RustSliceU8::from(#var)),
334+
Type::SliceRefU8(_) => quote!(::cxx::private::RustMutSliceU8::from(#var)),
334335
ty if types.needs_indirect_abi(ty) => quote!(#var.as_mut_ptr()),
335336
_ => quote!(#var),
336337
}
@@ -423,7 +424,8 @@ fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
423424
_ => call,
424425
},
425426
Type::Str(_) => quote!(#call.as_str()),
426-
Type::SliceRefU8(_) => quote!(#call.as_slice()),
427+
Type::SliceRefU8(ty) if ty.mutability.is_none() => quote!(#call.as_slice()),
428+
Type::SliceRefU8(ty) if ty.mutability.is_some() => quote!(#call.as_mut_slice()),
427429
_ => call,
428430
},
429431
};
@@ -654,7 +656,8 @@ fn expand_rust_function_shim_impl(
654656
_ => None,
655657
},
656658
Type::Str(_) => Some(quote!(::cxx::private::RustStr::from)),
657-
Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustSliceU8::from)),
659+
Type::SliceRefU8(ty) if ty.mutability.is_none() => Some(quote!(::cxx::private::RustSliceU8::from)),
660+
Type::SliceRefU8(_) => Some(quote!(::cxx::private::RustMutSliceU8::from)),
658661
_ => None,
659662
});
660663

@@ -1093,7 +1096,8 @@ fn expand_extern_type(ty: &Type, types: &Types, proper: bool) -> TokenStream {
10931096
}
10941097
}
10951098
Type::Str(_) => quote!(::cxx::private::RustStr),
1096-
Type::SliceRefU8(_) => quote!(::cxx::private::RustSliceU8),
1099+
Type::SliceRefU8(ty) if ty.mutability.is_none() => quote!(::cxx::private::RustSliceU8),
1100+
Type::SliceRefU8(_) => quote!(::cxx::private::RustMutSliceU8),
10971101
_ => quote!(#ty),
10981102
}
10991103
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,7 @@ mod function;
397397
mod opaque;
398398
mod result;
399399
mod rust_sliceu8;
400+
mod rust_mutsliceu8;
400401
mod rust_str;
401402
mod rust_string;
402403
mod rust_type;
@@ -441,6 +442,7 @@ pub mod private {
441442
pub use crate::opaque::Opaque;
442443
pub use crate::result::{r#try, Result};
443444
pub use crate::rust_sliceu8::RustSliceU8;
445+
pub use crate::rust_mutsliceu8::RustMutSliceU8;
444446
pub use crate::rust_str::RustStr;
445447
pub use crate::rust_string::RustString;
446448
pub use crate::rust_type::RustType;

src/rust_mutsliceu8.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use core::mem;
2+
use core::ptr::NonNull;
3+
use core::slice;
4+
5+
// Not necessarily ABI compatible with &mut [u8]. Codegen performs the translation.
6+
#[repr(C)]
7+
#[derive(Copy, Clone)]
8+
pub struct RustMutSliceU8 {
9+
pub(crate) ptr: NonNull<u8>,
10+
pub(crate) len: usize,
11+
}
12+
13+
impl RustMutSliceU8 {
14+
pub fn from(s: &mut [u8]) -> Self {
15+
let len = s.len();
16+
RustMutSliceU8 {
17+
ptr: NonNull::from(s).cast::<u8>(),
18+
len,
19+
}
20+
}
21+
22+
pub unsafe fn as_slice<'a>(self) -> &'a mut [u8] {
23+
slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len)
24+
}
25+
}
26+
27+
const_assert_eq!(
28+
mem::size_of::<Option<RustMutSliceU8>>(),
29+
mem::size_of::<RustMutSliceU8>(),
30+
);

syntax/check.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ fn check_type_ref(cx: &mut Check, ty: &Ref) {
178178
}
179179

180180
fn check_type_slice(cx: &mut Check, ty: &Slice) {
181-
cx.error(ty, "only &[u8] is supported so far, not other slice types");
181+
cx.error(ty, "only &[u8] and &mut [u8] are supported so far, not other slice types");
182182
}
183183

184184
fn check_type_fn(cx: &mut Check, ty: &Signature) {
@@ -477,7 +477,8 @@ fn describe(cx: &mut Check, ty: &Type) -> String {
477477
Type::Str(_) => "&str".to_owned(),
478478
Type::CxxVector(_) => "C++ vector".to_owned(),
479479
Type::Slice(_) => "slice".to_owned(),
480-
Type::SliceRefU8(_) => "&[u8]".to_owned(),
480+
Type::SliceRefU8(ty) if ty.mutability.is_none() => "&[u8]".to_owned(),
481+
Type::SliceRefU8(_) => "&mut [u8]".to_owned(),
481482
Type::Fn(_) => "function pointer".to_owned(),
482483
Type::Void(_) => "()".to_owned(),
483484
}

syntax/parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -638,7 +638,7 @@ fn parse_type_reference(ty: &TypeReference, namespace: &Namespace) -> Result<Typ
638638
}
639639
}
640640
Type::Slice(slice) => match &slice.inner {
641-
Type::Ident(ident) if ident.rust == U8 && ty.mutability.is_none() => Type::SliceRefU8,
641+
Type::Ident(ident) if ident.rust == U8 => Type::SliceRefU8,
642642
_ => Type::Ref,
643643
},
644644
_ => Type::Ref,

tests/ffi/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ pub mod ffi {
129129
fn c_return_mut(shared: &mut Shared) -> &mut usize;
130130
fn c_return_str(shared: &Shared) -> &str;
131131
fn c_return_sliceu8(shared: &Shared) -> &[u8];
132+
fn c_return_mutsliceu8(shared: &Shared) -> &mut [u8];
132133
fn c_return_rust_string() -> String;
133134
fn c_return_unique_ptr_string() -> UniquePtr<CxxString>;
134135
fn c_return_unique_ptr_vector_u8() -> UniquePtr<CxxVector<u8>>;
@@ -157,6 +158,7 @@ pub mod ffi {
157158
fn c_take_ref_c(c: &C);
158159
fn c_take_str(s: &str);
159160
fn c_take_sliceu8(s: &[u8]);
161+
fn c_take_mutsliceu8(s: &mut [u8]);
160162
fn c_take_rust_string(s: String);
161163
fn c_take_unique_ptr_string(s: UniquePtr<CxxString>);
162164
fn c_take_unique_ptr_vector_u8(v: UniquePtr<CxxVector<u8>>);
@@ -192,6 +194,7 @@ pub mod ffi {
192194
fn c_try_return_ref(s: &String) -> Result<&String>;
193195
fn c_try_return_str(s: &str) -> Result<&str>;
194196
fn c_try_return_sliceu8(s: &[u8]) -> Result<&[u8]>;
197+
fn c_try_return_mutsliceu8(s: &mut [u8]) -> Result<&mut [u8]>;
195198
fn c_try_return_rust_string() -> Result<String>;
196199
fn c_try_return_unique_ptr_string() -> Result<UniquePtr<CxxString>>;
197200
fn c_try_return_rust_vec() -> Result<Vec<u8>>;
@@ -256,6 +259,7 @@ pub mod ffi {
256259
fn r_take_ref_c(c: &C);
257260
fn r_take_str(s: &str);
258261
fn r_take_sliceu8(s: &[u8]);
262+
fn r_take_mutsliceu8(s: &mut [u8]);
259263
fn r_take_rust_string(s: String);
260264
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>);
261265
fn r_take_ref_vector(v: &CxxVector<u8>);
@@ -448,6 +452,11 @@ fn r_take_sliceu8(s: &[u8]) {
448452
assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
449453
}
450454

455+
fn r_take_mutsliceu8(s: &mut [u8]) {
456+
assert_eq!(s.len(), 5);
457+
assert_eq!(std::str::from_utf8(s).unwrap(), "2020\0");
458+
}
459+
451460
fn r_take_unique_ptr_string(s: UniquePtr<CxxString>) {
452461
assert_eq!(s.as_ref().unwrap().to_str().unwrap(), "2020");
453462
}

tests/ffi/tests.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ const size_t &c_return_nested_ns_ref(const ::A::B::ABShared &shared);
8484
size_t &c_return_mut(Shared &shared);
8585
rust::Str c_return_str(const Shared &shared);
8686
rust::Slice<const uint8_t> c_return_sliceu8(const Shared &shared);
87+
rust::Slice<uint8_t> c_return_mutsliceu8(const Shared &shared);
8788
rust::String c_return_rust_string();
8889
std::unique_ptr<std::string> c_return_unique_ptr_string();
8990
std::unique_ptr<std::vector<uint8_t>> c_return_unique_ptr_vector_u8();
@@ -114,6 +115,7 @@ void c_take_ref_c(const C &c);
114115
void c_take_ref_ns_c(const ::H::H &h);
115116
void c_take_str(rust::Str s);
116117
void c_take_sliceu8(rust::Slice<const uint8_t> s);
118+
void c_take_mutsliceu8(rust::Slice<uint8_t> s);
117119
void c_take_rust_string(rust::String s);
118120
void c_take_unique_ptr_string(std::unique_ptr<std::string> s);
119121
void c_take_unique_ptr_vector_u8(std::unique_ptr<std::vector<uint8_t>> v);
@@ -148,6 +150,7 @@ rust::Box<R> c_try_return_box();
148150
const rust::String &c_try_return_ref(const rust::String &);
149151
rust::Str c_try_return_str(rust::Str);
150152
rust::Slice<const uint8_t> c_try_return_sliceu8(rust::Slice<const uint8_t>);
153+
rust::Slice<uint8_t> c_try_return_sliceu8(rust::Slice<uint8_t>);
151154
rust::String c_try_return_rust_string();
152155
std::unique_ptr<std::string> c_try_return_unique_ptr_string();
153156
rust::Vec<uint8_t> c_try_return_rust_vec();

0 commit comments

Comments
 (0)