<commit_before>//! CLI arguments and library Args struct
//!
//! Use `ArgsBuilder` preferentially as that will shield you from breaking changes resulting from
//! added fields and some field type changes.
//!
//! # Examples
//!
//! ```
//! # use watchexec::cli::ArgsBuilder;
//! ArgsBuilder::default()
//!     .cmd(vec!["echo hello world".into()])
//!     .paths(vec![".".into()])
//!     .build()
//!     .expect("mission failed");
//! ```

use crate::error;
use clap::{App, Arg, Error};
use std::{
    ffi::OsString,
    path::{PathBuf, MAIN_SEPARATOR},
    process::Command,
};

/// Arguments to the watcher
#[derive(Builder, Clone, Debug)]
#[builder(setter(into, strip_option))]
#[builder(build_fn(validate = "Self::validate"))]
pub struct Args {
    /// Command to execute in popen3 format (first program, rest arguments).
    pub cmd: Vec<String>,
    /// List of paths to watch for changes.
    pub paths: Vec<PathBuf>,
    /// Positive filters (trigger only on matching changes). Glob format.
    #[builder(default)]
    pub filters: Vec<String>,
    /// Negative filters (do not trigger on matching changes). Glob format.
    #[builder(default)]
    pub ignores: Vec<String>,
    /// Clear the screen before each run.
    #[builder(default)]
    pub clear_screen: bool,
    /// If Some, send that signal (e.g. SIGHUP) to the child on change.
    #[builder(default)]
    pub signal: Option<String>,
    /// If true, kill the child if it's still running when a change comes in.
    #[builder(default)]
    pub restart: bool,
    /// Interval to debounce the changes. (milliseconds)
    #[builder(default = "500")]
    pub debounce: u64,
    /// Enable debug/verbose logging. No longer used as of 1.14.0 (soft-deprecated).
    ///
    /// Debug messages are printed via debug! so configure your logger appropriately instead.
    #[builder(default)]
    pub debug: bool,
    /// Run the commands right after starting.
    #[builder(default = "true")]
    pub run_initially: bool,
    /// Do not wrap the commands in a shell.
    #[builder(default)]
    pub no_shell: bool,
    /// Ignore metadata changes.
    #[builder(default)]
    pub no_meta: bool,
    /// Do not set WATCHEXEC_*_PATH environment variables for child process.
    #[builder(default)]
    pub no_environment: bool,
    /// Skip auto-loading .gitignore files
    #[builder(default)]
    pub no_vcs_ignore: bool,
    /// Skip auto-loading .ignore files
    #[builder(default)]
    pub no_ignore: bool,
    /// For testing only, always set to false.
    #[builder(setter(skip))]
    #[builder(default)]
    pub once: bool,
    /// Force using the polling backend.
    #[builder(default)]
    pub poll: bool,
    /// Interval for polling. (milliseconds)
    #[builder(default = "2")]
    pub poll_interval: u32,
    #[builder(default)]
    pub watch_when_idle: bool,
}

impl ArgsBuilder {
    fn validate(&self) -> Result<(), String> {
        if self.cmd.as_ref().map_or(true, Vec::is_empty) {
            return Err("cmd must not be empty".into());
        }

        if self.paths.as_ref().map_or(true, Vec::is_empty) {
            return Err("paths must not be empty".into());
        }

        Ok(())
    }
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cmd")
        .arg("/c")
        .arg("tput reset || cls")
        .status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("tput").arg("reset").status();
}

pub fn get_args() -> error::Result<Args> {
    get_args_impl(None::<&[&str]>)
}

pub fn get_args_from<I, T>(from: I) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    get_args_impl(Some(from))
}

