use crate::variable::{DynamicVariable, RcCell};
use crate::Variable;
use ahash::HashMap;
use anyhow::Context;
use rust_decimal::Decimal;
use std::ops::Deref;
use std::rc::Rc;
pub struct Arguments<'a>(pub &'a [Variable]);
impl<'a> Deref for Arguments<'a> {
type Target = [Variable];
fn deref(&self) -> &'a Self::Target {
&self.0
}
}
impl<'a> Arguments<'a> {
pub fn ovar(
&self,
pos: usize,
) -> Option<&'a Variable> {
self.0.get(pos)
}
pub fn var(
&self,
pos: usize,
) -> anyhow::Result<&'a Variable> {
self.ovar(pos).with_context(|| format!("参数索引越界: {pos}"))
}
pub fn obool(
&self,
pos: usize,
) -> anyhow::Result<Option<bool>> {
match self.ovar(pos) {
Some(v) => v
.as_bool()
.map(Some)
.with_context(|| format!("参数索引 {pos} 不是布尔类型")),
None => Ok(None),
}
}
pub fn bool(
&self,
pos: usize,
) -> anyhow::Result<bool> {
self.obool(pos)?.with_context(|| format!("参数索引 {pos} 不是布尔类型"))
}
pub fn ostr(
&self,
pos: usize,
) -> anyhow::Result<Option<&'a str>> {
match self.ovar(pos) {
Some(v) => v
.as_str()
.map(Some)
.with_context(|| format!("参数索引 {pos} 不是字符串类型")),
None => Ok(None),
}
}
pub fn str(
&self,
pos: usize,
) -> anyhow::Result<&'a str> {
self.ostr(pos)?
.with_context(|| format!("参数索引 {pos} 不是字符串类型"))
}
pub fn onumber(
&self,
pos: usize,
) -> anyhow::Result<Option<Decimal>> {
match self.ovar(pos) {
Some(v) => v
.as_number()
.map(Some)
.with_context(|| format!("参数索引 {pos} 不是数字类型")),
None => Ok(None),
}
}
pub fn number(
&self,
pos: usize,
) -> anyhow::Result<Decimal> {
self.onumber(pos)?
.with_context(|| format!("参数索引 {pos} 不是数字类型"))
}
pub fn oarray(
&self,
pos: usize,
) -> anyhow::Result<Option<RcCell<Vec<Variable>>>> {
match self.ovar(pos) {
Some(v) => v
.as_array()
.map(Some)
.with_context(|| format!("参数索引 {pos} 不是数组类型")),
None => Ok(None),
}
}
pub fn array(
&self,
pos: usize,
) -> anyhow::Result<RcCell<Vec<Variable>>> {
self.oarray(pos)?
.with_context(|| format!("参数索引 {pos} 不是数组类型"))
}
pub fn oobject(
&self,
pos: usize,
) -> anyhow::Result<Option<RcCell<HashMap<Rc<str>, Variable>>>> {
match self.ovar(pos) {
Some(v) => v
.as_object()
.map(Some)
.with_context(|| format!("参数索引 {pos} 不是对象类型")),
None => Ok(None),
}
}
pub fn object(
&self,
pos: usize,
) -> anyhow::Result<RcCell<HashMap<Rc<str>, Variable>>> {
self.oobject(pos)?
.with_context(|| format!("参数索引 {pos} 不是对象类型"))
}
pub fn odynamic<T: DynamicVariable + 'static>(
&self,
pos: usize,
) -> anyhow::Result<Option<&T>> {
match self.ovar(pos) {
None => Ok(None),
Some(s) => Ok(s.dynamic::<T>()),
}
}
pub fn dynamic<T: DynamicVariable + 'static>(
&self,
pos: usize,
) -> anyhow::Result<&T> {
self.odynamic(pos)?
.with_context(|| format!("参数索引 {pos} 不是动态类型"))
}
}