use crate::*;
pub(crate) fn match_tier(name: &str, q: &str) -> u8 {
if q.is_empty() {
return 0;
}
if name == q {
3
} else if name.ends_with(q)
&& (name[..name.len() - q.len()].ends_with("::") || name[..name.len() - q.len()].ends_with('.'))
{
2
} else if name.contains(q) {
1
} else {
0
}
}
pub(crate) fn name_segments(name: &str) -> Vec<&str> {
if name.contains("::") {
name.split("::").collect()
} else {
name.split('.').collect()
}
}
pub(crate) fn best_tier<'a>(names: impl Iterator<Item = &'a str>, q: &str) -> u8 {
names.map(|n| match_tier(n, q)).max().unwrap_or(0)
}
pub(crate) fn q_match(name: &str, q: &str, tier: u8) -> bool {
tier > 0 && match_tier(name, q) >= tier
}
pub(crate) fn simple_method(f: &str) -> &str {
f.rfind('.').map(|i| &f[i + 1..]).unwrap_or(f)
}
pub(crate) fn declaring_type(f: &str) -> &str {
f.rfind('.').map(|i| &f[..i]).unwrap_or(f)
}
pub(crate) fn is_subtype_of(ty: &str, owner: &str, hier: &BTreeMap<String, Vec<String>>) -> bool {
if ty == owner {
return true;
}
let mut seen: HashSet<&str> = HashSet::new();
let mut stack: Vec<&str> = vec![ty];
while let Some(t) = stack.pop() {
if let Some(sups) = hier.get(t) {
for s in sups {
if s == owner {
return true;
}
if seen.insert(s.as_str()) {
stack.push(s.as_str());
}
}
}
}
false
}
pub(crate) fn norm_name(name: &str) -> &str {
match name.strip_prefix('<') {
Some(rest) => rest.split(" as ").next().unwrap_or(rest),
None => name,
}
}
pub(crate) fn common_prefix_len(names: &[&String]) -> usize {
let mut prefix: Option<Vec<&str>> = None;
for n in names {
let segs: Vec<&str> = name_segments(norm_name(n)); match &mut prefix {
None => prefix = Some(segs),
Some(p) => {
let mut i = 0;
while i < p.len() && i < segs.len() && p[i] == segs[i] {
i += 1;
}
p.truncate(i);
}
}
}
prefix.map(|p| p.len()).unwrap_or(0)
}
pub(crate) fn layer_of(name: &str, prefix_len: usize) -> String {
let segs: Vec<&str> = name_segments(norm_name(name));
if prefix_len + 1 < segs.len() {
segs[prefix_len].to_string()
} else {
"(root)".to_string()
}
}
pub(crate) fn sorted(v: &[String]) -> Vec<String> {
let mut out = v.to_vec();
out.sort();
out
}
pub(crate) fn q_or(s: &str) -> &str {
if s.is_empty() { "?" } else { s }
}
pub(crate) fn three(args: &[String]) -> Option<(&str, &str, bool)> {
match args {
[a, b, c, ..] => Some((a.as_str(), b.as_str(), c == "1")),
_ => None,
}
}
pub(crate) fn two(args: &[String]) -> Option<(&str, bool)> {
match args {
[a, b, ..] => Some((a.as_str(), b == "1")),
_ => None,
}
}