libperl_macrogen/
c_fn_decl.rs1use std::collections::HashMap;
7
8use crate::intern::InternedStr;
9
10#[derive(Debug, Clone)]
12pub struct CParam {
13 pub name: Option<InternedStr>,
15 pub ty: String,
17}
18
19#[derive(Debug, Clone)]
21pub struct CFnDecl {
22 pub name: InternedStr,
24 pub params: Vec<CParam>,
26 pub ret_ty: String,
28 pub is_thx: bool,
30 pub is_target: bool,
32 pub location: Option<String>,
34}
35
36#[derive(Debug, Default)]
38pub struct CFnDeclDict {
39 pub fns: HashMap<InternedStr, CFnDecl>,
41}
42
43impl CFnDeclDict {
44 pub fn new() -> Self {
46 Self::default()
47 }
48
49 pub fn insert(&mut self, decl: CFnDecl) {
51 self.fns.insert(decl.name, decl);
52 }
53
54 pub fn contains(&self, name: InternedStr) -> bool {
56 self.fns.contains_key(&name)
57 }
58
59 pub fn get(&self, name: InternedStr) -> Option<&CFnDecl> {
61 self.fns.get(&name)
62 }
63
64 pub fn is_thx_dependent(&self, name: InternedStr) -> bool {
66 self.fns.get(&name).is_some_and(|d| d.is_thx)
67 }
68
69 pub fn thx_count(&self) -> usize {
71 self.fns.values().filter(|d| d.is_thx).count()
72 }
73
74 pub fn len(&self) -> usize {
76 self.fns.len()
77 }
78
79 pub fn is_empty(&self) -> bool {
81 self.fns.is_empty()
82 }
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 use crate::intern::StringInterner;
89
90 #[test]
91 fn test_c_fn_decl_dict_basic() {
92 let mut interner = StringInterner::new();
93 let mut dict = CFnDeclDict::new();
94
95 let name = interner.intern("Perl_foo");
96 let decl = CFnDecl {
97 name,
98 params: vec![
99 CParam { name: None, ty: "PerlInterpreter *".to_string() },
100 CParam { name: Some(interner.intern("x")), ty: "int".to_string() },
101 ],
102 ret_ty: "void".to_string(),
103 is_thx: true,
104 is_target: true,
105 location: Some("proto.h:123".to_string()),
106 };
107
108 dict.insert(decl);
109
110 assert!(dict.contains(name));
111 assert!(dict.is_thx_dependent(name));
112 assert_eq!(dict.len(), 1);
113 assert_eq!(dict.thx_count(), 1);
114
115 let retrieved = dict.get(name).unwrap();
116 assert_eq!(retrieved.params.len(), 2);
117 assert_eq!(retrieved.ret_ty, "void");
118 }
119
120 #[test]
121 fn test_c_fn_decl_dict_non_thx() {
122 let mut interner = StringInterner::new();
123 let mut dict = CFnDeclDict::new();
124
125 let name = interner.intern("strlen");
126 let decl = CFnDecl {
127 name,
128 params: vec![
129 CParam { name: Some(interner.intern("s")), ty: "const char *".to_string() },
130 ],
131 ret_ty: "size_t".to_string(),
132 is_thx: false,
133 is_target: false,
134 location: Some("string.h:100".to_string()),
135 };
136
137 dict.insert(decl);
138
139 assert!(dict.contains(name));
140 assert!(!dict.is_thx_dependent(name));
141 assert_eq!(dict.thx_count(), 0);
142 }
143}