mod resolved_spec;
mod spec_error;
mod unresolved_parser;
mod unresolved_spec;
mod version_types;
pub use resolved_spec::*;
pub use spec_error::*;
pub use unresolved_parser::*;
pub use unresolved_spec::*;
pub use version_types::*;
use regex::Regex;
use std::sync::OnceLock;
pub fn is_alias_name<T: AsRef<str>>(value: T) -> bool {
let value = value.as_ref();
value.chars().enumerate().all(|(i, c)| {
if i == 0 {
char::is_ascii_alphabetic(&c)
} else {
char::is_ascii_alphanumeric(&c)
|| c == '-'
|| c == '_'
|| c == '/'
|| c == '.'
|| c == '*'
}
})
}
pub fn is_calver<T: AsRef<str>>(value: T) -> bool {
get_calver_regex().is_match(value.as_ref())
}
pub fn is_semver<T: AsRef<str>>(value: T) -> bool {
get_semver_regex().is_match(value.as_ref())
}
pub fn clean_version_string<T: AsRef<str>>(value: T) -> String {
let mut version = value.as_ref().trim();
#[allow(clippy::assigning_clones)]
if (version.starts_with('v') || version.starts_with('V'))
&& version
.as_bytes()
.get(1)
.is_some_and(|c| c.is_ascii_digit())
{
version = &version[1..];
}
version.to_owned()
}
pub fn clean_version_req_string<T: AsRef<str>>(value: T) -> String {
value
.as_ref()
.trim()
.replace(".*", "")
.replace(".x", "")
.replace(".X", "")
.replace("-*", "")
.replace("&&", ",")
}
pub fn get_calver_regex() -> &'static Regex {
static CALVER_REGEX: OnceLock<Regex> = OnceLock::new();
CALVER_REGEX.get_or_init(|| {
Regex::new(r"^(?<year>[0-9]{1,4})-(?<month>((0?[1-9]{1})|10|11|12))(-(?<day>(0?[1-9]{1}|[1-3]{1}[0-9]{1})))?((_|\.)(?<micro>[0-9]+))?(?<pre>-[a-zA-Z]{1}[-0-9a-zA-Z.]+)?$").unwrap()
})
}
pub fn get_semver_regex() -> &'static Regex {
static SEMVER_REGEX: OnceLock<Regex> = OnceLock::new();
SEMVER_REGEX.get_or_init(|| {
Regex::new(r"^(?<major>[0-9]+).(?<minor>[0-9]+).(?<patch>[0-9]+)(?<pre>-[-0-9a-zA-Z.]+)?(?<build>\+[-0-9a-zA-Z.]+)?$")
.unwrap()
})
}