@@ -15,7 +15,8 @@ use cpython_sys::PyModuleDef_HEAD_INIT;
1515use cpython_sys:: PyModuleDef_Init ;
1616use cpython_sys:: PyObject ;
1717use cpython_sys:: PyObject_GetBuffer ;
18- use cpython_sys:: Py_DecRef ;
18+ use cpython_sys:: _Py_DecRef;
19+ use cpython_sys:: _Py_IncRef;
1920use cpython_sys:: PyErr_NoMemory ;
2021use cpython_sys:: PyErr_SetString ;
2122use cpython_sys:: PyExc_TypeError ;
@@ -27,6 +28,78 @@ const PAD_BYTE: u8 = b'=';
2728const 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]
31104fn 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