use serde_json::{json, Value};
use rust_store_core::computes::FnRegistry;
use rust_store_core::permission::Context;
fn num_or0(doc: &Value, key: &str) -> f64 {
match doc.get(key) {
Some(Value::Number(n)) => n.as_f64().unwrap_or(0.0),
_ => 0.0,
}
}
fn num_value(f: f64) -> Value {
if f.fract() == 0.0 && f.abs() <= 9_007_199_254_740_992.0 {
json!(f as i64)
} else {
json!(f)
}
}
pub struct TestFnRegistry;
impl FnRegistry for TestFnRegistry {
fn call_sync(&self, fn_ref: &str, doc: &Value) -> Result<Value, String> {
match fn_ref {
"sum_ab" => Ok(num_value(num_or0(doc, "a") + num_or0(doc, "b"))),
"mul_qp" => Ok(num_value(num_or0(doc, "qty") * num_or0(doc, "price"))),
"label" => Ok(json!(if num_or0(doc, "v") > 10.0 {
"big"
} else {
"small"
})),
"null_fn" => Ok(Value::Null),
"greet" => {
let name = doc.get("name").and_then(|v| v.as_str()).unwrap_or("");
Ok(json!(format!("hi:{}", name)))
}
other => Err(format!("未注册的同步测试函数: {}", other)),
}
}
fn call_async(
&self,
fn_ref: &str,
items: &mut [Value],
ctx: Option<&Context>,
) -> Result<(), String> {
match fn_ref {
"fill_area" => {
for it in items.iter_mut() {
let area = num_or0(it, "w") * num_or0(it, "h");
if let Some(o) = it.as_object_mut() {
o.insert("area".to_string(), num_value(area));
}
}
Ok(())
}
"ctx_tag" => {
let tag = match ctx.and_then(|c| c.user_id.clone()) {
Some(uid) => format!("u:{}", uid),
None => "anon".to_string(),
};
for it in items.iter_mut() {
if let Some(o) = it.as_object_mut() {
o.insert("tag".to_string(), json!(tag));
}
}
Ok(())
}
"tag_skus" => {
for it in items.iter_mut() {
let skus: Vec<String> = it
.get("items")
.and_then(|v| v.as_array())
.map(|arr| {
arr.iter()
.map(|s| {
s.get("sku")
.and_then(|v| v.as_str())
.unwrap_or("")
.to_string()
})
.collect()
})
.unwrap_or_default();
if let Some(o) = it.as_object_mut() {
o.insert("skuTag".to_string(), json!(skus.join("|")));
}
}
Ok(())
}
other => Err(format!("未注册的异步测试函数: {}", other)),
}
}
}