<commit_before>#![feature(if_let)]

use std::io::Command;
use std::io::process::InheritFd;
use std::default::Default;

/// Extra configuration to pass to gcc.
pub struct Config {
    /// Directories where gcc will look for header files.
    pub include_directories: Vec<Path>,
    /// Additional definitions (`-DKEY` or `-DKEY=VALUE`).
    pub definitions: Vec<(String, Option<String>)>,
    /// Additional object files to link into the final archive
    pub objects: Vec<Path>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            include_directories: Vec::new(),
            definitions: Vec::new(),
            objects: Vec::new(),
        }
    }
}

fn getenv(v: &str) -> Option<String> {
    use std::os::getenv;
    let r = getenv(v);
    println!("{} = {}", v, r);
    r
}

/// Compile a library from the given set of input C files.
///
/// This will simply compile all files into object files and then assemble them
/// into the output. This will read the standard environment variables to detect
/// cross compilations and such.
///
/// # Example
///
/// ```no_run
/// use std::default::Default;
/// gcc::compile_library("libfoo.a", &Default::default(), &[
///     "foo.c",
///     "bar.c",
/// ]);
/// ```
pub fn compile_library(output: &str, config: &Config, files: &[&str]) {
    assert!(output.starts_with("lib"));
    assert!(output.ends_with(".a"));

    let target = getenv("TARGET").unwrap();
    let opt_level = getenv("OPT_LEVEL").unwrap();

    let mut cmd = Command::new(gcc());
    cmd.arg(format!("-O{}", opt_level));
    cmd.arg("-c");
    cmd.arg("-ffunction-sections").arg("-fdata-sections");
    cmd.args(cflags().as_slice());

    if target.as_slice().contains("-ios") {
        cmd.args(ios_flags(target.as_slice()).as_slice());
    } else {
        if target.as_slice().contains("i686") {
            cmd.arg("-m32");
        } else if target.as_slice().contains("x86_64") {
            cmd.arg("-m64");
        }

        if !target.as_slice().contains("i686") {
            cmd.arg("-fPIC");
        }
    }

    for directory in config.include_directories.iter() {
        cmd.arg("-I").arg(directory);
    }

    for &(ref key, ref value) in config.definitions.iter() {
        if let &Some(ref value) = value {
            cmd.arg(format!("-D{}={}", key, value));
        } else {
            cmd.arg(format!("-D{}", key));
        }
    }

    let src = Path::new(getenv("CARGO_MANIFEST_DIR").unwrap());
    let dst = Path::new(getenv("OUT_DIR").unwrap());
    let mut objects = Vec::new();
    for file in files.iter() {
        let obj = dst.join(*file).with_extension("o");
        std::io::fs::mkdir_recursive(&obj.dir_path(), std::io::USER_RWX).unwrap();
        run(cmd.clone().arg(src.join(*file)).arg("-o").arg(&obj));
        objects.push(obj);
    }

    run(Command::new(ar()).arg("crus")
                          .arg(dst.join(output))
                          .args(objects.as_slice())
                          .args(config.objects.as_slice()));
    println!("cargo:rustc-flags=-L {} -l {}:static",
             dst.display(), output.slice(3, output.len() - 2));
}

fn run(cmd: &mut Command) {
    println!("running: {}", cmd);
    let status = match cmd.stdout(InheritFd(1)).stderr(InheritFd(2)).status() {
        Ok(status) => status,
        Err(e) => panic!("failed to spawn process: {}", e),
    };
    if !status.success() {
        panic!("nonzero exit status: {}", status);
    }
}

fn get_var(var_base: &str) -> Result<String, String> {
    let target = getenv("TARGET")
        .expect("Environment variable 'TARGET' is unset");
    let host = match getenv("HOST") {
            None => { return Err("Environment variable 'HOST' is unset".to_string()); }
            Some(x) => x
        };
    let kind = if host == target { "HOST" } else { "TARGET" };
    let target_u = target.split('-')
        .collect::<Vec<&str>>()
        .connect("_");
    let res = getenv(format!("{}_{}", var_base, target).as_slice())
        .or_else(|| getenv(format!("{}_{}", var_base, target_u).as_slice()))
        .or_else(|| getenv(format!("{}_{}", kind, var_base).as_slice()))
        .or_else(|| getenv(var_base));

    match res {
        Some(res) => Ok(res),
        None => Err("Could not get environment variable".to_string()),
    }
}

fn gcc() -> String {
    get_var("CC").unwrap_or(if cfg!(windows) {
        "gcc".to_string()
    } else {
        "cc".to_string()
    })
}

fn ar() -> String {
    get_var("AR").unwrap_or("ar".to_string())
}

fn cflags() -> Vec<String> {
    get_var("CFLAGS").unwrap_or(String::new())
       .as_slice().words().map(|s| s.to_string())
       .collect()
}

fn ios_flags(target: &str) -> Vec<String> {
    let mut is_device_arch = false;
    let mut res = Vec::new();

    if target.starts_with("arm-") {
        res.push("-arch");
        res.push("armv7");
        is_device_arch = true;
    } else if target.starts_with("arm64-") {
        res.push("-arch");
        res.push("arm64");
        is_device_arch = true;
    } else if target.starts_with("i386-") {
        res.push("-m32");
    } else if target.starts_with("x86_64-") {
        res.push("-m64");
    }

    let sdk = if is_device_arch {"iphoneos"} else {"iphonesimulator"};

    println!("Detecting iOS SDK path for {}", sdk);
    let sdk_path = Command::new("xcrun")
        .arg("--show-sdk-path")
        .arg("--sdk")
        .arg(sdk)
        .stderr(InheritFd(2))
        .output()
        .unwrap()
        .output;

    let sdk_path = String::from_utf8(sdk_path).unwrap();

    res.push("-isysroot");
    res.push(sdk_path.as_slice().trim());

    res.iter().map(|s| s.to_string()).collect::<Vec<_>>()
}
<commit_msg>Remove uneeded feature<commit_after>use std::io::Command;
use std::io::process::InheritFd;
use std::default::Default;

/// Extra configuration to pass to gcc.
pub struct Config {
    /// Directories where gcc will look for header files.
    pub include_directories: Vec<Path>,
    /// Additional definitions (`-DKEY` or `-DKEY=VALUE`).
    pub definitions: Vec<(String, Option<String>)>,
    /// Additional object files to link into the final archive
    pub objects: Vec<Path>,
}

impl Default for Config {
    fn default() -> Config {
        Config {
            include_directories: Vec::new(),
            definitions: Vec::new(),
            objects: Vec::new(),
        }
    }
}

fn getenv(v: &str) -> Option<String> {
    use std::os::getenv;
    let r = getenv(v);
    println!("{} = {}", v, r);
    r
}

/// Compile a library from the given set of input C files.
///
/// This will simply compile all files into object files and then assemble them
/// into the output. This will read the standard environment variables to detect
/// cross compilations and such.
///
/// # Example
///
/// ```no_run
/// use std::default::Default;
/// gcc::compile_library("libfoo.a", &Default::default(), &[
///     "foo.c",
///     "bar.c",
/// ]);
/// ```
pub fn compile_library(output: &str, config: &Config, files: &[&str]) {
    assert!(output.starts_with("lib"));
    assert!(output.ends_with(".a"));

    let target = getenv("TARGET").unwrap();
    let opt_level = getenv("OPT_LEVEL").unwrap();

    let mut cmd = Command::new(gcc());
    cmd.arg(format!("-O{}", opt_level));
    cmd.arg("-c");
    cmd.arg("-ffunction-sections").arg("-fdata-sections");
    cmd.args(cflags().as_slice());

    if target.as_slice().contains("-ios") {
        cmd.args(ios_flags(target.as_slice()).as_slice());
    } else {
        if target.as_slice().contains("i686") {
            cmd.arg("-m32");
        } else if target.as_slice().contains("x86_64") {
            cmd.arg("-m64");
        }

        if !target.as_slice().contains("i686") {
            cmd.arg("-fPIC");
        }
    }

    for directory in config.include_directories.iter() {
        cmd.arg("-I").arg(directory);
    }

    for &(ref key, ref value) in config.definitions.iter() {
        if let &Some(ref value) = value {
            cmd.arg(format!("-D{}={}", key, value));
        } else {
            cmd.arg(format!("-D{}", key));
        }
    }

    let src = Path::new(getenv("CARGO_MANIFEST_DIR").unwrap());
    let dst = Path::new(getenv("OUT_DIR").unwrap());
    let mut objects = Vec::new();
    for file in files.iter() {
        let obj = dst.join(*file).with_extension("o");
        std::io::fs::mkdir_recursive(&obj.dir_path(), std::io::USER_RWX).unwrap();
        run(cmd.clone().arg(src.join(*file)).arg("-o").arg(&obj));
        objects.push(obj);
    }

    run(Command::new(ar()).arg("crus")
                          .arg(dst.join(output))
                          .args(objects.as_slice())
                          .args(config.objects.as_slice()));
    println!("cargo:rustc-flags=-L {} -l {}:static",
             dst.display(), output.slice(3, output.len() - 2));
}

fn run(cmd: &mut Command) {
    println!("running: {}", cmd);
    let status = match cmd.stdout(InheritFd(1)).stderr(InheritFd(2)).status() {
        Ok(status) => status,
        Err(e) => panic!("failed to spawn process: {}", e),
    };
    if !status.success() {
        panic!("nonzero exit status: {}", status);
    }
}

fn get_var(var_base: &str) -> Result<String, String> {
    let target = getenv("TARGET")
        .expect("Environment variable 'TARGET' is unset");
    let host = match getenv("HOST") {
            None => { return Err("Environment variable 'HOST' is unset".to_string()); }
            Some(x) => x
        };
    let kind = if host == target { "HOST" } else { "TARGET" };
    let target_u = target.split('-')
        .collect::<Vec<&str>>()
        .connect("_");
    let res = getenv(format!("{}_{}", var_base, target).as_slice())
        .or_else(|| getenv(format!("{}_{}", var_base, target_u).as_slice()))
        .or_else(|| getenv(format!("{}_{}", kind, var_base).as_slice()))
        .or_else(|| getenv(var_base));

    match res {
        Some(res) => Ok(res),
        None => Err("Could not get environment variable".to_string()),
    }
}

