Skip to main content

hatter/eval/
args.rs

1use {
2    crate::{Env, Result, Value},
3    std::{ops, vec},
4};
5
6/// The `Args` struct makes it easier to work with arguments when
7/// writing Hatter functions in Rust.
8#[derive(Debug)]
9pub struct Args<'e> {
10    pub env: &'e mut Env,
11    args: Vec<Value>,
12}
13
14impl<'e> ops::Deref for Args<'e> {
15    type Target = Vec<Value>;
16    fn deref(&self) -> &Self::Target {
17        &self.args
18    }
19}
20
21impl<'e> ops::DerefMut for Args<'e> {
22    fn deref_mut(&mut self) -> &mut Self::Target {
23        &mut self.args
24    }
25}
26
27impl<'e> IntoIterator for Args<'e> {
28    type Item = Value;
29    type IntoIter = vec::IntoIter<Value>;
30    fn into_iter(self) -> Self::IntoIter {
31        self.args.into_iter()
32    }
33}
34
35impl<'e> Args<'e> {
36    pub fn new(env: &'e mut Env, args: Vec<Value>) -> Args<'e> {
37        Args { env, args }
38    }
39
40    pub fn get(&self, idx: usize) -> Option<&Value> {
41        self.args.get(idx)
42    }
43
44    /// Like `get()` but returns an error.
45    pub fn need(&self, idx: usize) -> Result<Value> {
46        self.args.get(idx).map(Value::clone).ok_or(error_kind!(
47            ArgNotFound,
48            "Argument Not Found: {}",
49            idx
50        ))
51    }
52
53    /// Errors if the arg doesn't exist or isn't a Number.
54    pub fn need_number(&self, idx: usize) -> Result<f64> {
55        if let Value::Number(num) = self.need(idx)? {
56            Ok(num)
57        } else {
58            Err(error_kind!(
59                WrongArgType,
60                "Expected Number, got: {:?}",
61                self.need(idx)?
62            ))
63        }
64    }
65
66    /// Errors if the arg doesn't exist or isn't a String.
67    pub fn need_string(&self, idx: usize) -> Result<&str> {
68        if let Some(Value::String(s)) = self.args.get(idx) {
69            Ok(s.to_str())
70        } else {
71            Err(error_kind!(
72                WrongArgType,
73                "Expected String, got: {:?}",
74                self.need(idx)?
75            ))
76        }
77    }
78
79    /// Errors if the arg doesn't exist or isn't a String.
80    pub fn need_list(&self, idx: usize) -> Result<Value> {
81        if let Some(li @ Value::List(..)) = self.args.get(idx) {
82            Ok(li.clone())
83        } else {
84            Err(error_kind!(
85                WrongArgType,
86                "Expected List, got: {:?}",
87                self.need(idx)?
88            ))
89        }
90    }
91}