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}