fn gcc() -> String {
    get_var("CC").unwrap_or(if cfg!(windows) {
        "gcc".to_string()
    } else {
        "cc".to_string()
    })
}

fn ar() -> String {
    get_var("AR").unwrap_or("ar".to_string())
}

fn cflags() -> Vec<String> {
    get_var("CFLAGS").unwrap_or(String::new())
       .as_slice().words().map(|s| s.to_string())
       .collect()
}

fn ios_flags(target: &str) -> Vec<String> {
    let mut is_device_arch = false;
    let mut res = Vec::new();

    if target.starts_with("arm-") {
        res.push("-arch");
        res.push("armv7");
        is_device_arch = true;
    } else if target.starts_with("arm64-") {
        res.push("-arch");
        res.push("arm64");
        is_device_arch = true;
    } else if target.starts_with("i386-") {
        res.push("-m32");
    } else if target.starts_with("x86_64-") {
        res.push("-m64");
    }

    let sdk = if is_device_arch {"iphoneos"} else {"iphonesimulator"};

    println!("Detecting iOS SDK path for {}", sdk);
    let sdk_path = Command::new("xcrun")
        .arg("--show-sdk-path")
        .arg("--sdk")
        .arg(sdk)
        .stderr(InheritFd(2))
        .output()
        .unwrap()
        .output;

    let sdk_path = String::from_utf8(sdk_path).unwrap();

    res.push("-isysroot");
    res.push(sdk_path.as_slice().trim());

    res.iter().map(|s| s.to_string()).collect::<Vec<_>>()
}
<|endoftext|>


<commit_before>#![feature(unicode)]

#[derive(Copy)]
pub enum Case {
    Upper,
    Lower
}

pub trait ChangeCase {
    fn to_uppercase(&self) -> Self;
    fn to_lowercase(&self) -> Self;
    fn to_capitalized(&self) -> Self;
    fn to_invertedcase(&self) -> Self;
    fn to_alternatingcase(&self, start_with: Case) -> Self;
}

impl ChangeCase for String {
    fn to_uppercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                result.push(c.to_uppercase());
            }
        }

        result
    }

    fn to_lowercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                result.push(c.to_lowercase());
            }
        }

        result
    }

    fn to_capitalized(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut chars = self.chars();
            result.push(chars.next().unwrap().to_uppercase());

            for c in chars {
                result.push(c.to_lowercase());
            }
        }

        result
    }

    fn to_invertedcase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {

            for c in self.chars() {
                if c.is_uppercase() {
                    result.push(c.to_lowercase());
                } else if c.is_lowercase() {
                    result.push(c.to_uppercase());
                } else {
                    result.push(c);
                }
            }
        }

        result
    }

    fn to_alternatingcase(&self, start_with: Case) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut current_case = start_with;

            for c in self.chars() {
                if c.is_uppercase() || c.is_lowercase() {
                    match current_case {
                        Case::Upper => {
                            result.push(c.to_uppercase());
                            current_case = Case::Lower;
                        },
                        Case::Lower => {
                            result.push(c.to_lowercase());
                            current_case = Case::Upper;
                        }
                    };
                } else {
                    result.push(c);
                }
            }
        }

        result
    }
}

#[test]
fn upper() {
    assert_eq!(String::from_str("Something").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("sOmEtHiNg").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("word word2").to_uppercase(), "WORD WORD2");
}

#[test]
fn lower() {
    assert_eq!(String::from_str("SOMETHING").to_lowercase(), "something");
    assert_eq!(String::from_str("sOmEtHiNg").to_lowercase(), "something");
    assert_eq!(String::from_str("Word WORD2").to_lowercase(), "word word2");
}

#[test]
fn capitalize() {
    assert_eq!(String::from_str("SOMETHING").to_capitalized(), "Something");
    assert_eq!(String::from_str("sOmEtHiNg").to_capitalized(), "Something");
    assert_eq!(String::from_str("Word WORD2").to_capitalized(), "Word word2");
}

#[test]
fn swapped() {
    assert_eq!(String::from_str("SOMETHING").to_invertedcase(), "something");
    assert_eq!(String::from_str("SoMeThInG").to_invertedcase(), "sOmEtHiNg");
    assert_eq!(String::from_str("Some WorD2").to_invertedcase(), "sOME wORd2");
}

#[test]
fn alternating() {
    assert_eq!(String::from_str("SOMETHING").to_alternatingcase(Case::Lower), "sOmEtHiNg");
    assert_eq!(String::from_str("SOMETHING").to_alternatingcase(Case::Upper), "SoMeThInG");
    assert_eq!(String::from_str("som3thing").to_alternatingcase(Case::Lower), "sOm3ThInG");
    assert_eq!(String::from_str("som3thing").to_alternatingcase(Case::Upper), "SoM3tHiNg");
    assert_eq!(String::from_str("some word").to_alternatingcase(Case::Lower), "sOmE wOrD");
}
<commit_msg>Add collections feature.<commit_after>#![feature(unicode, collections)]

#[derive(Copy)]
pub enum Case {
    Upper,
    Lower
}

pub trait ChangeCase {
    fn to_uppercase(&self) -> Self;
    fn to_lowercase(&self) -> Self;
    fn to_capitalized(&self) -> Self;
    fn to_invertedcase(&self) -> Self;
    fn to_alternatingcase(&self, start_with: Case) -> Self;
}

impl ChangeCase for String {
    fn to_uppercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                result.push(c.to_uppercase());
            }
        }

        result
    }

    fn to_lowercase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            for c in self.chars() {
                result.push(c.to_lowercase());
            }
        }

        result
    }

    fn to_capitalized(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut chars = self.chars();
            result.push(chars.next().unwrap().to_uppercase());

            for c in chars {
                result.push(c.to_lowercase());
            }
        }

        result
    }

    fn to_invertedcase(&self) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {

            for c in self.chars() {
                if c.is_uppercase() {
                    result.push(c.to_lowercase());
                } else if c.is_lowercase() {
                    result.push(c.to_uppercase());
                } else {
                    result.push(c);
                }
            }
        }

        result
    }

    fn to_alternatingcase(&self, start_with: Case) -> String {
        if self.is_empty() {
            return String::new();
        }

        let mut result = String::with_capacity(self.len());

        {
            let mut current_case = start_with;

            for c in self.chars() {
                if c.is_uppercase() || c.is_lowercase() {
                    match current_case {
                        Case::Upper => {
                            result.push(c.to_uppercase());
                            current_case = Case::Lower;
                        },
                        Case::Lower => {
                            result.push(c.to_lowercase());
                            current_case = Case::Upper;
                        }
                    };
                } else {
                    result.push(c);
                }
            }
        }

        result
    }
}

#[test]
fn upper() {
    assert_eq!(String::from_str("Something").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("sOmEtHiNg").to_uppercase(), "SOMETHING");
    assert_eq!(String::from_str("word word2").to_uppercase(), "WORD WORD2");
}

#[test]
fn lower() {
    assert_eq!(String::from_str("SOMETHING").to_lowercase(), "something");
    assert_eq!(String::from_str("sOmEtHiNg").to_lowercase(), "something");
    assert_eq!(String::from_str("Word WORD2").to_lowercase(), "word word2");
}

#[test]
fn capitalize() {
    assert_eq!(String::from_str("SOMETHING").to_capitalized(), "Something");
    assert_eq!(String::from_str("sOmEtHiNg").to_capitalized(), "Something");
    assert_eq!(String::from_str("Word WORD2").to_capitalized(), "Word word2");
}

#[test]
fn swapped() {
    assert_eq!(String::from_str("SOMETHING").to_invertedcase(), "something");
    assert_eq!(String::from_str("SoMeThInG").to_invertedcase(), "sOmEtHiNg");
    assert_eq!(String::from_str("Some WorD2").to_invertedcase(), "sOME wORd2");
}

#[test]
fn alternating() {
    assert_eq!(String::from_str("SOMETHING").to_alternatingcase(Case::Lower), "sOmEtHiNg");
    assert_eq!(String::from_str("SOMETHING").to_alternatingcase(Case::Upper), "SoMeThInG");
    assert_eq!(String::from_str("som3thing").to_alternatingcase(Case::Lower), "sOm3ThInG");
    assert_eq!(String::from_str("som3thing").to_alternatingcase(Case::Upper), "SoM3tHiNg");
    assert_eq!(String::from_str("some word").to_alternatingcase(Case::Lower), "sOmE wOrD");
}
<|endoftext|>


<commit_before>use eventual::{self, Async};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
use std::thread;
use std::io::{Read, Seek};
use vorbis;

use audio_decrypt::AudioDecrypt;
use audio_backend::Sink;
use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session};
use util::{self, SpotifyId, Subfile};
use spirc::PlayStatus;

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms as f64 / 1000f64)
}

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell().map(|t| (t * 1000f64) as i64)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell()
}

pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;

pub struct Player {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    commands: mpsc::Sender<PlayerCommand>,
}

#[derive(Clone)]
pub struct PlayerState {
    status: PlayStatus,
    position_ms: u32,
    position_measured_at: i64,
    update_time: i64,
    volume: u16,

    end_of_track: bool,
}

struct PlayerInternal {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

#[derive(Debug)]
enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Volume(u16),
    Stop,
    Seek(u32),
}

impl Player {
    pub fn new<F>(session: Session, sink_builder: F) -> Player
        where F: FnOnce() -> Box<Sink> + Send + 'static {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new(Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            volume: 0xFFFF,
            end_of_track: false,
        }));

        let observers = Arc::new(Mutex::new(Vec::new()));

        let internal = PlayerInternal {
            session: session,
            commands: cmd_rx,
            state: state.clone(),
            observers: observers.clone(),
        };

        thread::spawn(move || internal.run(sink_builder()));

        Player {
            commands: cmd_tx,
            state: state,
            observers: observers,
        }
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.send(cmd).unwrap();
    }

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    pub fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    pub fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    pub fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    pub fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }

    pub fn state(&self) -> PlayerState {
        self.state.lock().unwrap().clone()
    }

    pub fn volume(&self, vol: u16) {
        self.command(PlayerCommand::Volume(vol));
    }

    pub fn add_observer(&self, observer: PlayerObserver) {
        self.observers.lock().unwrap().push(observer);
    }
}

