use chumsky::{error::Rich, extra, Parser};
use super::{
error::Error,
filter::{self, SearchEmailsFilterQuery},
sort::{self, SearchEmailsSorter},
SearchEmailsQuery,
};
pub type ParserError<'a> = extra::Err<Rich<'a, char>>;
#[doc = include_str!("./filter/grammar.abnf")]
#[doc = include_str!("./sort/grammar.abnf")]
pub fn parse<'a>(input: impl AsRef<str> + 'a) -> Result<SearchEmailsQuery, Error> {
let input = input.as_ref().trim();
if let Some((filters_input, sorters_input)) = input.rsplit_once("order by") {
if filters_input.trim().is_empty() {
let filter = None;
let sort = parse_sort(sorters_input).map(Some)?;
Ok(SearchEmailsQuery { filter, sort })
} else {
let filter = parse_filter(filters_input).map(Some)?;
let sort = parse_sort(sorters_input).map(Some)?;
Ok(SearchEmailsQuery { filter, sort })
}
} else {
let filter = parse_filter(input).map(Some)?;
let sort = None;
Ok(SearchEmailsQuery { filter, sort })
}
}
pub fn parse_filter<'a>(input: impl AsRef<str> + 'a) -> Result<SearchEmailsFilterQuery, Error> {
let input = input.as_ref().trim();
filter::parser::query()
.parse(input)
.into_result()
.map_err(|errs| {
let errs = errs
.into_iter()
.map(|err| err.clone().into_owned())
.collect();
Error::ParseError(errs, input.to_owned())
})
}
pub fn parse_sort<'a>(input: impl AsRef<str> + 'a) -> Result<Vec<SearchEmailsSorter>, Error> {
let input = input.as_ref().trim();
sort::parser::query()
.parse(input)
.into_result()
.map_err(|errs| {
let errs = errs
.into_iter()
.map(|err| err.clone().into_owned())
.collect();
Error::ParseError(errs, input.to_owned())
})
}