use std::convert::Infallible;
use crate::{ffi, IntoPy, PyObject, PyResult, Python};
pub trait SomeWrap<T> {
fn wrap(self) -> Option<T>;
}
impl<T> SomeWrap<T> for T {
fn wrap(self) -> Option<T> {
Some(self)
}
}
impl<T> SomeWrap<T> for Option<T> {
fn wrap(self) -> Self {
self
}
}
#[cfg_attr(
diagnostic_namespace,
diagnostic::on_unimplemented(
message = "`{Self}` cannot be converted to a Python object",
note = "`IntoPy` is automatically implemented by the `#[pyclass]` macro",
note = "if you do not wish to have a corresponding Python type, implement `IntoPy` manually",
note = "if you do not own `{Self}` you can perform a manual conversion to one of the types in `pyo3::types::*`"
)
)]
pub trait OkWrap<T> {
type Error;
fn wrap(self) -> Result<T, Self::Error>;
}
impl<T> OkWrap<T> for T
where
T: IntoPy<PyObject>,
{
type Error = Infallible;
#[inline]
fn wrap(self) -> Result<T, Infallible> {
Ok(self)
}
}
impl<T, E> OkWrap<T> for Result<T, E>
where
T: IntoPy<PyObject>,
{
type Error = E;
#[inline]
fn wrap(self) -> Result<T, Self::Error> {
self
}
}
pub fn map_result_into_ptr<T: IntoPy<PyObject>>(
py: Python<'_>,
result: PyResult<T>,
) -> PyResult<*mut ffi::PyObject> {
result.map(|obj| obj.into_py(py).into_ptr())
}
pub fn map_result_into_py<T: IntoPy<PyObject>>(
py: Python<'_>,
result: PyResult<T>,
) -> PyResult<PyObject> {
result.map(|err| err.into_py(py))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn wrap_option() {
let a: Option<u8> = SomeWrap::wrap(42);
assert_eq!(a, Some(42));
let b: Option<u8> = SomeWrap::wrap(None);
assert_eq!(b, None);
}
#[test]
fn wrap_result() {
let a: Result<u8, _> = OkWrap::wrap(42u8);
assert!(matches!(a, Ok(42)));
let b: PyResult<u8> = OkWrap::wrap(Ok(42u8));
assert!(matches!(b, Ok(42)));
let c: Result<u8, &str> = OkWrap::wrap(Err("error"));
assert_eq!(c, Err("error"));
}
}