Skip to content

Commit

Permalink
Merge pull request #20 from baoyachi/overflow
Browse files Browse the repository at this point in the history
Overflow
  • Loading branch information
baoyachi authored Sep 18, 2023
2 parents 322b683 + fca3250 commit faa1bbc
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 39 deletions.
14 changes: 13 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
- name: Build Release
run: cargo build --release
- name: Run tests
run: cargo test
run: cargo test --all-features --all
- name: Run tests without default features.
run: cargo test --no-default-features
- name: Run examples with deserialize_duration
Expand All @@ -49,3 +49,15 @@ jobs:
override: true
- name: Build on nightly
run: cargo build --release
publish-crate:
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
needs: [ build ]
steps:
- name: Set up Rust
uses: hecrj/setup-rust-action@v1
- uses: actions/checkout@v3
- name: Publish
shell: bash
run: |
cargo publish --token ${{ secrets.CRATES_GITHUB_TOKEN }}
24 changes: 0 additions & 24 deletions .github/workflows/publish.yml

This file was deleted.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "duration-str"
version = "0.6.1"
version = "0.7.0"
authors = ["baoyachi <[email protected]>"]
edition = "2021"
description = "duration string parser"
Expand Down
53 changes: 40 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,16 @@ pub use naive_date::{

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

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

#[derive(Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -242,7 +244,7 @@ impl TimeUnit {
TimeUnit::MicroSecond => ONE_MICROSECOND_NANOSECOND,
TimeUnit::NanoSecond => 1,
};
Ok(time * unit)
time.checked_mul(unit).ok_or(DError::OverflowError)
}
}

Expand All @@ -269,15 +271,16 @@ impl CondUnit {

fn calc(&self, x: u64, y: u64) -> DResult<Duration> {
let nano_second = match self {
CondUnit::Plus => x + y,
CondUnit::Plus => x.checked_add(y).ok_or(DError::OverflowError)?,
CondUnit::Star => {
let x: Decimal = x.into();
let y: Decimal = y.into();
let ret =
(x / one_second_decimal()) * (y / one_second_decimal()) * one_second_decimal();
ret.to_u64().ok_or_else(|| {
DError::ParseError(format!("type of Decimal:{} convert to u64 error", ret))
})?
let ret = (x / one_second_decimal())
.checked_mul(y / one_second_decimal())
.ok_or(DError::OverflowError)?
.checked_mul(one_second_decimal())
.ok_or(DError::OverflowError)?;
ret.to_u64().ok_or(DError::OverflowError)?
}
};
Ok(Duration::from_nanos(nano_second))
Expand All @@ -303,15 +306,17 @@ impl Calc<(CondUnit, u64)> for Vec<(&str, CondUnit, TimeUnit)> {
)));
}
match init_cond {
CondUnit::Plus => init_duration += time_unit.duration(val)?,
CondUnit::Plus => {
init_duration = init_duration
.checked_add(time_unit.duration(val)?)
.ok_or(DError::OverflowError)?;
}
CondUnit::Star => {
let time: Decimal = time_unit.duration(val)?.into();
let i = time / one_second_decimal();
let mut init: Decimal = init_duration.into();
init *= i;
init_duration = init.to_u64().ok_or_else(|| {
DError::ParseError(format!("type of Decimal:{} convert to u64 error", init))
})?;
init = init.checked_mul(i).ok_or(DError::OverflowError)?;
init_duration = init.to_u64().ok_or(DError::OverflowError)?;
}
}
}
Expand Down Expand Up @@ -720,6 +725,7 @@ des_option_duration!(
);

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

Expand Down Expand Up @@ -861,6 +867,27 @@ mod tests {
let duration = parse("1m * 1m").unwrap();
assert_eq!(duration, Duration::new(3600, 0));
}

#[test]
fn test_overflow_plus() {
let result = parse("10000000000000000y+60");
assert_eq!(result, Err(DError::OverflowError));
}

#[test]
fn test_max_mul() {
let duration = parse("580y*1").unwrap();
assert_eq!(
duration,
std::time::Duration::from_millis(18290880000) * 1000
);
}

#[test]
fn test_overflow_mul() {
let result = parse("580y*2");
assert_eq!(result, Err(DError::OverflowError));
}
}

#[cfg(all(test, feature = "chrono"))]
Expand Down

0 comments on commit faa1bbc

Please sign in to comment.