diff --git a/src/diagnostic.rs b/src/diagnostic.rs index 689cd64..7105d5c 100644 --- a/src/diagnostic.rs +++ b/src/diagnostic.rs @@ -155,7 +155,8 @@ pub trait Diagnose<'s, T> { /// /// ## Example /// ``` - /// use jsonptr::{Pointer, ParseError, Diagnose}; + /// use core::any::{Any, TypeId}; + /// use jsonptr::{Pointer, ParseError, Diagnose, Report}; /// let subj = "invalid/pointer"; /// let err = Pointer::parse(subj).diagnose(subj).unwrap_err(); /// assert_eq!(err.type_id(),TypeId::of::>()); @@ -171,7 +172,8 @@ pub trait Diagnose<'s, T> { /// /// ## Example /// ``` - /// use jsonptr::{Pointer, ParseError, Diagnose}; + /// use core::any::{Any, TypeId}; + /// use jsonptr::{Pointer, ParseError, Diagnose, Report}; /// let subj = "invalid/pointer"; /// let err = Pointer::parse(subj).diagnose_with(|| subj).unwrap_err(); /// diff --git a/src/lib.rs b/src/lib.rs index ef885b1..1339c83 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -65,9 +65,10 @@ pub mod resolve; pub use resolve::{Resolve, ResolveMut}; pub mod diagnostic; +pub use diagnostic::{Diagnose, Report}; mod pointer; -pub use pointer::{ParseError, ParseErrors, Pointer, PointerBuf, RichParseError}; +pub use pointer::{ParseError, Pointer, PointerBuf, RichParseError}; mod token; pub use token::{EncodingError, InvalidEncoding, Token, Tokens}; diff --git a/src/pointer.rs b/src/pointer.rs index 86687a2..99b0512 100644 --- a/src/pointer.rs +++ b/src/pointer.rs @@ -1169,40 +1169,6 @@ impl core::fmt::Display for PointerBuf { } } -/* -░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ -╔══════════════════════════════════════════════════════════════════════════════╗ -║ ║ -║ ParseErrors ║ -║ ¯¯¯¯¯¯¯¯¯¯¯¯¯ ║ -╚══════════════════════════════════════════════════════════════════════════════╝ -░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ -*/ -pub struct ParseErrors(Vec); - -impl ParseErrors { - pub fn new(v: impl IntoIterator) -> Option { - let v = v.into_iter().collect::>(); - if v.is_empty() { - None - } else { - Some(Self(v)) - } - } -} -impl FromIterator for ParseErrors { - fn from_iter>(iter: I) -> Self { - Self::new(iter).unwrap() - } -} -impl IntoIterator for ParseErrors { - type Item = ParseError; - type IntoIter = alloc::vec::IntoIter; - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - /* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ╔══════════════════════════════════════════════════════════════════════════════╗ @@ -1231,13 +1197,15 @@ pub enum ParseError { } impl ParseError { + /// Offset of the partial pointer starting with the token that contained the + /// invalid encoding pub fn offset(&self) -> usize { match self { Self::NoLeadingBackslash => 0, Self::InvalidEncoding { offset, .. } => *offset, } } - + /// Length of the invalid encoding pub fn invalid_encoding_len(&self, subject: &str) -> usize { match self { Self::NoLeadingBackslash => 0, @@ -1364,6 +1332,7 @@ impl std::error::Error for ParseError { } } +/// A rich error type that includes the original string that failed to parse. pub type RichParseError = Report; /* @@ -1395,70 +1364,6 @@ impl fmt::Display for ReplaceError { #[cfg(feature = "std")] impl std::error::Error for ReplaceError {} -trait TryFromIter: Sized { - fn try_from_iter(iter: impl Iterator) -> Option; -} - -impl TryFromIter for ParseError { - fn try_from_iter(mut iter: impl Iterator) -> Option { - iter.next() - } -} -impl TryFromIter for ParseErrors { - fn try_from_iter(iter: impl Iterator) -> Option { - Self::new(iter) - } -} - -pub(crate) struct Validator<'b> { - // slashes ('/') separate tokens - // we increment the ptr_offset to point to this character - ptr_offset: usize, - // the bytes of the string to be validated - bytes: &'b [u8], - // the current cursor position within bytes - cursor: usize, - // whether or not an error was emitted on the previous iteration - sent: bool, -} - -impl<'b> Iterator for Validator<'b> { - type Item = ParseError; - - fn next(&mut self) -> Option { - if self.cursor >= self.bytes.len() { - return None; - } - if self.sent { - if let Some(cursor) = next_slash(self.bytes, self.cursor) { - self.cursor = cursor; - self.sent = false; - } else { - return None; - } - } - if let Err(err) = validate_bytes(self.bytes, self.cursor) { - self.sent = true; - return Some(err); - } - if self.bytes[self.cursor] == b'/' { - self.ptr_offset = self.cursor; - } - self.cursor = self.bytes.len(); - None - } -} - -const fn next_slash(bytes: &[u8], mut cursor: usize) -> Option { - while cursor < bytes.len() { - if bytes[cursor] == b'/' { - return Some(cursor); - } - cursor += 1; - } - None -} - const fn validate(value: &str) -> Result<&str, ParseError> { if value.is_empty() { return Ok(value); @@ -1524,16 +1429,6 @@ const fn validate_bytes(bytes: &[u8], offset: usize) -> Result<(), ParseError> { } Ok(()) } -const fn validate_tilde(bytes: &[u8], i: usize) -> Result<(), EncodingError> { - if i + 1 >= bytes.len() || (bytes[i + 1] != b'0' && bytes[i + 1] != b'1') { - Err(EncodingError { - offset: i, - source: InvalidEncoding::Tilde, - }) - } else { - Ok(()) - } -} /* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ diff --git a/src/token.rs b/src/token.rs index e20e04e..0944751 100644 --- a/src/token.rs +++ b/src/token.rs @@ -377,6 +377,7 @@ pub type InvalidEncodingError = EncodingError; pub struct EncodingError { /// offset of the erroneous `~` from within the `Token` pub offset: usize, + /// the specific encoding error pub source: InvalidEncoding, } @@ -407,6 +408,7 @@ impl fmt::Display for EncodingError { ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ */ +/// Represents the specific type of invalid encoding error. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub enum InvalidEncoding { /// `~` not followed by `0` or `1`