Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix partial_input output is too long and needs to be truncated #48

Merged
merged 6 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ jobs:

- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v4
if: ${{github.ref == 'refs/heads/master' }}
with:
personal_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./playground/site/dist
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ readme = "README.md"
categories = ["parsing", "date-and-time"]
repository = "https://github.com/baoyachi/duration-str"
license = "Apache-2.0"
exclude = ["./playground"]
exclude = ["duration-str.png", "./playground"]

[features]
default = ["chrono", "serde", "time"]

[dependencies]
thiserror = "1.0.37"
chrono = { version = "0.4.38", optional = true }
time = { version = "0.3.17", optional = true }
chrono = { version = "0.4.38", optional = true, default-features = false, features = ["now"] }
time = { version = "0.3.17", optional = true, default-features = false }

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

Expand Down
Binary file added duration-str.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 65 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,21 @@
use std::fmt::{Display, Formatter};
use std::fmt::{Debug, Display, Formatter};
use thiserror::Error;
use winnow::error::{ErrorKind, FromExternalError, ParserError};
use winnow::stream::Stream;

pub trait RawDebug {
fn raw(&self) -> String;
}

impl<A> RawDebug for A
where
A: AsRef<str>,
{
fn raw(&self) -> String {
self.as_ref().to_string()
}
}

#[derive(Error, Debug, PartialEq)]
pub enum DError {
#[error("{0}")]
Expand All @@ -11,9 +24,11 @@ pub enum DError {
OverflowError,
}

const PARTIAL_INPUT_MAX_LEN: usize = 11;

#[derive(Debug, PartialEq, Eq)]
pub struct PError<I> {
pub partial_input: I,
partial_input: I,
kind: ErrorKind,
cause: String,
}
Expand All @@ -31,6 +46,22 @@ impl<I> PError<I> {
self.cause = cause.as_ref().to_string();
self
}

pub fn partial_input(&self) -> String
where
I: RawDebug,
{
let raw = self.partial_input.raw();
if let Some(offset) = raw
.char_indices()
.enumerate()
.find_map(|(pos, (offset, _))| (PARTIAL_INPUT_MAX_LEN <= pos).then_some(offset))
{
format!("{}...", raw.split_at(offset).0)
} else {
raw
}
}
}

impl<I: Stream + Clone> ParserError<I> for PError<I> {
Expand Down Expand Up @@ -66,3 +97,35 @@ where
Ok(())
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_partial_input() {
let error = PError::new("1234567890abcde", ErrorKind::Complete);
let partial_input = error.partial_input();
assert_eq!(partial_input, "1234567890a...");

let error = PError::new("你好,龙骧虎步龙行龘龘龘", ErrorKind::Complete);
let partial_input = error.partial_input();
assert_eq!(partial_input, "你好,龙骧虎步龙行龘龘...");

let error = PError::new("hello,你好", ErrorKind::Complete);
let partial_input = error.partial_input();
assert_eq!(partial_input, "hello,你好");

let error = PError::new("1mins", ErrorKind::Complete);
let partial_input = error.partial_input();
assert_eq!(partial_input, "1mins");

let error = PError::new("MILLISECONDhah", ErrorKind::Complete);
let partial_input = error.partial_input();
assert_eq!(partial_input, "MILLISECOND...");

let error = PError::new("MILLISECOND", ErrorKind::Complete);
let partial_input = error.partial_input();
assert_eq!(partial_input, "MILLISECOND");
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#![doc(
html_logo_url = "https://raw.githubusercontent.com/baoyachi/duration-rs/master/duration-str.png"
)]
//! Parse string to `Duration` .
//!
//! The String value unit support for one of:["y","mon","w","d","h","m","s", "ms", "µs", "ns"]
Expand Down
4 changes: 2 additions & 2 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,16 @@ fn cond_unit1<'a>(input: &mut &'a str) -> PResult<CondUnit, PError<&'a str>> {
}

fn opt_cond_unit<'a>(input: &mut &'a str) -> PResult<CondUnit, PError<&'a str>> {
let multispace = multispace0::<_, PError<_>>;
let result = cond_unit1
.parse_next(input)
.map_err(|err: ErrMode<PError<_>>| {
err.map(|x| {
let partial_input = x.partial_input;
let partial_input = x.partial_input();
x.append_cause(CondUnit::expect_err(partial_input))
})
});
if result.is_err() {
let multispace = multispace0::<_, PError<_>>;
if (multispace, eof).parse_next(input).is_ok() {
// The input result is empty except for spaces. Give `TimeUnit` default value
return Ok(CondUnit::Plus);
Expand Down
4 changes: 2 additions & 2 deletions src/unit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub(crate) fn unit_abbr1<'a>(input: &mut &'a str) -> PResult<TimeUnit, PError<&'
.parse_next(input)
.map_err(|err: ErrMode<PError<_>>| {
err.map(|x| {
let partial_input = x.partial_input;
let partial_input = x.partial_input();
x.append_cause(TimeUnit::expect_err(partial_input))
})
})?;
Expand All @@ -121,9 +121,9 @@ pub(crate) fn unit_abbr1<'a>(input: &mut &'a str) -> PResult<TimeUnit, PError<&'
}

pub(crate) fn opt_unit_abbr<'a>(input: &mut &'a str) -> PResult<TimeUnit, PError<&'a str>> {
let multispace = multispace0::<_, PError<_>>;
let result = unit_abbr1(input);
if result.is_err() {
let multispace = multispace0::<_, PError<_>>;
if (multispace, eof).parse_next(input).is_ok() {
// The input result is empty except for spaces. Give `TimeUnit` default value
return Ok(TimeUnit::default());
Expand Down
Loading