memscope-rs 0.2.0

A memory tracking library for Rust applications.
Documentation
use super::types::{ConstraintType, GenericConstraint};

pub fn extract_constraints(type_name: &str) -> Vec<GenericConstraint> {
    let mut constraints = Vec::new();

    if is_collection_type(type_name) {
        constraints.push(GenericConstraint {
            parameter_name: "T".to_string(),
            constraint_type: ConstraintType::Sized,
            description: "Type must be Sized for standard collections".to_string(),
        });
    }

    if is_smart_pointer_type(type_name) {
        constraints.push(GenericConstraint {
            parameter_name: "T".to_string(),
            constraint_type: ConstraintType::Sized,
            description: "Type must be Sized for smart pointers".to_string(),
        });
    }

    if is_thread_safe_type(type_name) {
        constraints.push(GenericConstraint {
            parameter_name: "T".to_string(),
            constraint_type: ConstraintType::Send,
            description: "Type must be Send for thread-safe containers".to_string(),
        });
    }

    if is_sync_required_type(type_name) {
        constraints.push(GenericConstraint {
            parameter_name: "T".to_string(),
            constraint_type: ConstraintType::Sync,
            description: "Type must be Sync for shared concurrent access".to_string(),
        });
    }

    constraints
}

fn is_collection_type(type_name: &str) -> bool {
    let collection_patterns = [
        r"\bVec<",
        r"\bVecDeque<",
        r"\bLinkedList<",
        r"\bHashMap<",
        r"\bBTreeMap<",
        r"\bHashSet<",
        r"\bBTreeSet<",
        r"\bBinaryHeap<",
    ];

    collection_patterns.iter().any(|pattern| {
        regex::Regex::new(pattern)
            .map(|re| re.is_match(type_name))
            .unwrap_or(false)
    })
}

fn is_smart_pointer_type(type_name: &str) -> bool {
    let smart_pointer_patterns = [r"\bBox<", r"\bRc<", r"\bArc<", r"\bWeak<"];

    smart_pointer_patterns.iter().any(|pattern| {
        regex::Regex::new(pattern)
            .map(|re| re.is_match(type_name))
            .unwrap_or(false)
    })
}

fn is_thread_safe_type(type_name: &str) -> bool {
    let thread_safe_patterns = [
        r"\bMutex<",
        r"\bRwLock<",
        r"\bmpsc::",
        r"\bSender<",
        r"\bReceiver<",
    ];

    thread_safe_patterns.iter().any(|pattern| {
        regex::Regex::new(pattern)
            .map(|re| re.is_match(type_name))
            .unwrap_or(false)
    })
}

fn is_sync_required_type(type_name: &str) -> bool {
    let sync_required_patterns = [r"\bArc<", r"&\s*Mutex<", r"&\s*RwLock<"];

    sync_required_patterns.iter().any(|pattern| {
        regex::Regex::new(pattern)
            .map(|re| re.is_match(type_name))
            .unwrap_or(false)
    })
}

pub fn parse_generic_parameters(type_name: &str) -> (String, Vec<String>) {
    if let Some(start) = type_name.find('<') {
        if let Some(end) = type_name.rfind('>') {
            let base_type = type_name[..start].to_string();
            let params_str = &type_name[start + 1..end];

            let params: Vec<String> = params_str
                .split(',')
                .map(|s| s.trim().to_string())
                .filter(|s| !s.is_empty())
                .collect();

            return (base_type, params);
        }
    }

    (type_name.to_string(), Vec::new())
}