pyo3_object_store/
url.rs

1use pyo3::exceptions::PyValueError;
2use pyo3::prelude::*;
3use pyo3::pybacked::PyBackedStr;
4use pyo3::types::PyString;
5use pyo3::FromPyObject;
6use url::Url;
7
8/// A wrapper around [`url::Url`] that implements [`FromPyObject`].
9#[derive(Debug, Clone, PartialEq)]
10pub struct PyUrl(Url);
11
12impl PyUrl {
13    /// Create a new PyUrl from a [Url]
14    pub fn new(url: Url) -> Self {
15        Self(url)
16    }
17
18    /// Consume self and return the underlying [Url]
19    pub fn into_inner(self) -> Url {
20        self.0
21    }
22}
23
24impl<'py> FromPyObject<'_, 'py> for PyUrl {
25    type Error = PyErr;
26
27    fn extract(obj: Borrowed<'_, 'py, PyAny>) -> Result<Self, Self::Error> {
28        let s = obj.extract::<PyBackedStr>()?;
29        let url = Url::parse(&s).map_err(|err| PyValueError::new_err(err.to_string()))?;
30        Ok(Self(url))
31    }
32}
33
34impl<'py> IntoPyObject<'py> for PyUrl {
35    type Target = PyString;
36    type Output = Bound<'py, PyString>;
37    type Error = std::convert::Infallible;
38
39    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
40        Ok(PyString::new(py, self.0.as_str()))
41    }
42}
43
44impl<'py> IntoPyObject<'py> for &PyUrl {
45    type Target = PyString;
46    type Output = Bound<'py, PyString>;
47    type Error = std::convert::Infallible;
48
49    fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
50        Ok(PyString::new(py, self.0.as_str()))
51    }
52}
53
54impl AsRef<Url> for PyUrl {
55    fn as_ref(&self) -> &Url {
56        &self.0
57    }
58}
59
60impl From<PyUrl> for String {
61    fn from(value: PyUrl) -> Self {
62        value.0.into()
63    }
64}