Closed
Description
Just wanted to ask: New versions of Python have added support for pattern matching (PEP 622):
def make_point_3d(pt):
match pt:
case (x, y):
return Point3d(x, y, 0)
case (x, y, z):
return Point3d(x, y, z)
case Point2d(x, y):
return Point3d(x, y, 0)
case Point3d(_, _, _):
return pt
case _:
raise TypeError("not a point we support")
Would it be possible to extend Pyo3 to support #[derive(FromPyObject)]
for Rust enums, so that Rust can work natively with these Python enums? According to the specification, all that needs to be done is that the Python interpreter tries to look for new functions
Right now I am emulating this behaviour by having a struct with #[repr(transparent)]
and a function to create the case:
#[repr(C, u8)]
enum Point {
CaseA(PointCaseA),
CaseB(PointCaseB),
}
#[pyclass]
#[repr(C)]
struct PointCaseA {
x: f32,
y: f32,
}
#[pyclass]
#[repr(C)]
struct PointCaseB {
x: f32,
y: f32,
z: f32,
}
#[pyclass]
#[pyo3(name = "Point")]
#[repr(transparent)]
struct PointWrapper {
_0: Point,
}
#[pymethods]
impl PointWrapper {
// not the exact code, just pseudocode
pub fn destructure(&self) -> (&'static str, PyObject) {
let casted: &Point = unsafe { mem::transmute(&self) };
match casted {
CaseA(x, y) => ("CaseA", PyObject::Tuple(&[x, y]),
CaseB(x, y, z) => ("CaseB", PyObject::Tuple(&[x, y, z]),
}
}
}
def make_point_3d(pt): # pt = object created by Rust
tag, payload = pt.destructure()
if tag == "CaseA":
return Point3d(payload.x, payload.y, 0)
elif tag == "CaseB":
return Point3d(payload.x, payload.y, payload.z)
else:
raise TypeError("not a point we support")
It's not a very high priority, but it would be nice to have. Just wanted to ask if the PyO3 team is aware of this PEP.