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"
libc = "0.2.93"
hex = "0.4.3"
nom = "6.1.2"
num-traits = "0.2"
num-derive = "0.3"
tiny-keccak = { version = "2.0", features = ["sha3"] }
err = { path = "../err" }
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::Needed;
#[allow(unused_imports)]
use nom::{
bytes::complete::{tag, take, take_while_m_n},
@@ -9,7 +11,9 @@ use nom::{
};
use num_derive::{FromPrimitive, 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)]
pub enum DType {
@@ -85,35 +89,44 @@ pub struct Config {
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)?;
if len1 == -1 {
return Ok((inp, None));
}
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 {
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 s1 = String::from_utf8(snb.to_vec())?;
Ok((inp, Some(s1)))
match String::from_utf8(snb.to_vec()) {
Ok(s1) => Ok((inp, Some(s1))),
Err(e) => {
let err = nom::error::make_error(inp, ErrorKind::Verify);
Err(nom::Err::Error(err))
}
}
}
/*
Parse a single configuration entry.
*/
pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let (inp, len1) = be_i32(inp)?;
pub fn parse_entry(inp: &[u8]) -> IResult<&[u8], Option<ConfigEntry>> {
let t = be_i32(inp);
let (inp, len1) = t?;
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 {
return Ok((inp, None));
}
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 (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, dtlen) = be_i32(inp)?;
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 isCompressed = dtmask & 0x80 != 0;
@@ -137,11 +152,15 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let isShaped = dtmask & 0x10 != 0;
let (inp, dtype) = be_i8(inp)?;
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) {
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 {
false => (inp, None),
@@ -149,7 +168,10 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
let (inp, cm) = be_u8(inp)?;
match num_traits::FromPrimitive::from_u8(cm) {
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 => {
let (mut inp, dim) = be_u8(inp)?;
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![];
for _ in 0..dim {
@@ -169,15 +192,16 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
(inp, Some(shape))
}
};
let (inp, sourceName) = parseShortString(inp)?;
let (inp, unit) = parseShortString(inp)?;
let (inp, description) = parseShortString(inp)?;
let (inp, optionalFields) = parseShortString(inp)?;
let (inp, valueConverter) = parseShortString(inp)?;
let (inp, sourceName) = parse_short_string(inp)?;
let (inp, unit) = parse_short_string(inp)?;
let (inp, description) = parse_short_string(inp)?;
let (inp, optionalFields) = parse_short_string(inp)?;
let (inp, valueConverter) = parse_short_string(inp)?;
assert_eq!(inp.len(), inpE.len());
let (inpE, len2) = be_i32(inpE)?;
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((
inpE,
@@ -211,32 +235,42 @@ pub fn parseEntry(inp: &[u8]) -> Result<(&[u8], Option<ConfigEntry>), Error> {
/*
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, len1) = be_i32(inp)?;
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, len2) = be_i32(inp)?;
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 inpA = inp;
while inpA.len() > 0 {
let inp = inpA;
let (inp, e) = parseEntry(inp)?;
let (inp, e) = parse_entry(inp)?;
if let Some(e) = e {
entries.push(e);
}
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,
channelName: String::from_utf8(chn.to_vec())?,
channelName,
entries: entries,
})
};
Ok((inp, ret))
}
#[cfg(test)]
@@ -252,13 +286,13 @@ fn read_data() -> Vec<u8> {
#[test]
fn parse_dummy() {
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!("abc", config.channelName);
assert_eq!(0, config.1.formatVersion);
assert_eq!("abc", config.1.channelName);
}
#[test]
fn open_file() {
let config = parseConfig(&readData()).unwrap();
let config = parseConfig(&read_data()).unwrap().1;
assert_eq!(0, config.formatVersion);
assert_eq!(9, config.entries.len());
for e in &config.entries {