fn apply_volume(volume: u16, data: &[i16]) -> Cow<[i16]> {
    // Fast path when volume is 100%
    if volume == 0xFFFF {
        Cow::Borrowed(data)
    } else {
        Cow::Owned(data.iter()
                       .map(|&x| {
                           (x as i32
                            * volume as i32
                            / 0xFFFF) as i16
                       })
                       .collect())
    }
}

impl PlayerInternal {
    fn run(self, sink: Box<Sink>) {
        let mut decoder = None;

        loop {
            let playing = self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay;
            let cmd = if playing {
                self.commands.try_recv().ok()
            } else {
                Some(self.commands.recv().unwrap())
            };

            match cmd {
                Some(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            sink.stop().unwrap();
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        true
                    });
                    drop(decoder);

                    let mut track = self.session.metadata::<Track>(track_id).await().unwrap();

                    if !track.available {
                        let alternatives = track.alternatives
                                                .iter()
                                                .map(|alt_id| {
                                                    self.session.metadata::<Track>(*alt_id)
                                                })
                                                .collect::<Vec<TrackRef>>();

                        track = eventual::sequence(alternatives.into_iter())
                                    .iter()
                                    .find(|alt| alt.available)
                                    .unwrap();
                    }

                    let format = match self.session.config().bitrate {
                        Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
                        Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
                        Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
                    };
                    let (file_id, _) = track.files.into_iter().find(|&(_, f)| f == format).unwrap();

                    let key = self.session.audio_key(track.id, file_id).await().unwrap();
                    decoder = Some(
                        vorbis::Decoder::new(
                        Subfile::new(
                        AudioDecrypt::new(key,
                        self.session.audio_file(file_id)), 0xa7)).unwrap());

                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();

                    self.update(|state| {
                        state.status = if play {
                            sink.start().unwrap();
                            PlayStatus::kPlayStatusPlay
                        } else {
                            PlayStatus::kPlayStatusPause
                        };
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                    info!("Load Done");
                }
                Some(PlayerCommand::Seek(position)) => {
                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.start().unwrap();
                }
                Some(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.update_time = util::now_ms();
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                }
                Some(PlayerCommand::Volume(vol)) => {
                    self.update(|state| {
                        state.volume = vol;
                        true
                    });
                }
                Some(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        state.position_ms = 0;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    decoder = None;
                }
                None => (),
            }

            if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                let packet = decoder.as_mut().unwrap().packets().next();

                match packet {
                    Some(Ok(packet)) => {
                        let buffer = apply_volume(self.state.lock().unwrap().volume,
                                                  &packet.data);
                        sink.write(&buffer).unwrap();
                    }
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            true
                        });

                        sink.stop().unwrap();
                        decoder = None;
                    }
                }
            }
        }
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
    {
        let mut guard = self.state.lock().unwrap();
        let update = f(&mut guard);

        let observers = self.observers.lock().unwrap();
        if update {
            guard.update_time = util::now_ms();
            let state = guard.clone();
            drop(guard);

            for observer in observers.iter() {
                observer(&state);
            }
        }
    }
}

impl PlayerState {
    pub fn status(&self) -> PlayStatus {
        self.status
    }

    pub fn position(&self) -> (u32, i64) {
        (self.position_ms, self.position_measured_at)
    }

    pub fn volume(&self) -> u16 {
        self.volume
    }

    pub fn update_time(&self) -> i64 {
        self.update_time
    }

    pub fn end_of_track(&self) -> bool {
        self.end_of_track
    }
}
<commit_msg>player: Add seek_at command for precise seeking<commit_after>use eventual::{self, Async};
use std::borrow::Cow;
use std::sync::{mpsc, Mutex, Arc, MutexGuard};
use std::thread;
use std::io::{Read, Seek};
use vorbis;

use audio_decrypt::AudioDecrypt;
use audio_backend::Sink;
use metadata::{FileFormat, Track, TrackRef};
use session::{Bitrate, Session};
use util::{self, SpotifyId, Subfile};
pub use spirc::PlayStatus;

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms as f64 / 1000f64)
}

#[cfg(not(feature = "with-tremor"))]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell().map(|t| (t * 1000f64) as i64)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_seek_ms<R>(decoder: &mut vorbis::Decoder<R>, ms: i64) -> Result<(), vorbis::VorbisError> where R: Read + Seek {
    decoder.time_seek(ms)
}

#[cfg(feature = "with-tremor")]
fn vorbis_time_tell_ms<R>(decoder: &mut vorbis::Decoder<R>) -> Result<i64, vorbis::VorbisError> where R: Read + Seek {
    decoder.time_tell()
}

pub type PlayerObserver = Box<Fn(&PlayerState) + Send>;

#[derive(Clone)]
pub struct Player {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    commands: mpsc::Sender<PlayerCommand>,
}

#[derive(Clone)]
pub struct PlayerState {
    pub status: PlayStatus,
    pub position_ms: u32,
    pub position_measured_at: i64,
    pub update_time: i64,
    pub volume: u16,
    pub track: Option<SpotifyId>,

    pub end_of_track: bool,
}

struct PlayerInternal {
    state: Arc<Mutex<PlayerState>>,
    observers: Arc<Mutex<Vec<PlayerObserver>>>,

    session: Session,
    commands: mpsc::Receiver<PlayerCommand>,
}

#[derive(Debug)]
enum PlayerCommand {
    Load(SpotifyId, bool, u32),
    Play,
    Pause,
    Volume(u16),
    Stop,
    Seek(u32),
    SeekAt(u32, i64),
}

impl Player {
    pub fn new<F>(session: Session, sink_builder: F) -> Player
        where F: FnOnce() -> Box<Sink> + Send + 'static {
        let (cmd_tx, cmd_rx) = mpsc::channel();

        let state = Arc::new(Mutex::new(PlayerState {
            status: PlayStatus::kPlayStatusStop,
            position_ms: 0,
            position_measured_at: 0,
            update_time: util::now_ms(),
            volume: 0xFFFF,
            track: None,
            end_of_track: false,
        }));

        let observers = Arc::new(Mutex::new(Vec::new()));

        let internal = PlayerInternal {
            session: session,
            commands: cmd_rx,
            state: state.clone(),
            observers: observers.clone(),
        };

        thread::spawn(move || internal.run(sink_builder()));

        Player {
            commands: cmd_tx,
            state: state,
            observers: observers,
        }
    }

    fn command(&self, cmd: PlayerCommand) {
        self.commands.send(cmd).unwrap();
    }

    pub fn load(&self, track: SpotifyId, start_playing: bool, position_ms: u32) {
        self.command(PlayerCommand::Load(track, start_playing, position_ms));
    }

    pub fn play(&self) {
        self.command(PlayerCommand::Play)
    }

    pub fn pause(&self) {
        self.command(PlayerCommand::Pause)
    }

    pub fn stop(&self) {
        self.command(PlayerCommand::Stop)
    }

    pub fn seek(&self, position_ms: u32) {
        self.command(PlayerCommand::Seek(position_ms));
    }

    pub fn seek_at(&self, position_ms: u32, measured_at: i64) {
        self.command(PlayerCommand::SeekAt(position_ms, measured_at));
    }

    pub fn state(&self) -> PlayerState {
        self.state.lock().unwrap().clone()
    }

    pub fn volume(&self, vol: u16) {
        self.command(PlayerCommand::Volume(vol));
    }

    pub fn add_observer(&self, observer: PlayerObserver) {
        self.observers.lock().unwrap().push(observer);
    }
}

fn apply_volume(volume: u16, data: &[i16]) -> Cow<[i16]> {
    // Fast path when volume is 100%
    if volume == 0xFFFF {
        Cow::Borrowed(data)
    } else {
        Cow::Owned(data.iter()
                       .map(|&x| {
                           (x as i32
                            * volume as i32
                            / 0xFFFF) as i16
                       })
                       .collect())
    }
}

impl PlayerInternal {
    fn run(self, sink: Box<Sink>) {
        let mut decoder = None;

        loop {
            let playing = self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay;
            let cmd = if playing {
                self.commands.try_recv().ok()
            } else {
                Some(self.commands.recv().unwrap())
            };

            match cmd {
                Some(PlayerCommand::Load(track_id, play, position)) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            sink.stop().unwrap();
                        }
                        state.end_of_track = false;
                        state.status = PlayStatus::kPlayStatusPause;
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();
                        state.track = Some(track_id);
                        true
                    });
                    drop(decoder);

                    let mut track = self.session.metadata::<Track>(track_id).await().unwrap();

                    if !track.available {
                        let alternatives = track.alternatives
                                                .iter()
                                                .map(|alt_id| {
                                                    self.session.metadata::<Track>(*alt_id)
                                                })
                                                .collect::<Vec<TrackRef>>();

                        track = eventual::sequence(alternatives.into_iter())
                                    .iter()
                                    .find(|alt| alt.available)
                                    .unwrap();
                    }

                    let format = match self.session.config().bitrate {
                        Bitrate::Bitrate96 => FileFormat::OGG_VORBIS_96,
                        Bitrate::Bitrate160 => FileFormat::OGG_VORBIS_160,
                        Bitrate::Bitrate320 => FileFormat::OGG_VORBIS_320,
                    };
                    let (file_id, _) = track.files.into_iter().find(|&(_, f)| f == format).unwrap();

                    let key = self.session.audio_key(track.id, file_id).await().unwrap();
                    decoder = Some(
                        vorbis::Decoder::new(
                        Subfile::new(
                        AudioDecrypt::new(key,
                        self.session.audio_file(file_id)), 0xa7)).unwrap());

                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();

