Fix parsing of or chains from string

Signed-off-by: trivernis <trivernis@protonmail.com>
pull/8/head
trivernis 3 years ago
parent 36d0853a8b
commit fa904761f5
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -16,11 +16,12 @@ reqwest = {version = "0.11.4", features = ["json"]}
log = "0.4.14" log = "0.4.14"
mime = "0.3.16" mime = "0.3.16"
chrono = "0.4.19" chrono = "0.4.19"
regex = "1.5.4"
lazy_static = "1.4.0"
[dev-dependencies] [dev-dependencies]
env_logger = "0.8.4" env_logger = "0.8.4"
maplit = "1.0.2" maplit = "1.0.2"
lazy_static = "1.4.0"
[dev-dependencies.tokio] [dev-dependencies.tokio]
version = "1.8.0" version = "1.8.0"

@ -1,11 +1,15 @@
use crate::utils::tag_list_to_string_list; use crate::utils::tag_list_to_string_list;
use crate::wrapper::tag::Tag; use crate::wrapper::tag::Tag;
use lazy_static::lazy_static;
use regex::Regex;
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct OrChain { pub struct OrChain {
tags: Vec<Tag>, tags: Vec<Tag>,
} }
impl Eq for OrChain {}
impl OrChain { impl OrChain {
/// Creates a new or chain directly from a list of tags /// Creates a new or chain directly from a list of tags
pub fn new(tags: Vec<Tag>) -> Self { pub fn new(tags: Vec<Tag>) -> Self {
@ -27,9 +31,12 @@ where
S: AsRef<str>, S: AsRef<str>,
{ {
fn from(s: S) -> Self { fn from(s: S) -> Self {
lazy_static! {
static ref CHAIN_REGEX: Regex = Regex::new(r#"(\s|'|")or(\s|'|")"#).unwrap();
}
let s = s.as_ref().to_ascii_lowercase(); let s = s.as_ref().to_ascii_lowercase();
let tags = s let tags = CHAIN_REGEX
.split("or") .split(&s)
.map(|mut t| { .map(|mut t| {
t = t t = t
.trim_start() .trim_start()
@ -40,6 +47,7 @@ where
}) })
.map(Tag::from) .map(Tag::from)
.collect(); .collect();
log::debug!("String parsed to or-chain {:?}", tags);
Self { tags } Self { tags }
} }

@ -1,17 +1,20 @@
#[derive(Clone, Debug)] #[derive(Clone, Debug, PartialOrd, PartialEq)]
pub struct Tag { pub struct Tag {
pub negated: bool, pub negated: bool,
pub name: String, pub name: String,
pub namespace: Option<String>, pub namespace: Option<String>,
} }
impl Eq for Tag {}
impl<S> From<S> for Tag impl<S> From<S> for Tag
where where
S: AsRef<str>, S: AsRef<str>,
{ {
fn from(value: S) -> Self { fn from(value: S) -> Self {
let value = value.as_ref().trim(); let mut value = value.as_ref().trim();
let negated = value.strip_prefix("-").is_some(); let negated = value.starts_with("-");
value = value.trim_start_matches("-");
if let Some((namespace, tag)) = value.split_once(":") { if let Some((namespace, tag)) = value.split_once(":") {
Self { Self {
negated, negated,

@ -2,6 +2,7 @@ mod test_address;
mod test_files; mod test_files;
mod test_hydrus; mod test_hydrus;
mod test_import; mod test_import;
mod test_or_chain;
mod test_page; mod test_page;
mod test_service; mod test_service;
mod test_tags; mod test_tags;

@ -0,0 +1,26 @@
use super::super::common;
use hydrus_api::wrapper::builders::or_chain_builder::OrChainBuilder;
use hydrus_api::wrapper::builders::tag_builder::TagBuilder;
use hydrus_api::wrapper::or_chain::OrChain;
#[test]
fn it_parses_from_string() {
common::setup();
let chain_string =
"'character:megumin' or 'character:aqua' OR '-character:hatsune miku'or 'terminator'";
let chain = OrChain::from(chain_string);
assert_eq!(
chain,
OrChainBuilder::new()
.add_tag("character:megumin".into())
.add_tag("character:aqua".into())
.add_tag(
TagBuilder::new("hatsune miku")
.namespace("character")
.negate()
.build()
)
.add_tag("terminator".into())
.build()
);
}
Loading…
Cancel
Save