<commit_before>// Copyright 2013-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::cell::{RefCell, Cell};
use std::collections::{HashSet, HashMap};
use std::dynamic_lib::DynamicLibrary;
use std::env;
use std::ffi::OsString;
use std::io::prelude::*;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::sync::{Arc, Mutex};

use testing;
use rustc_lint;
use rustc::session::{self, config};
use rustc::session::config::get_unstable_features_setting;
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc_back::tempdir::TempDir;
use rustc_driver::{driver, Compilation};
use syntax::codemap::CodeMap;
use syntax::diagnostic;

use core;
use clean;
use clean::Clean;
use fold::DocFolder;
use html::markdown;
use passes;
use visit_ast::RustdocVisitor;

#[derive(Clone, Default)]
pub struct TestOptions {
    pub no_crate_inject: bool,
    pub attrs: Vec<String>,
}

pub fn run(input: &str,
           cfgs: Vec<String>,
           libs: SearchPaths,
           externs: core::Externs,
           mut test_args: Vec<String>,
           crate_name: Option<String>)
           -> isize {
    let input_path = PathBuf::from(input);
    let input = config::Input::File(input_path.clone());

    let sessopts = config::Options {
        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
                                              .parent().unwrap().to_path_buf()),
        search_paths: libs.clone(),
        crate_types: vec!(config::CrateTypeDylib),
        externs: externs.clone(),
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
    let span_diagnostic_handler =
    diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                      Some(input_path.clone()),
                                      span_diagnostic_handler);
    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

    let mut cfg = config::build_configuration(&sess);
    cfg.extend(config::parse_cfgspecs(cfgs).into_iter());
    let krate = driver::phase_1_parse_input(&sess, cfg, &input);
    let krate = driver::phase_2_configure_and_expand(&sess, krate,
                                                     "rustdoc-test", None)
        .expect("phase_2_configure_and_expand aborted in rustdoc!");

    let opts = scrape_test_config(&krate);

    let ctx = core::DocContext {
        krate: &krate,
        maybe_typed: core::NotTyped(sess),
        input: input,
        external_paths: RefCell::new(Some(HashMap::new())),
        external_traits: RefCell::new(None),
        external_typarams: RefCell::new(None),
        inlined: RefCell::new(None),
        populated_crate_impls: RefCell::new(HashSet::new()),
        deref_trait_did: Cell::new(None),
    };

    let mut v = RustdocVisitor::new(&ctx, None);
    v.visit(ctx.krate);
    let mut krate = v.clean(&ctx);
    match crate_name {
        Some(name) => krate.name = name,
        None => {}
    }
    let (krate, _) = passes::collapse_docs(krate);
    let (krate, _) = passes::unindent_comments(krate);

    let mut collector = Collector::new(krate.name.to_string(),
                                       libs,
                                       externs,
                                       false,
                                       opts);
    collector.fold_crate(krate);

    test_args.insert(0, "rustdoctest".to_string());

    testing::test_main(&test_args,
                       collector.tests.into_iter().collect());
    0
}

// Look for #![doc(test(no_crate_inject))], used by crates in the std facade
fn scrape_test_config(krate: &::syntax::ast::Crate) -> TestOptions {
    use syntax::attr::AttrMetaMethods;
    use syntax::print::pprust;

    let mut opts = TestOptions {
        no_crate_inject: false,
        attrs: Vec::new(),
    };

    let attrs = krate.attrs.iter().filter(|a| a.check_name("doc"))
                     .filter_map(|a| a.meta_item_list())
                     .flat_map(|l| l.iter())
                     .filter(|a| a.check_name("test"))
                     .filter_map(|a| a.meta_item_list())
                     .flat_map(|l| l.iter());
    for attr in attrs {
        if attr.check_name("no_crate_inject") {
            opts.no_crate_inject = true;
        }
        if attr.check_name("attr") {
            if let Some(l) = attr.meta_item_list() {
                for item in l {
                    opts.attrs.push(pprust::meta_item_to_string(item));
                }
            }
        }
    }

    return opts;
}

fn runtest(test: &str, cratename: &str, libs: SearchPaths,
           externs: core::Externs,
           should_panic: bool, no_run: bool, as_test_harness: bool,
           opts: &TestOptions) {
    // the test harness wants its own `main` & top level functions, so
    // never wrap the test in `fn main() { ... }`
    let test = maketest(test, Some(cratename), as_test_harness, opts);
    let input = config::Input::Str(test.to_string());

    let sessopts = config::Options {
        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
                                              .parent().unwrap().to_path_buf()),
        search_paths: libs,
        crate_types: vec!(config::CrateTypeExecutable),
        output_types: vec!(config::OutputTypeExe),
        externs: externs,
        cg: config::CodegenOptions {
            prefer_dynamic: true,
            .. config::basic_codegen_options()
        },
        test: as_test_harness,
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    // Shuffle around a few input and output handles here. We're going to pass
    // an explicit handle into rustc to collect output messages, but we also
    // want to catch the error message that rustc prints when it fails.
    //
    // We take our task-local stderr (likely set by the test runner) and replace
    // it with a sink that is also passed to rustc itself. When this function
    // returns the output of the sink is copied onto the output of our own task.
    //
    // The basic idea is to not use a default_handler() for rustc, and then also
    // not print things by default to the actual stderr.
    struct Sink(Arc<Mutex<Vec<u8>>>);
    impl Write for Sink {
        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
            Write::write(&mut *self.0.lock().unwrap(), data)
        }
        fn flush(&mut self) -> io::Result<()> { Ok(()) }
    }
    struct Bomb(Arc<Mutex<Vec<u8>>>, Box<Write+Send>);
    impl Drop for Bomb {
        fn drop(&mut self) {
            let _ = self.1.write_all(&self.0.lock().unwrap());
        }
    }
    let data = Arc::new(Mutex::new(Vec::new()));
    let emitter = diagnostic::EmitterWriter::new(box Sink(data.clone()), None);
    let old = io::set_panic(box Sink(data.clone()));
    let _bomb = Bomb(data, old.unwrap_or(box io::stdout()));

    // Compile the code
    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::mk_handler(true, box emitter);
    let span_diagnostic_handler =
        diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                       None,
                                       span_diagnostic_handler);
    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

    let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
    let out = Some(outdir.path().to_path_buf());
    let cfg = config::build_configuration(&sess);
    let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
    let mut control = driver::CompileController::basic();
    if no_run {
        control.after_analysis.stop = Compilation::Stop;
    }
    driver::compile_input(sess, cfg, &input, &out, &None, None, control);

    if no_run { return }

    // Run the code!
    //
    // We're careful to prepend the *target* dylib search path to the child's
    // environment to ensure that the target loads the right libraries at
    // runtime. It would be a sad day if the *host* libraries were loaded as a
    // mistake.
    let mut cmd = Command::new(&outdir.path().join("rust_out"));
    let var = DynamicLibrary::envvar();
    let newpath = {
        let path = env::var_os(var).unwrap_or(OsString::new());
        let mut path = env::split_paths(&path).collect::<Vec<_>>();
        path.insert(0, libdir.clone());
        env::join_paths(path.iter()).unwrap()
    };
    cmd.env(var, &newpath);

    match cmd.output() {
        Err(e) => panic!("couldn't run the test: {}{}", e,
                        if e.kind() == io::ErrorKind::PermissionDenied {
                            " - maybe your tempdir is mounted with noexec?"
                        } else { "" }),
        Ok(out) => {
            if should_panic && out.status.success() {
                panic!("test executable succeeded when it should have failed");
            } else if !should_panic && !out.status.success() {
                panic!("test executable failed:\n{}\n{}",
                       str::from_utf8(&out.stdout).unwrap_or(""),
                       str::from_utf8(&out.stderr).unwrap_or(""));
            }
        }
    }
}

pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool,
                opts: &TestOptions) -> String {
    let (crate_attrs, everything_else) = partition_source(s);

    let mut prog = String::new();

    // First push any outer attributes from the example, assuming they
    // are intended to be crate attributes.
    prog.push_str(&crate_attrs);

    // Next, any attributes for other aspects such as lints.
    for attr in &opts.attrs {
        prog.push_str(&format!("#![{}]\n", attr));
    }

    // Don't inject `extern crate std` because it's already injected by the
    // compiler.
    if !s.contains("extern crate") && !opts.no_crate_inject {
        match cratename {
            Some(cratename) => {
                if s.contains(cratename) {
                    prog.push_str(&format!("extern crate {};\n", cratename));
                }
            }
            None => {}
        }
    }
    if dont_insert_main || s.contains("fn main") {
        prog.push_str(&everything_else);
    } else {
        prog.push_str("fn main() {\n    ");
        prog.push_str(&everything_else.replace("\n", "\n    "));
        prog.push_str("\n}");
    }

    info!("final test program: {}", prog);

    return prog
}

fn partition_source(s: &str) -> (String, String) {
    use unicode::str::UnicodeStr;

    let mut after_header = false;
    let mut before = String::new();
    let mut after = String::new();

    for line in s.lines() {
        let trimline = line.trim();
        let header = trimline.is_whitespace() ||
            trimline.starts_with("#![feature");
        if !header || after_header {
            after_header = true;
            after.push_str(line);
            after.push_str("\n");
        } else {
            before.push_str(line);
            before.push_str("\n");
        }
    }

    return (before, after);
}

