lindera_py/
util.rs

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<PyObject> {
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 {
79    // use pyo3::types::IntoPyDict;
80    // use serde_json::json;
81
82    // use super::*;
83
84    // #[test]
85    // fn test_pydict_to_value() {
86    //     Python::with_gil(|py| {
87    //         let py_dict = [("key1", "value1"), ("key2", "value2")].into_py_dict_bound(py);
88    //         let value = pydict_to_value(&py_dict).unwrap();
89    //         let expected = json!({"key1": "value1", "key2": "value2"});
90    //         assert_eq!(value, expected);
91    //     });
92    // }
93
94    // #[test]
95    // fn test_python_to_json_with_dict() {
96    //     Python::with_gil(|py| {
97    //         let py_dict = [("key1", "value1"), ("key2", "value2")].into_py_dict_bound(py);
98    //         let value = python_to_json(&py_dict).unwrap();
99    //         let expected = json!({"key1": "value1", "key2": "value2"});
100    //         assert_eq!(value, expected);
101    //     });
102    // }
103
104    // #[test]
105    // fn test_python_to_json_with_list() {
106    //     Python::with_gil(|py| {
107    //         let binding = vec!["value1", "value2"].into_py(py);
108    //         let py_list = binding.downcast_bound::<PyAny>(py).unwrap();
109    //         let value = python_to_json(py_list).unwrap();
110    //         let expected = json!(["value1", "value2"]);
111    //         assert_eq!(value, expected);
112    //     });
113    // }
114
115    // #[test]
116    // fn test_python_to_json_with_string() {
117    //     Python::with_gil(|py| {
118    //         let binding = "value1".to_string().into_py(py);
119    //         let py_str = binding.downcast_bound::<PyAny>(py).unwrap();
120    //         let value = python_to_json(py_str).unwrap();
121    //         let expected = json!("value");
122    //         assert_eq!(value, expected);
123    //     });
124    // }
125
126    // #[test]
127    // fn test_python_to_json_with_int() {
128    //     Python::with_gil(|py| {
129    //         let binding = 42_i64.into_py(py);
130    //         let py_int = binding.downcast_bound::<PyAny>(py).unwrap();
131    //         let value = python_to_json(py_int).unwrap();
132    //         let expected = json!(42);
133    //         assert_eq!(value, expected);
134    //     });
135    // }
136
137    // #[test]
138    // fn test_python_to_json_with_float() {
139    //     Python::with_gil(|py| {
140    //         let binding = 3.14_f64.into_py(py);
141    //         let py_float = binding.downcast_bound::<PyAny>(py).unwrap();
142    //         let value = python_to_json(py_float).unwrap();
143    //         let expected = json!(3.14);
144    //         assert_eq!(value, expected);
145    //     });
146    // }
147
148    // #[test]
149    // fn test_python_to_json_with_none() {
150    //     Python::with_gil(|py| {
151    //         let binding = py.None();
152    //         let py_none = binding.downcast_bound::<PyAny>(py).unwrap();
153    //         let value = python_to_json(py_none).unwrap();
154    //         let expected = json!(null);
155    //         assert_eq!(value, expected);
156    //     });
157    // }
158
159    // #[test]
160    // fn test_python_to_json_with_unsupported_type() {
161    //     Python::with_gil(|py| {
162    //         let py_tuple = (1, 2).into_py(py);
163    //         let result = python_to_json(py_tuple);
164    //         assert!(result.is_err());
165    //     });
166    // }
167}