diff --git a/crates/capi/src/dictobject.rs b/crates/capi/src/dictobject.rs index e326ba87e3a..6cea9ea343c 100644 --- a/crates/capi/src/dictobject.rs +++ b/crates/capi/src/dictobject.rs @@ -1,7 +1,7 @@ use crate::PyObject; use crate::object::define_py_check; use crate::pystate::with_vm; -use core::ffi::c_int; +use core::ffi::{CStr, c_char, c_int}; use core::ptr::NonNull; use rustpython_vm::AsObject; use rustpython_vm::PyPayload; @@ -18,6 +18,15 @@ pub extern "C" fn PyDict_New() -> *mut PyObject { with_vm(|vm| vm.ctx.new_dict()) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_Clear(dict: *mut PyObject) { + with_vm(|vm| { + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + dict.clear(); + Ok(()) + }) +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn PyDict_SetItem( dict: *mut PyObject, @@ -32,6 +41,96 @@ pub unsafe extern "C" fn PyDict_SetItem( }) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_SetItemString( + dict: *mut PyObject, + key: *const c_char, + val: *mut PyObject, +) -> c_int { + with_vm(|vm| { + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("dictionary key must be valid UTF-8"))?; + let value = unsafe { &*val }.to_owned(); + dict.inner_setitem(key, value, vm) + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_GetItem(dict: *mut PyObject, key: *mut PyObject) -> *mut PyObject { + with_vm(|vm| { + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + let key = unsafe { &*key }; + + match dict.inner_getitem_opt(key, vm) { + Ok(Some(value)) => Ok(value.as_object().as_raw().cast_mut()), + Ok(None) | Err(_) => Ok(core::ptr::null_mut()), + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_GetItemWithError( + dict: *mut PyObject, + key: *mut PyObject, +) -> *mut PyObject { + with_vm(|vm| { + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + let key = unsafe { &*key }; + + if let Some(value) = dict.inner_getitem_opt(key, vm)? { + Ok(value.as_object().as_raw().cast_mut()) + } else { + Ok(core::ptr::null_mut()) + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_GetItemString( + dict: *mut PyObject, + key: *const c_char, +) -> *mut PyObject { + with_vm(|vm| { + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_unicode_decode_error("dictionary key must be valid UTF-8"))?; + + match dict.inner_getitem_opt(key, vm)? { + Some(value) => Ok(value.as_object().as_raw().cast_mut()), + None => Ok(core::ptr::null_mut()), + } + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_GetItemStringRef( + dict: *mut PyObject, + key: *const c_char, + result: *mut *mut PyObject, +) -> c_int { + with_vm(|vm| { + unsafe { + *result = core::ptr::null_mut(); + } + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("dictionary key must be valid UTF-8"))?; + + if let Some(value) = dict.inner_getitem_opt(key, vm)? { + unsafe { + *result = value.into_raw().as_ptr(); + } + Ok(true) + } else { + Ok(false) + } + }) +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn PyDict_GetItemRef( dict: *mut PyObject, @@ -128,6 +227,17 @@ pub unsafe extern "C" fn PyDict_DelItem(dict: *mut PyObject, key: *mut PyObject) }) } +#[unsafe(no_mangle)] +pub unsafe extern "C" fn PyDict_DelItemString(dict: *mut PyObject, key: *const c_char) -> c_int { + with_vm(|vm| { + let dict = unsafe { &*dict }.try_downcast_ref::(vm)?; + let key = unsafe { CStr::from_ptr(key) } + .to_str() + .map_err(|_| vm.new_value_error("dictionary key must be valid UTF-8"))?; + dict.del_item(key, vm) + }) +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn PyDict_Items(dict: *mut PyObject) -> *mut PyObject { with_vm(|vm| {