-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
The JSONPath spec states that integers, e.g., those used as indices or in slice selectors, must be within a specific range [-2^53 +1, 2^53 - 1]. This adds a new Integer type to be used to represent such integers, and check that they stay within that range. It also caught a couple of places where overflows would have led to panics.
- Loading branch information
There are no files selected for viewing
+1,198 −117 | cts.json | |
+10 −0 | tests/basic.json | |
+283 −19 | tests/filter.json | |
+42 −0 | tests/functions/match.json | |
+30 −0 | tests/functions/search.json | |
+48 −0 | tests/index_selector.json | |
+155 −0 | tests/name_selector.json | |
+156 −0 | tests/slice_selector.json |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
//! Representation of itegers in the JSONPath specification | ||
//! | ||
//! The JSONPath specification defines some rules for integers used in query strings (see [here][spec]). | ||
//! | ||
//! [spec]: https://www.rfc-editor.org/rfc/rfc9535.html#name-overview | ||
use std::{ | ||
num::{ParseIntError, TryFromIntError}, | ||
str::FromStr, | ||
}; | ||
|
||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | ||
pub struct Integer(i64); | ||
Check warning on line 13 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 13 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 13 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Clippy
|
||
|
||
const MAX: i64 = 9_007_199_254_740_992 - 1; | ||
const MIN: i64 = -9_007_199_254_740_992 + 1; | ||
|
||
impl Integer { | ||
fn try_new(value: i64) -> Result<Self, IntegerError> { | ||
if value < MIN || value > MAX { | ||
return Err(IntegerError::OutOfBounds); | ||
} else { | ||
return Ok(Self(value)); | ||
} | ||
} | ||
|
||
fn check(&self) -> bool { | ||
self.0 >= MIN && self.0 <= MAX | ||
} | ||
|
||
pub fn from_i64_opt(value: i64) -> Option<Self> { | ||
Check warning on line 31 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 31 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 31 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Clippy
|
||
Self::try_new(value).ok() | ||
} | ||
|
||
pub fn checked_abs(mut self) -> Option<Self> { | ||
Check warning on line 35 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 35 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 35 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Clippy
|
||
self.0 = self.0.checked_abs()?; | ||
self.check().then_some(self) | ||
} | ||
|
||
pub fn checked_add(mut self, rhs: Self) -> Option<Self> { | ||
Check warning on line 40 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 40 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 40 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Clippy
|
||
self.0 = self.0.checked_add(rhs.0)?; | ||
self.check().then_some(self) | ||
} | ||
|
||
pub fn checked_sub(mut self, rhs: Self) -> Option<Self> { | ||
Check warning on line 45 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 45 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 45 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Clippy
|
||
self.0 = self.0.checked_sub(rhs.0)?; | ||
self.check().then_some(self) | ||
} | ||
|
||
pub fn checked_mul(mut self, rhs: Self) -> Option<Self> { | ||
Check warning on line 50 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 50 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
|
||
self.0 = self.0.checked_mul(rhs.0)?; | ||
self.check().then_some(self) | ||
} | ||
} | ||
|
||
impl Default for Integer { | ||
fn default() -> Self { | ||
Self(0) | ||
} | ||
} | ||
|
||
impl TryFrom<i64> for Integer { | ||
type Error = IntegerError; | ||
|
||
fn try_from(value: i64) -> Result<Self, Self::Error> { | ||
Self::try_new(value) | ||
} | ||
} | ||
|
||
impl TryFrom<usize> for Integer { | ||
type Error = IntegerError; | ||
|
||
fn try_from(value: usize) -> Result<Self, Self::Error> { | ||
i64::try_from(value) | ||
.map_err(|_| IntegerError::OutOfBounds) | ||
.and_then(Self::try_new) | ||
} | ||
} | ||
|
||
impl FromStr for Integer { | ||
type Err = IntegerError; | ||
|
||
fn from_str(s: &str) -> Result<Self, Self::Err> { | ||
s.parse::<i64>().map_err(Into::into).and_then(Self::try_new) | ||
} | ||
} | ||
|
||
impl std::fmt::Display for Integer { | ||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
write!(f, "{}", self.0) | ||
} | ||
} | ||
|
||
impl TryFrom<Integer> for usize { | ||
type Error = TryFromIntError; | ||
|
||
fn try_from(value: Integer) -> Result<Self, Self::Error> { | ||
Self::try_from(value.0) | ||
} | ||
} | ||
|
||
impl PartialEq<i64> for Integer { | ||
fn eq(&self, other: &i64) -> bool { | ||
self.0.eq(other) | ||
} | ||
} | ||
|
||
impl PartialOrd<i64> for Integer { | ||
fn partial_cmp(&self, other: &i64) -> Option<std::cmp::Ordering> { | ||
self.0.partial_cmp(other) | ||
} | ||
} | ||
|
||
#[derive(Debug, thiserror::Error)] | ||
pub enum IntegerError { | ||
Check warning on line 115 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 115 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
|
||
#[error("the provided integer was outside the valid range, see https://www.rfc-editor.org/rfc/rfc9535.html#section-2.1-4.1")] | ||
OutOfBounds, | ||
Check warning on line 117 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 117 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
|
||
#[error(transparent)] | ||
Parse(#[from] ParseIntError), | ||
Check warning on line 119 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
Check failure on line 119 in serde_json_path_core/src/spec/integer.rs GitHub Actions / Docs
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
//! Types representing the IETF JSONPath Standard | ||
pub mod functions; | ||
pub mod integer; | ||
pub mod query; | ||
pub mod segment; | ||
pub mod selector; |