Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for CxxVector<*mut T> and CxxVector<*const T> #1375

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 46 additions & 17 deletions gen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::gen::nested::NamespaceEntries;
use crate::gen::out::OutFile;
use crate::gen::{builtin, include, Opt};
use crate::syntax::atom::Atom::{self, *};
use crate::syntax::instantiate::{ImplKey, NamedImplKey};
use crate::syntax::instantiate::{CxxVectorPayloadImplKey, ImplKey, NamedImplKey, PtrMutability};
use crate::syntax::map::UnorderedMap as Map;
use crate::syntax::set::UnorderedSet;
use crate::syntax::symbol::{self, Symbol};
Expand Down Expand Up @@ -1352,6 +1352,7 @@ fn write_space_after_type(out: &mut OutFile, ty: &Type) {
enum UniquePtr<'a> {
Ident(&'a Ident),
CxxVector(&'a Ident),
CxxVectorPtr(PtrMutability, &'a Ident),
}

trait ToTypename {
Expand All @@ -1371,6 +1372,17 @@ impl<'a> ToTypename for UniquePtr<'a> {
UniquePtr::CxxVector(element) => {
format!("::std::vector<{}>", element.to_typename(types))
}
UniquePtr::CxxVectorPtr(mutability, element) => {
let const_prefix = match mutability {
PtrMutability::Const => "const ",
PtrMutability::Mut => "",
};
format!(
"::std::vector<{}{}*>",
const_prefix,
element.to_typename(types)
)
}
}
}
}
Expand All @@ -1392,6 +1404,13 @@ impl<'a> ToMangled for UniquePtr<'a> {
UniquePtr::CxxVector(element) => {
symbol::join(&[&"std", &"vector", &element.to_mangled(types)])
}
UniquePtr::CxxVectorPtr(mutability, element) => {
let prefix = match mutability {
PtrMutability::Const => "ptrc",
PtrMutability::Mut => "ptrm",
};
symbol::join(&[&"std", &"vector", &prefix, &element.to_mangled(types)])
}
}
}
}
Expand All @@ -1412,7 +1431,7 @@ fn write_generic_instantiations(out: &mut OutFile) {
ImplKey::UniquePtr(ident) => write_unique_ptr(out, ident),
ImplKey::SharedPtr(ident) => write_shared_ptr(out, ident),
ImplKey::WeakPtr(ident) => write_weak_ptr(out, ident),
ImplKey::CxxVector(ident) => write_cxx_vector(out, ident),
ImplKey::CxxVector(payload) => write_cxx_vector(out, payload),
}
}
out.end_block(Block::ExternC);
Expand Down Expand Up @@ -1639,21 +1658,21 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
// bindings for a "new" method anyway. But the Rust code can't be called
// for Opaque types because the 'new' method is not implemented.
UniquePtr::Ident(ident) => out.types.is_maybe_trivial(ident),
UniquePtr::CxxVector(_) => false,
UniquePtr::CxxVector(_) | UniquePtr::CxxVectorPtr(..) => false,
};

let conditional_delete = match ty {
UniquePtr::Ident(ident) => {
!out.types.structs.contains_key(ident) && !out.types.enums.contains_key(ident)
}
UniquePtr::CxxVector(_) => false,
UniquePtr::CxxVector(_) | UniquePtr::CxxVectorPtr(..) => false,
};