pub struct Collector {
    pub tests: Vec<testing::TestDescAndFn>,
    names: Vec<String>,
    libs: SearchPaths,
    externs: core::Externs,
    cnt: usize,
    use_headers: bool,
    current_header: Option<String>,
    cratename: String,
    opts: TestOptions,
}

impl Collector {
    pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
               use_headers: bool, opts: TestOptions) -> Collector {
        Collector {
            tests: Vec::new(),
            names: Vec::new(),
            libs: libs,
            externs: externs,
            cnt: 0,
            use_headers: use_headers,
            current_header: None,
            cratename: cratename,
            opts: opts,
        }
    }

    pub fn add_test(&mut self, test: String,
                    should_panic: bool, no_run: bool, should_ignore: bool,
                    as_test_harness: bool) {
        let name = if self.use_headers {
            let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
            format!("{}_{}", s, self.cnt)
        } else {
            format!("{}_{}", self.names.connect("::"), self.cnt)
        };
        self.cnt += 1;
        let libs = self.libs.clone();
        let externs = self.externs.clone();
        let cratename = self.cratename.to_string();
        let opts = self.opts.clone();
        debug!("Creating test {}: {}", name, test);
        self.tests.push(testing::TestDescAndFn {
            desc: testing::TestDesc {
                name: testing::DynTestName(name),
                ignore: should_ignore,
                // compiler failures are test failures
                should_panic: testing::ShouldPanic::No,
            },
            testfn: testing::DynTestFn(Box::new(move|| {
                runtest(&test,
                        &cratename,
                        libs,
                        externs,
                        should_panic,
                        no_run,
                        as_test_harness,
                        &opts);
            }))
        });
    }

    pub fn register_header(&mut self, name: &str, level: u32) {
        if self.use_headers && level == 1 {
            // we use these headings as test names, so it's good if
            // they're valid identifiers.
            let name = name.chars().enumerate().map(|(i, c)| {
                    if (i == 0 && c.is_xid_start()) ||
                        (i != 0 && c.is_xid_continue()) {
                        c
                    } else {
                        '_'
                    }
                }).collect::<String>();

            // new header => reset count.
            self.cnt = 0;
            self.current_header = Some(name);
        }
    }
}

impl DocFolder for Collector {
    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
        let pushed = match item.name {
            Some(ref name) if name.is_empty() => false,
            Some(ref name) => { self.names.push(name.to_string()); true }
            None => false
        };
        match item.doc_value() {
            Some(doc) => {
                self.cnt = 0;
                markdown::find_testable_code(doc, &mut *self);
            }
            None => {}
        }
        let ret = self.fold_item_recur(item);
        if pushed {
            self.names.pop();
        }
        return ret;
    }
}
<commit_msg>rustdoc: don't inject "extern crate std;"<commit_after>// Copyright 2013-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::cell::{RefCell, Cell};
use std::collections::{HashSet, HashMap};
use std::dynamic_lib::DynamicLibrary;
use std::env;
use std::ffi::OsString;
use std::io::prelude::*;
use std::io;
use std::path::PathBuf;
use std::process::Command;
use std::str;
use std::sync::{Arc, Mutex};

use testing;
use rustc_lint;
use rustc::session::{self, config};
use rustc::session::config::get_unstable_features_setting;
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc_back::tempdir::TempDir;
use rustc_driver::{driver, Compilation};
use syntax::codemap::CodeMap;
use syntax::diagnostic;

use core;
use clean;
use clean::Clean;
use fold::DocFolder;
use html::markdown;
use passes;
use visit_ast::RustdocVisitor;

#[derive(Clone, Default)]
pub struct TestOptions {
    pub no_crate_inject: bool,
    pub attrs: Vec<String>,
}

pub fn run(input: &str,
           cfgs: Vec<String>,
           libs: SearchPaths,
           externs: core::Externs,
           mut test_args: Vec<String>,
           crate_name: Option<String>)
           -> isize {
    let input_path = PathBuf::from(input);
    let input = config::Input::File(input_path.clone());

    let sessopts = config::Options {
        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
                                              .parent().unwrap().to_path_buf()),
        search_paths: libs.clone(),
        crate_types: vec!(config::CrateTypeDylib),
        externs: externs.clone(),
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::default_handler(diagnostic::Auto, None, true);
    let span_diagnostic_handler =
    diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                      Some(input_path.clone()),
                                      span_diagnostic_handler);
    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

    let mut cfg = config::build_configuration(&sess);
    cfg.extend(config::parse_cfgspecs(cfgs).into_iter());
    let krate = driver::phase_1_parse_input(&sess, cfg, &input);
    let krate = driver::phase_2_configure_and_expand(&sess, krate,
                                                     "rustdoc-test", None)
        .expect("phase_2_configure_and_expand aborted in rustdoc!");

    let opts = scrape_test_config(&krate);

    let ctx = core::DocContext {
        krate: &krate,
        maybe_typed: core::NotTyped(sess),
        input: input,
        external_paths: RefCell::new(Some(HashMap::new())),
        external_traits: RefCell::new(None),
        external_typarams: RefCell::new(None),
        inlined: RefCell::new(None),
        populated_crate_impls: RefCell::new(HashSet::new()),
        deref_trait_did: Cell::new(None),
    };

    let mut v = RustdocVisitor::new(&ctx, None);
    v.visit(ctx.krate);
    let mut krate = v.clean(&ctx);
    match crate_name {
        Some(name) => krate.name = name,
        None => {}
    }
    let (krate, _) = passes::collapse_docs(krate);
    let (krate, _) = passes::unindent_comments(krate);

    let mut collector = Collector::new(krate.name.to_string(),
                                       libs,
                                       externs,
                                       false,
                                       opts);
    collector.fold_crate(krate);

    test_args.insert(0, "rustdoctest".to_string());

    testing::test_main(&test_args,
                       collector.tests.into_iter().collect());
    0
}

// Look for #![doc(test(no_crate_inject))], used by crates in the std facade
fn scrape_test_config(krate: &::syntax::ast::Crate) -> TestOptions {
    use syntax::attr::AttrMetaMethods;
    use syntax::print::pprust;

    let mut opts = TestOptions {
        no_crate_inject: false,
        attrs: Vec::new(),
    };

    let attrs = krate.attrs.iter().filter(|a| a.check_name("doc"))
                     .filter_map(|a| a.meta_item_list())
                     .flat_map(|l| l.iter())
                     .filter(|a| a.check_name("test"))
                     .filter_map(|a| a.meta_item_list())
                     .flat_map(|l| l.iter());
    for attr in attrs {
        if attr.check_name("no_crate_inject") {
            opts.no_crate_inject = true;
        }
        if attr.check_name("attr") {
            if let Some(l) = attr.meta_item_list() {
                for item in l {
                    opts.attrs.push(pprust::meta_item_to_string(item));
                }
            }
        }
    }

    return opts;
}

fn runtest(test: &str, cratename: &str, libs: SearchPaths,
           externs: core::Externs,
           should_panic: bool, no_run: bool, as_test_harness: bool,
           opts: &TestOptions) {
    // the test harness wants its own `main` & top level functions, so
    // never wrap the test in `fn main() { ... }`
    let test = maketest(test, Some(cratename), as_test_harness, opts);
    let input = config::Input::Str(test.to_string());

    let sessopts = config::Options {
        maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
                                              .parent().unwrap().to_path_buf()),
        search_paths: libs,
        crate_types: vec!(config::CrateTypeExecutable),
        output_types: vec!(config::OutputTypeExe),
        externs: externs,
        cg: config::CodegenOptions {
            prefer_dynamic: true,
            .. config::basic_codegen_options()
        },
        test: as_test_harness,
        unstable_features: get_unstable_features_setting(),
        ..config::basic_options().clone()
    };

    // Shuffle around a few input and output handles here. We're going to pass
    // an explicit handle into rustc to collect output messages, but we also
    // want to catch the error message that rustc prints when it fails.
    //
    // We take our task-local stderr (likely set by the test runner) and replace
    // it with a sink that is also passed to rustc itself. When this function
    // returns the output of the sink is copied onto the output of our own task.
    //
    // The basic idea is to not use a default_handler() for rustc, and then also
    // not print things by default to the actual stderr.
    struct Sink(Arc<Mutex<Vec<u8>>>);
    impl Write for Sink {
        fn write(&mut self, data: &[u8]) -> io::Result<usize> {
            Write::write(&mut *self.0.lock().unwrap(), data)
        }
        fn flush(&mut self) -> io::Result<()> { Ok(()) }
    }
    struct Bomb(Arc<Mutex<Vec<u8>>>, Box<Write+Send>);
    impl Drop for Bomb {
        fn drop(&mut self) {
            let _ = self.1.write_all(&self.0.lock().unwrap());
        }
    }
    let data = Arc::new(Mutex::new(Vec::new()));
    let emitter = diagnostic::EmitterWriter::new(box Sink(data.clone()), None);
    let old = io::set_panic(box Sink(data.clone()));
    let _bomb = Bomb(data, old.unwrap_or(box io::stdout()));

    // Compile the code
    let codemap = CodeMap::new();
    let diagnostic_handler = diagnostic::mk_handler(true, box emitter);
    let span_diagnostic_handler =
        diagnostic::mk_span_handler(diagnostic_handler, codemap);

    let sess = session::build_session_(sessopts,
                                       None,
                                       span_diagnostic_handler);
    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

    let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
    let out = Some(outdir.path().to_path_buf());
    let cfg = config::build_configuration(&sess);
    let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
    let mut control = driver::CompileController::basic();
    if no_run {
        control.after_analysis.stop = Compilation::Stop;
    }
    driver::compile_input(sess, cfg, &input, &out, &None, None, control);

    if no_run { return }

    // Run the code!
    //
    // We're careful to prepend the *target* dylib search path to the child's
    // environment to ensure that the target loads the right libraries at
    // runtime. It would be a sad day if the *host* libraries were loaded as a
    // mistake.
    let mut cmd = Command::new(&outdir.path().join("rust_out"));
    let var = DynamicLibrary::envvar();
    let newpath = {
        let path = env::var_os(var).unwrap_or(OsString::new());
        let mut path = env::split_paths(&path).collect::<Vec<_>>();
        path.insert(0, libdir.clone());
        env::join_paths(path.iter()).unwrap()
    };
    cmd.env(var, &newpath);

    match cmd.output() {
        Err(e) => panic!("couldn't run the test: {}{}", e,
                        if e.kind() == io::ErrorKind::PermissionDenied {
                            " - maybe your tempdir is mounted with noexec?"
                        } else { "" }),
        Ok(out) => {
            if should_panic && out.status.success() {
                panic!("test executable succeeded when it should have failed");
            } else if !should_panic && !out.status.success() {
                panic!("test executable failed:\n{}\n{}",
                       str::from_utf8(&out.stdout).unwrap_or(""),
                       str::from_utf8(&out.stderr).unwrap_or(""));
            }
        }
    }
}

