Skip to content

Commit 2c5cacf

Browse files
authored
Refactor Mapping Protocol (RustPython#4222)
1 parent 30aeb8b commit 2c5cacf

File tree

22 files changed

+310
-303
lines changed

22 files changed

+310
-303
lines changed

derive/src/pyclass.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ where
584584
let slot_name = slot_ident.to_string();
585585
let tokens = {
586586
const NON_ATOMIC_SLOTS: &[&str] = &["as_buffer"];
587-
const POINTER_SLOTS: &[&str] = &["as_number", "as_sequence"];
587+
const POINTER_SLOTS: &[&str] = &["as_number", "as_sequence", "as_mapping"];
588588
if NON_ATOMIC_SLOTS.contains(&slot_name.as_str()) {
589589
quote_spanned! { span =>
590590
slots.#slot_ident = Some(Self::#ident as _);

stdlib/src/array.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ mod array {
1212
str::wchar_t,
1313
},
1414
vm::{
15+
atomic_func,
1516
builtins::{
1617
PositionIterInternal, PyByteArray, PyBytes, PyBytesRef, PyDictRef, PyFloat, PyInt,
1718
PyIntRef, PyList, PyListRef, PyStr, PyStrRef, PyTupleRef, PyTypeRef,
@@ -1252,20 +1253,23 @@ mod array {
12521253
};
12531254

12541255
impl AsMapping for PyArray {
1255-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
1256-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
1257-
subscript: Some(|mapping, needle, vm| {
1258-
Self::mapping_downcast(mapping)._getitem(needle, vm)
1259-
}),
1260-
ass_subscript: Some(|mapping, needle, value, vm| {
1261-
let zelf = Self::mapping_downcast(mapping);
1262-
if let Some(value) = value {
1263-
Self::_setitem(zelf.to_owned(), needle, value, vm)
1264-
} else {
1265-
zelf._delitem(needle, vm)
1266-
}
1267-
}),
1268-
};
1256+
fn as_mapping() -> &'static PyMappingMethods {
1257+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
1258+
length: atomic_func!(|mapping, _vm| Ok(PyArray::mapping_downcast(mapping).len())),
1259+
subscript: atomic_func!(|mapping, needle, vm| {
1260+
PyArray::mapping_downcast(mapping)._getitem(needle, vm)
1261+
}),
1262+
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
1263+
let zelf = PyArray::mapping_downcast(mapping);
1264+
if let Some(value) = value {
1265+
PyArray::_setitem(zelf.to_owned(), needle, value, vm)
1266+
} else {
1267+
zelf._delitem(needle, vm)
1268+
}
1269+
}),
1270+
};
1271+
&AS_MAPPING
1272+
}
12691273
}
12701274

12711275
impl Iterable for PyArray {

stdlib/src/mmap.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -424,20 +424,24 @@ mod mmap {
424424
}
425425

426426
impl AsMapping for PyMmap {
427-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
428-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
429-
subscript: Some(|mapping, needle, vm| {
430-
Self::mapping_downcast(mapping)._getitem(needle, vm)
431-
}),
432-
ass_subscript: Some(|mapping, needle, value, vm| {
433-
let zelf = Self::mapping_downcast(mapping);
434-
if let Some(value) = value {
435-
Self::_setitem(zelf.to_owned(), needle, value, vm)
436-
} else {
437-
Err(vm.new_type_error("mmap object doesn't support item deletion".to_owned()))
438-
}
439-
}),
440-
};
427+
fn as_mapping() -> &'static PyMappingMethods {
428+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
429+
length: atomic_func!(|mapping, _vm| Ok(PyMmap::mapping_downcast(mapping).len())),
430+
subscript: atomic_func!(|mapping, needle, vm| {
431+
PyMmap::mapping_downcast(mapping)._getitem(needle, vm)
432+
}),
433+
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
434+
let zelf = PyMmap::mapping_downcast(mapping);
435+
if let Some(value) = value {
436+
PyMmap::_setitem(zelf.to_owned(), needle, value, vm)
437+
} else {
438+
Err(vm
439+
.new_type_error("mmap object doesn't support item deletion".to_owned()))
440+
}
441+
}),
442+
};
443+
&AS_MAPPING
444+
}
441445
}
442446

