mirror of
https://github.com/JockeTF/fimfareader.git
synced 2024-11-23 13:58:00 +01:00
Upgrade dependency Nom to v7
This commit is contained in:
parent
18ab30684d
commit
217eb6240f
3 changed files with 145 additions and 163 deletions
82
Cargo.lock
generated
82
Cargo.lock
generated
|
@ -32,23 +32,11 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.1.0"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
|
@ -247,9 +235,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.10"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
|
@ -266,19 +254,6 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags 1.3.2",
|
||||
"cfg-if",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
|
@ -297,6 +272,12 @@ version = "2.7.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.7.2"
|
||||
|
@ -312,7 +293,7 @@ version = "0.28.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
|
@ -320,13 +301,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "5.1.3"
|
||||
version = "7.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b"
|
||||
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||
dependencies = [
|
||||
"lexical-core",
|
||||
"memchr",
|
||||
"version_check",
|
||||
"minimal-lexical",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -364,9 +344,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
|
@ -384,9 +364,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.3"
|
||||
version = "1.10.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -407,9 +387,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
|
||||
[[package]]
|
||||
name = "rustyline"
|
||||
|
@ -417,7 +397,7 @@ version = "14.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7803e8936da37efd9b6d4478277f4b2b9bb5cdb37a113e8d63222e58da647e63"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"clipboard-win",
|
||||
"libc",
|
||||
|
@ -464,26 +444,20 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.114"
|
||||
version = "1.0.115"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
|
||||
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.53"
|
||||
version = "2.0.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032"
|
||||
checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -514,12 +488,6 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.92"
|
||||
|
|
|
@ -13,11 +13,11 @@ version = "*"
|
|||
[dependencies.chrono-english]
|
||||
version = "*"
|
||||
|
||||
[dependencies.nom]
|
||||
version = "7"
|
||||
|
||||
[dependencies.rayon]
|
||||
version = "*"
|
||||
|
||||
[dependencies.regex]
|
||||
version = "*"
|
||||
|
||||
[dependencies.nom]
|
||||
version = "5"
|
||||
|
|
|
@ -1,11 +1,28 @@
|
|||
//! Query parser.
|
||||
|
||||
use chrono::prelude::*;
|
||||
use chrono::DateTime;
|
||||
use chrono::Utc;
|
||||
|
||||
use nom::character::complete::*;
|
||||
use nom::branch::alt;
|
||||
use nom::bytes::complete::escaped;
|
||||
use nom::bytes::complete::tag;
|
||||
use nom::character::complete::char;
|
||||
use nom::character::complete::none_of;
|
||||
use nom::character::complete::one_of;
|
||||
use nom::character::complete::space0;
|
||||
use nom::combinator::eof;
|
||||
use nom::combinator::map;
|
||||
use nom::combinator::value;
|
||||
use nom::error::Error as NomError;
|
||||
use nom::error::ErrorKind as NomErrorKind;
|
||||
use nom::sequence::*;
|
||||
use nom::*;
|
||||
use nom::multi::separated_list1;
|
||||
use nom::sequence::delimited;
|
||||
use nom::sequence::preceded;
|
||||
use nom::sequence::terminated;
|
||||
use nom::sequence::tuple;
|
||||
use nom::Err as NomErr;
|
||||
use nom::Finish;
|
||||
use nom::IResult;
|
||||
|
||||
use fimfareader::archive::Story;
|
||||
use fimfareader::error::*;
|
||||
|
@ -20,6 +37,7 @@ pub enum Source {
|
|||
DtuFn(Box<dyn Fn(&Story) -> &Option<DateTime<Utc>> + Sync>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum Operator {
|
||||
Exact,
|
||||
Fuzzy,
|
||||
|
@ -28,67 +46,79 @@ pub enum Operator {
|
|||
}
|
||||
|
||||
macro_rules! sfn {
|
||||
($func:expr) => {
|
||||
|_| Source::StrFn(Box::new($func))
|
||||
($tag:expr => $func:expr) => {
|
||||
preceded(tag($tag), |input| {
|
||||
Ok((input, Source::StrFn(Box::new($func))))
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! ifn {
|
||||
($func:expr) => {
|
||||
|_| Source::IntFn(Box::new($func))
|
||||
};
|
||||
($tag:expr => $func:expr) => {{
|
||||
preceded(tag($tag), |input| {
|
||||
Ok((input, Source::IntFn(Box::new($func))))
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! dfn {
|
||||
($func:expr) => {
|
||||
|_| Source::DtuFn(Box::new($func))
|
||||
($tag:expr => $func:expr) => {
|
||||
preceded(tag($tag), |input| {
|
||||
Ok((input, Source::DtuFn(Box::new($func))))
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
named!(source<&str, Source>, preceded!(space0, alt!(
|
||||
tag!("id") => { ifn!(|s| s.id) } |
|
||||
fn source(input: &str) -> IResult<&str, Source> {
|
||||
let story = alt((
|
||||
ifn!("id" => |s| s.id),
|
||||
sfn!("story" => |s| &s.title),
|
||||
sfn!("title" => |s| &s.title),
|
||||
sfn!("description" => |s| &s.description_html),
|
||||
sfn!("short description" => |s| &s.short_description),
|
||||
sfn!("url" => |s| &s.url),
|
||||
dfn!("modified" => |s| &s.date_modified),
|
||||
dfn!("published" => |s| &s.date_published),
|
||||
dfn!("updated" => |s| &s.date_updated),
|
||||
ifn!("chapters" => |s| i64::from(s.num_chapters)),
|
||||
ifn!("comments" => |s| i64::from(s.num_comments)),
|
||||
ifn!("dislikes" => |s| i64::from(s.num_dislikes)),
|
||||
ifn!("likes" => |s| i64::from(s.num_likes)),
|
||||
ifn!("total views" => |s| i64::from(s.total_num_views)),
|
||||
ifn!("views" => |s| i64::from(s.num_views)),
|
||||
ifn!("words" => |s| i64::from(s.num_words)),
|
||||
));
|
||||
|
||||
tag!("story") => { sfn!(|s| &s.title) } |
|
||||
tag!("title") => { sfn!(|s| &s.title) } |
|
||||
let author = alt((
|
||||
sfn!("author" => |s| &s.author.name),
|
||||
sfn!("author name" => |s| &s.author.name),
|
||||
ifn!("author id" => |s| s.author.id),
|
||||
dfn!("author joined" => |s| &s.author.date_joined),
|
||||
));
|
||||
|
||||
tag!("description") => { sfn!(|s| &s.description_html) } |
|
||||
tag!("short description") => { sfn!(|s| &s.short_description) } |
|
||||
tag!("url") => { sfn!(|s| &s.url) } |
|
||||
let archive = alt((
|
||||
sfn!("path" => |s| &s.archive.path),
|
||||
sfn!("archive" => |s| &s.archive.path),
|
||||
sfn!("archive path" => |s| &s.archive.path),
|
||||
dfn!("entry checked" => |s| &s.archive.date_checked),
|
||||
dfn!("entry created" => |s| &s.archive.date_created),
|
||||
dfn!("entry fetched" => |s| &s.archive.date_fetched),
|
||||
dfn!("entry updated" => |s| &s.archive.date_updated),
|
||||
));
|
||||
|
||||
tag!("modified") => { dfn!(|s| &s.date_modified) } |
|
||||
tag!("published") => { dfn!(|s| &s.date_published) } |
|
||||
tag!("updated") => { dfn!(|s| &s.date_updated) } |
|
||||
preceded(space0, alt((story, author, archive)))(input)
|
||||
}
|
||||
|
||||
tag!("chapters") => { ifn!(|s| i64::from(s.num_chapters)) } |
|
||||
tag!("comments") => { ifn!(|s| i64::from(s.num_comments)) } |
|
||||
tag!("dislikes") => { ifn!(|s| i64::from(s.num_dislikes)) } |
|
||||
tag!("likes") => { ifn!(|s| i64::from(s.num_likes)) } |
|
||||
tag!("total views") => { ifn!(|s| i64::from(s.total_num_views)) } |
|
||||
tag!("views") => { ifn!(|s| i64::from(s.num_views)) } |
|
||||
tag!("words") => { ifn!(|s| i64::from(s.num_words)) } |
|
||||
fn operator(input: &str) -> IResult<&str, Operator> {
|
||||
let operator = alt((
|
||||
value(Operator::Exact, char('=')),
|
||||
value(Operator::Fuzzy, char(':')),
|
||||
value(Operator::LessThan, char('<')),
|
||||
value(Operator::MoreThan, char('>')),
|
||||
));
|
||||
|
||||
tag!("author") => { sfn!(|s| &s.author.name) } |
|
||||
tag!("author name") => { sfn!(|s| &s.author.name) } |
|
||||
|
||||
tag!("author id") => { ifn!(|s| s.author.id) } |
|
||||
tag!("author joined") => { dfn!(|s| &s.author.date_joined) } |
|
||||
|
||||
tag!("path") => { sfn!(|s| &s.archive.path) } |
|
||||
tag!("archive") => { sfn!(|s| &s.archive.path) } |
|
||||
tag!("archive path") => { sfn!(|s| &s.archive.path) } |
|
||||
|
||||
tag!("entry checked") => { dfn!(|s| &s.archive.date_checked) } |
|
||||
tag!("entry created") => { dfn!(|s| &s.archive.date_created) } |
|
||||
tag!("entry fetched") => { dfn!(|s| &s.archive.date_fetched) } |
|
||||
tag!("entry updated") => { dfn!(|s| &s.archive.date_updated) }
|
||||
)));
|
||||
|
||||
named!(operator<&str, Operator>, preceded!(space0, alt!(
|
||||
tag!("=") => { |_| Operator::Exact } |
|
||||
tag!(":") => { |_| Operator::Fuzzy } |
|
||||
tag!("<") => { |_| Operator::LessThan } |
|
||||
tag!(">") => { |_| Operator::MoreThan }
|
||||
)));
|
||||
preceded(space0, operator)(input)
|
||||
}
|
||||
|
||||
fn unescape(input: &str) -> String {
|
||||
input
|
||||
|
@ -98,47 +128,50 @@ fn unescape(input: &str) -> String {
|
|||
.replace("\\\\", "\\")
|
||||
}
|
||||
|
||||
named!(value<&str, &str>,
|
||||
escaped!(none_of!("),|\\"), '\\', one_of!("),|\\"))
|
||||
);
|
||||
fn evalue(input: &str) -> IResult<&str, &str> {
|
||||
escaped(none_of("),|\\"), '\\', one_of("),|\\"))(input)
|
||||
}
|
||||
|
||||
named!(target<&str, String>, preceded!(space0,
|
||||
map!(value, |value| unescape(value.trim()))
|
||||
));
|
||||
fn target(input: &str) -> IResult<&str, String> {
|
||||
preceded(space0, map(evalue, |value| unescape(value.trim())))(input)
|
||||
}
|
||||
|
||||
fn item(input: &str) -> IResult<&str, Filter> {
|
||||
let result = tuple((source, operator, target))(input)?;
|
||||
let (left, (src, op, value)) = result;
|
||||
|
||||
let Ok(filter) = optimize(src, op, &value) else {
|
||||
return Err(Err::Failure((input, NomErrorKind::Permutation)));
|
||||
let error = NomError::new(input, NomErrorKind::Permutation);
|
||||
return Err(NomErr::Failure(error));
|
||||
};
|
||||
|
||||
Ok((left, filter))
|
||||
}
|
||||
|
||||
named!(parens<&str, Filter>, alt!(
|
||||
delimited!(
|
||||
preceded!(space0, tag!("(")),
|
||||
preceded!(space0, call!(ofunc)),
|
||||
preceded!(space0, tag!(")"))
|
||||
) |
|
||||
call!(item)
|
||||
));
|
||||
fn parens(input: &str) -> IResult<&str, Filter> {
|
||||
let group = delimited(
|
||||
preceded(space0, char('(')),
|
||||
preceded(space0, ofunc),
|
||||
preceded(space0, char(')')),
|
||||
);
|
||||
|
||||
fn negate(input: &str) -> IResult<&str, Filter> {
|
||||
let (left, filter) = parens(input)?;
|
||||
|
||||
Ok((left, Box::new(move |s| !filter(s))))
|
||||
alt((group, item))(input)
|
||||
}
|
||||
|
||||
named!(nlist<&str, Filter>, preceded!(space0, alt!(
|
||||
preceded!(char('!'), call!(negate)) | call!(parens)
|
||||
)));
|
||||
fn negate(input: &str) -> IResult<&str, Filter> {
|
||||
let (input, filter) = parens(input)?;
|
||||
Ok((input, Box::new(move |s| !filter(s))))
|
||||
}
|
||||
|
||||
named!(alist<&str, Vec<Filter>>, separated_nonempty_list!(
|
||||
preceded!(space0, char(',')), call!(nlist)
|
||||
));
|
||||
fn nlist(input: &str) -> IResult<&str, Filter> {
|
||||
let negated = preceded(char('!'), negate);
|
||||
preceded(space0, alt((negated, parens)))(input)
|
||||
}
|
||||
|
||||
fn alist(input: &str) -> IResult<&str, Vec<Filter>> {
|
||||
let sep = preceded(space0, char(','));
|
||||
separated_list1(sep, nlist)(input)
|
||||
}
|
||||
|
||||
fn afunc(input: &str) -> IResult<&str, Filter> {
|
||||
let (left, mut filters) = alist(input)?;
|
||||
|
@ -160,9 +193,10 @@ fn afunc(input: &str) -> IResult<&str, Filter> {
|
|||
Ok((left, filter))
|
||||
}
|
||||
|
||||
named!(olist<&str, Vec<Filter>>, separated_nonempty_list!(
|
||||
preceded!(space0, char('|')), call!(afunc)
|
||||
));
|
||||
fn olist(input: &str) -> IResult<&str, Vec<Filter>> {
|
||||
let sep = preceded(space0, char('|'));
|
||||
separated_list1(sep, afunc)(input)
|
||||
}
|
||||
|
||||
fn ofunc(input: &str) -> IResult<&str, Filter> {
|
||||
let (left, mut filters) = olist(input)?;
|
||||
|
@ -184,33 +218,13 @@ fn ofunc(input: &str) -> IResult<&str, Filter> {
|
|||
Ok((left, filter))
|
||||
}
|
||||
|
||||
fn format_error(query: &str, input: &str, error: NomErrorKind) -> String {
|
||||
let description = error.description().to_lowercase();
|
||||
let position = query.len() - input.len();
|
||||
|
||||
format!("Invalid {} at {}", description, position)
|
||||
}
|
||||
|
||||
fn translate_error(query: &str, error: Err<(&str, NomErrorKind)>) -> Error {
|
||||
let message = match error {
|
||||
Err::Error((i, e)) => format_error(query, i, e),
|
||||
Err::Failure((i, e)) => format_error(query, i, e),
|
||||
Err::Incomplete(_) => String::from("Incomplete input"),
|
||||
};
|
||||
|
||||
Error::query(message)
|
||||
}
|
||||
|
||||
fn translate_incomplete(query: &str, input: &str) -> Error {
|
||||
let position = query.len() - input.len();
|
||||
|
||||
Error::query(format!("Incomplete input at {}", position))
|
||||
fn complete(input: &str) -> IResult<&str, Filter> {
|
||||
terminated(ofunc, eof)(input.trim())
|
||||
}
|
||||
|
||||
pub fn parse(query: &str) -> Result<Filter> {
|
||||
match ofunc(query.trim()) {
|
||||
Ok(("", filter)) => Ok(filter),
|
||||
Ok((i, _)) => Err(translate_incomplete(query, i)),
|
||||
Err(e) => Err(translate_error(query, e)),
|
||||
match complete(query).finish() {
|
||||
Ok((_, filter)) => Ok(filter),
|
||||
Err(e) => Err(Error::query(e)),
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue