pyo3/conversions/std/
string.rsuse std::borrow::Cow;
#[cfg(feature = "experimental-inspect")]
use crate::inspect::types::TypeInfo;
use crate::{
instance::Bound,
types::{any::PyAnyMethods, string::PyStringMethods, PyString},
FromPyObject, IntoPy, Py, PyAny, PyObject, PyResult, Python, ToPyObject,
};
impl ToPyObject for str {
#[inline]
fn to_object(&self, py: Python<'_>) -> PyObject {
PyString::new_bound(py, self).into()
}
}
impl<'a> IntoPy<PyObject> for &'a str {
#[inline]
fn into_py(self, py: Python<'_>) -> PyObject {
PyString::new_bound(py, self).into()
}
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
<String>::type_output()
}
}
impl<'a> IntoPy<Py<PyString>> for &'a str {
#[inline]
fn into_py(self, py: Python<'_>) -> Py<PyString> {
PyString::new_bound(py, self).into()
}
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
<String>::type_output()
}
}
impl ToPyObject for Cow<'_, str> {
#[inline]
fn to_object(&self, py: Python<'_>) -> PyObject {
PyString::new_bound(py, self).into()
}
}
impl IntoPy<PyObject> for Cow<'_, str> {
#[inline]
fn into_py(self, py: Python<'_>) -> PyObject {
self.to_object(py)
}
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
<String>::type_output()
}
}
impl ToPyObject for String {
#[inline]
fn to_object(&self, py: Python<'_>) -> PyObject {
PyString::new_bound(py, self).into()
}
}
impl ToPyObject for char {
fn to_object(&self, py: Python<'_>) -> PyObject {
self.into_py(py)
}
}
impl IntoPy<PyObject> for char {
fn into_py(self, py: Python<'_>) -> PyObject {
let mut bytes = [0u8; 4];
PyString::new_bound(py, self.encode_utf8(&mut bytes)).into()
}
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
<String>::type_output()
}
}
impl IntoPy<PyObject> for String {
fn into_py(self, py: Python<'_>) -> PyObject {
PyString::new_bound(py, &self).into()
}
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
TypeInfo::builtin("str")
}
}
impl<'a> IntoPy<PyObject> for &'a String {
#[inline]
fn into_py(self, py: Python<'_>) -> PyObject {
PyString::new_bound(py, self).into()
}
#[cfg(feature = "experimental-inspect")]
fn type_output() -> TypeInfo {
<String>::type_output()
}
}
#[cfg(feature = "gil-refs")]
impl<'py> FromPyObject<'py> for &'py str {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
ob.clone().into_gil_ref().downcast::<PyString>()?.to_str()
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
<String as crate::FromPyObject>::type_input()
}
}
#[cfg(all(not(feature = "gil-refs"), any(Py_3_10, not(Py_LIMITED_API))))]
impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for &'a str {
fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult<Self> {
ob.downcast::<PyString>()?.to_str()
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
<String as crate::FromPyObject>::type_input()
}
}
#[cfg(feature = "gil-refs")]
impl<'py> FromPyObject<'py> for Cow<'py, str> {
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
ob.extract().map(Cow::Owned)
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
<String as crate::FromPyObject>::type_input()
}
}
#[cfg(not(feature = "gil-refs"))]
impl<'a> crate::conversion::FromPyObjectBound<'a, '_> for Cow<'a, str> {
fn from_py_object_bound(ob: crate::Borrowed<'a, '_, PyAny>) -> PyResult<Self> {
ob.downcast::<PyString>()?.to_cow()
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
<String as crate::FromPyObject>::type_input()
}
}
impl FromPyObject<'_> for String {
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
obj.downcast::<PyString>()?.to_cow().map(Cow::into_owned)
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
Self::type_output()
}
}
impl FromPyObject<'_> for char {
fn extract_bound(obj: &Bound<'_, PyAny>) -> PyResult<Self> {
let s = obj.downcast::<PyString>()?.to_cow()?;
let mut iter = s.chars();
if let (Some(ch), None) = (iter.next(), iter.next()) {
Ok(ch)
} else {
Err(crate::exceptions::PyValueError::new_err(
"expected a string of length 1",
))
}
}
#[cfg(feature = "experimental-inspect")]
fn type_input() -> TypeInfo {
<String>::type_input()
}
}
#[cfg(test)]
mod tests {
use crate::types::any::PyAnyMethods;
use crate::Python;
use crate::{IntoPy, PyObject, ToPyObject};
use std::borrow::Cow;
#[test]
fn test_cow_into_py() {
Python::with_gil(|py| {
let s = "Hello Python";
let py_string: PyObject = Cow::Borrowed(s).into_py(py);
assert_eq!(s, py_string.extract::<Cow<'_, str>>(py).unwrap());
let py_string: PyObject = Cow::<str>::Owned(s.into()).into_py(py);
assert_eq!(s, py_string.extract::<Cow<'_, str>>(py).unwrap());
})
}
#[test]
fn test_cow_to_object() {
Python::with_gil(|py| {
let s = "Hello Python";
let py_string = Cow::Borrowed(s).to_object(py);
assert_eq!(s, py_string.extract::<Cow<'_, str>>(py).unwrap());
let py_string = Cow::<str>::Owned(s.into()).to_object(py);
assert_eq!(s, py_string.extract::<Cow<'_, str>>(py).unwrap());
})
}
#[test]
fn test_non_bmp() {
Python::with_gil(|py| {
let s = "\u{1F30F}";
let py_string = s.to_object(py);
assert_eq!(s, py_string.extract::<String>(py).unwrap());
})
}
#[test]
fn test_extract_str() {
Python::with_gil(|py| {
let s = "Hello Python";
let py_string = s.to_object(py);
let s2: Cow<'_, str> = py_string.bind(py).extract().unwrap();
assert_eq!(s, s2);
})
}
#[test]
fn test_extract_char() {
Python::with_gil(|py| {
let ch = '😃';
let py_string = ch.to_object(py);
let ch2: char = py_string.bind(py).extract().unwrap();
assert_eq!(ch, ch2);
})
}
#[test]
fn test_extract_char_err() {
Python::with_gil(|py| {
let s = "Hello Python";
let py_string = s.to_object(py);
let err: crate::PyResult<char> = py_string.bind(py).extract();
assert!(err
.unwrap_err()
.to_string()
.contains("expected a string of length 1"));
})
}
#[test]
fn test_string_into_py() {
Python::with_gil(|py| {
let s = "Hello Python";
let s2 = s.to_owned();
let s3 = &s2;
assert_eq!(
s,
IntoPy::<PyObject>::into_py(s3, py)
.extract::<Cow<'_, str>>(py)
.unwrap()
);
assert_eq!(
s,
IntoPy::<PyObject>::into_py(s2, py)
.extract::<Cow<'_, str>>(py)
.unwrap()
);
assert_eq!(
s,
IntoPy::<PyObject>::into_py(s, py)
.extract::<Cow<'_, str>>(py)
.unwrap()
);
})
}
}