fn get_args_impl<I, T>(from: Option<I>) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    let app = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debounce")
                 .help("Set the timeout between detected change and command execution, defaults to 500ms")
                 .takes_value(true)
                 .value_name("milliseconds")
                 .short("d")
                 .long("debounce"))
        .arg(Arg::with_name("verbose")
                 .help("Print debugging messages to stderr")
                 .short("v")
                 .long("verbose"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-ignore")
                 .help("Skip auto-loading of ignore files (.gitignore, .ignore, etc.) for filtering")
                 .long("no-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Force polling mode (interval in milliseconds)")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("no-meta")
                 .help("Ignore metadata changes")
                 .long("no-meta"))
        .arg(Arg::with_name("no-environment")
                 .help("Do not set WATCHEXEC_*_PATH environment variables for child process")
                 .long("no-environment"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .arg(Arg::with_name("watch-when-idle")
                 .help("Ignore events while the process is still running")
                 .short("W")
                 .long("watch-when-idle"));

    let args = match from {
        None => app.get_matches(),
        Some(i) => app.get_matches_from(i),
    };

    let cmd: Vec<String> = values_t!(args.values_of("command"), String)?;
    let paths = values_t!(args.values_of("path"), String)
        .unwrap_or_else(|_| vec![".".into()])
        .iter()
        .map(|string_path| string_path.into())
        .collect();

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or_else(|_| Vec::new());

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',').filter_map(|ext| {
                if ext.is_empty() {
                    None
                } else {
                    Some(format!("*.{}", ext.replace(".", "")))
                }
            }));
        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![
        format!("**{}.DS_Store", MAIN_SEPARATOR),
        String::from("*.py[co]"),
        String::from("#*#"),
        String::from(".#*"),
        String::from(".*.kate-swp"),
        String::from(".*.sw?"),
        String::from(".*.sw?x"),
        format!("**{}.git{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.hg{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.svn{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
    ];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or_else(|_| Vec::new()));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    let debounce = if args.occurrences_of("debounce") > 0 {
        value_t!(args.value_of("debounce"), u64).unwrap_or_else(|e| e.exit())
    } else {
        500
    };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Ok(Args {
        cmd,
        paths,
        filters,
        ignores,
        signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debounce,
        debug: args.is_present("verbose"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_meta: args.is_present("no-meta"),
        no_environment: args.is_present("no-environment"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        no_ignore: args.is_present("no-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval,
        watch_when_idle: args.is_present("watch-when-idle"),
    })
}
<commit_msg>Correct --watch help text as per #165<commit_after>//! CLI arguments and library Args struct
//!
//! Use `ArgsBuilder` preferentially as that will shield you from breaking changes resulting from
//! added fields and some field type changes.
//!
//! # Examples
//!
//! ```
//! # use watchexec::cli::ArgsBuilder;
//! ArgsBuilder::default()
//!     .cmd(vec!["echo hello world".into()])
//!     .paths(vec![".".into()])
//!     .build()
//!     .expect("mission failed");
//! ```

use crate::error;
use clap::{App, Arg, Error};
use std::{
    ffi::OsString,
    path::{PathBuf, MAIN_SEPARATOR},
    process::Command,
};

/// Arguments to the watcher
#[derive(Builder, Clone, Debug)]
#[builder(setter(into, strip_option))]
#[builder(build_fn(validate = "Self::validate"))]
pub struct Args {
    /// Command to execute in popen3 format (first program, rest arguments).
    pub cmd: Vec<String>,
    /// List of paths to watch for changes.
    pub paths: Vec<PathBuf>,
    /// Positive filters (trigger only on matching changes). Glob format.
    #[builder(default)]
    pub filters: Vec<String>,
    /// Negative filters (do not trigger on matching changes). Glob format.
    #[builder(default)]
    pub ignores: Vec<String>,
    /// Clear the screen before each run.
    #[builder(default)]
    pub clear_screen: bool,
    /// If Some, send that signal (e.g. SIGHUP) to the child on change.
    #[builder(default)]
    pub signal: Option<String>,
    /// If true, kill the child if it's still running when a change comes in.
    #[builder(default)]
    pub restart: bool,
    /// Interval to debounce the changes. (milliseconds)
    #[builder(default = "500")]
    pub debounce: u64,
    /// Enable debug/verbose logging. No longer used as of 1.14.0 (soft-deprecated).
    ///
    /// Debug messages are printed via debug! so configure your logger appropriately instead.
    #[builder(default)]
    pub debug: bool,
    /// Run the commands right after starting.
    #[builder(default = "true")]
    pub run_initially: bool,
    /// Do not wrap the commands in a shell.
    #[builder(default)]
    pub no_shell: bool,
    /// Ignore metadata changes.
    #[builder(default)]
    pub no_meta: bool,
    /// Do not set WATCHEXEC_*_PATH environment variables for child process.
    #[builder(default)]
    pub no_environment: bool,
    /// Skip auto-loading .gitignore files
    #[builder(default)]
    pub no_vcs_ignore: bool,
    /// Skip auto-loading .ignore files
    #[builder(default)]
    pub no_ignore: bool,
    /// For testing only, always set to false.
    #[builder(setter(skip))]
    #[builder(default)]
    pub once: bool,
    /// Force using the polling backend.
    #[builder(default)]
    pub poll: bool,
    /// Interval for polling. (milliseconds)
    #[builder(default = "2")]
    pub poll_interval: u32,
    #[builder(default)]
    pub watch_when_idle: bool,
}

impl ArgsBuilder {
    fn validate(&self) -> Result<(), String> {
        if self.cmd.as_ref().map_or(true, Vec::is_empty) {
            return Err("cmd must not be empty".into());
        }

        if self.paths.as_ref().map_or(true, Vec::is_empty) {
            return Err("paths must not be empty".into());
        }

        Ok(())
    }
}

#[cfg(target_family = "windows")]
pub fn clear_screen() {
    let _ = Command::new("cmd")
        .arg("/c")
        .arg("tput reset || cls")
        .status();
}

#[cfg(target_family = "unix")]
pub fn clear_screen() {
    let _ = Command::new("tput").arg("reset").status();
}

pub fn get_args() -> error::Result<Args> {
    get_args_impl(None::<&[&str]>)
}

pub fn get_args_from<I, T>(from: I) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    get_args_impl(Some(from))
}

fn get_args_impl<I, T>(from: Option<I>) -> error::Result<Args>
where
    I: IntoIterator<Item = T>,
    T: Into<OsString> + Clone,
{
    let app = App::new("watchexec")
        .version(crate_version!())
        .about("Execute commands when watched files change")
        .arg(Arg::with_name("command")
                 .help("Command to execute")
                 .multiple(true)
                 .required(true))
        .arg(Arg::with_name("extensions")
                 .help("Comma-separated list of file extensions to watch (js,css,html)")
                 .short("e")
                 .long("exts")
                 .takes_value(true))
        .arg(Arg::with_name("path")
                 .help("Watch a specific file or directory")
                 .short("w")
                 .long("watch")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true))
        .arg(Arg::with_name("clear")
                 .help("Clear screen before executing command")
                 .short("c")
                 .long("clear"))
        .arg(Arg::with_name("restart")
                 .help("Restart the process if it's still running")
                 .short("r")
                 .long("restart"))
        .arg(Arg::with_name("signal")
                 .help("Send signal to process upon changes, e.g. SIGHUP")
                 .short("s")
                 .long("signal")
                 .takes_value(true)
                 .number_of_values(1)
                 .value_name("signal"))
        .arg(Arg::with_name("kill")
                 .help("Send SIGKILL to child processes (deprecated, use -s SIGKILL instead)")
                 .short("k")
                 .long("kill"))
        .arg(Arg::with_name("debounce")
                 .help("Set the timeout between detected change and command execution, defaults to 500ms")
                 .takes_value(true)
                 .value_name("milliseconds")
                 .short("d")
                 .long("debounce"))
        .arg(Arg::with_name("verbose")
                 .help("Print debugging messages to stderr")
                 .short("v")
                 .long("verbose"))
        .arg(Arg::with_name("filter")
                 .help("Ignore all modifications except those matching the pattern")
                 .short("f")
                 .long("filter")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("ignore")
                 .help("Ignore modifications to paths matching the pattern")
                 .short("i")
                 .long("ignore")
                 .number_of_values(1)
                 .multiple(true)
                 .takes_value(true)
                 .value_name("pattern"))
        .arg(Arg::with_name("no-vcs-ignore")
                 .help("Skip auto-loading of .gitignore files for filtering")
                 .long("no-vcs-ignore"))
        .arg(Arg::with_name("no-ignore")
                 .help("Skip auto-loading of ignore files (.gitignore, .ignore, etc.) for filtering")
                 .long("no-ignore"))
        .arg(Arg::with_name("no-default-ignore")
                 .help("Skip auto-ignoring of commonly ignored globs")
                 .long("no-default-ignore"))
        .arg(Arg::with_name("postpone")
                 .help("Wait until first change to execute command")
                 .short("p")
                 .long("postpone"))
        .arg(Arg::with_name("poll")
                 .help("Force polling mode (interval in milliseconds)")
                 .long("force-poll")
                 .value_name("interval"))
        .arg(Arg::with_name("no-shell")
                 .help("Do not wrap command in 'sh -c' resp. 'cmd.exe /C'")
                 .short("n")
                 .long("no-shell"))
        .arg(Arg::with_name("no-meta")
                 .help("Ignore metadata changes")
                 .long("no-meta"))
        .arg(Arg::with_name("no-environment")
                 .help("Do not set WATCHEXEC_*_PATH environment variables for child process")
                 .long("no-environment"))
        .arg(Arg::with_name("once").short("1").hidden(true))
        .arg(Arg::with_name("watch-when-idle")
                 .help("Ignore events while the process is still running")
                 .short("W")
                 .long("watch-when-idle"));

    let args = match from {
        None => app.get_matches(),
        Some(i) => app.get_matches_from(i),
    };

    let cmd: Vec<String> = values_t!(args.values_of("command"), String)?;
    let paths = values_t!(args.values_of("path"), String)
        .unwrap_or_else(|_| vec![".".into()])
        .iter()
        .map(|string_path| string_path.into())
        .collect();

    // Treat --kill as --signal SIGKILL (for compatibility with older syntax)
    let signal = if args.is_present("kill") {
        Some("SIGKILL".to_string())
    } else {
        // Convert Option<&str> to Option<String>
        args.value_of("signal").map(str::to_string)
    };

    let mut filters = values_t!(args.values_of("filter"), String).unwrap_or_else(|_| Vec::new());

    if let Some(extensions) = args.values_of("extensions") {
        for exts in extensions {
            filters.extend(exts.split(',').filter_map(|ext| {
                if ext.is_empty() {
                    None
                } else {
                    Some(format!("*.{}", ext.replace(".", "")))
                }
            }));
        }
    }

    let mut ignores = vec![];
    let default_ignores = vec![
        format!("**{}.DS_Store", MAIN_SEPARATOR),
        String::from("*.py[co]"),
        String::from("#*#"),
        String::from(".#*"),
        String::from(".*.kate-swp"),
        String::from(".*.sw?"),
        String::from(".*.sw?x"),
        format!("**{}.git{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.hg{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
        format!("**{}.svn{}**", MAIN_SEPARATOR, MAIN_SEPARATOR),
    ];

    if args.occurrences_of("no-default-ignore") == 0 {
        ignores.extend(default_ignores)
    };
    ignores.extend(values_t!(args.values_of("ignore"), String).unwrap_or_else(|_| Vec::new()));

    let poll_interval = if args.occurrences_of("poll") > 0 {
        value_t!(args.value_of("poll"), u32).unwrap_or_else(|e| e.exit())
    } else {
        1000
    };

    let debounce = if args.occurrences_of("debounce") > 0 {
        value_t!(args.value_of("debounce"), u64).unwrap_or_else(|e| e.exit())
    } else {
        500
    };

    if signal.is_some() && args.is_present("postpone") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--postpone and --signal are mutually exclusive".to_string())
            .exit();
    }

    if signal.is_some() && args.is_present("kill") {
        // TODO: Error::argument_conflict() might be the better fit, usage was unclear, though
        Error::value_validation_auto("--kill and --signal is ambiguous.\n       Hint: Use only '--signal SIGKILL' without --kill".to_string())
            .exit();
    }

    Ok(Args {
        cmd,
        paths,
        filters,
        ignores,
        signal,
        clear_screen: args.is_present("clear"),
        restart: args.is_present("restart"),
        debounce,
        debug: args.is_present("verbose"),
        run_initially: !args.is_present("postpone"),
        no_shell: args.is_present("no-shell"),
        no_meta: args.is_present("no-meta"),
        no_environment: args.is_present("no-environment"),
        no_vcs_ignore: args.is_present("no-vcs-ignore"),
        no_ignore: args.is_present("no-ignore"),
        once: args.is_present("once"),
        poll: args.occurrences_of("poll") > 0,
        poll_interval,
        watch_when_idle: args.is_present("watch-when-idle"),
    })
}
<|endoftext|>


<commit_before>use std::error::Error;
use util::*;
use instruction::*;
use decoding::*;

pub trait Cpu {
    fn get_register(&self, reg: Register) -> u8;
    fn set_register(&mut self, reg: Register, val: u8);

    fn get_flags_register(&self) -> u8;
    fn set_flags_register(&mut self, flags: u8);

    fn get_program_counter(&self) -> u16;
    fn set_program_counter(&mut self, pc: u16);

    fn get_stack_pointer(&self) -> u16;
    fn set_stack_pointer(&mut self, pc: u16);

    fn tick(&mut self, count: u8);

    fn halt(&mut self);
    fn stop(&mut self);

    fn set_interrupts_enabled(&mut self, enabled: bool);

    fn get_memory(&self, addr: u16) -> Result<u8, Box<Error>>;
    fn set_memory(&mut self, addr: u16, n: u8) -> Result<(), Box<Error>>;

    fn get_memory16(&self, addr: u16) -> Result<u16, Box<Error>> {
        let l = self.get_memory(addr)?;
        let h = self.get_memory(addr + 1)?;
        Ok(make_word16(h, l))
    }

    fn set_memory16(&mut self, addr: u16, nn: u16) -> Result<(), Box<Error>> {
        self.set_memory(addr, low_byte(nn))?;
        self.set_memory(addr + 1, high_byte(nn))?;
        Ok(())
    }

    fn get_af(&self) -> u16 {
        make_word16(self.get_register(ARegister), self.get_flags_register())
    }

    fn get_bc(&self) -> u16 {
        make_word16(self.get_register(BRegister), self.get_register(CRegister))
    }

    fn get_de(&self) -> u16 {
        make_word16(self.get_register(DRegister), self.get_register(ERegister))
    }

    fn get_hl(&self) -> u16 {
        make_word16(self.get_register(HRegister), self.get_register(LRegister))
    }

    fn set_af(&mut self, v: u16) {
        self.set_register(ARegister, high_byte(v));
        self.set_flags_register(low_byte(v));
    }

    fn set_bc(&mut self, v: u16) {
        self.set_register(BRegister, high_byte(v));
        self.set_register(CRegister, low_byte(v));
    }

    fn set_de(&mut self, v: u16) {
        self.set_register(DRegister, high_byte(v));
        self.set_register(ERegister, low_byte(v));
    }

    fn set_hl(&mut self, v: u16) {
        self.set_register(HRegister, high_byte(v));
        self.set_register(LRegister, low_byte(v));
    }

    fn get_atbc(&self) -> Result<u8, Box<Error>> {
        self.get_memory(self.get_bc())
    }

    fn get_atde(&self) -> Result<u8, Box<Error>> {
        self.get_memory(self.get_de())
    }

    fn get_athl(&self) -> Result<u8, Box<Error>> {
        self.get_memory(self.get_hl())
    }

    fn get_atc(&self) -> Result<u8, Box<Error>> {
        let c = self.get_register(CRegister);
        self.get_memory(make_word16(0xff, c))
    }

    fn set_atbc(&mut self, v: u8) -> Result<(), Box<Error>> {
        let bc = self.get_bc();
        self.set_memory(bc, v)
    }

    fn set_atde(&mut self, v: u8) -> Result<(), Box<Error>> {
        let de = self.get_de();
        self.set_memory(de, v)
    }

    fn set_athl(&mut self, v: u8) -> Result<(), Box<Error>> {
        let hl = self.get_hl();
        self.set_memory(hl, v)
    }

    fn set_atc(&mut self, v: u8) -> Result<(), Box<Error>> {
        let c = self.get_register(CRegister);
        self.set_memory(make_word16(0xff, c), v)
    }

    fn step(&mut self) -> Result<(), Box<Error>> {
        let instruction = decode_instruction(|| {
            let pc = self.get_program_counter();
            if pc == u16::max_value() {
                Err("program counter wrapped at max address".into())
            } else {
                self.set_program_counter(pc + 1);
                self.get_memory(pc)
            }
        })?;

        self.do_instruction(instruction)
    }

    fn do_instruction(&mut self, i: Instruction) -> Result<(), Box<Error>> {
        match i {
            LD_R_R(tr, sr) => {
                let sv = self.get_register(sr);
                self.set_register(tr, sv);
                self.tick(4);
            }
            LD_R_N(tr, n) => {
                self.set_register(tr, n);
                self.tick(8);
            }
            LD_R_ATHL(tr) => {
                let v = self.get_athl()?;
                self.set_register(tr, v);
                self.tick(8);
            }
            LD_ATHL_R(sr) => {
                let v = self.get_register(sr);
                self.set_athl(v)?;
                self.tick(8);
            }
            LD_ATHL_N(n) => {
                self.set_athl(n)?;
                self.tick(8);
            }
            LD_A_ATC => {
                let v = self.get_atc()?;
                self.set_register(ARegister, v);
                self.tick(8);
            }
            LD_A_ATBC => {
                let v = self.get_atbc()?;
                self.set_register(ARegister, v);
                self.tick(8);
            }
            LD_A_ATDE => {
                let v = self.get_atde()?;
                self.set_register(ARegister, v);
                self.tick(8);
            }
            LD_A_ATNN(nn) => {
                let v = self.get_memory(nn)?;
                self.set_register(ARegister, v);
                self.tick(16);
            }
            LD_ATC_A => {
                let v = self.get_register(ARegister);
                self.set_atc(v)?;
                self.tick(8);
            }
            LD_ATBC_A => {
                let v = self.get_register(ARegister);
                self.set_atbc(v)?;
                self.tick(8);
            }
            LD_ATDE_A => {
                let v = self.get_register(ARegister);
                self.set_atde(v)?;
                self.tick(8);
            }
            LD_ATNN_A(nn) => {
                let v = self.get_register(ARegister);
                self.set_memory(nn, v)?;
                self.tick(16);
            }
            LDD_A_ATHL => {
                let hl = self.get_hl();
                let v = self.get_memory(hl)?;
                self.set_register(ARegister, v);
                self.set_hl(hl - 1);
                self.tick(8);
            }
            LDD_ATHL_A => {
                let hl = self.get_hl();
                let v = self.get_register(ARegister);
                self.set_memory(hl, v)?;
                self.set_hl(hl - 1);
                self.tick(8);
            }
            LDI_A_ATHL => {
                let hl = self.get_hl();
                let v = self.get_memory(hl)?;
                self.set_register(ARegister, v);
                self.set_hl(hl + 1);
                self.tick(8);
            }
            LDI_ATHL_A => {
                let hl = self.get_hl();
                let v = self.get_register(ARegister);
                self.set_memory(hl, v)?;
                self.set_hl(hl + 1);
                self.tick(8);
            }
            LDH_A_ATN(n) => {
                let v = self.get_memory(make_word16(0xff, n))?;
                self.set_register(ARegister, v);
                self.tick(12);
            }
            LDH_ATN_A(n) => {
                let v = self.get_register(ARegister);
                self.set_memory(make_word16(0xff, n), v)?;
                self.tick(12);
            }
            LD_BC_NN(nn) => {
                self.set_bc(nn);
                self.tick(12);
            }
            LD_DE_NN(nn) => {
                self.set_de(nn);
                self.tick(12);
            }
            LD_HL_NN(nn) => {
                self.set_hl(nn);
                self.tick(12);
            }
            LD_SP_NN(nn) => {
                self.set_stack_pointer(nn);
                self.tick(12);
            }
            LD_SP_HL => {
                let sp = self.get_stack_pointer();
                self.set_hl(sp);
                self.tick(8);
            }
            LDHL_SP_N(n) => {
                let sp = self.get_stack_pointer();
                self.set_hl(((sp as i32) + (n as i32)) as u16);
                self.tick(12);
            }
            LD_ATNN_SP(nn) => {
                let sp = self.get_stack_pointer();
                self.set_memory16(nn, sp)?;
                self.tick(20);
            }
            _ => unimplemented!(),
        }

        Ok(())
    }
}
<commit_msg>pushes and pops<commit_after>use std::error::Error;
use util::*;
use instruction::*;
use decoding::*;

pub trait Cpu {
    fn get_register(&self, reg: Register) -> u8;
    fn set_register(&mut self, reg: Register, val: u8);

    fn get_flags_register(&self) -> u8;
    fn set_flags_register(&mut self, flags: u8);

    fn get_program_counter(&self) -> u16;
    fn set_program_counter(&mut self, pc: u16);

    fn get_stack_pointer(&self) -> u16;
    fn set_stack_pointer(&mut self, pc: u16);

    fn tick(&mut self, count: u8);

    fn halt(&mut self);
    fn stop(&mut self);

    fn set_interrupts_enabled(&mut self, enabled: bool);

    fn get_memory(&self, addr: u16) -> Result<u8, Box<Error>>;
    fn set_memory(&mut self, addr: u16, n: u8) -> Result<(), Box<Error>>;

    fn get_memory16(&self, addr: u16) -> Result<u16, Box<Error>> {
        let l = self.get_memory(addr)?;
        let h = self.get_memory(addr + 1)?;
        Ok(make_word16(h, l))
    }

    fn set_memory16(&mut self, addr: u16, nn: u16) -> Result<(), Box<Error>> {
        self.set_memory(addr, low_byte(nn))?;
        self.set_memory(addr + 1, high_byte(nn))?;
        Ok(())
    }

    fn push_stack16(&mut self, nn: u16) -> Result<(), Box<Error>> {
        let sp = self.get_stack_pointer();
        self.set_memory16(sp - 2, nn)?;
        self.set_stack_pointer(sp - 2);
        Ok(())
    }

    fn pop_stack16(&mut self) -> Result<u16, Box<Error>> {
        let sp = self.get_stack_pointer();
        let nn = self.get_memory16(sp)?;
        self.set_stack_pointer(sp + 2);
        Ok(nn)
    }

    fn get_af(&self) -> u16 {
        make_word16(self.get_register(ARegister), self.get_flags_register())
    }

    fn get_bc(&self) -> u16 {
        make_word16(self.get_register(BRegister), self.get_register(CRegister))
    }

    fn get_de(&self) -> u16 {
        make_word16(self.get_register(DRegister), self.get_register(ERegister))
    }

    fn get_hl(&self) -> u16 {
        make_word16(self.get_register(HRegister), self.get_register(LRegister))
    }

    fn set_af(&mut self, v: u16) {
        self.set_register(ARegister, high_byte(v));
        self.set_flags_register(low_byte(v));
    }

    fn set_bc(&mut self, v: u16) {
        self.set_register(BRegister, high_byte(v));
        self.set_register(CRegister, low_byte(v));
    }

    fn set_de(&mut self, v: u16) {
        self.set_register(DRegister, high_byte(v));
        self.set_register(ERegister, low_byte(v));
    }

    fn set_hl(&mut self, v: u16) {
        self.set_register(HRegister, high_byte(v));
        self.set_register(LRegister, low_byte(v));
    }

    fn get_atbc(&self) -> Result<u8, Box<Error>> {
        self.get_memory(self.get_bc())
    }

    fn get_atde(&self) -> Result<u8, Box<Error>> {
        self.get_memory(self.get_de())
    }

    fn get_athl(&self) -> Result<u8, Box<Error>> {
        self.get_memory(self.get_hl())
    }

    fn get_atc(&self) -> Result<u8, Box<Error>> {
        let c = self.get_register(CRegister);
        self.get_memory(make_word16(0xff, c))
    }

    fn set_atbc(&mut self, v: u8) -> Result<(), Box<Error>> {
        let bc = self.get_bc();
        self.set_memory(bc, v)
    }

    fn set_atde(&mut self, v: u8) -> Result<(), Box<Error>> {
        let de = self.get_de();
        self.set_memory(de, v)
    }

    fn set_athl(&mut self, v: u8) -> Result<(), Box<Error>> {
        let hl = self.get_hl();
        self.set_memory(hl, v)
    }

    fn set_atc(&mut self, v: u8) -> Result<(), Box<Error>> {
        let c = self.get_register(CRegister);
        self.set_memory(make_word16(0xff, c), v)
    }

    fn step(&mut self) -> Result<(), Box<Error>> {
        let instruction = decode_instruction(|| {
            let pc = self.get_program_counter();
            if pc == u16::max_value() {
                Err("program counter wrapped at max address".into())
            } else {
                self.set_program_counter(pc + 1);
                self.get_memory(pc)
            }
        })?;

        self.do_instruction(instruction)
    }

    fn do_instruction(&mut self, i: Instruction) -> Result<(), Box<Error>> {
        match i {
            LD_R_R(tr, sr) => {
                let sv = self.get_register(sr);
                self.set_register(tr, sv);
                self.tick(4);
            }
            LD_R_N(tr, n) => {
                self.set_register(tr, n);
                self.tick(8);
            }
            LD_R_ATHL(tr) => {
                let v = self.get_athl()?;
                self.set_register(tr, v);
                self.tick(8);
            }
            LD_ATHL_R(sr) => {
                let v = self.get_register(sr);
                self.set_athl(v)?;
                self.tick(8);
            }
            LD_ATHL_N(n) => {
                self.set_athl(n)?;
                self.tick(8);
            }
            LD_A_ATC => {
                let v = self.get_atc()?;
                self.set_register(ARegister, v);
                self.tick(8);
            }
            LD_A_ATBC => {
                let v = self.get_atbc()?;
                self.set_register(ARegister, v);
                self.tick(8);
            }
            LD_A_ATDE => {
                let v = self.get_atde()?;
                self.set_register(ARegister, v);
                self.tick(8);
            }
            LD_A_ATNN(nn) => {
                let v = self.get_memory(nn)?;
                self.set_register(ARegister, v);
                self.tick(16);
            }
            LD_ATC_A => {
                let v = self.get_register(ARegister);
                self.set_atc(v)?;
                self.tick(8);
            }
            LD_ATBC_A => {
                let v = self.get_register(ARegister);
                self.set_atbc(v)?;
                self.tick(8);
            }
            LD_ATDE_A => {
                let v = self.get_register(ARegister);
                self.set_atde(v)?;
                self.tick(8);
            }
            LD_ATNN_A(nn) => {
                let v = self.get_register(ARegister);
                self.set_memory(nn, v)?;
                self.tick(16);
            }
            LDD_A_ATHL => {
                let hl = self.get_hl();
                let v = self.get_memory(hl)?;
                self.set_register(ARegister, v);
                self.set_hl(hl - 1);
                self.tick(8);
            }
            LDD_ATHL_A => {
                let hl = self.get_hl();
                let v = self.get_register(ARegister);
                self.set_memory(hl, v)?;
                self.set_hl(hl - 1);
                self.tick(8);
            }
            LDI_A_ATHL => {
                let hl = self.get_hl();
                let v = self.get_memory(hl)?;
                self.set_register(ARegister, v);
                self.set_hl(hl + 1);
                self.tick(8);
            }
            LDI_ATHL_A => {
                let hl = self.get_hl();
                let v = self.get_register(ARegister);
                self.set_memory(hl, v)?;
                self.set_hl(hl + 1);
                self.tick(8);
            }
            LDH_A_ATN(n) => {
                let v = self.get_memory(make_word16(0xff, n))?;
                self.set_register(ARegister, v);
                self.tick(12);
            }
            LDH_ATN_A(n) => {
                let v = self.get_register(ARegister);
                self.set_memory(make_word16(0xff, n), v)?;
                self.tick(12);
            }
            LD_BC_NN(nn) => {
                self.set_bc(nn);
                self.tick(12);
            }
            LD_DE_NN(nn) => {
                self.set_de(nn);
                self.tick(12);
            }
            LD_HL_NN(nn) => {
                self.set_hl(nn);
                self.tick(12);
            }
            LD_SP_NN(nn) => {
                self.set_stack_pointer(nn);
                self.tick(12);
            }
            LD_SP_HL => {
                let sp = self.get_stack_pointer();
                self.set_hl(sp);
                self.tick(8);
            }
            LDHL_SP_N(n) => {
                let sp = self.get_stack_pointer();
                self.set_hl(((sp as i32) + (n as i32)) as u16);
                self.tick(12);
            }
            LD_ATNN_SP(nn) => {
                let sp = self.get_stack_pointer();
                self.set_memory16(nn, sp)?;
                self.tick(20);
            }
            PUSH_AF => {
                let af = self.get_af();
                self.push_stack16(af)?;
                self.tick(16);
            }
            PUSH_BC => {
                let bc = self.get_bc();
                self.push_stack16(bc)?;
                self.tick(16);
            }
            PUSH_DE => {
                let de = self.get_de();
                self.push_stack16(de)?;
                self.tick(16);
            }
            PUSH_HL => {
                let hl = self.get_hl();
                self.push_stack16(hl)?;
                self.tick(16);
            }
            POP_AF => {
                let nn = self.pop_stack16()?;
                self.set_af(nn);
                self.tick(12);
            }
            POP_BC => {
                let nn = self.pop_stack16()?;
                self.set_bc(nn);
                self.tick(12);
            }
            POP_DE => {
                let nn = self.pop_stack16()?;
                self.set_de(nn);
                self.tick(12);
            }
            POP_HL => {
                let nn = self.pop_stack16()?;
                self.set_hl(nn);
                self.tick(12);
            }
            _ => unimplemented!(),
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>use num::integer::Integer;
use memory::Memory;
use memory::low_nibble;
use memory::high_nibble;
use extensions::Incrementor;
use ops::{mod};
use std::num::One;

pub struct Cpu {
    reg: Registers,
    mem: Memory
}

impl Cpu {
    pub fn new(memory: Memory) -> Cpu {
        return Cpu{reg: Registers::new(), mem: memory}
    }

    /// Execute a cycle on the cpu
    pub fn tick(&mut self) {
        let instr = self.fetch_instruction();

        match instr {
            0x00 => ops::nop(),
            0x01 => ops::ld_next_two_byte_into_reg_pair(&self.mem, &mut self.reg.pc, &mut self.reg.b, &mut self.reg.c),
            0x02 => ops::write_value_to_memory_at_address(&mut self.mem, self.reg.a.read(), self.reg.b.read(), self.reg.c.read()),
            0x03 => ops::increment_register_pair(&mut self.reg.b, &mut self.reg.c),
            0x04 => ops::increment_register(&mut self.reg.b, &mut self.reg.f),
            0x05 => ops::decrement_register(&mut self.reg.b, &mut self.reg.f),
            0x06 => ops::ld_immediate(&self.mem, &mut self.reg.pc, &mut self.reg.b),
            0x07 => ops::rotate_left_with_carry(&mut self.reg.a, &mut self.reg.f),
            0x08 => ops::write_sp_to_address_immediate(&mut self.mem, &mut self.reg.pc, &self.reg.sp),
            _ => return
        }
    }

    /// Fetches the instruction pointed to by the program counter
    /// and increments the pc by 1
    fn fetch_instruction(&mut self) -> u8 {
        let instr = self.mem.read_byte(self.reg.pc.val);
        self.reg.pc.increment();
        return instr;
    }
}

struct Registers {
    a: Register<u8>, b: Register<u8>, c: Register<u8>,
    d: Register<u8>, e: Register<u8>, f: Register<Flags>,
    h: Register<u8>, l: Register<u8>, // 8-bit registers

    pc: Register<u16>, sp: Register<u16>, // 16-bit registers
    m: Register<u16>, t: Register<u16> // clock
}

impl Registers {
    fn new() -> Registers {
        return Registers{
            a: Register::new(0),
            b: Register::new(0),
            c: Register::new(0),
            d: Register::new(0),
            e: Register::new(0),
            f: Register::new(Flags::empty()),
            h: Register::new(0),
            l: Register::new(0),

            pc: Register::new(0x100),
            sp: Register::new(0xFFFE),

            m: Register::new(0),
            t: Register::new(0)
        }
    }
}

pub struct Register<T: Copy> {
    val: T
}

impl<T: Copy> Register<T> {
    pub fn new(i: T) -> Register<T> {
        return Register { val: i };
    }

    pub fn read(&self) -> T {
        return self.val;
    }

    pub fn write(&mut self, i: T) {
        self.val = i;
    }
}

impl<T: Copy + Unsigned>  Register<T> {
    pub fn increment(&mut self) {
        let i = self.val;
        self.write(i + One::one());
    }

    pub fn decrement(&mut self) {
        let i = self.val;
        self.write(i - One::one());
    }
}

bitflags! {
    flags Flags: u8 {
        static ZeroFlag       = 0b10000000,
        static SubtractFlag   = 0b01000000,
        static HalfCarryFlag  = 0b00100000,
        static CarryFlag      = 0b00010000,
    }
}

#[test]
fn test_Register_new() {
    let reg: Register<u8> = Register::new(10);
    assert!(reg.val == 10);
}

#[test]
fn test_Register_read() {
    let reg: Register<u32> = Register::new(5);
    assert!(reg.read() == 5);
}

#[test]
fn test_Register_write() {
    let mut reg: Register<u16> = Register::new(483);

    reg.write(5);
    assert!(reg.val == 5);
}

#[test]
fn test_Register_increment() {
    let mut reg: Register<u16> = Register::new(483);

    reg.increment();
    assert!(reg.val == 484);

}

#[test]
fn test_Register_decrement() {
    let mut reg: Register<u16> = Register::new(401);

    reg.decrement();
    assert!(reg.val == 400);

}

#[test]
fn test_Registers_new() {
    let a = Registers::new();
    assert!(a.pc.read() == 0x100);
    assert!(a.sp.read() == 0xFFFE);
}
<commit_msg>Add 0x09 Add HL, BC<commit_after>use num::integer::Integer;
use memory::Memory;
use memory::low_nibble;
use memory::high_nibble;
use extensions::Incrementor;
use ops::{mod};
use std::num::One;

pub struct Cpu {
    reg: Registers,
    mem: Memory
}

impl Cpu {
    pub fn new(memory: Memory) -> Cpu {
        return Cpu{reg: Registers::new(), mem: memory}
    }

    /// Execute a cycle on the cpu
    pub fn tick(&mut self) {
        let instr = self.fetch_instruction();

        match instr {
            0x00 => ops::nop(),
            0x01 => ops::ld_next_two_byte_into_reg_pair(&self.mem, &mut self.reg.pc, &mut self.reg.b, &mut self.reg.c),
            0x02 => ops::write_value_to_memory_at_address(&mut self.mem, self.reg.a.read(), self.reg.b.read(), self.reg.c.read()),
            0x03 => ops::increment_register_pair(&mut self.reg.b, &mut self.reg.c),
            0x04 => ops::increment_register(&mut self.reg.b, &mut self.reg.f),
            0x05 => ops::decrement_register(&mut self.reg.b, &mut self.reg.f),
            0x06 => ops::ld_immediate(&self.mem, &mut self.reg.pc, &mut self.reg.b),
            0x07 => ops::rotate_left_with_carry(&mut self.reg.a, &mut self.reg.f),
            0x08 => ops::write_sp_to_address_immediate(&mut self.mem, &mut self.reg.pc, &self.reg.sp),
            0x09 => ops::add_register_pair_to_register_pair(&mut self.reg.h, &mut self.reg.l, &self.reg.b, &self.reg.c, &mut self.reg.f),
            _ => return
        }
    }

    /// Fetches the instruction pointed to by the program counter
    /// and increments the pc by 1
    fn fetch_instruction(&mut self) -> u8 {
        let instr = self.mem.read_byte(self.reg.pc.val);
        self.reg.pc.increment();
        return instr;
    }
}

struct Registers {
    a: Register<u8>, b: Register<u8>, c: Register<u8>,
    d: Register<u8>, e: Register<u8>, f: Register<Flags>,
    h: Register<u8>, l: Register<u8>, // 8-bit registers

    pc: Register<u16>, sp: Register<u16>, // 16-bit registers
    m: Register<u16>, t: Register<u16> // clock
}

impl Registers {
    fn new() -> Registers {
        return Registers{
            a: Register::new(0),
            b: Register::new(0),
            c: Register::new(0),
            d: Register::new(0),
            e: Register::new(0),
            f: Register::new(Flags::empty()),
            h: Register::new(0),
            l: Register::new(0),

            pc: Register::new(0x100),
            sp: Register::new(0xFFFE),

            m: Register::new(0),
            t: Register::new(0)
        }
    }
}

pub struct Register<T: Copy> {
    val: T
}

impl<T: Copy> Register<T> {
    pub fn new(i: T) -> Register<T> {
        return Register { val: i };
    }

    pub fn read(&self) -> T {
        return self.val;
    }

    pub fn write(&mut self, i: T) {
        self.val = i;
    }
}

impl<T: Copy + Unsigned>  Register<T> {
    pub fn increment(&mut self) {
        let i = self.val;
        self.write(i + One::one());
    }

    pub fn decrement(&mut self) {
        let i = self.val;
        self.write(i - One::one());
    }
}

bitflags! {
    flags Flags: u8 {
        static ZeroFlag       = 0b10000000,
        static SubtractFlag   = 0b01000000,
        static HalfCarryFlag  = 0b00100000,
        static CarryFlag      = 0b00010000,
    }
}

#[test]
fn test_Register_new() {
    let reg: Register<u8> = Register::new(10);
    assert!(reg.val == 10);
}

#[test]
fn test_Register_read() {
    let reg: Register<u32> = Register::new(5);
    assert!(reg.read() == 5);
}

#[test]
fn test_Register_write() {
    let mut reg: Register<u16> = Register::new(483);

    reg.write(5);
    assert!(reg.val == 5);
}

#[test]
fn test_Register_increment() {
    let mut reg: Register<u16> = Register::new(483);

    reg.increment();
    assert!(reg.val == 484);

}

#[test]
fn test_Register_decrement() {
    let mut reg: Register<u16> = Register::new(401);

    reg.decrement();
    assert!(reg.val == 400);

}

#[test]
fn test_Registers_new() {
    let a = Registers::new();
    assert!(a.pc.read() == 0x100);
    assert!(a.sp.read() == 0xFFFE);
}
<|endoftext|>


<commit_before>mod macros;

const NUM_BYTES: usize = 4096;
const NUM_REGISTERS: usize = 16;
const STACK_SIZE: usize = 48;

const VALUE_MASK: u16 = 0b0000_0000_1111_1111;
const REGISTER_ADDRESS_MASK: u16 = 0b0000_1111_0000_0000;

#[allow(dead_code)]
pub struct System {
    memory: [u8; NUM_BYTES],
    registers: [u8; NUM_REGISTERS],
    pc: u16,
    index: u16,
    stack: [u8; STACK_SIZE],
    sp: u8
}

#[allow(dead_code)]
impl System{
    pub fn new() -> Self {
        System {
            memory: [0; NUM_BYTES],
            registers: [0; NUM_REGISTERS],
            pc: 0,
            index: 0,
            stack: [0; STACK_SIZE],
            sp: 0
        }
    }

    /** Index into system memory at address and return word located there. */
    pub fn read_word(&self, address: usize) -> u16 {
        let left = self.memory[address] as u16;
        let right = self.memory[address + 1] as u16;
        (left << 8) | right
    }

    /** Execute the instruction. */
    pub fn execute(&mut self, opcode: u16) {
        match opcode {
            0x6000...0x7000 => {    // 0x6XNN : VX = NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = value;
            },
            0x7000...0x8000 => {    // 0x7XNN : VX = VX + NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = self.registers[register].wrapping_add(value);
            },
            _ => {
                eprintln!("Unrecognized instruction!");
            }
        }
    }
}

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

    /** Load some test data into the system memory for the purposes of testing. */
    fn load_test_data(system: &mut System) {
        system.memory[0] = 0xAF;
        system.memory[1] = 0x7F;
        system.memory[NUM_BYTES / 2] = 0x77;
        system.memory[NUM_BYTES / 2 + 1] = 0x88;
        system.memory[NUM_BYTES - 2] = 0x3A;
        system.memory[NUM_BYTES - 1] = 0x01;
    }

    /** Read a word (two bytes) from the system memory. */
    #[test]
    fn read_word() {
        let mut system = System::new();
        load_test_data(&mut system);
        assert_eq!(0xAF7F, system.read_word(0));
        assert_eq!(0x7788, system.read_word(NUM_BYTES / 2));
        assert_eq!(0x3A01, system.read_word(NUM_BYTES - 2));
    }

    /** The opcode 0x6XNN should store the constant NN into register VX. */
    #[test]
    fn load_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        assert_eq!(0x15, system.registers[0]);
        system.execute(0x6120);
        assert_eq!(0x20, system.registers[1]);
        system.execute(0x6225);
        assert_eq!(0x25, system.registers[2]);
        system.execute(0x6330);
        assert_eq!(0x30, system.registers[3]);
        system.execute(0x6435);
        assert_eq!(0x35, system.registers[4]);
        system.execute(0x6540);
        assert_eq!(0x40, system.registers[5]);
        system.execute(0x6645);
        assert_eq!(0x45, system.registers[6]);
        system.execute(0x6750);
        assert_eq!(0x50, system.registers[7]);
        system.execute(0x6855);
        assert_eq!(0x55, system.registers[8]);
        system.execute(0x6960);
        assert_eq!(0x60, system.registers[9]);
        system.execute(0x6A65);
        assert_eq!(0x65, system.registers[0xA]);
        system.execute(0x6B70);
        assert_eq!(0x70, system.registers[0xB]);
        system.execute(0x6C75);
        assert_eq!(0x75, system.registers[0xC]);
        system.execute(0x6D80);
        assert_eq!(0x80, system.registers[0xD]);
        system.execute(0x6E85);
        assert_eq!(0x85, system.registers[0xE]);
        system.execute(0x6F90);
        assert_eq!(0x90, system.registers[0xF]);
    }

    /** The opcode 0x7XNN should add the constant NN into register VX. */
    #[test]
    fn add_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        system.execute(0x7015);
        assert_eq!(0x2A, system.registers[0]);
        system.execute(0x6A42);
        system.execute(0x7A42);
        assert_eq!(0x84, system.registers[0xA]);
        system.execute(0x6EFF);
        system.execute(0x7E01);
        // registers should overlow appropriately
        assert_eq!(0x00, system.registers[0xE]);
    }
}
<commit_msg>copy register<commit_after>mod macros;

const NUM_BYTES: usize = 4096;
const NUM_REGISTERS: usize = 16;
const STACK_SIZE: usize = 48;

const VALUE_MASK: u16 = 0b0000_0000_1111_1111;
const REGISTER_ADDRESS_MASK: u16 = 0b0000_1111_0000_0000;

#[allow(dead_code)]
pub struct System {
    memory: [u8; NUM_BYTES],
    registers: [u8; NUM_REGISTERS],
    pc: u16,
    index: u16,
    stack: [u8; STACK_SIZE],
    sp: u8
}

#[allow(dead_code)]
impl System{
    pub fn new() -> Self {
        System {
            memory: [0; NUM_BYTES],
            registers: [0; NUM_REGISTERS],
            pc: 0,
            index: 0,
            stack: [0; STACK_SIZE],
            sp: 0
        }
    }

    /** Index into system memory at address and return word located there. */
    pub fn read_word(&self, address: usize) -> u16 {
        let left = self.memory[address] as u16;
        let right = self.memory[address + 1] as u16;
        (left << 8) | right
    }

    /** Execute the instruction. */
    pub fn execute(&mut self, opcode: u16) {
        match opcode {
            0x6000...0x7000 => {    // 0x6XNN : VX = NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = value;
            },
            0x7000...0x8000 => {    // 0x7XNN : VX = VX + NN
                let register = ((opcode & REGISTER_ADDRESS_MASK) >> 8) as usize;
                let value = (opcode & VALUE_MASK) as u8;
                self.registers[register] = self.registers[register].wrapping_add(value);
            },
            0x8000...0x9000 => {
                match opcode & 0b0000_0000_0000_1111 {
                    0x0 => {    // 0x8XY0 : VX = VY
                        let left = ((opcode & 0b0000_1111_0000_0000) >> 8) as usize;
                        let right = ((opcode & 0b0000_0000_1111_0000) >> 4) as usize;
                        self.registers[left] = self.registers[right];
                    },
                    _ => {
                        eprintln!("Unrecognized instruction!");
                    }
                }
            }
            _ => {
                eprintln!("Unrecognized instruction!");
            }
        }
    }
}

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

    /** Load some test data into the system memory for the purposes of testing. */
    fn load_test_data(system: &mut System) {
        system.memory[0] = 0xAF;
        system.memory[1] = 0x7F;
        system.memory[NUM_BYTES / 2] = 0x77;
        system.memory[NUM_BYTES / 2 + 1] = 0x88;
        system.memory[NUM_BYTES - 2] = 0x3A;
        system.memory[NUM_BYTES - 1] = 0x01;
    }

    /** Read a word (two bytes) from the system memory. */
    #[test]
    fn read_word() {
        let mut system = System::new();
        load_test_data(&mut system);
        assert_eq!(0xAF7F, system.read_word(0));
        assert_eq!(0x7788, system.read_word(NUM_BYTES / 2));
        assert_eq!(0x3A01, system.read_word(NUM_BYTES - 2));
    }

    /** The opcode 0x6XNN should store the constant NN into register VX. */
    #[test]
    fn load_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        assert_eq!(0x15, system.registers[0]);
        system.execute(0x6120);
        assert_eq!(0x20, system.registers[1]);
        system.execute(0x6225);
        assert_eq!(0x25, system.registers[2]);
        system.execute(0x6330);
        assert_eq!(0x30, system.registers[3]);
        system.execute(0x6435);
        assert_eq!(0x35, system.registers[4]);
        system.execute(0x6540);
        assert_eq!(0x40, system.registers[5]);
        system.execute(0x6645);
        assert_eq!(0x45, system.registers[6]);
        system.execute(0x6750);
        assert_eq!(0x50, system.registers[7]);
        system.execute(0x6855);
        assert_eq!(0x55, system.registers[8]);
        system.execute(0x6960);
        assert_eq!(0x60, system.registers[9]);
        system.execute(0x6A65);
        assert_eq!(0x65, system.registers[0xA]);
        system.execute(0x6B70);
        assert_eq!(0x70, system.registers[0xB]);
        system.execute(0x6C75);
        assert_eq!(0x75, system.registers[0xC]);
        system.execute(0x6D80);
        assert_eq!(0x80, system.registers[0xD]);
        system.execute(0x6E85);
        assert_eq!(0x85, system.registers[0xE]);
        system.execute(0x6F90);
        assert_eq!(0x90, system.registers[0xF]);
    }

    /** The opcode 0x7XNN should add the constant NN into register VX. */
    #[test]
    fn add_constant() {
        let mut system = System::new();
        system.execute(0x6015);
        system.execute(0x7015);
        assert_eq!(0x2A, system.registers[0]);

        system.execute(0x6A42);
        system.execute(0x7A42);
        assert_eq!(0x84, system.registers[0xA]);

        system.execute(0x6EFF);
        system.execute(0x7E01);
        // registers should overlow appropriately
        assert_eq!(0x00, system.registers[0xE]);
    }

    /** The opcode 0x8XY0 should copy the value from register VY into register VX. */
    #[test]
    fn copy_register() {
        let mut system = System::new();
        system.execute(0x6A42);
        system.execute(0x8EA0);
        assert_eq!(0x42, system.registers[0xA]);
        assert_eq!(0x42, system.registers[0xE]);

        system.execute(0x67DE);
        system.execute(0x8F70);
        assert_eq!(0xDE, system.registers[0x7]);
        assert_eq!(0xDE, system.registers[0xF]);
    }
}
<|endoftext|>


