mock_gen 0.1.22

Interface and mock generator for C++ classes
use std::fs::OpenOptions;
use std::io::prelude::*;
use std::io::{BufRead, BufReader, Write};

use crate::prelude::*;
use crate::utils::parse_func::*;

static FORMAT_OFF: &str = "// clang-format off";
static FORMAT_ON: &str = "// clang-format on";
static GEN_STRING_START: &str = "/* generated interface code */";
static GEN_STRING_END: &str = "/* generated interface code end */";

pub fn remove_generated(lines: &mut Vec<String>) -> Result<&mut Vec<String>> {
    for i in 0..lines.len() {
        if lines[i].contains(&GEN_STRING_START) {
            //remove lines
            let mut max_count = lines.len() - i;
            lines.remove(i);
            loop {
                if lines[i].contains(&GEN_STRING_END) {
                    lines.remove(i);
                    lines.remove(i);
                    break;
                }
                max_count -= 1;
                if (max_count <= 0) {
                    break;
                }
                lines.remove(i);
            }
            break;
        }
    }
    Ok(lines)
}

pub fn replace_line(funcs: Vec<String>, file: &str, class_name: &str) -> Result<()> {
    let mut objects: Vec<&str> = class_name.split("_").collect();
    objects.pop();
    objects.push("interface");

    let interface_name = objects.join("_");
    let mut lines = BufReader::new(OpenOptions::new().read(true).open(file).unwrap())
        .lines()
        .map(|line| line.unwrap())
        .collect::<Vec<String>>();

    //remove previous generated code
    let mut lines = remove_generated(&mut lines)?;
    let class_string = "class ".to_owned() + class_name;
    let mut offset = 4;
    for i in 0..lines.len() {
        if lines[i].contains(&class_string) {
            lines.remove(i);
            lines.insert(
                i,
                "class ".to_owned() + class_name + " : " + "public " + interface_name.as_str(),
            );
            lines.insert(i, "  public:".to_owned());
            lines.insert(i, "{".to_owned());
            lines.insert(i, "class ".to_owned() + interface_name.as_str());
            lines.insert(i, GEN_STRING_START.to_owned());
            for item in funcs.iter() {
                let virtual_func = String::from("\tvirtual ") + &item + " = 0;";
                lines.insert(i + offset, virtual_func);
                offset += 1;
            }
            lines.insert(i + offset, "};".to_owned());
            lines.insert(i + offset + 1, GEN_STRING_END.to_owned());
            lines.insert(i + offset + 2, "".to_owned());

            break;
        }
    }
    let mut file = OpenOptions::new()
        .write(true)
        .truncate(true)
        .open(file)
        .unwrap();
    for line in lines {
        writeln!(file, "{}", line).unwrap();
    }
    Ok(())
}