pub fn maketest(s: &str, cratename: Option<&str>, dont_insert_main: bool,
                opts: &TestOptions) -> String {
    let (crate_attrs, everything_else) = partition_source(s);

    let mut prog = String::new();

    // First push any outer attributes from the example, assuming they
    // are intended to be crate attributes.
    prog.push_str(&crate_attrs);

    // Next, any attributes for other aspects such as lints.
    for attr in &opts.attrs {
        prog.push_str(&format!("#![{}]\n", attr));
    }

    // Don't inject `extern crate std` because it's already injected by the
    // compiler.
    if !s.contains("extern crate") && !opts.no_crate_inject && cratename != Some("std") {
        match cratename {
            Some(cratename) => {
                if s.contains(cratename) {
                    prog.push_str(&format!("extern crate {};\n", cratename));
                }
            }
            None => {}
        }
    }
    if dont_insert_main || s.contains("fn main") {
        prog.push_str(&everything_else);
    } else {
        prog.push_str("fn main() {\n    ");
        prog.push_str(&everything_else.replace("\n", "\n    "));
        prog.push_str("\n}");
    }

    info!("final test program: {}", prog);

    return prog
}

fn partition_source(s: &str) -> (String, String) {
    use unicode::str::UnicodeStr;

    let mut after_header = false;
    let mut before = String::new();
    let mut after = String::new();

    for line in s.lines() {
        let trimline = line.trim();
        let header = trimline.is_whitespace() ||
            trimline.starts_with("#![feature");
        if !header || after_header {
            after_header = true;
            after.push_str(line);
            after.push_str("\n");
        } else {
            before.push_str(line);
            before.push_str("\n");
        }
    }

    return (before, after);
}

pub struct Collector {
    pub tests: Vec<testing::TestDescAndFn>,
    names: Vec<String>,
    libs: SearchPaths,
    externs: core::Externs,
    cnt: usize,
    use_headers: bool,
    current_header: Option<String>,
    cratename: String,
    opts: TestOptions,
}

impl Collector {
    pub fn new(cratename: String, libs: SearchPaths, externs: core::Externs,
               use_headers: bool, opts: TestOptions) -> Collector {
        Collector {
            tests: Vec::new(),
            names: Vec::new(),
            libs: libs,
            externs: externs,
            cnt: 0,
            use_headers: use_headers,
            current_header: None,
            cratename: cratename,
            opts: opts,
        }
    }

    pub fn add_test(&mut self, test: String,
                    should_panic: bool, no_run: bool, should_ignore: bool,
                    as_test_harness: bool) {
        let name = if self.use_headers {
            let s = self.current_header.as_ref().map(|s| &**s).unwrap_or("");
            format!("{}_{}", s, self.cnt)
        } else {
            format!("{}_{}", self.names.connect("::"), self.cnt)
        };
        self.cnt += 1;
        let libs = self.libs.clone();
        let externs = self.externs.clone();
        let cratename = self.cratename.to_string();
        let opts = self.opts.clone();
        debug!("Creating test {}: {}", name, test);
        self.tests.push(testing::TestDescAndFn {
            desc: testing::TestDesc {
                name: testing::DynTestName(name),
                ignore: should_ignore,
                // compiler failures are test failures
                should_panic: testing::ShouldPanic::No,
            },
            testfn: testing::DynTestFn(Box::new(move|| {
                runtest(&test,
                        &cratename,
                        libs,
                        externs,
                        should_panic,
                        no_run,
                        as_test_harness,
                        &opts);
            }))
        });
    }

    pub fn register_header(&mut self, name: &str, level: u32) {
        if self.use_headers && level == 1 {
            // we use these headings as test names, so it's good if
            // they're valid identifiers.
            let name = name.chars().enumerate().map(|(i, c)| {
                    if (i == 0 && c.is_xid_start()) ||
                        (i != 0 && c.is_xid_continue()) {
                        c
                    } else {
                        '_'
                    }
                }).collect::<String>();

            // new header => reset count.
            self.cnt = 0;
            self.current_header = Some(name);
        }
    }
}

impl DocFolder for Collector {
    fn fold_item(&mut self, item: clean::Item) -> Option<clean::Item> {
        let pushed = match item.name {
            Some(ref name) if name.is_empty() => false,
            Some(ref name) => { self.names.push(name.to_string()); true }
            None => false
        };
        match item.doc_value() {
            Some(doc) => {
                self.cnt = 0;
                markdown::find_testable_code(doc, &mut *self);
            }
            None => {}
        }
        let ret = self.fold_item_recur(item);
        if pushed {
            self.names.pop();
        }
        return ret;
    }
}
<|endoftext|>


<commit_before>use super::*;
use std::fmt::Debug;

#[test]
fn stream_basic()
{
    let sink = Sink::new();
    let stream = sink.stream();
    let rx = stream.channel();
    let signal = stream.hold(0);

    sink.send(42);
    sink.send(33);
    sink.feed(0..5);

    let result: Vec<i32> = rx.try_iter().collect();
    assert_eq!(result, [42, 33, 0, 1, 2, 3, 4]);
    assert_eq!(signal.sample(), 4);
}

#[test]
fn signal_basic()
{
    let signal = Signal::constant(42);
    assert_eq!(signal.sample(), 42);
    signal.sample_with(|val| assert_eq!(*val, 42));

    let val = 33;
    let signal = Signal::from_fn(move || val);
    assert_eq!(signal.sample(), val);

    let sink = Sink::new();
    let signal = sink.stream().hold(0).map(|a| *a * 2);
    sink.send(2);
    sink.send(4);
    assert_eq!(signal.sample(), 8);
}

fn vec_cons<T: Clone>(mut v: Vec<T>, x: Cow<T>) -> Vec<T> { v.push(x.into_owned()); v }

#[test]
fn stream_operations()
{
    let sink: Sink<i32> = Sink::new();
    let stream = sink.stream();

    let s_string = stream.map(|a| a.to_string()).fold(vec![], vec_cons);
    let s_odd = stream.filter(|a| *a % 2 != 0).fold(vec![], vec_cons);
    let s_even_half = stream.filter_map(|a| if *a % 2 == 0 { Some(*a / 2) } else { None }).fold(vec![], vec_cons);
    let (pos, neg) = stream.map(|a| if *a > 0 { Ok(*a) } else { Err(*a) }).split();
    let s_pos = pos.fold(vec![], vec_cons);
    let s_neg = neg.fold(vec![], vec_cons);
    let s_merged = pos.merge(&neg.map(|a| -*a)).fold(vec![], vec_cons);
    let s_accum = stream.fold(vec![], vec_cons).snapshot(&stream, |s, _| s.into_owned()).fold(vec![], vec_cons);

    sink.feed(vec![5, 8, 13, -2, 42, -33]);

    assert_eq!(s_string.sample(), ["5", "8", "13", "-2", "42", "-33"]);
    assert_eq!(s_odd.sample(), [5, 13, -33]);
    assert_eq!(s_even_half.sample(), [4, -1, 21]);
    assert_eq!(s_pos.sample(), [5, 8, 13, 42]);
    assert_eq!(s_neg.sample(), [-2, -33]);
    assert_eq!(s_merged.sample(), [5, 8, 13, 2, 42, 33]);
    assert_eq!(s_accum.sample(), [vec![5], vec![5, 8], vec![5, 8, 13], vec![5, 8, 13, -2], vec![5, 8, 13, -2, 42], vec![5, 8, 13, -2, 42, -33]]);
}

