<commit_before>extern crate serde;
extern crate toml;
extern crate walkdir;

use error::YabsError;
use ext::*;
use desc::desc::*;
use walkdir::{WalkDir, WalkDirIterator, DirEntry};

use std::ffi::OsStr;

#[derive(Debug,Default,Deserialize,Serialize,Clone,PartialEq)]
pub struct ProjectDesc {
    name: Option<String>,
    target: Option<Vec<String>>,
    lang: Option<String>,
    os: Option<String>,
    version: Option<String>,
    compiler: Option<String>,
    src: Option<Vec<String>>,
    libs: Option<Vec<String>>,
    #[serde(rename = "lib-dir")]
    lib_dir: Option<Vec<String>>,
    inc: Option<Vec<String>>,
    cflags: Option<Vec<String>>,
    #[serde(rename = "explicit-cflags")]
    explicit_cflags: Option<String>,
    lflags: Option<Vec<String>>,
    ignore: Option<Vec<String>>,
    #[serde(rename = "before-script")]
    before_script: Option<Vec<String>>,
    #[serde(rename = "after-script")]
    after_script: Option<Vec<String>>,
    #[serde(rename = "static-lib")]
    static_lib: Option<bool>,
    ar: Option<String>,
    arflags: Option<String>,
    clean: Option<Vec<String>>,
}

impl ProjectDesc {
    pub fn get_src(&self) -> Option<Vec<String>> {
        return self.src.clone();
    }

    pub fn is_in_ignore(&self, entry: &DirEntry) -> bool {
        if let Some(ignore) = self.ignore.as_ref() {
            for path in ignore {
                if let Some(entry_str) = entry.path().to_str() {
                    if entry_str.find(path).is_some() {
                        return true;
                    }
                }
            }
        }
        false
    }

    pub fn gen_file_list(&mut self) -> Result<(), YabsError> {
        // If sources are listed don't scan for files
        if self.src.is_some() {
            return Ok(());
        }
        let mut sources = Vec::new();
        let walk_dir = WalkDir::new(".").into_iter();
        for entry in walk_dir.filter_entry(|e| !&self.is_in_ignore(e)) {
            let entry = entry?;
            if entry.path().is_file() {
                let file_ext = entry.path().extension().unwrap_or(OsStr::new(""));
                if let Some(ext) = file_ext.to_str() {
                    if let Some(lang) = self.lang.as_ref() {
                        if ext == lang {
                            if let Some(entry_str) = entry.path().to_str() {
                                sources.push(entry_str.to_owned());
                            }
                        }
                    }
                }
            }
        }
        sources.sort();
        self.src = Some(sources);
        Ok(())
    }

    // Concatenates a vector of strings `list`, prepending each entry with `prepend`
    pub fn prepend_op_vec(&self, list: &Option<Vec<String>>, prepend: &str) -> String {
        let mut horrid_string = String::new();
        if let Some(items) = list.as_ref() {
            if let Some(split_last) = items.split_last() {
                for sub_item in split_last.1 {
                    if self.is_command(&sub_item) {
                        horrid_string.push_str(&format!("{} ", sub_item));
                    } else {
                        horrid_string.push_str(&format!("{}{} ", prepend.to_owned(), sub_item));
                    }
                }
                if self.is_command(&split_last.0) {
                    horrid_string.push_str(&format!("{} ", split_last.0));
                } else {
                    horrid_string.push_str(&format!("{}{}", prepend.to_owned(), split_last.0.clone()));
                }
            }
        }
        return horrid_string;
    }

    // Any string that starts and ends with the character "`" is regarded as a command
    pub fn is_command(&self, string: &String) -> bool {
        if string.starts_with("`") && string.ends_with("`") {
            return true;
        } else {
            return false;
        }
    }

    pub fn gen_target_list(&self) -> Target {
        let mut all = String::new();
        let mut target_str = String::new();
        if let Some(targets) = self.target.clone() {
            all = targets.join(" ");
            if let Some(static_lib) = self.static_lib {
                if targets.len() == 1 {
                    if static_lib {
                        target_str = format!("$(TARGET): $(OBJ)\n\
                            \t$(AR) $(ARFLAGS) $(TARGET) $(OBJ)\n\n");
                    } else {
                        target_str = format!("$(TARGET): $(OBJ)\n\
                            \t$(CC) $(LFLAGS) -o $(TARGET) $(OBJ) $(LIBDIR) $(LIBS)\n\n");
                    }
                } else {
                    if static_lib {
                        for target in targets {
                            target_str.push_str(&format!("{0}: $(OBJ)\n\
                                    \t$(AR) $(ARFLAGS) {0} $(OBJ)\n\n", target));
                        }
                    } else {
                        for target in targets {
                            target_str.push_str(&format!("{0}: $(OBJ)\n\
                                    \t$(CC) $(LFLAGS) -o {0} $(OBJ) $(LIBDIR) $(LIBS)\n\n", target));
                        }
                    }
                }
            } else {
                if targets.len() == 1 {
                    target_str = format!("$(TARGET): $(OBJ)\n\
                        \t$(CC) $(LFLAGS) -o $(TARGET) $(OBJ) $(LIBDIR) $(LIBS)\n\n");
                } else {
                    for target in targets {
                        target_str.push_str(&format!("{0}: $(OBJ)\n\
                                    \t$(CC) $(LFLAGS) -o {0} $(OBJ) $(LIBDIR) $(LIBS)\n\n", target));
                    }
                }
            }
        };
        Target { target: target_str, all: all }
    }

    fn gen_lib_dir_list(&self) -> String {
        return self.prepend_op_vec(&self.lib_dir, "-L");
    }

    fn gen_lib_list(&self) -> String {
        return self.prepend_op_vec(&self.libs, "-l");
    }

    fn gen_cflags_list(&self) -> String {
        return self.prepend_op_vec(&self.cflags, "-");
    }

    fn gen_lflags_list(&self) -> String {
        return self.prepend_op_vec(&self.lflags, "-");
    }

    fn gen_src_list(&self) -> String {
        let mut horrid_string: String = "SRC\t= ".to_owned();
        let mut lang = self.lang.clone().unwrap_or("cpp".to_owned());
        lang.insert(0, '.');
        if let Some(source_list) = self.src.as_ref() {
            // Multiple sources
            if source_list.len() > 1 {
                if let Some(split_first) = source_list.split_first() {
                    horrid_string.push_str(&format!("{} \\\n", split_first.0));
                    if let Some(split_last) = split_first.1.clone().split_last() {
                        for src in split_last.1 {
                            horrid_string.push_str(&format!("\t  {} \\\n", src));
                        }
                        horrid_string.push_str(&format!("\t  {}\n", split_last.0));
                    }
                }
            // One source file
            } else {
                for src in source_list {
                    horrid_string.push_str(&format!("{}\n", src));
                }
            }
            let mut parsed_obj_list = Vec::new();
            for obj in source_list {
                parsed_obj_list.push(obj.replace(&lang, ".o"));
            }
            horrid_string.push_str("OBJ\t= ");
            if parsed_obj_list.len() > 1 {
                if let Some(split_first) = parsed_obj_list.split_first() {
                    horrid_string.push_str(&format!("{} \\\n", split_first.0));
                    if let Some(split_last) = split_first.1.clone().split_last() {
                        for src in split_last.1 {
                            horrid_string.push_str(&format!("\t  {} \\\n", src));
                        }
                        horrid_string.push_str(&format!("\t  {}", split_last.0));
                    }
                }
            } else {
                for obj in parsed_obj_list {
                    horrid_string.push_str(&format!("{}\n", obj));
                }
            }
        }
        return horrid_string;
    }

    fn gen_inc_list(&self) -> String {
        return self.prepend_op_vec(&self.inc, "-I");
    }

    pub fn gen_make(&mut self) -> Result<String, YabsError> {
        self.gen_file_list()?;
        let target = &self.gen_target_list();
        Ok(format!(
            "INSTALL\t= /usr/bin/env install\n\
                AR\t= {ar}\n\
                ARFLAGS\t= {ar_flags}\n\
                DEST\t=\n\
                PREFIX\t=\n\
                CC\t= {compiler}\n\
                BINDIR\t=\n\
                TARGET\t= {all}\n\
                LINK\t= {compiler}\n\
                CFLAGS\t= {cflags}\n\
                LFLAGS\t=\n\
                LIBS\t= {libs}\n\
                INCDIR\t= {incdir}\n\
                LIBDIR\t= {lib_dir}\n\
                CLEAN\t=\n\
                DEL\t= rm -f\n\
                {srcs}\n\n\
                first: all\n\n\
                .PHONY: doc clean\n\n\
                all: {all}\n\n\
                {target_command}\
                %.o: %.{lang}\n\t$(CC) -c $(CFLAGS) $(INCDIR) -o $@ $<\n\
                clean:\n\
                \t$(DEL) $(OBJ)\n\
                \t$(DEL) {all}\n\
                \t$(DEL) {clean_list}\n\
                ",
                compiler = &self.compiler.as_ref().unwrap_or(&"gcc".to_owned()),
                ar = &self.ar.as_ref().unwrap_or(&"/usr/bin/env ar".to_owned()),
                ar_flags = &self.arflags.as_ref().unwrap_or(&"rcs".to_owned()),
                all = target.all,
                target_command = target.target,
                cflags = &self.gen_cflags_list(),
                libs = &self.gen_lib_list(),
                incdir = &self.gen_inc_list(),
                lib_dir = &self.gen_lib_dir_list(),
                srcs = &self.gen_src_list(),
                lang = &self.lang.clone().unwrap_or("c".to_owned()),
                clean_list = &self.clean.clone().unwrap_or(vec![]).join(" ")))
    }

