From 200f97d06bd582fa4ec29f9add38b658788cd67a Mon Sep 17 00:00:00 2001 From: jfh Date: Mon, 11 Oct 2021 06:18:02 +0300 Subject: [PATCH] Add trait for common set operations on set-like dictionary views. --- vm/src/builtins/dict.rs | 62 ++++++++++++----------------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/vm/src/builtins/dict.rs b/vm/src/builtins/dict.rs index 5fbdbb9eb7..fbde374d08 100644 --- a/vm/src/builtins/dict.rs +++ b/vm/src/builtins/dict.rs @@ -670,13 +670,6 @@ where #[pymethod(magic)] fn reversed(&self) -> Self::ReverseIter; - - fn to_set(zelf: PyRef, vm: &VirtualMachine) -> PyResult { - let len = zelf.dict().len(); - let zelf: PyObjectRef = Self::iter(zelf, vm)?; - let iter = PyIterIter::new(vm, zelf, Some(len)); - PySetInner::from_iter(iter, vm) - } } macro_rules! dict_view { @@ -911,8 +904,16 @@ dict_view! { vm.new_tuple((key, value)).into() } -#[pyimpl(with(DictView, Comparable, Iterable))] -impl PyDictKeys { +// Set operations defined on set-like views of the dictionary. +#[pyimpl] +trait ViewSetOps: DictView { + fn to_set(zelf: PyRef, vm: &VirtualMachine) -> PyResult { + let len = zelf.dict().len(); + let zelf: PyObjectRef = Self::iter(zelf, vm)?; + let iter = PyIterIter::new(vm, zelf, Some(len)); + PySetInner::from_iter(iter, vm) + } + #[pymethod(name = "__rxor__")] #[pymethod(magic)] fn xor(zelf: PyRef, other: ArgIterable, vm: &VirtualMachine) -> PyResult { @@ -946,43 +947,13 @@ impl PyDictKeys { } } -#[pyimpl(with(DictView, Comparable, Iterable))] -impl PyDictValues {} +impl ViewSetOps for PyDictKeys {} +#[pyimpl(with(DictView, Comparable, Iterable, ViewSetOps))] +impl PyDictKeys {} -#[pyimpl(with(DictView, Comparable, Iterable))] +impl ViewSetOps for PyDictItems {} +#[pyimpl(with(DictView, Comparable, Iterable, ViewSetOps))] impl PyDictItems { - #[pymethod(name = "__rxor__")] - #[pymethod(magic)] - fn xor(zelf: PyRef, other: ArgIterable, vm: &VirtualMachine) -> PyResult { - let zelf = Self::to_set(zelf, vm)?; - let inner = zelf.symmetric_difference(other, vm)?; - Ok(PySet { inner }) - } - - #[pymethod(name = "__rand__")] - #[pymethod(magic)] - fn and(zelf: PyRef, other: ArgIterable, vm: &VirtualMachine) -> PyResult { - let zelf = Self::to_set(zelf, vm)?; - let inner = zelf.intersection(other, vm)?; - Ok(PySet { inner }) - } - - #[pymethod(name = "__ror__")] - #[pymethod(magic)] - fn or(zelf: PyRef, other: ArgIterable, vm: &VirtualMachine) -> PyResult { - let zelf = Self::to_set(zelf, vm)?; - let inner = zelf.union(other, vm)?; - Ok(PySet { inner }) - } - - #[pymethod(name = "__rsub__")] - #[pymethod(magic)] - fn sub(zelf: PyRef, other: ArgIterable, vm: &VirtualMachine) -> PyResult { - let zelf = Self::to_set(zelf, vm)?; - let inner = zelf.difference(other, vm)?; - Ok(PySet { inner }) - } - #[pymethod(magic)] fn contains(zelf: PyRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult { let needle = match_class! { @@ -1004,6 +975,9 @@ impl PyDictItems { } } +#[pyimpl(with(DictView, Comparable, Iterable))] +impl PyDictValues {} + pub(crate) fn init(context: &PyContext) { PyDict::extend_class(context, &context.types.dict_type); PyDictKeys::extend_class(context, &context.types.dict_keys_type);