rhasm 0.1.1

A Rust implementation of the hasm assembler
Documentation
use std::collections::HashMap;
use crate::Instruction;

pub fn encode_instruction(
    instruction: &Instruction,
    symbol_table: &mut HashMap<String, u16>,
    cur_ram: &mut u16
) -> String {
    let mut encoded_instruction: Vec<char> = vec![];
    match instruction {
        Instruction::AInstruction(addr) => {
            encoded_instruction.push('0');
            let parsed_addr = 
            if addr.chars().all(|char| char.is_digit(10)) {
                let is_num = addr.parse::<u16>();
                if let Ok(num) = is_num {
                    num
                } else {
                    panic!("Invalid A-Instruction address or label: {}", addr);
                }
            } else {
                *symbol_table.entry(addr.to_string()).or_insert_with(|| {
                    *cur_ram += 1;
                    *cur_ram - 1
                })
            };
            let binary_addr = format!("{:015b}", parsed_addr);
            encoded_instruction.extend(binary_addr.chars());
        }
        Instruction::CInstruction(dest_str, comp_str, jump_string) => {
            encoded_instruction.extend("111".chars());
            encoded_instruction.extend(get_comp_code(comp_str).chars());
            encoded_instruction.extend(get_dest_code(dest_str).chars());
            encoded_instruction.extend(get_jump_code(jump_string).chars());
        }
    }
    return encoded_instruction.iter().collect();
}

fn get_dest_code(mnemonic: &str) -> String {
    let mut dest: [u8; 3] = [0; 3];
    if mnemonic.contains("A") {
        dest[0] = 1;
    }
    if mnemonic.contains("D") {
        dest[1] = 1;
    }
    if mnemonic.contains("M") {
        dest[2] = 1;
    }
    dest.iter()
        .map(|x| format!("{}", x))
        .collect()
}

fn get_jump_code(mnemonic: &str) -> String {
    let out = match mnemonic {
        "JGT" => "001",
        "JEQ" => "010",
        "JGE" => "011",
        "JLT" => "100",
        "JNE" => "101",
        "JLE" => "110",
        "JMP" => "111",
        "" => "000",
        _ => {
            panic!("Invalid Jump Mnemonic: {}", mnemonic);
        }
    };
    out.to_string()
}

fn get_comp_code(mnemonic: &str) -> String {
    let out = match mnemonic {
        "0" => "0101010",
        "1" => "0111111",
        "-1" => "0111010",
        "D" => "0001100",
        "A" => "0110000",
        "!D" => "0001101",
        "!A" => "0110001",
        "-D" => "0001111",
        "-A" => "0110011",
        "D+1" => "0011111",
        "A+1" => "0110111",
        "D-1" => "0001110",
        "A-1" => "0110010",
        "D+A" => "0000010",
        "D-A" => "0010011",
        "A-D" => "0000111",
        "D&A" => "0000000",
        "D|A" => "0010101",
        "M" => "1110000",
        "!M" => "1110001",
        "-M" => "1110011",
        "M+1" => "1110111",
        "M-1" => "1110010",
        "D+M" => "1000010",
        "D-M" => "1010011",
        "M-D" => "1000111",
        "D&M" => "1000000",
        "D|M" => "1010101",
        _ => {
            panic!("Invalid Computation Mnemonic: {}", mnemonic);
        }
    };
    out.to_string()
}