1use std::collections::HashMap;
2
3use pyo3::exceptions::PyTypeError;
4use pyo3::prelude::*;
5use pyo3::types::{PyBool, PyDict, PyFloat, PyInt, PyList, PyNone, PyString};
6use serde_json::{Value, json};
7
8pub fn pyany_to_value(value: &Bound<'_, PyAny>) -> PyResult<Value> {
9 if value.is_instance_of::<PyString>() {
10 Ok(Value::from(value.extract::<String>()?))
11 } else if value.is_instance_of::<PyBool>() {
12 Ok(Value::from(value.extract::<bool>()?))
13 } else if value.is_instance_of::<PyFloat>() {
14 Ok(Value::from(value.extract::<f64>()?))
15 } else if value.is_instance_of::<PyInt>() {
16 Ok(Value::from(value.extract::<i64>()?))
17 } else if value.is_instance_of::<PyList>() {
18 pylist_to_value(&value.extract::<Bound<'_, PyList>>()?)
19 } else if value.is_instance_of::<PyDict>() {
20 pydict_to_value(&value.extract::<Bound<'_, PyDict>>()?)
21 } else if value.is_instance_of::<PyNone>() {
22 Ok(Value::Null)
23 } else {
24 Err(PyErr::new::<PyTypeError, _>(format!(
25 "Unsupported Python object: {value}"
26 )))
27 }
28}
29
30fn pylist_to_value(pylist: &Bound<'_, PyList>) -> PyResult<Value> {
31 let mut vec: Vec<Value> = Vec::new();
32 for value in pylist.into_iter() {
33 vec.push(pyany_to_value(&value)?);
34 }
35 Ok(vec.into())
36}
37
38pub fn pydict_to_value(pydict: &Bound<'_, PyDict>) -> PyResult<Value> {
39 let mut map: HashMap<String, Value> = HashMap::new();
40 for (key, value) in pydict.into_iter() {
41 map.insert(key.extract::<String>()?, pyany_to_value(&value)?);
42 }
43 Ok(json!(map))
44}
45
46pub fn value_to_pydict(py: Python, value: &Value) -> PyResult<Py<PyAny>> {
47 match value {
48 Value::Null => Ok(py.None()),
49 Value::Bool(b) => Ok(PyBool::new(py, *b).into_pyobject(py)?.to_owned().into()),
50 Value::Number(num) => {
51 if let Some(i) = num.as_i64() {
52 Ok(i.into_pyobject(py)?.into())
53 } else if let Some(f) = num.as_f64() {
54 Ok(f.into_pyobject(py)?.into())
55 } else {
56 Err(PyTypeError::new_err("Unsupported number type"))
57 }
58 }
59 Value::String(s) => Ok(PyString::new(py, s).into_pyobject(py)?.into()),
60 Value::Array(arr) => {
61 let py_list = PyList::empty(py);
62 for item in arr {
63 py_list.append(value_to_pydict(py, item)?)?;
64 }
65 Ok(py_list.into())
66 }
67 Value::Object(obj) => {
68 let py_dict = PyDict::new(py);
69 for (key, val) in obj {
70 py_dict.set_item(key, value_to_pydict(py, val)?)?;
71 }
72 Ok(py_dict.into())
73 }
74 }
75}
76
77#[cfg(test)]
78mod tests {}