Skip to main content

memscope_rs/analysis/generic/
utils.rs

1use 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}