diff --git a/crates/capi/src/lib.rs b/crates/capi/src/lib.rs index ebabc1521e9..62e7797a27b 100644 --- a/crates/capi/src/lib.rs +++ b/crates/capi/src/lib.rs @@ -10,6 +10,7 @@ extern crate alloc; pub mod abstract_; pub mod import; +pub mod longobject; pub mod object; pub mod pyerrors; pub mod pylifecycle; diff --git a/crates/capi/src/longobject.rs b/crates/capi/src/longobject.rs new file mode 100644 index 00000000000..8c9fe5e1acb --- /dev/null +++ b/crates/capi/src/longobject.rs @@ -0,0 +1,89 @@ +use crate::PyObject; +use crate::object::define_py_check; +use crate::pystate::with_vm; +use core::ffi::{c_long, c_longlong, c_ulong, c_ulonglong}; +use rustpython_vm::PyResult; +use rustpython_vm::builtins::PyInt; + +define_py_check!(fn PyLong_Check, types.int_type); +define_py_check!(exact fn PyLong_CheckExact, types.int_type); + +#[unsafe(no_mangle)] +pub extern "C" fn PyLong_FromLong(value: c_long) -> *mut PyObject { + with_vm(|vm| vm.ctx.new_int(value)) +} + +#[unsafe(no_mangle)] +pub extern "C" fn PyLong_FromLongLong(value: c_longlong) -> *mut PyObject { + with_vm(|vm| vm.ctx.new_int(value)) +} + +#[unsafe(no_mangle)] +pub extern "C" fn PyLong_FromSsize_t(value: isize) -> *mut PyObject { + with_vm(|vm| vm.ctx.new_int(value)) +} + +#[unsafe(no_mangle)] +pub extern "C" fn PyLong_FromSize_t(value: usize) -> *mut PyObject { + with_vm(|vm| vm.ctx.new_int(value)) +} + +#[unsafe(no_mangle)] +pub extern "C" fn PyLong_FromUnsignedLong(value: c_ulong) -> *mut PyObject { + with_vm(|vm| vm.ctx.new_int(value)) +} + +#[unsafe(no_mangle)] +pub extern "C" fn PyLong_FromUnsignedLongLong(value: c_ulonglong) -> *mut PyObject { + with_vm(|vm| vm.ctx.new_int(value)) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyLong_AsLong(obj: *mut PyObject) -> c_long { + with_vm::, _>(|vm| { + unsafe { &*obj } + .to_owned() + .try_index(vm)? + .as_bigint() + .try_into() + .map_err(|_| vm.new_overflow_error("Python int too large to convert to C long")) + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyLong_AsUnsignedLongLong(obj: *mut PyObject) -> c_ulonglong { + with_vm::, _>(|vm| { + unsafe { &*obj } + .to_owned() + .try_downcast::(vm)? + .as_bigint() + .try_into() + .map_err(|_| { + vm.new_overflow_error("Python int too large to convert to C unsigned long long") + }) + }) +} + +#[cfg(false)] +mod tests { + use pyo3::prelude::*; + use pyo3::types::PyInt; + + #[test] + fn test_py_int_u32() { + Python::attach(|py| { + let number = PyInt::new(py, 123); + assert!(number.is_instance_of::()); + assert_eq!(number.extract::().unwrap(), 123); + }) + } + + #[test] + fn test_py_int_u64() { + Python::attach(|py| { + let number = PyInt::new(py, 123u64); + assert!(number.is_instance_of::()); + assert_eq!(number.extract::().unwrap(), 123); + }) + } +} diff --git a/crates/capi/src/object.rs b/crates/capi/src/object.rs index f71475049f8..89995f8e908 100644 --- a/crates/capi/src/object.rs +++ b/crates/capi/src/object.rs @@ -33,6 +33,7 @@ macro_rules! define_py_check { }; } +pub(crate) use define_py_check; define_py_check!(fn PyType_Check, types.type_type); define_py_check!(exact fn PyType_CheckExact, types.type_type); diff --git a/crates/capi/src/util.rs b/crates/capi/src/util.rs index 6137ca9029f..9119581902a 100644 --- a/crates/capi/src/util.rs +++ b/crates/capi/src/util.rs @@ -1,6 +1,6 @@ use crate::PyObject; use core::convert::Infallible; -use core::ffi::{c_char, c_double, c_int, c_long, c_void}; +use core::ffi::{c_char, c_double, c_int, c_long, c_ulonglong, c_void}; use rustpython_vm::{PyObjectRef, PyRef, PyResult, VirtualMachine}; pub(crate) trait FfiResult { @@ -93,6 +93,14 @@ impl FfiResult for c_long { } } +impl FfiResult for c_ulonglong { + const ERR_VALUE: Self = Self::MAX; + + fn into_output(self, _vm: &VirtualMachine) -> Self { + self + } +} + impl FfiResult for c_double { const ERR_VALUE: Self = -1.0;