<commit_before>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

#[derive(Clone)]
pub enum Element {
    Other(Sexp),
    Module(footprint::Module),
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
        }
    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<commit_msg>net and netclass as explicit types (unparsed yet)<commit_after>// (c) 2016 Joost Yervante Damad <joost@productize.be>

use std::fmt;
use std::path::PathBuf;

// from parent
use ERes;
use err;
use read_file;
use footprint;

extern crate rustysexp;
use self::rustysexp::Sexp;

pub struct Layout {
    pub version:i64,
    pub elements:Vec<Element>,
}

#[derive(Clone)]
pub enum Element {
    Module(footprint::Module),
    Net(Net),
    NetClass(NetClass),
    Other(Sexp),
}

#[derive(Clone)]
pub struct Net {
    pub num:i64,
    pub name:String,
}

#[derive(Clone)]
pub struct NetClass {
    pub name:String,
    pub desc:String,
    pub clearance:f64,
    pub trace_width:f64,
    pub via_dia:f64,
    pub via_drill:f64,
    pub uvia_dia:f64,
    pub uvia_drill:f64,
    pub nets:Vec<String>,
}

impl Layout {
    fn new() -> Layout {
        Layout {
            version:0,
            elements:vec![],
        }
    }

    pub fn modify_module<F>(&mut self, reference:&String, fun:F) -> ERes<()>
        where F:Fn(&mut footprint::Module) -> ()
    {
        for ref mut x in &mut self.elements[..] {
            match **x {
                Element::Module(ref mut m) => {
                    if m.is_reference(reference) {
                        return Ok(fun(m))
                    }
                },
                Element::Net(_) => (),
                Element::NetClass(_) => (),
                Element::Other(_) => (),
            }
        }
        Err(format!("did not find module with reference {}", reference))
    }
}

