Skip to content

Commit

Permalink
fix: fixed handling of large 64-bit integers in query (#199)
Browse files Browse the repository at this point in the history
  • Loading branch information
pamburus authored Apr 25, 2024
1 parent 16bdbe7 commit 034ddfd
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ categories = ["command-line-utilities"]
description = "Utility for viewing json-formatted log files."
keywords = ["cli", "human", "log"]
name = "hl"
version = "0.27.3"
version = "0.27.4"
edition = "2021"
build = "build.rs"

Expand Down
2 changes: 2 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ pub enum Error {
LevelParseError(#[from] level::ParseError),
#[error(transparent)]
ParseFloatError(#[from] ParseFloatError),
#[error(transparent)]
ParseIntError(#[from] ParseIntError),
}

/// SizeParseError is an error which may occur when parsing size.
Expand Down
89 changes: 80 additions & 9 deletions src/model.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// std imports
use std::{collections::HashMap, fmt, iter::IntoIterator, marker::PhantomData, ops::Range};
use std::{
cmp::Ordering, collections::HashMap, fmt, iter::IntoIterator, marker::PhantomData, ops::Range, str::FromStr,
};

// third-party imports
use chrono::{DateTime, Utc};
Expand Down Expand Up @@ -1119,15 +1121,84 @@ impl<'a> KeyMatcher<'a> {

// ---

#[derive(Debug)]
pub enum Number {
Integer(i128),
Float(f64),
}

impl FromStr for Number {
type Err = Error;

#[inline]
fn from_str(s: &str) -> Result<Self> {
if s.contains('.') {
Ok(Self::Float(s.parse().map_err(|e| Error::from(e))?))
} else {
Ok(Self::Integer(s.parse().map_err(|e| Error::from(e))?))
}
}
}

impl PartialEq<Number> for Number {
#[inline(always)]
fn eq(&self, other: &Number) -> bool {
match self {
Self::Integer(a) => match other {
Self::Integer(b) => a == b,
Self::Float(b) => (*a as f64) == *b,
},
Self::Float(a) => match other {
Self::Integer(b) => *a == (*b as f64),
Self::Float(b) => a == b,
},
}
}
}

impl Eq for Number {}

impl From<i128> for Number {
#[inline(always)]
fn from(value: i128) -> Self {
Self::Integer(value)
}
}

impl From<f64> for Number {
#[inline(always)]
fn from(value: f64) -> Self {
Self::Float(value)
}
}

impl PartialOrd<Number> for Number {
#[inline(always)]
fn partial_cmp(&self, other: &Number) -> Option<Ordering> {
match self {
Self::Integer(a) => match other {
Self::Integer(b) => a.partial_cmp(b),
Self::Float(b) => (*a as f64).partial_cmp(b),
},
Self::Float(a) => match other {
Self::Integer(b) => a.partial_cmp(&(*b as f64)),
Self::Float(b) => a.partial_cmp(b),
},
}
}
}

// ---

#[derive(Debug)]
pub enum NumericOp {
Eq(f64),
Ne(f64),
Gt(f64),
Ge(f64),
Lt(f64),
Le(f64),
In(Vec<f64>),
Eq(Number),
Ne(Number),
Gt(Number),
Ge(Number),
Lt(Number),
Le(Number),
In(Vec<Number>),
}

// ---
Expand All @@ -1150,7 +1221,7 @@ impl ValueMatchPolicy {
Self::In(patterns) => patterns.iter().any(|pattern| subject == pattern),
Self::WildCard(pattern) => pattern.matches(subject),
Self::Numerically(op) => {
if let Some(value) = subject.parse::<f64>().ok() {
if let Some(value) = subject.parse::<Number>().ok() {
match op {
NumericOp::Eq(pattern) => value == *pattern,
NumericOp::Ne(pattern) => value != *pattern,
Expand Down
2 changes: 1 addition & 1 deletion src/query.pest
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ simple_string = @{ simple_char+ }
simple_char = @{ (LETTER | NUMBER | "@" | "." | "_" | "-" | ":" | "/" | "!" | "#" | "%" | "$" | "*" | "+" | "?") }

number = @{
"-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT*) ~ ("." ~ ASCII_DIGIT*)? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT+)?
"-"? ~ ("0" | ASCII_NONZERO_DIGIT ~ ASCII_DIGIT{,19}) ~ ("." ~ ASCII_DIGIT{,19})? ~ (^"e" ~ ("+" | "-")? ~ ASCII_DIGIT{1, 4})?
}

ws = _{ (" " | "\t" | "\r" | "\n") }
6 changes: 3 additions & 3 deletions src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use wildflower::Pattern;
use crate::error::Result;
use crate::level::RelaxedLevel;
use crate::model::{
FieldFilter, FieldFilterKey, Level, NumericOp, Record, RecordFilter, UnaryBoolOp, ValueMatchPolicy,
FieldFilter, FieldFilterKey, Level, Number, NumericOp, Record, RecordFilter, UnaryBoolOp, ValueMatchPolicy,
};
use crate::types::FieldKind;

Expand Down Expand Up @@ -191,14 +191,14 @@ fn parse_string_set(pair: Pair<Rule>) -> Result<Vec<String>> {
inner.map(|p| parse_string(p)).collect::<Result<Vec<_>>>()
}

fn parse_number(pair: Pair<Rule>) -> Result<f64> {
fn parse_number(pair: Pair<Rule>) -> Result<Number> {
assert_eq!(pair.as_rule(), Rule::number);

let inner = pair.as_str();
Ok(inner.parse()?)
}

fn parse_number_set(pair: Pair<Rule>) -> Result<Vec<f64>> {
fn parse_number_set(pair: Pair<Rule>) -> Result<Vec<Number>> {
assert_eq!(pair.as_rule(), Rule::number_set);

let inner = pair.into_inner();
Expand Down

0 comments on commit 034ddfd

Please sign in to comment.