use std::collections::HashMap;
use crate::intern::InternedStr;
#[derive(Debug, Clone)]
pub struct CParam {
pub name: Option<InternedStr>,
pub ty: String,
}
#[derive(Debug, Clone)]
pub struct CFnDecl {
pub name: InternedStr,
pub params: Vec<CParam>,
pub ret_ty: String,
pub is_thx: bool,
pub is_target: bool,
pub location: Option<String>,
}
#[derive(Debug, Default)]
pub struct CFnDeclDict {
pub fns: HashMap<InternedStr, CFnDecl>,
}
impl CFnDeclDict {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, decl: CFnDecl) {
self.fns.insert(decl.name, decl);
}
pub fn contains(&self, name: InternedStr) -> bool {
self.fns.contains_key(&name)
}
pub fn get(&self, name: InternedStr) -> Option<&CFnDecl> {
self.fns.get(&name)
}
pub fn is_thx_dependent(&self, name: InternedStr) -> bool {
self.fns.get(&name).is_some_and(|d| d.is_thx)
}
pub fn thx_count(&self) -> usize {
self.fns.values().filter(|d| d.is_thx).count()
}
pub fn len(&self) -> usize {
self.fns.len()
}
pub fn is_empty(&self) -> bool {
self.fns.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::intern::StringInterner;
#[test]
fn test_c_fn_decl_dict_basic() {
let mut interner = StringInterner::new();
let mut dict = CFnDeclDict::new();
let name = interner.intern("Perl_foo");
let decl = CFnDecl {
name,
params: vec![
CParam { name: None, ty: "PerlInterpreter *".to_string() },
CParam { name: Some(interner.intern("x")), ty: "int".to_string() },
],
ret_ty: "void".to_string(),
is_thx: true,
is_target: true,
location: Some("proto.h:123".to_string()),
};
dict.insert(decl);
assert!(dict.contains(name));
assert!(dict.is_thx_dependent(name));
assert_eq!(dict.len(), 1);
assert_eq!(dict.thx_count(), 1);
let retrieved = dict.get(name).unwrap();
assert_eq!(retrieved.params.len(), 2);
assert_eq!(retrieved.ret_ty, "void");
}
#[test]
fn test_c_fn_decl_dict_non_thx() {
let mut interner = StringInterner::new();
let mut dict = CFnDeclDict::new();
let name = interner.intern("strlen");
let decl = CFnDecl {
name,
params: vec![
CParam { name: Some(interner.intern("s")), ty: "const char *".to_string() },
],
ret_ty: "size_t".to_string(),
is_thx: false,
is_target: false,
location: Some("string.h:100".to_string()),
};
dict.insert(decl);
assert!(dict.contains(name));
assert!(!dict.is_thx_dependent(name));
assert_eq!(dict.thx_count(), 0);
}
}