1use std::collections::HashMap;
6use regex::Regex;
7
8#[derive(Debug, Clone, PartialEq)]
9pub enum TypeLifetime {
10 SelfRef,
12 SelfMutRef,
14 Ref(String),
16 MutRef(String),
18 ConstPtr,
20 MutPtr,
22 Owned,
24}
25
26#[derive(Debug, Clone)]
27pub struct MethodLifetime {
28 pub method_name: String,
29 pub is_const: bool,
30 pub param_lifetimes: Vec<TypeLifetime>,
31 pub return_lifetime: TypeLifetime,
32}
33
34#[derive(Debug, Clone)]
35pub struct TypeLifetimeSpec {
36 pub type_name: String,
37 pub methods: HashMap<String, Vec<MethodLifetime>>, pub members: HashMap<String, TypeLifetime>,
39 pub typedefs: HashMap<String, TypeLifetime>, }
41
42pub struct TypeLifetimeRegistry {
44 specs: HashMap<String, TypeLifetimeSpec>,
45}
46
47impl TypeLifetimeRegistry {
48 pub fn new() -> Self {
49 let mut registry = TypeLifetimeRegistry {
50 specs: HashMap::new(),
51 };
52 registry.load_stl_annotations();
53 registry
54 }
55
56 pub fn get_type_spec(&self, type_name: &str) -> Option<&TypeLifetimeSpec> {
57 let base_type = extract_base_type(type_name);
59 self.specs.get(base_type)
60 }
61
62 pub fn add_type_spec(&mut self, spec: TypeLifetimeSpec) {
63 self.specs.insert(spec.type_name.clone(), spec);
64 }
65
66 fn load_stl_annotations(&mut self) {
68 let mut vector_spec = TypeLifetimeSpec {
70 type_name: "std::vector".to_string(),
71 methods: HashMap::new(),
72 members: HashMap::new(),
73 typedefs: HashMap::new(),
74 };
75
76 vector_spec.methods.insert("at".to_string(), vec![
78 MethodLifetime {
79 method_name: "at".to_string(),
80 is_const: false,
81 param_lifetimes: vec![TypeLifetime::Owned], return_lifetime: TypeLifetime::SelfMutRef,
83 },
84 MethodLifetime {
85 method_name: "at".to_string(),
86 is_const: true,
87 param_lifetimes: vec![TypeLifetime::Owned], return_lifetime: TypeLifetime::SelfRef,
89 },
90 ]);
91
92 vector_spec.methods.insert("operator[]".to_string(), vec![
93 MethodLifetime {
94 method_name: "operator[]".to_string(),
95 is_const: false,
96 param_lifetimes: vec![TypeLifetime::Owned], return_lifetime: TypeLifetime::SelfMutRef,
98 },
99 MethodLifetime {
100 method_name: "operator[]".to_string(),
101 is_const: true,
102 param_lifetimes: vec![TypeLifetime::Owned], return_lifetime: TypeLifetime::SelfRef,
104 },
105 ]);
106
107 vector_spec.methods.insert("push_back".to_string(), vec![
108 MethodLifetime {
109 method_name: "push_back".to_string(),
110 is_const: false,
111 param_lifetimes: vec![TypeLifetime::Owned], return_lifetime: TypeLifetime::Owned, },
114 ]);
115
116 vector_spec.methods.insert("data".to_string(), vec![
117 MethodLifetime {
118 method_name: "data".to_string(),
119 is_const: false,
120 param_lifetimes: vec![],
121 return_lifetime: TypeLifetime::MutPtr,
122 },
123 MethodLifetime {
124 method_name: "data".to_string(),
125 is_const: true,
126 param_lifetimes: vec![],
127 return_lifetime: TypeLifetime::ConstPtr,
128 },
129 ]);
130
131 vector_spec.methods.insert("begin".to_string(), vec![
132 MethodLifetime {
133 method_name: "begin".to_string(),
134 is_const: false,
135 param_lifetimes: vec![],
136 return_lifetime: TypeLifetime::SelfMutRef,
137 },
138 MethodLifetime {
139 method_name: "begin".to_string(),
140 is_const: true,
141 param_lifetimes: vec![],
142 return_lifetime: TypeLifetime::SelfRef,
143 },
144 ]);
145
146 vector_spec.typedefs.insert("iterator".to_string(), TypeLifetime::SelfMutRef);
147 vector_spec.typedefs.insert("const_iterator".to_string(), TypeLifetime::SelfRef);
148
149 self.specs.insert("std::vector".to_string(), vector_spec);
150
151 let mut unique_ptr_spec = TypeLifetimeSpec {
153 type_name: "std::unique_ptr".to_string(),
154 methods: HashMap::new(),
155 members: HashMap::new(),
156 typedefs: HashMap::new(),
157 };
158
159 unique_ptr_spec.methods.insert("get".to_string(), vec![
160 MethodLifetime {
161 method_name: "get".to_string(),
162 is_const: false,
163 param_lifetimes: vec![],
164 return_lifetime: TypeLifetime::MutPtr,
165 },
166 MethodLifetime {
167 method_name: "get".to_string(),
168 is_const: true,
169 param_lifetimes: vec![],
170 return_lifetime: TypeLifetime::ConstPtr,
171 },
172 ]);
173
174 unique_ptr_spec.methods.insert("operator*".to_string(), vec![
175 MethodLifetime {
176 method_name: "operator*".to_string(),
177 is_const: false,
178 param_lifetimes: vec![],
179 return_lifetime: TypeLifetime::SelfMutRef,
180 },
181 MethodLifetime {
182 method_name: "operator*".to_string(),
183 is_const: true,
184 param_lifetimes: vec![],
185 return_lifetime: TypeLifetime::SelfRef,
186 },
187 ]);
188
189 unique_ptr_spec.methods.insert("release".to_string(), vec![
190 MethodLifetime {
191 method_name: "release".to_string(),
192 is_const: false,
193 param_lifetimes: vec![],
194 return_lifetime: TypeLifetime::Owned,
195 },
196 ]);
197
198 self.specs.insert("std::unique_ptr".to_string(), unique_ptr_spec);
199
200 let mut map_spec = TypeLifetimeSpec {
202 type_name: "std::map".to_string(),
203 methods: HashMap::new(),
204 members: HashMap::new(),
205 typedefs: HashMap::new(),
206 };
207
208 map_spec.methods.insert("at".to_string(), vec![
209 MethodLifetime {
210 method_name: "at".to_string(),
211 is_const: false,
212 param_lifetimes: vec![TypeLifetime::SelfRef], return_lifetime: TypeLifetime::SelfMutRef,
214 },
215 MethodLifetime {
216 method_name: "at".to_string(),
217 is_const: true,
218 param_lifetimes: vec![TypeLifetime::SelfRef], return_lifetime: TypeLifetime::SelfRef,
220 },
221 ]);
222
223 map_spec.methods.insert("operator[]".to_string(), vec![
224 MethodLifetime {
225 method_name: "operator[]".to_string(),
226 is_const: false,
227 param_lifetimes: vec![TypeLifetime::SelfRef], return_lifetime: TypeLifetime::SelfMutRef,
229 },
230 ]);
231
232 map_spec.methods.insert("find".to_string(), vec![
233 MethodLifetime {
234 method_name: "find".to_string(),
235 is_const: false,
236 param_lifetimes: vec![TypeLifetime::SelfRef], return_lifetime: TypeLifetime::SelfMutRef,
238 },
239 MethodLifetime {
240 method_name: "find".to_string(),
241 is_const: true,
242 param_lifetimes: vec![TypeLifetime::SelfRef], return_lifetime: TypeLifetime::SelfRef,
244 },
245 ]);
246
247 self.specs.insert("std::map".to_string(), map_spec);
248
249 }
251}
252
253pub fn parse_type_lifetime_annotation(comment: &str) -> Option<TypeLifetimeSpec> {
255 let type_re = Regex::new(r"@type_lifetime:\s*([^{]+)\s*\{([^}]+)\}").ok()?;
256
257 if let Some(captures) = type_re.captures(comment) {
258 let type_name = captures.get(1)?.as_str().trim();
259 let body = captures.get(2)?.as_str();
260
261 let mut spec = TypeLifetimeSpec {
262 type_name: type_name.to_string(),
263 methods: HashMap::new(),
264 members: HashMap::new(),
265 typedefs: HashMap::new(),
266 };
267
268 for line in body.lines() {
270 let line = line.trim();
271 if line.is_empty() || line.starts_with("//") {
272 continue;
273 }
274
275 if line.contains("->") {
276 parse_method_lifetime(line, &mut spec);
278 } else if line.contains(":") {
279 parse_member_lifetime(line, &mut spec);
281 }
282 }
283
284 Some(spec)
285 } else {
286 None
287 }
288}
289
290fn parse_method_lifetime(line: &str, spec: &mut TypeLifetimeSpec) {
291 let method_re = Regex::new(r"(\w+)\((.*?)\)(\s+const)?\s*->\s*(.+)").unwrap();
293
294 if let Some(captures) = method_re.captures(line) {
295 let method_name = captures.get(1).map(|m| m.as_str()).unwrap_or("");
296 let params = captures.get(2).map(|m| m.as_str()).unwrap_or("");
297 let is_const = captures.get(3).is_some();
298 let return_type = captures.get(4).map(|m| m.as_str()).unwrap_or("");
299
300 let method_lifetime = MethodLifetime {
301 method_name: method_name.to_string(),
302 is_const,
303 param_lifetimes: parse_param_types(params),
304 return_lifetime: parse_type_lifetime(return_type),
305 };
306
307 spec.methods.entry(method_name.to_string())
308 .or_insert_with(Vec::new)
309 .push(method_lifetime);
310 }
311}
312
313fn parse_member_lifetime(line: &str, spec: &mut TypeLifetimeSpec) {
314 if let Some(colon_pos) = line.find(':') {
316 let name = line[..colon_pos].trim();
317 let lifetime = line[colon_pos + 1..].trim();
318
319 if name == "iterator" || name == "const_iterator" ||
321 name == "reference" || name == "const_reference" ||
322 name == "pointer" || name == "const_pointer" {
323 spec.typedefs.insert(name.to_string(), parse_type_lifetime(lifetime));
324 } else {
325 spec.members.insert(name.to_string(), parse_type_lifetime(lifetime));
326 }
327 }
328}
329
330fn parse_param_types(params: &str) -> Vec<TypeLifetime> {
331 if params.is_empty() {
332 return vec![];
333 }
334
335 params.split(',')
336 .map(|p| parse_type_lifetime(p.trim()))
337 .collect()
338}
339
340fn parse_type_lifetime(s: &str) -> TypeLifetime {
341 let s = s.trim();
342
343 match s {
344 "&'self" => TypeLifetime::SelfRef,
345 "&'self mut" => TypeLifetime::SelfMutRef,
346 "*const" => TypeLifetime::ConstPtr,
347 "*mut" => TypeLifetime::MutPtr,
348 "owned" => TypeLifetime::Owned,
349 _ => {
350 if s.starts_with("&'") && s.contains("mut") {
351 if let Some(name) = extract_lifetime_name(s) {
353 TypeLifetime::MutRef(name)
354 } else {
355 TypeLifetime::Owned
356 }
357 } else if s.starts_with("&'") {
358 if let Some(name) = extract_lifetime_name(s) {
359 TypeLifetime::Ref(name)
360 } else {
361 TypeLifetime::Owned
362 }
363 } else {
364 TypeLifetime::Owned
365 }
366 }
367 }
368}
369
370fn extract_lifetime_name(s: &str) -> Option<String> {
371 let re = Regex::new(r"'([a-z][a-z0-9]*)").ok()?;
372 re.captures(s)
373 .and_then(|cap| cap.get(1))
374 .map(|m| m.as_str().to_string())
375}
376
377fn extract_base_type(type_name: &str) -> &str {
378 if let Some(angle_pos) = type_name.find('<') {
381 &type_name[..angle_pos]
382 } else {
383 type_name
384 }
385}
386
387#[cfg(test)]
388mod tests {
389 use super::*;
390
391 #[test]
392 fn test_parse_type_lifetime() {
393 let comment = r#"
394 @type_lifetime: std::vector<T> {
395 at(size_t) -> &'self mut
396 at(size_t) const -> &'self
397 data() -> *mut
398 iterator: &'self mut
399 }
400 "#;
401
402 let spec = parse_type_lifetime_annotation(comment).unwrap();
403 assert_eq!(spec.type_name, "std::vector<T>");
404 assert_eq!(spec.methods["at"].len(), 2);
405 assert_eq!(spec.typedefs["iterator"], TypeLifetime::SelfMutRef);
406 }
407
408 #[test]
409 fn test_registry() {
410 let registry = TypeLifetimeRegistry::new();
411 let vector_spec = registry.get_type_spec("std::vector<int>").unwrap();
412 assert_eq!(vector_spec.type_name, "std::vector");
413 }
414}