impl fmt::Display for Layout {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(writeln!(f, "(kicad_pcb (version {})", self.version));
        for element in &self.elements[..] {
            try!(writeln!(f, "  {}", element));
            try!(writeln!(f, ""));
        }
        writeln!(f, ")")
    }
}

impl fmt::Display for Element {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match *self {
            Element::Other(ref s) => write!(f, "{}", s),
            Element::Module(ref s) => write!(f, "{}", s),
            Element::Net(ref s) => write!(f, "{}", s),
            Element::NetClass(ref s) => write!(f, "{}", s),
        }
    }
}

impl fmt::Display for Net {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.name.contains("(") || self.name.contains(")") {
            write!(f, "(net {} \"{}\")", self.num, self.name)
        } else {
            write!(f, "(net {} {})", self.num, self.name)
        }
    }
}
impl fmt::Display for NetClass {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        try!(write!(f, "(net_class {} \"{}\" ", self.name, self.desc));
        try!(write!(f, "(clearance {}) ", self.clearance));
        try!(write!(f, "(trace_width {}) ", self.trace_width));
        try!(write!(f, "(via_dia {}) ", self.via_dia));
        try!(write!(f, "(via_drill {}) ", self.via_drill));
        try!(write!(f, "(uvia_dia {}) ", self.uvia_dia));
        try!(write!(f, "(uvia_drill {}) ", self.uvia_drill));
        for net in &self.nets {
            if net.contains("(") || net.contains(")") {
                try!(write!(f, "(add_net \"{}\")", net))
            } else {
                try!(write!(f, "(add_net {})", net))
            }
        }
        write!(f, ")")

    }
}

