From 94cee7f171eff3f9c1dae8e22f14a84f0df67f3b Mon Sep 17 00:00:00 2001 From: Bas Schoenmaeckers Date: Thu, 25 Jun 2026 13:58:36 +0200 Subject: [PATCH] Add more mapping functions to c-api --- crates/capi/src/abstract_/mapping.rs | 157 +++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/crates/capi/src/abstract_/mapping.rs b/crates/capi/src/abstract_/mapping.rs index 18b188613dc..143d5a97744 100644 --- a/crates/capi/src/abstract_/mapping.rs +++ b/crates/capi/src/abstract_/mapping.rs @@ -1,4 +1,15 @@ use crate::{PyObject, pystate::with_vm}; +use core::ffi::{CStr, c_char, c_int}; +use rustpython_vm::AsObject; + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_Check(obj: *mut PyObject) -> c_int { + with_vm(|_vm| { + let obj = unsafe { &*obj }; + Ok(obj.mapping_unchecked().check()) + }) +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn PyMapping_Size(obj: *mut PyObject) -> isize { with_vm(|vm| { @@ -7,6 +18,11 @@ pub unsafe extern "C" fn PyMapping_Size(obj: *mut PyObject) -> isize { }) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_Length(obj: *mut PyObject) -> isize { + unsafe { PyMapping_Size(obj) } +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn PyMapping_Keys(obj: *mut PyObject) -> *mut PyObject { with_vm(|vm| { @@ -37,6 +53,147 @@ pub unsafe extern "C" fn PyMapping_Items(obj: *mut PyObject) -> *mut PyObject { }) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_GetItemString( + obj: *mut PyObject, + key: *const c_char, +) -> *mut PyObject { + with_vm(|vm| { + let obj = unsafe { &*obj }; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("mapping key must be valid UTF-8"))?; + obj.get_item(key, vm) + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_GetOptionalItem( + obj: *mut PyObject, + key: *mut PyObject, + result: *mut *mut PyObject, +) -> c_int { + with_vm(|vm| { + unsafe { + *result = core::ptr::null_mut(); + } + let obj = unsafe { &*obj }; + let key = unsafe { &*key }; + + match obj.get_item(key, vm) { + Ok(value) => { + unsafe { + *result = value.into_raw().as_ptr(); + } + Ok(true) + } + Err(err) if err.fast_isinstance(vm.ctx.exceptions.key_error) => Ok(false), + Err(err) => Err(err), + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_GetOptionalItemString( + obj: *mut PyObject, + key: *const c_char, + result: *mut *mut PyObject, +) -> c_int { + with_vm(|vm| { + unsafe { + *result = core::ptr::null_mut(); + } + let obj = unsafe { &*obj }; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("mapping key must be valid UTF-8"))?; + + match obj.get_item(key, vm) { + Ok(value) => { + unsafe { + *result = value.into_raw().as_ptr(); + } + Ok(true) + } + Err(err) if err.fast_isinstance(vm.ctx.exceptions.key_error) => Ok(false), + Err(err) => Err(err), + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_HasKey(obj: *mut PyObject, key: *mut PyObject) -> c_int { + with_vm(|vm| { + let obj = unsafe { &*obj }; + let key = unsafe { &*key }; + obj.get_item(key, vm).is_ok() + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_HasKeyString(obj: *mut PyObject, key: *const c_char) -> c_int { + with_vm(|vm| { + let obj = unsafe { &*obj }; + if let Ok(key) = unsafe { CStr::from_ptr(key) }.to_str() { + obj.get_item(key, vm).is_ok() + } else { + false + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_HasKeyWithError( + obj: *mut PyObject, + key: *mut PyObject, +) -> c_int { + with_vm(|vm| { + let obj = unsafe { &*obj }; + let key = unsafe { &*key }; + + match obj.get_item(key, vm) { + Ok(_) => Ok(true), + Err(err) if err.fast_isinstance(vm.ctx.exceptions.key_error) => Ok(false), + Err(err) => Err(err), + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_HasKeyStringWithError( + obj: *mut PyObject, + key: *const c_char, +) -> c_int { + with_vm(|vm| { + let obj = unsafe { &*obj }; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("mapping key must be valid UTF-8"))?; + + match obj.get_item(key, vm) { + Ok(_) => Ok(true), + Err(err) if err.fast_isinstance(vm.ctx.exceptions.key_error) => Ok(false), + Err(err) => Err(err), + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyMapping_SetItemString( + obj: *mut PyObject, + key: *const c_char, + value: *mut PyObject, +) -> c_int { + with_vm(|vm| { + let obj = unsafe { &*obj }; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("mapping key must be valid UTF-8"))?; + let value = unsafe { &*value }.to_owned(); + obj.set_item(key, value, vm) + }) +} + #[cfg(false)] mod tests { use pyo3::prelude::*;