Issues with nom 6 error type
This commit is contained in:
@@ -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" }
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user