use pyo3::prelude::*;
#[pyclass(skip_from_py_object)]
#[pyo3(name = "KeyCollision")]
#[derive(Clone)]
pub struct KeyCollision {
#[pyo3(get)]
pub key: String,
#[pyo3(get)]
pub values: Vec<String>,
#[pyo3(get)]
pub indices: Vec<usize>,
}
#[pymethods]
impl KeyCollision {
fn __repr__(&self) -> String {
let values = self
.values
.iter()
.map(|v| format!("{v:?}"))
.collect::<Vec<_>>()
.join(", ");
format!(
"KeyCollision(key={:?}, values=[{values}], indices={:?})",
self.key, self.indices
)
}
}
impl From<crate::api::KeyCollision> for KeyCollision {
fn from(c: crate::api::KeyCollision) -> Self {
KeyCollision {
key: c.key,
values: c.values,
indices: c.indices,
}
}
}
#[pyfunction]
#[pyo3(signature = (values, *, key, lang=None))]
pub fn _find_key_collisions(
values: Vec<String>,
key: &str,
lang: Option<&str>,
) -> PyResult<Vec<KeyCollision>> {
let key: crate::api::KeyForm = key.parse()?;
Ok(crate::api::find_key_collisions(&values, key, lang)?
.into_iter()
.map(KeyCollision::from)
.collect())
}
#[pyfunction]
pub fn _edit_distance(a: &str, b: &str) -> usize {
crate::api::edit_distance(a, b)
}
#[pyclass(skip_from_py_object)]
pub struct NearestMatch {
#[pyo3(get)]
pub value: String,
#[pyo3(get)]
pub distance: usize,
}
#[pymethods]
impl NearestMatch {
fn __repr__(&self) -> String {
format!(
"NearestMatch(value={:?}, distance={})",
self.value, self.distance
)
}
}
impl From<crate::api::NearestMatch> for NearestMatch {
fn from(m: crate::api::NearestMatch) -> Self {
Self {
value: m.value,
distance: m.distance,
}
}
}
#[pyfunction]
#[pyo3(signature = (value, candidates, *, max_distance=1))]
pub fn _nearest_match(
value: &str,
candidates: Vec<String>,
max_distance: usize,
) -> Option<NearestMatch> {
crate::api::nearest_match(value, candidates.iter().map(String::as_str), max_distance)
.map(NearestMatch::from)
}