yogurt/argument/
parser.rs1use crate::{Error, InvalidCommandReason, Result};
2use std::fmt::Debug;
3
4pub trait ArgumentParser: Debug + Clone {
5 type Output;
6
7 fn parse(&self, token: &str) -> Result<Self::Output>;
8
9 fn validator(&self) -> fn(&str) -> bool;
10}
11
12#[derive(Debug, Clone)]
13pub struct StringArgument;
14
15impl ArgumentParser for StringArgument {
16 type Output = String;
17
18 fn parse(&self, token: &str) -> Result<Self::Output> {
19 Ok(token.to_string())
20 }
21
22 fn validator(&self) -> fn(&str) -> bool {
23 |_| true
24 }
25}
26
27#[derive(Debug, Clone)]
28pub struct IntArgument;
29
30impl ArgumentParser for IntArgument {
31 type Output = i32;
32
33 fn parse(&self, token: &str) -> Result<Self::Output> {
34 token
35 .parse()
36 .map_err(|_| Error::InvalidCommand(InvalidCommandReason::InvalidArgument))
37 }
38
39 fn validator(&self) -> fn(&str) -> bool {
40 |str| str.parse::<i32>().is_ok()
41 }
42}
43
44#[derive(Debug, Clone)]
45pub struct BoundedIntArgument {
46 min: i32,
47 max: i32,
48}
49
50impl ArgumentParser for BoundedIntArgument {
51 type Output = i32;
52
53 fn parse(&self, token: &str) -> Result<Self::Output> {
54 let int: i32 = token
55 .parse()
56 .map_err(|_| Error::InvalidCommand(InvalidCommandReason::InvalidArgument))?;
57 if int <= self.max && int >= self.min {
58 Ok(int)
59 } else {
60 Err(Error::InvalidCommand(InvalidCommandReason::InvalidArgument))
61 }
62 }
63
64 fn validator(&self) -> fn(&str) -> bool {
65 |str| str.parse::<i32>().is_ok()
66 }
67}
68
69#[derive(Debug, Clone)]
70pub struct ChoiceArgument(Vec<String>);
71
72impl ArgumentParser for ChoiceArgument {
73 type Output = String;
74
75 fn parse(&self, token: &str) -> Result<Self::Output> {
76 let token = token.to_string();
77 if self.0.contains(&token) {
78 Ok(token)
79 } else {
80 Err(Error::InvalidCommand(InvalidCommandReason::InvalidArgument))
81 }
82 }
83
84 fn validator(&self) -> fn(&str) -> bool {
85 |_| true
86 }
87}