                    self.update(|state| {
                        state.status = if play {
                            sink.start().unwrap();
                            PlayStatus::kPlayStatusPlay
                        } else {
                            PlayStatus::kPlayStatusPause
                        };
                        state.position_ms = position;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                    info!("Load Done");
                }
                Some(PlayerCommand::Seek(position)) => {
                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        true
                    });
                }
                Some(PlayerCommand::SeekAt(position, measured_at)) => {
                    let position = (util::now_ms() - measured_at + position as i64) as u32;

                    let before = util::now_ms();
                    vorbis_time_seek_ms(decoder.as_mut().unwrap(), position as i64).unwrap();
                    self.update(|state| {
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();

                        println!("SEEK: {} {} {}", before, util::now_ms(), util::now_ms() - before);

                        true
                    });
                }
                Some(PlayerCommand::Play) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPlay;
                        state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.start().unwrap();
                }
                Some(PlayerCommand::Pause) => {
                    self.update(|state| {
                        state.status = PlayStatus::kPlayStatusPause;
                        state.update_time = util::now_ms();
                        state.position_ms = decoder.as_mut().map(|d| vorbis_time_tell_ms(d).unwrap()).unwrap_or(0) as u32;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                }
                Some(PlayerCommand::Volume(vol)) => {
                    self.update(|state| {
                        state.volume = vol;
                        true
                    });
                }
                Some(PlayerCommand::Stop) => {
                    self.update(|state| {
                        if state.status == PlayStatus::kPlayStatusPlay {
                            state.status = PlayStatus::kPlayStatusPause;
                        }
                        state.position_ms = 0;
                        state.position_measured_at = util::now_ms();
                        true
                    });

                    sink.stop().unwrap();
                    decoder = None;
                }
                None => (),
            }

            if self.state.lock().unwrap().status == PlayStatus::kPlayStatusPlay {
                let packet = decoder.as_mut().unwrap().packets().next();

                match packet {
                    Some(Ok(packet)) => {
                        let buffer = apply_volume(self.state.lock().unwrap().volume,
                                                  &packet.data);
                        sink.write(&buffer).unwrap();

                        self.update(|state| {
                            state.position_ms = vorbis_time_tell_ms(decoder.as_mut().unwrap()).unwrap() as u32;
                            state.position_measured_at = util::now_ms();

                            false
                        });
                    }
                    Some(Err(vorbis::VorbisError::Hole)) => (),
                    Some(Err(e)) => panic!("Vorbis error {:?}", e),
                    None => {
                        self.update(|state| {
                            state.status = PlayStatus::kPlayStatusStop;
                            state.end_of_track = true;
                            true
                        });

                        sink.stop().unwrap();
                        decoder = None;
                    }
                }
            }
        }
    }

    fn update<F>(&self, f: F)
        where F: FnOnce(&mut MutexGuard<PlayerState>) -> bool
    {
        let mut guard = self.state.lock().unwrap();
        let update = f(&mut guard);

        let observers = self.observers.lock().unwrap();
        if update {
            guard.update_time = util::now_ms();
            let state = guard.clone();
            drop(guard);

            for observer in observers.iter() {
                observer(&state);
            }
        }
    }
}

impl PlayerState {
    pub fn status(&self) -> PlayStatus {
        self.status
    }

    pub fn position(&self) -> (u32, i64) {
        (self.position_ms, self.position_measured_at)
    }

    pub fn volume(&self) -> u16 {
        self.volume
    }

    pub fn update_time(&self) -> i64 {
        self.update_time
    }

