2019-09-15 01:03:52 +08:00
|
|
|
use nom::{
|
|
|
|
IResult,
|
|
|
|
branch::alt,
|
|
|
|
bytes::complete::{tag, take_while1},
|
|
|
|
character::{is_digit, complete::char},
|
|
|
|
combinator::{map, value},
|
|
|
|
sequence::{preceded, tuple, Tuple},
|
|
|
|
multi::fold_many1,
|
|
|
|
error::ErrorKind,
|
|
|
|
};
|
2019-09-14 09:09:07 +08:00
|
|
|
use btoi::{btoi, ParseIntegerError};
|
2019-09-11 05:37:51 +08:00
|
|
|
use super::session::ReportMode;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub enum Error {
|
2019-09-15 01:03:52 +08:00
|
|
|
Parser(ErrorKind),
|
|
|
|
Incomplete,
|
|
|
|
UnexpectedInput(u8),
|
2019-09-14 09:09:07 +08:00
|
|
|
ParseInteger(ParseIntegerError)
|
|
|
|
}
|
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
impl<'t> From<nom::Err<(&'t [u8], ErrorKind)>> for Error {
|
|
|
|
fn from(e: nom::Err<(&'t [u8], ErrorKind)>) -> Self {
|
|
|
|
match e {
|
|
|
|
nom::Err::Incomplete(_) =>
|
|
|
|
Error::Incomplete,
|
|
|
|
nom::Err::Error((_, e)) =>
|
|
|
|
Error::Parser(e),
|
|
|
|
nom::Err::Failure((_, e)) =>
|
|
|
|
Error::Parser(e),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-14 09:09:07 +08:00
|
|
|
impl From<ParseIntegerError> for Error {
|
|
|
|
fn from(e: ParseIntegerError) -> Self {
|
|
|
|
Error::ParseInteger(e)
|
|
|
|
}
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
#[derive(Debug, Clone)]
|
2019-09-11 06:23:15 +08:00
|
|
|
pub enum ShowCommand {
|
2019-09-11 05:37:51 +08:00
|
|
|
ReportMode,
|
2019-09-12 22:12:03 +08:00
|
|
|
}
|
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
#[derive(Debug, Clone)]
|
2019-09-11 05:37:51 +08:00
|
|
|
pub enum Command {
|
|
|
|
Quit,
|
2019-09-11 06:23:15 +08:00
|
|
|
Show(ShowCommand),
|
2019-09-11 05:37:51 +08:00
|
|
|
Report(ReportMode),
|
2019-09-14 09:09:07 +08:00
|
|
|
Pwm {
|
2019-09-15 01:03:52 +08:00
|
|
|
width: u32,
|
|
|
|
total: u32,
|
2019-09-14 09:09:07 +08:00
|
|
|
},
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
fn whitespace(input: &[u8]) -> IResult<&[u8], ()> {
|
|
|
|
fold_many1(char(' '), (), |(), _| ())(input)
|
|
|
|
}
|
2019-09-11 05:37:51 +08:00
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
fn unsigned(input: &[u8]) -> IResult<&[u8], Result<u32, ParseIntegerError>> {
|
|
|
|
take_while1(is_digit)(input)
|
|
|
|
.map(|(input, digits)| (input, btoi(digits)))
|
|
|
|
}
|
2019-09-11 05:37:51 +08:00
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
fn report_mode(input: &[u8]) -> IResult<&[u8], ReportMode> {
|
|
|
|
alt((value(ReportMode::Off, tag("off")),
|
|
|
|
value(ReportMode::Once, tag("once")),
|
|
|
|
value(ReportMode::Continuous, tag("continuous"))
|
|
|
|
))(input)
|
|
|
|
}
|
2019-09-14 09:09:07 +08:00
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
fn report(input: &[u8]) -> IResult<&[u8], Command> {
|
|
|
|
preceded(
|
|
|
|
preceded(
|
|
|
|
tag("report"),
|
|
|
|
whitespace
|
|
|
|
),
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
preceded(
|
|
|
|
tag("mode"),
|
|
|
|
alt((
|
|
|
|
preceded(
|
|
|
|
whitespace,
|
|
|
|
map(report_mode,
|
|
|
|
|mode| Command::Report(mode))
|
|
|
|
),
|
|
|
|
|input| Ok((input, Command::Show(ShowCommand::ReportMode)))
|
|
|
|
))
|
|
|
|
)),
|
|
|
|
|input| Ok((input, Command::Report(ReportMode::Once)))
|
|
|
|
))
|
|
|
|
)(input)
|
|
|
|
}
|
2019-09-14 09:09:07 +08:00
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
fn pwm(input: &[u8]) -> IResult<&[u8], Result<Command, Error>> {
|
|
|
|
let (input, _) = tag("pwm")(input)?;
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, width) = unsigned(input)?;
|
|
|
|
let width = match width {
|
|
|
|
Ok(width) => width,
|
|
|
|
Err(e) => return Ok((input, Err(e.into()))),
|
|
|
|
};
|
|
|
|
let (input, _) = whitespace(input)?;
|
|
|
|
let (input, total) = unsigned(input)?;
|
|
|
|
let total = match total {
|
|
|
|
Ok(total) => total,
|
|
|
|
Err(e) => return Ok((input, Err(e.into()))),
|
|
|
|
};
|
|
|
|
Ok((input, Ok(Command::Pwm { width, total })))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn command(input: &[u8]) -> IResult<&[u8], Command> {
|
|
|
|
alt((value(Command::Quit, tag("quit")),
|
|
|
|
report
|
|
|
|
))(input)
|
|
|
|
}
|
2019-09-14 09:09:07 +08:00
|
|
|
|
2019-09-15 01:03:52 +08:00
|
|
|
impl Command {
|
|
|
|
pub fn parse(input: &[u8]) -> Result<Self, Error> {
|
|
|
|
match command(input) {
|
|
|
|
Ok((b"", command)) =>
|
|
|
|
Ok(command),
|
|
|
|
Ok((input_remain, _)) =>
|
|
|
|
Err(Error::UnexpectedInput(input_remain[0])),
|
|
|
|
Err(e) =>
|
|
|
|
Err(e.into()),
|
|
|
|
}
|
2019-09-11 05:37:51 +08:00
|
|
|
}
|
|
|
|
}
|