Skip to main content

_etoon/
lib.rs

1pub mod toon;
2
3#[cfg(feature = "python")]
4mod py_binding {
5    use crate::toon::{encode_with, Config};
6    use pyo3::prelude::*;
7    use pyo3::types::PyBytes;
8
9    #[pyfunction]
10    // Each argument maps to a Python keyword; they can't be grouped into a
11    // struct without breaking the binding signature.
12    #[allow(clippy::too_many_arguments)]
13    #[pyo3(signature = (json_bytes, delimiter=",", key_folding=false, flatten_depth=None, empty_array_bare=true, escape_controls=true, max_depth=1000, max_input_bytes=0))]
14    fn dumps_bytes<'py>(
15        py: Python<'py>,
16        json_bytes: &Bound<'py, PyBytes>,
17        delimiter: &str,
18        key_folding: bool,
19        flatten_depth: Option<usize>,
20        empty_array_bare: bool,
21        escape_controls: bool,
22        max_depth: usize,
23        max_input_bytes: usize,
24    ) -> PyResult<String> {
25        let delim = delimiter.as_bytes().first().copied().unwrap_or(b',');
26        if !matches!(delim, b',' | b'\t' | b'|') {
27            return Err(pyo3::exceptions::PyValueError::new_err(
28                "delimiter must be ',', '\\t', or '|'",
29            ));
30        }
31        let cfg = Config {
32            delimiter: delim,
33            key_folding,
34            flatten_depth,
35            empty_array_bare,
36            escape_controls,
37            max_depth,
38            max_input_bytes,
39        };
40        let bytes = json_bytes.as_bytes();
41        py.detach(|| encode_with(bytes, &cfg))
42            .map_err(pyo3::exceptions::PyValueError::new_err)
43    }
44
45    #[pymodule]
46    fn _etoon(m: &Bound<'_, PyModule>) -> PyResult<()> {
47        m.add_function(wrap_pyfunction!(dumps_bytes, m)?)?;
48        Ok(())
49    }
50}