@@ -4,8 +4,9 @@ use std::mem::MaybeUninit;
44use std:: ptr;
55use std:: slice;
66
7+ use cpython_sys:: _Py_DecRef;
8+ use cpython_sys:: _Py_IncRef;
79use cpython_sys:: METH_FASTCALL ;
8- use cpython_sys:: Py_DecRef ;
910use cpython_sys:: Py_buffer ;
1011use cpython_sys:: Py_ssize_t ;
1112use cpython_sys:: PyBuffer_Release ;
@@ -26,6 +27,78 @@ const PYBUF_SIMPLE: c_int = 0;
2627const PAD_BYTE : u8 = b'=' ;
2728const 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]
30103fn 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