Advertisement
Guest User

Untitled

a guest
Apr 26th, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.34 KB | None | 0 0
  1. use nom::is_alphabetic;
  2. use std::str;
  3.  
  4. #[derive(Debug, PartialEq, Eq)]
  5. pub enum Keyword {
  6. Unknown,
  7. Help,
  8. Echo,
  9. }
  10.  
  11. #[derive(Debug, PartialEq, Eq)]
  12. pub enum Command {
  13. Unknown,
  14. Help,
  15. Echo(String),
  16. }
  17.  
  18. fn to_keyword(s: &[u8]) -> Keyword {
  19. if compare_no_case(&s, b"help") {
  20. return Keyword::Help;
  21. } else if compare_no_case(&s, b"echo") {
  22. return Keyword::Echo;
  23. }
  24.  
  25. Keyword::Unknown
  26. }
  27.  
  28. fn is_argument_char(i: u8) -> bool {
  29. !b"\r\n".contains(&i)
  30. }
  31.  
  32. pub fn to_command(keyword: Keyword, argument: &[u8]) -> Command {
  33. match keyword {
  34. Keyword::Unknown => Command::Unknown,
  35. Keyword::Help => Command::Help,
  36. Keyword::Echo => Command::Echo(str::from_utf8(argument).unwrap().into()),
  37. }
  38. }
  39.  
  40. fn is_token_char(i: u8) -> bool {
  41. is_alphabetic(i) || b"_-".contains(&i)
  42. }
  43.  
  44. pub fn compare_no_case(left: &[u8], right: &[u8]) -> bool {
  45. if left.len() != right.len() {
  46. return false;
  47. }
  48.  
  49. left.iter().zip(right).all(|(a, b)| match (*a, *b) {
  50. (0...64, 0...64) | (91...96, 91...96) | (123...255, 123...255) => a == b,
  51. (65...90, 65...90) | (97...122, 97...122) | (65...90, 97...122) | (97...122, 65...90) => {
  52. *a | 0b00_10_00_00 == *b | 0b00_10_00_00
  53. }
  54. _ => false,
  55. })
  56. }
  57.  
  58. named!(eoc, alt!(tag!("\n") | tag!("\r\n")));
  59. named!(space, alt!(tag!(" ") | tag!("\t")));
  60. named!(keyword<&[u8], Keyword>, map!(take_while!(is_token_char), to_keyword));
  61. named!(argument, take_while!(is_argument_char));
  62.  
  63. named!(command<&[u8], Command>,
  64. do_parse!(
  65. tag!("!") >>
  66. keyword: keyword >>
  67. opt!(space) >>
  68. argument: argument >>
  69. eoc >>
  70. (to_command(keyword, argument))
  71. )
  72. );
  73.  
  74. pub fn parse(input: &str) -> Result<Command, nom::Err<&[u8]>> {
  75. let result = command(input.as_bytes())?;
  76. Ok(result.1)
  77. }
  78.  
  79. #[cfg(test)]
  80. mod tests {
  81. use crate::parser::*;
  82.  
  83. #[test]
  84. fn parse_command_with_crlf() {
  85. assert_eq!(parse("!help\r\n"), Ok(Command::Help));
  86. }
  87.  
  88. #[test]
  89. fn parse_command_with_lf() {
  90. assert_eq!(parse("!help\n"), Ok(Command::Help));
  91. }
  92.  
  93. #[test]
  94. fn parse_unknown_command() {
  95. assert_eq!(parse("!omg\n"), Ok(Command::Unknown));
  96. }
  97.  
  98. #[test]
  99. fn parse_command_with_argument() {
  100. assert_eq!(parse("!echo omg\n"), Ok(Command::Echo("omg".into())));
  101. }
  102. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement