// Copyright © SixtyFPS GmbH // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial use pyo3::prelude::*; use pyo3::types::{IntoPyDict, PyDict}; pub struct PyValue(pub slint_interpreter::Value); struct PyValueRef<'a>(&'a slint_interpreter::Value); impl IntoPy for PyValue { fn into_py(self, py: Python<'_>) -> PyObject { // Share the conversion code below that operates on the reference self.to_object(py).into_py(py) } } impl ToPyObject for PyValue { fn to_object(&self, py: Python<'_>) -> PyObject { PyValueRef(&self.0).to_object(py) } } impl<'a> IntoPy for PyValueRef<'a> { fn into_py(self, py: Python<'_>) -> PyObject { // Share the conversion code below that operates on the reference self.to_object(py).into_py(py) } } impl<'a> ToPyObject for PyValueRef<'a> { fn to_object(&self, py: Python<'_>) -> PyObject { match &self.0 { slint_interpreter::Value::Void => ().into_py(py), slint_interpreter::Value::Number(num) => num.into_py(py), slint_interpreter::Value::String(str) => str.into_py(py), slint_interpreter::Value::Bool(b) => b.into_py(py), slint_interpreter::Value::Image(_) => todo!(), slint_interpreter::Value::Model(_) => todo!(), slint_interpreter::Value::Struct(structval) => structval .iter() .map(|(name, val)| (name.to_string().into_py(py), PyValueRef(val).into_py(py))) .into_py_dict(py) .into_py(py), slint_interpreter::Value::Brush(_) => todo!(), _ => todo!(), } } } impl FromPyObject<'_> for PyValue { fn extract(ob: &PyAny) -> PyResult { if ob.is_none() { return Ok(slint_interpreter::Value::Void.into()); } let interpreter_val = ob .extract::() .map(|b| slint_interpreter::Value::Bool(b)) .or_else(|_| { ob.extract::<&'_ str>().map(|s| slint_interpreter::Value::String(s.into())) }) .or_else(|_| ob.extract::().map(|num| slint_interpreter::Value::Number(num))) .or_else(|_| { ob.extract::<&PyDict>().and_then(|dict| { let dict_items: Result, PyErr> = dict .iter() .map(|(name, pyval)| { let name = name.extract::<&str>()?.to_string(); let slintval: PyValue = pyval.extract()?; Ok((name, slintval.0)) }) .collect::, PyErr>>(); Ok(slint_interpreter::Value::Struct(slint_interpreter::Struct::from_iter( dict_items?.into_iter(), ))) }) })?; Ok(PyValue(interpreter_val)) } } impl From for PyValue { fn from(value: slint_interpreter::Value) -> Self { Self(value) } }