From dff9cd770ccc942589658b00d9a8a293593e40ef Mon Sep 17 00:00:00 2001 From: Dominik Werder Date: Fri, 16 Apr 2021 16:15:53 +0200 Subject: [PATCH] Issues with nom 6 error type --- disk/Cargo.toml | 3 ++ disk/src/channelconfig.rs | 104 +++++++++++++++++++++++++------------- err/Cargo.toml | 1 + err/src/lib.rs | 41 +++++++++++++++ 4 files changed, 114 insertions(+), 35 deletions(-) diff --git a/disk/Cargo.toml b/disk/Cargo.toml index 28f4a25..1396c0d 100644 --- a/disk/Cargo.toml +++ b/disk/Cargo.toml @@ -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" } diff --git a/disk/src/channelconfig.rs b/disk/src/channelconfig.rs index 6fa2c26..06d829d 100644 --- a/disk/src/channelconfig.rs +++ b/disk/src/channelconfig.rs @@ -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, } -fn parseShortString(inp: &[u8]) -> Result<(&[u8], Option), Error> { +fn parse_short_string(inp: &[u8]) -> IResult<&[u8], Option> { 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), Error> { - let (inp, len1) = be_i32(inp)?; +pub fn parse_entry(inp: &[u8]) -> IResult<&[u8], Option> { + 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), 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), 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), 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), 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), 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), Error> { /* Parse the full configuration file. */ -pub fn parseConfig(inp: &[u8]) -> Result { +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 { #[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 { diff --git a/err/Cargo.toml b/err/Cargo.toml index 7a3dd2a..1aac78c 100644 --- a/err/Cargo.toml +++ b/err/Cargo.toml @@ -10,3 +10,4 @@ http = "0.2" serde_json = "1.0" async-channel = "1.6" chrono = { version = "0.4.19", features = ["serde"] } +nom = "6.1.2" diff --git a/err/src/lib.rs b/err/src/lib.rs index 129c0e5..c68b759 100644 --- a/err/src/lib.rs +++ b/err/src/lib.rs @@ -1,4 +1,7 @@ +use nom::error::ErrorKind; +use std::fmt::Debug; use std::num::ParseIntError; +use std::string::FromUtf8Error; #[derive(Debug)] pub struct Error { @@ -17,6 +20,12 @@ impl From for Error { } } +impl From<&str> for Error { + fn from(k: &str) -> Self { + Self { msg: k.into() } + } +} + impl std::fmt::Display for Error { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { write!(fmt, "Error") @@ -66,3 +75,35 @@ impl From for Error { Self { msg: k.to_string() } } } + +impl From for Error { + fn from(k: FromUtf8Error) -> Self { + Self { msg: k.to_string() } + } +} + +impl From> for Error { + fn from(k: nom::Err) -> Self { + Self { + msg: format!("nom::Err"), + } + } +} + +impl From> for Error { + fn from(k: nom::error::VerboseError) -> Self { + Self { + msg: format!("nom::error::VerboseError"), + } + } +} + +impl nom::error::ParseError for Error { + fn from_error_kind(input: I, kind: ErrorKind) -> Self { + todo!() + } + + fn append(input: I, kind: ErrorKind, other: Self) -> Self { + todo!() + } +}