use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (text, *, target_script="latin", digit_policy="numeric"))]
pub fn _normalize_confusables(
text: &str,
target_script: &str,
digit_policy: &str,
) -> PyResult<String> {
Ok(crate::confusables::normalize_confusables(
text,
target_script,
digit_policy,
)?)
}
#[pyfunction]
#[pyo3(signature = (text, *, target_script="latin"))]
pub fn _is_confusable(text: &str, target_script: &str) -> PyResult<bool> {
Ok(crate::confusables::is_confusable(text, target_script)?)
}
#[pyfunction]
#[pyo3(signature = (*, target_script="latin"))]
pub fn _unmapped_confusables(target_script: &str) -> PyResult<Vec<String>> {
Ok(crate::confusables::unmapped_confusables(target_script)?
.into_iter()
.map(String::from)
.collect())
}
#[pyfunction]
pub fn _confusable_coverage(script: &str) -> PyResult<(String, u32, u32)> {
let row = crate::api::confusable_coverage(script)?;
Ok((row.script.to_owned(), row.sources, row.folded))
}
#[pyfunction]
#[pyo3(signature = (text, *, target_script="latin", allowed_scripts=None))]
pub fn _find_confusables(
text: &str,
target_script: &str,
allowed_scripts: Option<Vec<String>>,
) -> PyResult<Vec<(String, usize, String)>> {
let allowed = allowed_scripts.unwrap_or_default();
let allowed: Vec<&str> = allowed.iter().map(String::as_str).collect();
Ok(
crate::confusables::find_confusables(text, target_script, &allowed)?
.into_iter()
.map(|(ch, offset, target)| (ch.to_string(), offset, target.to_string()))
.collect(),
)
}
#[pyfunction]
#[pyo3(signature = (text, *, target_script="latin"))]
pub fn _find_unmapped_confusables(
text: &str,
target_script: &str,
) -> PyResult<Vec<(String, usize)>> {
Ok(
crate::confusables::find_unmapped_confusables(text, target_script)?
.into_iter()
.map(|(ch, offset)| (ch.to_string(), offset))
.collect(),
)
}
#[pyclass(skip_from_py_object)]
#[pyo3(name = "SmuggledPayload")]
#[derive(Clone)]
pub struct SmuggledPayload {
#[pyo3(get)]
pub scheme: String,
#[pyo3(get)]
pub start: usize,
#[pyo3(get)]
pub end: usize,
#[pyo3(get)]
pub units: usize,
#[pyo3(get)]
pub data: Vec<u8>,
#[pyo3(get)]
pub text: Option<String>,
}
#[pymethods]
impl SmuggledPayload {
fn __repr__(&self) -> String {
let text = match &self.text {
Some(s) => format!("{s:?}"),
None => "None".to_owned(),
};
format!(
"SmuggledPayload(scheme={:?}, start={}, end={}, units={}, text={text})",
self.scheme, self.start, self.end, self.units
)
}
}
impl From<crate::smuggled::Payload> for SmuggledPayload {
fn from(p: crate::smuggled::Payload) -> Self {
SmuggledPayload {
scheme: p.scheme.as_str().to_owned(),
start: p.start,
end: p.end,
units: p.units,
data: p.bytes,
text: p.text,
}
}
}
#[pyfunction]
#[pyo3(signature = (text,))]
pub fn _decode_smuggled(text: &str) -> Vec<SmuggledPayload> {
crate::smuggled::decode_smuggled(text)
.into_iter()
.map(Into::into)
.collect()
}