use pyo3::prelude::*;
use pyo3::types::PyBytes;
use crate::codec::Codec;
use crate::error::KnafehError;
#[pyclass(name = "Codec")]
pub struct PyCodec {
_inner: Py<PyAny>,
}
#[pymethods]
impl PyCodec {
#[new]
fn new(obj: Py<PyAny>) -> Self {
Self { _inner: obj }
}
}
#[allow(dead_code)]
pub(crate) struct PythonCodecBridge {
pub(crate) obj: Py<PyAny>,
}
impl Codec for PythonCodecBridge {
fn encode(&self, value: &[u8]) -> Result<Vec<u8>, KnafehError> {
Python::attach(|py| {
let py_bytes = PyBytes::new(py, value);
let result = self
.obj
.call_method1(py, "encode", (py_bytes,))
.map_err(|e| KnafehError::Codec(format!("Python encode error: {e}")))?;
let bytes: &Bound<PyBytes> = result
.cast_bound(py)
.map_err(|e| KnafehError::Codec(format!("encode must return bytes: {e}")))?;
Ok(bytes.as_bytes().to_vec())
})
}
fn decode(&self, data: &[u8]) -> Result<Vec<u8>, KnafehError> {
Python::attach(|py| {
let py_bytes = PyBytes::new(py, data);
let result = self
.obj
.call_method1(py, "decode", (py_bytes,))
.map_err(|e| KnafehError::Codec(format!("Python decode error: {e}")))?;
let bytes: &Bound<PyBytes> = result
.cast_bound(py)
.map_err(|e| KnafehError::Codec(format!("decode must return bytes: {e}")))?;
Ok(bytes.as_bytes().to_vec())
})
}
fn content_type(&self) -> &str {
"application/octet-stream"
}
fn name(&self) -> &str {
"python-custom"
}
}