mock_gen 0.1.22

Interface and mock generator for C++ classes
//! module for parsing out the functions
#![crate_name = "doc"]

use regex::Regex;
use std::fs::{File, OpenOptions};
use std::io::prelude::*;
use std::io::{BufRead, BufReader};

use crate::prelude::*;

pub fn find_class_substring(filename: &str, class_name: &str) -> Result<String> {
    let mut owned_string = "".to_owned();
    let mut lines = BufReader::new(OpenOptions::new().read(true).open(filename).unwrap())
        .lines()
        .map(|line| line.unwrap())
        .collect::<Vec<String>>();
    let mut bracket_count = 0;
    let mut offset = 0;
    let class_string = "class ".to_owned() + class_name;

    for i in 0..lines.len() {
        if lines[i].contains(&class_string) {
            if lines[i].contains("{") {
                bracket_count += 1;
            }
            loop {
                offset += 1;
                owned_string = owned_string + &lines[i + offset];
                if lines[i + offset].contains("{") {
                    bracket_count += 1
                }
                if lines[i + offset].contains("}") {
                    bracket_count -= 1
                }
                if bracket_count == 0 {
                    break;
                }
            }
            break;
        }
    }
    Ok(owned_string)
}

pub fn filter_incorrects(name: &str) -> Result<bool> {
    let re = Regex::new(r"\w+\(\s+?\w+?\s+?\)").unwrap();
    match re.captures(name) {
        Some(x) => Ok(false),
        _ => Ok(true),
    }
}

pub fn find_function_names(class_string: &str) -> Result<Vec<String>> {
    // Create a regular expression to match function declarations
    let re = Regex::new(r"(?:static|const|constexpr)?\s*?\w+(?:\s+|\s*\*\*?\s*|\s+\*\*?\s*|\s*\*\*?|\s+\&?\s*|\s*\&?\s+)(?:const\s*
        (?:\s+|\s+\*\*?\s*|\s*\*\*?|\s+\&?\s*|\s*\&?\s+))?\w+((\n)*)\(([^.{}:=;]*)\)\s?(?:const)?(?:;|\n|\s)").unwrap();

    // Iterate over each match and add the function name to the result vector
    let mut result = Vec::new();
    for cap in re.captures_iter(&class_string) {
        let function_name = cap.get(0).unwrap().as_str().to_string();
        if filter_incorrects(&function_name).unwrap() {
            let func_n = remove_whitespace(&function_name);
            if func_n.contains("static ") {
                continue;
            }
            let func_n_trim = &func_n[0..func_n.find(";").unwrap_or(func_n.len())];
            result.push(func_n_trim.to_owned());
        }
    }
    Ok(result)
}

pub fn find_c_function_names(filename: &str) -> Result<Vec<String>> {
    // Create a regular expression to match function declarations

    let re = Regex::new(r"\w+(\s*?(\*\*?|\&)?\s*?)\w+((\n)*)\(([^.{}:\-=;]*)(?:;|\n)").unwrap();
    let mut lines = BufReader::new(OpenOptions::new().read(true).open(filename).unwrap())
        .lines()
        .map(|line| line.unwrap())
        .collect::<Vec<String>>();

    let mut edited_lines = Vec::new();
    for line in lines.iter() {
        if line.contains("//") {
            let split_line: Vec<&str> = line.split("//").collect();
            let edit = split_line[0].trim().to_owned();
            edited_lines.push(edit);
        } else if line.contains("/*") {
            let split_line: Vec<&str> = line.split("/*").collect();
            let edit = split_line[0].trim().to_owned();
            edited_lines.push(edit);
        } else {
            let edit = line.to_owned();
            edited_lines.push(edit);
        }
    }
    let mut file_string: String = edited_lines.join("\n");
    // Iterate over each match and add the function name to the result vector
    let mut result = Vec::new();
    for cap in re.captures_iter(&file_string) {
        let function_name = cap.get(0).unwrap().as_str().to_string();
        let function_name_trimmed = remove_whitespace(&function_name);
        if function_name_trimmed.contains("return")
            || function_name_trimmed.contains("PACKED")
            || function_name_trimmed.contains("#define")
        {
            continue;
        }
        result.push(function_name_trimmed);
    }
    Ok(result)
}

fn remove_whitespace(s: &str) -> String {
    let words: Vec<_> = s.split_whitespace().collect();
    words.join(" ")
}