443447
impl AsSequence for PyMmap {

vm/src/builtins/bytearray.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -768,20 +768,23 @@ impl<'a> BufferResizeGuard<'a> for PyByteArray {
768768
}
769769

770770
impl AsMapping for PyByteArray {
771-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
772-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
773-
subscript: Some(|mapping, needle, vm| {
774-
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
775-
}),
776-
ass_subscript: Some(|mapping, needle, value, vm| {
777-
let zelf = Self::mapping_downcast(mapping);
778-
if let Some(value) = value {
779-
Self::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
780-
} else {
781-
zelf.delitem(needle.to_owned(), vm)
782-
}
783-
}),
784-
};
771+
fn as_mapping() -> &'static PyMappingMethods {
772+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
773+
length: atomic_func!(|mapping, _vm| Ok(PyByteArray::mapping_downcast(mapping).len())),
774+
subscript: atomic_func!(|mapping, needle, vm| {
775+
PyByteArray::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
776+
}),
777+
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
778+
let zelf = PyByteArray::mapping_downcast(mapping);
779+
if let Some(value) = value {
780+
PyByteArray::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
781+
} else {
782+
zelf.delitem(needle.to_owned(), vm)
783+
}
784+
}),
785+
};
786+
&AS_MAPPING
787+
}
785788
}
786789

787790
impl AsSequence for PyByteArray {

vm/src/builtins/bytes.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -571,11 +571,16 @@ impl AsBuffer for PyBytes {
571571
}
572572

573573
impl AsMapping for PyBytes {
574-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
575-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
576-
subscript: Some(|mapping, needle, vm| Self::mapping_downcast(mapping)._getitem(needle, vm)),
577-
ass_subscript: None,
578-
};
574+
fn as_mapping() -> &'static PyMappingMethods {
575+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
576+
length: atomic_func!(|mapping, _vm| Ok(PyBytes::mapping_downcast(mapping).len())),
577+
subscript: atomic_func!(
578+
|mapping, needle, vm| PyBytes::mapping_downcast(mapping)._getitem(needle, vm)
579+
),
580+
..PyMappingMethods::NOT_IMPLEMENTED
581+
};
582+
&AS_MAPPING
583+
}
579584
}
580585

581586
impl AsSequence for PyBytes {

vm/src/builtins/dict.rs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -453,20 +453,23 @@ impl Initializer for PyDict {
453453
}
454454

455455
impl AsMapping for PyDict {
456-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
457-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
458-
subscript: Some(|mapping, needle, vm| {
459-
Self::mapping_downcast(mapping).inner_getitem(needle, vm)
460-
}),
461-
ass_subscript: Some(|mapping, needle, value, vm| {
462-
let zelf = Self::mapping_downcast(mapping);
463-
if let Some(value) = value {
464-
zelf.inner_setitem(needle, value, vm)
465-
} else {
466-
zelf.inner_delitem(needle, vm)
467-
}
468-
}),
469-
};
456+
fn as_mapping() -> &'static PyMappingMethods {
457+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
458+
length: atomic_func!(|mapping, _vm| Ok(PyDict::mapping_downcast(mapping).len())),
459+
subscript: atomic_func!(|mapping, needle, vm| {
460+
PyDict::mapping_downcast(mapping).inner_getitem(needle, vm)
461+
}),
462+
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
463+
let zelf = PyDict::mapping_downcast(mapping);
464+
if let Some(value) = value {
465+
zelf.inner_setitem(needle, value, vm)
466+
} else {
467+
zelf.inner_delitem(needle, vm)
468+
}
469+
}),
470+
};
471+
&AS_MAPPING
472+
}
470473
}
471474