#[cfg(feature="either")]
#[test]
fn merge_with()
{
    let sink1: Sink<i32> = Sink::new();
    let sink2: Sink<f32> = Sink::new();
    let stream: Stream<Result<_, _>> = sink1.stream().merge_with(&sink2.stream(), |e| e.either(|l| Ok(*l), |r| Err(*r)));
    let result = stream.fold(vec![], vec_cons);

    sink1.send(1);
    sink2.send(2.0);
    sink1.send(3);
    sink1.send(4);
    sink2.send(5.0);

    assert_eq!(result.sample(), [Ok(1), Err(2.0), Ok(3), Ok(4), Err(5.0)]);
}

#[test]
fn stream_channel()
{
    let sink = Sink::new();
    let rx = sink.stream().channel();

    let thread = std::thread::spawn(move || {
        let mut sum = 0;
        while let Some(val) = rx.recv().unwrap()
        {
            sum += val;
        }
        sum
    });
    sink.feed((1..100).map(Some));
    sink.send(None);

    let result = thread.join().unwrap();
    assert_eq!(result, 4950);
}

#[test]
fn stream_switch()
{
    let stream_sink = Sink::new();
    let sink1 = Sink::new();
    let sink2 = Sink::new();

    let switched = stream_sink.stream().switch();
    let events = switched.channel();

    sink1.send(1);
    sink2.send(2);

    stream_sink.send(sink2.stream());
    sink1.send(3);
    sink2.send(4);
    assert_eq!(events.try_recv(), Ok(4));

    stream_sink.send(sink1.stream());
    sink1.send(5);
    sink2.send(6);
    assert_eq!(events.try_recv(), Ok(5));
}

#[test]
fn signal_switch()
{
    let signal_sink = Sink::new();
    let switched = signal_sink.stream().hold(Signal::constant(0)).switch();

    signal_sink.send(Signal::constant(1));
    assert_eq!(switched.sample(), 1);

    signal_sink.send(Signal::constant(2));
    assert_eq!(switched.sample(), 2);
}

#[derive(Debug)]
struct Storage<T>(Vec<T>);

impl<T> Storage<T>
{
    fn new() -> Self { Storage(Vec::new()) }
    fn push(mut self, a: T) -> Self { self.0.push(a); self }
}

impl<T: Debug> Clone for Storage<T>
{
    fn clone(&self) -> Self { panic!("storage cloned! {:?}", self.0) }
}

#[test]
fn cloning()
{
    let sink = Sink::new();
    let accum = sink.stream().fold(Storage::new(), |a, v| a.push(*v));

    sink.feed(0..5);
    accum.sample_with(|res| assert_eq!(res.0, [0, 1, 2, 3, 4]));
}
<commit_msg>test for Signal::hold_if<commit_after>use super::*;
use std::fmt::Debug;

#[test]
fn stream_basic()
{
    let sink = Sink::new();
    let stream = sink.stream();
    let rx = stream.channel();
    let signal = stream.hold(0);

    sink.send(42);
    sink.send(33);
    sink.feed(0..5);

    let result: Vec<i32> = rx.try_iter().collect();
    assert_eq!(result, [42, 33, 0, 1, 2, 3, 4]);
    assert_eq!(signal.sample(), 4);
}

#[test]
fn signal_basic()
{
    let signal = Signal::constant(42);
    assert_eq!(signal.sample(), 42);
    signal.sample_with(|val| assert_eq!(*val, 42));

    let val = 33;
    let signal = Signal::from_fn(move || val);
    assert_eq!(signal.sample(), val);

    let sink = Sink::new();
    let stream = sink.stream();
    let s_double = stream.hold(0).map(|a| *a * 2);
    let s_odd = stream.hold_if(0, |a| *a % 2 != 0);

    sink.send(2);
    sink.send(3);
    sink.send(4);

    assert_eq!(s_double.sample(), 8);
    assert_eq!(s_odd.sample(), 3);
}

fn vec_cons<T: Clone>(mut v: Vec<T>, x: Cow<T>) -> Vec<T> { v.push(x.into_owned()); v }

#[test]
fn stream_operations()
{
    let sink: Sink<i32> = Sink::new();
    let stream = sink.stream();

    let s_string = stream.map(|a| a.to_string()).fold(vec![], vec_cons);
    let s_odd = stream.filter(|a| *a % 2 != 0).fold(vec![], vec_cons);
    let s_even_half = stream.filter_map(|a| if *a % 2 == 0 { Some(*a / 2) } else { None }).fold(vec![], vec_cons);
    let (pos, neg) = stream.map(|a| if *a > 0 { Ok(*a) } else { Err(*a) }).split();
    let s_pos = pos.fold(vec![], vec_cons);
    let s_neg = neg.fold(vec![], vec_cons);
    let s_merged = pos.merge(&neg.map(|a| -*a)).fold(vec![], vec_cons);
    let s_accum = stream.fold(vec![], vec_cons).snapshot(&stream, |s, _| s.into_owned()).fold(vec![], vec_cons);

    sink.feed(vec![5, 8, 13, -2, 42, -33]);

    assert_eq!(s_string.sample(), ["5", "8", "13", "-2", "42", "-33"]);
    assert_eq!(s_odd.sample(), [5, 13, -33]);
    assert_eq!(s_even_half.sample(), [4, -1, 21]);
    assert_eq!(s_pos.sample(), [5, 8, 13, 42]);
    assert_eq!(s_neg.sample(), [-2, -33]);
    assert_eq!(s_merged.sample(), [5, 8, 13, 2, 42, 33]);
    assert_eq!(s_accum.sample(), [vec![5], vec![5, 8], vec![5, 8, 13], vec![5, 8, 13, -2], vec![5, 8, 13, -2, 42], vec![5, 8, 13, -2, 42, -33]]);
}

#[cfg(feature="either")]
#[test]
fn merge_with()
{
    let sink1: Sink<i32> = Sink::new();
    let sink2: Sink<f32> = Sink::new();
    let stream: Stream<Result<_, _>> = sink1.stream().merge_with(&sink2.stream(), |e| e.either(|l| Ok(*l), |r| Err(*r)));
    let result = stream.fold(vec![], vec_cons);

    sink1.send(1);
    sink2.send(2.0);
    sink1.send(3);
    sink1.send(4);
    sink2.send(5.0);

    assert_eq!(result.sample(), [Ok(1), Err(2.0), Ok(3), Ok(4), Err(5.0)]);
}

#[test]
fn stream_channel()
{
    let sink = Sink::new();
    let rx = sink.stream().channel();

    let thread = std::thread::spawn(move || {
        let mut sum = 0;
        while let Some(val) = rx.recv().unwrap()
        {
            sum += val;
        }
        sum
    });
    sink.feed((1..100).map(Some));
    sink.send(None);

    let result = thread.join().unwrap();
    assert_eq!(result, 4950);
}

#[test]
fn stream_switch()
{
    let stream_sink = Sink::new();
    let sink1 = Sink::new();
    let sink2 = Sink::new();

    let switched = stream_sink.stream().switch();
    let events = switched.channel();

    sink1.send(1);
    sink2.send(2);

    stream_sink.send(sink2.stream());
    sink1.send(3);
    sink2.send(4);
    assert_eq!(events.try_recv(), Ok(4));

    stream_sink.send(sink1.stream());
    sink1.send(5);
    sink2.send(6);
    assert_eq!(events.try_recv(), Ok(5));
}

#[test]
fn signal_switch()
{
    let signal_sink = Sink::new();
    let switched = signal_sink.stream().hold(Signal::constant(0)).switch();

    signal_sink.send(Signal::constant(1));
    assert_eq!(switched.sample(), 1);

    signal_sink.send(Signal::constant(2));
    assert_eq!(switched.sample(), 2);
}

#[derive(Debug)]
struct Storage<T>(Vec<T>);

impl<T> Storage<T>
{
    fn new() -> Self { Storage(Vec::new()) }
    fn push(mut self, a: T) -> Self { self.0.push(a); self }
}

impl<T: Debug> Clone for Storage<T>
{
    fn clone(&self) -> Self { panic!("storage cloned! {:?}", self.0) }
}

#[test]
fn cloning()
{
    let sink = Sink::new();
    let accum = sink.stream().fold(Storage::new(), |a, v| a.push(*v));

    sink.feed(0..5);
    accum.sample_with(|res| assert_eq!(res.0, [0, 1, 2, 3, 4]));
}
<|endoftext|>


<commit_before>use std::fmt;
use std::mem::transmute;
use std::ops::Deref;

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::*;

use super::*;

