1use std::collections::HashMap;
7
8use pyo3::exceptions::PyTypeError;
9use pyo3::prelude::*;
10use pyo3::types::{PyBool, PyDict, PyFloat, PyInt, PyList, PyNone, PyString};
11use serde_json::{Value, json};
12
13pub fn pyany_to_value(value: &Bound<'_, PyAny>) -> PyResult<Value> {
27 if value.is_instance_of::<PyString>() {
28 Ok(Value::from(value.extract::<String>()?))
29 } else if value.is_instance_of::<PyBool>() {
30 Ok(Value::from(value.extract::<bool>()?))
31 } else if value.is_instance_of::<PyFloat>() {
32 Ok(Value::from(value.extract::<f64>()?))
33 } else if value.is_instance_of::<PyInt>() {
34 Ok(Value::from(value.extract::<i64>()?))
35 } else if value.is_instance_of::<PyList>() {
36 pylist_to_value(&value.extract::<Bound<'_, PyList>>()?)
37 } else if value.is_instance_of::<PyDict>() {
38 pydict_to_value(&value.extract::<Bound<'_, PyDict>>()?)
39 } else if value.is_instance_of::<PyNone>() {
40 Ok(Value::Null)
41 } else {
42 Err(PyErr::new::<PyTypeError, _>(format!(
43 "Unsupported Python object: {value}"
44 )))
45 }
46}
47
48fn pylist_to_value(pylist: &Bound<'_, PyList>) -> PyResult<Value> {
49 let mut vec: Vec<Value> = Vec::new();
50 for value in pylist.into_iter() {
51 vec.push(pyany_to_value(&value)?);
52 }
53 Ok(vec.into())
54}
55
56pub fn pydict_to_value(pydict: &Bound<'_, PyDict>) -> PyResult<Value> {
66 let mut map: HashMap<String, Value> = HashMap::new();
67 for (key, value) in pydict.into_iter() {
68 map.insert(key.extract::<String>()?, pyany_to_value(&value)?);
69 }
70 Ok(json!(map))
71}
72
73pub fn value_to_pydict(py: Python, value: &Value) -> PyResult<Py<PyAny>> {
84 match value {
85 Value::Null => Ok(py.None()),
86 Value::Bool(b) => Ok(PyBool::new(py, *b).into_pyobject(py)?.to_owned().into()),
87 Value::Number(num) => {
88 if let Some(i) = num.as_i64() {
89 Ok(i.into_pyobject(py)?.into())
90 } else if let Some(f) = num.as_f64() {
91 Ok(f.into_pyobject(py)?.into())
92 } else {
93 Err(PyTypeError::new_err("Unsupported number type"))
94 }
95 }
96 Value::String(s) => Ok(PyString::new(py, s).into_pyobject(py)?.into()),
97 Value::Array(arr) => {
98 let py_list = PyList::empty(py);
99 for item in arr {
100 py_list.append(value_to_pydict(py, item)?)?;
101 }
102 Ok(py_list.into())
103 }
104 Value::Object(obj) => {
105 let py_dict = PyDict::new(py);
106 for (key, val) in obj {
107 py_dict.set_item(key, value_to_pydict(py, val)?)?;
108 }
109 Ok(py_dict.into())
110 }
111 }
112}
113
114#[cfg(test)]
115mod tests {}