3535//! assert_eq!(Index::Next.for_len_unchecked(30), 30);
3636//! ```
3737
38- use crate :: Token ;
38+ use crate :: {
39+ diagnostic:: { diagnostic_url, IntoReport , Label } ,
40+ Token ,
41+ } ;
3942use alloc:: string:: String ;
40- use core:: { fmt, num:: ParseIntError , str:: FromStr } ;
43+ use core:: { fmt, iter :: once , num:: ParseIntError , str:: FromStr } ;
4144
4245/// Represents an abstract index into an array.
4346///
@@ -177,7 +180,6 @@ impl FromStr for Index {
177180 // representing a `usize` but not allowed in RFC 6901 array
178181 // indices
179182 Err ( ParseIndexError :: InvalidCharacter ( InvalidCharacterError {
180- source : String :: from ( s) ,
181183 offset,
182184 } ) )
183185 } ,
@@ -309,6 +311,75 @@ impl fmt::Display for ParseIndexError {
309311 }
310312}
311313
314+ // shouldn't be used directly, but is part of a public interface
315+ #[ doc( hidden) ]
316+ #[ derive( Debug ) ]
317+ pub enum StringOrToken {
318+ String ( String ) ,
319+ Token ( Token < ' static > ) ,
320+ }
321+
322+ impl From < String > for StringOrToken {
323+ fn from ( value : String ) -> Self {
324+ Self :: String ( value)
325+ }
326+ }
327+
328+ impl From < Token < ' static > > for StringOrToken {
329+ fn from ( value : Token < ' static > ) -> Self {
330+ Self :: Token ( value)
331+ }
332+ }
333+
334+ impl core:: ops:: Deref for StringOrToken {
335+ type Target = str ;
336+
337+ fn deref ( & self ) -> & Self :: Target {
338+ match self {
339+ StringOrToken :: String ( s) => s. as_str ( ) ,
340+ StringOrToken :: Token ( t) => t. encoded ( ) ,
341+ }
342+ }
343+ }
344+
345+ impl IntoReport for ParseIndexError {
346+ type Subject = StringOrToken ;
347+
348+ fn url ( ) -> & ' static str {
349+ diagnostic_url ! ( enum ParseIndexError )
350+ }
351+
352+ fn labels (
353+ & self ,
354+ subject : & Self :: Subject ,
355+ ) -> Option < Box < dyn Iterator < Item = crate :: diagnostic:: Label > > > {
356+ let subject = & * * subject;
357+ match self {
358+ ParseIndexError :: InvalidInteger ( _) => None ,
359+ ParseIndexError :: LeadingZeros => {
360+ let len = subject
361+ . chars ( )
362+ . position ( |c| c != '0' )
363+ . expect ( "starts with zeros" ) ;
364+ let text = String :: from ( "leading zeros" ) ;
365+ Some ( Box :: new ( once ( Label :: new ( text, 0 , len) ) ) )
366+ }
367+ ParseIndexError :: InvalidCharacter ( err) => {
368+ let len = subject
369+ . chars ( )
370+ . skip ( err. offset )
371+ . position ( |c| !c. is_ascii_digit ( ) )
372+ . expect ( "at least one non-digit char" ) ;
373+ let text = String :: from ( "invalid character(s)" ) ;
374+ Some ( Box :: new ( once ( Label :: new ( text, err. offset , len) ) ) )
375+ }
376+ }
377+ }
378+ }
379+
380+ #[ cfg( feature = "miette" ) ]
381+ impl miette:: Diagnostic for ParseIndexError { }
382+
312383#[ cfg( feature = "std" ) ]
313384impl std:: error:: Error for ParseIndexError {
314385 fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
@@ -323,7 +394,6 @@ impl std::error::Error for ParseIndexError {
323394/// Indicates that a non-digit character was found when parsing the RFC 6901 array index.
324395#[ derive( Debug , Clone , PartialEq , Eq ) ]
325396pub struct InvalidCharacterError {
326- pub ( crate ) source : String ,
327397 pub ( crate ) offset : usize ,
328398}
329399
@@ -334,29 +404,14 @@ impl InvalidCharacterError {
334404 pub fn offset ( & self ) -> usize {
335405 self . offset
336406 }
337-
338- /// Returns the source string.
339- pub fn source ( & self ) -> & str {
340- & self . source
341- }
342-
343- /// Returns the offending character.
344- #[ allow( clippy:: missing_panics_doc) ]
345- pub fn char ( & self ) -> char {
346- self . source
347- . chars ( )
348- . nth ( self . offset )
349- . expect ( "char was found at offset" )
350- }
351407}
352408
353409impl fmt:: Display for InvalidCharacterError {
354410 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
355411 write ! (
356412 f,
357- "token contains the non-digit character '{}', \
358- which is disallowed by RFC 6901",
359- self . char ( )
413+ "token contains a non-digit character, \
414+ which is disallowed by RFC 6901",
360415 )
361416 }
362417}
0 commit comments