/// Enumeration of all the base types of the LLVM type system.
#[allow(non_camel_case_types)]
#[derive(Debug)]
pub enum Kind<'a> {
    Void(&'a Void),
    Half(&'a Half),
    Float(&'a Float),
    Double(&'a Double),
    X86_FP80(&'a X86_FP80),
    FP128(&'a FP128),
    PPC_FP128(&'a PPC_FP128),
    Label(&'a Label),
    Integer(&'a Integer),
    Function(&'a Function),
    Struct(&'a Struct),
    Array(&'a Array),
    Pointer(&'a Pointer),
    Vector(&'a Vector),
    Metadata(&'a Metadata),
    X86_MMX(&'a X86_MMX),
    Token(&'a Token),
}

/// A generic LLVM type. Should always be used as `&Type`.
///
/// `Type`s are owned by `Context` instances such that only one instance of a
/// specific `Type` exists per `Context`, e.g. only 1 `Type` for `i64` exists
/// per context. `Type`s are also never mutated and never destroyed, living for
/// the lifetime of the `Context` that owns them.
///
/// In LLVM, there is a heirarchy of types. An `&Type` can be downcast to a
/// subtype, such as `&Integer`, with the `downcast` method. Downcasting makes
/// subtype specific methods, such as `width` on `&Integer` available.
// TODO: mark this as an unsized type
pub struct Type(LLVMType);

impl<'a> From<LLVMTypeRef> for &'a Type {
    fn from(ptr: LLVMTypeRef) -> &'a Type {
        unsafe { transmute::<LLVMTypeRef, &Type>(ptr) }
    }
}

impl<'a> From<&'a Type> for LLVMTypeRef {
    fn from(ty: &'a Type) -> LLVMTypeRef {
        unsafe { transmute::<&Type, LLVMTypeRef>(ty) }
    }
}

impl Type {
    pub fn is_sized(&self) -> bool {
        unsafe { LLVMTypeIsSized(self.into()) == 1 }
    }

    pub fn downcast(&self) -> Kind {
        unsafe {
            match LLVMGetTypeKind(self.into()) {
                LLVMTypeKind::LLVMVoidTypeKind => Kind::Void(transmute(self)),
                LLVMTypeKind::LLVMHalfTypeKind => Kind::Half(transmute(self)),
                LLVMTypeKind::LLVMFloatTypeKind => Kind::Float(transmute(self)),
                LLVMTypeKind::LLVMDoubleTypeKind => Kind::Double(transmute(self)),
                LLVMTypeKind::LLVMX86_FP80TypeKind => Kind::X86_FP80(transmute(self)),
                LLVMTypeKind::LLVMFP128TypeKind => Kind::FP128(transmute(self)),
                LLVMTypeKind::LLVMPPC_FP128TypeKind => Kind::PPC_FP128(transmute(self)),
                LLVMTypeKind::LLVMLabelTypeKind => Kind::Label(transmute(self)),
                LLVMTypeKind::LLVMIntegerTypeKind => Kind::Integer(transmute(self)),
                LLVMTypeKind::LLVMFunctionTypeKind => Kind::Function(transmute(self)),
                LLVMTypeKind::LLVMStructTypeKind => Kind::Struct(transmute(self)),
                LLVMTypeKind::LLVMArrayTypeKind => Kind::Array(transmute(self)),
                LLVMTypeKind::LLVMPointerTypeKind => Kind::Pointer(transmute(self)),
                LLVMTypeKind::LLVMVectorTypeKind => Kind::Vector(transmute(self)),
                LLVMTypeKind::LLVMMetadataTypeKind => Kind::Metadata(transmute(self)),
                LLVMTypeKind::LLVMX86_MMXTypeKind => Kind::X86_MMX(transmute(self)),
                LLVMTypeKind::LLVMTokenTypeKind => Kind::Token(transmute(self)),
            }
        }
    }
}

// This counts as the llvm::Type::print method from the C++ API, though the C++
// version has more options.
impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            let s_ptr = LLVMPrintTypeToString(self.into());
            let r = write!(f, "{}", c_str_to_str!(s_ptr));
            LLVMDisposeMessage(s_ptr);
            r
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "llvm::Type({})", self)
    }
}

impl PartialEq for Type {
    fn eq(&self, other: &Self) -> bool {
        LLVMTypeRef::from(self) == LLVMTypeRef::from(other)
    }
}

impl Eq for Type {}

macro_rules! impl_type {
    ($t:ty) => {
        impl Deref for $t {
            type Target = Type;

            fn deref(&self) -> &Self::Target {
                unsafe { transmute::<&Self, &Self::Target>(self) }
            }
        }

        // This would not be needed if the compiler could infer that the
        // From<&Type> for LLVMTypeRef above worked on &SubType.
        impl<'a> From<&'a $t> for LLVMTypeRef {
            fn from(ty: &'a $t) -> LLVMTypeRef {
                unsafe { transmute::<&$t, LLVMTypeRef>(ty) }
            }
        }

        impl<'a> From<LLVMTypeRef> for &'a $t {
            fn from(ptr: LLVMTypeRef) -> &'a $t {
                unsafe { transmute::<LLVMTypeRef, &$t>(ptr) }
            }
        }

        impl fmt::Display for $t {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                self.deref().fmt(f)
            }
}

        impl fmt::Debug for $t {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "llvm::types::{}({})", stringify!($t), self)
            }
        }
    }
}

// Base types:

pub struct Void(Type);
impl_type!(Void);

pub struct Half(Type);
impl_type!(Half);

pub struct Float(Type);
impl_type!(Float);

pub struct Double(Type);
impl_type!(Double);

#[allow(non_camel_case_types)]
pub struct X86_FP80(Type);
impl_type!(X86_FP80);

#[allow(non_camel_case_types)]
pub struct FP128(Type);
impl_type!(FP128);

#[allow(non_camel_case_types)]
pub struct PPC_FP128(Type);
impl_type!(PPC_FP128);

pub struct Label(Type);
impl_type!(Label);

pub struct Metadata(Type);
impl_type!(Metadata);

#[allow(non_camel_case_types)]
pub struct X86_MMX(Type);
impl_type!(X86_MMX);

pub struct Token(Type);
impl_type!(Token);

/// Integer types are constructed with a size. Construct them with the methods
/// that `Context` provides.
pub struct Integer(Type);
impl_type!(Integer);

impl Integer {
    pub fn width(&self) -> u32 {
        unsafe { LLVMGetIntTypeWidth(self.into()) }
    }
}

/// A function type is a tuple consisting of a return type and an array of
/// parameter types.
pub struct Function(Type);
impl_type!(Function);

impl Function {
    pub fn new<'a>(
        return_type: &'a Type,
        param_types: &[&'a Type],
        is_var_args: bool,
    ) -> &'a Function {
        unsafe {
            LLVMFunctionType(
                return_type.into(),
                transmute::<*const &Type, *mut LLVMTypeRef>(param_types.as_ptr()),
                param_types.len() as u32,
                is_var_args as LLVMBool,
            ).into()
        }
    }
}

pub struct Struct(Type);
impl_type!(Struct);

pub struct Array(Type);
impl_type!(Array);

pub struct Pointer(Type);
impl_type!(Pointer);

pub struct Vector(Type);
impl_type!(Vector);

/// Trait marking Rust types that have LLVM counterparts
pub trait ContextType {
    type LlvmType;

    fn get_type_in_context<'a>(context: &'a Context) -> &'a Self::LlvmType;
}

macro_rules! impl_context_type {
    ($t: ty => $llvm_type: ty, $to_type_in_context: ident) => {
        impl ContextType for $t {
            type LlvmType = $llvm_type;

            fn get_type_in_context<'a>(context: &'a Context) -> &'a Self::LlvmType {
                unsafe {
                    $to_type_in_context(context.ptr).into()
                }
            }
        }
    }
}

impl_context_type!(bool => Integer, LLVMInt1TypeInContext);
// This might actually not be true, Not sure
impl_context_type!(char => Integer, LLVMInt8TypeInContext);
impl_context_type!(u8 => Integer, LLVMInt8TypeInContext);
impl_context_type!(u16 => Integer, LLVMInt16TypeInContext);
impl_context_type!(u32 => Integer, LLVMInt32TypeInContext);
impl_context_type!(u64 => Integer, LLVMInt64TypeInContext);
impl_context_type!(i8 => Integer, LLVMInt8TypeInContext);
impl_context_type!(i16 => Integer, LLVMInt16TypeInContext);
impl_context_type!(i32 => Integer, LLVMInt32TypeInContext);
impl_context_type!(i64 => Integer, LLVMInt64TypeInContext);
impl_context_type!(f32 => Float, LLVMFloatTypeInContext);
impl_context_type!(f64 => Double, LLVMDoubleTypeInContext);
//TODO: Function Types
//TODO: Structure Types
//TODO: Sequential Types
//TODO: Other Types
<commit_msg>add more methods for downcasting Types<commit_after>use std::fmt;
use std::mem::transmute;
use std::ops::Deref;

use llvm_sys::prelude::*;
use llvm_sys::core::*;
use llvm_sys::*;

use super::*;

/// Enumeration of all the base types of the LLVM type system.
#[allow(non_camel_case_types)]
#[derive(Debug)]
pub enum Kind<'a> {
    Void(&'a Void),
    Half(&'a Half),
    Float(&'a Float),
    Double(&'a Double),
    X86_FP80(&'a X86_FP80),
    FP128(&'a FP128),
    PPC_FP128(&'a PPC_FP128),
    Label(&'a Label),
    Integer(&'a Integer),
    Function(&'a Function),
    Struct(&'a Struct),
    Array(&'a Array),
    Pointer(&'a Pointer),
    Vector(&'a Vector),
    Metadata(&'a Metadata),
    X86_MMX(&'a X86_MMX),
    Token(&'a Token),
}

/// A generic LLVM type. Should always be used as `&Type`.
///
/// `Type`s are owned by `Context` instances such that only one instance of a
/// specific `Type` exists per `Context`, e.g. only 1 `Type` for `i64` exists
/// per context. `Type`s are also never mutated and never destroyed, living for
/// the lifetime of the `Context` that owns them.
///
/// In LLVM, there is a heirarchy of types. An `&Type` can be downcast to a
/// subtype, such as `&Integer`, with the `downcast` method. Downcasting makes
/// subtype specific methods, such as `width` on `&Integer` available.
// TODO: mark this as an unsized type
pub struct Type(LLVMType);

impl<'a> From<LLVMTypeRef> for &'a Type {
    fn from(ptr: LLVMTypeRef) -> &'a Type {
        unsafe { transmute::<LLVMTypeRef, &Type>(ptr) }
    }
}

impl<'a> From<&'a Type> for LLVMTypeRef {
    fn from(ty: &'a Type) -> LLVMTypeRef {
        unsafe { transmute::<&Type, LLVMTypeRef>(ty) }
    }
}

macro_rules! try_as_fns {
            pub fn $name<'a>(&'a self) -> Option<&'a $variant> {
                if let Kind::$variant(t) = self.downcast() {
                    Some(t)
                }
                else {
                    None
                }
            }
        )*
    }
}

impl Type {
    pub fn is_sized(&self) -> bool {
        unsafe { LLVMTypeIsSized(self.into()) == 1 }
    }

    pub fn downcast(&self) -> Kind {
        unsafe {
            match LLVMGetTypeKind(self.into()) {
                LLVMTypeKind::LLVMVoidTypeKind => Kind::Void(transmute(self)),
                LLVMTypeKind::LLVMHalfTypeKind => Kind::Half(transmute(self)),
                LLVMTypeKind::LLVMFloatTypeKind => Kind::Float(transmute(self)),
                LLVMTypeKind::LLVMDoubleTypeKind => Kind::Double(transmute(self)),
                LLVMTypeKind::LLVMX86_FP80TypeKind => Kind::X86_FP80(transmute(self)),
                LLVMTypeKind::LLVMFP128TypeKind => Kind::FP128(transmute(self)),
                LLVMTypeKind::LLVMPPC_FP128TypeKind => Kind::PPC_FP128(transmute(self)),
                LLVMTypeKind::LLVMLabelTypeKind => Kind::Label(transmute(self)),
                LLVMTypeKind::LLVMIntegerTypeKind => Kind::Integer(transmute(self)),
                LLVMTypeKind::LLVMFunctionTypeKind => Kind::Function(transmute(self)),
                LLVMTypeKind::LLVMStructTypeKind => Kind::Struct(transmute(self)),
                LLVMTypeKind::LLVMArrayTypeKind => Kind::Array(transmute(self)),
                LLVMTypeKind::LLVMPointerTypeKind => Kind::Pointer(transmute(self)),
                LLVMTypeKind::LLVMVectorTypeKind => Kind::Vector(transmute(self)),
                LLVMTypeKind::LLVMMetadataTypeKind => Kind::Metadata(transmute(self)),
                LLVMTypeKind::LLVMX86_MMXTypeKind => Kind::X86_MMX(transmute(self)),
                LLVMTypeKind::LLVMTokenTypeKind => Kind::Token(transmute(self)),
            }
        }
    }

    try_as_fns! {
        pub fn try_as_void -> Void
        pub fn try_as_half -> Half
        pub fn try_as_float -> Float
        pub fn try_as_double -> Integer
        pub fn try_as_x86_fp80 -> X86_FP80
        pub fn try_as_fp128 -> FP128
        pub fn try_as_ppc_fp128 -> PPC_FP128
        pub fn try_as_label -> Label
        pub fn try_as_integer -> Integer
        pub fn try_as_function -> Function
        pub fn try_as_struct -> Struct
        pub fn try_as_array -> Array
        pub fn try_as_pointer -> Pointer
        pub fn try_as_vector -> Vector
        pub fn try_as_metadata -> Metadata
        pub fn try_as_x86_mmx -> X86_MMX
        pub fn try_as_token -> Token
    }
}

// This counts as the llvm::Type::print method from the C++ API, though the C++
// version has more options.
impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        unsafe {
            let s_ptr = LLVMPrintTypeToString(self.into());
            let r = write!(f, "{}", c_str_to_str!(s_ptr));
            LLVMDisposeMessage(s_ptr);
            r
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "llvm::Type({})", self)
    }
}

impl PartialEq for Type {
    fn eq(&self, other: &Self) -> bool {
        LLVMTypeRef::from(self) == LLVMTypeRef::from(other)
    }
}

impl Eq for Type {}

macro_rules! impl_type {
    ($t:ty) => {
        impl Deref for $t {
            type Target = Type;

            fn deref(&self) -> &Self::Target {
                unsafe { transmute::<&Self, &Self::Target>(self) }
            }
        }

        // This would not be needed if the compiler could infer that the
        // From<&Type> for LLVMTypeRef above worked on &SubType.
        impl<'a> From<&'a $t> for LLVMTypeRef {
            fn from(ty: &'a $t) -> LLVMTypeRef {
                unsafe { transmute::<&$t, LLVMTypeRef>(ty) }
            }
        }

        impl<'a> From<LLVMTypeRef> for &'a $t {
            fn from(ptr: LLVMTypeRef) -> &'a $t {
                unsafe { transmute::<LLVMTypeRef, &$t>(ptr) }
            }
        }

        impl fmt::Display for $t {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                self.deref().fmt(f)
            }
}

        impl fmt::Debug for $t {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "llvm::types::{}({})", stringify!($t), self)
            }
        }
    }
}

// Base types:

pub struct Void(Type);
impl_type!(Void);

pub struct Half(Type);
impl_type!(Half);

pub struct Float(Type);
impl_type!(Float);

pub struct Double(Type);
impl_type!(Double);

#[allow(non_camel_case_types)]
pub struct X86_FP80(Type);
impl_type!(X86_FP80);

#[allow(non_camel_case_types)]
pub struct FP128(Type);
impl_type!(FP128);

#[allow(non_camel_case_types)]
pub struct PPC_FP128(Type);
impl_type!(PPC_FP128);

pub struct Label(Type);
impl_type!(Label);

pub struct Metadata(Type);
impl_type!(Metadata);

#[allow(non_camel_case_types)]
pub struct X86_MMX(Type);
impl_type!(X86_MMX);

pub struct Token(Type);
impl_type!(Token);

/// Integer types are constructed with a size. Construct them with the methods
/// that `Context` provides.
pub struct Integer(Type);
impl_type!(Integer);

impl Integer {
    pub fn width(&self) -> u32 {
        unsafe { LLVMGetIntTypeWidth(self.into()) }
    }
}

/// A function type is a tuple consisting of a return type and an array of
/// parameter types.
pub struct Function(Type);
impl_type!(Function);

impl Function {
    pub fn new<'a>(
        return_type: &'a Type,
        param_types: &[&'a Type],
        is_var_args: bool,
    ) -> &'a Function {
        unsafe {
            LLVMFunctionType(
                return_type.into(),
                transmute::<*const &Type, *mut LLVMTypeRef>(param_types.as_ptr()),
                param_types.len() as u32,
                is_var_args as LLVMBool,
            ).into()
        }
    }
}

pub struct Struct(Type);
impl_type!(Struct);

pub struct Array(Type);
impl_type!(Array);

pub struct Pointer(Type);
impl_type!(Pointer);

pub struct Vector(Type);
impl_type!(Vector);

/// Trait marking Rust types that have LLVM counterparts
pub trait ContextType {
    type LlvmType;

    fn get_type_in_context<'a>(context: &'a Context) -> &'a Self::LlvmType;
}

macro_rules! impl_context_type {
    ($t: ty => $llvm_type: ty, $to_type_in_context: ident) => {
        impl ContextType for $t {
            type LlvmType = $llvm_type;

            fn get_type_in_context<'a>(context: &'a Context) -> &'a Self::LlvmType {
                unsafe {
                    $to_type_in_context(context.ptr).into()
                }
            }
        }
    }
}

impl_context_type!(bool => Integer, LLVMInt1TypeInContext);
// This might actually not be true, Not sure
impl_context_type!(char => Integer, LLVMInt8TypeInContext);
impl_context_type!(u8 => Integer, LLVMInt8TypeInContext);
impl_context_type!(u16 => Integer, LLVMInt16TypeInContext);
impl_context_type!(u32 => Integer, LLVMInt32TypeInContext);
impl_context_type!(u64 => Integer, LLVMInt64TypeInContext);
impl_context_type!(i8 => Integer, LLVMInt8TypeInContext);
impl_context_type!(i16 => Integer, LLVMInt16TypeInContext);
impl_context_type!(i32 => Integer, LLVMInt32TypeInContext);
impl_context_type!(i64 => Integer, LLVMInt64TypeInContext);
impl_context_type!(f32 => Float, LLVMFloatTypeInContext);
impl_context_type!(f64 => Double, LLVMDoubleTypeInContext);
//TODO: Function Types
//TODO: Structure Types
//TODO: Sequential Types
//TODO: Other Types
<|endoftext|>


<commit_before>// 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::num::Zero;
use std::io;
use std::fmt;
use std::error::Error;

use serde;
use serde_json;
use nix;
use term;
use dbus;

pub type FroyoResult<T> = Result<T, FroyoError>;

//
// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(pub u64);
}

impl Zero for Sectors {
    fn zero() -> Self {
        Sectors(0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(pub u64);
}

impl Zero for SectorOffset {
    fn zero() -> Self {
        SectorOffset(0)
    }
}

impl serde::Serialize for SectorOffset {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for SectorOffset {
    fn deserialize<D>(deserializer: &mut D) -> Result<SectorOffset, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(SectorOffset(val))
    }
}

// A type for Data Blocks as used by the thin pool.
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct DataBlocks(pub u64);
}

impl Zero for DataBlocks {
    fn zero() -> Self {
        DataBlocks(0)
    }
}

impl serde::Serialize for DataBlocks {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for DataBlocks {
    fn deserialize<D>(deserializer: &mut D) -> Result<DataBlocks, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(DataBlocks(val))
    }
}

//
// An error type for errors generated within Froyo
//
#[derive(Debug, Clone)]
pub struct InternalError(pub String);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum FroyoError {
    Froyo(InternalError),
    Io(io::Error),
    Serde(serde_json::error::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for FroyoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FroyoError::Froyo(ref err) => write!(f, "Froyo error: {}", err.0),
            FroyoError::Io(ref err) => write!(f, "IO error: {}", err),
            FroyoError::Serde(ref err) => write!(f, "Serde error: {}", err),
            FroyoError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            FroyoError::Dbus(ref err) => write!(f, "Dbus error: {}", err),
            FroyoError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for FroyoError {
    fn description(&self) -> &str {
        match *self {
            FroyoError::Froyo(ref err) => &err.0,
            FroyoError::Io(ref err) => err.description(),
            FroyoError::Serde(ref err) => Error::description(err),
            FroyoError::Nix(ref err) => err.errno().desc(),
            FroyoError::Dbus(ref err) => err.description(),
            FroyoError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            FroyoError::Froyo(ref err) => Some(err),
            FroyoError::Io(ref err) => Some(err),
            FroyoError::Serde(ref err) => Some(err),
            FroyoError::Nix(ref err) => Some(err),
            FroyoError::Dbus(ref err) => Some(err),
            FroyoError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for FroyoError {
    fn from(err: InternalError) -> FroyoError {
        FroyoError::Froyo(err)
    }
}

impl From<io::Error> for FroyoError {
    fn from(err: io::Error) -> FroyoError {
        FroyoError::Io(err)
    }
}

impl From<serde_json::error::Error> for FroyoError {
    fn from(err: serde_json::error::Error) -> FroyoError {
        FroyoError::Serde(err)
    }
}

impl From<nix::Error> for FroyoError {
    fn from(err: nix::Error) -> FroyoError {
        FroyoError::Nix(err)
    }
}

impl From<dbus::Error> for FroyoError {
    fn from(err: dbus::Error) -> FroyoError {
        FroyoError::Dbus(err)
    }
}

impl From<term::Error> for FroyoError {
    fn from(err: term::Error) -> FroyoError {
        FroyoError::Term(err)
    }
}
<commit_msg>Improve DBus error messages<commit_after>// 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::num::Zero;
use std::io;
use std::fmt;
use std::error::Error;

use serde;
use serde_json;
use nix;
use term;
use dbus;

pub type FroyoResult<T> = Result<T, FroyoError>;

//
// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(pub u64);
}

impl Zero for Sectors {
    fn zero() -> Self {
        Sectors(0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(pub u64);
}

impl Zero for SectorOffset {
    fn zero() -> Self {
        SectorOffset(0)
    }
}

impl serde::Serialize for SectorOffset {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for SectorOffset {
    fn deserialize<D>(deserializer: &mut D) -> Result<SectorOffset, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(SectorOffset(val))
    }
}

// A type for Data Blocks as used by the thin pool.
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct DataBlocks(pub u64);
}

impl Zero for DataBlocks {
    fn zero() -> Self {
        DataBlocks(0)
    }
}

impl serde::Serialize for DataBlocks {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for DataBlocks {
    fn deserialize<D>(deserializer: &mut D) -> Result<DataBlocks, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(DataBlocks(val))
    }
}

//
// An error type for errors generated within Froyo
//
#[derive(Debug, Clone)]
pub struct InternalError(pub String);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum FroyoError {
    Froyo(InternalError),
    Io(io::Error),
    Serde(serde_json::error::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for FroyoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FroyoError::Froyo(ref err) => write!(f, "Froyo error: {}", err.0),
            FroyoError::Io(ref err) => write!(f, "IO error: {}", err),
            FroyoError::Serde(ref err) => write!(f, "Serde error: {}", err),
            FroyoError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            FroyoError::Dbus(ref err) => write!(
                f, "Dbus error: {}", err.message().unwrap_or("Unknown")),
            FroyoError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for FroyoError {
    fn description(&self) -> &str {
        match *self {
            FroyoError::Froyo(ref err) => &err.0,
            FroyoError::Io(ref err) => err.description(),
            FroyoError::Serde(ref err) => Error::description(err),
            FroyoError::Nix(ref err) => err.errno().desc(),
            FroyoError::Dbus(ref err) => err.message().unwrap_or("D-Bus Error"),
            FroyoError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            FroyoError::Froyo(ref err) => Some(err),
            FroyoError::Io(ref err) => Some(err),
            FroyoError::Serde(ref err) => Some(err),
            FroyoError::Nix(ref err) => Some(err),
            FroyoError::Dbus(ref err) => Some(err),
            FroyoError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for FroyoError {
    fn from(err: InternalError) -> FroyoError {
        FroyoError::Froyo(err)
    }
}

impl From<io::Error> for FroyoError {
    fn from(err: io::Error) -> FroyoError {
        FroyoError::Io(err)
    }
}

impl From<serde_json::error::Error> for FroyoError {
    fn from(err: serde_json::error::Error) -> FroyoError {
        FroyoError::Serde(err)
    }
}

impl From<nix::Error> for FroyoError {
    fn from(err: nix::Error) -> FroyoError {
        FroyoError::Nix(err)
    }
}

impl From<dbus::Error> for FroyoError {
    fn from(err: dbus::Error) -> FroyoError {
        FroyoError::Dbus(err)
    }
}

impl From<term::Error> for FroyoError {
    fn from(err: term::Error) -> FroyoError {
        FroyoError::Term(err)
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::error;
use gl;

pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}

#[derive(Clone, Copy)]
pub struct Viewport {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32
}

impl Viewport {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Viewport {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

bitflags! {
    flags BufferBits: gl::types::GLbitfield {
        const COLOR_BUFFER_BIT = gl::COLOR_BUFFER_BIT,
        const DEPTH_BUFFER_BIT = gl::DEPTH_BUFFER_BIT,
        const STENCIL_BUFFER_BIT = gl::STENCIL_BUFFER_BIT
    }
}

#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    Message(String)
}

impl fmt::Display for GLError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLError::InvalidEnum => {
                write!(f, "Invalid enum")
            },
            GLError::InvalidValue => {
                write!(f, "Invalid value")
            },
            GLError::InvalidOperation => {
                write!(f, "Invalid operation")
            },
            GLError::InvalidFramebufferOperation => {
                write!(f, "Invalid framebuffer operation")
            },
            GLError::OutOfMemory => {
                write!(f, "Out of memory")
            },
            GLError::Message(ref s) => {
                write!(f, "{}", s)
            }
        }
    }
}

impl error::Error for GLError {
    fn description(&self) -> &str {
        match *self {
            GLError::InvalidEnum => "Invalid enum variant in OpenGL call.",
            GLError::InvalidValue => "Out-of-range value in OpenGL call.",
            GLError::InvalidOperation => "The specified OpenGL operation is not allowed in the current state.",
            GLError::InvalidFramebufferOperation => "OpenGL command tried to read or write to an incomplete framebuffer.",
            GLError::OutOfMemory => "There is not enough memory left to execute the specified OpenGL command.",
            GLError::Message(ref s) => &s
        }
    }
}

gl_enum! {
    pub gl_enum DrawingMode {
        Points as POINTS = gl::POINTS,
        LineStrip as LINE_STRIP = gl::LINE_STRIP,
        LineLoop as LINE_LOOP = gl::LINE_LOOP,
        Lines as LINES = gl::LINES,
        TriangleStrip as TRIANGLE_STRIP = gl::TRIANGLE_STRIP,
        TriangleFan as TRIANGLE_FAN = gl::TRIANGLE_FAN,
        Triangles as TRIANGLES = gl::TRIANGLES
    }
}

gl_enum! {
    pub gl_enum DataType {
        Byte as BYTE = gl::BYTE,
        UnsignedByte as UNSIGNED_BYTE = gl::UNSIGNED_BYTE,
        Short as SHORT = gl::SHORT,
        UnsignedShort as UNSIGNED_SHORT = gl::UNSIGNED_SHORT,
        Fixed as FIXED = gl::FIXED,
        Float as FLOAT = gl::FLOAT
    }
}
<commit_msg>Add `GLFramebufferError` enum<commit_after>use std::fmt;
use std::error;
use gl;

pub struct Color {
    pub r: f32,
    pub g: f32,
    pub b: f32,
    pub a: f32
}

impl Color {
    pub fn rgba(r: f32, g: f32, b: f32, a: f32) -> Self {
        Color { r: r, g: g, b: b, a: a}
    }
}

#[derive(Clone, Copy)]
pub struct Viewport {
    pub x: u32,
    pub y: u32,
    pub width: u32,
    pub height: u32
}

impl Viewport {
    pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
        Viewport {
            x: x,
            y: y,
            width: width,
            height: height
        }
    }
}

bitflags! {
    flags BufferBits: gl::types::GLbitfield {
        const COLOR_BUFFER_BIT = gl::COLOR_BUFFER_BIT,
        const DEPTH_BUFFER_BIT = gl::DEPTH_BUFFER_BIT,
        const STENCIL_BUFFER_BIT = gl::STENCIL_BUFFER_BIT
    }
}

#[derive(Debug)]
pub enum GLError {
    InvalidEnum,
    InvalidValue,
    InvalidOperation,
    InvalidFramebufferOperation,
    OutOfMemory,
    Message(String)
}

impl fmt::Display for GLError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GLError::InvalidEnum => {
                write!(f, "Invalid enum")
            },
            GLError::InvalidValue => {
                write!(f, "Invalid value")
            },
            GLError::InvalidOperation => {
                write!(f, "Invalid operation")
            },
            GLError::InvalidFramebufferOperation => {
                write!(f, "Invalid framebuffer operation")
            },
            GLError::OutOfMemory => {
                write!(f, "Out of memory")
            },
            GLError::Message(ref s) => {
                write!(f, "{}", s)
            }
        }
    }
}

impl error::Error for GLError {
    fn description(&self) -> &str {
        match *self {
            GLError::InvalidEnum => "Invalid enum variant in OpenGL call.",
            GLError::InvalidValue => "Out-of-range value in OpenGL call.",
            GLError::InvalidOperation => "The specified OpenGL operation is not allowed in the current state.",
            GLError::InvalidFramebufferOperation => "OpenGL command tried to read or write to an incomplete framebuffer.",
            GLError::OutOfMemory => "There is not enough memory left to execute the specified OpenGL command.",
            GLError::Message(ref s) => &s
        }
    }
}

#[derive(Debug)]
pub enum GLFramebufferError {
    IncompleteAttachment,
    IncompleteDimensions,
    IncompleteMissingAttachment,
    Unsupported
}

gl_enum! {
    pub gl_enum DrawingMode {
        Points as POINTS = gl::POINTS,
        LineStrip as LINE_STRIP = gl::LINE_STRIP,
        LineLoop as LINE_LOOP = gl::LINE_LOOP,
        Lines as LINES = gl::LINES,
        TriangleStrip as TRIANGLE_STRIP = gl::TRIANGLE_STRIP,
        TriangleFan as TRIANGLE_FAN = gl::TRIANGLE_FAN,
        Triangles as TRIANGLES = gl::TRIANGLES
    }
}

gl_enum! {
    pub gl_enum DataType {
        Byte as BYTE = gl::BYTE,
        UnsignedByte as UNSIGNED_BYTE = gl::UNSIGNED_BYTE,
        Short as SHORT = gl::SHORT,
        UnsignedShort as UNSIGNED_SHORT = gl::UNSIGNED_SHORT,
        Fixed as FIXED = gl::FIXED,
        Float as FLOAT = gl::FLOAT
    }
}
<|endoftext|>


<commit_before>extern crate num_cpus;

use std::fs::File;
use std::io::prelude::*;
use regex::RegexSet;
use gitignore::*;
use std::path::PathBuf;
use self::num_cpus::get;
use std::fs::Metadata;

#[cfg(target_os = "linux")]
use std::os::linux::fs::MetadataExt;

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "netbsd",
            target_os = "solaris"))]
use std::os::unix::fs::MetadataExt;

#[cfg(target_os = "linux")]
pub fn size(m: &Metadata, blocks: bool) -> u64 {
    if blocks { m.st_blocks() * 512 } else { m.len() }
}

#[cfg(target_os = "windows")]
pub fn size(m: &Metadata, _: bool) -> u64 {
    m.len()
}

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "netbsd",
            target_os = "solaris"))]
pub fn size(m: &Metadata, blocks: bool) -> u64 {
    if blocks {
        m.blocks() * 512 // idk if this is correct on bsd/linux
    } else {
        m.len()
    }
}

/// Gather the information from `.gitignore`, `.ignore`, and darcs `boring` files in a given
/// directory, and assemble a `RegexSet` from it.
pub fn mk_ignores(in_paths: &PathBuf, maybe_ignore: &Option<RegexSet>) -> Option<RegexSet> {

    if let Some(ref ignore) = *maybe_ignore {
        Some(ignore.to_owned())
    } else if let (ignore_path, Ok(mut file)) =
        {
            let mut ignore_path = in_paths.clone();
            ignore_path.push(".ignore");
            (ignore_path.clone(), File::open(ignore_path.clone()))
        }
    {
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(
            "File read failed.",
        ); // ok because we check that the file exists
        Some(file_contents_to_regex(&contents, &ignore_path))
    } else if let (gitignore_path, Ok(mut file)) =
        {
            let mut gitignore_path = in_paths.clone();
            gitignore_path.push(".gitignore");
            (gitignore_path.clone(), File::open(gitignore_path))
        }
    {
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(
            "File read failed.",
        ); // ok because we check that the file exists
        Some(file_contents_to_regex(&contents, &gitignore_path))
    } else if let (darcs_path, Ok(mut file)) =
        {
            let mut darcs_path = in_paths.clone();
            darcs_path.push("_darcs/prefs/boring");
            (darcs_path.clone(), File::open(darcs_path))
        }
    {
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(
            "File read failed.",
        ); // ok because we check that the file exists
        Some(darcs_contents_to_regex(&contents, &darcs_path))
    } else {
        None
    }
}

/// Helper function to get the number of CPUs. We subtract 1, because the main thread that's doing
/// the spawning counts as one OS thread.
pub fn get_processors() -> usize {
    let n = get();
    if n > 1 { n - 1 } else { n }
}
<commit_msg>experimental, possibly tempermental redox support<commit_after>extern crate num_cpus;

use std::fs::File;
use std::io::prelude::*;
use regex::RegexSet;
use gitignore::*;
use std::path::PathBuf;
use self::num_cpus::get;
use std::fs::Metadata;

#[cfg(target_os = "linux")]
use std::os::linux::fs::MetadataExt;

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "netbsd",
            target_os = "dragonfly", target_os = "solaris"))]
use std::os::unix::fs::MetadataExt;

#[cfg(target_os = "linux")]
pub fn size(m: &Metadata, blocks: bool) -> u64 {
    if blocks { m.st_blocks() * 512 } else { m.len() }
}

#[cfg(any(target_os = "windows", target_os = "redox"))]
pub fn size(m: &Metadata, _: bool) -> u64 {
    m.len()
}

#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "netbsd",
            target_os = "dragonfly", target_os = "solaris"))]
