mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
move obj_as to sequence_downcast
This commit is contained in:
committed by
Jeong YunWon
parent
994c0be479
commit
0abe90dd0a
@@ -765,21 +765,21 @@ impl AsSequence for PyByteArray {
|
||||
|
||||
impl PyByteArray {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
concat: Some(|seq, other, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.inner()
|
||||
.concat(other, vm)
|
||||
.map(|x| PyByteArray::from(x).into_object(vm))
|
||||
}),
|
||||
repeat: Some(|seq, n, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.mul(n as isize, vm)
|
||||
.map(|x| x.into_object(vm))
|
||||
}),
|
||||
item: Some(|seq, i, vm| seq.obj_as::<Self>().inner().item(i, vm)),
|
||||
item: Some(|seq, i, vm| Self::sequence_downcast(seq).inner().item(i, vm)),
|
||||
ass_item: Some(|seq, i, value, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
if let Some(value) = value {
|
||||
zelf.setitem_by_idx(i, value, vm)
|
||||
} else {
|
||||
@@ -788,15 +788,15 @@ impl PyByteArray {
|
||||
}),
|
||||
contains: Some(|seq, other, vm| {
|
||||
let other = <Either<PyBytesInner, PyIntRef>>::try_from_object(vm, other.to_owned())?;
|
||||
seq.obj_as::<Self>().contains(other, vm)
|
||||
Self::sequence_downcast(seq).contains(other, vm)
|
||||
}),
|
||||
inplace_concat: Some(|seq, other, vm| {
|
||||
let other = ArgBytesLike::try_from_object(vm, other.to_owned())?;
|
||||
let zelf = seq.obj_as::<Self>().to_owned();
|
||||
let zelf = Self::sequence_downcast(seq).to_owned();
|
||||
Self::iadd(zelf, other, vm).map(|x| x.into())
|
||||
}),
|
||||
inplace_repeat: Some(|seq, n, vm| {
|
||||
let zelf = seq.obj_as::<Self>().to_owned();
|
||||
let zelf = Self::sequence_downcast(seq).to_owned();
|
||||
Self::imul(zelf, n as isize, vm).map(|x| x.into())
|
||||
}),
|
||||
};
|
||||
|
||||
@@ -580,18 +580,23 @@ impl AsSequence for PyBytes {
|
||||
|
||||
impl PyBytes {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
concat: Some(|seq, other, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.inner
|
||||
.concat(other, vm)
|
||||
.map(|x| vm.ctx.new_bytes(x).into())
|
||||
}),
|
||||
repeat: Some(|seq, n, vm| Ok(vm.ctx.new_bytes(seq.obj_as::<Self>().repeat(n)).into())),
|
||||
item: Some(|seq, i, vm| seq.obj_as::<Self>().inner.item(i, vm)),
|
||||
repeat: Some(|seq, n, vm| {
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_bytes(Self::sequence_downcast(seq).repeat(n))
|
||||
.into())
|
||||
}),
|
||||
item: Some(|seq, i, vm| Self::sequence_downcast(seq).inner.item(i, vm)),
|
||||
contains: Some(|seq, other, vm| {
|
||||
let other = <Either<PyBytesInner, PyIntRef>>::try_from_object(vm, other.to_owned())?;
|
||||
seq.obj_as::<Self>().contains(other, vm)
|
||||
Self::sequence_downcast(seq).contains(other, vm)
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
|
||||
@@ -465,7 +465,7 @@ impl AsSequence for PyDict {
|
||||
|
||||
impl PyDict {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
contains: Some(|seq, target, vm| seq.obj_as::<Self>().entries.contains(vm, target)),
|
||||
contains: Some(|seq, target, vm| Self::sequence_downcast(seq).entries.contains(vm, target)),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
@@ -1029,8 +1029,13 @@ impl AsSequence for PyDictKeys {
|
||||
}
|
||||
impl PyDictKeys {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
contains: Some(|seq, target, vm| seq.obj_as::<Self>().dict.entries.contains(vm, target)),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
contains: Some(|seq, target, vm| {
|
||||
Self::sequence_downcast(seq)
|
||||
.dict
|
||||
.entries
|
||||
.contains(vm, target)
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
@@ -1081,8 +1086,13 @@ impl AsSequence for PyDictItems {
|
||||
}
|
||||
impl PyDictItems {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
contains: Some(|seq, target, vm| seq.obj_as::<Self>().dict.entries.contains(vm, target)),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
contains: Some(|seq, target, vm| {
|
||||
Self::sequence_downcast(seq)
|
||||
.dict
|
||||
.entries
|
||||
.contains(vm, target)
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
@@ -1101,7 +1111,7 @@ impl AsSequence for PyDictValues {
|
||||
}
|
||||
impl PyDictValues {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -404,20 +404,24 @@ impl AsSequence for PyList {
|
||||
}
|
||||
impl PyList {
|
||||
const SEQUENCE_METHDOS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
concat: Some(|seq, other, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.concat(other, vm)
|
||||
.map(|x| x.into_object())
|
||||
}),
|
||||
repeat: Some(|seq, n, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.mul(n as isize, vm)
|
||||
.map(|x| x.into_object())
|
||||
}),
|
||||
item: Some(|seq, i, vm| seq.obj_as::<Self>().borrow_vec().get_item_by_index(vm, i)),
|
||||
item: Some(|seq, i, vm| {
|
||||
Self::sequence_downcast(seq)
|
||||
.borrow_vec()
|
||||
.get_item_by_index(vm, i)
|
||||
}),
|
||||
ass_item: Some(|seq, i, value, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
if let Some(value) = value {
|
||||
zelf.borrow_vec_mut().set_item_by_index(vm, i, value)
|
||||
} else {
|
||||
@@ -425,19 +429,18 @@ impl PyList {
|
||||
}
|
||||
}),
|
||||
contains: Some(|seq, target, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf.mut_contains(vm, target)
|
||||
}),
|
||||
inplace_concat: Some(|seq, other, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
Ok(Self::inplace_concat(zelf, other, vm))
|
||||
}),
|
||||
inplace_repeat: Some(|seq, n, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf.borrow_vec_mut().imul(vm, n as isize)?;
|
||||
Ok(zelf.to_owned().into_object())
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -189,7 +189,7 @@ impl AsSequence for PyMappingProxy {
|
||||
|
||||
impl PyMappingProxy {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
contains: Some(|seq, target, vm| seq.obj_as::<Self>()._contains(target, vm)),
|
||||
contains: Some(|seq, target, vm| Self::sequence_downcast(seq)._contains(target, vm)),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -991,12 +991,12 @@ impl AsSequence for PyMemoryView {
|
||||
impl PyMemoryView {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf.try_not_released(vm)?;
|
||||
zelf.len(vm)
|
||||
}),
|
||||
item: Some(|seq, i, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf.try_not_released(vm)?;
|
||||
zelf.getitem_by_idx(i, vm)
|
||||
}),
|
||||
|
||||
@@ -1298,21 +1298,21 @@ impl AsSequence for PyStr {
|
||||
|
||||
impl PyStr {
|
||||
const SEQUENCE_METHDOS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
concat: Some(|seq, other, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
Self::add(zelf.to_owned(), other.to_owned(), vm)
|
||||
}),
|
||||
repeat: Some(|seq, n, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
Self::mul(zelf.to_owned(), n as isize, vm).map(|x| x.into())
|
||||
}),
|
||||
item: Some(|seq, i, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf.get_item_by_index(vm, i)
|
||||
.map(|x| zelf.new_substr(x.to_string()).into_ref(vm).into())
|
||||
}),
|
||||
contains: Some(|seq, needle, vm| seq.obj_as::<Self>()._contains(needle, vm)),
|
||||
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq)._contains(needle, vm)),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -379,22 +379,36 @@ impl PyRange {
|
||||
}
|
||||
|
||||
impl PyRange {
|
||||
fn protocol_length(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.len()
|
||||
.to_isize()
|
||||
.ok_or_else(|| {
|
||||
vm.new_overflow_error("RustPython int too large to convert to C ssize_t".to_owned())
|
||||
})
|
||||
.map(|x| x as usize)
|
||||
}
|
||||
|
||||
const MAPPING_METHODS: PyMappingMethods = PyMappingMethods {
|
||||
length: Some(|mapping, vm| {
|
||||
Self::mapping_downcast(mapping)
|
||||
.len()
|
||||
.to_usize()
|
||||
.ok_or_else(|| {
|
||||
vm.new_overflow_error(
|
||||
"RustPython int too large to convert to C ssize_t".to_owned(),
|
||||
)
|
||||
})
|
||||
}),
|
||||
length: Some(|mapping, vm| Self::mapping_downcast(mapping).protocol_length(vm)),
|
||||
subscript: Some(|mapping, needle, vm| {
|
||||
Self::mapping_downcast(mapping).getitem(needle.to_owned(), vm)
|
||||
}),
|
||||
ass_subscript: None,
|
||||
};
|
||||
|
||||
const SEQUENCE_METHDOS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, vm| Self::sequence_downcast(seq).protocol_length(vm)),
|
||||
item: Some(|seq, i, vm| {
|
||||
Self::sequence_downcast(seq)
|
||||
.get(&i.into())
|
||||
.map(|x| PyInt::from(x).into_ref(vm).into())
|
||||
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))
|
||||
}),
|
||||
contains: Some(|seq, needle, vm| {
|
||||
Ok(Self::sequence_downcast(seq).contains(needle.to_owned(), vm))
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
impl AsMapping for PyRange {
|
||||
@@ -412,30 +426,6 @@ impl AsSequence for PyRange {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyRange {
|
||||
const SEQUENCE_METHDOS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
.len()
|
||||
.to_isize()
|
||||
.ok_or_else(|| {
|
||||
vm.new_overflow_error(
|
||||
"RustPython int too large to convert to C ssize_t".to_owned(),
|
||||
)
|
||||
})
|
||||
.map(|x| x as usize)
|
||||
}),
|
||||
item: Some(|seq, i, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
.get(&i.into())
|
||||
.map(|x| PyInt::from(x).into_ref(vm).into())
|
||||
.ok_or_else(|| vm.new_index_error("index out of range".to_owned()))
|
||||
}),
|
||||
contains: Some(|seq, needle, vm| Ok(seq.obj_as::<Self>().contains(needle.to_owned(), vm))),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
impl Hashable for PyRange {
|
||||
fn hash(zelf: &crate::PyObjectView<Self>, vm: &VirtualMachine) -> PyResult<PyHash> {
|
||||
let length = zelf.compute_length();
|
||||
|
||||
@@ -665,8 +665,8 @@ impl AsSequence for PySet {
|
||||
|
||||
impl PySet {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
contains: Some(|seq, needle, vm| seq.obj_as::<Self>().inner.contains(needle, vm)),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq).inner.contains(needle, vm)),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
@@ -905,8 +905,8 @@ impl AsSequence for PyFrozenSet {
|
||||
|
||||
impl PyFrozenSet {
|
||||
const SEQUENCE_METHODS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
contains: Some(|seq, needle, vm| seq.obj_as::<Self>().inner.contains(needle, vm)),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq).inner.contains(needle, vm)),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -340,9 +340,9 @@ impl AsSequence for PyTuple {
|
||||
|
||||
impl PyTuple {
|
||||
const SEQUENCE_METHDOS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
concat: Some(|seq, other, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
match Self::add(zelf.to_owned(), other.to_owned(), vm) {
|
||||
PyArithmeticValue::Implemented(tuple) => Ok(tuple.into()),
|
||||
PyArithmeticValue::NotImplemented => Err(vm.new_type_error(format!(
|
||||
@@ -352,15 +352,15 @@ impl PyTuple {
|
||||
}
|
||||
}),
|
||||
repeat: Some(|seq, n, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
Self::mul(zelf.to_owned(), n as isize, vm).map(|x| x.into())
|
||||
}),
|
||||
item: Some(|seq, i, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf.elements.get_item_by_index(vm, i)
|
||||
}),
|
||||
contains: Some(|seq, needle, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf._contains(needle, vm)
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
|
||||
@@ -8,8 +8,8 @@ use crate::{
|
||||
common::lock::OnceCell,
|
||||
function::IntoPyObject,
|
||||
protocol::PyMapping,
|
||||
IdProtocol, PyArithmeticValue, PyObject, PyObjectPayload, PyObjectRef, PyObjectView, PyResult,
|
||||
PyValue, TypeProtocol, VirtualMachine,
|
||||
IdProtocol, PyArithmeticValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
|
||||
VirtualMachine,
|
||||
};
|
||||
|
||||
// Sequence Protocol
|
||||
@@ -84,10 +84,6 @@ impl<'a> PySequence<'a> {
|
||||
}
|
||||
|
||||
impl PySequence<'_> {
|
||||
pub fn obj_as<T: PyObjectPayload>(&self) -> &PyObjectView<T> {
|
||||
unsafe { self.obj.downcast_unchecked_ref::<T>() }
|
||||
}
|
||||
|
||||
// PySequence_Check
|
||||
pub fn check(&self, vm: &VirtualMachine) -> bool {
|
||||
self.methods(vm).item.is_some()
|
||||
|
||||
@@ -521,37 +521,36 @@ mod _collections {
|
||||
|
||||
impl PyDeque {
|
||||
const SEQUENCE_METHDOS: PySequenceMethods = PySequenceMethods {
|
||||
length: Some(|seq, _vm| Ok(seq.obj_as::<Self>().len())),
|
||||
length: Some(|seq, _vm| Ok(Self::sequence_downcast(seq).len())),
|
||||
concat: Some(|seq, other, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.concat(other, vm)
|
||||
.map(|x| x.into_ref(vm).into())
|
||||
}),
|
||||
repeat: Some(|seq, n, vm| {
|
||||
seq.obj_as::<Self>()
|
||||
Self::sequence_downcast(seq)
|
||||
.mul(n as isize, vm)
|
||||
.map(|x| x.into_ref(vm).into())
|
||||
}),
|
||||
item: Some(|seq, i, vm| seq.obj_as::<Self>().getitem(i, vm)),
|
||||
item: Some(|seq, i, vm| Self::sequence_downcast(seq).getitem(i, vm)),
|
||||
ass_item: Some(|seq, i, value, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
if let Some(value) = value {
|
||||
zelf.setitem(i, value, vm)
|
||||
} else {
|
||||
zelf.delitem(i, vm)
|
||||
}
|
||||
}),
|
||||
contains: Some(|seq, needle, vm| seq.obj_as::<Self>()._contains(needle, vm)),
|
||||
contains: Some(|seq, needle, vm| Self::sequence_downcast(seq)._contains(needle, vm)),
|
||||
inplace_concat: Some(|seq, other, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
zelf._extend(other, vm)?;
|
||||
Ok(zelf.to_owned().into())
|
||||
}),
|
||||
inplace_repeat: Some(|seq, n, vm| {
|
||||
let zelf = seq.obj_as::<Self>();
|
||||
let zelf = Self::sequence_downcast(seq);
|
||||
Self::imul(zelf.to_owned(), n as isize, vm).map(|x| x.into())
|
||||
}),
|
||||
..*PySequenceMethods::not_implemented()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
pub use crate::builtins::object::{generic_getattr, generic_setattr};
|
||||
use crate::common::{hash::PyHash, lock::PyRwLock};
|
||||
use crate::function::IntoPyObject;
|
||||
use crate::protocol::PySequenceMethods;
|
||||
use crate::protocol::{PySequence, PySequenceMethods};
|
||||
use crate::{
|
||||
builtins::{PyInt, PyStrRef, PyType, PyTypeRef},
|
||||
function::{FromArgs, FuncArgs, IntoPyResult, OptionalArg},
|
||||
@@ -843,10 +843,15 @@ pub trait AsSequence: PyValue {
|
||||
let zelf = unsafe { zelf.downcast_unchecked_ref::<Self>() };
|
||||
Self::as_sequence(zelf, vm)
|
||||
}
|
||||
|
||||
fn as_sequence(
|
||||
zelf: &PyObjectView<Self>,
|
||||
vm: &VirtualMachine,
|
||||
) -> Cow<'static, PySequenceMethods>;
|
||||
|
||||
fn sequence_downcast<'a>(seq: &'a PySequence) -> &'a PyObjectView<Self> {
|
||||
unsafe { seq.obj.downcast_unchecked_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
|
||||
Reference in New Issue
Block a user