fn parse_version(e:&Sexp) -> ERes<i64> {
    let l = try!(e.slice_atom("version"));
    try!(l[0].atom()).i()
}

fn parse_other(e:&Sexp) -> Element {
    let e2 = e.clone();
    Element::Other(e2)
}

fn parse_module(e:&Sexp) -> ERes<Element> {
    let e2 = e.clone();
    let m = try!(footprint::parse_module(e2));
    Ok(Element::Module(m))
}

fn parse(s: &str) -> ERes<Layout> {
    let exp = match rustysexp::parse_str(s) {
        Ok(s) => s,
        Err(x) => return Err(format!("ParseError: {}", x)),
    };
    let l1 = try!(exp.slice_atom("kicad_pcb"));
    let mut layout = Layout::new();

    for ref e in l1 {
        match &try!(e.list_name())[..] {
            "version" => layout.version = try!(parse_version(e)),
            "module" => layout.elements.push(try!(parse_module(e))),
            _ => layout.elements.push(parse_other(e)),
        }
    }
    Ok(layout)
}

pub fn parse_str(s: &str) -> ERes<Layout> {
    parse(s)
}

pub fn parse_file(filename: &PathBuf) -> ERes<Layout> {
    let name = filename.to_str().unwrap();
    let s = try!(match read_file(name) {
        Ok(s) => Ok(s),
        Err(x) => Err(format!("io error: {}", x))
    });
    parse(&s[..])
}
<|endoftext|>