    pub fn end_of_track(&self) -> bool {
        self.end_of_track
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

const cobalt_yml: &'static [u8] = b"name: cobalt blog
source: \".\"
dest: \"build\"
ignore:
  - .git/*
  - build/*
";

const default_liquid: &'static [u8] = b"<!DOCTYPE html>

        <meta charset=\"utf-8\">
        {% if is_post %}
          <title>{{ title }}</title>
        {% else %}
       	  <title>Cobalt.rs Blog</title>
        {% endif %}

      {% if is_post %}
        {% include '_layouts/post.liquid' %}
      {% else %}
        {{ content }}
      {% endif %}

";

const post_liquid: &'static [u8] = b"

{{ title }}

    {{content}}

";

const post_1_md: &'static [u8] = b"extends: default.liquid

title: First Post
date: 14 January 2016 21:00:30 -0500
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const index_liquid: &'static [u8] = b"extends: default.liquid
---

Blog!

    {% for post in posts %}

{{post.title}}

{{ post.title }}

    {% endfor %}

";

use std::path::Path;
use std::fs::{DirBuilder, OpenOptions};
use std::io::Write;
use error::Result;
use config::Config;

pub fn create_new_project<P: AsRef<Path>>(dest: P) -> Result<()> {
    let dest = dest.as_ref();

    try!(create_folder(&dest));

    try!(create_file(&dest.join(".cobalt.yml"), cobalt_yml));
    try!(create_file(&dest.join("index.liquid"), index_liquid));

    try!(create_folder(&dest.join("_layouts")));
    try!(create_file(&dest.join("_layouts/default.liquid"), default_liquid));
    try!(create_file(&dest.join("_layouts/post.liquid"), post_liquid));

    try!(create_folder(&dest.join("posts")));
    try!(create_file(&dest.join("posts/post-1.md"), post_1_md));

    Ok(())
}

pub fn create_new_document(doc_type: &str, name: &str, config: &Config) -> Result<()> {
    let path = Path::new(&config.source);
    let full_path = &path.join(&config.posts).join(name);

    match doc_type {
        "page" => create_file(name, index_liquid)?,
        "post" => create_file(full_path, post_1_md)?,
        _ => bail!("Can only create post or page")
    }

    Ok(())
}

fn create_folder<P: AsRef<Path>>(path: P) -> Result<()> {
    trace!("Creating folder {:?}", &path.as_ref());

    try!(DirBuilder::new().recursive(true).create(path));

    Ok(())
}

fn create_file<P: AsRef<Path>>(name: P, content: &[u8]) -> Result<()> {
    trace!("Creating file {:?}", &name.as_ref());

    let mut file = try!(OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(name));

    file.write_all(content)?;

    Ok(())
}
<commit_msg>Better bail message<commit_after>#![allow(non_upper_case_globals)]

const cobalt_yml: &'static [u8] = b"name: cobalt blog
source: \".\"
dest: \"build\"
ignore:
  - .git/*
  - build/*
";

const default_liquid: &'static [u8] = b"<!DOCTYPE html>

        <meta charset=\"utf-8\">
        {% if is_post %}
          <title>{{ title }}</title>
        {% else %}
       	  <title>Cobalt.rs Blog</title>
        {% endif %}

      {% if is_post %}
        {% include '_layouts/post.liquid' %}
      {% else %}
        {{ content }}
      {% endif %}

";

const post_liquid: &'static [u8] = b"

{{ title }}

    {{content}}

";

const post_1_md: &'static [u8] = b"extends: default.liquid

title: First Post
date: 14 January 2016 21:00:30 -0500
---

# This is our first Post!

Welcome to the first post ever on cobalt.rs!
";

const index_liquid: &'static [u8] = b"extends: default.liquid
---

Blog!

    {% for post in posts %}

{{post.title}}

{{ post.title }}

    {% endfor %}

";

use std::path::Path;
use std::fs::{DirBuilder, OpenOptions};
use std::io::Write;
use error::Result;
use config::Config;

pub fn create_new_project<P: AsRef<Path>>(dest: P) -> Result<()> {
    let dest = dest.as_ref();

    try!(create_folder(&dest));

    try!(create_file(&dest.join(".cobalt.yml"), cobalt_yml));
    try!(create_file(&dest.join("index.liquid"), index_liquid));

    try!(create_folder(&dest.join("_layouts")));
    try!(create_file(&dest.join("_layouts/default.liquid"), default_liquid));
    try!(create_file(&dest.join("_layouts/post.liquid"), post_liquid));

    try!(create_folder(&dest.join("posts")));
    try!(create_file(&dest.join("posts/post-1.md"), post_1_md));

    Ok(())
}

pub fn create_new_document(doc_type: &str, name: &str, config: &Config) -> Result<()> {
    let path = Path::new(&config.source);
    let full_path = &path.join(&config.posts).join(name);

    match doc_type {
        "page" => create_file(name, index_liquid)?,
        "post" => create_file(full_path, post_1_md)?,
        _ => bail!("Unsupported document type {}", doc_type)
    }

    Ok(())
}

fn create_folder<P: AsRef<Path>>(path: P) -> Result<()> {
    trace!("Creating folder {:?}", &path.as_ref());

    try!(DirBuilder::new().recursive(true).create(path));

    Ok(())
}

fn create_file<P: AsRef<Path>>(name: P, content: &[u8]) -> Result<()> {
    trace!("Creating file {:?}", &name.as_ref());

    let mut file = try!(OpenOptions::new()
        .write(true)
        .create_new(true)
        .open(name));

    file.write_all(content)?;

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::fmt;

use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
use memchr::memchr;

/// A prefix extracted from a compiled regular expression.
///
/// A regex prefix is a set of literal strings that *must* be matched at the
/// beginning of a regex in order for the entire regex to match.
///
/// There are a variety of ways to efficiently scan the search text for a
/// prefix. Currently, there are three implemented:
///
/// 1. The prefix is a single byte. Just use memchr.
/// 2. If the prefix is a set of two or more single byte prefixes, then
///    a single sparse map is created. Checking if there is a match is a lookup
///    in this map for each byte in the search text.
/// 3. In all other cases, build an Aho-Corasick automaton.
///
/// It's possible that there's room here for other substring algorithms,
/// such as Boyer-Moore for single-set prefixes greater than 1, or Rabin-Karp
/// for small sets of same-length prefixes.
#[derive(Clone)]
pub enum Prefix {
    /// No prefixes. (Never advances through the input.)
    Empty,
    /// A single byte prefix.
    Byte(u8),
    /// A set of two or more single byte prefixes.
    /// This could be reduced to a bitset, which would use only 8 bytes,
    /// but I don't think we care.
    Bytes {
        chars: Vec<u8>,
        sparse: Vec<bool>,
    },
    Single(SingleSearch),
    /// A full Aho-Corasick DFA automaton.
    Automaton(FullAcAutomaton),
}

impl Prefix {
    /// Create a new prefix matching machine.
    pub fn new(mut pfxs: Vec<String>) -> Prefix {
        if pfxs.len() == 0 || pfxs[0].len() == 0 {
            Prefix::Empty
        } else if pfxs.len() == 1 && pfxs[0].len() == 1 {
            Prefix::Byte(pfxs[0].as_bytes()[0])
        } else if pfxs.len() >= 2 && pfxs.iter().all(|s| s.len() == 1) {
            let mut set = vec![false; 256];
            let mut chars = vec![];
            for p in pfxs {
                chars.push(p.as_bytes()[0]);
                set[p.as_bytes()[0] as usize] = true;
            }
            Prefix::Bytes { chars: chars, sparse: set }
        } else if pfxs.len() == 1 {
            Prefix::Single(SingleSearch::new(pfxs.pop().unwrap()))
        } else {
            Prefix::Automaton(AcAutomaton::new(pfxs).into_full())
        }
    }

    /// Find the position of a prefix in `haystack` if it exists.
    ///
    /// In the matching engines, we only actually need the starting index
    /// because the prefix is used to only skip ahead---the matching engine
    /// still needs to run over the prefix input. However, we return the ending
    /// location as well in case the prefix corresponds to the entire regex,
    /// in which case, you need the end of the match.
    pub fn find(&self, haystack: &str) -> Option<(usize, usize)> {
        use self::Prefix::*;
        match *self {
            Empty => Some((0, 0)),
            Byte(b) => memchr(b, haystack.as_bytes()).map(|i| (i, i+1)),
            Bytes { ref sparse, .. } => {
                find_singles(sparse, haystack.as_bytes())
            }
            Single(ref searcher) => {
                searcher.find(haystack).map(|i| (i, i + searcher.pat.len()))
            }
            Automaton(ref aut) => {
                aut.find(haystack).next().map(|m| (m.start, m.end))
            }
        }
    }

    /// Returns true iff this prefix is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of prefixes in this machine.
    pub fn len(&self) -> usize {
        match *self {
            Prefix::Empty => 0,
            Prefix::Byte(_) => 1,
            Prefix::Bytes { ref chars, .. } => chars.len(),
            Prefix::Single(_) => 1,
            Prefix::Automaton(ref aut) => aut.len(),
        }
    }

    /// Returns true iff the prefix match preserves priority.
    ///
    /// For example, given the alternation `ab|a` and the target string `ab`,
    /// does the prefix machine guarantee that `ab` will match? (A full
    /// Aho-Corasick automaton does not!)
    pub fn preserves_priority(&self) -> bool {
        match *self {
            Prefix::Empty => true,
            Prefix::Byte(_) => true,
            Prefix::Bytes{..} => true,
            Prefix::Single(_) => true,
            Prefix::Automaton(ref aut) => {
                // Okay, so the automaton can respect priority in one
                // particular case: when every pattern is of the same length.
                // The trick is that the automaton will report the leftmost
                // match, which in this case, corresponds to the correct
                // match for the regex engine. If any other alternate matches
                // at the same position, then they must be exactly equivalent.

                // Guaranteed at least one prefix by construction, so use
                // that for the length.
                aut.patterns().iter().all(|p| p.len() == aut.pattern(0).len())
            }
        }
    }

    /// Returns all of the prefixes participating in this machine.
    ///
    /// For debug/testing only! (It allocates.)
    #[allow(dead_code)]
    pub fn prefixes(&self) -> Vec<String> {
        match *self {
            Prefix::Empty => vec![],
            Prefix::Byte(b) => vec![format!("{}", b as char)],
            Prefix::Bytes { ref chars, .. } => {
                chars.iter().map(|&b| format!("{}", b as char)).collect()
            }
            Prefix::Single(ref searcher) => vec![searcher.pat.clone()],
            Prefix::Automaton(ref aut) => aut.patterns().to_vec(),
        }
    }
}

/// Provides an implementation of fast subtring search.
///
/// In particular, this uses Boyer-Moore-Horspool with Tim Raita's twist:
/// https://en.wikipedia.org/wiki/Raita_Algorithm
///
/// I'm skeptical of the utility here, because benchmarks suggest that it is
/// difficult to beat Aho-Corasick on random text. Namely, both algorithms are
/// dominated by the performance of `memchr` for the leading byte prefix.
/// With that said, BMH does seem to surpass AC when the search text gets
/// longer (see the `easy0_1MB` vs. `easy1_1MB` benchmarks).
///
/// More analysis needs to be done to test this on different search texts.
#[derive(Clone, Debug)]
struct SingleSearch {
    pat: String,
    shift: Vec<usize>,
}

impl SingleSearch {
    fn new(pat: String) -> SingleSearch {
        assert!(pat.len() >= 1);
        let mut shift = vec![pat.len(); 256];
        for i in 0..(pat.len() - 1) {
            shift[pat.as_bytes()[i] as usize] = pat.len() - i - 1;
        }
        SingleSearch {
            pat: pat,
            shift: shift,
        }
    }

    fn find(&self, haystack: &str) -> Option<usize> {
        let pat = self.pat.as_bytes();
        let haystack = haystack.as_bytes();
        if haystack.len() < pat.len() {
            return None;
        }
        let mut i = match memchr(pat[0], haystack) {
            None => return None,
            Some(i) => i,
        };
        while i <= haystack.len() - pat.len() {
            let b = haystack[i + pat.len() - 1];
            if b == pat[pat.len() - 1]
               && haystack[i] == pat[0]
               && haystack[i + (pat.len() / 2)] == pat[pat.len() / 2]
               && pat == &haystack[i..i + pat.len()] {
                return Some(i);
            }
            i += self.shift[b as usize];
            i += match memchr(pat[0], &haystack[i..]) {
                None => return None,
                Some(i) => i,
            };
        }
        None
    }
}

/// A quick scan for multiple single byte prefixes using a sparse map.
fn find_singles(sparse: &[bool], haystack: &[u8]) -> Option<(usize, usize)> {
    // TODO: Improve this with ideas found in jetscii crate.
    for (hi, &b) in haystack.iter().enumerate() {
        if sparse[b as usize] {
            return Some((hi, hi+1));
        }
    }
    None
}

impl fmt::Debug for Prefix {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Prefix::Empty => write!(f, "Empty"),
            Prefix::Byte(b) => write!(f, "{:?}", b as char),
            Prefix::Bytes { ref chars, .. } => {
                let chars: Vec<String> =
                    chars.iter()
                         .map(|&c| format!("{:?}", c as char))
                         .collect();
                write!(f, "{}", chars.connect(", "))
            }
            Prefix::Single(ref searcher) => write!(f, "{:?}", searcher),
            Prefix::Automaton(ref aut) => write!(f, "{:?}", aut),
        }
    }
}
<commit_msg>Suppress 1.3 deprecation warning<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::fmt;

use aho_corasick::{Automaton, AcAutomaton, FullAcAutomaton};
use memchr::memchr;

/// A prefix extracted from a compiled regular expression.
///
/// A regex prefix is a set of literal strings that *must* be matched at the
/// beginning of a regex in order for the entire regex to match.
///
/// There are a variety of ways to efficiently scan the search text for a
/// prefix. Currently, there are three implemented:
///
/// 1. The prefix is a single byte. Just use memchr.
/// 2. If the prefix is a set of two or more single byte prefixes, then
///    a single sparse map is created. Checking if there is a match is a lookup
///    in this map for each byte in the search text.
/// 3. In all other cases, build an Aho-Corasick automaton.
///
/// It's possible that there's room here for other substring algorithms,
/// such as Boyer-Moore for single-set prefixes greater than 1, or Rabin-Karp
/// for small sets of same-length prefixes.
#[derive(Clone)]
pub enum Prefix {
    /// No prefixes. (Never advances through the input.)
    Empty,
    /// A single byte prefix.
    Byte(u8),
    /// A set of two or more single byte prefixes.
    /// This could be reduced to a bitset, which would use only 8 bytes,
    /// but I don't think we care.
    Bytes {
        chars: Vec<u8>,
        sparse: Vec<bool>,
    },
    Single(SingleSearch),
    /// A full Aho-Corasick DFA automaton.
    Automaton(FullAcAutomaton),
}

impl Prefix {
    /// Create a new prefix matching machine.
    pub fn new(mut pfxs: Vec<String>) -> Prefix {
        if pfxs.len() == 0 || pfxs[0].len() == 0 {
            Prefix::Empty
        } else if pfxs.len() == 1 && pfxs[0].len() == 1 {
            Prefix::Byte(pfxs[0].as_bytes()[0])
        } else if pfxs.len() >= 2 && pfxs.iter().all(|s| s.len() == 1) {
            let mut set = vec![false; 256];
            let mut chars = vec![];
            for p in pfxs {
                chars.push(p.as_bytes()[0]);
                set[p.as_bytes()[0] as usize] = true;
            }
            Prefix::Bytes { chars: chars, sparse: set }
        } else if pfxs.len() == 1 {
            Prefix::Single(SingleSearch::new(pfxs.pop().unwrap()))
        } else {
            Prefix::Automaton(AcAutomaton::new(pfxs).into_full())
        }
    }

    /// Find the position of a prefix in `haystack` if it exists.
    ///
    /// In the matching engines, we only actually need the starting index
    /// because the prefix is used to only skip ahead---the matching engine
    /// still needs to run over the prefix input. However, we return the ending
    /// location as well in case the prefix corresponds to the entire regex,
    /// in which case, you need the end of the match.
    pub fn find(&self, haystack: &str) -> Option<(usize, usize)> {
        use self::Prefix::*;
        match *self {
            Empty => Some((0, 0)),
            Byte(b) => memchr(b, haystack.as_bytes()).map(|i| (i, i+1)),
            Bytes { ref sparse, .. } => {
                find_singles(sparse, haystack.as_bytes())
            }
            Single(ref searcher) => {
                searcher.find(haystack).map(|i| (i, i + searcher.pat.len()))
            }
            Automaton(ref aut) => {
                aut.find(haystack).next().map(|m| (m.start, m.end))
            }
        }
    }

    /// Returns true iff this prefix is empty.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of prefixes in this machine.
    pub fn len(&self) -> usize {
        match *self {
            Prefix::Empty => 0,
            Prefix::Byte(_) => 1,
            Prefix::Bytes { ref chars, .. } => chars.len(),
            Prefix::Single(_) => 1,
            Prefix::Automaton(ref aut) => aut.len(),
        }
    }

    /// Returns true iff the prefix match preserves priority.
    ///
    /// For example, given the alternation `ab|a` and the target string `ab`,
    /// does the prefix machine guarantee that `ab` will match? (A full
    /// Aho-Corasick automaton does not!)
    pub fn preserves_priority(&self) -> bool {
        match *self {
            Prefix::Empty => true,
            Prefix::Byte(_) => true,
            Prefix::Bytes{..} => true,
            Prefix::Single(_) => true,
            Prefix::Automaton(ref aut) => {
                // Okay, so the automaton can respect priority in one
                // particular case: when every pattern is of the same length.
                // The trick is that the automaton will report the leftmost
                // match, which in this case, corresponds to the correct
                // match for the regex engine. If any other alternate matches
                // at the same position, then they must be exactly equivalent.

                // Guaranteed at least one prefix by construction, so use
                // that for the length.
                aut.patterns().iter().all(|p| p.len() == aut.pattern(0).len())
            }
        }
    }

    /// Returns all of the prefixes participating in this machine.
    ///
    /// For debug/testing only! (It allocates.)
    #[allow(dead_code)]
    pub fn prefixes(&self) -> Vec<String> {
        match *self {
            Prefix::Empty => vec![],
            Prefix::Byte(b) => vec![format!("{}", b as char)],
            Prefix::Bytes { ref chars, .. } => {
                chars.iter().map(|&b| format!("{}", b as char)).collect()
            }
            Prefix::Single(ref searcher) => vec![searcher.pat.clone()],
            Prefix::Automaton(ref aut) => aut.patterns().to_vec(),
        }
    }
}

/// Provides an implementation of fast subtring search.
///
/// In particular, this uses Boyer-Moore-Horspool with Tim Raita's twist:
/// https://en.wikipedia.org/wiki/Raita_Algorithm
///
/// I'm skeptical of the utility here, because benchmarks suggest that it is
/// difficult to beat Aho-Corasick on random text. Namely, both algorithms are
/// dominated by the performance of `memchr` for the leading byte prefix.
/// With that said, BMH does seem to surpass AC when the search text gets
/// longer (see the `easy0_1MB` vs. `easy1_1MB` benchmarks).
///
/// More analysis needs to be done to test this on different search texts.
#[derive(Clone, Debug)]
struct SingleSearch {
    pat: String,
    shift: Vec<usize>,
}

impl SingleSearch {
    fn new(pat: String) -> SingleSearch {
        assert!(pat.len() >= 1);
        let mut shift = vec![pat.len(); 256];
        for i in 0..(pat.len() - 1) {
            shift[pat.as_bytes()[i] as usize] = pat.len() - i - 1;
        }
        SingleSearch {
            pat: pat,
            shift: shift,
        }
    }

    fn find(&self, haystack: &str) -> Option<usize> {
        let pat = self.pat.as_bytes();
        let haystack = haystack.as_bytes();
        if haystack.len() < pat.len() {
            return None;
        }
        let mut i = match memchr(pat[0], haystack) {
            None => return None,
            Some(i) => i,
        };
        while i <= haystack.len() - pat.len() {
            let b = haystack[i + pat.len() - 1];
            if b == pat[pat.len() - 1]
               && haystack[i] == pat[0]
               && haystack[i + (pat.len() / 2)] == pat[pat.len() / 2]
               && pat == &haystack[i..i + pat.len()] {
                return Some(i);
            }
            i += self.shift[b as usize];
            i += match memchr(pat[0], &haystack[i..]) {
                None => return None,
                Some(i) => i,
            };
        }
        None
    }
}

/// A quick scan for multiple single byte prefixes using a sparse map.
fn find_singles(sparse: &[bool], haystack: &[u8]) -> Option<(usize, usize)> {
    // TODO: Improve this with ideas found in jetscii crate.
    for (hi, &b) in haystack.iter().enumerate() {
        if sparse[b as usize] {
            return Some((hi, hi+1));
        }
    }
    None
}

impl fmt::Debug for Prefix {
    #[allow(deprecated)] // connect => join in 1.3
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Prefix::Empty => write!(f, "Empty"),
            Prefix::Byte(b) => write!(f, "{:?}", b as char),
            Prefix::Bytes { ref chars, .. } => {
                let chars: Vec<String> =
                    chars.iter()
                         .map(|&c| format!("{:?}", c as char))
                         .collect();
                write!(f, "{}", chars.connect(", "))
            }
            Prefix::Single(ref searcher) => write!(f, "{:?}", searcher),
            Prefix::Automaton(ref aut) => write!(f, "{:?}", aut),
        }
    }
}
<|endoftext|>


<commit_before>use std::num::Wrapping;
use super::VirtualMachine;

pub fn jump_to_sys_routine(_vm: &mut VirtualMachine, _addr: usize) {
    // Do nothing
}

pub fn clear_display(vm: &mut VirtualMachine) {
    for px in vm.display.iter_mut() {
        *px = 0;
    }
}

pub fn ret_from_subroutine(vm: &mut VirtualMachine) {
    vm.pc = vm.stack[vm.sp as usize];
    vm.sp -= 1;
}

pub fn jump_addr(vm: &mut VirtualMachine, addr: u16) {
    vm.pc = addr;
}

pub fn call_subroutine(vm: &mut VirtualMachine, addr: usize) {
    vm.sp += 1;
    vm.stack[vm.sp as usize] = vm.pc;
    vm.pc = addr as u16;
}

pub fn skip_next_vx_eq(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 == to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_ne(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 != to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_eq_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] == vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x].0 = byte;
}

pub fn add_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x] = vm.v[x] + Wrapping(byte);
}

pub fn set_vx_to_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[y];
}

pub fn set_vx_to_vx_or_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] | vm.v[y];
}

pub fn set_vx_to_vx_and_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] & vm.v[y];
}

pub fn set_vx_to_vx_xor_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] ^ vm.v[y];
}

pub fn add_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x].0 as u16 + vm.v[y].0 as u16 > 255 {
        1
    } else {
        0
    };
    vm.v[x] = vm.v[x] + vm.v[y];
}

pub fn sub_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x] > vm.v[y] { 1 } else { 0 };
    vm.v[x] = vm.v[x] - vm.v[y];
}

pub fn subn_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[y] > vm.v[x] { 1 } else { 0 };
    vm.v[x] = vm.v[y] - vm.v[x];
}

pub fn set_vx_to_vy_shr_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 7);
    vm.v[x] = vm.v[y] >> 1;
}

pub fn set_vx_to_vy_shl_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 0);
    vm.v[x] = vm.v[y] << 1;
}

fn nth_bit(byte: u8, pos: usize) -> u8 {
    use bit_utils::BitInformation;
    if byte.has_x_bit(7 - pos) { 1 } else { 0 }
}

#[test]
fn test_nth_bit() {
    assert_eq!(nth_bit(0b10000000, 0), 1);
    for i in 1..8 {
        assert_eq!(nth_bit(0b10000000, i), 0);
    }
    assert_eq!(nth_bit(0b01000000, 1), 1);
    assert_eq!(nth_bit(0b00100000, 2), 1);
    assert_eq!(nth_bit(0b00010000, 3), 1);
    assert_eq!(nth_bit(0b00001000, 4), 1);
    assert_eq!(nth_bit(0b00000100, 5), 1);
    assert_eq!(nth_bit(0b00000010, 6), 1);
    assert_eq!(nth_bit(0b00000001, 7), 1);
}

pub fn skip_next_vx_ne_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] != vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_i(vm: &mut VirtualMachine, to: u16) {
    vm.i = to;
}

extern crate rand;

pub fn set_vx_rand_and(vm: &mut VirtualMachine, x: usize, to: u8) {
    use self::rand::Rng;
    let mut rgen = rand::thread_rng();
    vm.v[x].0 = rgen.gen::<u8>() & to;
}

pub fn display_sprite(vm: &mut VirtualMachine, vx: usize, vy: usize, n: usize) {
    use super::{DISPLAY_HEIGHT, DISPLAY_WIDTH};

    vm.v[0xF].0 = 0;

    for y in 0..n {
        let b = vm.ram[vm.i as usize + y];
        for x in 0..8 {
            let xx = x + vm.v[vx].0 as usize;
            let yy = y + vm.v[vy].0 as usize;

            if xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT {
                let idx = yy * DISPLAY_WIDTH + xx;
                if b & (0b10000000 >> x) != 0 {
                    if vm.display[idx] == 1 {
                        vm.v[0xF].0 = 1;
                    }
                    vm.display[idx] ^= 1;
                }
            }
        }
    }

    vm.display_updated = true;
}

pub fn skip_next_key_vx_not_pressed(vm: &mut VirtualMachine, x: usize) {
    if !vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn skip_next_key_vx_pressed(vm: &mut VirtualMachine, x: usize) {
    if vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn set_vx_to_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.v[x].0 = vm.delay_timer;
}

pub fn wait_for_keypress_store_in_vx(vm: &mut VirtualMachine, x: usize) {
    vm.keypress_wait.wait = true;
    vm.keypress_wait.vx = x;
}

pub fn set_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.delay_timer = vm.v[x].0;
}

pub fn set_sound_timer(vm: &mut VirtualMachine, x: usize) {
    vm.sound_timer = vm.v[x].0;
}

pub fn add_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    vm.i += vm.v[x].0 as u16;
}

pub fn set_i_to_loc_of_digit_vx(vm: &mut VirtualMachine, x: usize) {
    vm.i = (vm.v[x] * Wrapping(5)).0 as u16;
}

pub fn store_bcd_of_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    let num = vm.v[x].0; // TODO: Should probably be wrapping
    let h = num / 100;
    let t = (num - h * 100) / 10;
    let o = num - h * 100 - t * 10;
    vm.ram[vm.i as usize] = h;
    vm.ram[vm.i as usize + 1] = t;
    vm.ram[vm.i as usize + 2] = o;
}

pub fn copy_v0_through_vx_to_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.ram[(vm.i + pos as u16) as usize] = vm.v[pos as usize].0;
    }
    vm.i += (x + 1) as u16;
}

pub fn read_v0_through_vx_from_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.v[pos as usize].0 = vm.ram[(vm.i + pos as u16) as usize];
    }
    vm.i += (x + 1) as u16;
}

#[test]
fn test_strore_bcd_of_vx_to_i() {
    let mut vm = VirtualMachine::new();
    vm.v[0].0 = 146;
    vm.i = 0;
    store_bcd_of_vx_to_i(&mut vm, 0);
    assert!(vm.ram[0] == 1);
    assert!(vm.ram[1] == 4);
    assert!(vm.ram[2] == 6);
}
<commit_msg>Rustfmt import reordering<commit_after>use super::VirtualMachine;
use std::num::Wrapping;

pub fn jump_to_sys_routine(_vm: &mut VirtualMachine, _addr: usize) {
    // Do nothing
}

pub fn clear_display(vm: &mut VirtualMachine) {
    for px in vm.display.iter_mut() {
        *px = 0;
    }
}

pub fn ret_from_subroutine(vm: &mut VirtualMachine) {
    vm.pc = vm.stack[vm.sp as usize];
    vm.sp -= 1;
}

pub fn jump_addr(vm: &mut VirtualMachine, addr: u16) {
    vm.pc = addr;
}

pub fn call_subroutine(vm: &mut VirtualMachine, addr: usize) {
    vm.sp += 1;
    vm.stack[vm.sp as usize] = vm.pc;
    vm.pc = addr as u16;
}

pub fn skip_next_vx_eq(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 == to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_ne(vm: &mut VirtualMachine, x: usize, to: u8) {
    if vm.v[x].0 != to {
        vm.pc += 2;
    }
}

pub fn skip_next_vx_eq_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] == vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x].0 = byte;
}

pub fn add_vx_byte(vm: &mut VirtualMachine, x: usize, byte: u8) {
    vm.v[x] = vm.v[x] + Wrapping(byte);
}

pub fn set_vx_to_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[y];
}

pub fn set_vx_to_vx_or_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] | vm.v[y];
}

pub fn set_vx_to_vx_and_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] & vm.v[y];
}

pub fn set_vx_to_vx_xor_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[x] = vm.v[x] ^ vm.v[y];
}

pub fn add_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x].0 as u16 + vm.v[y].0 as u16 > 255 {
        1
    } else {
        0
    };
    vm.v[x] = vm.v[x] + vm.v[y];
}

pub fn sub_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[x] > vm.v[y] { 1 } else { 0 };
    vm.v[x] = vm.v[x] - vm.v[y];
}

pub fn subn_vx_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = if vm.v[y] > vm.v[x] { 1 } else { 0 };
    vm.v[x] = vm.v[y] - vm.v[x];
}

pub fn set_vx_to_vy_shr_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 7);
    vm.v[x] = vm.v[y] >> 1;
}

pub fn set_vx_to_vy_shl_1(vm: &mut VirtualMachine, x: usize, y: usize) {
    vm.v[0xF].0 = nth_bit(vm.v[y].0, 0);
    vm.v[x] = vm.v[y] << 1;
}

fn nth_bit(byte: u8, pos: usize) -> u8 {
    use bit_utils::BitInformation;
    if byte.has_x_bit(7 - pos) { 1 } else { 0 }
}

#[test]
fn test_nth_bit() {
    assert_eq!(nth_bit(0b10000000, 0), 1);
    for i in 1..8 {
        assert_eq!(nth_bit(0b10000000, i), 0);
    }
    assert_eq!(nth_bit(0b01000000, 1), 1);
    assert_eq!(nth_bit(0b00100000, 2), 1);
    assert_eq!(nth_bit(0b00010000, 3), 1);
    assert_eq!(nth_bit(0b00001000, 4), 1);
    assert_eq!(nth_bit(0b00000100, 5), 1);
    assert_eq!(nth_bit(0b00000010, 6), 1);
    assert_eq!(nth_bit(0b00000001, 7), 1);
}

pub fn skip_next_vx_ne_vy(vm: &mut VirtualMachine, x: usize, y: usize) {
    if vm.v[x] != vm.v[y] {
        vm.pc += 2;
    }
}

pub fn set_i(vm: &mut VirtualMachine, to: u16) {
    vm.i = to;
}

extern crate rand;

pub fn set_vx_rand_and(vm: &mut VirtualMachine, x: usize, to: u8) {
    use self::rand::Rng;
    let mut rgen = rand::thread_rng();
    vm.v[x].0 = rgen.gen::<u8>() & to;
}

pub fn display_sprite(vm: &mut VirtualMachine, vx: usize, vy: usize, n: usize) {
    use super::{DISPLAY_HEIGHT, DISPLAY_WIDTH};

    vm.v[0xF].0 = 0;

    for y in 0..n {
        let b = vm.ram[vm.i as usize + y];
        for x in 0..8 {
            let xx = x + vm.v[vx].0 as usize;
            let yy = y + vm.v[vy].0 as usize;

            if xx < DISPLAY_WIDTH && yy < DISPLAY_HEIGHT {
                let idx = yy * DISPLAY_WIDTH + xx;
                if b & (0b10000000 >> x) != 0 {
                    if vm.display[idx] == 1 {
                        vm.v[0xF].0 = 1;
                    }
                    vm.display[idx] ^= 1;
                }
            }
        }
    }

    vm.display_updated = true;
}

pub fn skip_next_key_vx_not_pressed(vm: &mut VirtualMachine, x: usize) {
    if !vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn skip_next_key_vx_pressed(vm: &mut VirtualMachine, x: usize) {
    if vm.keys[vm.v[x].0 as usize] {
        vm.pc += 2;
    }
}

pub fn set_vx_to_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.v[x].0 = vm.delay_timer;
}

pub fn wait_for_keypress_store_in_vx(vm: &mut VirtualMachine, x: usize) {
    vm.keypress_wait.wait = true;
    vm.keypress_wait.vx = x;
}

pub fn set_delay_timer(vm: &mut VirtualMachine, x: usize) {
    vm.delay_timer = vm.v[x].0;
}

pub fn set_sound_timer(vm: &mut VirtualMachine, x: usize) {
    vm.sound_timer = vm.v[x].0;
}

pub fn add_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    vm.i += vm.v[x].0 as u16;
}

pub fn set_i_to_loc_of_digit_vx(vm: &mut VirtualMachine, x: usize) {
    vm.i = (vm.v[x] * Wrapping(5)).0 as u16;
}

pub fn store_bcd_of_vx_to_i(vm: &mut VirtualMachine, x: usize) {
    let num = vm.v[x].0; // TODO: Should probably be wrapping
    let h = num / 100;
    let t = (num - h * 100) / 10;
    let o = num - h * 100 - t * 10;
    vm.ram[vm.i as usize] = h;
    vm.ram[vm.i as usize + 1] = t;
    vm.ram[vm.i as usize + 2] = o;
}

pub fn copy_v0_through_vx_to_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.ram[(vm.i + pos as u16) as usize] = vm.v[pos as usize].0;
    }
    vm.i += (x + 1) as u16;
}

pub fn read_v0_through_vx_from_mem(vm: &mut VirtualMachine, x: usize) {
    for pos in 0...x {
        vm.v[pos as usize].0 = vm.ram[(vm.i + pos as u16) as usize];
    }
    vm.i += (x + 1) as u16;
}

#[test]
fn test_strore_bcd_of_vx_to_i() {
    let mut vm = VirtualMachine::new();
    vm.v[0].0 = 146;
    vm.i = 0;
    store_bcd_of_vx_to_i(&mut vm, 0);
    assert!(vm.ram[0] == 1);
    assert!(vm.ram[1] == 4);
    assert!(vm.ram[2] == 6);
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::mem;
use std::ptr;
use std::raw::Slice;
use rawslice::{RawSlice, RawMutSlice};

/// Extension trait for convenience methods on raw pointers
pub trait RawPtrExt<T>: RawPtr<T> {
    /// Converts the pointer into a raw slice.
    fn as_raw_slice(self, len: uint) -> *const [T];

    /// Converts the pointer into a slice.
    unsafe fn as_slice<'a>(self, len: uint) -> &'a [T];

    /// Calculates the offset from a pointer by addition. The offset *must* be in-bounds of
    /// the object, or one-byte-past-the-end.  `count` is in units of T; e.g. a
    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
    unsafe fn add(self, count: uint) -> Self {
        self.offset(count as int)
    }

    // Calculates the offset from a pointer by subtraction. The offset *must* be in-bounds of
    /// the object, or one-byte-past-the-end.  `count` is in units of T; e.g. a
    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
    unsafe fn sub(self, count: uint) -> Self {
        self.offset(-(count as int))
    }

    /// Reads the value from `self` and returns it.
    unsafe fn read(self) -> T;
}

/// Extension trait for convenience methods on mutable raw pointers
pub trait RawMutPtrExt<T>: RawPtrExt<T> {
    /// Converts the pointer into a raw mutable slice.
    fn as_raw_mut_slice(self, len: uint) -> *mut [T];

    /// Converts the pointer into a mutable slice.
    unsafe fn as_mut_slice<'a>(self, len: uint) -> &'a mut [T];

    /// Unsafely overwrite a memory location with the given value without destroying
    /// the old value.
    ///
    /// This operation is unsafe because it does not destroy the previous value
    /// contained at the location `dst`. This could leak allocations or resources,
    /// so care must be taken to previously deallocate the value at `dst`.
    unsafe fn write(self, src: T);

    /// Sets the `count * size_of<T>()` bytes at the address of this pointer to the the given
    /// byte. Good for zeroing out memory.
    unsafe fn write_bytes(self, byte: u8, count: uint);

    /// Copies `count * size_of<T>()` many bytes from `src` to the address of this pointer,
    /// assuming that the source and destination *may* overlap.
    unsafe fn copy(self, src: *const T, count: uint);

    /// Copies `count * size_of<T>()` many bytes from `src` to the address of this pointer,
    /// assuming that the source and destination *do not* overlap.
    unsafe fn copy_nonoverlapping(self, src: *const T, count: uint);

    /// Swaps the values of `self` and `y`. Note that in contrast to `mem::swap`, `x` and `y`
    /// may point to the same address of memory. Useful for making some operations branchless.
    unsafe fn swap(self, y: *mut T);

    /// Replace the value of the pointer, returning the old value. This is simply
    /// a convenience for calling `mem::replace` with a raw pointer.
    unsafe fn replace(self, src: T) -> T;
}

impl<T> RawPtrExt<T> for *const T {
    fn as_raw_slice(self, len: uint) -> *const [T] {
        unsafe {
            mem::transmute(Slice {
                data: self,
                len: len
            })
        }
    }

    unsafe fn as_slice<'a>(self, len: uint) -> &'a [T] {
        self.as_raw_slice(len).as_slice()
    }

    unsafe fn read(self) -> T {
        ptr::read(self)
    }
}

impl<T> RawPtrExt<T> for *mut T {
    fn as_raw_slice(self, len: uint) -> *const [T] {
        (self as *const T).as_raw_slice(len)
    }

    unsafe fn as_slice<'a>(self, len: uint) -> &'a [T] {
        self.as_raw_slice(len).as_slice()
    }

    unsafe fn read(self) -> T {
        ptr::read(self as *const T)
    }
}

impl<T> RawMutPtrExt<T> for *mut T {
    fn as_raw_mut_slice(self, len: uint) -> *mut [T] {
        unsafe {
            mem::transmute(Slice {
                data: self as *const T,
                len: len
            })
        }
    }

    unsafe fn as_mut_slice<'a>(self, len: uint) -> &'a mut [T] {
        self.as_raw_mut_slice(len).as_mut_slice()
    }

    unsafe fn write(self, src: T) {
        ptr::write(self, src);
    }

    unsafe fn write_bytes(self, byte: u8, count: uint) {
        ptr::set_memory(self, byte, count);
    }

    unsafe fn copy(self, src: *const T, count: uint) {
        ptr::copy_memory(self, src, count);
    }

    unsafe fn copy_nonoverlapping(self, src: *const T, count: uint) {
        ptr::copy_nonoverlapping_memory(self, src, count);
    }

    unsafe fn swap(self, y: *mut T) {
        ptr::swap(self, y);
    }

    unsafe fn replace(self, src: T) -> T {
        ptr::replace(self, src)
    }
}

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

    #[test]
    fn test_arithmetic() {
        unsafe {
            let mut x = [1u,2,3,4];
            let y = x[].as_ptr();
            assert_eq!(*y, 1);
            assert_eq!(*y.add(2), 3);
            assert_eq!(*y.add(2).sub(1), 2);

            let y = x[mut].as_mut_ptr();
            assert_eq!(*y, 1);
            assert_eq!(*y.add(2), 3);
            assert_eq!(*y.add(2).sub(1), 2);
        }
    }

    #[test]
    fn test_read_write() {
        unsafe {
            let x = &mut 1u as *mut _;
            assert_eq!(x.read(), 1);
            x.write(2);
            assert_eq!(x.read(), 2);
            x.write_bytes(0, 1);
            assert_eq!(x.read(), 0);
        }
    }

    #[test]
    fn test_copy() {
        unsafe {
            let mut x = [1u,2,3,4];
            let y = [5u,6,7,8];
            let xptr = x[mut].as_mut_ptr();
            let yptr = y[].as_ptr();

            xptr.copy(xptr.add(1) as *const _, 2);
            assert_eq!(x[], [2,3,3,4][]);
            xptr.copy_nonoverlapping(yptr, 4);
            assert_eq!(x[], y[]);
        }
    }

    #[test]
    fn test_swap_replace() {
        unsafe {
            let x = &mut 1u as *mut _;
            let y = &mut 2;
            x.swap(y);
            assert_eq!(*x, 2);
            assert_eq!(*y, 1);

            x.replace(3);
            assert_eq!(*x, 3);
        }
    }
}<commit_msg>rawptr: // -> /// in first line of sub() docs<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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.

use std::mem;
use std::ptr;
use std::raw::Slice;
use rawslice::{RawSlice, RawMutSlice};

/// Extension trait for convenience methods on raw pointers
pub trait RawPtrExt<T>: RawPtr<T> {
    /// Converts the pointer into a raw slice.
    fn as_raw_slice(self, len: uint) -> *const [T];

    /// Converts the pointer into a slice.
    unsafe fn as_slice<'a>(self, len: uint) -> &'a [T];

    /// Calculates the offset from a pointer by addition. The offset *must* be in-bounds of
    /// the object, or one-byte-past-the-end.  `count` is in units of T; e.g. a
    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
    unsafe fn add(self, count: uint) -> Self {
        self.offset(count as int)
    }

    /// Calculates the offset from a pointer by subtraction. The offset *must* be in-bounds of
    /// the object, or one-byte-past-the-end.  `count` is in units of T; e.g. a
    /// `count` of 3 represents a pointer offset of `3 * sizeof::<T>()` bytes.
    unsafe fn sub(self, count: uint) -> Self {
        self.offset(-(count as int))
    }

    /// Reads the value from `self` and returns it.
    unsafe fn read(self) -> T;
}

/// Extension trait for convenience methods on mutable raw pointers
pub trait RawMutPtrExt<T>: RawPtrExt<T> {
    /// Converts the pointer into a raw mutable slice.
    fn as_raw_mut_slice(self, len: uint) -> *mut [T];

    /// Converts the pointer into a mutable slice.
    unsafe fn as_mut_slice<'a>(self, len: uint) -> &'a mut [T];

    /// Unsafely overwrite a memory location with the given value without destroying
    /// the old value.
    ///
    /// This operation is unsafe because it does not destroy the previous value
    /// contained at the location `dst`. This could leak allocations or resources,
    /// so care must be taken to previously deallocate the value at `dst`.
    unsafe fn write(self, src: T);

    /// Sets the `count * size_of<T>()` bytes at the address of this pointer to the the given
    /// byte. Good for zeroing out memory.
    unsafe fn write_bytes(self, byte: u8, count: uint);

    /// Copies `count * size_of<T>()` many bytes from `src` to the address of this pointer,
    /// assuming that the source and destination *may* overlap.
    unsafe fn copy(self, src: *const T, count: uint);

    /// Copies `count * size_of<T>()` many bytes from `src` to the address of this pointer,
    /// assuming that the source and destination *do not* overlap.
    unsafe fn copy_nonoverlapping(self, src: *const T, count: uint);

    /// Swaps the values of `self` and `y`. Note that in contrast to `mem::swap`, `x` and `y`
    /// may point to the same address of memory. Useful for making some operations branchless.
    unsafe fn swap(self, y: *mut T);

    /// Replace the value of the pointer, returning the old value. This is simply
    /// a convenience for calling `mem::replace` with a raw pointer.
    unsafe fn replace(self, src: T) -> T;
}

impl<T> RawPtrExt<T> for *const T {
    fn as_raw_slice(self, len: uint) -> *const [T] {
        unsafe {
            mem::transmute(Slice {
                data: self,
                len: len
            })
        }
    }

    unsafe fn as_slice<'a>(self, len: uint) -> &'a [T] {
        self.as_raw_slice(len).as_slice()
    }

    unsafe fn read(self) -> T {
        ptr::read(self)
    }
}

impl<T> RawPtrExt<T> for *mut T {
    fn as_raw_slice(self, len: uint) -> *const [T] {
        (self as *const T).as_raw_slice(len)
    }

    unsafe fn as_slice<'a>(self, len: uint) -> &'a [T] {
        self.as_raw_slice(len).as_slice()
    }

    unsafe fn read(self) -> T {
        ptr::read(self as *const T)
    }
}

impl<T> RawMutPtrExt<T> for *mut T {
    fn as_raw_mut_slice(self, len: uint) -> *mut [T] {
        unsafe {
            mem::transmute(Slice {
                data: self as *const T,
                len: len
            })
        }
    }

    unsafe fn as_mut_slice<'a>(self, len: uint) -> &'a mut [T] {
        self.as_raw_mut_slice(len).as_mut_slice()
    }

    unsafe fn write(self, src: T) {
        ptr::write(self, src);
    }

    unsafe fn write_bytes(self, byte: u8, count: uint) {
        ptr::set_memory(self, byte, count);
    }

    unsafe fn copy(self, src: *const T, count: uint) {
        ptr::copy_memory(self, src, count);
    }

    unsafe fn copy_nonoverlapping(self, src: *const T, count: uint) {
        ptr::copy_nonoverlapping_memory(self, src, count);
    }

    unsafe fn swap(self, y: *mut T) {
        ptr::swap(self, y);
    }

    unsafe fn replace(self, src: T) -> T {
        ptr::replace(self, src)
    }
}

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

    #[test]
    fn test_arithmetic() {
        unsafe {
            let mut x = [1u,2,3,4];
            let y = x[].as_ptr();
            assert_eq!(*y, 1);
            assert_eq!(*y.add(2), 3);
            assert_eq!(*y.add(2).sub(1), 2);

            let y = x[mut].as_mut_ptr();
            assert_eq!(*y, 1);
            assert_eq!(*y.add(2), 3);
            assert_eq!(*y.add(2).sub(1), 2);
        }
    }

    #[test]
    fn test_read_write() {
        unsafe {
            let x = &mut 1u as *mut _;
            assert_eq!(x.read(), 1);
            x.write(2);
            assert_eq!(x.read(), 2);
            x.write_bytes(0, 1);
            assert_eq!(x.read(), 0);
        }
    }

    #[test]
    fn test_copy() {
        unsafe {
            let mut x = [1u,2,3,4];
            let y = [5u,6,7,8];
            let xptr = x[mut].as_mut_ptr();
            let yptr = y[].as_ptr();

            xptr.copy(xptr.add(1) as *const _, 2);
            assert_eq!(x[], [2,3,3,4][]);
            xptr.copy_nonoverlapping(yptr, 4);
            assert_eq!(x[], y[]);
        }
    }

    #[test]
    fn test_swap_replace() {
        unsafe {
            let x = &mut 1u as *mut _;
            let y = &mut 2;
            x.swap(y);
            assert_eq!(*x, 2);
            assert_eq!(*y, 1);

            x.replace(3);
            assert_eq!(*x, 3);
        }
    }
}
<|endoftext|>