oxihuman-core 0.1.2

Core data structures, algorithms, and asset management for OxiHuman
Documentation
#![allow(dead_code)]

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct Command {
    name: String,
    executed: bool,
}

#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct CommandInvoker {
    history: Vec<Command>,
    undo_stack: Vec<Command>,
    redo_stack: Vec<Command>,
}

#[allow(dead_code)]
pub fn new_command_invoker() -> CommandInvoker {
    CommandInvoker {
        history: Vec::new(),
        undo_stack: Vec::new(),
        redo_stack: Vec::new(),
    }
}

#[allow(dead_code)]
pub fn execute_command(inv: &mut CommandInvoker, name: &str) {
    let cmd = Command {
        name: name.to_string(),
        executed: true,
    };
    inv.undo_stack.push(cmd.clone());
    inv.history.push(cmd);
    inv.redo_stack.clear();
}

#[allow(dead_code)]
pub fn undo_command(inv: &mut CommandInvoker) -> bool {
    if let Some(mut cmd) = inv.undo_stack.pop() {
        cmd.executed = false;
        inv.redo_stack.push(cmd);
        true
    } else {
        false
    }
}

#[allow(dead_code)]
pub fn redo_command(inv: &mut CommandInvoker) -> bool {
    if let Some(mut cmd) = inv.redo_stack.pop() {
        cmd.executed = true;
        inv.undo_stack.push(cmd);
        true
    } else {
        false
    }
}

#[allow(dead_code)]
pub fn command_count(inv: &CommandInvoker) -> usize {
    inv.history.len()
}

#[allow(dead_code)]
pub fn can_undo_cmd(inv: &CommandInvoker) -> bool {
    !inv.undo_stack.is_empty()
}

#[allow(dead_code)]
pub fn can_redo_cmd(inv: &CommandInvoker) -> bool {
    !inv.redo_stack.is_empty()
}

#[allow(dead_code)]
pub fn invoker_clear(inv: &mut CommandInvoker) {
    inv.history.clear();
    inv.undo_stack.clear();
    inv.redo_stack.clear();
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_new_invoker() {
        let inv = new_command_invoker();
        assert_eq!(command_count(&inv), 0);
    }

    #[test]
    fn test_execute() {
        let mut inv = new_command_invoker();
        execute_command(&mut inv, "move");
        assert_eq!(command_count(&inv), 1);
    }

    #[test]
    fn test_undo() {
        let mut inv = new_command_invoker();
        execute_command(&mut inv, "scale");
        assert!(undo_command(&mut inv));
        assert!(!can_undo_cmd(&inv));
    }

    #[test]
    fn test_redo() {
        let mut inv = new_command_invoker();
        execute_command(&mut inv, "rotate");
        undo_command(&mut inv);
        assert!(redo_command(&mut inv));
    }

    #[test]
    fn test_undo_empty() {
        let mut inv = new_command_invoker();
        assert!(!undo_command(&mut inv));
    }

    #[test]
    fn test_redo_empty() {
        let mut inv = new_command_invoker();
        assert!(!redo_command(&mut inv));
    }

    #[test]
    fn test_can_undo() {
        let mut inv = new_command_invoker();
        assert!(!can_undo_cmd(&inv));
        execute_command(&mut inv, "delete");
        assert!(can_undo_cmd(&inv));
    }

    #[test]
    fn test_can_redo() {
        let mut inv = new_command_invoker();
        execute_command(&mut inv, "insert");
        assert!(!can_redo_cmd(&inv));
        undo_command(&mut inv);
        assert!(can_redo_cmd(&inv));
    }

    #[test]
    fn test_clear() {
        let mut inv = new_command_invoker();
        execute_command(&mut inv, "a");
        execute_command(&mut inv, "b");
        invoker_clear(&mut inv);
        assert_eq!(command_count(&inv), 0);
        assert!(!can_undo_cmd(&inv));
    }

    #[test]
    fn test_execute_clears_redo() {
        let mut inv = new_command_invoker();
        execute_command(&mut inv, "x");
        undo_command(&mut inv);
        execute_command(&mut inv, "y");
        assert!(!can_redo_cmd(&inv));
    }
}