<commit_before>use super::TestDatabase;
use crate::db::CratesIoData;
use crate::docbuilder::BuildResult;
use crate::utils::{Dependency, MetadataPackage, Target};
use failure::Error;

#[must_use = "FakeRelease does nothing until you call .create()"]
pub(crate) struct FakeRelease<'db> {
    db: &'db TestDatabase,
    package: MetadataPackage,
    build_result: BuildResult,
    /// name, content
    source_files: Vec<(String, Vec<u8>)>,
    /// name, content
    rustdoc_files: Vec<(String, Vec<u8>)>,
    doc_targets: Vec<String>,
    default_target: Option<String>,
    cratesio_data: CratesIoData,
    has_docs: bool,
    has_examples: bool,
}

impl<'db> FakeRelease<'db> {
    pub(super) fn new(db: &'db TestDatabase) -> Self {
        FakeRelease {
            db,
            package: MetadataPackage {
                id: "fake-package-id".into(),
                name: "fake-package".into(),
                version: "1.0.0".into(),
                license: Some("MIT".into()),
                repository: Some("https://git.example.com".into()),
                homepage: Some("https://www.example.com".into()),
                description: Some("Fake package".into()),
                documentation: Some("https://docs.example.com".into()),
                dependencies: vec![Dependency {
                    name: "fake-dependency".into(),
                    req: "^1.0.0".into(),
                    kind: None,
                }],
                targets: vec![Target::dummy_lib("fake_package".into(), None)],
                readme: None,
                keywords: vec!["fake".into(), "package".into()],
                authors: vec!["Fake Person <fake@example.com>".into()],
            },
            build_result: BuildResult {
                rustc_version: "rustc 2.0.0-nightly (000000000 1970-01-01)".into(),
                docsrs_version: "docs.rs 1.0.0 (000000000 1970-01-01)".into(),
                build_log: "It works!".into(),
                successful: true,
            },
            source_files: Vec::new(),
            rustdoc_files: Vec::new(),
            doc_targets: Vec::new(),
            default_target: None,
            cratesio_data: CratesIoData {
                release_time: time::get_time(),
                yanked: false,
                downloads: 0,
                owners: Vec::new(),
            },
            has_docs: true,
            has_examples: false,
        }
    }

    pub(crate) fn name(mut self, new: &str) -> Self {
        self.package.name = new.into();
        self.package.id = format!("{}-id", new);
        self
    }

    pub(crate) fn version(mut self, new: &str) -> Self {
        self.package.version = new.into();
        self
    }

    pub(crate) fn build_result_successful(mut self, new: bool) -> Self {
        self.build_result.successful = new;
        self
    }

    pub(crate) fn cratesio_data_yanked(mut self, new: bool) -> Self {
        self.cratesio_data.yanked = new;
        self
    }

    pub(crate) fn file<M, P, D>(mut self, mimetype: M, path: P, data: D) -> Self
        where M: Into<String>,
              P: Into<String>,
              D: Into<Vec<u8>>,
        {
        let (mimetype, path, data) = (mimetype.into(), path.into(), data.into());
        self.files.push((mimetype, path, data));
        self
    }

    pub(crate) fn rustdoc_file<P, D>(mut self, path: P, data: D) -> Self
        where P: Into<String>,
              D: Into<Vec<u8>>,
        {
        let (path, data) = (path.into(), data.into());
        self.rustdoc_files.push((path, data));

        self
    }

    pub(crate) fn create(self) -> Result<i32, Error> {
        let tempdir = tempdir::TempDir::new("docs.rs-fake")?;

        let upload_files = |prefix, files: Vec<(String, Vec<u8>)>, package: &MetadataPackage, db: &TestDatabase| {
            for (path, data) in files {
                let file = tempdir.path().join(&path);
                std::fs::write(file, data)?;
            }

            let prefix = format!("{}/{}/{}", prefix, package.name, package.version);
            crate::db::add_path_into_database(&db.conn(), &prefix, tempdir.path())
        };

        let rustdoc_meta = upload_files("rustdoc", self.rustdoc_files, &self.package, self.db)?;
        log::debug!("added rustdoc files {}", rustdoc_meta);
        let source_meta = upload_files("source", self.source_files, &self.package, self.db)?;
        log::debug!("added source files {}", source_meta);

        let release_id = crate::db::add_package_into_database(
            &self.db.conn(),
            &self.package,
            tempdir.path(),
            &self.build_result,
            Some(source_meta),
            self.doc_targets,
            &self.default_target,
            &self.cratesio_data,
            self.has_docs,
            self.has_examples,
        )?;
        crate::db::add_build_into_database(&self.db.conn(), &release_id, &self.build_result)?;

        Ok(release_id)
    }
}
<commit_msg>don't duplicate rustdoc files as source files<commit_after>use super::TestDatabase;
use crate::db::CratesIoData;
use crate::docbuilder::BuildResult;
use crate::utils::{Dependency, MetadataPackage, Target};
use failure::Error;

