pyo3_utils/py_match.rs
1//! When you want to expose an **state machine** enum to Python,
2//! you should implement the trait in this module.
3//!
4//! # Tips
5//!
6//! In most cases, `enum` is just like Python's `Union` type, rather than a state machine.
7//! For such cases, you can directly return the matched `FooEnum`,
8//! without creating a newtype `struct Foo(third_party::Foo)`.
9//!
10//! # Example:
11/*!
12```rust
13use pyo3::prelude::*;
14use pyo3_utils::py_match::PyMatchRef;
15
16mod third_party {
17 pub enum Foo {
18 A { a: i32 },
19 }
20}
21
22#[pyclass(frozen)]
23#[non_exhaustive]
24enum FooEnum {
25 A { a: i32 },
26}
27
28#[pyclass(frozen)]
29#[non_exhaustive]
30struct Foo(third_party::Foo);
31
32impl PyMatchRef for Foo {
33 type Output = FooEnum;
34
35 fn match_ref(&self) -> Self::Output {
36 match &self.0 {
37 third_party::Foo::A { a } => FooEnum::A { a: *a },
38 }
39 }
40}
41
42// In the future, we might provide a macro to automatically generate this pymethod,
43// for now, please do it manually.
44#[pymethods]
45impl Foo {
46 fn match_ref(&self) -> <Self as PyMatchRef>::Output {
47 <Self as PyMatchRef>::match_ref(self)
48 }
49}
50```
51*/
52
53pub trait PyMatchRef {
54 type Output;
55
56 fn match_ref(&self) -> Self::Output;
57}
58
59pub trait PyMatchMut {
60 type Output;
61
62 fn match_mut(&mut self) -> Self::Output;
63}
64
65/// It is recommended to implement this trait only when using `clone` in [PyMatchRef]/[PyMatchMut]
66/// would significantly impact memory/performance.
67pub trait PyMatchInto {
68 type Output;
69
70 fn match_into(self) -> Self::Output;
71}