pymethods: add support for inplace concat & repeat

This commit is contained in:
David Hewitt 2022-02-23 08:03:43 +00:00
parent 253507b5dd
commit 424644181b
3 changed files with 41 additions and 1 deletions

View File

@ -243,6 +243,18 @@ and `Return` a final value - see its docs for further details and an example.
Used by the `*` operator, after trying the numeric multiplication via
the `__mul__` and `__rmul__` methods.
* `fn __inplace_concat__(&self, other: impl FromPyObject) -> PyResult<impl ToPyObject>`
Concatenates two sequences.
Used by the `+=` operator, after trying the numeric addition via
the `__iadd__` method.
* `fn __inplace_repeat__(&self, count: isize) -> PyResult<impl ToPyObject>`
Concatenates two sequences.
Used by the `*=` operator, after trying the numeric multiplication via
the `__imul__` method.
### Descriptors

View File

@ -53,6 +53,12 @@ impl PyMethodKind {
"__contains__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CONTAINS__)),
"__concat__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__CONCAT__)),
"__repeat__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__REPEAT__)),
"__inplace_concat__" => {
PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INPLACE_CONCAT__))
}
"__inplace_repeat__" => {
PyMethodKind::Proto(PyMethodProtoKind::Slot(&__INPLACE_REPEAT__))
}
"__getitem__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__GETITEM__)),
"__pos__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__POS__)),
"__neg__" => PyMethodKind::Proto(PyMethodProtoKind::Slot(&__NEG__)),
@ -606,6 +612,10 @@ const __CONTAINS__: SlotDef = SlotDef::new("Py_sq_contains", "objobjproc")
.ret_ty(Ty::Int);
const __CONCAT__: SlotDef = SlotDef::new("Py_sq_concat", "binaryfunc").arguments(&[Ty::Object]);
const __REPEAT__: SlotDef = SlotDef::new("Py_sq_repeat", "ssizeargfunc").arguments(&[Ty::PySsizeT]);
const __INPLACE_CONCAT__: SlotDef =
SlotDef::new("Py_sq_concat", "binaryfunc").arguments(&[Ty::Object]);
const __INPLACE_REPEAT__: SlotDef =
SlotDef::new("Py_sq_repeat", "ssizeargfunc").arguments(&[Ty::PySsizeT]);
const __GETITEM__: SlotDef = SlotDef::new("Py_mp_subscript", "binaryfunc").arguments(&[Ty::Object]);
const __POS__: SlotDef = SlotDef::new("Py_nb_positive", "unaryfunc");

View File

@ -66,12 +66,17 @@ impl ByteSequence {
}
}
fn __concat__(&self, other: PyRef<Self>) -> Self {
fn __concat__(&self, other: &Self) -> Self {
let mut elements = self.elements.clone();
elements.extend_from_slice(&other.elements);
Self { elements }
}
fn __inplace_concat__(mut slf: PyRefMut<Self>, other: &Self) -> Py<Self> {
slf.elements.extend_from_slice(&other.elements);
slf.into()
}
fn __repeat__(&self, count: isize) -> PyResult<Self> {
if count >= 0 {
let mut elements = Vec::with_capacity(self.elements.len() * count as usize);
@ -83,6 +88,19 @@ impl ByteSequence {
Err(PyValueError::new_err("invalid repeat count"))
}
}
fn __inplace_repeat__(mut slf: PyRefMut<Self>, count: isize) -> PyResult<Py<Self>> {
if count >= 0 {
let mut elements = Vec::with_capacity(slf.elements.len() * count as usize);
for _ in 0..count {
elements.extend(&slf.elements);
}
slf.elements = elements;
Ok(slf.into())
} else {
Err(PyValueError::new_err("invalid repeat count"))
}
}
}
/// Return a dict with `s = ByteSequence([1, 2, 3])`.