mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 16:02:18 +00:00
* chore: improve release pipeline * fix pipelines * fix sccache * update workflows * fix workflow * update workflow * remove sccache and cross * bring back sccache * fix pipelines * fix nodejs build * fix pipelines * move python to abi3 for future proofing * fix workflow ordering bug * gate releases via environment - configure go via release * set release as 1.0.0-beta
72 lines
2.3 KiB
Rust
72 lines
2.3 KiB
Rust
use anyhow::Context;
|
|
use pyo3::prelude::{PyAnyMethods, PyBytesMethods, PyDictMethods, PyListMethods, PyStringMethods};
|
|
use pyo3::types::{PyBytes, PyDict, PyList, PyString};
|
|
use pyo3::{Bound, FromPyObject, IntoPyObject, IntoPyObjectExt, PyAny, PyErr, PyResult, Python};
|
|
use pythonize::depythonize;
|
|
use serde_json::Value;
|
|
|
|
#[repr(transparent)]
|
|
#[derive(Clone, Debug)]
|
|
pub struct PyValue(pub Value);
|
|
|
|
pub fn value_to_object<'py>(py: Python<'py>, val: &Value) -> PyResult<Bound<'py, PyAny>> {
|
|
match val {
|
|
Value::Null => py.None().into_bound_py_any(py),
|
|
Value::Bool(b) => b.into_bound_py_any(py),
|
|
Value::Number(n) => {
|
|
let oi64 = n.as_i64().map(|i| i.into_bound_py_any(py));
|
|
let ou64 = n.as_u64().map(|i| i.into_bound_py_any(py));
|
|
let of64 = n.as_f64().map(|i| i.into_bound_py_any(py));
|
|
oi64.or(ou64).or(of64).expect("number too large")
|
|
}
|
|
Value::String(s) => s.into_bound_py_any(py),
|
|
Value::Array(v) => {
|
|
let list = PyList::empty(py);
|
|
for item in v {
|
|
list.append(value_to_object(py, item)?)?;
|
|
}
|
|
|
|
list.into_bound_py_any(py)
|
|
}
|
|
Value::Object(m) => {
|
|
let dict = PyDict::new(py);
|
|
for (key, value) in m {
|
|
dict.set_item(key, value_to_object(py, value)?)?;
|
|
}
|
|
|
|
dict.into_bound_py_any(py)
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'py> IntoPyObject<'py> for PyValue {
|
|
type Target = PyAny;
|
|
type Output = Bound<'py, PyAny>;
|
|
type Error = PyErr;
|
|
|
|
fn into_pyobject(self, py: Python<'py>) -> Result<Self::Output, Self::Error> {
|
|
value_to_object(py, &self.0)
|
|
}
|
|
}
|
|
|
|
impl<'py> FromPyObject<'py> for PyValue {
|
|
fn extract_bound(ob: &Bound<'py, PyAny>) -> PyResult<Self> {
|
|
if let Ok(s) = ob.downcast::<PyString>() {
|
|
let str_slice = s.to_cow()?;
|
|
|
|
let var = serde_json::from_str(&str_slice).context("Invalid JSON")?;
|
|
return Ok(PyValue(var));
|
|
}
|
|
|
|
if let Ok(b) = ob.downcast::<PyBytes>() {
|
|
let bytes = b.as_bytes();
|
|
|
|
let var = serde_json::from_slice(bytes).context("Invalid JSON")?;
|
|
return Ok(PyValue(var));
|
|
}
|
|
|
|
let var = depythonize(ob)?;
|
|
Ok(PyValue(var))
|
|
}
|
|
}
|