2021-11-04 14:22:35 +01:00
use std ::fmt ::Display ;
2021-11-04 16:12:17 +01:00
use nom ::error ::{ self , ParseError } ;
use nom ::Parser ;
2021-11-04 14:22:35 +01:00
use crate ::{ IResult , Span } ;
2021-11-09 00:50:15 +01:00
pub trait NomErrorExt < E > {
2021-11-04 14:22:35 +01:00
fn is_failure ( & self ) -> bool ;
fn map_err < O : FnOnce ( E ) -> E > ( self , op : O ) -> nom ::Err < E > ;
fn map_fail < O : FnOnce ( E ) -> E > ( self , op : O ) -> nom ::Err < E > ;
}
2021-11-09 00:50:15 +01:00
impl < E > NomErrorExt < E > for nom ::Err < E > {
2021-11-04 14:22:35 +01:00
fn is_failure ( & self ) -> bool {
matches! ( self , Self ::Failure ( _ ) )
}
fn map_err < O : FnOnce ( E ) -> E > ( self , op : O ) -> nom ::Err < E > {
match self {
e @ Self ::Failure ( _ ) = > e ,
2022-01-10 15:59:04 +01:00
e = > e . map ( op ) ,
2021-11-04 14:22:35 +01:00
}
}
fn map_fail < O : FnOnce ( E ) -> E > ( self , op : O ) -> nom ::Err < E > {
match self {
e @ Self ::Error ( _ ) = > e ,
2022-01-10 15:59:04 +01:00
e = > e . map ( op ) ,
2021-11-04 14:22:35 +01:00
}
}
}
/// cut a parser and map the error
2021-11-04 16:12:17 +01:00
pub fn cut_with_err < ' a , O > (
2022-12-13 15:29:52 +01:00
mut parser : impl FnMut ( Span < ' a > ) -> IResult < ' a , O > ,
2021-11-04 16:12:17 +01:00
mut with : impl FnMut ( Error < ' a > ) -> Error < ' a > ,
) -> impl FnMut ( Span < ' a > ) -> IResult < O > {
move | input | match parser . parse ( input ) {
Err ( nom ::Err ::Error ( e ) ) = > Err ( nom ::Err ::Failure ( with ( e ) ) ) ,
rest = > rest ,
}
2021-11-04 14:22:35 +01:00
}
#[ derive(Debug) ]
pub struct Error < ' a > {
context : Span < ' a > ,
kind : ErrorKind < ' a > ,
}
2022-08-17 16:06:29 +02:00
#[ derive(Debug) ]
pub enum ExpectedValueKind {
ReservedKeyword ,
Other ,
}
2021-11-04 14:22:35 +01:00
#[ derive(Debug) ]
pub enum ErrorKind < ' a > {
ReservedGeo ( & ' a str ) ,
2022-10-28 15:30:53 +02:00
GeoRadius ,
GeoBoundingBox ,
MisusedGeoRadius ,
MisusedGeoBoundingBox ,
2021-11-04 14:22:35 +01:00
InvalidPrimary ,
2023-09-06 11:40:21 +02:00
InvalidEscapedNumber ,
2021-11-04 14:22:35 +01:00
ExpectedEof ,
2022-08-17 16:06:29 +02:00
ExpectedValue ( ExpectedValueKind ) ,
2021-12-20 16:18:15 +01:00
MalformedValue ,
2022-06-15 10:13:34 +02:00
InOpeningBracket ,
InClosingBracket ,
2022-11-08 10:17:16 +01:00
NonFiniteFloat ,
2022-08-17 16:06:29 +02:00
InExpectedValue ( ExpectedValueKind ) ,
2022-06-15 10:13:34 +02:00
ReservedKeyword ( String ) ,
2021-11-04 14:22:35 +01:00
MissingClosingDelimiter ( char ) ,
Char ( char ) ,
2021-11-04 16:12:17 +01:00
InternalError ( error ::ErrorKind ) ,
2022-08-18 11:27:39 +02:00
DepthLimitReached ,
2021-11-04 16:12:17 +01:00
External ( String ) ,
2021-11-04 14:22:35 +01:00
}
impl < ' a > Error < ' a > {
2021-11-04 16:20:53 +01:00
pub fn kind ( & self ) -> & ErrorKind < ' a > {
& self . kind
}
2021-11-08 15:30:26 +01:00
pub fn context ( & self ) -> & Span < ' a > {
& self . context
}
2021-11-04 16:20:53 +01:00
pub fn new_from_kind ( context : Span < ' a > , kind : ErrorKind < ' a > ) -> Self {
2021-11-04 14:22:35 +01:00
Self { context , kind }
}
2021-11-04 16:20:53 +01:00
2021-11-04 17:24:55 +01:00
pub fn new_from_external ( context : Span < ' a > , error : impl std ::error ::Error ) -> Self {
Self ::new_from_kind ( context , ErrorKind ::External ( error . to_string ( ) ) )
}
2021-11-04 14:22:35 +01:00
pub fn char ( self ) -> char {
match self . kind {
ErrorKind ::Char ( c ) = > c ,
2021-12-20 16:18:15 +01:00
error = > panic! ( " Internal filter parser error: {:?} " , error ) ,
2021-11-04 14:22:35 +01:00
}
2021-11-04 16:12:17 +01:00
}
2021-11-04 14:22:35 +01:00
}
impl < ' a > ParseError < Span < ' a > > for Error < ' a > {
fn from_error_kind ( input : Span < ' a > , kind : error ::ErrorKind ) -> Self {
let kind = match kind {
error ::ErrorKind ::Eof = > ErrorKind ::ExpectedEof ,
2021-11-04 16:12:17 +01:00
kind = > ErrorKind ::InternalError ( kind ) ,
2021-11-04 14:22:35 +01:00
} ;
Self { context : input , kind }
}
fn append ( _input : Span < ' a > , _kind : error ::ErrorKind , other : Self ) -> Self {
other
}
fn from_char ( input : Span < ' a > , c : char ) -> Self {
Self { context : input , kind : ErrorKind ::Char ( c ) }
}
}
impl < ' a > Display for Error < ' a > {
fn fmt ( & self , f : & mut std ::fmt ::Formatter < '_ > ) -> std ::fmt ::Result {
let input = self . context . fragment ( ) ;
2021-11-09 11:19:30 +01:00
// When printing our error message we want to escape all `\n` to be sure we keep our format with the
// first line being the diagnostic and the second line being the incriminated filter.
let escaped_input = input . escape_debug ( ) ;
2022-06-15 10:13:34 +02:00
match & self . kind {
2022-08-17 16:06:29 +02:00
ErrorKind ::ExpectedValue ( _ ) if input . trim ( ) . is_empty ( ) = > {
2021-11-04 14:22:35 +01:00
writeln! ( f , " Was expecting a value but instead got nothing. " ) ?
}
2022-08-17 16:06:29 +02:00
ErrorKind ::ExpectedValue ( ExpectedValueKind ::ReservedKeyword ) = > {
writeln! ( f , " Was expecting a value but instead got `{escaped_input}`, which is a reserved keyword. To use `{escaped_input}` as a field name or a value, surround it by quotes. " ) ?
}
ErrorKind ::ExpectedValue ( ExpectedValueKind ::Other ) = > {
writeln! ( f , " Was expecting a value but instead got `{}`. " , escaped_input ) ?
}
2021-12-20 16:18:15 +01:00
ErrorKind ::MalformedValue = > {
writeln! ( f , " Malformed value: `{}`. " , escaped_input ) ?
}
2021-11-04 16:12:17 +01:00
ErrorKind ::MissingClosingDelimiter ( c ) = > {
2021-11-09 11:19:30 +01:00
writeln! ( f , " Expression `{}` is missing the following closing delimiter: `{}`. " , escaped_input , c ) ?
2021-11-04 14:22:35 +01:00
}
ErrorKind ::InvalidPrimary = > {
2023-03-14 18:08:12 +01:00
let text = if input . trim ( ) . is_empty ( ) { " but instead got nothing. " . to_string ( ) } else { format! ( " at ` {} `. " , escaped_input ) } ;
writeln! ( f , " Was expecting an operation `=`, `!=`, `>=`, `>`, `<=`, `<`, `IN`, `NOT IN`, `TO`, `EXISTS`, `NOT EXISTS`, `IS NULL`, `IS NOT NULL`, `IS EMPTY`, `IS NOT EMPTY`, `_geoRadius`, or `_geoBoundingBox` {} " , text ) ?
2021-11-04 14:22:35 +01:00
}
2023-09-06 11:40:21 +02:00
ErrorKind ::InvalidEscapedNumber = > {
writeln! ( f , " Found an invalid escaped sequence number: `{}`. " , escaped_input ) ?
}
2021-11-04 14:22:35 +01:00
ErrorKind ::ExpectedEof = > {
2021-11-09 11:19:30 +01:00
writeln! ( f , " Found unexpected characters at the end of the filter: `{}`. You probably forgot an `OR` or an `AND` rule. " , escaped_input ) ?
2021-11-04 14:22:35 +01:00
}
2022-10-28 15:30:53 +02:00
ErrorKind ::GeoRadius = > {
2021-11-04 14:22:35 +01:00
writeln! ( f , " The `_geoRadius` filter expects three arguments: `_geoRadius(latitude, longitude, radius)`. " ) ?
}
2022-10-28 15:30:53 +02:00
ErrorKind ::GeoBoundingBox = > {
2023-02-06 16:50:27 +01:00
writeln! ( f , " The `_geoBoundingBox` filter expects two pairs of arguments: `_geoBoundingBox([latitude, longitude], [latitude, longitude])`. " ) ?
2022-10-28 15:30:53 +02:00
}
2021-11-04 14:22:35 +01:00
ErrorKind ::ReservedGeo ( name ) = > {
2023-03-31 22:10:37 +02:00
writeln! ( f , " `{}` is a reserved keyword and thus can't be used as a filter expression. Use the `_geoRadius(latitude, longitude, distance)` or `_geoBoundingBox([latitude, longitude], [latitude, longitude])` built-in rules to filter on `_geo` coordinates. " , name . escape_debug ( ) ) ?
2021-11-04 14:22:35 +01:00
}
2022-10-28 15:30:53 +02:00
ErrorKind ::MisusedGeoRadius = > {
2021-11-04 14:22:35 +01:00
writeln! ( f , " The `_geoRadius` filter is an operation and can't be used as a value. " ) ?
2022-10-28 15:30:53 +02:00
}
ErrorKind ::MisusedGeoBoundingBox = > {
writeln! ( f , " The `_geoBoundingBox` filter is an operation and can't be used as a value. " ) ?
2021-11-04 14:22:35 +01:00
}
2022-06-15 10:13:34 +02:00
ErrorKind ::ReservedKeyword ( word ) = > {
writeln! ( f , " `{word}` is a reserved keyword and thus cannot be used as a field name unless it is put inside quotes. Use \" {word} \" or \' {word} \' instead. " ) ?
}
ErrorKind ::InOpeningBracket = > {
writeln! ( f , " Expected `[` after `IN` keyword. " ) ?
}
ErrorKind ::InClosingBracket = > {
writeln! ( f , " Expected matching `]` after the list of field names given to `IN[` " ) ?
}
2022-11-08 10:17:16 +01:00
ErrorKind ::NonFiniteFloat = > {
writeln! ( f , " Non finite floats are not supported " ) ?
}
2022-08-17 16:06:29 +02:00
ErrorKind ::InExpectedValue ( ExpectedValueKind ::ReservedKeyword ) = > {
writeln! ( f , " Expected only comma-separated field names inside `IN[..]` but instead found `{escaped_input}`, which is a keyword. To use `{escaped_input}` as a field name or a value, surround it by quotes. " ) ?
}
ErrorKind ::InExpectedValue ( ExpectedValueKind ::Other ) = > {
writeln! ( f , " Expected only comma-separated field names inside `IN[..]` but instead found `{escaped_input}`. " ) ?
2022-06-15 10:13:34 +02:00
}
2021-11-04 14:22:35 +01:00
ErrorKind ::Char ( c ) = > {
panic! ( " Tried to display a char error with ` {} ` " , c )
}
2022-08-18 11:27:39 +02:00
ErrorKind ::DepthLimitReached = > writeln! (
f ,
" The filter exceeded the maximum depth limit. Try rewriting the filter so that it contains fewer nested conditions. "
) ? ,
2021-11-04 16:12:17 +01:00
ErrorKind ::InternalError ( kind ) = > writeln! (
2021-11-04 14:22:35 +01:00
f ,
2021-11-04 16:12:17 +01:00
" Encountered an internal `{:?}` error while parsing your filter. Please fill an issue " , kind
2021-11-04 14:22:35 +01:00
) ? ,
2021-11-04 16:12:17 +01:00
ErrorKind ::External ( ref error ) = > writeln! ( f , " {} " , error ) ? ,
2021-11-04 14:22:35 +01:00
}
2021-11-09 10:27:29 +01:00
let base_column = self . context . get_utf8_column ( ) ;
let size = self . context . fragment ( ) . chars ( ) . count ( ) ;
2021-11-09 11:19:30 +01:00
write! ( f , " {}:{} {} " , base_column , base_column + size , self . context . extra )
2021-11-04 14:22:35 +01:00
}
}