use wasm_bindgen::prelude::*;
use wasm_bindgen::JsError;
use crate::traversal::predicate;
use crate::traversal::predicate::p as rust_p;
use crate::wasm::types::js_to_value;
#[wasm_bindgen]
pub struct Predicate {
pub(crate) inner: Box<dyn predicate::Predicate>,
}
impl Predicate {
pub(crate) fn new(pred: impl predicate::Predicate + 'static) -> Self {
Self {
inner: Box::new(pred),
}
}
pub(crate) fn into_inner(self) -> Box<dyn predicate::Predicate> {
self.inner
}
}
impl Clone for Predicate {
fn clone(&self) -> Self {
Self {
inner: self.inner.clone_box(),
}
}
}
#[wasm_bindgen]
pub struct P;
#[wasm_bindgen]
impl P {
pub fn eq(value: JsValue) -> Result<Predicate, JsError> {
let v = js_to_value(value)?;
Ok(Predicate::new(rust_p::eq(v)))
}
pub fn neq(value: JsValue) -> Result<Predicate, JsError> {
let v = js_to_value(value)?;
Ok(Predicate::new(rust_p::neq(v)))
}
pub fn lt(value: JsValue) -> Result<Predicate, JsError> {
let v = js_to_value(value)?;
Ok(Predicate::new(rust_p::lt(v)))
}
pub fn lte(value: JsValue) -> Result<Predicate, JsError> {
let v = js_to_value(value)?;
Ok(Predicate::new(rust_p::lte(v)))
}
pub fn gt(value: JsValue) -> Result<Predicate, JsError> {
let v = js_to_value(value)?;
Ok(Predicate::new(rust_p::gt(v)))
}
pub fn gte(value: JsValue) -> Result<Predicate, JsError> {
let v = js_to_value(value)?;
Ok(Predicate::new(rust_p::gte(v)))
}
pub fn between(start: JsValue, end: JsValue) -> Result<Predicate, JsError> {
let s = js_to_value(start)?;
let e = js_to_value(end)?;
Ok(Predicate::new(rust_p::between(s, e)))
}
pub fn inside(start: JsValue, end: JsValue) -> Result<Predicate, JsError> {
let s = js_to_value(start)?;
let e = js_to_value(end)?;
Ok(Predicate::new(rust_p::inside(s, e)))
}
pub fn outside(start: JsValue, end: JsValue) -> Result<Predicate, JsError> {
let s = js_to_value(start)?;
let e = js_to_value(end)?;
Ok(Predicate::new(rust_p::outside(s, e)))
}
pub fn within(values: JsValue) -> Result<Predicate, JsError> {
let vals = crate::wasm::types::js_array_to_values(values)?;
Ok(Predicate::new(rust_p::within(vals)))
}
pub fn without(values: JsValue) -> Result<Predicate, JsError> {
let vals = crate::wasm::types::js_array_to_values(values)?;
Ok(Predicate::new(rust_p::without(vals)))
}
pub fn containing(substring: &str) -> Predicate {
Predicate::new(rust_p::containing(substring))
}
#[wasm_bindgen(js_name = "notContaining")]
pub fn not_containing(substring: &str) -> Predicate {
Predicate::new(rust_p::not_containing(substring))
}
#[wasm_bindgen(js_name = "startingWith")]
pub fn starting_with(prefix: &str) -> Predicate {
Predicate::new(rust_p::starting_with(prefix))
}
#[wasm_bindgen(js_name = "notStartingWith")]
pub fn not_starting_with(prefix: &str) -> Predicate {
Predicate::new(rust_p::not_starting_with(prefix))
}
#[wasm_bindgen(js_name = "endingWith")]
pub fn ending_with(suffix: &str) -> Predicate {
Predicate::new(rust_p::ending_with(suffix))
}
#[wasm_bindgen(js_name = "notEndingWith")]
pub fn not_ending_with(suffix: &str) -> Predicate {
Predicate::new(rust_p::not_ending_with(suffix))
}
pub fn regex(pattern: &str) -> Result<Predicate, JsError> {
Ok(Predicate::new(rust_p::regex(pattern)))
}
#[wasm_bindgen(js_name = "and")]
pub fn and_(p1: Predicate, p2: Predicate) -> Predicate {
Predicate {
inner: rust_p::and_pred(p1.inner, p2.inner),
}
}
#[wasm_bindgen(js_name = "or")]
pub fn or_(p1: Predicate, p2: Predicate) -> Predicate {
Predicate {
inner: rust_p::or_pred(p1.inner, p2.inner),
}
}
#[wasm_bindgen(js_name = "not")]
pub fn not_(pred: Predicate) -> Predicate {
Predicate {
inner: rust_p::not_pred(pred.inner),
}
}
#[wasm_bindgen(js_name = "withinDistance")]
pub fn within_distance(lon: f64, lat: f64, distance_km: f64) -> Predicate {
use crate::geo::{Distance, Point};
let center = Point { lon, lat };
let radius = Distance::Kilometers(distance_km);
Predicate::new(rust_p::within_distance(center, radius))
}
}