Skip to content

Commit

Permalink
Support for CxxVector<*mut T> and CxxVector<*const T>
Browse files Browse the repository at this point in the history
  • Loading branch information
makai410 committed Oct 30, 2024
1 parent a7898a2 commit 84f362d
Show file tree
Hide file tree
Showing 14 changed files with 680 additions and 101 deletions.
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

0 comments on commit 84f362d

Please sign in to comment.