memscope_rs/analysis/generic/
utils.rs1use super::types::{ConstraintType, GenericConstraint};
2
3pub fn extract_constraints(type_name: &str) -> Vec<GenericConstraint> {
4 let mut constraints = Vec::new();
5
6 if is_collection_type(type_name) {
7 constraints.push(GenericConstraint {
8 parameter_name: "T".to_string(),
9 constraint_type: ConstraintType::Sized,
10 description: "Type must be Sized for standard collections".to_string(),
11 });
12 }
13
14 if is_smart_pointer_type(type_name) {
15 constraints.push(GenericConstraint {
16 parameter_name: "T".to_string(),
17 constraint_type: ConstraintType::Sized,
18 description: "Type must be Sized for smart pointers".to_string(),
19 });
20 }
21
22 if is_thread_safe_type(type_name) {
23 constraints.push(GenericConstraint {
24 parameter_name: "T".to_string(),
25 constraint_type: ConstraintType::Send,
26 description: "Type must be Send for thread-safe containers".to_string(),
27 });
28 }
29
30 if is_sync_required_type(type_name) {
31 constraints.push(GenericConstraint {
32 parameter_name: "T".to_string(),
33 constraint_type: ConstraintType::Sync,
34 description: "Type must be Sync for shared concurrent access".to_string(),
35 });
36 }
37
38 constraints
39}
40
41fn is_collection_type(type_name: &str) -> bool {
42 let collection_patterns = [
43 r"\bVec<",
44 r"\bVecDeque<",
45 r"\bLinkedList<",
46 r"\bHashMap<",
47 r"\bBTreeMap<",
48 r"\bHashSet<",
49 r"\bBTreeSet<",
50 r"\bBinaryHeap<",
51 ];
52
53 collection_patterns.iter().any(|pattern| {
54 regex::Regex::new(pattern)
55 .map(|re| re.is_match(type_name))
56 .unwrap_or(false)
57 })
58}
59
60fn is_smart_pointer_type(type_name: &str) -> bool {
61 let smart_pointer_patterns = [r"\bBox<", r"\bRc<", r"\bArc<", r"\bWeak<"];
62
63 smart_pointer_patterns.iter().any(|pattern| {
64 regex::Regex::new(pattern)
65 .map(|re| re.is_match(type_name))
66 .unwrap_or(false)
67 })
68}
69
70fn is_thread_safe_type(type_name: &str) -> bool {
71 let thread_safe_patterns = [
72 r"\bMutex<",
73 r"\bRwLock<",
74 r"\bmpsc::",
75 r"\bSender<",
76 r"\bReceiver<",
77 ];
78
79 thread_safe_patterns.iter().any(|pattern| {
80 regex::Regex::new(pattern)
81 .map(|re| re.is_match(type_name))
82 .unwrap_or(false)
83 })
84}
85
86fn is_sync_required_type(type_name: &str) -> bool {
87 let sync_required_patterns = [r"\bArc<", r"&\s*Mutex<", r"&\s*RwLock<"];
88
89 sync_required_patterns.iter().any(|pattern| {
90 regex::Regex::new(pattern)
91 .map(|re| re.is_match(type_name))
92 .unwrap_or(false)
93 })
94}
95
96pub fn parse_generic_parameters(type_name: &str) -> (String, Vec<String>) {
97 if let Some(start) = type_name.find('<') {
98 if let Some(end) = type_name.rfind('>') {
99 let base_type = type_name[..start].to_string();
100 let params_str = &type_name[start + 1..end];
101
102 let params: Vec<String> = params_str
103 .split(',')
104 .map(|s| s.trim().to_string())
105 .filter(|s| !s.is_empty())
106 .collect();
107
108 return (base_type, params);
109 }
110 }
111
112 (type_name.to_string(), Vec::new())
113}