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}