# RFC-003: v1.2 内置函数系统
**状态**: 已实现 (Implemented)
**作者**: XQPath 项目组
**创建日期**: 2025 年 7 月
**最后更新**: 2025 年 7 月 27 日
## 摘要
本 RFC 定义了 XQPath v1.2 内置函数系统的设计,包括基础函数、高级函数、条件表达式、比较操作符、逻辑操作符和错误处理机制。
## 动机
XQPath v1.1 虽然支持了表达式系统,但缺乏数据处理函数,限制了其在实际场景中的应用。为了提供完整的 jq 风格数据处理能力,需要实现丰富的内置函数系统。
## 详细设计
### 函数系统架构
#### 基础函数接口
```rust
pub trait BuiltinFunction: Send + Sync {
fn name(&self) -> &str;
fn call(&self, input: &[Value]) -> Result<Vec<Value>, String>;
}
```
#### 高级函数接口
```rust
pub trait AdvancedBuiltinFunction: Send + Sync {
fn name(&self) -> &str;
fn call(&self, input: &[Value], arg_expr: &PathExpression, context: &Value)
-> Result<Vec<Value>, String>;
}
```
#### 函数注册表
```rust
#[derive(Debug, Default)]
pub struct FunctionRegistry {
builtin_functions: HashMap<String, Box<dyn BuiltinFunction>>,
advanced_functions: HashMap<String, Box<dyn AdvancedBuiltinFunction>>,
}
impl FunctionRegistry {
pub fn register_builtin(&mut self, func: Box<dyn BuiltinFunction>) {
self.builtin_functions.insert(func.name().to_string(), func);
}
pub fn register_advanced(&mut self, func: Box<dyn AdvancedBuiltinFunction>) {
self.advanced_functions.insert(func.name().to_string(), func);
}
pub fn call_function(&self, name: &str, input: &[Value], args: Option<(&PathExpression, &Value)>)
-> Result<Vec<Value>, String> {
if let Some(func) = self.builtin_functions.get(name) {
func.call(input)
} else if let Some(func) = self.advanced_functions.get(name) {
if let Some((arg_expr, context)) = args {
func.call(input, arg_expr, context)
} else {
Err(format!("Function '{}' requires an argument expression", name))
}
} else {
Err(format!("Unknown function: {}", name))
}
}
}
```
### 内置函数实现
#### 基础函数
```rust
// length() - 获取长度
struct LengthFunction;
impl BuiltinFunction for LengthFunction {
fn name(&self) -> &str { "length" }
fn call(&self, input: &[Value]) -> Result<Vec<Value>, String> {
let results = input.iter().map(|value| {
let len = match value {
Value::Array(arr) => arr.len(),
Value::Object(obj) => obj.len(),
Value::String(s) => s.chars().count(),
Value::Null => 0,
_ => return Err(format!("Cannot get length of {}", value_type_name(value))),
};
Ok(Value::Number(serde_json::Number::from(len)))
}).collect::<Result<Vec<_>, _>>()?;
Ok(results)
}
}
// type() - 获取类型
struct TypeFunction;
impl BuiltinFunction for TypeFunction {
fn name(&self) -> &str { "type" }
fn call(&self, input: &[Value]) -> Result<Vec<Value>, String> {
let results = input.iter().map(|value| {
let type_name = match value {
Value::Null => "null",
Value::Bool(_) => "boolean",
Value::Number(_) => "number",
Value::String(_) => "string",
Value::Array(_) => "array",
Value::Object(_) => "object",
};
Value::String(type_name.to_string())
}).collect();
Ok(results)
}
}
// keys() - 获取对象键名
struct KeysFunction;
impl BuiltinFunction for KeysFunction {
fn name(&self) -> &str { "keys" }
fn call(&self, input: &[Value]) -> Result<Vec<Value>, String> {
let results = input.iter().map(|value| {
match value {
Value::Object(obj) => {
let mut keys: Vec<String> = obj.keys().cloned().collect();
keys.sort();
Ok(Value::Array(keys.into_iter().map(Value::String).collect()))
}
Value::Array(arr) => {
let indices: Vec<Value> = (0..arr.len())
.map(|i| Value::Number(serde_json::Number::from(i)))
.collect();
Ok(Value::Array(indices))
}
_ => Err(format!("Cannot get keys of {}", value_type_name(value))),
}
}).collect::<Result<Vec<_>, _>>()?;
Ok(results)
}
}
```
#### 高级函数
```rust
// map(expr) - 映射函数
struct MapFunction;
impl AdvancedBuiltinFunction for MapFunction {
fn name(&self) -> &str { "map" }
fn call(&self, input: &[Value], arg_expr: &PathExpression, context: &Value)
-> Result<Vec<Value>, String> {
let results = input.iter().map(|value| {
match value {
Value::Array(arr) => {
let mapped: Result<Vec<_>, _> = arr.iter().map(|item| {
let item_results = evaluate_path_expression(arg_expr, item)?;
// 取第一个结果,如果没有结果则为 null
Ok(item_results.into_iter().next().unwrap_or(Value::Null))
}).collect();
mapped.map(Value::Array)
}
_ => Err(format!("Cannot map over {}", value_type_name(value))),
}
}).collect::<Result<Vec<_>, _>>()?;
Ok(results)
}
}
// select(condition) - 过滤函数
struct SelectFunction;
impl AdvancedBuiltinFunction for SelectFunction {
fn name(&self) -> &str { "select" }
fn call(&self, input: &[Value], arg_expr: &PathExpression, context: &Value)
-> Result<Vec<Value>, String> {
let results = input.iter().filter_map(|value| {
match evaluate_path_expression(arg_expr, value) {
Ok(condition_results) => {
// 检查条件是否为真
let is_truthy = condition_results.iter().any(|result| {
match result {
Value::Bool(b) => *b,
Value::Null => false,
Value::Number(n) => n.as_f64().unwrap_or(0.0) != 0.0,
Value::String(s) => !s.is_empty(),
Value::Array(a) => !a.is_empty(),
Value::Object(o) => !o.is_empty(),
}
});
if is_truthy {
Some(value.clone())
} else {
None
}
}
Err(_) => None, // 条件求值失败时过滤掉
}
}).collect();
Ok(results)
}
}
```
### 条件表达式系统
#### AST 扩展
```rust
#[derive(Debug, Clone, PartialEq)]
pub enum PathExpression {
// ...existing variants...
// 条件表达式
Conditional {
condition: Box<PathExpression>,
then_expr: Box<PathExpression>,
else_expr: Option<Box<PathExpression>>,
},
// 比较操作
Comparison {
left: Box<PathExpression>,
op: ComparisonOp,
right: Box<PathExpression>,
},
// 逻辑操作
Logical {
op: LogicalOp,
operands: Vec<PathExpression>,
},
}
#[derive(Debug, Clone, PartialEq)]
pub enum ComparisonOp {
Equal, // ==
NotEqual, // !=
Less, // <
LessEqual, // <=
Greater, // >
GreaterEqual, // >=
}
#[derive(Debug, Clone, PartialEq)]
pub enum LogicalOp {
And, // and
Or, // or
Not, // not
}
```
#### 条件表达式求值
```rust
impl ExpressionEvaluator {
fn evaluate_conditional(&self, condition: &PathExpression, then_expr: &PathExpression,
else_expr: &Option<Box<PathExpression>>, input: &Value)
-> Result<Vec<Value>, EvaluationError> {
// 求值条件
let condition_results = self.evaluate_expression(condition, input)?;
// 检查条件是否为真
let is_truthy = condition_results.iter().any(|result| self.is_truthy(result));
if is_truthy {
self.evaluate_expression(then_expr, input)
} else if let Some(else_expr) = else_expr {
self.evaluate_expression(else_expr, input)
} else {
Ok(vec![Value::Null])
}
}
fn evaluate_comparison(&self, left: &PathExpression, op: &ComparisonOp,
right: &PathExpression, input: &Value)
-> Result<Vec<Value>, EvaluationError> {
let left_results = self.evaluate_expression(left, input)?;
let right_results = self.evaluate_expression(right, input)?;
// 对所有左右值对进行比较
let mut results = Vec::new();
for left_val in &left_results {
for right_val in &right_results {
let comparison_result = self.compare_values(left_val, op, right_val)?;
results.push(Value::Bool(comparison_result));
}
}
Ok(results)
}
fn compare_values(&self, left: &Value, op: &ComparisonOp, right: &Value)
-> Result<bool, EvaluationError> {
use std::cmp::Ordering;
let ordering = match (left, right) {
(Value::Number(l), Value::Number(r)) => {
l.as_f64().unwrap().partial_cmp(&r.as_f64().unwrap())
}
(Value::String(l), Value::String(r)) => {
Some(l.cmp(r))
}
(Value::Bool(l), Value::Bool(r)) => {
Some(l.cmp(r))
}
_ if matches!(op, ComparisonOp::Equal | ComparisonOp::NotEqual) => {
Some(if left == right { Ordering::Equal } else { Ordering::Greater })
}
_ => return Err(EvaluationError::TypeMismatch {
left_type: value_type_name(left).to_string(),
right_type: value_type_name(right).to_string(),
op: format!("{:?}", op),
}),
};
let result = match (op, ordering) {
(ComparisonOp::Equal, Some(Ordering::Equal)) => true,
(ComparisonOp::NotEqual, Some(Ordering::Equal)) => false,
(ComparisonOp::NotEqual, _) => true,
(ComparisonOp::Less, Some(Ordering::Less)) => true,
(ComparisonOp::LessEqual, Some(Ordering::Less | Ordering::Equal)) => true,
(ComparisonOp::Greater, Some(Ordering::Greater)) => true,
(ComparisonOp::GreaterEqual, Some(Ordering::Greater | Ordering::Equal)) => true,
_ => false,
};
Ok(result)
}
}
```
### 错误处理机制
#### Try-Catch 表达式
```rust
#[derive(Debug, Clone, PartialEq)]
pub enum PathExpression {
// ...existing variants...
// Try-Catch 表达式
TryCatch {
try_expr: Box<PathExpression>,
catch_expr: Box<PathExpression>,
},
// 可选操作符
Optional(Box<PathExpression>),
}
impl ExpressionEvaluator {
fn evaluate_try_catch(&self, try_expr: &PathExpression, catch_expr: &PathExpression,
input: &Value) -> Result<Vec<Value>, EvaluationError> {
match self.evaluate_expression(try_expr, input) {
Ok(results) => Ok(results),
Err(_) => self.evaluate_expression(catch_expr, input),
}
}
fn evaluate_optional(&self, expr: &PathExpression, input: &Value)
-> Result<Vec<Value>, EvaluationError> {
match self.evaluate_expression(expr, input) {
Ok(results) => Ok(results),
Err(_) => Ok(vec![Value::Null]),
}
}
}
```
## 实现计划
### Phase 1: 基础函数实现 ✅
- [x] length(), type(), keys(), values() 函数
- [x] 函数注册表和调用机制
- [x] 基本的函数调用语法解析
### Phase 2: 条件表达式系统 ✅
- [x] if-then-else 语法解析和求值
- [x] 比较操作符实现
- [x] 逻辑操作符实现
### Phase 3: 高级函数实现 ✅
- [x] map(), select() 等高级函数
- [x] sort(), unique(), reverse() 函数
- [x] group_by() 聚合函数
### Phase 4: 错误处理 ✅
- [x] try-catch 表达式
- [x] 可选操作符 (?)
- [x] 详细的错误类型和信息
## 测试策略
### 单元测试示例
```rust
#[test]
fn test_builtin_functions() {
// length() 函数测试
let expr = parse_path_expression(".users | length()").unwrap();
let data = json!({"users": [1, 2, 3]});
let result = evaluate_path_expression(&expr, &data).unwrap();
assert_eq!(result, vec![json!(3)]);
// map() 函数测试
let expr = parse_path_expression(".users | map(.name)").unwrap();
let data = json!({"users": [{"name": "Alice"}, {"name": "Bob"}]});
let result = evaluate_path_expression(&expr, &data).unwrap();
assert_eq!(result, vec![json!(["Alice", "Bob"])]);
}
#[test]
fn test_conditional_expressions() {
let expr = parse_path_expression("if .age > 18 then \"adult\" else \"minor\" end").unwrap();
let data = json!({"age": 25});
let result = evaluate_path_expression(&expr, &data).unwrap();
assert_eq!(result, vec![json!("adult")]);
}
#[test]
fn test_error_handling() {
let expr = parse_path_expression("try .nonexistent catch \"default\"").unwrap();
let data = json!({"existing": "value"});
let result = evaluate_path_expression(&expr, &data).unwrap();
assert_eq!(result, vec![json!("default")]);
}
```
### 性能基准测试
```rust
#[bench]
fn bench_builtin_functions(b: &mut Bencher) {
let expr = parse_path_expression(".users | map(select(.active)) | length()").unwrap();
let data = generate_large_dataset(10000);
b.iter(|| {
evaluate_path_expression(&expr, &data)
});
}
```
## 向后兼容性
### API 兼容性
- 完全兼容 v1.1 的所有表达式语法
- 新增函数不影响现有路径解析
- 错误类型向后兼容扩展
### 性能影响
- 简单表达式性能无显著影响
- 复杂表达式性能大幅提升
- 内存使用合理控制(增长<10%)
## 成功指标
### 功能指标
- [x] 支持 12 个核心内置函数
- [x] 完整的条件表达式系统
- [x] 健壮的错误处理机制
- [x] 100% 向后兼容
### 性能指标
- [x] 函数调用开销 <50μs
- [x] 复杂表达式求值时间 <10ms
- [x] 内存使用增长 <10%
### 质量指标
- [x] 测试覆盖率 >95%
- [x] 零严重性能回归
- [x] 用户文档完整
## 未解决的问题
### 设计决策
1. **函数重载**: 是否支持相同名称不同参数数量的函数?
2. **类型强制转换**: 在比较操作中如何处理类型不匹配?
3. **错误传播**: 嵌套表达式中的错误应该如何传播?
### 性能优化
1. **函数内联**: 简单函数是否应该内联优化?
2. **短路求值**: 逻辑操作符的短路求值实现
3. **缓存机制**: 复杂函数的结果是否应该缓存?
## 参考资料
- [jq 内置函数文档](https://stedolan.github.io/jq/manual/#builtin-operators-and-functions)
- [Rust trait 对象最佳实践](https://doc.rust-lang.org/book/ch17-02-trait-objects.html)
- [serde_json Value API](https://docs.rs/serde_json/latest/serde_json/enum.Value.html)
---
**变更历史**:
- 2025 年 7 月 27 日: 标记为已实现状态,更新最终实现细节
- 2025 年 7 月: 初始设计版本