#[macro_export]
macro_rules! py_wrap_error {
($module: ident, $rust: ty, $python: ident, $base: ty) => {
$crate::pyo3::create_exception!($module, $python, $base);
impl $crate::ToPythonError for $rust {
fn to_py_err(self) -> $crate::pyo3::PyErr {
<$python>::new_err(self.to_string())
}
}
};
}
#[macro_export]
macro_rules! py_wrap_type {
(
$(#[$meta: meta])*
$name: ident($from: ty)$(as $py_alias: literal)?$(;)?
) => {
#[repr(transparent)]
#[allow(clippy::use_self)]
#[$crate::pyo3::pyclass$((name = $py_alias))?]
#[derive(Clone)]
$(#[$meta])*
pub struct $name($from);
impl $crate::PyTryFrom<$name> for $from {
fn py_try_from(
py: $crate::pyo3::Python,
item: &$name,
) -> $crate::pyo3::PyResult<Self> {
Ok(item.0.clone())
}
}
impl $crate::PyTryFrom<$crate::pyo3::PyAny> for $name {
fn py_try_from(
py: $crate::pyo3::Python,
item: &$crate::pyo3::PyAny,
) -> $crate::pyo3::PyResult<Self> {
item.extract()
}
}
impl $crate::PyTryFrom<$name> for $name {
fn py_try_from(
py: $crate::pyo3::Python,
item: &$name,
) -> $crate::pyo3::PyResult<Self> {
Ok(item.clone())
}
}
$crate::private_impl_to_python_with_reference!(&self, py, $from => $name {
Ok($name::from(self.clone()))
});
$crate::private_impl_to_python_with_reference!(&self, py, $name => $crate::pyo3::Py<$crate::pyo3::PyAny> {
Ok(<Self as $crate::pyo3::ToPyObject>::to_object(self, py))
});
impl From<$name> for $from {
fn from(wrapper: $name) -> Self {
wrapper.0
}
}
impl From<$from> for $name {
fn from(inner: $from) -> Self {
Self(inner)
}
}
impl From<&$from> for $name {
fn from(inner: &$from) -> Self {
Self(inner.clone())
}
}
impl AsRef<$from> for $name {
fn as_ref(&self) -> &$from {
&self.0
}
}
impl $crate::PyWrapper for $name {
type Inner = $from;
}
impl $crate::pyo3::conversion::ToPyObject for $name {
fn to_object(&self, py: $crate::pyo3::Python) -> $crate::pyo3::PyObject {
#[allow(clippy::use_self)]
const NAME: &'static str = stringify!($name);
let cell = $crate::pyo3::PyCell::new(py, self.clone())
.unwrap_or_else(|err| {
panic!(
"failed to create {} on Python heap: {}",
NAME,
err
)
});
$crate::pyo3::conversion::ToPyObject::to_object(&cell, py)
}
}
};
}
#[macro_export]
macro_rules! py_wrap_simple_enum {
(
$(#[$meta: meta])*
$name: ident($rs_inner: ident) $(as $py_class: literal)? {
$($variant_name: ident),+
}
) => {
#[derive(Copy, Clone)]
#[$crate::pyo3::pyclass$((name = $py_class))?]
$(#[$meta])*
pub enum $name {
$(
$variant_name
),+
}
impl From<$name> for $rs_inner {
fn from(item: $name) -> Self {
match item {
$(
$name::$variant_name => Self::$variant_name,
)+
}
}
}
impl From<&$name> for $rs_inner {
fn from(item: &$name) -> Self {
Self::from(*item)
}
}
impl From<$rs_inner> for $name {
fn from(item: $rs_inner) -> Self {
match item {
$(
$rs_inner::$variant_name => $name::$variant_name,
)+
}
}
}
impl From<&$rs_inner> for $name {
fn from(item: &$rs_inner) -> Self {
Self::from(*item)
}
}
impl $crate::PyWrapper for $name {
type Inner = $rs_inner;
}
impl AsRef<$rs_inner> for $name {
fn as_ref(&self) -> &$rs_inner {
match self {
$(
$name::$variant_name => &$rs_inner::$variant_name,
)+
}
}
}
impl $crate::pyo3::conversion::ToPyObject for $name {
fn to_object(&self, py: $crate::pyo3::Python) -> $crate::pyo3::PyObject {
let cell = $crate::pyo3::PyCell::new(py, self.clone())
.unwrap_or_else(|err| panic!("failed to create {} on Python heap: {}", stringify!($name), err));
cell.to_object(py)
}
}
}
}
#[macro_export]
macro_rules! py_wrap_struct {
(
$(#[$meta: meta])*
$name: ident($rs_from: ty) $(as $py_class: literal)? {
$($py_for_from: ident -> rs {
$($py_ident: ident: $py_src: ty => $rs_dest: ty $to_rs: block),+
},)?
$(rs -> $py_for_to: ident {
$($rs_ident: ident: $rs_src: ty => $py_dest: ty $to_py: block),+
})?
}
) => {
$crate::py_wrap_type! {
$(
#[$meta]
)*
$name($rs_from) $(as $py_class)?;
}
$($(
impl TryFrom<$py_src> for $name {
#[allow(unused_qualifications)]
type Error = pyo3::PyErr;
fn try_from($py_ident: $py_src) -> Result<Self, Self::Error> {
$crate::pyo3::Python::with_gil(|$py_for_from| {
let rust = {
$to_rs
}?;
Ok(Self::from(<$rs_from>::from(rust)))
})
}
}
)+)?
$($(
impl TryFrom<$name> for $py_dest {
#[allow(unused_qualifications)]
type Error = pyo3::PyErr;
fn try_from(outer: $name) -> Result<Self, Self::Error> {
let $rs_ident = $crate::PyWrapper::into_inner(outer);
let $rs_ident: $rs_src = From::from($rs_ident);
$crate::pyo3::Python::with_gil(|$py_for_to| {
$to_py
})
}
}
)+)?
$crate::impl_as_mut_for_wrapper!($name);
#[$crate::pyo3::pymethods]
impl $name {
#![allow(clippy::use_self)]
#[new]
pub fn new(py: $crate::pyo3::Python, input: $crate::pyo3::Py<$crate::pyo3::PyAny>) -> $crate::pyo3::PyResult<Self> {
use $crate::pyo3::FromPyObject;
$($(
if let Ok(item) = input.extract::<$py_src>(py) {
return Self::try_from(item);
}
)+)?
Err($crate::pyo3::exceptions::PyValueError::new_err(
concat!("expected one of:" $($(, " ", std::stringify!($py_src))+)?)
))
}
}
}
}
#[macro_export]
macro_rules! private_ultimate_type {
($type: ty) => { $type };
($type: ty, $($others: ty),+) => { $crate::private_ultimate_type!($($others),+) }
}
#[macro_export]
macro_rules! private_intermediate_to_python {
($py: ident, &$item: ident $(=> $convert: ty)+) => {{
$(
let $item: $convert = $crate::ToPython::<$convert>::to_python(&$item, $py)?;
)+
Ok::<_, $crate::pyo3::PyErr>($item)
}}
}
#[macro_export]
macro_rules! private_intermediate_try_from_python {
($py: ident, &$item: ident => $convert: ty $($(=> $delayed: ty)+)?) => {{
$(let $item: $convert = $crate::private_intermediate_try_from_python!($py, &$item $(=> $delayed)+)?;
let $item = &$item;)?
<_ as $crate::PyTryFrom<$convert>>::py_try_from($py, $item)
}};
}
#[macro_export]
macro_rules! py_wrap_union_enum {
(
$(#[$meta: meta])*
$name: ident($rs_inner: ident) $(as $py_class: literal)? {
$($variant_name: ident: $variant: ident $($(=> $convert: ty)+)?),+
}
) => {
$crate::py_wrap_type! {
$(#[$meta])*
$name($rs_inner) $(as $py_class)?;
}
$crate::impl_as_mut_for_wrapper!($name);
$crate::paste::paste! {
#[$crate::pyo3::pymethods]
impl $name {
#[new]
pub fn new(py: $crate::pyo3::Python, input: &$crate::pyo3::PyAny) -> $crate::pyo3::PyResult<Self> {
$(
$(
if let Ok(inner) = <_ as $crate::PyTryFrom<$crate::pyo3::PyAny>>::py_try_from(py, input) {
let inner = &inner;
let converted = $crate::private_intermediate_try_from_python!(py, &inner $(=> $convert)+);
if let Ok(item) = converted {
return Ok(Self::from($rs_inner::$variant(item)));
}
}
)?
)+
Err($crate::pyo3::exceptions::PyValueError::new_err(
format!(
"could not create {} from {}",
stringify!($name),
input.repr()?
)
))
}
#[allow(unreachable_code, unreachable_pattern)]
pub fn inner(&self, py: $crate::pyo3::Python) -> $crate::pyo3::PyResult<$crate::pyo3::Py<$crate::pyo3::PyAny>> {
match &self.0 {
$(
$($rs_inner::$variant(inner) => {
Ok($crate::pyo3::conversion::IntoPy::<$crate::pyo3::Py<$crate::pyo3::PyAny>>::into_py(
$crate::private_intermediate_to_python!(py, &inner $(=> $convert)+)?,
py,
))
},)?
)+
_ => {
use $crate::pyo3::exceptions::PyRuntimeError;
Err(PyRuntimeError::new_err("Enum variant has no inner data or is unimplemented"))
}
}
}
$(
const fn [< is_ $variant_name >](&self) -> bool {
match &self.0 {
$($rs_inner::$variant(_) => {
let _: Option<$crate::private_ultimate_type!($($convert),+)> = None;
true
},
)?
_ => false
}
}
$(
#[staticmethod]
pub fn [< from_ $variant_name >](py: $crate::pyo3::Python, inner: $crate::private_ultimate_type!($($convert),+)) -> $crate::pyo3::PyResult<Self> {
let inner = &inner;
$crate::private_intermediate_try_from_python!(py, &inner $(=> $convert)+)
.map($rs_inner::$variant)
.map(Self)
}
fn [< as_ $variant_name >](&self, py: $crate::pyo3::Python) -> Option<$crate::private_ultimate_type!($($convert),+)> {
self.[< to_ $variant_name >](py).ok()
}
fn [< to_ $variant_name >](&self, py: $crate::pyo3::Python) -> $crate::pyo3::PyResult<$crate::private_ultimate_type!($($convert),+)> {
if let $rs_inner::$variant(inner) = &self.0 {
$crate::private_intermediate_to_python!(py, &inner $(=> $convert)+)
} else {
Err($crate::pyo3::exceptions::PyValueError::new_err(
concat!("expected self to be a ", stringify!($variant_name))
))
}
}
)?
)+
}
}
}
}
#[macro_export]
macro_rules! wrap_error {
($name: ident ($inner: ty)$(;)?) => {
#[derive(Debug)]
#[repr(transparent)]
pub struct $name($inner);
impl From<$inner> for $name {
fn from(inner: $inner) -> Self {
Self(inner)
}
}
impl From<$name> for $inner {
fn from(outer: $name) -> Self {
outer.0
}
}
impl ::std::fmt::Display for $name {
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
write!(f, "{}", self.0)
}
}
impl ::std::error::Error for $name {}
};
}
#[macro_export]
macro_rules! py_wrap_data_struct {
(
$(#[$meta: meta])*
$name: ident($rs_inner: ty) $(as $class_name: literal)? {
$(
$field_name: ident: $field_rs_type: ty $(=> $convert: ty)+
),+
}
) => {
$crate::py_wrap_type! {
$(
#[$meta]
)*
$name($rs_inner) $(as $class_name)?;
}
$crate::impl_as_mut_for_wrapper!($name);
$crate::paste::paste! {
#[rigetti_pyo3::pyo3::pymethods]
impl $name {
$(
#[getter]
fn [< get_ $field_name >](&self, py: $crate::pyo3::Python<'_>) -> $crate::pyo3::PyResult<$crate::private_ultimate_type!($($convert),+)> {
use $crate::{PyWrapper, ToPython};
let inner = &self.as_inner().$field_name;
$crate::private_intermediate_to_python!(py, &inner $(=> $convert)+)
}
#[setter]
fn [< set_ $field_name >](&mut self, py: $crate::pyo3::Python<'_>, from: $crate::private_ultimate_type!($($convert),+)) -> $crate::pyo3::PyResult<()> {
use $crate::{PyTryFrom, PyWrapperMut};
let from = &from;
let new_val: $field_rs_type = $crate::private_intermediate_try_from_python!(py, &from $(=> $convert)+)?;
self.as_inner_mut().$field_name = new_val;
Ok(())
}
)+
}
}
};
}