472475
impl AsSequence for PyDict {

vm/src/builtins/genericalias.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use super::type_;
22
use crate::{
3+
atomic_func,
34
builtins::{PyList, PyStr, PyStrRef, PyTuple, PyTupleRef, PyType, PyTypeRef},
45
class::PyClassImpl,
56
common::hash,
@@ -318,13 +319,15 @@ pub fn subs_parameters<F: Fn(&VirtualMachine) -> PyResult<String>>(
318319
}
319320

320321
impl AsMapping for PyGenericAlias {
321-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
322-
length: None,
323-
subscript: Some(|mapping, needle, vm| {
324-
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
325-
}),
326-
ass_subscript: None,
327-
};
322+
fn as_mapping() -> &'static PyMappingMethods {
323+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
324+
subscript: atomic_func!(|mapping, needle, vm| {
325+
PyGenericAlias::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
326+
}),
327+
..PyMappingMethods::NOT_IMPLEMENTED
328+
};
329+
&AS_MAPPING
330+
}
328331
}
329332

330333
impl Callable for PyGenericAlias {

vm/src/builtins/list.rs

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -405,18 +405,23 @@ impl Initializer for PyList {
405405
}
406406

407407
impl AsMapping for PyList {
408-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
409-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
410-
subscript: Some(|mapping, needle, vm| Self::mapping_downcast(mapping)._getitem(needle, vm)),
411-
ass_subscript: Some(|mapping, needle, value, vm| {
412-
let zelf = Self::mapping_downcast(mapping);
413-
if let Some(value) = value {
414-
zelf._setitem(needle, value, vm)
415-
} else {
416-
zelf._delitem(needle, vm)
417-
}
418-
}),
419-
};
408+
fn as_mapping() -> &'static PyMappingMethods {
409+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
410+
length: atomic_func!(|mapping, _vm| Ok(PyList::mapping_downcast(mapping).len())),
411+
subscript: atomic_func!(
412+
|mapping, needle, vm| PyList::mapping_downcast(mapping)._getitem(needle, vm)
413+
),
414+
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
415+
let zelf = PyList::mapping_downcast(mapping);
416+
if let Some(value) = value {
417+
zelf._setitem(needle, value, vm)
418+
} else {
419+
zelf._delitem(needle, vm)
420+
}
421+
}),
422+
};
423+
&AS_MAPPING
424+
}
420425
}
421426