if conditional_delete {
out.builtin.is_complete = true;
let definition = match ty {
UniquePtr::Ident(ty) => &out.types.resolve(ty).name.cxx,
UniquePtr::CxxVector(_) => unreachable!(),
UniquePtr::CxxVector(_) | UniquePtr::CxxVectorPtr(..) => unreachable!(),
};
writeln!(
out,
Expand Down Expand Up @@ -1895,7 +1914,17 @@ fn write_weak_ptr(out: &mut OutFile, key: NamedImplKey) {
writeln!(out, "}}");
}

fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
fn write_cxx_vector(out: &mut OutFile, payload: CxxVectorPayloadImplKey) {
let (key, ptr_prefix, unique_ptr_payload) = match payload {
CxxVectorPayloadImplKey::Named(id) => (id, "", UniquePtr::CxxVector(id.rust)),
CxxVectorPayloadImplKey::Ptr(id, mutability) => {
let prefix = match mutability {
PtrMutability::Const => "ptrc$",
PtrMutability::Mut => "ptrm$",
};
(id, prefix, UniquePtr::CxxVectorPtr(mutability, id.rust))
}
};
let element = key.rust;
let inner = element.to_typename(out.types);
let instance = element.to_mangled(out.types);
Expand All @@ -1907,26 +1936,26 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
begin_function_definition(out);
writeln!(
out,
"::std::vector<{}> *cxxbridge1$std$vector${}$new() noexcept {{",
inner, instance,
"::std::vector<{}> *cxxbridge1$std$vector${}{}$new() noexcept {{",
inner, ptr_prefix, instance,
);
writeln!(out, " return new ::std::vector<{}>();", inner);
writeln!(out, "}}");

begin_function_definition(out);
writeln!(
out,
"::std::size_t cxxbridge1$std$vector${}$size(::std::vector<{}> const &s) noexcept {{",
instance, inner,
"::std::size_t cxxbridge1$std$vector${}{}$size(const ::std::vector<{}> &s) noexcept {{",
ptr_prefix, instance, inner,
);
writeln!(out, " return s.size();");
writeln!(out, "}}");

begin_function_definition(out);
writeln!(
out,
"{} *cxxbridge1$std$vector${}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
inner, instance, inner,
"{} *cxxbridge1$std$vector${}{}$get_unchecked(::std::vector<{}> *s, ::std::size_t pos) noexcept {{",
inner, ptr_prefix, instance, inner,
);
writeln!(out, " return &(*s)[pos];");
writeln!(out, "}}");
Expand All @@ -1935,8 +1964,8 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
begin_function_definition(out);
writeln!(
out,
"void cxxbridge1$std$vector${}$push_back(::std::vector<{}> *v, {} *value) noexcept {{",
instance, inner, inner,
"void cxxbridge1$std$vector${}{}$push_back(::std::vector<{}> *v, {} *value) noexcept {{",
ptr_prefix, instance, inner, inner,
);
writeln!(out, " v->push_back(::std::move(*value));");
writeln!(out, " ::rust::destroy(value);");
Expand All @@ -1945,14 +1974,14 @@ fn write_cxx_vector(out: &mut OutFile, key: NamedImplKey) {
begin_function_definition(out);
writeln!(
out,
"void cxxbridge1$std$vector${}$pop_back(::std::vector<{}> *v, {} *out) noexcept {{",
instance, inner, inner,
"void cxxbridge1$std$vector${}{}$pop_back(::std::vector<{}> *v, {} *out) noexcept {{",
ptr_prefix, instance, inner, inner,
);
writeln!(out, " ::new (out) {}(::std::move(v->back()));", inner);
writeln!(out, " v->pop_back();");
writeln!(out, "}}");
}

out.include.memory = true;
write_unique_ptr_common(out, UniquePtr::CxxVector(element));
write_unique_ptr_common(out, unique_ptr_payload);
}
122 changes: 67 additions & 55 deletions macro/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use crate::syntax::atom::Atom::*;
use crate::syntax::attrs::{self, OtherAttrs};
use crate::syntax::cfg::CfgExpr;
use crate::syntax::file::Module;
use crate::syntax::instantiate::{ImplKey, NamedImplKey};
use crate::syntax::instantiate::{CxxVectorPayloadImplKey, ImplKey, NamedImplKey, PtrMutability};
use crate::syntax::qualified::QualifiedName;
use crate::syntax::report::Errors;
use crate::syntax::symbol::Symbol;
Expand Down Expand Up @@ -108,8 +108,8 @@ fn expand(ffi: Module, doc: Doc, attrs: OtherAttrs, apis: &[Api], types: &Types)
ImplKey::WeakPtr(ident) => {
expanded.extend(expand_weak_ptr(ident, types, explicit_impl));
}
ImplKey::CxxVector(ident) => {
expanded.extend(expand_cxx_vector(ident, explicit_impl, types));
ImplKey::CxxVector(payload) => {
expanded.extend(expand_cxx_vector(payload, explicit_impl, types));
}
}
}
Expand Down Expand Up @@ -1670,21 +1670,31 @@ fn expand_weak_ptr(key: NamedImplKey, types: &Types, explicit_impl: Option<&Impl
}

fn expand_cxx_vector(
key: NamedImplKey,
payload: CxxVectorPayloadImplKey,
explicit_impl: Option<&Impl>,
types: &Types,
) -> TokenStream {
let (ptr_prefix, key, ty_prefix, elem_trait) = match payload {
CxxVectorPayloadImplKey::Named(id) => ("", id, quote! {}, quote!{ ::cxx::private::VectorElement }),
CxxVectorPayloadImplKey::Ptr(id, PtrMutability::Const) => ("ptrc$", id, quote! { *const }, quote!{ ::cxx::private::ConstPtrVectorElement }),
CxxVectorPayloadImplKey::Ptr(id, PtrMutability::Mut) => ("ptrm$", id, quote! { *mut }, quote!{ ::cxx::private::MutPtrVectorElement }),
};
let elem = key.rust;
let name = elem.to_string();
let resolve = types.resolve(elem);
let prefix = format!("cxxbridge1$std$vector${}$", resolve.name.to_symbol());
let prefix = format!(
"cxxbridge1$std$vector${}{}$",
ptr_prefix,
resolve.name.to_symbol()
);
let link_new = format!("{}new", prefix);
let link_size = format!("{}size", prefix);
let link_get_unchecked = format!("{}get_unchecked", prefix);
let link_push_back = format!("{}push_back", prefix);
let link_pop_back = format!("{}pop_back", prefix);
let unique_ptr_prefix = format!(
"cxxbridge1$unique_ptr$std$vector${}$",
"cxxbridge1$unique_ptr$std$vector${}{}$",
ptr_prefix,
resolve.name.to_symbol(),
);
let link_unique_ptr_null = format!("{}null", unique_ptr_prefix);
Expand All @@ -1694,6 +1704,7 @@ fn expand_cxx_vector(
let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);

let (impl_generics, ty_generics) = generics::split_for_impl(key, explicit_impl, resolve);
let impl_target = quote! { #ty_prefix #elem #ty_generics };

let begin_span = explicit_impl.map_or(key.begin_span, |explicit| explicit.impl_token.span);
let end_span = explicit_impl.map_or(key.end_span, |explicit| explicit.brace_token.span.join());
Expand All @@ -1702,75 +1713,76 @@ fn expand_cxx_vector(
let can_pass_element_by_value = types.is_maybe_trivial(elem);
let by_value_methods = if can_pass_element_by_value {
Some(quote_spanned! {end_span=>
unsafe fn __push_back(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
value: &mut ::cxx::core::mem::ManuallyDrop<Self>,
) {
extern "C" {
#[link_name = #link_push_back]
fn __push_back #impl_generics(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
value: *mut ::cxx::core::ffi::c_void,
);
}
unsafe {
__push_back(
this,
value as *mut ::cxx::core::mem::ManuallyDrop<Self> as *mut ::cxx::core::ffi::c_void,
);
}
}
unsafe fn __pop_back(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<Self>>,
out: &mut ::cxx::core::mem::MaybeUninit<Self>,
) {
extern "C" {
#[link_name = #link_pop_back]
fn __pop_back #impl_generics(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#elem #ty_generics>>,
out: *mut ::cxx::core::ffi::c_void,
);
unsafe fn __push_back(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#ty_prefix Self>>,
value: &mut ::cxx::core::mem::ManuallyDrop<#ty_prefix Self>,
) {
extern "C" {
#[link_name = #link_push_back]
fn __push_back #impl_generics(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#impl_target>>,
value: *mut ::cxx::core::ffi::c_void,
);
}
unsafe {
__push_back(
this,
value as *mut ::cxx::core::mem::ManuallyDrop<#ty_prefix Self> as *mut ::cxx::core::ffi::c_void,
);
}
}
unsafe {
__pop_back(
this,
out as *mut ::cxx::core::mem::MaybeUninit<Self> as *mut ::cxx::core::ffi::c_void,
);
unsafe fn __pop_back(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#ty_prefix Self>>,
out: &mut ::cxx::core::mem::MaybeUninit<#ty_prefix Self>,
) {
extern "C" {
#[link_name = #link_pop_back]
fn __pop_back #impl_generics(
this: ::cxx::core::pin::Pin<&mut ::cxx::CxxVector<#impl_target>>,
out: *mut ::cxx::core::ffi::c_void,
);
}
unsafe {
__pop_back(
this,
out as *mut ::cxx::core::mem::MaybeUninit<#ty_prefix Self> as *mut ::cxx::core::ffi::c_void,
);
}
}
}
})
})
} else {
None
};