    pub fn run_script(&self, script: &Option<Vec<String>>) -> Result<(), YabsError> {
        if let Some(script) = script.as_ref() {
            for cmd in script {
                run_cmd(cmd)?;
            }
        }
        Ok(())
    }

    pub fn build_bin(&mut self) -> Result<(), YabsError> {
        self.run_script(&self.before_script)?;
        self.gen_file_list()?;
        if let Some(src_list) = self.src.as_ref() {
            let mut lang = self.lang.clone().unwrap_or("cpp".to_owned());
            lang.insert(0, '.');
            let mut cmd_string;
            let mut obj_vec = Vec::new();
            for src in src_list {
                run_cmd(&format!("{cc} -c {cflag} {inc} -o {object} {source}",
                                         cc = self.compiler.as_ref().unwrap_or(&"gcc".to_owned()),
                                         cflag = self.gen_cflags_list(),
                                         inc = self.gen_inc_list(),
                                         source = src,
                                         object = src.replace(&lang, ".o"),
                                         ))?;
                obj_vec.push(src.replace(&lang, ".o"));
            }
            for target in self.target.clone().unwrap_or(vec!["a".to_owned()]) {
                if self.static_lib.unwrap_or(false) == true {
                    cmd_string = format!("{ar} {ar_flags} {target} {obj_list}",
                                                 ar = self.ar.as_ref().unwrap_or(&"/usr/bin/env ar".to_owned()),
                                                 ar_flags = self.arflags.as_ref().unwrap_or(&"rcs".to_owned()),
                                                 target = target,
                                                 obj_list = obj_vec.join(" "),
                                                 );
                    run_cmd(&cmd_string)?;
                } else {
                    cmd_string = format!("{cc} {lflags} -o {target} {obj_list} {lib_dir} {libs}",
                                                 cc = self.compiler.as_ref().unwrap_or(&"gcc".to_owned()),
                                                 lflags = self.gen_lflags_list(),
                                                 target = target,
                                                 obj_list = &self.prepend_op_vec(&Some(obj_vec.clone()), " "),
                                                 lib_dir = self.gen_lib_dir_list(),
                                                 libs = self.gen_lib_list());
                    run_cmd(&cmd_string)?;
                }
            };
        };
        self.run_script(&self.after_script)?;
        Ok(())
    }
}
<commit_msg>Set env variable VERSION<commit_after>extern crate serde;
extern crate toml;
extern crate walkdir;

use error::YabsError;
use ext::*;
use desc::desc::*;
use walkdir::{WalkDir, WalkDirIterator, DirEntry};

use std::ffi::OsStr;
use std::env;

#[derive(Debug,Default,Deserialize,Serialize,Clone,PartialEq)]
pub struct ProjectDesc {
    name: Option<String>,
    target: Option<Vec<String>>,
    lang: Option<String>,
    os: Option<String>,
    version: Option<String>,
    compiler: Option<String>,
    src: Option<Vec<String>>,
    libs: Option<Vec<String>>,
    #[serde(rename = "lib-dir")]
    lib_dir: Option<Vec<String>>,
    inc: Option<Vec<String>>,
    cflags: Option<Vec<String>>,
    #[serde(rename = "explicit-cflags")]
    explicit_cflags: Option<String>,
    lflags: Option<Vec<String>>,
    ignore: Option<Vec<String>>,
    #[serde(rename = "before-script")]
    before_script: Option<Vec<String>>,
    #[serde(rename = "after-script")]
    after_script: Option<Vec<String>>,
    #[serde(rename = "static-lib")]
    static_lib: Option<bool>,
    ar: Option<String>,
    arflags: Option<String>,
    clean: Option<Vec<String>>,
}

impl ProjectDesc {
    pub fn get_src(&self) -> Option<Vec<String>> {
        return self.src.clone();
    }

    pub fn is_in_ignore(&self, entry: &DirEntry) -> bool {
        if let Some(ignore) = self.ignore.as_ref() {
            for path in ignore {
                if let Some(entry_str) = entry.path().to_str() {
                    if entry_str.find(path).is_some() {
                        return true;
                    }
                }
            }
        }
        false
    }

    pub fn gen_file_list(&mut self) -> Result<(), YabsError> {
        // If sources are listed don't scan for files
        if self.src.is_some() {
            return Ok(());
        }
        let mut sources = Vec::new();
        let walk_dir = WalkDir::new(".").into_iter();
        for entry in walk_dir.filter_entry(|e| !&self.is_in_ignore(e)) {
            let entry = entry?;
            if entry.path().is_file() {
                let file_ext = entry.path().extension().unwrap_or(OsStr::new(""));
                if let Some(ext) = file_ext.to_str() {
                    if let Some(lang) = self.lang.as_ref() {
                        if ext == lang {
                            if let Some(entry_str) = entry.path().to_str() {
                                sources.push(entry_str.to_owned());
                            }
                        }
                    }
                }
            }
        }
        sources.sort();
        self.src = Some(sources);
        Ok(())
    }

    // Concatenates a vector of strings `list`, prepending each entry with `prepend`
    pub fn prepend_op_vec(&self, list: &Option<Vec<String>>, prepend: &str) -> String {
        let mut horrid_string = String::new();
        if let Some(items) = list.as_ref() {
            if let Some(split_last) = items.split_last() {
                for sub_item in split_last.1 {
                    if self.is_command(&sub_item) {
                        horrid_string.push_str(&format!("{} ", sub_item));
                    } else {
                        horrid_string.push_str(&format!("{}{} ", prepend.to_owned(), sub_item));
                    }
                }
                if self.is_command(&split_last.0) {
                    horrid_string.push_str(&format!("{} ", split_last.0));
                } else {
                    horrid_string.push_str(&format!("{}{}", prepend.to_owned(), split_last.0.clone()));
                }
            }
        }
        return horrid_string;
    }

    // Any string that starts and ends with the character "`" is regarded as a command
    pub fn is_command(&self, string: &String) -> bool {
        if string.starts_with("`") && string.ends_with("`") {
            return true;
        } else {
            return false;
        }
    }

    pub fn gen_target_list(&self) -> Target {
        let mut all = String::new();
        let mut target_str = String::new();
        if let Some(targets) = self.target.clone() {
            all = targets.join(" ");
            if let Some(static_lib) = self.static_lib {
                if targets.len() == 1 {
                    if static_lib {
                        target_str = format!("$(TARGET): $(OBJ)\n\
                            \t$(AR) $(ARFLAGS) $(TARGET) $(OBJ)\n\n");
                    } else {
                        target_str = format!("$(TARGET): $(OBJ)\n\
                            \t$(CC) $(LFLAGS) -o $(TARGET) $(OBJ) $(LIBDIR) $(LIBS)\n\n");
                    }
                } else {
                    if static_lib {
                        for target in targets {
                            target_str.push_str(&format!("{0}: $(OBJ)\n\
                                    \t$(AR) $(ARFLAGS) {0} $(OBJ)\n\n", target));
                        }
                    } else {
                        for target in targets {
                            target_str.push_str(&format!("{0}: $(OBJ)\n\
                                    \t$(CC) $(LFLAGS) -o {0} $(OBJ) $(LIBDIR) $(LIBS)\n\n", target));
                        }
                    }
                }
            } else {
                if targets.len() == 1 {
                    target_str = format!("$(TARGET): $(OBJ)\n\
                        \t$(CC) $(LFLAGS) -o $(TARGET) $(OBJ) $(LIBDIR) $(LIBS)\n\n");
                } else {
                    for target in targets {
                        target_str.push_str(&format!("{0}: $(OBJ)\n\
                                    \t$(CC) $(LFLAGS) -o {0} $(OBJ) $(LIBDIR) $(LIBS)\n\n", target));
                    }
                }
            }
        };
        Target { target: target_str, all: all }
    }

    fn gen_lib_dir_list(&self) -> String {
        return self.prepend_op_vec(&self.lib_dir, "-L");
    }

    fn gen_lib_list(&self) -> String {
        return self.prepend_op_vec(&self.libs, "-l");
    }

    fn gen_cflags_list(&self) -> String {
        return self.prepend_op_vec(&self.cflags, "-");
    }

    fn gen_lflags_list(&self) -> String {
        return self.prepend_op_vec(&self.lflags, "-");
    }

