fix: write back to out-param pointer in WrapParamRef for *mut types (#84)

This commit is contained in:
Bill Avery committed 2025-04-12 16:10:30 -07:00
1 parent d07119128b
commit 0f863ce9d3
2 files changed
+70 -30

No files matched your search

+66 -26
View File
@@ -6,7 +6,7 @@
//!
//! In order to create a new Rust type for a raw cef type, simply create a module for it first. And
//! then work on the implementations based on following conditions:
//!
//!
//! ## If raw cef type is a simple struct with basic fields
//! For example like [`cef_settings_t`], just create a struct like [`Settings`] and define a method
//! `as_raw` that can create the raw cef type.
@@ -42,8 +42,9 @@
use std::{
fmt::Debug,
mem,
mem::{self, ManuallyDrop},
ops::Deref,
ptr::NonNull,
sync::atomic::{fence, AtomicUsize, Ordering},
};
@@ -150,45 +151,84 @@ where
}
}
pub struct WrapParamRef<T>(mem::ManuallyDrop<T>);
impl<T, U> From<*mut T> for WrapParamRef<U>
pub struct WrapParamRef<T, P>
where
T: Sized + Copy + Into<U>,
U: Sized,
T: Sized + Into<P>,
P: Sized + Copy + Into<T>,
{
fn from(value: *mut T) -> Self {
value: T,
output: Option<NonNull<P>>,
}
impl<T, P> Drop for WrapParamRef<T, P>
where
T: Sized + Into<P>,
P: Sized + Copy + Into<T>,
{
fn drop(&mut self) {
if let Some(output) = &mut self.output {
let output = unsafe { output.as_mut() };
let mut value = unsafe { mem::zeroed() };
mem::swap(&mut self.value, &mut value);
*output = value.into();
}
}
}
impl<T, P> From<*mut P> for WrapParamRef<T, P>
where
T: Sized + Into<P>,
P: Sized + Copy + Into<T>,
{
fn from(value: *mut P) -> Self {
let mut output = NonNull::new(value);
let value = output
.as_mut()
.map(|p| {
let mut value = unsafe { mem::zeroed() };
mem::swap(unsafe { p.as_mut() }, &mut value);
value.into()
})
.unwrap_or_else(|| unsafe { mem::zeroed() });
Self { value, output }
}
}
impl<T, P> From<*const P> for WrapParamRef<T, P>
where
T: Sized + Into<P>,
P: Sized + Copy + Into<T>,
{
fn from(value: *const P) -> Self {
let value = unsafe { value.as_ref() }
.map(|value| (*value).into())
.unwrap_or_else(|| unsafe { mem::zeroed() });
WrapParamRef(mem::ManuallyDrop::new(value))
Self {
value,
output: None,
}
}
}
impl<T, U> From<*const T> for WrapParamRef<U>
impl<T, P> AsMut<T> for WrapParamRef<T, P>
where
T: Sized + Copy + Into<U>,
U: Sized,
T: Sized + Into<P>,
P: Sized + Copy + Into<T>,
{
fn from(value: *const T) -> Self {
let value = unsafe { value.as_ref() }
.map(|value| (*value).into())
.unwrap_or_else(|| unsafe { mem::zeroed() });
WrapParamRef(mem::ManuallyDrop::new(value))
}
}
impl<T> AsMut<T> for WrapParamRef<T> {
fn as_mut(&mut self) -> &mut T {
&mut *self.0
&mut self.value
}
}
impl<T> AsRef<T> for WrapParamRef<T> {
impl<T, P> AsRef<T> for WrapParamRef<T, P>
where
T: Sized + Into<P>,
P: Sized + Copy + Into<T>,
{
fn as_ref(&self) -> &T {
&*self.0
&self.value
}
}
@@ -268,7 +308,7 @@ impl<T: Rc> RefGuard<T> {
/// value to the function call. Using this method elsewhere may cause incorrect reference count
/// and memory safety issues.
pub unsafe fn into_raw(self) -> *mut T {
mem::ManuallyDrop::new(self).object
ManuallyDrop::new(self).object
}
/// Convert the value to another value that is also reference counted.
+4 -4
View File
@@ -893,7 +893,7 @@ impl SignatureRef<'_> {
let mut #arg_name = if #arg_name.is_null() {
None
} else {
Some(WrapParamRef::<#ty>::from(#arg_name))
Some(WrapParamRef::<#ty, _>::from(#arg_name))
};
let #arg_name = #arg_name.as_mut().map(|arg| arg.as_mut());
}),
@@ -901,7 +901,7 @@ impl SignatureRef<'_> {
let #arg_name = if #arg_name.is_null() {
None
} else {
Some(WrapParamRef::<#ty>::from(#arg_name))
Some(WrapParamRef::<#ty, _>::from(#arg_name))
};
let #arg_name = #arg_name.as_ref().map(|arg| arg.as_ref());
}),
@@ -1000,11 +1000,11 @@ impl SignatureRef<'_> {
match modifiers {
[TypeModifier::MutPtr, ..] => Some(quote! {
let mut #arg_name = WrapParamRef::<#ty>::from(#arg_name);
let mut #arg_name = WrapParamRef::<#ty, _>::from(#arg_name);
let #arg_name = #arg_name.as_mut();
}),
[TypeModifier::ConstPtr, ..] => Some(quote! {
let #arg_name = WrapParamRef::<#ty>::from(#arg_name);
let #arg_name = WrapParamRef::<#ty, _>::from(#arg_name);
let #arg_name = #arg_name.as_ref();
}),
_ => None,