Skip to content

Commit

Permalink
* Renames crate::resolve::ResolveError to crate::resolve::Error
Browse files Browse the repository at this point in the history
* Adds type alias `crate::resolve::ResolveError` for `crate::resolve::Error`
* Renames `crate::assign::AssignError` to `crate::assign::Error`
* Adds type alias `crate::assign::AssignError` for crate::assign::Error`
* Adds `position` (token index) to variants of `assign::Error` & `resolve::Error`
  • Loading branch information
chanced committed Oct 21, 2024
1 parent c694765 commit 45c4fde
Show file tree
Hide file tree
Showing 4 changed files with 255 additions and 226 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ syn = { version = "1.0.109", optional = true }

[features]
assign = []
default = ["std", "serde", "json", "resolve", "assign", "delete"]
default = ["std", "serde", "json", "toml", "resolve", "assign", "delete"]
delete = ["resolve"]
json = ["dep:serde_json", "serde"]
resolve = []
Expand Down
126 changes: 84 additions & 42 deletions src/assign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,55 +133,66 @@ pub trait Assign {
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
╔══════════════════════════════════════════════════════════════════════════════╗
║ ║
AssignError
║ ¯¯¯¯¯¯¯¯¯¯¯¯¯
Error
¯¯¯¯¯¯¯
╚══════════════════════════════════════════════════════════════════════════════╝
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
*/

// TODO: should AssignError be deprecated?
/// Alias for [`Error`].
///
/// Possible error returned from [`Assign`] implementations for
/// [`serde_json::Value`] and
/// [`toml::Value`](https://docs.rs/toml/0.8.14/toml/index.html).
pub type AssignError = Error;

/// Possible error returned from [`Assign`] implementations for
/// [`serde_json::Value`] and
/// [`toml::Value`](https://docs.rs/toml/0.8.14/toml/index.html).
#[derive(Debug, PartialEq, Eq)]
pub enum AssignError {
/// A `Token` within the `Pointer` failed to be parsed as an array index.
pub enum Error {
/// A [`Token`] within the [`Pointer`] failed to be parsed as an array index.
FailedToParseIndex {
/// Position (index) of the token which failed to parse as an `Index`
position: usize,
/// Offset of the partial pointer starting with the invalid index.
offset: usize,
/// The source [`ParseIndexError`]
source: ParseIndexError,
},

/// target array.
/// A [`Token`] within the [`Pointer`] contains an [`Index`] which is out of bounds.
///
/// The current or resulting array's length is less than the index.
OutOfBounds {
/// Position (index) of the token which failed to parse as an `Index`
position: usize,
/// Offset of the partial pointer starting with the invalid index.
offset: usize,
/// The source [`OutOfBoundsError`]
source: OutOfBoundsError,
},
}

impl fmt::Display for AssignError {
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::FailedToParseIndex { offset, .. } => {
write!(
f,
"assignment failed due to an invalid index at offset {offset}"
)
Self::FailedToParseIndex { .. } => {
write!(f, "assignment failed due to an invalid index")
}
Self::OutOfBounds { offset, .. } => {
Self::OutOfBounds { .. } => {
write!(
f,
"assignment failed due to index at offset {offset} being out of bounds"
"assignment failed due to index an index being out of bounds"
)
}
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for AssignError {
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::FailedToParseIndex { source, .. } => Some(source),
Expand All @@ -207,7 +218,7 @@ enum Assigned<'v, V> {

#[cfg(feature = "json")]
mod json {
use super::{Assign, AssignError, Assigned};
use super::{Assign, Assigned, Error};
use crate::{Pointer, Token};
use alloc::{
string::{String, ToString},
Expand Down Expand Up @@ -235,7 +246,7 @@ mod json {
}
impl Assign for Value {
type Value = Value;
type Error = AssignError;
type Error = Error;
fn assign<V>(&mut self, ptr: &Pointer, value: V) -> Result<Option<Self::Value>, Self::Error>
where
V: Into<Self::Value>,
Expand All @@ -248,14 +259,15 @@ mod json {
mut ptr: &Pointer,
mut dest: &mut Value,
mut value: Value,
) -> Result<Option<Value>, AssignError> {
) -> Result<Option<Value>, Error> {
let mut offset = 0;

let mut position = 0;
while let Some((token, tail)) = ptr.split_front() {
let tok_len = token.encoded().len();

let assigned = match dest {
Value::Array(array) => assign_array(token, tail, array, value, offset)?,
Value::Array(array) => assign_array(token, tail, array, value, position, offset)?,
Value::Object(obj) => assign_object(token, tail, obj, value),
_ => assign_scalar(ptr, dest, value),
};
Expand All @@ -273,6 +285,7 @@ mod json {
}
}
offset += 1 + tok_len;
position += 1;
}

// Pointer is root, we can replace `dest` directly
Expand All @@ -285,14 +298,23 @@ mod json {
remaining: &Pointer,
array: &'v mut Vec<Value>,
src: Value,
position: usize,
offset: usize,
) -> Result<Assigned<'v, Value>, AssignError> {
) -> Result<Assigned<'v, Value>, Error> {
// parsing the index
let idx = token
.to_index()
.map_err(|source| AssignError::FailedToParseIndex { offset, source })?
.map_err(|source| Error::FailedToParseIndex {
position,
offset,
source,
})?
.for_len_incl(array.len())
.map_err(|source| AssignError::OutOfBounds { offset, source })?;
.map_err(|source| Error::OutOfBounds {
position,
offset,
source,
})?;

debug_assert!(idx <= array.len());

Expand Down Expand Up @@ -381,7 +403,7 @@ mod json {

#[cfg(feature = "toml")]
mod toml {
use super::{Assign, AssignError, Assigned};
use super::{Assign, Assigned, Error};
use crate::{Pointer, Token};
use alloc::{string::String, vec, vec::Vec};
use core::mem;
Expand All @@ -406,7 +428,7 @@ mod toml {

impl Assign for Value {
type Value = Value;
type Error = AssignError;
type Error = Error;
fn assign<V>(&mut self, ptr: &Pointer, value: V) -> Result<Option<Self::Value>, Self::Error>
where
V: Into<Self::Value>,
Expand All @@ -419,14 +441,15 @@ mod toml {
mut ptr: &Pointer,
mut dest: &mut Value,
mut value: Value,
) -> Result<Option<Value>, AssignError> {
) -> Result<Option<Value>, Error> {
let mut offset = 0;
let mut position = 0;

while let Some((token, tail)) = ptr.split_front() {
let tok_len = token.encoded().len();

let assigned = match dest {
Value::Array(array) => assign_array(token, tail, array, value, offset)?,
Value::Array(array) => assign_array(token, tail, array, value, position, offset)?,
Value::Table(tbl) => assign_object(token, tail, tbl, value),
_ => assign_scalar(ptr, dest, value),
};
Expand All @@ -444,6 +467,7 @@ mod toml {
}
}
offset += 1 + tok_len;
position += 1;
}

// Pointer is root, we can replace `dest` directly
Expand All @@ -457,14 +481,23 @@ mod toml {
remaining: &Pointer,
array: &'v mut Vec<Value>,
src: Value,
position: usize,
offset: usize,
) -> Result<Assigned<'v, Value>, AssignError> {
) -> Result<Assigned<'v, Value>, Error> {
// parsing the index
let idx = token
.to_index()
.map_err(|source| AssignError::FailedToParseIndex { offset, source })?
.map_err(|source| Error::FailedToParseIndex {
position,
offset,
source,
})?
.for_len_incl(array.len())
.map_err(|source| AssignError::OutOfBounds { offset, source })?;
.map_err(|source| Error::OutOfBounds {
position,
offset,
source,
})?;

debug_assert!(idx <= array.len());

Expand Down Expand Up @@ -550,7 +583,7 @@ mod toml {
#[cfg(test)]
#[allow(clippy::too_many_lines)]
mod tests {
use super::{Assign, AssignError};
use super::{Assign, Error};
use crate::{
index::{OutOfBoundsError, ParseIndexError},
Pointer,
Expand All @@ -574,9 +607,6 @@ mod tests {
V::Error: Debug + PartialEq,
Result<Option<V>, V::Error>: PartialEq<Result<Option<V::Value>, V::Error>>,
{
fn all(tests: impl IntoIterator<Item = Test<V>>) {
tests.into_iter().enumerate().for_each(|(i, t)| t.run(i));
}
fn run(self, i: usize) {
let Test {
ptr,
Expand Down Expand Up @@ -607,7 +637,7 @@ mod tests {
fn assign_json() {
use alloc::vec;
use serde_json::json;
Test::all([
[
Test {
ptr: "/foo",
data: json!({}),
Expand Down Expand Up @@ -731,7 +761,8 @@ mod tests {
ptr: "/1",
data: json!([]),
assign: json!("foo"),
expected: Err(AssignError::OutOfBounds {
expected: Err(Error::OutOfBounds {
position: 0,
offset: 0,
source: OutOfBoundsError {
index: 1,
Expand All @@ -751,7 +782,8 @@ mod tests {
ptr: "/a",
data: json!([]),
assign: json!("foo"),
expected: Err(AssignError::FailedToParseIndex {
expected: Err(Error::FailedToParseIndex {
position: 0,
offset: 0,
source: ParseIndexError::InvalidInteger(usize::from_str("foo").unwrap_err()),
}),
Expand All @@ -761,7 +793,8 @@ mod tests {
ptr: "/002",
data: json!([]),
assign: json!("foo"),
expected: Err(AssignError::FailedToParseIndex {
expected: Err(Error::FailedToParseIndex {
position: 0,
offset: 0,
source: ParseIndexError::LeadingZeros,
}),
Expand All @@ -771,13 +804,17 @@ mod tests {
ptr: "/+23",
data: json!([]),
assign: json!("foo"),
expected: Err(AssignError::FailedToParseIndex {
expected: Err(Error::FailedToParseIndex {
position: 0,
offset: 0,
source: ParseIndexError::InvalidCharacters("+".into()),
}),
expected_data: json!([]),
},
]);
]
.into_iter()
.enumerate()
.for_each(|(i, t)| t.run(i));
}

/*
Expand All @@ -791,7 +828,7 @@ mod tests {
fn assign_toml() {
use alloc::vec;
use toml::{toml, Table, Value};
Test::all([
[
Test {
data: Value::Table(toml::Table::new()),
ptr: "/foo",
Expand Down Expand Up @@ -910,7 +947,8 @@ mod tests {
data: Value::Array(vec![]),
ptr: "/1",
assign: "foo".into(),
expected: Err(AssignError::OutOfBounds {
expected: Err(Error::OutOfBounds {
position: 0,
offset: 0,
source: OutOfBoundsError {
index: 1,
Expand All @@ -923,12 +961,16 @@ mod tests {
data: Value::Array(vec![]),
ptr: "/a",
assign: "foo".into(),
expected: Err(AssignError::FailedToParseIndex {
expected: Err(Error::FailedToParseIndex {
position: 0,
offset: 0,
source: ParseIndexError::InvalidInteger(usize::from_str("foo").unwrap_err()),
}),
expected_data: Value::Array(vec![]),
},
]);
]
.into_iter()
.enumerate()
.for_each(|(i, t)| t.run(i));
}
}
Loading

0 comments on commit 45c4fde

Please sign in to comment.