add PyMapping struct for mapping protocol

This commit is contained in:
snowapril
2021-09-21 00:12:26 +09:00
parent 14ce6aa49a
commit 77351b3da8
2 changed files with 50 additions and 17 deletions

View File

@@ -12,7 +12,7 @@ use crate::{
IdProtocol, IntoPyObject, ItemProtocol,
PyArithmeticValue::*,
PyAttributes, PyClassDef, PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef,
PyResult, PyValue, TryFromObject, TypeProtocol,
PyResult, PyValue, TryFromBorrowedObject, TypeProtocol,
};
use crossbeam_utils::atomic::AtomicCell;
use std::fmt;
@@ -902,25 +902,27 @@ pub(crate) fn init(context: &PyContext) {
PyDictReverseItemIterator::extend_class(context, &context.types.dict_reverseitemiterator_type);
}
#[allow(clippy::type_complexity)]
pub struct PyMapping {
dict: PyDictRef,
pub length: Option<fn(PyObjectRef, &VirtualMachine) -> PyResult<usize>>,
pub subscript: Option<fn(PyObjectRef, PyObjectRef, &VirtualMachine) -> PyResult>,
pub ass_subscript:
Option<fn(PyObjectRef, PyObjectRef, PyObjectRef, &VirtualMachine) -> PyResult<()>>,
}
impl TryFromObject for PyMapping {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let dict = vm.ctx.new_dict();
PyDict::merge(
&dict.entries,
OptionalArg::Present(obj),
KwArgs::default(),
vm,
)?;
Ok(PyMapping { dict })
}
}
impl PyMapping {}
impl PyMapping {
pub fn into_dict(self) -> PyDictRef {
self.dict
impl TryFromBorrowedObject for PyMapping {
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Self> {
let obj_cls = obj.class();
for cls in obj_cls.iter_mro() {
if let Some(f) = cls.slots.as_mapping.load() {
return f(obj, vm);
}
}
Err(vm.new_type_error(format!(
"a dict-like object is required, not '{}'",
obj_cls.name()
)))
}
}

View File

@@ -543,7 +543,38 @@ pub trait AsMapping: PyValue {
Self::as_mapping(zelf, vm)
}
fn downcast(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
zelf.downcast::<Self>().map_err(|obj| {
vm.new_type_error(format!(
"{} type is required, not {}",
Self::class(vm),
obj.class()
))
})
}
fn downcast_ref<'a>(zelf: &'a PyObjectRef, vm: &VirtualMachine) -> PyResult<&'a PyRef<Self>> {
zelf.downcast_ref::<Self>().ok_or_else(|| {
vm.new_type_error(format!(
"{} type is required, not {}",
Self::class(vm),
zelf.class()
))
})
}
fn as_mapping(zelf: &PyRef<Self>, vm: &VirtualMachine) -> PyResult<PyMapping>;
fn length(zelf: PyObjectRef, _vm: &VirtualMachine) -> PyResult<usize>;
fn subscript(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult;
fn ass_subscript(
zelf: PyObjectRef,
needle: PyObjectRef,
value: PyObjectRef,
vm: &VirtualMachine,
) -> PyResult<()>;
}
#[pyimpl]