    fn gen_src_list(&self) -> String {
        let mut horrid_string: String = "SRC\t= ".to_owned();
        let mut lang = self.lang.clone().unwrap_or("cpp".to_owned());
        lang.insert(0, '.');
        if let Some(source_list) = self.src.as_ref() {
            // Multiple sources
            if source_list.len() > 1 {
                if let Some(split_first) = source_list.split_first() {
                    horrid_string.push_str(&format!("{} \\\n", split_first.0));
                    if let Some(split_last) = split_first.1.clone().split_last() {
                        for src in split_last.1 {
                            horrid_string.push_str(&format!("\t  {} \\\n", src));
                        }
                        horrid_string.push_str(&format!("\t  {}\n", split_last.0));
                    }
                }
            // One source file
            } else {
                for src in source_list {
                    horrid_string.push_str(&format!("{}\n", src));
                }
            }
            let mut parsed_obj_list = Vec::new();
            for obj in source_list {
                parsed_obj_list.push(obj.replace(&lang, ".o"));
            }
            horrid_string.push_str("OBJ\t= ");
            if parsed_obj_list.len() > 1 {
                if let Some(split_first) = parsed_obj_list.split_first() {
                    horrid_string.push_str(&format!("{} \\\n", split_first.0));
                    if let Some(split_last) = split_first.1.clone().split_last() {
                        for src in split_last.1 {
                            horrid_string.push_str(&format!("\t  {} \\\n", src));
                        }
                        horrid_string.push_str(&format!("\t  {}", split_last.0));
                    }
                }
            } else {
                for obj in parsed_obj_list {
                    horrid_string.push_str(&format!("{}\n", obj));
                }
            }
        }
        return horrid_string;
    }

    fn gen_inc_list(&self) -> String {
        return self.prepend_op_vec(&self.inc, "-I");
    }

    pub fn gen_make(&mut self) -> Result<String, YabsError> {
        self.gen_file_list()?;
        let target = &self.gen_target_list();
        Ok(format!(
            "INSTALL\t= /usr/bin/env install\n\
                AR\t= {ar}\n\
                ARFLAGS\t= {ar_flags}\n\
                DEST\t=\n\
                PREFIX\t=\n\
                CC\t= {compiler}\n\
                BINDIR\t=\n\
                TARGET\t= {all}\n\
                LINK\t= {compiler}\n\
                CFLAGS\t= {cflags}\n\
                LFLAGS\t=\n\
                LIBS\t= {libs}\n\
                INCDIR\t= {incdir}\n\
                LIBDIR\t= {lib_dir}\n\
                CLEAN\t=\n\
                DEL\t= rm -f\n\
                {srcs}\n\n\
                first: all\n\n\
                .PHONY: doc clean\n\n\
                all: {all}\n\n\
                {target_command}\
                %.o: %.{lang}\n\t$(CC) -c $(CFLAGS) $(INCDIR) -o $@ $<\n\
                clean:\n\
                \t$(DEL) $(OBJ)\n\
                \t$(DEL) {all}\n\
                \t$(DEL) {clean_list}\n\
                ",
                compiler = &self.compiler.as_ref().unwrap_or(&"gcc".to_owned()),
                ar = &self.ar.as_ref().unwrap_or(&"/usr/bin/env ar".to_owned()),
                ar_flags = &self.arflags.as_ref().unwrap_or(&"rcs".to_owned()),
                all = target.all,
                target_command = target.target,
                cflags = &self.gen_cflags_list(),
                libs = &self.gen_lib_list(),
                incdir = &self.gen_inc_list(),
                lib_dir = &self.gen_lib_dir_list(),
                srcs = &self.gen_src_list(),
                lang = &self.lang.clone().unwrap_or("c".to_owned()),
                clean_list = &self.clean.clone().unwrap_or(vec![]).join(" ")))
    }

    pub fn run_script(&self, script: &Option<Vec<String>>) -> Result<(), YabsError> {
        if let Some(script) = script.as_ref() {
            for cmd in script {
                run_cmd(cmd)?;
            }
        }
        Ok(())
    }

