use pyo3::exceptions::PyValueError;
use pyo3::prelude::*;
use pyo3::types::PyDict;
use crate::link::{self, ManifestLink};
fn map_err(e: crate::Error) -> PyErr {
match e.code() {
Some(code) => PyValueError::new_err(format!("{e} [{code}]")),
None => PyValueError::new_err(e.to_string()),
}
}
fn to_dict<'py>(py: Python<'py>, l: &ManifestLink) -> PyResult<Bound<'py, PyDict>> {
let out = PyDict::new(py);
out.set_item("uri", l.uri.as_str())?;
out.set_item("jumbf", l.jumbf.as_deref())?;
out.set_item("is_embedded", l.is_embedded())?;
Ok(out)
}
#[pyfunction]
fn format(uri: &str) -> PyResult<String> {
link::format(uri).map_err(map_err)
}
#[pyfunction]
fn format_strict(uri: &str) -> PyResult<String> {
link::format_strict(uri).map_err(map_err)
}
#[pyfunction]
fn encode_target(uri: &str) -> String {
link::encode_target(uri)
}
#[pyfunction]
fn extract<'py>(py: Python<'py>, values: Vec<String>) -> PyResult<Option<Bound<'py, PyDict>>> {
match link::extract(values.iter().map(String::as_str)) {
Ok(found) => Ok(Some(to_dict(py, &found)?)),
Err(crate::Error::NotFound) => Ok(None),
Err(e) => Err(map_err(e)),
}
}
#[pyfunction]
fn locate_all<'py>(py: Python<'py>, values: Vec<String>) -> PyResult<Vec<Bound<'py, PyDict>>> {
link::locate_all(values.iter().map(String::as_str))
.iter()
.map(|l| to_dict(py, l))
.collect()
}
#[pymodule]
fn c2pa_http(m: &Bound<'_, PyModule>) -> PyResult<()> {
m.add_function(wrap_pyfunction!(format, m)?)?;
m.add_function(wrap_pyfunction!(format_strict, m)?)?;
m.add_function(wrap_pyfunction!(encode_target, m)?)?;
m.add_function(wrap_pyfunction!(extract, m)?)?;
m.add_function(wrap_pyfunction!(locate_all, m)?)?;
m.add("REL", crate::link::REL)?;
m.add("__version__", env!("CARGO_PKG_VERSION"))?;
Ok(())
}