pub fn size(m: &Metadata, blocks: bool) -> u64 {
    if blocks {
        m.blocks() * 512 // idk if this is correct on bsd/linux
    } else {
        m.len()
    }
}

/// Gather the information from `.gitignore`, `.ignore`, and darcs `boring` files in a given
/// directory, and assemble a `RegexSet` from it.
pub fn mk_ignores(in_paths: &PathBuf, maybe_ignore: &Option<RegexSet>) -> Option<RegexSet> {

    if let Some(ref ignore) = *maybe_ignore {
        Some(ignore.to_owned())
    } else if let (ignore_path, Ok(mut file)) =
        {
            let mut ignore_path = in_paths.clone();
            ignore_path.push(".ignore");
            (ignore_path.clone(), File::open(ignore_path.clone()))
        }
    {
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(
            "File read failed.",
        ); // ok because we check that the file exists
        Some(file_contents_to_regex(&contents, &ignore_path))
    } else if let (gitignore_path, Ok(mut file)) =
        {
            let mut gitignore_path = in_paths.clone();
            gitignore_path.push(".gitignore");
            (gitignore_path.clone(), File::open(gitignore_path))
        }
    {
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(
            "File read failed.",
        ); // ok because we check that the file exists
        Some(file_contents_to_regex(&contents, &gitignore_path))
    } else if let (darcs_path, Ok(mut file)) =
        {
            let mut darcs_path = in_paths.clone();
            darcs_path.push("_darcs/prefs/boring");
            (darcs_path.clone(), File::open(darcs_path))
        }
    {
        let mut contents = String::new();
        file.read_to_string(&mut contents).expect(
            "File read failed.",
        ); // ok because we check that the file exists
        Some(darcs_contents_to_regex(&contents, &darcs_path))
    } else {
        None
    }
}

/// Helper function to get the number of CPUs. We subtract 1, because the main thread that's doing
/// the spawning counts as one OS thread.
pub fn get_processors() -> usize {
    let n = get();
    if n > 1 { n - 1 } else { n }
}
<|endoftext|>