422427
impl AsSequence for PyList {

vm/src/builtins/mappingproxy.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,15 @@ impl Constructor for PyMappingProxy {
4747
type Args = PyObjectRef;
4848

4949
fn py_new(cls: PyTypeRef, mapping: Self::Args, vm: &VirtualMachine) -> PyResult {
50-
if let Some(methods) = PyMapping::find_methods(&mapping, vm) {
50+
if let Some(methods) = PyMapping::find_methods(&mapping) {
5151
if mapping.payload_if_subclass::<PyList>(vm).is_none()
5252
&& mapping.payload_if_subclass::<PyTuple>(vm).is_none()
5353
{
5454
return Self {
55-
mapping: MappingProxyInner::Mapping(ArgMapping::with_methods(mapping, methods)),
55+
mapping: MappingProxyInner::Mapping(ArgMapping::with_methods(
56+
mapping,
57+
unsafe { methods.borrow_static() },
58+
)),
5659
}
5760
.into_ref_with_type(vm, cls)
5861
.map(Into::into);
@@ -201,13 +204,16 @@ impl Comparable for PyMappingProxy {
201204
}
202205

203206
impl AsMapping for PyMappingProxy {
204-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
205-
length: Some(|mapping, vm| Self::mapping_downcast(mapping).len(vm)),
206-
subscript: Some(|mapping, needle, vm| {
207-
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
208-
}),
209-
ass_subscript: None,
210-
};
207+
fn as_mapping() -> &'static PyMappingMethods {
208+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
209+
length: atomic_func!(|mapping, vm| PyMappingProxy::mapping_downcast(mapping).len(vm)),
210+
subscript: atomic_func!(|mapping, needle, vm| {
211+
PyMappingProxy::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
212+
}),
213+
..PyMappingMethods::NOT_IMPLEMENTED
214+
};
215+
&AS_MAPPING
216+
}
211217
}
212218

213219
impl AsSequence for PyMappingProxy {

vm/src/builtins/memory.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -974,21 +974,24 @@ impl Drop for PyMemoryView {
974974
}
975975

976976
impl AsMapping for PyMemoryView {
977-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
978-
length: Some(|mapping, vm| Self::mapping_downcast(mapping).len(vm)),
979-
subscript: Some(|mapping, needle, vm| {
980-
let zelf = Self::mapping_downcast(mapping);
981-
Self::getitem(zelf.to_owned(), needle.to_owned(), vm)
982-
}),
983-
ass_subscript: Some(|mapping, needle, value, vm| {
984-
let zelf = Self::mapping_downcast(mapping);
985-
if let Some(value) = value {
986-
Self::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
987-
} else {
988-
Err(vm.new_type_error("cannot delete memory".to_owned()))
989-
}
990-
}),
991-
};
977+
fn as_mapping() -> &'static PyMappingMethods {
978+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
979+
length: atomic_func!(|mapping, vm| PyMemoryView::mapping_downcast(mapping).len(vm)),
980+
subscript: atomic_func!(|mapping, needle, vm| {
981+
let zelf = PyMemoryView::mapping_downcast(mapping);
982+
PyMemoryView::getitem(zelf.to_owned(), needle.to_owned(), vm)
983+
}),
984+
ass_subscript: atomic_func!(|mapping, needle, value, vm| {
985+
let zelf = PyMemoryView::mapping_downcast(mapping);
986+
if let Some(value) = value {
987+
PyMemoryView::setitem(zelf.to_owned(), needle.to_owned(), value, vm)
988+
} else {
989+
Err(vm.new_type_error("cannot delete memory".to_owned()))
990+
}
991+
}),
992+
};
993+
&AS_MAPPING
994+
}
992995
}
993996

994997
impl AsSequence for PyMemoryView {

vm/src/builtins/range.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -398,13 +398,18 @@ impl PyRange {
398398
}
399399

400400
impl AsMapping for PyRange {
401-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
402-
length: Some(|mapping, vm| Self::mapping_downcast(mapping).protocol_length(vm)),
403-
subscript: Some(|mapping, needle, vm| {
404-
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
405-
}),
406-
ass_subscript: None,
407-
};
401+
fn as_mapping() -> &'static PyMappingMethods {
402+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
403+
length: atomic_func!(
404+
|mapping, vm| PyRange::mapping_downcast(mapping).protocol_length(vm)
405+
),
406+
subscript: atomic_func!(|mapping, needle, vm| {
407+
PyRange::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
408+
}),
409+
..PyMappingMethods::NOT_IMPLEMENTED
410+
};
411+
&AS_MAPPING
412+
}
408413
}
409414

410415
impl AsSequence for PyRange {

vm/src/builtins/str.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1311,11 +1311,16 @@ impl Iterable for PyStr {
13111311
}
13121312

13131313
impl AsMapping for PyStr {
1314-
const AS_MAPPING: PyMappingMethods = PyMappingMethods {
1315-
length: Some(|mapping, _vm| Ok(Self::mapping_downcast(mapping).len())),
1316-
subscript: Some(|mapping, needle, vm| Self::mapping_downcast(mapping)._getitem(needle, vm)),
1317-
ass_subscript: None,
1318-
};
1314+
fn as_mapping() -> &'static PyMappingMethods {
1315+
static AS_MAPPING: PyMappingMethods = PyMappingMethods {
1316+
length: atomic_func!(|mapping, _vm| Ok(PyStr::mapping_downcast(mapping).len())),
1317+
subscript: atomic_func!(
1318+
|mapping, needle, vm| PyStr::mapping_downcast(mapping)._getitem(needle, vm)
1319+
),
1320+
..PyMappingMethods::NOT_IMPLEMENTED
1321+
};
1322+
&AS_MAPPING
1323+
}
13191324
}
13201325

13211326
impl AsSequence for PyStr {

0 commit comments

Comments
 (0)