use once_cell::sync::Lazy;
use regex::bytes::Regex;
use serde::Serialize;
use crate::Data;
use crate::DATA;
include!(concat!(env!("OUT_DIR"), "/regex_data.rs"));
pub struct Identifier {
pub min_rarity: f32,
pub max_rarity: f32,
pub tags: Vec<String>,
pub exclude_tags: Vec<String>,
pub boundaryless: bool,
pub file_support: bool,
}
impl Identifier {
#[inline]
pub fn min_rarity(mut self, rarity: f32) -> Self {
self.min_rarity = rarity;
self
}
#[inline]
pub fn max_rarity(mut self, rarity: f32) -> Self {
self.max_rarity = rarity;
self
}
#[inline]
pub fn include_tags(mut self, tags: &[String]) -> Self {
self.tags.extend_from_slice(tags);
self
}
#[inline]
pub fn exclude_tags(mut self, tags: &[String]) -> Self {
self.exclude_tags.extend_from_slice(tags);
self
}
#[inline]
pub fn boundaryless(mut self, boundaryless: bool) -> Self {
self.boundaryless = boundaryless;
self
}
#[inline]
pub fn file_support(mut self, support: bool) -> Self {
self.file_support = support;
self
}
}
impl Default for Identifier {
fn default() -> Self {
Identifier {
min_rarity: 0.0,
max_rarity: 1.0,
tags: vec![],
exclude_tags: vec![],
boundaryless: false,
file_support: false,
}
}
}
#[derive(Serialize, Debug)]
pub struct Match {
pub text: Vec<u8>,
pub data: Data,
}
impl Match {
pub fn new(text: Vec<u8>, data: Data) -> Match {
Match { text, data }
}
}
#[cfg(not(target_arch = "wasm32"))]
impl Identifier {
pub fn identify(&self, text: &[u8]) -> Vec<Match> {
let regexes = if self.boundaryless {
&BOUNDARYLESS_REGEX
} else {
®EX
};
DATA.iter()
.enumerate()
.filter_map(|(i, e)| {
if is_valid_filter(self, e) && regexes[i].is_match(text) {
Some(Match::new(text.to_owned(), e.clone()))
} else {
None
}
})
.collect::<Vec<Match>>()
}
pub fn first_match(&self, text: &[u8]) -> Option<Match> {
let regexes = if self.boundaryless {
&BOUNDARYLESS_REGEX
} else {
®EX
};
for (i, x) in DATA
.iter()
.enumerate()
.filter(|(_, x)| is_valid_filter(self, x))
{
if regexes[i].is_match(text) {
return Some(Match::new(text.to_owned(), x.clone()));
}
}
None
}
}
impl Identifier {
#[inline]
pub fn to_json(result: &[Match]) -> String {
serde_json::to_string_pretty(result).unwrap_or_default()
}
}
#[cfg(target_arch = "wasm32")]
impl Identifier {
pub fn identify(&self, text: &[Vec<u8>]) -> Vec<Match> {
let regexes = if self.boundaryless {
&BOUNDARYLESS_REGEX
} else {
®EX
};
DATA.iter()
.enumerate()
.filter_map(|(i, e)| {
if is_valid_filter(self, e) && regexes[i].is_match(text) {
Some(Match::new(text.to_owned(), e.clone()))
} else {
None
}
})
.collect::<Vec<Match>>()
}
}
fn is_valid_filter(configs: &Identifier, regex_data: &Data) -> bool {
if regex_data.rarity < configs.min_rarity {
return false;
}
if regex_data.rarity > configs.max_rarity {
return false;
}
if configs
.tags
.iter()
.any(|y| !regex_data.tags.iter().any(|x| x == y))
{
return false;
}
if configs
.exclude_tags
.iter()
.any(|y| regex_data.tags.iter().any(|x| x == y))
{
return false;
}
true
}