Skip to content

Commit 4db3902

Browse files
committed
PoC RC
1 parent 39915de commit 4db3902

File tree

1 file changed

+84
-10
lines changed

1 file changed

+84
-10
lines changed

Modules/_base64/src/lib.rs

Lines changed: 84 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use std::mem::MaybeUninit;
44
use std::ptr;
55
use std::slice;
66

7+
use cpython_sys::_Py_DecRef;
8+
use cpython_sys::_Py_IncRef;
79
use cpython_sys::METH_FASTCALL;
8-
use cpython_sys::Py_DecRef;
910
use cpython_sys::Py_buffer;
1011
use cpython_sys::Py_ssize_t;
1112
use cpython_sys::PyBuffer_Release;
@@ -26,6 +27,78 @@ const PYBUF_SIMPLE: c_int = 0;
2627
const PAD_BYTE: u8 = b'=';
2728
const ENCODE_TABLE: [u8; 64] = *b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2829

30+
pub struct PyRc {
31+
ptr: std::ptr::NonNull<PyObject>,
32+
}
33+
34+
impl PyRc {
35+
/// # Safety
36+
/// `ptr` must be a valid pointer to a PyObject.
37+
pub unsafe fn from_raw(ptr: *mut PyObject) -> Option<Self> {
38+
let ptr = std::ptr::NonNull::new(ptr)?;
39+
Some(Self { ptr })
40+
}
41+
42+
pub fn into_non_null(zelf: Self) -> std::ptr::NonNull<PyObject> {
43+
let ptr = zelf.ptr;
44+
std::mem::forget(zelf);
45+
ptr
46+
}
47+
48+
pub fn into_raw(zelf: Self) -> *mut PyObject {
49+
let ptr = zelf.ptr.as_ptr();
50+
std::mem::forget(zelf);
51+
ptr
52+
}
53+
54+
pub fn as_raw(&self) -> *mut PyObject {
55+
self.ptr.as_ptr()
56+
}
57+
}
58+
59+
impl AsRef<PyObject> for PyRc {
60+
fn as_ref(&self) -> &PyObject {
61+
unsafe { self.ptr.as_ref() }
62+
}
63+
}
64+
65+
impl AsMut<PyObject> for PyRc {
66+
fn as_mut(&mut self) -> &mut PyObject {
67+
unsafe { self.ptr.as_mut() }
68+
}
69+
}
70+
71+
impl std::ops::Deref for PyRc {
72+
type Target = PyObject;
73+
74+
fn deref(&self) -> &Self::Target {
75+
self.as_ref()
76+
}
77+
}
78+
79+
impl std::ops::DerefMut for PyRc {
80+
fn deref_mut(&mut self) -> &mut Self::Target {
81+
self.as_mut()
82+
}
83+
}
84+
85+
impl Clone for PyRc {
86+
fn clone(&self) -> Self {
87+
unsafe {
88+
_Py_IncRef(self.ptr.as_ptr());
89+
}
90+
Self { ptr: self.ptr }
91+
}
92+
}
93+
94+
impl Drop for PyRc {
95+
fn drop(&mut self) {
96+
unsafe {
97+
_Py_DecRef(self.ptr.as_ptr());
98+
}
99+
}
100+
}
101+
29102
#[inline]
30103
fn encoded_output_len(input_len: usize) -> Option<usize> {
31104
input_len
@@ -135,12 +208,12 @@ pub unsafe extern "C" fn standard_b64encode(
135208

136209
// Safe cast by Safety
137210
match standard_b64encode_impl(source) {
138-
Ok(result) => result,
211+
Ok(result) => PyRc::into_raw(result),
139212
Err(_) => ptr::null_mut(),
140213
}
141214
}
142215

143-
fn standard_b64encode_impl(source: &PyObject) -> Result<*mut PyObject, ()> {
216+
fn standard_b64encode_impl(source: &PyObject) -> Result<PyRc, ()> {
144217
let buffer = match BorrowedBuffer::from_object(source) {
145218
Ok(buf) => buf,
146219
Err(_) => return Err(()),
@@ -174,16 +247,17 @@ fn standard_b64encode_impl(source: &PyObject) -> Result<*mut PyObject, ()> {
174247
return Err(());
175248
}
176249

177-
let result = unsafe { PyBytes_FromStringAndSize(ptr::null(), output_len as Py_ssize_t) };
178-
if result.is_null() {
250+
let Some(result) = (unsafe {
251+
PyRc::from_raw(PyBytes_FromStringAndSize(
252+
ptr::null(),
253+
output_len as Py_ssize_t,
254+
))
255+
}) else {
179256
return Err(());
180-
}
257+
};
181258

182-
let dest_ptr = unsafe { PyBytes_AsString(result) };
259+
let dest_ptr = unsafe { PyBytes_AsString(result.as_raw()) };
183260
if dest_ptr.is_null() {
184-
unsafe {
185-
Py_DecRef(result);
186-
}
187261
return Err(());
188262
}
189263
let dest = unsafe { slice::from_raw_parts_mut(dest_ptr.cast::<u8>(), output_len) };

0 commit comments

Comments
 (0)