use crate::{container::Container, detect::DetectionMatches};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GcMode {
Refc,
ArcOrc,
Unknown,
}
pub fn gc_mode(matches: DetectionMatches) -> GcMode {
let has_v2 = matches.contains(DetectionMatches::NTIV2_SYMBOL);
let has_legacy = matches.contains(DetectionMatches::NTI_LEGACY_SYMBOL);
match (has_v2, has_legacy) {
(true, _) => GcMode::ArcOrc,
(false, true) => GcMode::Refc,
_ => GcMode::Unknown,
}
}
pub fn nim_main_prefix<'a>(container: &'a Container<'a>) -> Option<&'a str> {
for sym in container.symbols() {
let name = sym.name.as_ref();
let stripped = name.strip_prefix('_').unwrap_or(name);
if stripped == "NimMain" {
return Some("");
}
if stripped.ends_with("NimMain")
&& !stripped.contains("__")
&& stripped.len() > "NimMain".len()
{
let prefix = &stripped[..stripped.len() - "NimMain".len()];
if prefix
.bytes()
.all(|b| b.is_ascii_alphanumeric() || b == b'_')
{
return Some(prefix);
}
}
}
None
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn gc_mode_from_flags() {
assert_eq!(gc_mode(DetectionMatches::NTIV2_SYMBOL), GcMode::ArcOrc);
assert_eq!(gc_mode(DetectionMatches::NTI_LEGACY_SYMBOL), GcMode::Refc);
assert_eq!(gc_mode(DetectionMatches::EMPTY), GcMode::Unknown);
assert_eq!(
gc_mode(DetectionMatches::NTIV2_SYMBOL | DetectionMatches::NTI_LEGACY_SYMBOL),
GcMode::ArcOrc
);
}
}