quote_spanned! {end_span=>
#unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
#unsafe_token impl #impl_generics #elem_trait for #elem #ty_generics {
#[doc(hidden)]
fn __typename(f: &mut ::cxx::core::fmt::Formatter<'_>) -> ::cxx::core::fmt::Result {
f.write_str(#name)
}
fn __vector_new() -> *mut ::cxx::CxxVector<Self> {
fn __vector_new() -> *mut ::cxx::CxxVector<#ty_prefix Self> {
extern "C" {
#[link_name = #link_new]
fn __vector_new #impl_generics() -> *mut ::cxx::CxxVector<#elem #ty_generics>;
fn __vector_new #impl_generics() -> *mut ::cxx::CxxVector<#impl_target>;
}
unsafe { __vector_new() }
}
fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
fn __vector_size(v: &::cxx::CxxVector<#ty_prefix Self>) -> usize {
extern "C" {
#[link_name = #link_size]
fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
fn __vector_size #impl_generics(_: &::cxx::CxxVector<#impl_target>) -> usize;
}
unsafe { __vector_size(v) }
}
unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<#ty_prefix Self>, pos: usize) -> *mut #ty_prefix Self {
extern "C" {
#[link_name = #link_get_unchecked]
fn __get_unchecked #impl_generics(
v: *mut ::cxx::CxxVector<#elem #ty_generics>,
v: *mut ::cxx::CxxVector<#impl_target>,
pos: usize,
) -> *mut ::cxx::core::ffi::c_void;
}
unsafe { __get_unchecked(v, pos) as *mut Self }
unsafe { __get_unchecked(v, pos) as *mut #ty_prefix Self }
}
#by_value_methods
fn __unique_ptr_null() -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
Expand All @@ -1784,28 +1796,28 @@ fn expand_cxx_vector(
}
repr
}
unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<#ty_prefix Self>) -> ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void> {
extern "C" {
#[link_name = #link_unique_ptr_raw]
fn __unique_ptr_raw #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
fn __unique_ptr_raw #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>, raw: *mut ::cxx::CxxVector<#impl_target>);
}
let mut repr = ::cxx::core::mem::MaybeUninit::uninit();
unsafe {
__unique_ptr_raw(&mut repr, raw);
}
repr
}
unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<Self> {
unsafe fn __unique_ptr_get(repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#ty_prefix Self> {
extern "C" {
#[link_name = #link_unique_ptr_get]
fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#elem #ty_generics>;
fn __unique_ptr_get #impl_generics(this: *const ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *const ::cxx::CxxVector<#impl_target>;
}
unsafe { __unique_ptr_get(&repr) }
}
unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<Self> {
unsafe fn __unique_ptr_release(mut repr: ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#ty_prefix Self> {
extern "C" {
#[link_name = #link_unique_ptr_release]
fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
fn __unique_ptr_release #impl_generics(this: *mut ::cxx::core::mem::MaybeUninit<*mut ::cxx::core::ffi::c_void>) -> *mut ::cxx::CxxVector<#impl_target>;
}
unsafe { __unique_ptr_release(&mut repr) }
}
Expand Down
Loading