    pub fn build_bin(&mut self) -> Result<(), YabsError> {
        self.run_script(&self.before_script)?;
        env::set_var("VERSION", format!("\"{}\"", &self.version.clone().unwrap_or("0.0.1".to_owned())));
        self.gen_file_list()?;
        if let Some(src_list) = self.src.as_ref() {
            let mut lang = self.lang.clone().unwrap_or("cpp".to_owned());
            lang.insert(0, '.');
            let mut cmd_string;
            let mut obj_vec = Vec::new();
            for src in src_list {
                run_cmd(&format!("{cc} -c {cflag} {inc} -o {object} {source}",
                                         cc = self.compiler.as_ref().unwrap_or(&"gcc".to_owned()),
                                         cflag = self.gen_cflags_list(),
                                         inc = self.gen_inc_list(),
                                         source = src,
                                         object = src.replace(&lang, ".o"),
                                         ))?;
                obj_vec.push(src.replace(&lang, ".o"));
            }
            for target in self.target.clone().unwrap_or(vec!["a".to_owned()]) {
                if self.static_lib.unwrap_or(false) == true {
                    cmd_string = format!("{ar} {ar_flags} {target} {obj_list}",
                                                 ar = self.ar.as_ref().unwrap_or(&"/usr/bin/env ar".to_owned()),
                                                 ar_flags = self.arflags.as_ref().unwrap_or(&"rcs".to_owned()),
                                                 target = target,
                                                 obj_list = obj_vec.join(" "),
                                                 );
                    run_cmd(&cmd_string)?;
                } else {
                    cmd_string = format!("{cc} {lflags} -o {target} {obj_list} {lib_dir} {libs}",
                                                 cc = self.compiler.as_ref().unwrap_or(&"gcc".to_owned()),
                                                 lflags = self.gen_lflags_list(),
                                                 target = target,
                                                 obj_list = &self.prepend_op_vec(&Some(obj_vec.clone()), " "),
                                                 lib_dir = self.gen_lib_dir_list(),
                                                 libs = self.gen_lib_list());
                    run_cmd(&cmd_string)?;
                }
            };
        };
        self.run_script(&self.after_script)?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>use self::beacon_chain_harness::BeaconChainHarness;
use self::validator_harness::ValidatorHarness;
use beacon_chain::CheckPoint;
use bls::create_proof_of_possession;
use clap::{App, Arg};
use env_logger::{Builder, Env};
use log::{info, warn};
use ssz::TreeHash;
use std::{fs::File, io::prelude::*};
use types::*;
use types::{
    attester_slashing::AttesterSlashingBuilder, proposer_slashing::ProposerSlashingBuilder,
};
use yaml_rust::{Yaml, YamlLoader};

mod beacon_chain_harness;
mod validator_harness;

fn main() {
    let matches = App::new("Lighthouse Test Harness Runner")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Runs `test_harness` using a YAML manifest.")
        .arg(
            Arg::with_name("yaml")
                .long("yaml")
                .value_name("FILE")
                .help("YAML file manifest.")
                .required(true),
        )
        .get_matches();

    Builder::from_env(Env::default().default_filter_or("debug")).init();

    if let Some(yaml_file) = matches.value_of("yaml") {
        let docs = {
            let mut file = File::open(yaml_file).unwrap();

            let mut yaml_str = String::new();
            file.read_to_string(&mut yaml_str).unwrap();

            YamlLoader::load_from_str(&yaml_str).unwrap()
        };

        for doc in &docs {
            for test_case in doc["test_cases"].as_vec().unwrap() {
                let manifest = Manifest::from_yaml(test_case);
                manifest.assert_result_valid(manifest.execute())
            }
        }
    }
}

struct Manifest {
    pub results: Results,
    pub config: Config,
}

impl Manifest {
    pub fn from_yaml(test_case: &Yaml) -> Self {
        Self {
            results: Results::from_yaml(&test_case["results"]),
            config: Config::from_yaml(&test_case["config"]),
        }
    }

    fn spec(&self) -> ChainSpec {
        let mut spec = ChainSpec::foundation();

        if let Some(n) = self.config.epoch_length {
            spec.epoch_length = n;
        }

        spec
    }

    pub fn execute(&self) -> ExecutionResult {
        let spec = self.spec();
        let validator_count = self.config.deposits_for_chain_start;
        let slots = self.config.num_slots;

        info!(
            "Building BeaconChainHarness with {} validators...",
            validator_count
        );

        let mut harness = BeaconChainHarness::new(spec, validator_count);

        info!("Starting simulation across {} slots...", slots);

        for slot_height in 0..slots {
            // Feed deposits to the BeaconChain.
            if let Some(ref deposits) = self.config.deposits {
                for (slot, deposit, keypair) in deposits {
                    if *slot == slot_height {
                        info!("Including deposit at slot height {}.", slot_height);
                        harness.add_deposit(deposit.clone(), Some(keypair.clone()));
                    }
                }
            }

            // Feed proposer slashings to the BeaconChain.
            if let Some(ref slashings) = self.config.proposer_slashings {
                for (slot, validator_index) in slashings {
                    if *slot == slot_height {
                        info!(
                            "Including proposer slashing at slot height {} for validator #{}.",
                            slot_height, validator_index
                        );
                        let slashing = build_proposer_slashing(&harness, *validator_index);
                        harness.add_proposer_slashing(slashing);
                    }
                }
            }

            // Feed attester slashings to the BeaconChain.
            if let Some(ref slashings) = self.config.attester_slashings {
                for (slot, validator_indices) in slashings {
                    if *slot == slot_height {
                        info!(
                            "Including attester slashing at slot height {} for validators {:?}.",
                            slot_height, validator_indices
                        );
                        let slashing =
                            build_double_vote_attester_slashing(&harness, &validator_indices[..]);
                        harness.add_attester_slashing(slashing);
                    }
                }
            }

            // Build a block or skip a slot.
            match self.config.skip_slots {
                Some(ref skip_slots) if skip_slots.contains(&slot_height) => {
                    warn!("Skipping slot at height {}.", slot_height);
                    harness.increment_beacon_chain_slot();
                }
                _ => {
                    info!("Producing block at slot height {}.", slot_height);
                    harness.advance_chain_with_block();
                }
            }
        }

        harness.run_fork_choice();

        info!("Test execution complete!");

        ExecutionResult {
            chain: harness.chain_dump().expect("Chain dump failed."),
        }
    }

    pub fn assert_result_valid(&self, result: ExecutionResult) {
        info!("Verifying test results...");

        let skipped_slots = self
            .config
            .skip_slots
            .clone()
            .and_then(|slots| Some(slots.len()))
            .unwrap_or_else(|| 0);
        let expected_blocks = self.config.num_slots as usize + 1 - skipped_slots;

        assert_eq!(result.chain.len(), expected_blocks);

        info!(
            "OK: Chain length is {} ({} skipped slots).",
            result.chain.len(),
            skipped_slots
        );

        if let Some(ref skip_slots) = self.config.skip_slots {
            for checkpoint in &result.chain {
                let block_slot = checkpoint.beacon_block.slot.as_u64();
                assert!(
                    !skip_slots.contains(&block_slot),
                    "Slot {} was not skipped.",
                    block_slot
                );
            }
            info!("OK: Skipped slots not present in chain.");
        }

        if let Some(ref deposits) = self.config.deposits {
            let latest_state = &result.chain.last().expect("Empty chain.").beacon_state;
            assert_eq!(
                latest_state.validator_registry.len(),
                self.config.deposits_for_chain_start + deposits.len()
            );
            info!(
                "OK: Validator registry has {} more validators.",
                deposits.len()
            );
        }
    }
}

fn build_double_vote_attester_slashing(
    harness: &BeaconChainHarness,
    validator_indices: &[u64],
) -> AttesterSlashing {
    let signer = |validator_index: u64, message: &[u8], epoch: Epoch, domain: u64| {
        harness
            .validator_sign(validator_index as usize, message, epoch, domain)
            .expect("Unable to sign AttesterSlashing")
    };

    AttesterSlashingBuilder::double_vote(validator_indices, signer, &harness.spec)
}

fn build_proposer_slashing(harness: &BeaconChainHarness, validator_index: u64) -> ProposerSlashing {
    let signer = |validator_index: u64, message: &[u8], epoch: Epoch, domain: u64| {
        harness
            .validator_sign(validator_index as usize, message, epoch, domain)
            .expect("Unable to sign AttesterSlashing")
    };

    ProposerSlashingBuilder::double_vote(validator_index, signer, &harness.spec)
}

pub type DepositTuple = (u64, Deposit, Keypair);
pub type ProposerSlashingTuple = (u64, u64);
pub type AttesterSlashingTuple = (u64, Vec<u64>);

struct ExecutionResult {
    pub chain: Vec<CheckPoint>,
}

struct Results {
    pub num_validators: Option<usize>,
    pub slashed_validators: Option<Vec<u64>>,
    pub exited_validators: Option<Vec<u64>>,
}

impl Results {
    pub fn from_yaml(yaml: &Yaml) -> Self {
        Self {
            num_validators: as_usize(&yaml, "num_validators"),
            slashed_validators: as_vec_u64(&yaml, "slashed_validators"),
            exited_validators: as_vec_u64(&yaml, "exited_validators"),
        }
    }
}

struct Config {
    pub deposits_for_chain_start: usize,
    pub epoch_length: Option<u64>,
    pub num_slots: u64,
    pub skip_slots: Option<Vec<u64>>,
    pub deposits: Option<Vec<DepositTuple>>,
    pub proposer_slashings: Option<Vec<ProposerSlashingTuple>>,
    pub attester_slashings: Option<Vec<AttesterSlashingTuple>>,
}

impl Config {
    pub fn from_yaml(yaml: &Yaml) -> Self {
        Self {
            deposits_for_chain_start: as_usize(&yaml, "deposits_for_chain_start")
                .expect("Must specify validator count"),
            epoch_length: as_u64(&yaml, "epoch_length"),
            num_slots: as_u64(&yaml, "num_slots").expect("Must specify `config.num_slots`"),
            skip_slots: as_vec_u64(yaml, "skip_slots"),
            deposits: parse_deposits(&yaml),
            proposer_slashings: parse_proposer_slashings(&yaml),
            attester_slashings: parse_attester_slashings(&yaml),
        }
    }
}

fn parse_attester_slashings(yaml: &Yaml) -> Option<Vec<AttesterSlashingTuple>> {
    let mut slashings = vec![];

    for slashing in yaml["attester_slashings"].as_vec()? {
        let slot = as_u64(slashing, "slot").expect("Incomplete attester_slashing (slot)");
        let validator_indices = as_vec_u64(slashing, "validator_indices")
            .expect("Incomplete attester_slashing (validator_indices)");

        slashings.push((slot, validator_indices));
    }

    Some(slashings)
}

fn parse_proposer_slashings(yaml: &Yaml) -> Option<Vec<ProposerSlashingTuple>> {
    let mut slashings = vec![];

    for slashing in yaml["proposer_slashings"].as_vec()? {
        let slot = as_u64(slashing, "slot").expect("Incomplete proposer slashing (slot)_");
        let validator_index = as_u64(slashing, "validator_index")
            .expect("Incomplete proposer slashing (validator_index)");

        slashings.push((slot, validator_index));
    }

    Some(slashings)
}

fn parse_deposits(yaml: &Yaml) -> Option<Vec<DepositTuple>> {
    let mut deposits = vec![];

    for deposit in yaml["deposits"].as_vec()? {
        let keypair = Keypair::random();
        let proof_of_possession = create_proof_of_possession(&keypair);

        let slot = as_u64(deposit, "slot").expect("Incomplete deposit");
        let deposit = Deposit {
            branch: vec![],
            index: as_u64(deposit, "merkle_index").unwrap(),
            deposit_data: DepositData {
                amount: 32_000_000_000,
                timestamp: 1,
                deposit_input: DepositInput {
                    pubkey: keypair.pk.clone(),
                    withdrawal_credentials: Hash256::zero(),
                    proof_of_possession,
                },
            },
        };

        deposits.push((slot, deposit, keypair));
    }

    Some(deposits)
}

fn as_usize(yaml: &Yaml, key: &str) -> Option<usize> {
    yaml[key].as_i64().and_then(|n| Some(n as usize))
}

fn as_u64(yaml: &Yaml, key: &str) -> Option<u64> {
    yaml[key].as_i64().and_then(|n| Some(n as u64))
}

fn as_hash256(yaml: &Yaml, key: &str) -> Option<Hash256> {
    yaml[key]
        .as_str()
        .and_then(|s| Some(Hash256::from(s.as_bytes())))
}

fn as_vec_u64(yaml: &Yaml, key: &str) -> Option<Vec<u64>> {
    yaml[key].clone().into_vec().and_then(|vec| {
        Some(
            vec.iter()
                .map(|item| item.as_i64().unwrap() as u64)
                .collect(),
        )
    })
}
<commit_msg>Fix warnings in test_harness/src/bin.rs<commit_after>use self::beacon_chain_harness::BeaconChainHarness;
use self::validator_harness::ValidatorHarness;
use beacon_chain::CheckPoint;
use bls::create_proof_of_possession;
use clap::{App, Arg};
use env_logger::{Builder, Env};
use log::{info, warn};
use std::{fs::File, io::prelude::*};
use types::*;
use types::{
    attester_slashing::AttesterSlashingBuilder, proposer_slashing::ProposerSlashingBuilder,
};
use yaml_rust::{Yaml, YamlLoader};

mod beacon_chain_harness;
mod validator_harness;

fn main() {
    let matches = App::new("Lighthouse Test Harness Runner")
        .version("0.0.1")
        .author("Sigma Prime <contact@sigmaprime.io>")
        .about("Runs `test_harness` using a YAML manifest.")
        .arg(
            Arg::with_name("yaml")
                .long("yaml")
                .value_name("FILE")
                .help("YAML file manifest.")
                .required(true),
        )
        .get_matches();

    Builder::from_env(Env::default().default_filter_or("debug")).init();

    if let Some(yaml_file) = matches.value_of("yaml") {
        let docs = {
            let mut file = File::open(yaml_file).unwrap();

            let mut yaml_str = String::new();
            file.read_to_string(&mut yaml_str).unwrap();

            YamlLoader::load_from_str(&yaml_str).unwrap()
        };

        for doc in &docs {
            for test_case in doc["test_cases"].as_vec().unwrap() {
                let manifest = Manifest::from_yaml(test_case);
                manifest.assert_result_valid(manifest.execute())
            }
        }
    }
}

struct Manifest {
    pub results: Results,
    pub config: Config,
}

impl Manifest {
    pub fn from_yaml(test_case: &Yaml) -> Self {
        Self {
            results: Results::from_yaml(&test_case["results"]),
            config: Config::from_yaml(&test_case["config"]),
        }
    }

    fn spec(&self) -> ChainSpec {
        let mut spec = ChainSpec::foundation();

        if let Some(n) = self.config.epoch_length {
            spec.epoch_length = n;
        }

        spec
    }

    pub fn execute(&self) -> ExecutionResult {
        let spec = self.spec();
        let validator_count = self.config.deposits_for_chain_start;
        let slots = self.config.num_slots;

        info!(
            "Building BeaconChainHarness with {} validators...",
            validator_count
        );

        let mut harness = BeaconChainHarness::new(spec, validator_count);

        info!("Starting simulation across {} slots...", slots);

        for slot_height in 0..slots {
            // Feed deposits to the BeaconChain.
            if let Some(ref deposits) = self.config.deposits {
                for (slot, deposit, keypair) in deposits {
                    if *slot == slot_height {
                        info!("Including deposit at slot height {}.", slot_height);
                        harness.add_deposit(deposit.clone(), Some(keypair.clone()));
                    }
                }
            }

            // Feed proposer slashings to the BeaconChain.
            if let Some(ref slashings) = self.config.proposer_slashings {
                for (slot, validator_index) in slashings {
                    if *slot == slot_height {
                        info!(
                            "Including proposer slashing at slot height {} for validator #{}.",
                            slot_height, validator_index
                        );
                        let slashing = build_proposer_slashing(&harness, *validator_index);
                        harness.add_proposer_slashing(slashing);
                    }
                }
            }

            // Feed attester slashings to the BeaconChain.
            if let Some(ref slashings) = self.config.attester_slashings {
                for (slot, validator_indices) in slashings {
                    if *slot == slot_height {
                        info!(
                            "Including attester slashing at slot height {} for validators {:?}.",
                            slot_height, validator_indices
                        );
                        let slashing =
                            build_double_vote_attester_slashing(&harness, &validator_indices[..]);
                        harness.add_attester_slashing(slashing);
                    }
                }
            }

            // Build a block or skip a slot.
            match self.config.skip_slots {
                Some(ref skip_slots) if skip_slots.contains(&slot_height) => {
                    warn!("Skipping slot at height {}.", slot_height);
                    harness.increment_beacon_chain_slot();
                }
                _ => {
                    info!("Producing block at slot height {}.", slot_height);
                    harness.advance_chain_with_block();
                }
            }
        }

        harness.run_fork_choice();

        info!("Test execution complete!");

        ExecutionResult {
            chain: harness.chain_dump().expect("Chain dump failed."),
        }
    }

    pub fn assert_result_valid(&self, result: ExecutionResult) {
        info!("Verifying test results...");

        let skipped_slots = self
            .config
            .skip_slots
            .clone()
            .and_then(|slots| Some(slots.len()))
            .unwrap_or_else(|| 0);
        let expected_blocks = self.config.num_slots as usize + 1 - skipped_slots;

        assert_eq!(result.chain.len(), expected_blocks);

        info!(
            "OK: Chain length is {} ({} skipped slots).",
            result.chain.len(),
            skipped_slots
        );

        if let Some(ref skip_slots) = self.config.skip_slots {
            for checkpoint in &result.chain {
                let block_slot = checkpoint.beacon_block.slot.as_u64();
                assert!(
                    !skip_slots.contains(&block_slot),
                    "Slot {} was not skipped.",
                    block_slot
                );
            }
            info!("OK: Skipped slots not present in chain.");
        }

        if let Some(ref deposits) = self.config.deposits {
            let latest_state = &result.chain.last().expect("Empty chain.").beacon_state;
            assert_eq!(
                latest_state.validator_registry.len(),
                self.config.deposits_for_chain_start + deposits.len()
            );
            info!(
                "OK: Validator registry has {} more validators.",
                deposits.len()
            );
        }
    }
}

fn build_double_vote_attester_slashing(
    harness: &BeaconChainHarness,
    validator_indices: &[u64],
) -> AttesterSlashing {
    let signer = |validator_index: u64, message: &[u8], epoch: Epoch, domain: u64| {
        harness
            .validator_sign(validator_index as usize, message, epoch, domain)
            .expect("Unable to sign AttesterSlashing")
    };

    AttesterSlashingBuilder::double_vote(validator_indices, signer, &harness.spec)
}

fn build_proposer_slashing(harness: &BeaconChainHarness, validator_index: u64) -> ProposerSlashing {
    let signer = |validator_index: u64, message: &[u8], epoch: Epoch, domain: u64| {
        harness
            .validator_sign(validator_index as usize, message, epoch, domain)
            .expect("Unable to sign AttesterSlashing")
    };

    ProposerSlashingBuilder::double_vote(validator_index, signer, &harness.spec)
}

pub type DepositTuple = (u64, Deposit, Keypair);
pub type ProposerSlashingTuple = (u64, u64);
pub type AttesterSlashingTuple = (u64, Vec<u64>);

struct ExecutionResult {
    pub chain: Vec<CheckPoint>,
}

struct Results {
    pub num_validators: Option<usize>,
    pub slashed_validators: Option<Vec<u64>>,
    pub exited_validators: Option<Vec<u64>>,
}

impl Results {
    pub fn from_yaml(yaml: &Yaml) -> Self {
        Self {
            num_validators: as_usize(&yaml, "num_validators"),
            slashed_validators: as_vec_u64(&yaml, "slashed_validators"),
            exited_validators: as_vec_u64(&yaml, "exited_validators"),
        }
    }
}

struct Config {
    pub deposits_for_chain_start: usize,
    pub epoch_length: Option<u64>,
    pub num_slots: u64,
    pub skip_slots: Option<Vec<u64>>,
    pub deposits: Option<Vec<DepositTuple>>,
    pub proposer_slashings: Option<Vec<ProposerSlashingTuple>>,
    pub attester_slashings: Option<Vec<AttesterSlashingTuple>>,
}

impl Config {
    pub fn from_yaml(yaml: &Yaml) -> Self {
        Self {
            deposits_for_chain_start: as_usize(&yaml, "deposits_for_chain_start")
                .expect("Must specify validator count"),
            epoch_length: as_u64(&yaml, "epoch_length"),
            num_slots: as_u64(&yaml, "num_slots").expect("Must specify `config.num_slots`"),
            skip_slots: as_vec_u64(yaml, "skip_slots"),
            deposits: parse_deposits(&yaml),
            proposer_slashings: parse_proposer_slashings(&yaml),
            attester_slashings: parse_attester_slashings(&yaml),
        }
    }
}

fn parse_attester_slashings(yaml: &Yaml) -> Option<Vec<AttesterSlashingTuple>> {
    let mut slashings = vec![];

    for slashing in yaml["attester_slashings"].as_vec()? {
        let slot = as_u64(slashing, "slot").expect("Incomplete attester_slashing (slot)");
        let validator_indices = as_vec_u64(slashing, "validator_indices")
            .expect("Incomplete attester_slashing (validator_indices)");

        slashings.push((slot, validator_indices));
    }

    Some(slashings)
}

fn parse_proposer_slashings(yaml: &Yaml) -> Option<Vec<ProposerSlashingTuple>> {
    let mut slashings = vec![];

    for slashing in yaml["proposer_slashings"].as_vec()? {
        let slot = as_u64(slashing, "slot").expect("Incomplete proposer slashing (slot)_");
        let validator_index = as_u64(slashing, "validator_index")
            .expect("Incomplete proposer slashing (validator_index)");

        slashings.push((slot, validator_index));
    }

    Some(slashings)
}

fn parse_deposits(yaml: &Yaml) -> Option<Vec<DepositTuple>> {
    let mut deposits = vec![];

    for deposit in yaml["deposits"].as_vec()? {
        let keypair = Keypair::random();
        let proof_of_possession = create_proof_of_possession(&keypair);

        let slot = as_u64(deposit, "slot").expect("Incomplete deposit");
        let deposit = Deposit {
            branch: vec![],
            index: as_u64(deposit, "merkle_index").unwrap(),
            deposit_data: DepositData {
                amount: 32_000_000_000,
                timestamp: 1,
                deposit_input: DepositInput {
                    pubkey: keypair.pk.clone(),
                    withdrawal_credentials: Hash256::zero(),
                    proof_of_possession,
                },
            },
        };

        deposits.push((slot, deposit, keypair));
    }

    Some(deposits)
}

fn as_usize(yaml: &Yaml, key: &str) -> Option<usize> {
    yaml[key].as_i64().and_then(|n| Some(n as usize))
}

fn as_u64(yaml: &Yaml, key: &str) -> Option<u64> {
    yaml[key].as_i64().and_then(|n| Some(n as u64))
}

fn as_vec_u64(yaml: &Yaml, key: &str) -> Option<Vec<u64>> {
    yaml[key].clone().into_vec().and_then(|vec| {
        Some(
            vec.iter()
                .map(|item| item.as_i64().unwrap() as u64)
                .collect(),
        )
    })
}
<|endoftext|>


<commit_before>fn insert<T: Clone>(elem: T, list: &[T], k: uint) -> ~[T] {
    let mut res = ~[];
    res.push_all(list.slice_to(k-1));
    res.push(elem);
    res.push_all(list.slice_from(k));
    res
}

fn main() {
    let list = ~['a', 'b', 'c', 'd'];
    println!("{:?}", insert('X', list, 2));
}

<commit_msg>Cleanup Problem 21<commit_after>// The author of this work hereby waives all claim of copyright (economic and
// moral) in this work and immediately places it in the public domain; it may
// be used, distorted or destroyed in any manner whatsoever without further
// attribution or notice to the creator.

//! Problem 21: Vectors: insert
//!
//! Insert an element at a given position into a vector.  Start counting vector
//! elements with 0. If the position is larger or equal to the length of the
//! vector, insert the element at the end.
//!
//! Your function could have this signature:
//! `fn insert<T>(elem: T, vec: Vec<T>, k: uint) -> Vec<T>`

use std::cmp::min;

fn insert<T>(elem: T, vec: Vec<T>, k: uint) -> Vec<T> {
    let mut vec = vec;
    let l = vec.len();
    vec.insert(min(k, l), elem);
    vec
}

#[test]
fn insert_in() {
    let vec = vec!('a', 'b', 'c', 'd');
    assert_eq!(insert('X', vec, 2), vec!('a', 'b', 'X', 'c', 'd'));
}

#[test]
fn insert_out() {
    let vec = vec!('a', 'b', 'c', 'd');
    assert_eq!(insert('X', vec, 10), vec!('a', 'b', 'c', 'd', 'X'));
}

<|endoftext|>


<commit_before>use JITVal = jit::Value;
use jit::{
    get_type,
    Function,
    Compile,
    UByte,
    SysChar,
    SysBool,
    NInt,
    NUInt,
    Int,
    UInt,
    Pointer,
    Float64
};
use JSVal = front::stdlib::value::Value;
use front::stdlib::value::{Value, VNull, to_value};
use front::stdlib::value::ResultValue;
use front::run::executor::Executor;
use std::gc::GC;
use std::c_str::CString;
/// A JIT executor
pub struct JitExecutor {
    global: JSVal
}
impl JitExecutor {
    /// Create a new JIT executor
    pub fn new() -> JitExecutor {
        JitExecutor {
            global: Value::new_global()
        }
    }

}
impl<'a> Executor<(JITVal<'a>, &'a Function<'a>)> for JitExecutor {
    #[inline]
    fn get_global_obj(&self) -> JSVal {
        self.global
    }
    fn execute(&self, comp:&(JITVal<'a>, &'a Function<'a>)) -> ResultValue {
        let &(ref val, ref func) = comp;
        func.insn_return(&convert_to_value(*func, val));
        func.set_optimization_level(5);
        func.set_recompilable();
        func.compile();
        Ok(func.with_closure3(|run:fn(JSVal, JSVal, JSVal) -> JSVal| {
            run(self.global, self.global, self.global)
        }))
    }
}

fn convert_to_value<'a>(func:&Function<'a>, val:&'a JITVal<'a>) -> JITVal<'a> {
    let val_type = val.get_type();
    let val_kind = val_type.get_kind();
    if val_kind.contains(SysBool) || val_kind.contains(UByte) {
        let bool_value = to_value::<bool>;
        let sig = get_type::<fn(bool) -> *const int>();
        func.insn_call_native1(Some("bool_value"), bool_value, sig, &mut [val])
    } else if val_kind.contains(Pointer) {
        let ref_t = val_type.get_ref();
        if ref_t.get_kind().contains(SysChar) {
            fn string_value(val: &i8) -> JSVal {
                unsafe {
                    let text = CString::new(val, false);
                    to_value(text.as_str().unwrap().into_string())
                }
            }
            let sig = get_type::<fn(String) -> *const int>();
            func.insn_call_native1(Some("string_value"), string_value, sig, &mut [val])
        } else {
            fn ptr_value(ptr: &i8) -> JSVal {
                match ptr.to_uint() {
                    0u => JSVal::undefined(),
                    1u => JSVal {
                        ptr: box(GC) VNull
                    },
                    ptr => fail!("Invalid pointer: {}", ptr)
                }
            }
            let sig = get_type::<fn(*const i8) -> *const int>();
            func.insn_call_native1(Some("ptr_value"), ptr_value, &sig, &mut [val])
        }
    } else if val_kind.contains(Int) || val_kind.contains(UInt) {
        let int_value = to_value::<i32>;
        let sig = get_type::<fn(i32) -> *const int>();
        func.insn_call_native1(Some("int_value"), int_value, &sig, &mut [val])
    } else if val_kind.contains(NInt) || val_kind.contains(NUInt) {
        fn sys_int_value(num:int) -> JSVal {
            to_value::<i32>(num as i32)
        }
        let sig = get_type::<fn(int) -> *const int>();
        func.insn_call_native1(Some("sys_int_value"), sys_int_value, &sig, &mut [val])
    } else if val_kind.contains(Float64) {
        let float_value = to_value::<f64>;
        let sig = get_type::<fn(f64) -> *const int>();
        func.insn_call_native1(Some("float_value"), float_value, &sig, &mut [val])
    } else {
        fail!("Invalid kind {}", val_kind.bits())
    }
}<commit_msg>More updates for latest `jit.rs`<commit_after>use JITVal = jit::Value;
use jit::{
    get_type,
    Function,
    Compile,
    UByte,
    SysChar,
    SysBool,
    NInt,
    NUInt,
    Int,
    UInt,
    Pointer,
    Float64
};
use JSVal = front::stdlib::value::Value;
use front::stdlib::value::{Value, VNull, to_value};
use front::stdlib::value::ResultValue;
use front::run::executor::Executor;
use std::gc::GC;
use std::c_str::CString;
/// A JIT executor
pub struct JitExecutor {
    global: JSVal
}
impl JitExecutor {
    /// Create a new JIT executor
    pub fn new() -> JitExecutor {
        JitExecutor {
            global: Value::new_global()
        }
    }

}
impl<'a> Executor<(JITVal<'a>, &'a Function<'a>)> for JitExecutor {
    #[inline]
    fn get_global_obj(&self) -> JSVal {
        self.global
    }
    fn execute(&self, comp:&(JITVal<'a>, &'a Function<'a>)) -> ResultValue {
        let &(ref val, ref func) = comp;
        func.insn_return(&convert_to_value(*func, val));
        func.set_optimization_level(5);
        func.set_recompilable();
        func.compile();
        Ok(func.with_closure3(|run:fn(JSVal, JSVal, JSVal) -> JSVal| {
            run(self.global, self.global, self.global)
        }))
    }
}

fn convert_to_value<'a>(func:&Function<'a>, val:&'a JITVal<'a>) -> JITVal<'a> {
    let val_type = val.get_type();
    let val_kind = val_type.get_kind();
    if val_kind.contains(SysBool) || val_kind.contains(UByte) {
        let bool_value = to_value::<bool>;
        let sig = get_type::<fn(bool) -> *const int>();
        func.insn_call_native1(Some("bool_value"), bool_value, sig, &mut [val])
    } else if val_kind.contains(Pointer) {
        let ref_t = val_type.get_ref();
        if ref_t.get_kind().contains(SysChar) {
            fn string_value(val: &i8) -> JSVal {
                unsafe {
                    let text = CString::new(val, false);
                    to_value(text.as_str().unwrap().into_string())
                }
            }
            let sig = get_type::<fn(String) -> *const int>();
            func.insn_call_native1(Some("string_value"), string_value, sig, &mut [val])
        } else {
            fn ptr_value(ptr: &i8) -> JSVal {
                match ptr.to_uint() {
                    Some(0u) => JSVal::undefined(),
                    Some(1u) => JSVal {
                        ptr: box(GC) VNull
                    },
                    ptr => fail!("Invalid pointer: {}", ptr)
                }
            }
            let sig = get_type::<fn(*const i8) -> *const int>();
            func.insn_call_native1(Some("ptr_value"), ptr_value, sig, &mut [val])
        }
    } else if val_kind.contains(Int) || val_kind.contains(UInt) {
        let int_value = to_value::<i32>;
        let sig = get_type::<fn(i32) -> *const int>();
        func.insn_call_native1(Some("int_value"), int_value, sig, &mut [val])
    } else if val_kind.contains(NInt) || val_kind.contains(NUInt) {
        fn sys_int_value(num:int) -> JSVal {
            to_value::<i32>(num as i32)
        }
        let sig = get_type::<fn(int) -> *const int>();
        func.insn_call_native1(Some("sys_int_value"), sys_int_value, sig, &mut [val])
    } else if val_kind.contains(Float64) {
        let float_value = to_value::<f64>;
        let sig = get_type::<fn(f64) -> *const int>();
        func.insn_call_native1(Some("float_value"), float_value, sig, &mut [val])
    } else {
        fail!("Invalid kind {}", val_kind.bits())
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;

use ffi;

use gles::{self, Context3d, TextureBuffer, TexFormat};
use ppb::{get_video_decoder_opt, VideoDecoderIf};

use super::{GenericResource, Resource, ResourceType, Callback, Code,
            CallbackArgs, StorageToArgsMapper};

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct VideoDecoder(GenericResource);
impl Resource for VideoDecoder {
    fn unwrap(&self) -> ffi::PP_Resource { self.0.unwrap() }
    fn type_of(&self) -> Option<ResourceType> { Some(ResourceType::VideoDecoder) }
}
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoDecoder {
    fn from(v: ffi::PP_Resource) -> VideoDecoder {
        VideoDecoder(From::from(v))
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum H264Profile {
    BaseLine,
    Main,
    Extended,
    High,
    High10,
    High422,
    High444Predictive,
    ScalableBaseLine,
    ScalableHigh,
    StereoHigh,
    MultiViewHigh,
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for H264Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::H264Profile::*;
        match self {
            BaseLine => ffi::PP_VIDEOPROFILE_H264BASELINE,
            Main => ffi::PP_VIDEOPROFILE_H264MAIN,
            Extended => ffi::PP_VIDEOPROFILE_H264EXTENDED,
            High => ffi::PP_VIDEOPROFILE_H264HIGH,
            High10 => ffi::PP_VIDEOPROFILE_H264HIGH10PROFILE,
            High422 => ffi::PP_VIDEOPROFILE_H264HIGH422PROFILE,
            High444Predictive => ffi::PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE,
            ScalableBaseLine => ffi::PP_VIDEOPROFILE_H264SCALABLEBASELINE,
            ScalableHigh => ffi::PP_VIDEOPROFILE_H264SCALABLEHIGH,
            StereoHigh => ffi::PP_VIDEOPROFILE_H264STEREOHIGH,
            MultiViewHigh => ffi::PP_VIDEOPROFILE_H264MULTIVIEWHIGH,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Profile {
    VP9,
    VP8,
    H264(H264Profile),
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::Profile::*;
        match self {
            H264(v) => v.into(),
            VP9 => ffi::PP_VIDEOPROFILE_VP9_ANY,
            VP8 => ffi::PP_VIDEOPROFILE_VP8_ANY,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Acceleration {
    Hardware { with_fallback: bool },
    Software,
}
#[doc(hidden)]
impl Into<ffi::PP_HardwareAcceleration> for Acceleration {
    fn into(self) -> ffi::PP_HardwareAcceleration {
        match self {
            Acceleration::Hardware { with_fallback: false, } =>
                ffi::PP_HARDWAREACCELERATION_ONLY,
            Acceleration::Hardware { with_fallback: true,  } =>
                ffi::PP_HARDWAREACCELERATION_WITHFALLBACK,
            Acceleration::Software =>
                ffi::PP_HARDWAREACCELERATION_NONE,
        }
    }
}
impl Default for Acceleration {
    fn default() -> Acceleration { Acceleration::Hardware { with_fallback: true } }
}

pub struct Frame {
    pub tag: u32,
    texture: TextureBuffer,
    texture_target: gles::types::Enum,
    pub texture_size: super::Size,
    pub visible_rect: super::Rect,
}
impl Frame {
    pub fn format(&self) -> TexFormat { TexFormat::Rgba }
}
impl From<ffi::Struct_PP_VideoPicture> for Frame {
    fn from(raw: ffi::Struct_PP_VideoPicture) -> Frame {
        Frame {
            tag: raw.decode_id,
            texture: From::from(raw.texture_id),
            texture_target: From::from(raw.texture_target),
            texture_size: From::from(raw.texture_size),
            visible_rect: From::from(raw.visible_rect),
        }
    }
}
impl Into<ffi::Struct_PP_VideoPicture> for Frame {
    fn into(self) -> ffi::Struct_PP_VideoPicture {
        use gles::traits::Buffer;
        ffi::Struct_PP_VideoPicture {
            decode_id: self.tag,
            texture_id: self.texture.unwrap(),
            texture_target: self.texture_target,
            texture_size: self.texture_size.into(),
            visible_rect: self.visible_rect.into(),
        }
    }
}
impl gles::traits::BindableBuffer for Frame {
    type Target = gles::BoundTexBuffer;
    fn bind(&self, ctxt: &mut Context3d) -> gles::BoundTexBuffer {
        use gles::traits::BindableTargetBuffer;
        self.texture.bind(ctxt, self.texture_target)
    }
}

impl VideoDecoder {
    pub fn initialize<F>(&self, g3d: Context3d, profile: Profile,
                         accel: Acceleration, callback: F) -> Code
        where F: Callback,
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.initialize(self.unwrap(), g3d.unwrap(), profile.into(),
                                        accel.into(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    /// PPAPI allocates it's own copy of the data before returning.
    pub fn decode<'a, F>(&self, decode_tag: u32, data: Cow<'a, [u8]>, callback: F) -> Code
        where F: Callback
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.decode(self.unwrap(), decode_tag,
                                    data.as_ref().len(), data.as_ref().as_ptr(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn flush<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.flush(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn reset<F>(&self, callback: F) -> Code where F: Callback {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback();
                let code = i.reset(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn get_picture<F>(&self, callback: CallbackArgs<F, Frame>) ->
        Code<Frame> where F: FnOnce(Code<Frame>)
    {
        impl super::InPlaceInit for ffi::Struct_PP_VideoPicture { }
        fn arg_map(raw: ffi::Struct_PP_VideoPicture, _status: Code) -> Frame {
            From::from(raw)
        }
        get_video_decoder_opt()
            .map(move |i| {
                let raw: ffi::Struct_PP_VideoPicture = Default::default();
                let mapper = StorageToArgsMapper(arg_map);
                let cc = callback.to_ffi_callback(raw, mapper);
                let code = i.get_picture(self.unwrap(), cc.raw_args(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn recycle(&self, frame: Frame) {
        get_video_decoder_opt()
            .map(move |i| {
                let ffi: ffi::Struct_PP_VideoPicture =
                    frame.into();
                i.recycle_picture(self.unwrap(), &ffi)
            });
    }
}
<commit_msg>Change `VideoDecoder`s functions so they accept the new callback type.<commit_after>// Copyright (c) 2014 Richard Diamond & contributors.
//
// This file is part of the Rust PPApi project.
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::borrow::Cow;

use ffi;

use gles::{self, Context3d, TextureBuffer, TexFormat};
use ppb::{get_video_decoder_opt, VideoDecoderIf};

use super::{GenericResource, Resource, ResourceType, Callback, Code,
            CallbackArgs, StorageToArgsMapper};

#[derive(Clone, Eq, PartialEq, Hash, Debug)]
pub struct VideoDecoder(GenericResource);
impl Resource for VideoDecoder {
    fn unwrap(&self) -> ffi::PP_Resource { self.0.unwrap() }
    fn type_of(&self) -> Option<ResourceType> { Some(ResourceType::VideoDecoder) }
}
#[doc(hidden)]
impl From<ffi::PP_Resource> for VideoDecoder {
    fn from(v: ffi::PP_Resource) -> VideoDecoder {
        VideoDecoder(From::from(v))
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum H264Profile {
    BaseLine,
    Main,
    Extended,
    High,
    High10,
    High422,
    High444Predictive,
    ScalableBaseLine,
    ScalableHigh,
    StereoHigh,
    MultiViewHigh,
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for H264Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::H264Profile::*;
        match self {
            BaseLine => ffi::PP_VIDEOPROFILE_H264BASELINE,
            Main => ffi::PP_VIDEOPROFILE_H264MAIN,
            Extended => ffi::PP_VIDEOPROFILE_H264EXTENDED,
            High => ffi::PP_VIDEOPROFILE_H264HIGH,
            High10 => ffi::PP_VIDEOPROFILE_H264HIGH10PROFILE,
            High422 => ffi::PP_VIDEOPROFILE_H264HIGH422PROFILE,
            High444Predictive => ffi::PP_VIDEOPROFILE_H264HIGH444PREDICTIVEPROFILE,
            ScalableBaseLine => ffi::PP_VIDEOPROFILE_H264SCALABLEBASELINE,
            ScalableHigh => ffi::PP_VIDEOPROFILE_H264SCALABLEHIGH,
            StereoHigh => ffi::PP_VIDEOPROFILE_H264STEREOHIGH,
            MultiViewHigh => ffi::PP_VIDEOPROFILE_H264MULTIVIEWHIGH,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Profile {
    VP9,
    VP8,
    H264(H264Profile),
}
#[doc(hidden)]
impl Into<ffi::PP_VideoProfile> for Profile {
    fn into(self) -> ffi::PP_VideoProfile {
        use self::Profile::*;
        match self {
            H264(v) => v.into(),
            VP9 => ffi::PP_VIDEOPROFILE_VP9_ANY,
            VP8 => ffi::PP_VIDEOPROFILE_VP8_ANY,
        }
    }
}

#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
pub enum Acceleration {
    Hardware { with_fallback: bool },
    Software,
}
#[doc(hidden)]
impl Into<ffi::PP_HardwareAcceleration> for Acceleration {
    fn into(self) -> ffi::PP_HardwareAcceleration {
        match self {
            Acceleration::Hardware { with_fallback: false, } =>
                ffi::PP_HARDWAREACCELERATION_ONLY,
            Acceleration::Hardware { with_fallback: true,  } =>
                ffi::PP_HARDWAREACCELERATION_WITHFALLBACK,
            Acceleration::Software =>
                ffi::PP_HARDWAREACCELERATION_NONE,
        }
    }
}
impl Default for Acceleration {
    fn default() -> Acceleration { Acceleration::Hardware { with_fallback: true } }
}

pub struct Frame {
    pub tag: u32,
    texture: TextureBuffer,
    texture_target: gles::types::Enum,
    pub texture_size: super::Size,
    pub visible_rect: super::Rect,
}
impl Frame {
    pub fn format(&self) -> TexFormat { TexFormat::Rgba }
}
impl From<ffi::Struct_PP_VideoPicture> for Frame {
    fn from(raw: ffi::Struct_PP_VideoPicture) -> Frame {
        Frame {
            tag: raw.decode_id,
            texture: From::from(raw.texture_id),
            texture_target: From::from(raw.texture_target),
            texture_size: From::from(raw.texture_size),
            visible_rect: From::from(raw.visible_rect),
        }
    }
}
impl Into<ffi::Struct_PP_VideoPicture> for Frame {
    fn into(self) -> ffi::Struct_PP_VideoPicture {
        use gles::traits::Buffer;
        ffi::Struct_PP_VideoPicture {
            decode_id: self.tag,
            texture_id: self.texture.unwrap(),
            texture_target: self.texture_target,
            texture_size: self.texture_size.into(),
            visible_rect: self.visible_rect.into(),
        }
    }
}
impl gles::traits::BindableBuffer for Frame {
    type Target = gles::BoundTexBuffer;
    fn bind(&self, ctxt: &mut Context3d) -> gles::BoundTexBuffer {
        use gles::traits::BindableTargetBuffer;
        self.texture.bind(ctxt, self.texture_target)
    }
}

impl VideoDecoder {
    pub fn initialize<F>(&self, g3d: Context3d, profile: Profile,
                         accel: Acceleration, callback: CallbackArgs<F, ()>) -> Code<()>
        where F: FnOnce(Code<()>),
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback((), Default::default());
                let code = i.initialize(self.unwrap(), g3d.unwrap(), profile.into(),
                                        accel.into(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    /// PPAPI allocates it's own copy of the data before returning.
    pub fn decode<'a, F>(&self, decode_tag: u32, data: Cow<'a, [u8]>,
                         callback: CallbackArgs<F, ()>) -> Code<()>
        where F: FnOnce(Code<()>)
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback((), Default::default());
                let code = i.decode(self.unwrap(), decode_tag,
                                    data.as_ref().len(), data.as_ref().as_ptr(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn flush<F>(&self, callback: CallbackArgs<F, ()>) -> Code<()>
        where F: FnOnce(Code<()>)
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback((), Default::default());
                let code = i.flush(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn reset<F>(&self, callback: CallbackArgs<F, ()>) -> Code<()>
        where F: FnOnce(Code<()>)
    {
        get_video_decoder_opt()
            .map(move |i| {
                let cc = callback.to_ffi_callback((), Default::default());
                let code = i.reset(self.unwrap(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn get_picture<F>(&self, callback: CallbackArgs<F, Frame>) ->
        Code<Frame> where F: FnOnce(Code<Frame>)
    {
        impl super::InPlaceInit for ffi::Struct_PP_VideoPicture { }
        fn arg_map(raw: ffi::Struct_PP_VideoPicture, _status: Code) -> Frame {
            From::from(raw)
        }
        get_video_decoder_opt()
            .map(move |i| {
                let raw: ffi::Struct_PP_VideoPicture = Default::default();
                let mapper = StorageToArgsMapper(arg_map);
                let cc = callback.to_ffi_callback(raw, mapper);
                let code = i.get_picture(self.unwrap(), cc.raw_args(), cc.cc());
                cc.drop_with_code(code)
            })
            .unwrap_or(Code::NoInterface)
    }
    pub fn recycle(&self, frame: Frame) {
        get_video_decoder_opt()
            .map(move |i| {
                let ffi: ffi::Struct_PP_VideoPicture =
                    frame.into();
                i.recycle_picture(self.unwrap(), &ffi)
            });
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 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.

/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accomodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accomodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut T {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> DerefMut for &'a mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}
<commit_msg>Rollup merge of #43868 - lukaramu:issue-43866, r=steveklabnik<commit_after>// Copyright 2012 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.

/// Used for immutable dereferencing operations, like `*v`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in immutable contexts, `Deref` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In mutable contexts, [`DerefMut`] is used.
///
/// Implementing `Deref` for smart pointers makes accessing the data behind them
/// convenient, which is why they implement `Deref`. On the other hand, the
/// rules regarding `Deref` and [`DerefMut`] were designed specifically to
/// accomodate smart pointers. Because of this, **`Deref` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `Deref` is invoked implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `Deref<Target = U>`, and `x` is a value of type `T`, then:
///
/// * In immutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&T` are coerced to values of type `&U`
/// * `T` implicitly implements all the (immutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`DerefMut`]: trait.DerefMut.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is accessible by dereferencing the
/// struct.
///
/// ```
/// use std::ops::Deref;
///
/// struct DerefExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// let x = DerefExample { value: 'a' };
/// assert_eq!('a', *x);
/// ```
#[lang = "deref"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
    /// The resulting type after dereferencing.
    #[stable(feature = "rust1", since = "1.0.0")]
    type Target: ?Sized;

    /// Dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref(&self) -> &Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> Deref for &'a mut T {
    type Target = T;

    fn deref(&self) -> &T { *self }
}

/// Used for mutable dereferencing operations, like in `*v = 1;`.
///
/// In addition to being used for explicit dereferencing operations with the
/// (unary) `*` operator in mutable contexts, `DerefMut` is also used implicitly
/// by the compiler in many circumstances. This mechanism is called
/// ['`Deref` coercion'][more]. In immutable contexts, [`Deref`] is used.
///
/// Implementing `DerefMut` for smart pointers makes mutating the data behind
/// them convenient, which is why they implement `DerefMut`. On the other hand,
/// the rules regarding [`Deref`] and `DerefMut` were designed specifically to
/// accomodate smart pointers. Because of this, **`DerefMut` should only be
/// implemented for smart pointers** to avoid confusion.
///
/// For similar reasons, **this trait should never fail**. Failure during
/// dereferencing can be extremely confusing when `DerefMut` is invoked
/// implicitly.
///
/// # More on `Deref` coercion
///
/// If `T` implements `DerefMut<Target = U>`, and `x` is a value of type `T`,
/// then:
///
/// * In mutable contexts, `*x` on non-pointer types is equivalent to
///   `*Deref::deref(&x)`.
/// * Values of type `&mut T` are coerced to values of type `&mut U`
/// * `T` implicitly implements all the (mutable) methods of the type `U`.
///
/// For more details, visit [the chapter in *The Rust Programming Language*]
/// [book] as well as the reference sections on [the dereference operator]
/// [ref-deref-op], [the `Deref` trait][ref-deref-trait], and [type coercions].
///
/// [book]: ../../book/second-edition/ch15-02-deref.html
/// [`Deref`]: trait.Deref.html
/// [more]: #more-on-deref-coercion
/// [ref-deref-op]: ../../reference/expressions.html#the-dereference-operator
/// [ref-deref-trait]: ../../reference/the-deref-trait.html
/// [type coercions]: ../../reference/type-coercions.html
///
/// # Examples
///
/// A struct with a single field which is modifiable by dereferencing the
/// struct.
///
/// ```
/// use std::ops::{Deref, DerefMut};
///
/// struct DerefMutExample<T> {
///     value: T
/// }
///
/// impl<T> Deref for DerefMutExample<T> {
///     type Target = T;
///
///     fn deref(&self) -> &T {
///         &self.value
///     }
/// }
///
/// impl<T> DerefMut for DerefMutExample<T> {
///     fn deref_mut(&mut self) -> &mut T {
///         &mut self.value
///     }
/// }
///
/// let mut x = DerefMutExample { value: 'a' };
/// *x = 'b';
/// assert_eq!('b', *x);
/// ```
#[lang = "deref_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait DerefMut: Deref {
    /// Mutably dereferences the value.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn deref_mut(&mut self) -> &mut Self::Target;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: ?Sized> DerefMut for &'a mut T {
    fn deref_mut(&mut self) -> &mut T { *self }
}
<|endoftext|>