-
Notifications
You must be signed in to change notification settings - Fork 84
/
Copy pathping.rs
96 lines (86 loc) · 2.29 KB
/
ping.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! The assignment command parser.
//!
//! This can parse arbitrary input, giving the user to be assigned.
//!
//! The grammar is as follows:
//!
//! ```text
//! Command: `@bot ping <team>`.
//! ```
use crate::error::Error;
use crate::token::{Token, Tokenizer};
use std::fmt;
#[derive(PartialEq, Eq, Debug)]
pub struct PingCommand {
pub team: String,
}
#[derive(PartialEq, Eq, Debug)]
pub enum ParseError {
ExpectedEnd,
NoTeam,
}
impl std::error::Error for ParseError {}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ParseError::ExpectedEnd => write!(f, "expected end of command"),
ParseError::NoTeam => write!(f, "no team specified"),
}
}
}
impl PingCommand {
pub fn parse<'a>(input: &mut Tokenizer<'a>) -> Result<Option<Self>, Error<'a>> {
let mut toks = input.clone();
if let Some(Token::Word("ping")) = toks.peek_token()? {
toks.next_token()?;
let team = if let Some(Token::Word(team)) = toks.next_token()? {
team.to_owned()
} else {
return Err(toks.error(ParseError::NoTeam));
};
if let Some(Token::Dot) | Some(Token::EndOfLine) = toks.peek_token()? {
toks.next_token()?;
*input = toks;
return Ok(Some(PingCommand { team }));
} else {
return Err(toks.error(ParseError::ExpectedEnd));
}
} else {
return Ok(None);
}
}
}
#[cfg(test)]
fn parse<'a>(input: &'a str) -> Result<Option<PingCommand>, Error<'a>> {
let mut toks = Tokenizer::new(input);
Ok(PingCommand::parse(&mut toks)?)
}
#[test]
fn test_1() {
assert_eq!(
parse("ping LLVM-icebreakers."),
Ok(Some(PingCommand {
team: "LLVM-icebreakers".into()
}))
);
}
#[test]
fn test_2() {
use std::error::Error;
assert_eq!(
parse("ping foo foo")
.unwrap_err()
.source()
.unwrap()
.downcast_ref(),
Some(&ParseError::ExpectedEnd),
);
}
#[test]
fn test_3() {
use std::error::Error;
assert_eq!(
parse("ping").unwrap_err().source().unwrap().downcast_ref(),
Some(&ParseError::NoTeam),
);
}