diff --git a/pkgs/mx-sanebot/src/msg_handler.rs b/pkgs/mx-sanebot/src/msg_handler.rs index f4f523dc..4c69d7f4 100644 --- a/pkgs/mx-sanebot/src/msg_handler.rs +++ b/pkgs/mx-sanebot/src/msg_handler.rs @@ -3,7 +3,7 @@ use std::fmt; use std::process; use std::str; -use super::parsing; +use super::parsing::{self, Parser}; mod tt { @@ -12,6 +12,7 @@ mod tt { Lit, Then, }; + use crate::ilit; // grammar: // REQUEST = (HELP | BT | BT-ADD) @@ -26,15 +27,15 @@ mod tt { pub(super) type Bang = Lit<{ '!' as u8 }>; pub(super) type Help = Then< - Lit<{ 'H' as u8 }>, Then< - Lit<{ 'E' as u8 }>, Then< - Lit<{ 'L' as u8 }>, - Lit<{ 'P' as u8 }>, + ilit!('H'), Then< + ilit!('E'), Then< + ilit!('L'), + ilit!('P'), >>>; pub(super) type Bt = Then< - Lit<{ 'B' as u8 }>, - Lit<{ 'T' as u8 }>, + ilit!('B'), + ilit!('T'), >; } @@ -51,11 +52,9 @@ impl MessageHandler { } fn parse_msg(&self, msg: &str) -> Result { - let msg = msg.trim(); - match msg { - "!help" => Ok(Request::Help), - "!bt" => Ok(Request::Bt), - _ => Err(()) + match msg.as_bytes().parse_all::() { + Ok(req) => Ok(req.into()), + Err(_) => Err(()), } } } diff --git a/pkgs/mx-sanebot/src/parsing.rs b/pkgs/mx-sanebot/src/parsing.rs index 4e75f039..307ecb36 100644 --- a/pkgs/mx-sanebot/src/parsing.rs +++ b/pkgs/mx-sanebot/src/parsing.rs @@ -15,7 +15,12 @@ pub enum Either { } // case-insensitive u8 character. -// type ILit = Either, Lit<{ BYTE.to_ascii_uppercase() }>>; +#[macro_export] +macro_rules! ilit { + ($BYTE:literal) => { + Either, Lit<{ ($BYTE as u8).to_ascii_uppercase() }>> + } +} pub type PResult = std::result::Result<(C, P), P>; @@ -37,6 +42,25 @@ pub trait Parser: Sized { } } +impl<'a> Parser for &'a [u8] { + fn expect_byte(self, b: Option) -> PResult { + match (b, self.split_first()) { + // expected the correct character + (Some(exp), Some((first, rest))) if *first == exp => Ok( ((), rest) ), + // expected EOF, got EOF + (None, None) => Ok( ((), self)), + _ => Err(self), + } + } + fn expect(self) -> PResult { + match C::consume(self.clone()) { + Ok(res) => Ok(res), + // rewind the parser should we fail + Err(_p) => Err(self), + } + } +} + pub trait Parse: Sized { fn consume(p: P) -> PResult; }