#[must_use = "FakeRelease does nothing until you call .create()"]
pub(crate) struct FakeRelease<'db> {
    db: &'db TestDatabase,
    package: MetadataPackage,
    build_result: BuildResult,
    /// name, content
    source_files: Vec<(String, Vec<u8>)>,
    /// name, content
    rustdoc_files: Vec<(String, Vec<u8>)>,
    doc_targets: Vec<String>,
    default_target: Option<String>,
    cratesio_data: CratesIoData,
    has_docs: bool,
    has_examples: bool,
}

impl<'db> FakeRelease<'db> {
    pub(super) fn new(db: &'db TestDatabase) -> Self {
        FakeRelease {
            db,
            package: MetadataPackage {
                id: "fake-package-id".into(),
                name: "fake-package".into(),
                version: "1.0.0".into(),
                license: Some("MIT".into()),
                repository: Some("https://git.example.com".into()),
                homepage: Some("https://www.example.com".into()),
                description: Some("Fake package".into()),
                documentation: Some("https://docs.example.com".into()),
                dependencies: vec![Dependency {
                    name: "fake-dependency".into(),
                    req: "^1.0.0".into(),
                    kind: None,
                }],
                targets: vec![Target::dummy_lib("fake_package".into(), None)],
                readme: None,
                keywords: vec!["fake".into(), "package".into()],
                authors: vec!["Fake Person <fake@example.com>".into()],
            },
            build_result: BuildResult {
                rustc_version: "rustc 2.0.0-nightly (000000000 1970-01-01)".into(),
                docsrs_version: "docs.rs 1.0.0 (000000000 1970-01-01)".into(),
                build_log: "It works!".into(),
                successful: true,
            },
            source_files: Vec::new(),
            rustdoc_files: Vec::new(),
            doc_targets: Vec::new(),
            default_target: None,
            cratesio_data: CratesIoData {
                release_time: time::get_time(),
                yanked: false,
                downloads: 0,
                owners: Vec::new(),
            },
            has_docs: true,
            has_examples: false,
        }
    }

    pub(crate) fn name(mut self, new: &str) -> Self {
        self.package.name = new.into();
        self.package.id = format!("{}-id", new);
        self
    }

    pub(crate) fn version(mut self, new: &str) -> Self {
        self.package.version = new.into();
        self
    }

    pub(crate) fn build_result_successful(mut self, new: bool) -> Self {
        self.build_result.successful = new;
        self
    }

    pub(crate) fn cratesio_data_yanked(mut self, new: bool) -> Self {
        self.cratesio_data.yanked = new;
        self
    }

    pub(crate) fn file<M, P, D>(mut self, mimetype: M, path: P, data: D) -> Self
        where M: Into<String>,
              P: Into<String>,
              D: Into<Vec<u8>>,
        {
        let (mimetype, path, data) = (mimetype.into(), path.into(), data.into());
        self.files.push((mimetype, path, data));
        self
    }

    pub(crate) fn rustdoc_file<P, D>(mut self, path: P, data: D) -> Self
        where P: Into<String>,
              D: Into<Vec<u8>>,
        {
        let (path, data) = (path.into(), data.into());
        self.rustdoc_files.push((path, data));

        self
    }

    pub(crate) fn create(self) -> Result<i32, Error> {
        let tempdir = tempdir::TempDir::new("docs.rs-fake")?;

        let upload_files = |prefix: &str, files: Vec<(String, Vec<u8>)>, package: &MetadataPackage, db: &TestDatabase| {
            let path_prefix = tempdir.path().join(prefix);
            std::fs::create_dir(&path_prefix)?;

            for (path, data) in files {
                let file = path_prefix.join(&path);
                std::fs::write(file, data)?;
            }

            let prefix = format!("{}/{}/{}", prefix, package.name, package.version);
            crate::db::add_path_into_database(&db.conn(), &prefix, path_prefix)
        };

        let rustdoc_meta = upload_files("rustdoc", self.rustdoc_files, &self.package, self.db)?;
        log::debug!("added rustdoc files {}", rustdoc_meta);
        let source_meta = upload_files("source", self.source_files, &self.package, self.db)?;
        log::debug!("added source files {}", source_meta);

        let release_id = crate::db::add_package_into_database(
            &self.db.conn(),
            &self.package,
            tempdir.path(),
            &self.build_result,
            Some(source_meta),
            self.doc_targets,
            &self.default_target,
            &self.cratesio_data,
            self.has_docs,
            self.has_examples,
        )?;
        crate::db::add_build_into_database(&self.db.conn(), &release_id, &self.build_result)?;

        Ok(release_id)
    }
}
<|endoftext|>


<commit_before>use std::fmt::Display;
use std::io::{self, Write};

pub fn echo<S: Display>(message: S) {
    print!("{}", message);
    if let Err(why) = io::stdout().flush() {
        panic!("{}", why);
    }
}

pub fn read_line_from_stdin() -> Result<String, io::Error>  {
    let mut input = String::new();
    io::stdin().read_line(&mut input)
        .map(|_| input.trim().to_string())
}

pub enum Tag {
    Execution,
    Okay,
    Notice,
    Warning,
    Error,
    Caution,
}

pub fn format_with_tag<S: Display>(indent_level: usize, tag: Tag, message: S) -> String {
    let indent = (0 .. indent_level).map(|_| "  ").collect::<String>();

    let tag = match tag {
        Tag::Execution => "EXECUTION",
        Tag::Okay      => "OK",
        Tag::Notice    => "NOTICE",
        Tag::Warning   => "WARNING",
        Tag::Error     => "ERROR",
        Tag::Caution   => "CAUTION",
    };

    format!("{}{}: {}", indent, tag, message)
}

pub fn print_with_tag<S: Display>(indent_level: usize, tag: Tag, message: S) {
    println!("{}", format_with_tag(indent_level, tag, message));
}
<commit_msg>[Remedy] Add extra line break<commit_after>use std::fmt::Display;
use std::io::{self, Write};

pub fn echo<S: Display>(message: S) {
    print!("{}", message);
    if let Err(why) = io::stdout().flush() {
        panic!("{}", why);
    }
}

pub fn read_line_from_stdin() -> Result<String, io::Error>  {
    let mut input = String::new();
    io::stdin().read_line(&mut input)
        .map(|_| input.trim().to_string())
}

pub enum Tag {
    Execution,
    Okay,
    Notice,
    Warning,
    Error,
    Caution,
}

pub fn format_with_tag<S: Display>(indent_level: usize, tag: Tag, message: S) -> String {
    let indent = (0 .. indent_level).map(|_| "  ").collect::<String>();

    let extra = match tag {
        Tag::Okay | Tag::Notice => "\n",
        _                       => "",
    };

    let tag = match tag {
        Tag::Execution => "EXECUTION",
        Tag::Okay      => "OK",
        Tag::Notice    => "NOTICE",
        Tag::Warning   => "WARNING",
        Tag::Error     => "ERROR",
        Tag::Caution   => "CAUTION",
    };

    format!("{}{}: {}{}", indent, tag, message, extra)
}

pub fn print_with_tag<S: Display>(indent_level: usize, tag: Tag, message: S) {
    println!("{}", format_with_tag(indent_level, tag, message));
}
<|endoftext|>


<commit_before>// Copyright 2017 Dario Domizioli ("hhexo").
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// These tests are based on the book called "Seven Concurrency Models
// In Seven Weeks". Chapter 5 of the book is about the actor model. I am trying
// to replicate the exercises in the book by writing equivalent tests for the
// mecha library.

#[cfg(test)]
mod chapter5_day1 {

use std::sync::mpsc;
use std::collections::HashMap;

use Actor;
use MessageType;
use MessageDatum;
use Message;
use ActorAddress;
use spawn_link;

struct Talker;

const GREET: &'static str = ":greet";
const PRAISE: &'static str = ":praise";
const CELEBRATE: &'static str = ":celebrate";

impl Actor for Talker {
    fn process_message(&mut self, message: Message, _: &ActorAddress) {
        match *message.get_type() {
            MessageType::Custom(GREET) => {
                match *message.get_datum() {
                    MessageDatum::Str(ref s) => {
                        println!("Hello {}!", s);
                    },
                    _ => (),
                }
            },
            MessageType::Custom(PRAISE) => {
                match *message.get_datum() {
                    MessageDatum::Str(ref s) => {
                        println!("{}, you're amazing!", s);
                    },
                    _ => (),
                }
            },
            MessageType::Custom(CELEBRATE) => {
                match *message.get_datum() {
                    MessageDatum::Map(ref m) => {
                        let name = m.get("name").unwrap().clone().as_str().unwrap();
                        let age = m.get("age").unwrap().clone().as_u64().unwrap();
                        println!("Here's to another {} years, {}!", age, name);
                    },
                    _ => (),
                }
            },
            _ => (),
        }
    }
}

struct Issuer;

impl Actor for Issuer {
    fn process_message(&mut self, message: Message, myself: &ActorAddress) {
        match *message.get_type() {
            MessageType::Init => {
                let worker = spawn_link(Talker, myself);
                Message::custom(GREET).with_str("Hewey").send_to(&worker);
                Message::custom(PRAISE).with_str("Dewey").send_to(&worker);
                let mut m = HashMap::new();
                m.insert("name".to_string(), MessageDatum::from("Louie"));
                m.insert("age".to_string(), MessageDatum::from(16u64));
                Message::custom(CELEBRATE).with_map(m).send_to(&worker);
                Message::shutdown().send_to(&worker);
            },
            MessageType::Exited => {
                // This means our worker has exited, we can exit too. Send
                // ourselves a Shutdown.
                Message::shutdown().send_to(myself);
            },
            _ => ()
        }
    }
}

#[test]
fn test_talker() {
    let (tx, rx) = mpsc::channel();
    let fake_actor = ActorAddress::new(tx);
    spawn_link(Issuer, &fake_actor);

    // Now let's receive the Exited message.
    let m = rx.recv().unwrap();
    assert_eq!(*m.get_type(), MessageType::Exited);
    match *m.get_datum() {
        MessageDatum::Void => (), // ok
        _ => { assert!(false, "Unexpected message datum"); }
    }
}

}
<commit_msg>Added more examples as tests<commit_after>// Copyright 2017 Dario Domizioli ("hhexo").
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// These tests are based on the book called "Seven Concurrency Models
// In Seven Weeks". Chapter 5 of the book is about the actor model. I am trying
// to replicate the exercises in the book by writing equivalent tests for the
// mecha library.

