Macro py_wrap_union_enum

Source
macro_rules! py_wrap_union_enum {
    (@from $name: ident, $rs_enum: ident, $variant_name: ident, $variant: ident $(=> $convert: ty)+) => { ... };
    (@from $name: ident, $rs_enum: ident, $variant_name: ident, $variant: ident) => { ... };
    (@is_variant $self: ident, $rs_enum: ident, $variant: ident ($(=> $_convert: ty)+)) => { ... };
    (@is_variant $self: ident, $rs_enum: ident, $variant: ident) => { ... };
    (
        $(#[$meta: meta])*
        $name: ident($rs_inner: ident) $(as $py_class: literal)? {
            $($variant_name: ident: $variant: ident $($(=> $convert: ty)+)?),+
        }
    ) => { ... };
}
Expand description

Create a newtype wrapper for a Rust enum with unique 1-tuple variants.

§Implements

  • Conversion between the wrapper and the inner enum
  • A Python constructor that creates a new instance from one of the Python variants.
  • A Python function inner() that directly returns the Python version of the variant discriminant (i.e. Discriminant in Enum::Variant(Discriminant)).
  • Python conversion functions:
    • from_x: Like the constructor, but for a specific variant x.
    • is_x: Returns True if the enum is variant x.
    • as_x: Returns the discriminant if the enum is variant x, otherwise None.
    • to_x: Returns the discriminant if the enum is variant x, otherwise raises ValueError.

§Example

use rigetti_pyo3::py_wrap_union_enum;
use rigetti_pyo3::pyo3::prelude::*;
use rigetti_pyo3::pyo3::types::*;
use std::collections::HashSet;

#[derive(Clone)]
pub enum TestEnum {
    Unit,
    String(String),
    Integer(i32),
    UInteger(u32),
    List(Vec<HashSet<String>>),
    Mapping(std::collections::HashMap<String, String>),
}

py_wrap_union_enum! {
    PyTestEnum(TestEnum) as "TestEnum" {
        // Syntax is (1): (2) [=> (3)] [=> (4)] [...], where:
        // 1: The name used in generated methods
        // 2: The name of the Rust enum variant
        // 3: The (Python) type the inner item must convert to (if it has associated data)
        // 4: The (Python) type the type from (3) must convert to, etc.
        unit: Unit,
        // Read as "give the name `string` to variant `String`, which must convert (from
        // a `String`) to a `String` and then to a `Py<PyString>`."
        //
        // That is, `string` is used to generate methods `is_string`, `from_string`, etc.;
        // the first `String` is the name of the variant, not the type (which is elided);
        // the second `String` is the type to convert the elided type into, and `Py<String>` is
        // the final type to convert into.
        //
        // This specifies an unnecessary conversion from String => String to illustrate
        // conversion chaining.
        string: String => String => Py<PyString>,
        int: Integer => Py<PyInt>,
        uint: UInteger => Py<PyInt>,
        list: List => Py<PyList>,
        // Alternatively, in the case of `Vec<T>` where `T` does not have conversion to `PyAny`.
        // list: List => Vec<Py<PySet>> => Py<PyList>,
        // Generates `from_dict`, `is_dict`, `as_dict`, `to_dict`
        dict: Mapping => Py<PyDict>
    }
}