From 610af7659260f531b96867d758a3522477d35e20 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Sat, 1 Jun 2019 23:04:31 +0000 Subject: [PATCH] rust: esp8266at: Wrap parsing of responses to avoid exposing dependency on nom Makes it possible to switch parser later for whatever reason, it's undesirable to expose these implementation details to clients. --- rust/esp8266at/examples/parsetest.rs | 14 ++++++++------ rust/esp8266at/src/mainloop.rs | 17 ++++++++--------- rust/esp8266at/src/response.rs | 21 ++++++++++++++++++--- rust/weather/Cargo.toml | 1 - rust/weather/src/main.rs | 15 +++++++-------- 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/rust/esp8266at/examples/parsetest.rs b/rust/esp8266at/examples/parsetest.rs index 73ea3bf..3022792 100644 --- a/rust/esp8266at/examples/parsetest.rs +++ b/rust/esp8266at/examples/parsetest.rs @@ -2,7 +2,7 @@ use std::fs::File; use std::io::BufRead; use std::io::BufReader; -use esp8266at::response::parse_response; +use esp8266at::response::{parse,ParseResult}; fn main() { let f = File::open("data/parses.txt").unwrap(); @@ -13,14 +13,16 @@ fn main() { let mut lb = l[2..].as_bytes().to_vec(); lb.push(13); lb.push(10); - let res = parse_response(&lb); + let res = parse(&lb); match res { - Err(x) => { + ParseResult::Err => { println!("failed command was: {}", l); - println!("{:?}", x); } - Ok((res, x)) => { - if res.is_empty() { + ParseResult::Incomplete => { + println!("incomplete command was: {}", l); + } + ParseResult::Ok(res, x) => { + if res == lb.len() { println!("{:?}", x); } else { println!("non-empty residue command was: {}", l); diff --git a/rust/esp8266at/src/mainloop.rs b/rust/esp8266at/src/mainloop.rs index ddbf1b1..671c6e5 100644 --- a/rust/esp8266at/src/mainloop.rs +++ b/rust/esp8266at/src/mainloop.rs @@ -1,10 +1,9 @@ /** Example synchronous serial receive event loop (for std) */ -use nom::Offset; use std::fmt; use std::io; use crate::handler::{NetworkEvent, SerialNetworkHandler}; -use crate::response::parse_response; +use crate::response::{parse, ParseResult}; /** Mainloop handling serial input and dispatching network events */ pub fn mainloop( @@ -34,24 +33,24 @@ where while start < ofs { // try parsing let tail = &serial_buf[start..ofs]; - let erase = match parse_response(tail) { - Ok((residue, resp)) => { + let erase = match parse(tail) { + ParseResult::Ok(offset, resp) => { h.message( &resp, - &mut |a, b, debug| { + |a, b, debug| { running = f(a, b, debug); }, debug, )?; - tail.offset(residue) + offset } - Err(nom::Err::Incomplete(_)) => { + ParseResult::Incomplete => { // Incomplete, ignored, just retry after a new receive 0 } - Err(err) => { - writeln!(debug, "err: {:?}", err).unwrap(); + ParseResult::Err => { + writeln!(debug, "err: {:?}", tail).unwrap(); // Erase unparseable data to next line, if line is complete if let Some(ofs) = tail.iter().position(|&x| x == b'\n') { ofs + 1 diff --git a/rust/esp8266at/src/response.rs b/rust/esp8266at/src/response.rs index 8e7772e..0c128b9 100644 --- a/rust/esp8266at/src/response.rs +++ b/rust/esp8266at/src/response.rs @@ -1,6 +1,6 @@ -use core::str; /** Parser for ESP8266 AT responses */ -use nom::{digit, hex_digit}; +use core::str; +use nom::{Offset, digit, hex_digit}; /** Connection type for CIPSTATUS etc */ #[derive(Debug, Copy, Clone, PartialEq, Eq)] @@ -73,6 +73,13 @@ pub enum Response<'a> { RecvPrompt, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ParseResult<'a> { + Ok(usize, Response<'a>), + Incomplete, + Err, +} + /* Decimal unsigned integer */ named!(num_u32<&[u8], u32>, // The unwrap() here is safe because digit will never return non-UTF8 @@ -279,7 +286,7 @@ named!(ipd_data<&[u8],Response>, ); /* Parse response from line */ -named!(pub parse_response<&[u8],Response>, +named!(parse_response<&[u8],Response>, alt!( nl_terminated | ipd_data @@ -288,6 +295,14 @@ named!(pub parse_response<&[u8],Response>, ) ); +pub fn parse(response: &[u8]) -> ParseResult { + match parse_response(response) { + Ok((residue, resp)) => ParseResult::Ok(response.offset(residue), resp), + Err(nom::Err::Incomplete(_)) => ParseResult::Incomplete, + Err(_) => ParseResult::Err, + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/rust/weather/Cargo.toml b/rust/weather/Cargo.toml index 5745c16..91d47fe 100644 --- a/rust/weather/Cargo.toml +++ b/rust/weather/Cargo.toml @@ -13,4 +13,3 @@ riscv = "0.5" k210-shared = { path = "../k210-shared" } k210-console = { path = "../k210-console" } esp8266at = { path = "../esp8266at", default-features = false } -nom = { version = "4", default-features = false } diff --git a/rust/weather/src/main.rs b/rust/weather/src/main.rs index 2c2899f..d9694d7 100644 --- a/rust/weather/src/main.rs +++ b/rust/weather/src/main.rs @@ -7,7 +7,7 @@ use core::str; use embedded_hal::serial; use esp8266at::handler::{NetworkEvent, SerialNetworkHandler}; -use esp8266at::response::{parse_response, ConnectionType}; +use esp8266at::response::{parse, ConnectionType, ParseResult}; use esp8266at::traits::{self, Write}; use k210_hal::pac; use k210_hal::prelude::*; @@ -21,7 +21,6 @@ use k210_shared::soc::sleep::usleep; use k210_shared::soc::spi::SPIExt; use k210_shared::soc::sysctl; use nb::block; -use nom::Offset; use riscv::register::mcycle; use riscv_rt::entry; use k210_console::console::{Console, ScreenImage, DISP_HEIGHT, DISP_WIDTH}; @@ -159,8 +158,8 @@ fn main() -> ! { while start < ofs { // try parsing let tail = &serial_buf[start..ofs]; - let erase = match parse_response(tail) { - Ok((residue, resp)) => { + let erase = match parse(tail) { + ParseResult::Ok(offset, resp) => { sh.message(&resp, |port, ev, _debug| { match ev { NetworkEvent::Ready => { @@ -195,17 +194,17 @@ fn main() -> ! { } }, &mut debug).unwrap(); - tail.offset(residue) + offset } - Err(nom::Err::Incomplete(_)) => { + ParseResult::Incomplete => { // Incomplete, ignored, just retry after a new receive 0 } - Err(err) => { + ParseResult::Err => { if tail.len() > 100 { writeln!(debug, "err: Error([too long ...])").unwrap(); } else { - writeln!(debug, "err: {:?}", err).unwrap(); + writeln!(debug, "err: {:?}", tail).unwrap(); } // Erase unparseable data to next line, if line is complete if let Some(ofs) = tail.iter().position(|&x| x == b'\n') {