mf_expression/functions/
arguments.rs

1//! 函数参数处理模块
2//!
3//! 提供便捷的参数访问方法,支持类型检查和错误处理
4
5use crate::variable::{DynamicVariable, RcCell};
6use crate::Variable;
7use ahash::HashMap;
8use anyhow::Context;
9use rust_decimal::Decimal;
10use std::ops::Deref;
11use std::rc::Rc;
12
13/// 函数参数包装器
14///
15/// 提供对函数参数切片的便捷访问方法
16pub struct Arguments<'a>(pub &'a [Variable]);
17
18impl<'a> Deref for Arguments<'a> {
19    type Target = [Variable];
20
21    fn deref(&self) -> &'a Self::Target {
22        &self.0
23    }
24}
25
26impl<'a> Arguments<'a> {
27    /// 获取可选变量(返回Option)
28    ///
29    /// # 参数
30    /// * `pos` - 参数位置索引
31    ///
32    /// # 返回值
33    /// * `Some(&Variable)` - 参数存在
34    /// * `None` - 参数不存在(索引越界)
35    pub fn ovar(
36        &self,
37        pos: usize,
38    ) -> Option<&'a Variable> {
39        self.0.get(pos)
40    }
41
42    /// 获取必需变量(返回Result)
43    ///
44    /// # 参数
45    /// * `pos` - 参数位置索引
46    ///
47    /// # 返回值
48    /// * `Ok(&Variable)` - 参数存在
49    /// * `Err` - 参数不存在或索引越界
50    pub fn var(
51        &self,
52        pos: usize,
53    ) -> anyhow::Result<&'a Variable> {
54        self.ovar(pos).with_context(|| format!("参数索引越界: {pos}"))
55    }
56
57    /// 获取可选布尔值
58    ///
59    /// # 参数
60    /// * `pos` - 参数位置索引
61    ///
62    /// # 返回值
63    /// * `Ok(Some(bool))` - 参数存在且为布尔类型
64    /// * `Ok(None)` - 参数不存在
65    /// * `Err` - 参数存在但不是布尔类型
66    pub fn obool(
67        &self,
68        pos: usize,
69    ) -> anyhow::Result<Option<bool>> {
70        match self.ovar(pos) {
71            Some(v) => v
72                .as_bool()
73                .map(Some)
74                .with_context(|| format!("参数索引 {pos} 不是布尔类型")),
75            None => Ok(None),
76        }
77    }
78
79    /// 获取必需布尔值
80    ///
81    /// # 参数
82    /// * `pos` - 参数位置索引
83    ///
84    /// # 返回值
85    /// * `Ok(bool)` - 参数存在且为布尔类型
86    /// * `Err` - 参数不存在或不是布尔类型
87    pub fn bool(
88        &self,
89        pos: usize,
90    ) -> anyhow::Result<bool> {
91        self.obool(pos)?.with_context(|| format!("参数索引 {pos} 不是布尔类型"))
92    }
93
94    /// 获取可选字符串
95    ///
96    /// # 参数
97    /// * `pos` - 参数位置索引
98    ///
99    /// # 返回值
100    /// * `Ok(Some(&str))` - 参数存在且为字符串类型
101    /// * `Ok(None)` - 参数不存在
102    /// * `Err` - 参数存在但不是字符串类型
103    pub fn ostr(
104        &self,
105        pos: usize,
106    ) -> anyhow::Result<Option<&'a str>> {
107        match self.ovar(pos) {
108            Some(v) => v
109                .as_str()
110                .map(Some)
111                .with_context(|| format!("参数索引 {pos} 不是字符串类型")),
112            None => Ok(None),
113        }
114    }
115
116    /// 获取必需字符串
117    ///
118    /// # 参数
119    /// * `pos` - 参数位置索引
120    ///
121    /// # 返回值
122    /// * `Ok(&str)` - 参数存在且为字符串类型
123    /// * `Err` - 参数不存在或不是字符串类型
124    pub fn str(
125        &self,
126        pos: usize,
127    ) -> anyhow::Result<&'a str> {
128        self.ostr(pos)?
129            .with_context(|| format!("参数索引 {pos} 不是字符串类型"))
130    }
131
132    /// 获取可选数字
133    ///
134    /// # 参数
135    /// * `pos` - 参数位置索引
136    ///
137    /// # 返回值
138    /// * `Ok(Some(Decimal))` - 参数存在且为数字类型
139    /// * `Ok(None)` - 参数不存在
140    /// * `Err` - 参数存在但不是数字类型
141    pub fn onumber(
142        &self,
143        pos: usize,
144    ) -> anyhow::Result<Option<Decimal>> {
145        match self.ovar(pos) {
146            Some(v) => v
147                .as_number()
148                .map(Some)
149                .with_context(|| format!("参数索引 {pos} 不是数字类型")),
150            None => Ok(None),
151        }
152    }
153
154    /// 获取必需数字
155    ///
156    /// # 参数
157    /// * `pos` - 参数位置索引
158    ///
159    /// # 返回值
160    /// * `Ok(Decimal)` - 参数存在且为数字类型
161    /// * `Err` - 参数不存在或不是数字类型
162    pub fn number(
163        &self,
164        pos: usize,
165    ) -> anyhow::Result<Decimal> {
166        self.onumber(pos)?
167            .with_context(|| format!("参数索引 {pos} 不是数字类型"))
168    }
169
170    /// 获取可选数组
171    ///
172    /// # 参数
173    /// * `pos` - 参数位置索引
174    ///
175    /// # 返回值
176    /// * `Ok(Some(RcCell<Vec<Variable>>))` - 参数存在且为数组类型
177    /// * `Ok(None)` - 参数不存在
178    /// * `Err` - 参数存在但不是数组类型
179    pub fn oarray(
180        &self,
181        pos: usize,
182    ) -> anyhow::Result<Option<RcCell<Vec<Variable>>>> {
183        match self.ovar(pos) {
184            Some(v) => v
185                .as_array()
186                .map(Some)
187                .with_context(|| format!("参数索引 {pos} 不是数组类型")),
188            None => Ok(None),
189        }
190    }
191
192    /// 获取必需数组
193    ///
194    /// # 参数
195    /// * `pos` - 参数位置索引
196    ///
197    /// # 返回值
198    /// * `Ok(RcCell<Vec<Variable>>)` - 参数存在且为数组类型
199    /// * `Err` - 参数不存在或不是数组类型
200    pub fn array(
201        &self,
202        pos: usize,
203    ) -> anyhow::Result<RcCell<Vec<Variable>>> {
204        self.oarray(pos)?
205            .with_context(|| format!("参数索引 {pos} 不是数组类型"))
206    }
207
208    /// 获取可选对象
209    ///
210    /// # 参数
211    /// * `pos` - 参数位置索引
212    ///
213    /// # 返回值
214    /// * `Ok(Some(RcCell<HashMap<Rc<str>, Variable>>))` - 参数存在且为对象类型
215    /// * `Ok(None)` - 参数不存在
216    /// * `Err` - 参数存在但不是对象类型
217    pub fn oobject(
218        &self,
219        pos: usize,
220    ) -> anyhow::Result<Option<RcCell<HashMap<Rc<str>, Variable>>>> {
221        match self.ovar(pos) {
222            Some(v) => v
223                .as_object()
224                .map(Some)
225                .with_context(|| format!("参数索引 {pos} 不是对象类型")),
226            None => Ok(None),
227        }
228    }
229
230    /// 获取必需对象
231    ///
232    /// # 参数
233    /// * `pos` - 参数位置索引
234    ///
235    /// # 返回值
236    /// * `Ok(RcCell<HashMap<Rc<str>, Variable>>)` - 参数存在且为对象类型
237    /// * `Err` - 参数不存在或不是对象类型
238    pub fn object(
239        &self,
240        pos: usize,
241    ) -> anyhow::Result<RcCell<HashMap<Rc<str>, Variable>>> {
242        self.oobject(pos)?
243            .with_context(|| format!("参数索引 {pos} 不是对象类型"))
244    }
245
246    /// 获取可选动态类型变量
247    ///
248    /// # 类型参数
249    /// * `T` - 实现DynamicVariable特征的类型
250    ///
251    /// # 参数
252    /// * `pos` - 参数位置索引
253    ///
254    /// # 返回值
255    /// * `Ok(Some(&T))` - 参数存在且为指定动态类型
256    /// * `Ok(None)` - 参数不存在或不是指定动态类型
257    /// * `Err` - 发生其他错误
258    pub fn odynamic<T: DynamicVariable + 'static>(
259        &self,
260        pos: usize,
261    ) -> anyhow::Result<Option<&T>> {
262        match self.ovar(pos) {
263            None => Ok(None),
264            Some(s) => Ok(s.dynamic::<T>()),
265        }
266    }
267
268    /// 获取必需动态类型变量
269    ///
270    /// # 类型参数
271    /// * `T` - 实现DynamicVariable特征的类型
272    ///
273    /// # 参数
274    /// * `pos` - 参数位置索引
275    ///
276    /// # 返回值
277    /// * `Ok(&T)` - 参数存在且为指定动态类型
278    /// * `Err` - 参数不存在或不是指定动态类型
279    pub fn dynamic<T: DynamicVariable + 'static>(
280        &self,
281        pos: usize,
282    ) -> anyhow::Result<&T> {
283        self.odynamic(pos)?
284            .with_context(|| format!("参数索引 {pos} 不是动态类型"))
285    }
286}