Issues with nom 6 error type

This commit is contained in:
Dominik Werder
2021-04-16 16:15:53 +02:00
parent 55376b4405
commit dff9cd770c
4 changed files with 114 additions and 35 deletions

View File

@@ -21,6 +21,9 @@ tracing = "0.1.25"
fs2 = "0.4.3" fs2 = "0.4.3"
libc = "0.2.93" libc = "0.2.93"
hex = "0.4.3" hex = "0.4.3"
nom = "6.1.2"
num-traits = "0.2"
num-derive = "0.3"
tiny-keccak = { version = "2.0", features = ["sha3"] } tiny-keccak = { version = "2.0", features = ["sha3"] }
err = { path = "../err" } err = { path = "../err" }
taskrun = { path = "../taskrun" } taskrun = { path = "../taskrun" }

View File

@@ -1,5 +1,7 @@
use crate::{BadError, Error}; use err::Error;
use nom::error::{ErrorKind, VerboseError};
use nom::number::complete::{be_i16, be_i32, be_i64, be_i8, be_u8}; use nom::number::complete::{be_i16, be_i32, be_i64, be_i8, be_u8};
use nom::Needed;
#[allow(unused_imports)] #[allow(unused_imports)]
use nom::{ use nom::{
bytes::complete::{tag, take, take_while_m_n}, bytes::complete::{tag, take, take_while_m_n},
@@ -9,7 +11,9 @@ use nom::{
}; };
use num_derive::{FromPrimitive, ToPrimitive}; use num_derive::{FromPrimitive, ToPrimitive};
use num_traits::ToPrimitive; use num_traits::ToPrimitive;
use serde_derive::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[allow(unused_imports)]
use tracing::{debug, error, info, trace, warn};
#[derive(Debug, FromPrimitive, ToPrimitive, Serialize, Deserialize)] #[derive(Debug, FromPrimitive, ToPrimitive, Serialize, Deserialize)]
pub enum DType { pub enum DType {
@@ -85,35 +89,44 @@ pub struct Config {
pub entries: Vec<ConfigEntry>, pub entries: Vec<ConfigEntry>,
} }
fn parseShortString(inp: &[u8]) -> Result<(&[u8], Option<String>), Error> { fn parse_short_string(inp: &[u8]) -> IResult<&[u8], Option<String>> {
let (inp, len1) = be_i32(inp)?; let (inp, len1) = be_i32(inp)?;
if len1 == -1 { if len1 == -1 {
return Ok((inp, None)); return Ok((inp, None));
} }
if len1 < 4 { if len1 < 4 {
return BadError(format!("bad string len {}", len1)); error!("bad string len {}", len1);
let err = nom::error::make_error(inp, ErrorKind::Verify);
return Err(nom::Err::Error(err));
} }
if len1 > 500 { if len1 > 500 {
return BadError(format!("large string len {}", len1)); error!("large string len {}", len1);
let err = nom::error::make_error(inp, ErrorKind::Verify);
return Err(nom::Err::Error(err));
} }
let (inp, snb) = take((len1 - 4) as usize)(inp)?; let (inp, snb) = take((len1 - 4) as usize)(inp)?;
let s1 = String::from_utf8(snb.to_vec())?; match String::from_utf8(snb.to_vec()) {
Ok((inp, Some(s1))) Ok(s1) => Ok((inp, Some(s1))),
Err(e) => {
let err = nom::error::make_error(inp, ErrorKind::Verify);
Err(nom::Err::Error(err))
}
}
} }
/* pub fn parse_entry(inp: &[u8]) -> IResult<&[u8], Option<ConfigEntry>> {
Parse a single configuration entry. let t = be_i32(inp);
*/ let (inp, len1) = t?;
pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let (inp, len1) = be_i32(inp)?;
if len1 < 0 || len1 > 4000 { if len1 < 0 || len1 > 4000 {
return BadError(format!("ConfigEntry bad len1 {}", len1)); return Err(nom::Err::Error(nom::error::Error::new(inp, ErrorKind::Verify)));
//return Err(format!("ConfigEntry bad len1 {}", len1).into());
} }
if inp.len() == 0 { if inp.len() == 0 {
return Ok((inp, None)); return Ok((inp, None));
} }
if inp.len() < len1 as usize - 4 { if inp.len() < len1 as usize - 4 {
return BadError(format!("incomplete input")); return Err(nom::Err::Incomplete(Needed::new(len1 as usize - 4)));
//return Err(format!("incomplete input").into());
} }
let inpE = &inp[(len1 - 8) as usize..]; let inpE = &inp[(len1 - 8) as usize..];
let (inp, ts) = be_i64(inp)?; let (inp, ts) = be_i64(inp)?;
@@ -128,7 +141,9 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let (inp, precision) = be_i16(inp)?; let (inp, precision) = be_i16(inp)?;
let (inp, dtlen) = be_i32(inp)?; let (inp, dtlen) = be_i32(inp)?;
if dtlen > 100 { if dtlen > 100 {
return BadError(format!("unexpected data type len {}", dtlen)); error!("unexpected data type len {}", dtlen);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
//return Err(format!("unexpected data type len {}", dtlen).into());
} }
let (inp, dtmask) = be_u8(inp)?; let (inp, dtmask) = be_u8(inp)?;
let isCompressed = dtmask & 0x80 != 0; let isCompressed = dtmask & 0x80 != 0;
@@ -137,11 +152,15 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let isShaped = dtmask & 0x10 != 0; let isShaped = dtmask & 0x10 != 0;
let (inp, dtype) = be_i8(inp)?; let (inp, dtype) = be_i8(inp)?;
if dtype > 13 { if dtype > 13 {
return BadError(format!("unexpected data type {}", dtype)); error!("unexpected data type {}", dtype);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
} }
let dtype = match num_traits::FromPrimitive::from_i8(dtype) { let dtype = match num_traits::FromPrimitive::from_i8(dtype) {
Some(k) => k, Some(k) => k,
None => return BadError(format!("Can not convert {} to DType", dtype)), None => {
error!("Can not convert {} to DType", dtype);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
}
}; };
let (inp, compressionMethod) = match isCompressed { let (inp, compressionMethod) = match isCompressed {
false => (inp, None), false => (inp, None),
@@ -149,7 +168,10 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let (inp, cm) = be_u8(inp)?; let (inp, cm) = be_u8(inp)?;
match num_traits::FromPrimitive::from_u8(cm) { match num_traits::FromPrimitive::from_u8(cm) {
Some(k) => (inp, Some(k)), Some(k) => (inp, Some(k)),
None => return BadError("unknown compression"), None => {
error!("unknown compression");
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
}
} }
} }
}; };
@@ -158,7 +180,8 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
true => { true => {
let (mut inp, dim) = be_u8(inp)?; let (mut inp, dim) = be_u8(inp)?;
if dim > 4 { if dim > 4 {
return BadError(format!("unexpected number of dimensions: {}", dim)); error!("unexpected number of dimensions: {}", dim);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
} }
let mut shape = vec![]; let mut shape = vec![];
for _ in 0..dim { for _ in 0..dim {
@@ -169,15 +192,16 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
(inp, Some(shape)) (inp, Some(shape))
} }
}; };
let (inp, sourceName) = parseShortString(inp)?; let (inp, sourceName) = parse_short_string(inp)?;
let (inp, unit) = parseShortString(inp)?; let (inp, unit) = parse_short_string(inp)?;
let (inp, description) = parseShortString(inp)?; let (inp, description) = parse_short_string(inp)?;
let (inp, optionalFields) = parseShortString(inp)?; let (inp, optionalFields) = parse_short_string(inp)?;
let (inp, valueConverter) = parseShortString(inp)?; let (inp, valueConverter) = parse_short_string(inp)?;
assert_eq!(inp.len(), inpE.len()); assert_eq!(inp.len(), inpE.len());
let (inpE, len2) = be_i32(inpE)?; let (inpE, len2) = be_i32(inpE)?;
if len1 != len2 { if len1 != len2 {
return BadError(format!("mismatch len1 {} len2 {}", len1, len2)); error!("mismatch len1 {} len2 {}", len1, len2);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
} }
Ok(( Ok((
inpE, inpE,
@@ -211,32 +235,42 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
/* /*
Parse the full configuration file. Parse the full configuration file.
*/ */
pub fn parseConfig(inp: &[u8]) -> Result<Config, Error> { pub fn parseConfig(inp: &[u8]) -> IResult<&[u8], Config> {
let (inp, ver) = be_i16(inp)?; let (inp, ver) = be_i16(inp)?;
let (inp, len1) = be_i32(inp)?; let (inp, len1) = be_i32(inp)?;
if len1 <= 8 || len1 > 500 { if len1 <= 8 || len1 > 500 {
return BadError(format!("no channel name. len1 {}", len1)); error!("no channel name. len1 {}", len1);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
} }
let (inp, chn) = take((len1 - 8) as usize)(inp)?; let (inp, chn) = take((len1 - 8) as usize)(inp)?;
let (inp, len2) = be_i32(inp)?; let (inp, len2) = be_i32(inp)?;
if len1 != len2 { if len1 != len2 {
return BadError(format!("Mismatch len1 {} len2 {}", len1, len2)); error!("Mismatch len1 {} len2 {}", len1, len2);
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
} }
let mut entries = vec![]; let mut entries = vec![];
let mut inpA = inp; let mut inpA = inp;
while inpA.len() > 0 { while inpA.len() > 0 {
let inp = inpA; let inp = inpA;
let (inp, e) = parseEntry(inp)?; let (inp, e) = parse_entry(inp)?;
if let Some(e) = e { if let Some(e) = e {
entries.push(e); entries.push(e);
} }
inpA = inp; inpA = inp;
} }
Ok(Config { let channelName = match String::from_utf8(chn.to_vec()) {
Ok(k) => k,
Err(e) => {
error!("channelName utf8 error");
return Err(nom::Err::Error(nom::error::make_error(inp, ErrorKind::Verify)));
}
};
let ret = Config {
formatVersion: ver, formatVersion: ver,
channelName: String::from_utf8(chn.to_vec())?, channelName,
entries: entries, entries: entries,
}) };
Ok((inp, ret))
} }
#[cfg(test)] #[cfg(test)]
@@ -252,13 +286,13 @@ fn read_data() -> Vec<u8> {
#[test] #[test]
fn parse_dummy() { fn parse_dummy() {
let config = parseConfig(&[0, 0, 0, 0, 0, 11, 0x61, 0x62, 0x63, 0, 0, 0, 11, 0, 0, 0, 1]).unwrap(); let config = parseConfig(&[0, 0, 0, 0, 0, 11, 0x61, 0x62, 0x63, 0, 0, 0, 11, 0, 0, 0, 1]).unwrap();
assert_eq!(0, config.formatVersion); assert_eq!(0, config.1.formatVersion);
assert_eq!("abc", config.channelName); assert_eq!("abc", config.1.channelName);
} }
#[test] #[test]
fn open_file() { fn open_file() {
let config = parseConfig(&readData()).unwrap(); let config = parseConfig(&read_data()).unwrap().1;
assert_eq!(0, config.formatVersion); assert_eq!(0, config.formatVersion);
assert_eq!(9, config.entries.len()); assert_eq!(9, config.entries.len());
for e in &config.entries { for e in &config.entries {

View File

@@ -10,3 +10,4 @@ http = "0.2"
serde_json = "1.0" serde_json = "1.0"
async-channel = "1.6" async-channel = "1.6"
chrono = { version = "0.4.19", features = ["serde"] } chrono = { version = "0.4.19", features = ["serde"] }
nom = "6.1.2"

View File

@@ -1,4 +1,7 @@
use nom::error::ErrorKind;
use std::fmt::Debug;
use std::num::ParseIntError; use std::num::ParseIntError;
use std::string::FromUtf8Error;
#[derive(Debug)] #[derive(Debug)]
pub struct Error { pub struct Error {
@@ -17,6 +20,12 @@ impl From<String> for Error {
} }
} }
impl From<&str> for Error {
fn from(k: &str) -> Self {
Self { msg: k.into() }
}
}
impl std::fmt::Display for Error { impl std::fmt::Display for Error {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "Error") write!(fmt, "Error")
@@ -66,3 +75,35 @@ impl From<ParseIntError> for Error {
Self { msg: k.to_string() } Self { msg: k.to_string() }
} }
} }
impl From<FromUtf8Error> for Error {
fn from(k: FromUtf8Error) -> Self {
Self { msg: k.to_string() }
}
}
impl<T> From<nom::Err<T>> for Error {
fn from(k: nom::Err<T>) -> Self {
Self {
msg: format!("nom::Err<T>"),
}
}
}
impl<I> From<nom::error::VerboseError<I>> for Error {
fn from(k: nom::error::VerboseError<I>) -> Self {
Self {
msg: format!("nom::error::VerboseError<I>"),
}
}
}
impl<I> nom::error::ParseError<I> for Error {
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
todo!()
}
fn append(input: I, kind: ErrorKind, other: Self) -> Self {
todo!()
}
}