@@ -5,7 +5,8 @@ use core::ptr::NonNull;
55use rustpython_vm:: builtins:: { PyStr , PyType , object_generic_set_dict, object_get_dict} ;
66use rustpython_vm:: bytecode:: ComparisonOperator ;
77use rustpython_vm:: function:: PySetterValue ;
8- use rustpython_vm:: { AsObject , Py , PyPayload } ;
8+ use rustpython_vm:: types:: { PyComparisonOp , hash_not_implemented} ;
9+ use rustpython_vm:: { AsObject , Py , PyPayload , PyResult , VirtualMachine } ;
910
1011pub type PyTypeObject = Py < PyType > ;
1112
@@ -100,25 +101,27 @@ pub unsafe extern "C" fn PyType_GetFullyQualifiedName(ptr: *const PyTypeObject)
100101 } )
101102}
102103
104+ #[ inline]
105+ fn get_constant ( vm : & VirtualMachine , constant_id : c_uint ) -> PyResult < & PyObject > {
106+ let ctx = & vm. ctx ;
107+ match constant_id {
108+ 0 => Ok ( ctx. none . as_object ( ) ) ,
109+ 1 => Ok ( ctx. false_value . as_object ( ) ) ,
110+ 2 => Ok ( ctx. true_value . as_object ( ) ) ,
111+ 3 => Ok ( ctx. ellipsis . as_object ( ) ) ,
112+ 4 => Ok ( ctx. not_implemented . as_object ( ) ) ,
113+ _ => Err ( vm. new_system_error ( "Invalid constant ID passed to Py_GetConstantBorrowed" ) ) ,
114+ }
115+ }
116+
103117#[ unsafe( no_mangle) ]
104118pub extern "C" fn Py_GetConstantBorrowed ( constant_id : c_uint ) -> * mut PyObject {
105- with_vm ( |vm| {
106- let ctx = & vm. ctx ;
107- let constant = match constant_id {
108- 0 => ctx. none . as_object ( ) ,
109- 1 => ctx. false_value . as_object ( ) ,
110- 2 => ctx. true_value . as_object ( ) ,
111- 3 => ctx. ellipsis . as_object ( ) ,
112- 4 => ctx. not_implemented . as_object ( ) ,
113- _ => {
114- return Err (
115- vm. new_system_error ( "Invalid constant ID passed to Py_GetConstantBorrowed" )
116- ) ;
117- }
118- }
119- . as_raw ( ) ;
120- Ok ( constant)
121- } )
119+ with_vm ( |vm| get_constant ( vm, constant_id) . map ( PyObject :: as_raw) )
120+ }
121+
122+ #[ unsafe( no_mangle) ]
123+ pub extern "C" fn Py_GetConstant ( constant_id : c_uint ) -> * mut PyObject {
124+ with_vm ( |vm| get_constant ( vm, constant_id) . map ( ToOwned :: to_owned) )
122125}
123126
124127#[ unsafe( no_mangle) ]
@@ -143,12 +146,22 @@ pub unsafe extern "C" fn PyObject_GetAttrString(
143146 let name = unsafe {
144147 CStr :: from_ptr ( attr_name)
145148 . to_str ( )
146- . expect ( "attribute name must be valid UTF-8" )
149+ . map_err ( |_| vm . new_value_error ( "attribute name must be valid UTF-8" ) ) ?
147150 } ;
148151 obj. get_attr ( name, vm)
149152 } )
150153}
151154
155+ #[ unsafe( no_mangle) ]
156+ pub unsafe extern "C" fn PyObject_ASCII ( obj : * mut PyObject ) -> * mut PyObject {
157+ with_vm ( |vm| unsafe { & * obj } . ascii ( vm) )
158+ }
159+
160+ #[ unsafe( no_mangle) ]
161+ pub unsafe extern "C" fn PyObject_Bytes ( obj : * mut PyObject ) -> * mut PyObject {
162+ with_vm ( |vm| unsafe { & * obj } . to_owned ( ) . bytes ( vm) )
163+ }
164+
152165#[ unsafe( no_mangle) ]
153166pub unsafe extern "C" fn PyObject_GetOptionalAttr (
154167 obj : * mut PyObject ,
@@ -172,6 +185,31 @@ pub unsafe extern "C" fn PyObject_GetOptionalAttr(
172185 } )
173186}
174187
188+ #[ unsafe( no_mangle) ]
189+ pub unsafe extern "C" fn PyObject_GetOptionalAttrString (
190+ obj : * mut PyObject ,
191+ attr_name : * const c_char ,
192+ result : * mut * mut PyObject ,
193+ ) -> c_int {
194+ with_vm ( |vm| {
195+ unsafe {
196+ * result = core:: ptr:: null_mut ( ) ;
197+ }
198+ let obj = unsafe { & * obj } ;
199+ let name = unsafe { CStr :: from_ptr ( attr_name) }
200+ . to_str ( )
201+ . map_err ( |_| vm. new_value_error ( "attribute name must be valid UTF-8" ) ) ?;
202+ if let Some ( attr) = vm. get_attribute_opt ( obj. to_owned ( ) , name) ? {
203+ unsafe {
204+ * result = attr. into_raw ( ) . as_ptr ( ) ;
205+ }
206+ Ok ( true )
207+ } else {
208+ Ok ( false )
209+ }
210+ } )
211+ }
212+
175213#[ unsafe( no_mangle) ]
176214pub unsafe extern "C" fn PyObject_SetAttrString (
177215 obj : * mut PyObject ,
@@ -182,7 +220,7 @@ pub unsafe extern "C" fn PyObject_SetAttrString(
182220 let obj = unsafe { & * obj } ;
183221 let name = unsafe { CStr :: from_ptr ( attr_name) }
184222 . to_str ( )
185- . expect ( "attribute name must be valid UTF-8" ) ;
223+ . map_err ( |_| vm . new_value_error ( "attribute name must be valid UTF-8" ) ) ? ;
186224 let value = unsafe { & * value } . to_owned ( ) ;
187225 obj. set_attr ( name, value, vm)
188226 } )
@@ -202,6 +240,46 @@ pub unsafe extern "C" fn PyObject_SetAttr(
202240 } )
203241}
204242
243+ #[ unsafe( no_mangle) ]
244+ pub unsafe extern "C" fn PyObject_DelAttr ( obj : * mut PyObject , name : * mut PyObject ) -> c_int {
245+ with_vm ( |vm| {
246+ let obj = unsafe { & * obj } ;
247+ let name = unsafe { & * name } . try_downcast_ref :: < PyStr > ( vm) ?;
248+ obj. del_attr ( name, vm)
249+ } )
250+ }
251+
252+ #[ unsafe( no_mangle) ]
253+ pub unsafe extern "C" fn PyObject_DelAttrString (
254+ obj : * mut PyObject ,
255+ attr_name : * const c_char ,
256+ ) -> c_int {
257+ with_vm ( |vm| {
258+ let obj = unsafe { & * obj } ;
259+ let name = unsafe { CStr :: from_ptr ( attr_name) }
260+ . to_str ( )
261+ . map_err ( |_| vm. new_value_error ( "attribute name must be valid UTF-8" ) ) ?;
262+ obj. del_attr ( name, vm)
263+ } )
264+ }
265+
266+ #[ unsafe( no_mangle) ]
267+ pub unsafe extern "C" fn PyObject_GenericSetAttr (
268+ obj : * mut PyObject ,
269+ name : * mut PyObject ,
270+ value : * mut PyObject ,
271+ ) -> c_int {
272+ with_vm ( |vm| {
273+ let obj = unsafe { & * obj } ;
274+ let name = unsafe { & * name } . try_downcast_ref :: < PyStr > ( vm) ?;
275+ let value = match NonNull :: new ( value) {
276+ Some ( value) => PySetterValue :: Assign ( unsafe { value. as_ref ( ) } . to_owned ( ) ) ,
277+ None => PySetterValue :: Delete ,
278+ } ;
279+ obj. generic_setattr ( name, value, vm)
280+ } )
281+ }
282+
205283#[ unsafe( no_mangle) ]
206284pub unsafe extern "C" fn PyObject_HasAttrWithError (
207285 obj : * mut PyObject ,
@@ -214,6 +292,64 @@ pub unsafe extern "C" fn PyObject_HasAttrWithError(
214292 } )
215293}
216294
295+ #[ unsafe( no_mangle) ]
296+ pub unsafe extern "C" fn PyObject_HasAttr ( obj : * mut PyObject , attr_name : * mut PyObject ) -> c_int {
297+ with_vm ( |vm| {
298+ let obj = unsafe { & * obj } ;
299+ let name = match unsafe { & * attr_name } . try_downcast_ref :: < PyStr > ( vm) {
300+ Ok ( name) => name,
301+ Err ( err) => {
302+ vm. run_unraisable ( err, None , obj. to_owned ( ) ) ;
303+ return false ;
304+ }
305+ } ;
306+
307+ match obj. has_attr ( name, vm) {
308+ Ok ( has_attr) => has_attr,
309+ Err ( err) => {
310+ vm. run_unraisable ( err, None , obj. to_owned ( ) ) ;
311+ false
312+ }
313+ }
314+ } )
315+ }
316+
317+ #[ unsafe( no_mangle) ]
318+ pub unsafe extern "C" fn PyObject_HasAttrString (
319+ obj : * mut PyObject ,
320+ attr_name : * const c_char ,
321+ ) -> c_int {
322+ with_vm ( |vm| {
323+ let obj = unsafe { & * obj } ;
324+ let Ok ( name) = unsafe { CStr :: from_ptr ( attr_name) } . to_str ( ) else {
325+ vm. run_unraisable ( vm. new_value_error ( "attribute name must be valid UTF-8" ) , None , obj. to_owned ( ) ) ;
326+ return false ;
327+ } ;
328+
329+ match obj. has_attr ( name, vm) {
330+ Ok ( has_attr) => has_attr,
331+ Err ( err) => {
332+ vm. run_unraisable ( err, None , obj. to_owned ( ) ) ;
333+ false
334+ }
335+ }
336+ } )
337+ }
338+
339+ #[ unsafe( no_mangle) ]
340+ pub unsafe extern "C" fn PyObject_HasAttrStringWithError (
341+ obj : * mut PyObject ,
342+ attr_name : * const c_char ,
343+ ) -> c_int {
344+ with_vm ( |vm| {
345+ let obj = unsafe { & * obj } ;
346+ let name = unsafe { CStr :: from_ptr ( attr_name) }
347+ . to_str ( )
348+ . map_err ( |_| vm. new_value_error ( "attribute name must be valid UTF-8" ) ) ?;
349+ obj. has_attr ( name, vm)
350+ } )
351+ }
352+
217353#[ unsafe( no_mangle) ]
218354pub unsafe extern "C" fn PyObject_GenericGetAttr (
219355 obj : * mut PyObject ,
@@ -248,26 +384,44 @@ pub extern "C" fn PyObject_Str(obj: *mut PyObject) -> *mut PyObject {
248384 } )
249385}
250386
387+ #[ inline]
388+ fn parse_richcompare_op ( vm : & VirtualMachine , op : c_int ) -> PyResult < PyComparisonOp > {
389+ match op {
390+ 0 => Ok ( ComparisonOperator :: Less ) ,
391+ 1 => Ok ( ComparisonOperator :: LessOrEqual ) ,
392+ 2 => Ok ( ComparisonOperator :: Equal ) ,
393+ 3 => Ok ( ComparisonOperator :: NotEqual ) ,
394+ 4 => Ok ( ComparisonOperator :: Greater ) ,
395+ 5 => Ok ( ComparisonOperator :: GreaterOrEqual ) ,
396+ _ => Err ( vm. new_system_error ( "invalid comparison operator" ) ) ,
397+ }
398+ . map ( Into :: into)
399+ }
400+
251401#[ unsafe( no_mangle) ]
252402pub unsafe extern "C" fn PyObject_RichCompare (
253403 left : * mut PyObject ,
254404 right : * mut PyObject ,
255405 op : c_int ,
256406) -> * mut PyObject {
257407 with_vm ( |vm| {
258- let op = match op {
259- 0 => ComparisonOperator :: Less ,
260- 1 => ComparisonOperator :: LessOrEqual ,
261- 2 => ComparisonOperator :: Equal ,
262- 3 => ComparisonOperator :: NotEqual ,
263- 4 => ComparisonOperator :: Greater ,
264- 5 => ComparisonOperator :: GreaterOrEqual ,
265- _ => return Err ( vm. new_system_error ( "invalid comparison operator" ) ) ,
266- } ;
267408 let left = unsafe { & * left } ;
268409 let right = unsafe { & * right } ;
269410 left. to_owned ( )
270- . rich_compare ( right. to_owned ( ) , op. into ( ) , vm)
411+ . rich_compare ( right. to_owned ( ) , parse_richcompare_op ( vm, op) ?, vm)
412+ } )
413+ }
414+
415+ #[ unsafe( no_mangle) ]
416+ pub unsafe extern "C" fn PyObject_RichCompareBool (
417+ left : * mut PyObject ,
418+ right : * mut PyObject ,
419+ op : c_int ,
420+ ) -> c_int {
421+ with_vm ( |vm| {
422+ let left = unsafe { & * left } ;
423+ let right = unsafe { & * right } ;
424+ left. rich_compare_bool ( right, parse_richcompare_op ( vm, op) ?, vm)
271425 } )
272426}
273427
@@ -298,6 +452,69 @@ pub unsafe extern "C" fn PyObject_IsTrue(obj: *mut PyObject) -> c_int {
298452 } )
299453}
300454
455+ #[ unsafe( no_mangle) ]
456+ pub unsafe extern "C" fn PyObject_Not ( obj : * mut PyObject ) -> c_int {
457+ with_vm ( |vm| {
458+ let obj = unsafe { & * obj } ;
459+ obj. to_owned ( ) . not ( vm)
460+ } )
461+ }
462+
463+ #[ unsafe( no_mangle) ]
464+ pub unsafe extern "C" fn PyObject_Hash ( obj : * mut PyObject ) -> isize {
465+ with_vm ( |vm| {
466+ let obj = unsafe { & * obj } ;
467+ obj. hash ( vm) . map ( |hash| hash as isize )
468+ } )
469+ }
470+
471+ #[ unsafe( no_mangle) ]
472+ pub unsafe extern "C" fn PyObject_HashNotImplemented ( obj : * mut PyObject ) -> isize {
473+ with_vm ( |vm| {
474+ let obj = unsafe { & * obj } ;
475+ hash_not_implemented ( obj, vm) . map ( |hash| hash as isize )
476+ } )
477+ }
478+
479+ #[ unsafe( no_mangle) ]
480+ pub unsafe extern "C" fn PyObject_SelfIter ( obj : * mut PyObject ) -> * mut PyObject {
481+ with_vm ( |_vm| unsafe { ( & * obj) . to_owned ( ) } )
482+ }
483+
484+ #[ unsafe( no_mangle) ]
485+ pub unsafe extern "C" fn Py_Is ( x : * mut PyObject , y : * mut PyObject ) -> c_int {
486+ ( x == y) as c_int
487+ }
488+
489+ #[ unsafe( no_mangle) ]
490+ pub unsafe extern "C" fn Py_IsNone ( x : * mut PyObject ) -> c_int {
491+ with_vm ( |vm| vm. is_none ( unsafe { & * x } ) )
492+ }
493+
494+ #[ unsafe( no_mangle) ]
495+ pub unsafe extern "C" fn Py_ReprEnter ( obj : * mut PyObject ) -> c_int {
496+ with_vm ( |vm| {
497+ let obj = unsafe { & * obj } ;
498+ let id = obj. get_id ( ) ;
499+ let mut guards = vm. repr_guards . borrow_mut ( ) ;
500+ if guards. contains ( & id) {
501+ true
502+ } else {
503+ guards. insert ( id) ;
504+ false
505+ }
506+ } )
507+ }
508+
509+ #[ unsafe( no_mangle) ]
510+ pub unsafe extern "C" fn Py_ReprLeave ( obj : * mut PyObject ) {
511+ with_vm ( |vm| {
512+ vm. repr_guards
513+ . borrow_mut ( )
514+ . remove ( & unsafe { & * obj } . get_id ( ) ) ;
515+ } )
516+ }
517+
301518#[ unsafe( no_mangle) ]
302519pub unsafe extern "C" fn PyObject_GenericGetDict (
303520 obj : * mut PyObject ,
0 commit comments