use anyhow::Result;
use pyo3::conversion::IntoPyObject;
use pyo3::prelude::*;
use pyo3::types::{IntoPyDict, PyDict, PyTuple};
use serde_json::{Map, Value};
#[pyfunction]
pub fn create_cart(data: &[u8]) -> Result<Vec<u8>> {
malwaredb_client::encode_to_cart(data)
}
#[pyfunction]
pub fn decode_cart(py: Python<'_>, data: &[u8]) -> Result<Py<PyTuple>> {
let (binary, header, footer) = malwaredb_client::decode_from_cart(data)?;
let header = if let Some(header) = header {
convert_json_map_to_dict(py, header)?
} else {
PyDict::new(py).into()
};
let footer = if let Some(footer) = footer {
convert_json_map_to_dict(py, footer)?
} else {
PyDict::new(py).into()
};
Ok(PyTuple::new(
py,
&[
binary.into_pyobject(py)?,
header.into_pyobject(py)?.into_any(),
footer.into_pyobject(py)?.into_any(),
],
)?
.unbind())
}
#[cfg(not(feature = "rust_lib"))]
pub fn register_cart_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> {
let cart_module = PyModule::new(parent_module.py(), "cart")?;
cart_module.add_function(wrap_pyfunction!(create_cart, &cart_module)?)?;
cart_module.add_function(wrap_pyfunction!(decode_cart, &cart_module)?)?;
parent_module.add_submodule(&cart_module)
}
#[inline]
fn convert_json_map_to_dict(py: Python<'_>, map: Map<String, Value>) -> Result<Py<PyDict>> {
let mut vec_: Vec<(String, Py<PyAny>)> = Vec::with_capacity(map.len());
for (key, value) in map {
if let Some(val) = value.as_f64() {
vec_.push((key, Py::<PyAny>::from(val.into_pyobject(py)?)));
continue;
}
if let Some(val) = value.as_str() {
vec_.push((key, Py::<PyAny>::from(val.into_pyobject(py)?)));
continue;
}
if let Some(val) = value.as_u64() {
vec_.push((key, Py::<PyAny>::from(val.into_pyobject(py)?)));
continue;
}
if let Some(val) = value.as_i64() {
vec_.push((key, Py::<PyAny>::from(val.into_pyobject(py)?)));
continue;
}
println!("Parsing JSON to dict, found key {key} with unexpected or unknown value type: {value:?}");
}
Ok(vec_.into_py_dict(py)?.unbind())
}