mod cpu_regex;
mod device_regex;
mod engine_regex;
mod os_regex;
mod product_regex;
mod replacement;
pub(crate) use cpu_regex::CPURegex;
pub(crate) use device_regex::DeviceRegex;
pub(crate) use engine_regex::EngineRegex;
pub(crate) use os_regex::OSRegex;
pub(crate) use product_regex::ProductRegex;
use regex::{Error as RegexError, Regex, RegexBuilder};
pub(crate) use replacement::{Replacement, capture_str, resolve};
use yaml_rust::{Yaml, yaml::Hash};
use crate::UserAgentParserError;
const DFA_SIZE_LIMIT: usize = 8 * 1024 * 1024;
#[inline]
pub(crate) fn build_regex(pattern: &str, case_insensitive: bool) -> Result<Regex, RegexError> {
RegexBuilder::new(pattern)
.case_insensitive(case_insensitive)
.dfa_size_limit(DFA_SIZE_LIMIT)
.build()
}
pub(crate) fn from_yaml_section<T>(
yaml: &Yaml,
mut f: impl FnMut(Regex, &Hash) -> Result<T, UserAgentParserError>,
) -> Result<Vec<T>, UserAgentParserError> {
let yamls = yaml.as_vec().ok_or(UserAgentParserError::IncorrectSource)?;
let mut entries = Vec::with_capacity(yamls.len());
let yaml_regex = Yaml::String("regex".to_string());
let yaml_regex_flag = Yaml::String("regex_flag".to_string());
for yaml in yamls {
let yaml = yaml.as_hash().ok_or(UserAgentParserError::IncorrectSource)?;
let pattern = yaml
.get(&yaml_regex)
.ok_or(UserAgentParserError::IncorrectSource)?
.as_str()
.ok_or(UserAgentParserError::IncorrectSource)?;
let case_insensitive = match yaml.get(&yaml_regex_flag) {
Some(yaml) => yaml.as_str().ok_or(UserAgentParserError::IncorrectSource)? == "i",
None => false,
};
entries.push(f(build_regex(pattern, case_insensitive)?, yaml)?);
}
Ok(entries)
}
pub(crate) fn optional_replacement(
yaml: &Hash,
key: &Yaml,
) -> Result<Option<Replacement>, UserAgentParserError> {
match yaml.get(key) {
Some(yaml) => {
let text = yaml.as_str().ok_or(UserAgentParserError::IncorrectSource)?;
Ok(Some(Replacement::new(text)))
},
None => Ok(None),
}
}