use crate::value_ops::value_to_f64;
use nodedb_types::Value;
use nodedb_types::geometry::Geometry;
pub(super) fn str_arg(args: &[Value], idx: usize) -> Option<String> {
args.get(idx)?.as_str().map(|s| s.to_string())
}
pub(super) fn num_arg(args: &[Value], idx: usize) -> Option<f64> {
args.get(idx).and_then(|v| value_to_f64(v, true))
}
pub(super) fn geom_arg(args: &[Value], idx: usize) -> Option<Geometry> {
match args.get(idx)? {
Value::Geometry(g) => Some(g.clone()),
Value::String(s) => geometry_from_text(s),
other => {
let json = serde_json::Value::from(other.clone());
serde_json::from_value(json).ok()
}
}
}
pub fn geometry_from_text(text: &str) -> Option<Geometry> {
let trimmed = text.trim();
if trimmed.starts_with('{') {
nodedb_types::geometry::from_geojson_str(trimmed)
} else {
nodedb_spatial::geometry_from_wkt(trimmed)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn geojson_and_wkt_strings_both_parse() {
let geojson = geometry_from_text(r#"{"type":"Point","coordinates":[1.0,2.0]}"#);
let wkt = geometry_from_text("POINT(1 2)");
assert_eq!(geojson, wkt);
assert_eq!(geojson, Some(Geometry::point(1.0, 2.0)));
}
#[test]
fn surrounding_whitespace_does_not_defeat_parsing() {
assert!(geometry_from_text(" POINT(1 2) ").is_some());
assert!(geometry_from_text(" {\"type\":\"Point\",\"coordinates\":[1,2]} ").is_some());
}
#[test]
fn non_geometry_text_is_rejected() {
assert!(geometry_from_text("not a geometry").is_none());
assert!(geometry_from_text("").is_none());
}
}