Skip to content

Commit

Permalink
fix parsing error location precise prompt
Browse files Browse the repository at this point in the history
  • Loading branch information
baoyachi committed May 10, 2024
1 parent f767558 commit 7aa131e
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 167 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "duration-str"
version = "0.9.0"
version = "0.10.0"
authors = ["baoyachi <liaoymxsdl@gmail.com>"]
edition = "2021"
description = "duration string parser"
Expand All @@ -20,7 +20,7 @@ time = { version = "0.3.17", optional = true }

serde = { version = "1.0.147", features = ["derive"], optional = true }
rust_decimal = { version = "1.29.1", default-features = false }
winnow = "0.6.6"
winnow = "0.6.8"

[dev-dependencies]
serde_json = { version = "1.0.87" }
Expand Down
68 changes: 68 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::fmt::{Display, Formatter};
use thiserror::Error;
use winnow::error::{ErrorKind, FromExternalError, ParserError};
use winnow::stream::Stream;

#[derive(Error, Debug, PartialEq)]
pub enum DError {
#[error("{0}")]
ParseError(String),
#[error("overflow error")]
OverflowError,
}

#[derive(Debug, PartialEq, Eq)]
pub struct PError<I> {
pub partial_input: I,
kind: ErrorKind,
cause: String,
}

impl<I> PError<I> {
fn new(input: I, kind: ErrorKind) -> Self {
PError {
partial_input: input,
kind,
cause: "".to_string(),
}
}

pub fn append_cause<C: AsRef<str>>(mut self, cause: C) -> Self {
self.cause = cause.as_ref().to_string();
self
}
}

impl<I: Stream + Clone> ParserError<I> for PError<I> {
fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
PError::new(input.clone(), kind)
}

fn append(self, _: &I, _: &<I as Stream>::Checkpoint, _: ErrorKind) -> Self {
self
}
}

impl<I: Clone, E: std::error::Error + Send + Sync + 'static> FromExternalError<I, E> for PError<I> {
#[inline]
fn from_external_error(input: &I, kind: ErrorKind, e: E) -> Self {
let mut err = Self::new(input.clone(), kind);
{
err.cause = e.to_string();
}
err
}
}

impl<I> Display for PError<I>
where
I: Display,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "partial_input:{}", self.partial_input)?;
if !self.cause.is_empty() {
write!(f, ", {}", self.cause)?;
}
Ok(())
}
}
28 changes: 11 additions & 17 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,8 @@
//! }
//! ```
mod error;
pub(crate) mod macros;
mod parser;
#[cfg(feature = "serde")]
mod serde;
Expand All @@ -179,8 +181,8 @@ use rust_decimal::prelude::ToPrimitive;
use rust_decimal::Decimal;
use std::str::FromStr;
use std::time::Duration;
use thiserror::Error;

use crate::error::DError;
use crate::unit::TimeUnit;
#[cfg(feature = "chrono")]
pub use naive_date::{
Expand All @@ -189,16 +191,6 @@ pub use naive_date::{

pub type DResult<T> = Result<T, DError>;

#[derive(Error, Debug, PartialEq)]
pub enum DError {
#[error("`{0}`")]
ParseError(String),
#[error("`{0}`")]
NormalError(String),
#[error("overflow error")]
OverflowError,
}

const ONE_MICROSECOND_NANOSECOND: u64 = 1000;
const ONE_MILLISECOND_NANOSECOND: u64 = 1000 * ONE_MICROSECOND_NANOSECOND;
const ONE_SECOND_NANOSECOND: u64 = 1000 * ONE_MILLISECOND_NANOSECOND;
Expand All @@ -222,9 +214,10 @@ trait ExpectErr<const LEN: usize> {
fn expect_err<S: AsRef<str> + Display>(s: S) -> String;
}

#[derive(Debug, Eq, PartialEq, Clone)]
#[derive(Debug, Eq, PartialEq, Clone, Default)]
enum CondUnit {
Plus,
#[default]
Star,
}

Expand Down Expand Up @@ -292,7 +285,7 @@ impl Calc<(CondUnit, u64)> for Vec<(&str, CondUnit, TimeUnit)> {
init_cond = cond.clone();
init_duration = init_cond.change_duration();
} else if &init_cond != cond {
return Err(DError::NormalError(format!(
return Err(DError::ParseError(format!(
"not support '{}' with '{}' calculate",
init_cond.to_string(),
cond.to_string()
Expand All @@ -317,12 +310,13 @@ impl Calc<(CondUnit, u64)> for Vec<(&str, CondUnit, TimeUnit)> {
}
}

impl ToString for CondUnit {
fn to_string(&self) -> String {
match self {
impl Display for CondUnit {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let str = match self {
Self::Plus => PLUS.to_string(),
Self::Star => STAR.to_string(),
}
};
write!(f, "{}", str)
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#[cfg(test)]
#[macro_export]
macro_rules! catch_err {
($result:expr) => {
format!("{}", $result.err().unwrap())
};
}
Loading

0 comments on commit 7aa131e

Please sign in to comment.