Skip to content

Commit e6d7c18

Browse files
committed
PoC RC
1 parent ed31a89 commit e6d7c18

File tree

1 file changed

+79
-10
lines changed

1 file changed

+79
-10
lines changed

Modules/_base64/src/lib.rs

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ use cpython_sys::PyModuleDef_HEAD_INIT;
1515
use cpython_sys::PyModuleDef_Init;
1616
use cpython_sys::PyObject;
1717
use cpython_sys::PyObject_GetBuffer;
18-
use cpython_sys::Py_DecRef;
18+
use cpython_sys::_Py_DecRef;
19+
use cpython_sys::_Py_IncRef;
1920
use cpython_sys::PyErr_NoMemory;
2021
use cpython_sys::PyErr_SetString;
2122
use cpython_sys::PyExc_TypeError;
@@ -27,6 +28,78 @@ const PAD_BYTE: u8 = b'=';
2728
const ENCODE_TABLE: [u8; 64] =
2829
*b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
2930

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

133206
// Safe cast by Safety
134207
match standard_b64encode_impl(source) {
135-
Ok(result) => result,
208+
Ok(result) => PyRc::into_raw(result),
136209
Err(_) => ptr::null_mut(),
137210
}
138211
}
139212

140-
fn standard_b64encode_impl(source: &mut PyObject) -> Result<*mut PyObject, ()> {
213+
fn standard_b64encode_impl(source: &mut PyObject) -> Result<PyRc, ()> {
141214
let buffer = match BorrowedBuffer::from_object(source) {
142215
Ok(buf) => buf,
143216
Err(_) => return Err(()),
@@ -171,16 +244,12 @@ fn standard_b64encode_impl(source: &mut PyObject) -> Result<*mut PyObject, ()> {
171244
return Err(());
172245
}
173246

174-
let result = unsafe { PyBytes_FromStringAndSize(ptr::null(), output_len as Py_ssize_t) };
175-
if result.is_null() {
247+
let Some(result) = (unsafe { PyRc::from_raw(PyBytes_FromStringAndSize(ptr::null(), output_len as Py_ssize_t)) }) else {
176248
return Err(());
177-
}
249+
};
178250

179-
let dest_ptr = unsafe { PyBytes_AsString(result) };
251+
let dest_ptr = unsafe { PyBytes_AsString(result.as_ptr()) };
180252
if dest_ptr.is_null() {
181-
unsafe {
182-
Py_DecRef(result);
183-
}
184253
return Err(());
185254
}
186255
let dest = unsafe { slice::from_raw_parts_mut(dest_ptr.cast::<u8>(), output_len) };

0 commit comments

Comments
 (0)