use alloc::{string::String, vec::Vec};
use chumsky::{Parser, error::Rich, extra};
use crate::search::{
error::Error,
filter::{self, query::SearchEmailsFilterQuery},
query::SearchEmailsQuery,
sort::{self, query::SearchEmailsSorter},
};
pub type ParserError<'a> = extra::Err<Rich<'a, char>>;
pub fn parse(input: impl AsRef<str>) -> 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(input: impl AsRef<str>) -> 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, String::from(input))
})
}
pub fn parse_sort(input: impl AsRef<str>) -> 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, String::from(input))
})
}