#[cfg(test)]
mod chapter5_day1 {

use std::sync::mpsc;
use std::collections::HashMap;

use Actor;
use MessageType;
use MessageDatum;
use Message;
use ActorAddress;
use spawn_link;

// ----------------------------------------------------------------------------

struct Talker;

const GREET: &'static str = ":greet";
const PRAISE: &'static str = ":praise";
const CELEBRATE: &'static str = ":celebrate";

impl Actor for Talker {
    fn process_message(&mut self, message: Message, _: &ActorAddress) {
        match *message.get_type() {
            MessageType::Custom(GREET) => {
                match *message.get_datum() {
                    MessageDatum::Str(ref s) => {
                        println!("Hello {}!", s);
                    },
                    _ => (),
                }
            },
            MessageType::Custom(PRAISE) => {
                match *message.get_datum() {
                    MessageDatum::Str(ref s) => {
                        println!("{}, you're amazing!", s);
                    },
                    _ => (),
                }
            },
            MessageType::Custom(CELEBRATE) => {
                match *message.get_datum() {
                    MessageDatum::Map(ref m) => {
                        let name = m.get("name").unwrap().clone().as_str().unwrap();
                        let age = m.get("age").unwrap().clone().as_u64().unwrap();
                        println!("Here's to another {} years, {}!", age, name);
                    },
                    _ => (),
                }
            },
            _ => (),
        }
    }
}

struct Issuer;

impl Actor for Issuer {
    fn process_message(&mut self, message: Message, myself: &ActorAddress) {
        match *message.get_type() {
            MessageType::Init => {
                let worker = spawn_link(Talker, myself);
                Message::custom(GREET).with_str("Hewey").send_to(&worker);
                Message::custom(PRAISE).with_str("Dewey").send_to(&worker);
                let mut m = HashMap::new();
                m.insert("name".to_string(), MessageDatum::from("Louie"));
                m.insert("age".to_string(), MessageDatum::from(16u64));
                Message::custom(CELEBRATE).with_map(m).send_to(&worker);
                Message::shutdown().send_to(&worker);
            },
            MessageType::Exited => {
                // This means our worker has exited, we can exit too. Send
                // ourselves a Shutdown.
                Message::shutdown().send_to(myself);
            },
            _ => ()
        }
    }
}

#[test]
fn test_talker() {
    let (tx, rx) = mpsc::channel();
    let fake_actor = ActorAddress::new(tx);
    spawn_link(Issuer, &fake_actor);

    // Now let's receive the Exited message.
    let m = rx.recv().unwrap();
    assert_eq!(*m.get_type(), MessageType::Exited);
    match *m.get_datum() {
        MessageDatum::Void => (), // ok
        _ => { assert!(false, "Unexpected message datum"); }
    }
}

// ----------------------------------------------------------------------------

struct Counter {
    count: i64
}
impl Counter {
    pub fn new() -> Counter { Counter { count: 0i64 } }
}

const NEXT : &'static str = ":next";

impl Actor for Counter {
    fn process_message(&mut self, message: Message, _: &ActorAddress) {
        match *message.get_type() {
            MessageType::Custom(NEXT) => {
                println!("Current count: {}", self.count);
                self.count += 1;
            },
            _ => ()
        }
    }
}

#[test]
fn test_counter() {
    let (tx, rx) = mpsc::channel();
    let fake_actor = ActorAddress::new(tx);
    let worker = spawn_link(Counter::new(), &fake_actor);

    Message::custom(NEXT).send_to(&worker);
    Message::custom(NEXT).send_to(&worker);
    Message::custom(NEXT).send_to(&worker);
    Message::shutdown().send_to(&worker);

    // Now let's receive the Exited message.
    let m = rx.recv().unwrap();
    assert_eq!(*m.get_type(), MessageType::Exited);
    match *m.get_datum() {
        MessageDatum::Void => (), // ok
        _ => { assert!(false, "Unexpected message datum"); }
    }
}

struct CounterApi {
    counter_actor: ActorAddress
}
impl CounterApi {
    pub fn start(count: i64, link: &ActorAddress) -> CounterApi {
        CounterApi {
            counter_actor: spawn_link(Counter { count: count }, link)
        }
    }

    pub fn next(&self) {
        Message::custom(NEXT).send_to(&self.counter_actor);
    }

    pub fn shutdown(&self) {
        Message::shutdown().send_to(&self.counter_actor);
    }
}

#[test]
fn test_counter_with_api() {
    let (tx, rx) = mpsc::channel();
    let fake_actor = ActorAddress::new(tx);
    let api = CounterApi::start(0i64, &fake_actor);

    api.next();
    api.next();
    api.next();
    api.shutdown();

    // Now let's receive the Exited message.
    let m = rx.recv().unwrap();
    assert_eq!(*m.get_type(), MessageType::Exited);
    match *m.get_datum() {
        MessageDatum::Void => (), // ok
        _ => { assert!(false, "Unexpected message datum"); }
    }
}

}
<|endoftext|>


<commit_before>struct Gradient {
    start: Vec<i32>,
    steps: Vec<f32>,
    n: i32,
    total: i32,
}

impl Gradient {
    fn to_parts(hex: &str) -> Vec<i32> {
        [0, 2, 4].iter()
                 .map(|&n| i32::from_str_radix(&hex[n..(n + 2)], 16).unwrap())
                 .collect()
    }

    fn to_steps(start: &[i32], stop: &[i32], n: i32) -> Vec<f32> {
        start.iter()
             .zip(stop.iter())
             .map(|(&a, &b)| (a - b) as f32 / (n as f32 - 1.0))
             .collect()
    }

    pub fn new(start: &str, stop: &str, n: i32) -> Gradient {
        let from = Gradient::to_parts(&start);
        let to = Gradient::to_parts(&stop);
        let steps = Gradient::to_steps(&from[..], &to[..], n);

        Gradient{
            start: from,
            steps: steps,
            n: 0,
            total: n,
        }
    }
}

impl Iterator for Gradient {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.n {
            n if n == self.total => None,
            n => {
                let rgb: String = self.start
                    .iter()
                    .zip(self.steps.iter())
                    .map(|(&a, &b)| a - (n as f32 * b) as i32)
                    .map(|i| format!("{:02x}", i))
                    .collect();

                self.n += 1;

                Some(rgb)
            }
        }
    }
}

fn main() {
    // For benchmarking...
    let g = Gradient::new("000000", "ffffff", 10000);
    g.collect::<Vec<String>>();
}

#[test]
fn it_works() {
    let ga = Gradient::new("000000", "ffffff", 16);
    let gb = Gradient::new("ff334c", "d8ff1a", 10);
    let result_a = vec!["000000", "111111", "222222", "333333", "444444",
                        "555555", "666666", "777777", "888888", "999999",
                        "aaaaaa", "bbbbbb", "cccccc", "dddddd", "eeeeee",
                        "ffffff"];
    let result_b = vec!["ff334c", "fb4947", "f76041", "f2773c", "ee8d36",
                        "eaa431", "e5bb2b", "e1d126", "dde820", "d8ff1a"];

    assert_eq!(ga.collect::<Vec<String>>(), result_a.iter().map(|r| r.to_string()).collect::<Vec<String>>());
    assert_eq!(gb.collect::<Vec<String>>(), result_b.iter().map(|r| r.to_string()).collect::<Vec<String>>());
}
<commit_msg>ADded unitlike struct that generates GradientIters<commit_after>struct Gradient;
struct GradientIter {
    start: Vec<i32>,
    steps: Vec<f32>,
    n: i32,
    total: i32,
}

impl Gradient {
    fn to_parts(&self, hex: &str) -> Vec<i32> {
        [0, 2, 4].iter()
                 .map(|&n| i32::from_str_radix(&hex[n..(n + 2)], 16).unwrap())
                 .collect()
    }

    fn to_steps(&self, start: &[i32], stop: &[i32], n: i32) -> Vec<f32> {
        start.iter()
             .zip(stop.iter())
             .map(|(&a, &b)| (a - b) as f32 / (n as f32 - 1.0))
             .collect()
    }

    fn gradient_iter(&self, start: &str, stop: &str, n: i32) -> GradientIter {
        let from = self.to_parts(&start);
        let to = self.to_parts(&stop);
        let steps = self.to_steps(&from[..], &to[..], n);

        GradientIter{
            start: from,
            steps: steps,
            n: 0,
            total: n,
        }
    }
}

impl Iterator for GradientIter {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.n {
            n if n == self.total => None,
            n => {
                let rgb: String = self.start
                    .iter()
                    .zip(self.steps.iter())
                    .map(|(&a, &b)| a - (n as f32 * b) as i32)
                    .map(|i| format!("{:02x}", i))
                    .collect();

                self.n += 1;

                Some(rgb)
            }
        }
    }
}

fn main() {
    // For benchmarking...
    let ga = Gradient.gradient_iter("000000", "ffffff", 10000);
    ga.collect::<Vec<String>>();
}

#[test]
fn it_works() {
    let g = Gradient;
    let ga = g.gradient_iter("000000", "ffffff", 16);
    let gb = g.gradient_iter("ff334c", "d8ff1a", 10);
    let result_a = vec!["000000", "111111", "222222", "333333", "444444",
                        "555555", "666666", "777777", "888888", "999999",
                        "aaaaaa", "bbbbbb", "cccccc", "dddddd", "eeeeee",
                        "ffffff"];
    let result_b = vec!["ff334c", "fb4947", "f76041", "f2773c", "ee8d36",
                        "eaa431", "e5bb2b", "e1d126", "dde820", "d8ff1a"];

    assert_eq!(ga.collect::<Vec<String>>(), result_a.iter().map(|r| r.to_string()).collect::<Vec<String>>());
    assert_eq!(gb.collect::<Vec<String>>(), result_b.iter().map(|r| r.to_string()).collect::<Vec<String>>());
}
<|endoftext|>