<commit_before>// -*- rust -*-

import front.creader;
import front.parser;
import front.token;
import front.eval;
import front.ast;
import middle.trans;
import middle.resolve;
import middle.capture;
import middle.ty;
import middle.typeck;
import middle.typestate_check;
import back.Link;
import lib.llvm;
import util.common;

import std.FS;
import std.Map.mk_hashmap;
import std.Option;
import std.Option.some;
import std.Option.none;
import std.Str;
import std.Vec;
import std.IO;
import std.Time;

import std.GetOpts;
import std.GetOpts.optopt;
import std.GetOpts.optmulti;
import std.GetOpts.optflag;
import std.GetOpts.opt_present;

import back.Link.output_type;

fn default_environment(session.session sess,
                       str argv0,
                       str input) -> eval.env {

    auto libc = "libc.so";
    alt (sess.get_targ_cfg().os) {
        case (session.os_win32) { libc = "msvcrt.dll"; }
        case (session.os_macos) { libc = "libc.dylib"; }
        case (session.os_linux) { libc = "libc.so.6"; }
    }

    ret
        vec(
            // Target bindings.
            tup("target_os", eval.val_str(std.OS.target_os())),
            tup("target_arch", eval.val_str("x86")),
            tup("target_libc", eval.val_str(libc)),

            // Build bindings.
            tup("build_compiler", eval.val_str(argv0)),
            tup("build_input", eval.val_str(input))
            );
}

fn parse_input(session.session sess,
                      parser.parser p,
                      str input) -> @ast.crate {
    if (Str.ends_with(input, ".rc")) {
        ret parser.parse_crate_from_crate_file(p);
    } else if (Str.ends_with(input, ".rs")) {
        ret parser.parse_crate_from_source_file(p);
    }
    sess.err("unknown input file type: " + input);
    fail;
}

fn time[T](bool do_it, str what, fn()->T thunk) -> T {
    if (!do_it) { ret thunk(); }

    auto start = Time.get_time();
    auto rv = thunk();
    auto end = Time.get_time();

    // FIXME: Actually do timeval math.
    log_err #fmt("time: %s took %u s", what, (end.sec - start.sec) as uint);
    ret rv;
}

fn compile_input(session.session sess,
                 eval.env env,
                 str input, str output) {
    auto time_passes = sess.get_opts().time_passes;
    auto def = tup(0, 0);
    auto p = parser.new_parser(sess, env, def, input, 0u);
    auto crate = time[@ast.crate](time_passes, "parsing",
                                  bind parse_input(sess, p, input));
    if (sess.get_opts().output_type == Link.output_type_none) {ret;}

    crate = time[@ast.crate](time_passes, "external crate reading",
                             bind creader.read_crates(sess, crate));
    crate = time[@ast.crate](time_passes, "resolution",
                             bind resolve.resolve_crate(sess, crate));
    time[()](time_passes, "capture checking",
             bind capture.check_for_captures(sess, crate));

    auto ty_cx = ty.mk_ctxt(sess);
    auto typeck_result =
        time[typeck.typecheck_result](time_passes, "typechecking",
                                      bind typeck.check_crate(ty_cx, crate));
    crate = typeck_result._0;
    auto type_cache = typeck_result._1;

    if (sess.get_opts().run_typestate) {
        crate = time[@ast.crate](time_passes, "typestate checking",
            bind typestate_check.check_crate(crate));
    }

    auto llmod = time[llvm.ModuleRef](time_passes, "translation",
        bind trans.trans_crate(sess, crate, ty_cx, type_cache, output));

    time[()](time_passes, "LLVM passes",
             bind Link.Write.run_passes(sess, llmod, output));
}

fn pretty_print_input(session.session sess,
                             eval.env env,
                             str input) {
    auto def = tup(0, 0);
    auto p = front.parser.new_parser(sess, env, def, input, 0u);
    auto crate = front.parser.parse_crate_from_source_file(p);
    pretty.pprust.print_file(crate.node.module, input, std.IO.stdout());
}

fn version(str argv0) {
    auto vers = "unknown version";
    auto env_vers = #env("CFG_VERSION");
    if (Str.byte_len(env_vers) != 0u) {
        vers = env_vers;
    }
    IO.stdout().write_str(#fmt("%s %s\n", argv0, vers));
}

fn usage(str argv0) {
    IO.stdout().write_str(#fmt("usage: %s [options] <input>\n", argv0) + "
options:

    -h --help          display this message
    -v --version       print version info and exit

    -o <filename>      write output to <filename>
    --glue             generate glue.bc file
    --shared           compile a shared-library crate
    --pretty           pretty-print the input instead of compiling
    --ls               list the symbols defined by a crate file
    -L <path>          add a directory to the library search path
    --noverify         suppress LLVM verification step (slight speedup)
    --depend           print dependencies, in makefile-rule form
    --parse-only       parse only; do not compile, assemble, or link
    -g                 produce debug info
    -O                 optimize
    -S                 compile only; do not assemble or link
    -c                 compile and assemble, but do not link
    --save-temps       write intermediate files in addition to normal output
    --time-passes      time the individual phases of the compiler
    --time-llvm-passes time the individual phases of the LLVM backend
    --sysroot <path>   override the system root (default: rustc's directory)
    --no-typestate     don't run the typestate pass (unsafe!)\n\n");
}

fn get_os(str triple) -> session.os {
    if (Str.find(triple, "win32") > 0 ||
        Str.find(triple, "mingw32") > 0 ) {
        ret session.os_win32;
    } else if (Str.find(triple, "darwin") > 0) { ret session.os_macos; }
    else if (Str.find(triple, "linux") > 0) { ret session.os_linux; }
}

fn get_arch(str triple) -> session.arch {
    if (Str.find(triple, "i386") > 0 ||
        Str.find(triple, "i486") > 0 ||
        Str.find(triple, "i586") > 0 ||
        Str.find(triple, "i686") > 0 ||
        Str.find(triple, "i786") > 0 ) {
        ret session.arch_x86;
    } else if (Str.find(triple, "x86_64") > 0) {
        ret session.arch_x64;
    } else if (Str.find(triple, "arm") > 0 ||
        Str.find(triple, "xscale") > 0 ) {
        ret session.arch_arm;
    }
}

fn get_default_sysroot(str binary) -> str {
    auto dirname = FS.dirname(binary);
    if (Str.eq(dirname, binary)) { ret "."; }
    ret dirname;
}

fn main(vec[str] args) {

    let str triple =
        std.Str.rustrt.str_from_cstr(llvm.llvm.LLVMRustGetHostTriple());

    let @session.config target_cfg =
        @rec(os = get_os(triple),
             arch = get_arch(triple),
             int_type = common.ty_i32,
             uint_type = common.ty_u32,
             float_type = common.ty_f64);

    auto opts = vec(optflag("h"), optflag("help"),
                    optflag("v"), optflag("version"),
                    optflag("glue"),
                    optflag("pretty"), optflag("ls"), optflag("parse-only"),
                    optflag("O"), optflag("shared"), optmulti("L"),
                    optflag("S"), optflag("c"), optopt("o"), optopt("g"),
                    optflag("save-temps"), optopt("sysroot"),
                    optflag("time-passes"), optflag("time-llvm-passes"),
                    optflag("no-typestate"), optflag("noverify"));
    auto binary = Vec.shift[str](args);
    auto match;
    alt (GetOpts.getopts(args, opts)) {
        case (GetOpts.failure(?f)) {
            log_err #fmt("error: %s", GetOpts.fail_str(f));
            fail;
        }
        case (GetOpts.success(?m)) { match = m; }
    }
    if (opt_present(match, "h") ||
        opt_present(match, "help")) {
        usage(binary);
        ret;
    }

    if (opt_present(match, "v") ||
        opt_present(match, "version")) {
        version(binary);
        ret;
    }

    auto pretty = opt_present(match, "pretty");
    auto ls = opt_present(match, "ls");
    auto glue = opt_present(match, "glue");
    auto shared = opt_present(match, "shared");
    auto output_file = GetOpts.opt_maybe_str(match, "o");
    auto library_search_paths = GetOpts.opt_strs(match, "L");

    auto output_type = Link.output_type_bitcode;
    if (opt_present(match, "parse-only")) {
        output_type = Link.output_type_none;
    } else if (opt_present(match, "S")) {
        output_type = Link.output_type_assembly;
    } else if (opt_present(match, "c")) {
        output_type = Link.output_type_object;
    }

    auto verify = !opt_present(match, "noverify");
    auto save_temps = opt_present(match, "save-temps");
    // FIXME: Maybe we should support -O0, -O1, -Os, etc
    auto optimize = opt_present(match, "O");
    auto debuginfo = opt_present(match, "g");
    auto time_passes = opt_present(match, "time-passes");
    auto time_llvm_passes = opt_present(match, "time-llvm-passes");
    auto run_typestate = !opt_present(match, "no-typestate");
    auto sysroot_opt = GetOpts.opt_maybe_str(match, "sysroot");

    auto sysroot;
    alt (sysroot_opt) {
        case (none[str]) { sysroot = get_default_sysroot(binary); }
        case (some[str](?s)) { sysroot = s; }
    }

    let @session.options sopts =
        @rec(shared = shared,
             optimize = optimize,
             debuginfo = debuginfo,
             verify = verify,
             run_typestate = run_typestate,
             save_temps = save_temps,
             time_passes = time_passes,
             time_llvm_passes = time_llvm_passes,
             output_type = output_type,
             library_search_paths = library_search_paths,
             sysroot = sysroot);

    auto crate_cache = common.new_int_hash[session.crate_metadata]();
    auto target_crate_num = 0;
    let vec[@ast.meta_item] md = vec();
    auto sess =
        session.session(target_crate_num, target_cfg, sopts,
                        crate_cache, md, front.codemap.new_codemap());

    auto n_inputs = Vec.len[str](match.free);

    if (glue) {
        if (n_inputs > 0u) {
            sess.err("No input files allowed with --glue.");
        }
        auto out = Option.from_maybe[str]("glue.bc", output_file);
        middle.trans.make_common_glue(sess, out);
        ret;
    }

    if (n_inputs == 0u) {
        sess.err("No input filename given.");
    } else if (n_inputs > 1u) {
        sess.err("Multiple input filenames provided.");
    }

    auto ifile = match.free.(0);
    auto env = default_environment(sess, args.(0), ifile);
    if (pretty) {
        pretty_print_input(sess, env, ifile);
    } else if (ls) {
        front.creader.list_file_metadata(ifile, std.IO.stdout());
    } else {
        alt (output_file) {
            case (none[str]) {
                let vec[str] parts = Str.split(ifile, '.' as u8);
                Vec.pop[str](parts);
                alt (output_type) {
                    case (Link.output_type_none) { parts += vec("pp"); }
                    case (Link.output_type_bitcode) { parts += vec("bc"); }
                    case (Link.output_type_assembly) { parts += vec("s"); }
                    case (Link.output_type_object) { parts += vec("o"); }
                }
                auto ofile = Str.connect(parts, ".");
                compile_input(sess, env, ifile, ofile);
            }
            case (some[str](?ofile)) {
                compile_input(sess, env, ifile, ofile);
            }
        }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>rustc: Make -g not take an argument<commit_after>// -*- rust -*-

import front.creader;
import front.parser;
import front.token;
import front.eval;
import front.ast;
import middle.trans;
import middle.resolve;
import middle.capture;
import middle.ty;
import middle.typeck;
import middle.typestate_check;
import back.Link;
import lib.llvm;
import util.common;

import std.FS;
import std.Map.mk_hashmap;
import std.Option;
import std.Option.some;
import std.Option.none;
import std.Str;
import std.Vec;
import std.IO;
import std.Time;

import std.GetOpts;
import std.GetOpts.optopt;
import std.GetOpts.optmulti;
import std.GetOpts.optflag;
import std.GetOpts.opt_present;

import back.Link.output_type;

fn default_environment(session.session sess,
                       str argv0,
                       str input) -> eval.env {

    auto libc = "libc.so";
    alt (sess.get_targ_cfg().os) {
        case (session.os_win32) { libc = "msvcrt.dll"; }
        case (session.os_macos) { libc = "libc.dylib"; }
        case (session.os_linux) { libc = "libc.so.6"; }
    }

    ret
        vec(
            // Target bindings.
            tup("target_os", eval.val_str(std.OS.target_os())),
            tup("target_arch", eval.val_str("x86")),
            tup("target_libc", eval.val_str(libc)),

            // Build bindings.
            tup("build_compiler", eval.val_str(argv0)),
            tup("build_input", eval.val_str(input))
            );
}

fn parse_input(session.session sess,
                      parser.parser p,
                      str input) -> @ast.crate {
    if (Str.ends_with(input, ".rc")) {
        ret parser.parse_crate_from_crate_file(p);
    } else if (Str.ends_with(input, ".rs")) {
        ret parser.parse_crate_from_source_file(p);
    }
    sess.err("unknown input file type: " + input);
    fail;
}

fn time[T](bool do_it, str what, fn()->T thunk) -> T {
    if (!do_it) { ret thunk(); }

    auto start = Time.get_time();
    auto rv = thunk();
    auto end = Time.get_time();

    // FIXME: Actually do timeval math.
    log_err #fmt("time: %s took %u s", what, (end.sec - start.sec) as uint);
    ret rv;
}

fn compile_input(session.session sess,
                 eval.env env,
                 str input, str output) {
    auto time_passes = sess.get_opts().time_passes;
    auto def = tup(0, 0);
    auto p = parser.new_parser(sess, env, def, input, 0u);
    auto crate = time[@ast.crate](time_passes, "parsing",
                                  bind parse_input(sess, p, input));
    if (sess.get_opts().output_type == Link.output_type_none) {ret;}

    crate = time[@ast.crate](time_passes, "external crate reading",
                             bind creader.read_crates(sess, crate));
    crate = time[@ast.crate](time_passes, "resolution",
                             bind resolve.resolve_crate(sess, crate));
    time[()](time_passes, "capture checking",
             bind capture.check_for_captures(sess, crate));

    auto ty_cx = ty.mk_ctxt(sess);
    auto typeck_result =
        time[typeck.typecheck_result](time_passes, "typechecking",
                                      bind typeck.check_crate(ty_cx, crate));
    crate = typeck_result._0;
    auto type_cache = typeck_result._1;

    if (sess.get_opts().run_typestate) {
        crate = time[@ast.crate](time_passes, "typestate checking",
            bind typestate_check.check_crate(crate));
    }

    auto llmod = time[llvm.ModuleRef](time_passes, "translation",
        bind trans.trans_crate(sess, crate, ty_cx, type_cache, output));

    time[()](time_passes, "LLVM passes",
             bind Link.Write.run_passes(sess, llmod, output));
}

fn pretty_print_input(session.session sess,
                             eval.env env,
                             str input) {
    auto def = tup(0, 0);
    auto p = front.parser.new_parser(sess, env, def, input, 0u);
    auto crate = front.parser.parse_crate_from_source_file(p);
    pretty.pprust.print_file(crate.node.module, input, std.IO.stdout());
}

fn version(str argv0) {
    auto vers = "unknown version";
    auto env_vers = #env("CFG_VERSION");
    if (Str.byte_len(env_vers) != 0u) {
        vers = env_vers;
    }
    IO.stdout().write_str(#fmt("%s %s\n", argv0, vers));
}

fn usage(str argv0) {
    IO.stdout().write_str(#fmt("usage: %s [options] <input>\n", argv0) + "
options:

    -h --help          display this message
    -v --version       print version info and exit

    -o <filename>      write output to <filename>
    --glue             generate glue.bc file
    --shared           compile a shared-library crate
    --pretty           pretty-print the input instead of compiling
    --ls               list the symbols defined by a crate file
    -L <path>          add a directory to the library search path
    --noverify         suppress LLVM verification step (slight speedup)
    --depend           print dependencies, in makefile-rule form
    --parse-only       parse only; do not compile, assemble, or link
    -g                 produce debug info
    -O                 optimize
    -S                 compile only; do not assemble or link
    -c                 compile and assemble, but do not link
    --save-temps       write intermediate files in addition to normal output
    --time-passes      time the individual phases of the compiler
    --time-llvm-passes time the individual phases of the LLVM backend
    --sysroot <path>   override the system root (default: rustc's directory)
    --no-typestate     don't run the typestate pass (unsafe!)\n\n");
}

fn get_os(str triple) -> session.os {
    if (Str.find(triple, "win32") > 0 ||
        Str.find(triple, "mingw32") > 0 ) {
        ret session.os_win32;
    } else if (Str.find(triple, "darwin") > 0) { ret session.os_macos; }
    else if (Str.find(triple, "linux") > 0) { ret session.os_linux; }
}

fn get_arch(str triple) -> session.arch {
    if (Str.find(triple, "i386") > 0 ||
        Str.find(triple, "i486") > 0 ||
        Str.find(triple, "i586") > 0 ||
        Str.find(triple, "i686") > 0 ||
        Str.find(triple, "i786") > 0 ) {
        ret session.arch_x86;
    } else if (Str.find(triple, "x86_64") > 0) {
        ret session.arch_x64;
    } else if (Str.find(triple, "arm") > 0 ||
        Str.find(triple, "xscale") > 0 ) {
        ret session.arch_arm;
    }
}

fn get_default_sysroot(str binary) -> str {
    auto dirname = FS.dirname(binary);
    if (Str.eq(dirname, binary)) { ret "."; }
    ret dirname;
}

fn main(vec[str] args) {

    let str triple =
        std.Str.rustrt.str_from_cstr(llvm.llvm.LLVMRustGetHostTriple());

    let @session.config target_cfg =
        @rec(os = get_os(triple),
             arch = get_arch(triple),
             int_type = common.ty_i32,
             uint_type = common.ty_u32,
             float_type = common.ty_f64);

    auto opts = vec(optflag("h"), optflag("help"),
                    optflag("v"), optflag("version"),
                    optflag("glue"),
                    optflag("pretty"), optflag("ls"), optflag("parse-only"),
                    optflag("O"), optflag("shared"), optmulti("L"),
                    optflag("S"), optflag("c"), optopt("o"), optflag("g"),
                    optflag("save-temps"), optopt("sysroot"),
                    optflag("time-passes"), optflag("time-llvm-passes"),
                    optflag("no-typestate"), optflag("noverify"));
    auto binary = Vec.shift[str](args);
    auto match;
    alt (GetOpts.getopts(args, opts)) {
        case (GetOpts.failure(?f)) {
            log_err #fmt("error: %s", GetOpts.fail_str(f));
            fail;
        }
        case (GetOpts.success(?m)) { match = m; }
    }
    if (opt_present(match, "h") ||
        opt_present(match, "help")) {
        usage(binary);
        ret;
    }

    if (opt_present(match, "v") ||
        opt_present(match, "version")) {
        version(binary);
        ret;
    }

    auto pretty = opt_present(match, "pretty");
    auto ls = opt_present(match, "ls");
    auto glue = opt_present(match, "glue");
    auto shared = opt_present(match, "shared");
    auto output_file = GetOpts.opt_maybe_str(match, "o");
    auto library_search_paths = GetOpts.opt_strs(match, "L");

    auto output_type = Link.output_type_bitcode;
    if (opt_present(match, "parse-only")) {
        output_type = Link.output_type_none;
    } else if (opt_present(match, "S")) {
        output_type = Link.output_type_assembly;
    } else if (opt_present(match, "c")) {
        output_type = Link.output_type_object;
    }

    auto verify = !opt_present(match, "noverify");
    auto save_temps = opt_present(match, "save-temps");
    // FIXME: Maybe we should support -O0, -O1, -Os, etc
    auto optimize = opt_present(match, "O");
    auto debuginfo = opt_present(match, "g");
    auto time_passes = opt_present(match, "time-passes");
    auto time_llvm_passes = opt_present(match, "time-llvm-passes");
    auto run_typestate = !opt_present(match, "no-typestate");
    auto sysroot_opt = GetOpts.opt_maybe_str(match, "sysroot");

    auto sysroot;
    alt (sysroot_opt) {
        case (none[str]) { sysroot = get_default_sysroot(binary); }
        case (some[str](?s)) { sysroot = s; }
    }

    let @session.options sopts =
        @rec(shared = shared,
             optimize = optimize,
             debuginfo = debuginfo,
             verify = verify,
             run_typestate = run_typestate,
             save_temps = save_temps,
             time_passes = time_passes,
             time_llvm_passes = time_llvm_passes,
             output_type = output_type,
             library_search_paths = library_search_paths,
             sysroot = sysroot);

    auto crate_cache = common.new_int_hash[session.crate_metadata]();
    auto target_crate_num = 0;
    let vec[@ast.meta_item] md = vec();
    auto sess =
        session.session(target_crate_num, target_cfg, sopts,
                        crate_cache, md, front.codemap.new_codemap());

    auto n_inputs = Vec.len[str](match.free);

    if (glue) {
        if (n_inputs > 0u) {
            sess.err("No input files allowed with --glue.");
        }
        auto out = Option.from_maybe[str]("glue.bc", output_file);
        middle.trans.make_common_glue(sess, out);
        ret;
    }

    if (n_inputs == 0u) {
        sess.err("No input filename given.");
    } else if (n_inputs > 1u) {
        sess.err("Multiple input filenames provided.");
    }

    auto ifile = match.free.(0);
    auto env = default_environment(sess, args.(0), ifile);
    if (pretty) {
        pretty_print_input(sess, env, ifile);
    } else if (ls) {
        front.creader.list_file_metadata(ifile, std.IO.stdout());
    } else {
        alt (output_file) {
            case (none[str]) {
                let vec[str] parts = Str.split(ifile, '.' as u8);
                Vec.pop[str](parts);
                alt (output_type) {
                    case (Link.output_type_none) { parts += vec("pp"); }
                    case (Link.output_type_bitcode) { parts += vec("bc"); }
                    case (Link.output_type_assembly) { parts += vec("s"); }
                    case (Link.output_type_object) { parts += vec("o"); }
                }
                auto ofile = Str.connect(parts, ".");
                compile_input(sess, env, ifile, ofile);
            }
            case (some[str](?ofile)) {
                compile_input(sess, env, ifile, ofile);
            }
        }
    }
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before><commit_msg>Add cargo (#222)<commit_after>use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time::Duration;

use console::Term;
use indicatif::{ProgressBar, ProgressStyle};
use rand::Rng;

static CRATES: &'static [&'static str] = &[
    "console",
    "lazy_static",
    "libc",
    "regex",
    "regex-syntax",
    "terminal_size",
    "libc",
    "unicode-width",
    "lazy_static",
    "number_prefix",
    "regex",
    "rand",
    "getrandom",
    "cfg-if",
    "libc",
    "rand_chacha",
    "ppv-lite86",
    "rand_core",
    "getrandom",
    "rand_core",
    "tokio",
    "bytes",
    "pin-project-lite",
    "slab",
    "indicatif",
    "cargo(example)",
];

fn main() {
    // number of cpus, constant
    let cpus = 4;

    // mimic cargo progress bar although it behaves a bit different
    let pb = ProgressBar::new(CRATES.len() as u64);
    pb.set_style(
        ProgressStyle::default_bar()
            // note that bar size is fixed unlike cargo which is dynamic
            // and also the truncation in cargo uses trailers (`...`)
            .template(if Term::stdout().size().1 > 80 {
                "{prefix:>12.green} [{bar:57}] {pos}/{len} {wide_msg}"
            } else {
                "{prefix:>12.green} [{bar:57}] {pos}/{len}"
            })
            .progress_chars("#> "),
    );
    pb.set_prefix("Building");

    // process in another thread
    // crates to be iterated but not exactly a tree
    let crates = Arc::new(Mutex::new(CRATES.iter()));
    let (tx, rx) = mpsc::channel();
    for n in 0..cpus {
        let tx = tx.clone();
        let crates = crates.clone();
        thread::spawn(move || {
            let mut rng = rand::thread_rng();
            loop {
                let krate = crates.lock().unwrap().next();
                // notify main thread if n thread is processing a crate
                tx.send((n, krate)).unwrap();
                if let Some(krate) = krate {
                    thread::sleep(Duration::from_millis(
                        // last compile and linking is always slow, let's mimic that
                        if CRATES[CRATES.len() - 1] == *krate {
                            rng.gen_range(1000, 2000)
                        } else {
                            rng.gen_range(50, 300)
                        },
                    ));
                } else {
                    break;
                }
            }
        });
    }
    // drop tx to stop waiting
    drop(tx);

    // do progress drawing in main thread
    let mut processing = vec![None; cpus];
    while let Ok((n, krate)) = rx.recv() {
        processing[n] = krate;
        let crates: Vec<&str> = processing.iter().filter_map(|t| t.copied()).collect();
        pb.set_message(&crates.join(", "));
        if krate.is_some() {
            // crate is built
            pb.inc(1);
        }
    }
    pb.finish_and_clear();
}
<|endoftext|>


<commit_before><commit_msg>Add embedding examples<commit_after>extern crate perl_sys;

use perl_sys::fn_bindings::{
    eval_pv, ouroboros_sys_init3, ouroboros_sys_term, perl_alloc,
    perl_construct, perl_destruct, perl_free, perl_parse, perl_run,
};
use perl_sys::pthx;

pthx! {
    fn init(_perl) {}
}

#[link(name="perl")]
extern "C" {}

#[link_name="my_perl"]
pub static mut MY_PERL: *mut perl_sys::types::PerlInterpreter = std::ptr::null_mut();

fn main() {
    let mut argv = [
        b"\0"[..].as_ptr() as *mut _,
        b"-e0\0"[..].as_ptr() as *mut _,
        std::ptr::null_mut(),
    ];
    let mut argc = 2;
    let mut argv = argv.as_mut_ptr();
    let mut envp = [std::ptr::null_mut()].as_mut_ptr();

    unsafe {
        ouroboros_sys_init3(&mut argc, &mut argv, &mut envp);
        MY_PERL = perl_alloc();
        perl_construct(MY_PERL);
        perl_parse(MY_PERL, init, argc, argv, envp);
        perl_run(MY_PERL);

        pthx!(eval_pv(MY_PERL, b"print 1 + 2, chr(10) \0".as_ptr() as *const _, 1));

        perl_destruct(MY_PERL);
        perl_free(MY_PERL);
        ouroboros_sys_term();
    }
}
<|endoftext|>


<commit_before><commit_msg>Example sandbox for the new rasterizer<commit_after>extern crate polydraw;

use polydraw::{Application, Renderer, Frame};
use polydraw::draw::RGB;
use polydraw::raster::{Scene, Point, Segment, Circle, EdgeType, Edge, Poly};
use polydraw::geom::number::NumberOps;

const DIV_PER_PIXEL: i64 = 1000;

#[inline]
fn to_px(v: i64) -> i64 {
   v / DIV_PER_PIXEL
}

#[inline]
fn from_px(v: i64) -> i64 {
   v as i64 * DIV_PER_PIXEL
}

struct SceneRenderer {
   index: usize,
}

impl SceneRenderer {
   fn new() -> Self {
      SceneRenderer {
         index: 0
      }
   }
}

impl Renderer for SceneRenderer {
   fn render(&mut self, frame: &mut Frame) {
      frame.clear();
   }
}

fn main() {
   let mut renderer = SceneRenderer::new();

   Application::new()
      .renderer(&mut renderer)
      .title("Scene")
      .run();
}
<|endoftext|>


<commit_before><commit_msg>Fix for broken pipe panic<commit_after><|endoftext|>


<commit_before>import rustc::syntax::ast;

export parse_fn;

fn parse_fn(
    name: str,
    id: ast::node_id,
    attrs: [ast::attribute]
) -> doc::fndoc {
    let _fndoc = none;
    for attr: ast::attribute in attrs {
        alt attr.node.value.node {
            ast::meta_name_value(
                "doc", {node: ast::lit_str(value), span: _}) {
                _fndoc = some(~{
                    id: id,
                    name: name,
                    brief: some(value),
                    desc: none,
                    return: none,
                    args: []
                });
            }
            ast::meta_list("doc", docs) {
                _fndoc = some(
                    parse_fn_(name, id, docs));
            }
        }
    }

    let _fndoc0 = alt _fndoc {
        some(_d) { _d }
        none. {
          ~{
              id: id,
              name: name,
              brief: none,
              desc: none,
              return: none,
              args: []
          }
        }
    };

    ret _fndoc0;
}

#[doc(
  brief = "Parses function docs from a complex #[doc] attribute.",
  desc = "Supported attributes:

* `brief`: Brief description
* `desc`: Long description
* `return`: Description of return value
* `args`: List of argname = argdesc pairs
",
  args(items = "Doc attribute contents"),
  return = "Parsed function docs."
)]
fn parse_fn_(
    name: str,
    id: ast::node_id,
    items: [@ast::meta_item]
) -> doc::fndoc {
    let brief = none;
    let desc = none;
    let return = none;
    let argdocs = [];
    let argdocsfound = none;
    for item: @ast::meta_item in items {
        alt item.node {
            ast::meta_name_value("brief", {node: ast::lit_str(value),
                                           span: _}) {
                brief = some(value);
            }
            ast::meta_name_value("desc", {node: ast::lit_str(value),
                                              span: _}) {
                desc = some(value);
            }
            ast::meta_name_value("return", {node: ast::lit_str(value),
                                            span: _}) {
                return = some(value);
            }
            ast::meta_list("args", args) {
                argdocsfound = some(args);
            }
            _ { }
        }
    }

    alt argdocsfound {
        none. { }
        some(ds) {
            for d: @ast::meta_item in ds {
                alt d.node {
                  ast::meta_name_value(key, {node: ast::lit_str(value),
                                             span: _}) {
                    argdocs += [(key, value)];
                  }
                }
            }
        }
    }

    ~{
        id: id,
        name: name,
        brief: brief,
        desc: desc,
        return: some({
            desc: return,
            ty: none,
        }),
        args: argdocs }
}

#[cfg(test)]
mod tests {

    fn parse_attributes(source: str) -> [ast::attribute] {
        import rustc::driver::diagnostic;
        import rustc::syntax::codemap;
        import rustc::syntax::parse::parser;

        let cm = codemap::new_codemap();
        let parse_sess = @{
            cm: cm,
            mutable next_id: 0,
            diagnostic: diagnostic::mk_handler(cm, none)
        };
        let parser = parser::new_parser_from_source_str(
            parse_sess, [], "-", source);

        parser::parse_outer_attributes(parser)
    }

    #[test]
    fn parse_fn_should_handle_undocumented_functions() {
        let source = "";
        let attrs = parse_attributes(source);
        let doc = parse_fn("f", 0, attrs);
        assert doc.brief == none;
        assert doc.desc == none;
        assert doc.return == none;
        assert vec::len(doc.args) == 0u;
    }

    #[test]
    fn parse_fn_should_parse_simple_doc_attributes() {
        let source = "#[doc = \"basic\"]";
        let attrs = parse_attributes(source);
        let doc = parse_fn("f", 0, attrs);
        assert doc.brief == some("basic");
    }

    #[test]
    fn parse_fn_should_parse_the_brief_description() {
        let source = "#[doc(brief = \"short\")]";
        let attrs = parse_attributes(source);
        let doc = parse_fn("f", 0, attrs);
        assert doc.brief == some("short");
    }

    #[test]
    fn parse_fn_should_parse_the_long_description() {
        let source = "#[doc(desc = \"description\")]";
        let attrs = parse_attributes(source);
        let doc = parse_fn("f", 0, attrs);
        assert doc.desc == some("description");
    }

    #[test]
    fn parse_fn_should_parse_the_return_value_description() {
        let source = "#[doc(return = \"return value\")]";
        let attrs = parse_attributes(source);
        let doc = parse_fn("f", 0, attrs);
        assert option::get(doc.return).desc == some("return value");
    }

    #[test]
    fn parse_fn_should_parse_the_argument_descriptions() {
        let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
        let attrs = parse_attributes(source);
        let doc = parse_fn("f", 0, attrs);
        assert doc.args[0] == ("a", "arg a");
        assert doc.args[1] == ("b", "arg b");
    }
}<commit_msg>rustdoc: Remove non-attribute related stuff from attr_parser<commit_after>import rustc::syntax::ast;

export fn_attrs, arg_attrs;
export parse_fn;

type fn_attrs = {
    brief: option<str>,
    desc: option<str>,
    args: [arg_attrs],
    return: option<str>
};

type arg_attrs = {
    name: str,
    desc: str
};

fn parse_fn(
    attrs: [ast::attribute]
) -> fn_attrs {

    for attr in attrs {
        alt attr.node.value.node {
          ast::meta_name_value(
              "doc", {node: ast::lit_str(value), span: _}) {
            ret {
                brief: none,
                desc: some(value),
                args: [],
                return: none
            };
          }
          ast::meta_list("doc", docs) {
            ret parse_fn_(docs);
          }
        }
    }

    {
        brief: none,
        desc: none,
        args: [],
        return: none
    }
}

fn parse_fn_(
    items: [@ast::meta_item]
) -> fn_attrs {
    let brief = none;
    let desc = none;
    let return = none;
    let argdocs = [];
    let argdocsfound = none;
    for item: @ast::meta_item in items {
        alt item.node {
            ast::meta_name_value("brief", {node: ast::lit_str(value),
                                           span: _}) {
                brief = some(value);
            }
            ast::meta_name_value("desc", {node: ast::lit_str(value),
                                              span: _}) {
                desc = some(value);
            }
            ast::meta_name_value("return", {node: ast::lit_str(value),
                                            span: _}) {
                return = some(value);
            }
            ast::meta_list("args", args) {
                argdocsfound = some(args);
            }
            _ { }
        }
    }

    alt argdocsfound {
        none. { }
        some(ds) {
            for d: @ast::meta_item in ds {
                alt d.node {
                  ast::meta_name_value(key, {node: ast::lit_str(value),
                                             span: _}) {
                    argdocs += [{
                        name: key,
                        desc: value
                    }];
                  }
                }
            }
        }
    }

    {
        brief: brief,
        desc: desc,
        args: argdocs,
        return: return
    }
}

#[cfg(test)]
mod tests {

    fn parse_attributes(source: str) -> [ast::attribute] {
        import rustc::driver::diagnostic;
        import rustc::syntax::codemap;
        import rustc::syntax::parse::parser;

        let cm = codemap::new_codemap();
        let parse_sess = @{
            cm: cm,
            mutable next_id: 0,
            diagnostic: diagnostic::mk_handler(cm, none)
        };
        let parser = parser::new_parser_from_source_str(
            parse_sess, [], "-", source);

        parser::parse_outer_attributes(parser)
    }

    #[test]
    fn parse_fn_should_handle_undocumented_functions() {
        let source = "";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == none;
        assert attrs.desc == none;
        assert attrs.return == none;
        assert vec::len(attrs.args) == 0u;
    }

    #[tes]
    fn parse_fn_should_parse_simple_doc_attributes() {
        let source = "#[doc = \"basic\"]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == some("basic");
    }

    #[test]
    fn parse_fn_should_parse_the_brief_description() {
        let source = "#[doc(brief = \"short\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.brief == some("short");
    }

    #[test]
    fn parse_fn_should_parse_the_long_description() {
        let source = "#[doc(desc = \"description\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.desc == some("description");
    }

    #[test]
    fn parse_fn_should_parse_the_return_value_description() {
        let source = "#[doc(return = \"return value\")]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.return == some("return value");
    }

    #[test]
    fn parse_fn_should_parse_the_argument_descriptions() {
        let source = "#[doc(args(a = \"arg a\", b = \"arg b\"))]";
        let attrs = parse_attributes(source);
        let attrs = parse_fn(attrs);
        assert attrs.args[0] == {name: "a", desc: "arg a"};
        assert attrs.args[1] == {name: "b", desc: "arg b"};
    }
}<|endoftext|>


<commit_before><commit_msg>finish rust version<commit_after>fn find_k_closest_elements(arr: Vec<i32>, k: i32, x: i32) -> Vec<i32> {
    let mut i_large = 0;
    let length = arr.len() as i32;
    for v in &arr {
        if *v >= x {
            break;
        } else {
            i_large += 1;
        }
    }

    let i = if i_large - k >= 0 { i_large - k } else { 0 };
    let j = if i_large + k < length {
        i_large + k
    } else {
        length
    };

    let mut temp_result: Vec<i32> = vec![];
    for ind in i..j {
        temp_result.push(*arr.iter().nth(ind as usize).unwrap());
    }

    //println!("{:?}", temp_result);
    temp_result.sort_by_key(|v| (*v - x).abs());
    let mut re = temp_result.drain(..k as usize).collect::<Vec<i32>>();
    re.sort();

    re
}

fn main() {
    println!("{:?}", find_k_closest_elements(vec![1, 2, 3, 4, 5], 4, 3));
    println!(
        "{:?}",
        find_k_closest_elements(vec![0, 0, 0, 1, 3, 5, 6, 7, 8, 8], 2, 2)
    );
}
<|endoftext|>


<commit_before><commit_msg>Add Default impls, ignore_all ctors to filter types<commit_after><|endoftext|>


<commit_before><commit_msg>chore: Whitespace<commit_after><|endoftext|>


<commit_before><commit_msg>Use the correct datatype for fdopen.<commit_after><|endoftext|>


<commit_before>use quote::{ToTokens, Tokens};
use syn::synom::Synom;
use syn::{Field, FieldsNamed, Meta, NestedMeta};

use api::strip_serde_attrs;

#[derive(Debug)]
pub struct Request {
    fields: Vec<RequestField>,
}

impl Synom for Request {
    named!(parse -> Self, do_parse!(
        fields: syn!(FieldsNamed) >>
        (Request {
            fields,
        })
    ));
}

impl Request {
    pub fn has_body_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_body())
    }

    pub fn has_path_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_path())
    }

    pub fn has_query_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_query())
    }

    pub fn path_field_count(&self) -> usize {
        self.fields.iter().filter(|field| field.is_path()).count()
    }

    pub fn newtype_body_field(&self) -> Option<&Field> {
        for request_field in self.fields.iter() {
            match *request_field {
                RequestField::NewtypeBody(ref field) => {
                    return Some(field);
                }
                _ => continue,
            }
        }

        None
    }

    pub fn request_body_init_fields(&self) -> Tokens {
        self.struct_init_fields(RequestFieldKind::Body)
    }

    pub fn request_path_init_fields(&self) -> Tokens {
        self.struct_init_fields(RequestFieldKind::Path)
    }

    pub fn request_query_init_fields(&self) -> Tokens {
        self.struct_init_fields(RequestFieldKind::Query)
    }

    fn struct_init_fields(&self, request_field_kind: RequestFieldKind) -> Tokens {
        let mut tokens = Tokens::new();

        for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) {
            let field_name = field.ident.as_ref().expect("expected body field to have a name");

            tokens.append(quote! {
                #field_name: request.#field_name,
            });
        }

        tokens
    }
}

impl From<Vec<Field>> for Request {
    fn from(fields: Vec<Field>) -> Self {
        let mut has_newtype_body = false;

        let request_fields = fields.into_iter().map(|mut field| {
            let mut request_field_kind = RequestFieldKind::Body;

            field.attrs = field.attrs.into_iter().filter(|attr| {
                let (attr_ident, nested_meta_items) = match attr.value {
                    Meta::List(ref attr_ident, ref nested_meta_items) => (attr_ident, nested_meta_items),
                    _ => return true,
                };

                if attr_ident != "ruma_api" {
                    return true;
                }

                for nested_meta_item in nested_meta_items {
                    match *nested_meta_item {
                        NestedMeta::Meta(ref meta_item) => {
                            match *meta_item {
                                Meta::Word(ref ident) => {
                                    if ident == "body" {
                                        has_newtype_body = true;
                                        request_field_kind = RequestFieldKind::NewtypeBody;
                                    } else if ident == "header" {
                                        request_field_kind = RequestFieldKind::Header;
                                    } else if ident == "path" {
                                        request_field_kind = RequestFieldKind::Path;
                                    } else if ident == "query" {
                                        request_field_kind = RequestFieldKind::Query;
                                    } else {
                                        panic!(
                                            "ruma_api! attribute meta item on requests must be: body, header, path, or query"
                                        );
                                    }
                                }
                                _ => panic!(
                                    "ruma_api! attribute meta item on requests cannot be a list or name/value pair"
                                ),
                            }
                        }
                        NestedMeta::Literal(_) => panic!(
                            "ruma_api! attribute meta item on requests must be: body, header, path, or query"
                        ),
                    }
                }

                false
            }).collect();

            if request_field_kind == RequestFieldKind::Body {
                assert!(
                    !has_newtype_body,
                    "ruma_api! requests cannot have both normal body fields and a newtype body field"
                );
            }

            RequestField::new(request_field_kind, field)
        }).collect();

        Request {
            fields: request_fields,
        }
    }
}

impl ToTokens for Request {
    fn to_tokens(&self, mut tokens: &mut Tokens) {
        tokens.append(quote! {
            /// Data for a request to this API endpoint.
            #[derive(Debug)]
            pub struct Request
        });

        if self.fields.len() == 0 {
            tokens.append(";");
        } else {
            tokens.append("{");

            for request_field in self.fields.iter() {
                strip_serde_attrs(request_field.field()).to_tokens(&mut tokens);

                tokens.append(",");
            }

            tokens.append("}");
        }

        if let Some(newtype_body_field) = self.newtype_body_field() {
            let mut field = newtype_body_field.clone();

            field.ident = None;

            tokens.append(quote! {
                /// Data in the request body.
                #[derive(Debug, Serialize)]
                struct RequestBody
            });

            tokens.append("(");

            field.to_tokens(&mut tokens);

            tokens.append(");");
        } else if self.has_body_fields() {
            tokens.append(quote! {
                /// Data in the request body.
                #[derive(Debug, Serialize)]
                struct RequestBody
            });

            tokens.append("{");

            for request_field in self.fields.iter() {
                match *request_field {
                    RequestField::Body(ref field) => {
                        field.to_tokens(&mut tokens);

                        tokens.append(",");
                    }
                    _ => {}
                }
            }

            tokens.append("}");
        }

        if self.has_path_fields() {
            tokens.append(quote! {
                /// Data in the request path.
                #[derive(Debug, Serialize)]
                struct RequestPath
            });

            tokens.append("{");

            for request_field in self.fields.iter() {
                match *request_field {
                    RequestField::Path(ref field) => {
                        field.to_tokens(&mut tokens);

                        tokens.append(",");
                    }
                    _ => {}
                }
            }

            tokens.append("}");
        }

        if self.has_query_fields() {
            tokens.append(quote! {
                /// Data in the request's query string.
                #[derive(Debug, Serialize)]
                struct RequestQuery
            });

            tokens.append("{");

            for request_field in self.fields.iter() {
                match *request_field {
                    RequestField::Query(ref field) => {
                        field.to_tokens(&mut tokens);

                        tokens.append(",");
                    }
                    _ => {}
                }
            }

            tokens.append("}");
        }
    }
}

#[derive(Debug)]
pub enum RequestField {
    Body(Field),
    Header(Field),
    NewtypeBody(Field),
    Path(Field),
    Query(Field),
}

impl RequestField {
    fn new(kind: RequestFieldKind, field: Field) -> RequestField {
        match kind {
            RequestFieldKind::Body => RequestField::Body(field),
            RequestFieldKind::Header => RequestField::Header(field),
            RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
            RequestFieldKind::Path => RequestField::Path(field),
            RequestFieldKind::Query => RequestField::Query(field),
        }
    }

    fn kind(&self) -> RequestFieldKind {
        match *self {
            RequestField::Body(_) => RequestFieldKind::Body,
            RequestField::Header(_) => RequestFieldKind::Header,
            RequestField::NewtypeBody(_) => RequestFieldKind::NewtypeBody,
            RequestField::Path(_) => RequestFieldKind::Path,
            RequestField::Query(_) => RequestFieldKind::Query,
        }
    }

    fn is_body(&self) -> bool {
        self.kind() == RequestFieldKind::Body
    }

    fn is_path(&self) -> bool {
        self.kind() == RequestFieldKind::Path
    }

    fn is_query(&self) -> bool {
        self.kind() == RequestFieldKind::Query
    }

    fn field(&self) -> &Field {
        match *self {
            RequestField::Body(ref field) => field,
            RequestField::Header(ref field) => field,
            RequestField::NewtypeBody(ref field) => field,
            RequestField::Path(ref field) => field,
            RequestField::Query(ref field) => field,
        }
    }

    fn field_(&self, kind: RequestFieldKind) -> Option<&Field> {
        if self.kind() == kind {
            Some(self.field())
        } else {
            None
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum RequestFieldKind {
    Body,
    Header,
    NewtypeBody,
    Path,
    Query,
}
<commit_msg>ExprStruct --> Request<commit_after>use quote::{ToTokens, Tokens};
use syn::synom::Synom;
use syn::{ExprStruct, Field, FieldValue, FieldsNamed, Meta, NestedMeta};

use api::strip_serde_attrs;

pub struct Request {
    fields: Vec<RequestField>,
}

impl Request {
    pub fn has_body_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_body())
    }

    pub fn has_path_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_path())
    }

    pub fn has_query_fields(&self) -> bool {
        self.fields.iter().any(|field| field.is_query())
    }

    pub fn path_field_count(&self) -> usize {
        self.fields.iter().filter(|field| field.is_path()).count()
    }

    pub fn newtype_body_field(&self) -> Option<&FieldValue> {
        for request_field in self.fields.iter() {
            match *request_field {
                RequestField::NewtypeBody(ref field) => {
                    return Some(field);
                }
                _ => continue,
            }
        }

        None
    }

    pub fn request_body_init_fields(&self) -> Tokens {
        self.struct_init_fields(RequestFieldKind::Body)
    }

    pub fn request_path_init_fields(&self) -> Tokens {
        self.struct_init_fields(RequestFieldKind::Path)
    }

    pub fn request_query_init_fields(&self) -> Tokens {
        self.struct_init_fields(RequestFieldKind::Query)
    }

    fn struct_init_fields(&self, request_field_kind: RequestFieldKind) -> Tokens {
        let mut tokens = Tokens::new();

        for field in self.fields.iter().flat_map(|f| f.field_(request_field_kind)) {
            let field_name = field.ident.as_ref().expect("expected body field to have a name");

            tokens.append(quote! {
                #field_name: request.#field_name,
            });
        }

        tokens
    }
}

impl From<ExprStruct> for Request {
    fn from(expr: ExprStruct) -> Self {
        let mut has_newtype_body = false;

        let fields = expr.fields.into_iter().map(|mut field_value| {
            let mut field_kind = RequestFieldKind::Body;

            field_value.attrs = field_value.attrs.into_iter().filter(|attr| {
                let meta = attr.interpret_meta()
                    .expect("ruma_api! could not parse request field attributes");

                let Meta::List(meta_list) = meta;

                if meta_list.ident.as_ref() != "ruma_api" {
                    return true;
                }

                for nested_meta_item in meta_list.nested {
                    match nested_meta_item {
                        NestedMeta::Meta(meta_item) => {
                            match meta_item {
                                Meta::Word(ident) => {
                                    match ident.as_ref() {
                                    "body" => {
                                        has_newtype_body = true;
                                        field_kind = RequestFieldKind::NewtypeBody;
                                    }
                                    "header" => field_kind = RequestFieldKind::Header,
                                    "path" => field_kind = RequestFieldKind::Path,
                                    "query" => field_kind = RequestFieldKind::Query,
                                    _ => panic!(
                                            "ruma_api! attribute meta item on requests must be: body, header, path, or query"
                                        ),
                                    }
                                }
                                _ => panic!(
                                    "ruma_api! attribute meta item on requests cannot be a list or name/value pair"
                                ),
                            }
                        }
                        NestedMeta::Literal(_) => panic!(
                            "ruma_api! attribute meta item on requests must be: body, header, path, or query"
                        ),
                    }
                }

                false
            }).collect();

            if field_kind == RequestFieldKind::Body {
                assert!(
                    !has_newtype_body,
                    "ruma_api! requests cannot have both normal body fields and a newtype body field"
                );
            }

            RequestField::new(field_kind, field_value)
        }).collect();

        Request {
            fields,
        }
    }
}

impl ToTokens for Request {
    fn to_tokens(&self, mut tokens: &mut Tokens) {
        tokens.append(quote! {
            /// Data for a request to this API endpoint.
            #[derive(Debug)]
            pub struct Request
        });

        if self.fields.len() == 0 {
            tokens.append(";");
        } else {
            tokens.append("{");

            for request_field in self.fields.iter() {
                strip_serde_attrs(request_field.field()).to_tokens(&mut tokens);

                tokens.append(",");
            }

            tokens.append("}");
        }

        if let Some(newtype_body_field) = self.newtype_body_field() {
            let mut field = newtype_body_field.clone();

            field.ident = None;

            tokens.append(quote! {
                /// Data in the request body.
                #[derive(Debug, Serialize)]
                struct RequestBody
            });

            tokens.append("(");

            field.to_tokens(&mut tokens);

            tokens.append(");");
        } else if self.has_body_fields() {
            tokens.append(quote! {
                /// Data in the request body.
                #[derive(Debug, Serialize)]
                struct RequestBody
            });

            tokens.append("{");

            for request_field in self.fields.iter() {
                match *request_field {
                    RequestField::Body(ref field) => {
                        field.to_tokens(&mut tokens);

                        tokens.append(",");
                    }
                    _ => {}
                }
            }

            tokens.append("}");
        }

        if self.has_path_fields() {
            tokens.append(quote! {
                /// Data in the request path.
                #[derive(Debug, Serialize)]
                struct RequestPath
            });

            tokens.append("{");

            for request_field in self.fields.iter() {
                match *request_field {
                    RequestField::Path(ref field) => {
                        field.to_tokens(&mut tokens);

                        tokens.append(",");
                    }
                    _ => {}
                }
            }

            tokens.append("}");
        }

        if self.has_query_fields() {
            tokens.append(quote! {
                /// Data in the request's query string.
                #[derive(Debug, Serialize)]
                struct RequestQuery
            });

            tokens.append("{");

            for request_field in self.fields.iter() {
                match *request_field {
                    RequestField::Query(ref field) => {
                        field.to_tokens(&mut tokens);

                        tokens.append(",");
                    }
                    _ => {}
                }
            }

            tokens.append("}");
        }
    }
}

pub enum RequestField {
    Body(FieldValue),
    Header(FieldValue),
    NewtypeBody(FieldValue),
    Path(FieldValue),
    Query(FieldValue),
}

impl RequestField {
    fn new(kind: RequestFieldKind, field: FieldValue) -> RequestField {
        match kind {
            RequestFieldKind::Body => RequestField::Body(field),
            RequestFieldKind::Header => RequestField::Header(field),
            RequestFieldKind::NewtypeBody => RequestField::NewtypeBody(field),
            RequestFieldKind::Path => RequestField::Path(field),
            RequestFieldKind::Query => RequestField::Query(field),
        }
    }

    fn kind(&self) -> RequestFieldKind {
        match *self {
            RequestField::Body(_) => RequestFieldKind::Body,
            RequestField::Header(_) => RequestFieldKind::Header,
            RequestField::NewtypeBody(_) => RequestFieldKind::NewtypeBody,
            RequestField::Path(_) => RequestFieldKind::Path,
            RequestField::Query(_) => RequestFieldKind::Query,
        }
    }

    fn is_body(&self) -> bool {
        self.kind() == RequestFieldKind::Body
    }

    fn is_path(&self) -> bool {
        self.kind() == RequestFieldKind::Path
    }

    fn is_query(&self) -> bool {
        self.kind() == RequestFieldKind::Query
    }

    fn field(&self) -> &FieldValue {
        match *self {
            RequestField::Body(ref field) => field,
            RequestField::Header(ref field) => field,
            RequestField::NewtypeBody(ref field) => field,
            RequestField::Path(ref field) => field,
            RequestField::Query(ref field) => field,
        }
    }

    fn field_(&self, kind: RequestFieldKind) -> Option<&FieldValue> {
        if self.kind() == kind {
            Some(self.field())
        } else {
            None
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
enum RequestFieldKind {
    Body,
    Header,
    NewtypeBody,
    Path,
    Query,
}
<|endoftext|>


<commit_before><commit_msg>Added a generic handle implementation.<commit_after>//! The generic implementation of a "handle" proxy object used throughout wlroots-rs.

use std::{clone::Clone, cell::Cell, fmt, rc::Weak, hash::{Hash, Hasher}, ptr,
          panic, marker::PhantomData};

use errors::{HandleErr, HandleResult};

/// A non-owned reference counted handle to a resource.
///
/// The resource could be destroyed at any time, it depends on the resource.
///
/// For example an output is destroyed when it's physical output is "disconnected"
/// on DRM. "disconnected" depends on the output (e.g. sometimes turning it off counts
/// as "disconnected").
/// However, when the backend is instead headless an output lives until it is
/// destroyed explicitly by the library user.
///
/// Some resources are completely controlled by the user. For example although
/// you refer to a `Seat` with handles it is only destroyed when you call the
/// special destroy method on the seat handle.
///
/// Please refer to the specific resource documentation for a description of
/// the lifetime particular to that resource.
pub struct Handle<D, T, W: Handleable<D, T> + Sized> {
    pub(crate) ptr: *mut T,
    pub(crate) handle: Weak<Cell<bool>>,
    pub(crate) _marker: PhantomData<W>,
    pub(crate) data: D
}

pub trait Handleable<D, T> {
    /// Constructs the resource manager from a raw pointer of the resource
    /// this handleable manages. **This should increment the reference count**.
    ///
    /// # Safety
    /// The pointer must be valid and must already have been set up by wlroots-rs
    /// internal mechanisms. If you have to ask, it probably isn't.
    #[doc(hidden)]
    unsafe fn from_ptr(resource_ptr: *mut T) -> Self where Self: Sized;

    /// Gets the pointer to the resource this object manages.
    #[doc(hidden)]
    unsafe fn as_ptr(&self) -> *mut T;

    /// Creates a weak reference to the resource.
    fn weak_reference(&self) -> Handle<D, T, Self> where Self: Sized;

    /// Gets the resource from the handle.
    ///
    /// This is used internally to upgrade a handle, and should not be used.
    /// Thus the documentation is hidden and it's marked `unsafe`.
    ///
    /// If you _need_ to use this, use `Handle::upgrade` instead.
    #[doc(hidden)]
    unsafe fn from_handle(&Handle<D, T, Self>) -> HandleResult<Self>
        where Self: Sized;
}

impl <D: Clone, T, W: Handleable<D, T>> Clone for Handle<D, T, W> {
    fn clone(&self) -> Self {
        Handle { ptr: self.ptr,
                 handle: self.handle.clone(),
                 _marker: PhantomData,
                 data: self.data.clone()
        }
    }
}

impl <D, T, W: Handleable<D, T>> fmt::Debug for Handle<D, T, W> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Handle with pointer: {:p}", self.ptr)
    }
}

impl <D, T, W: Handleable<D, T>> Hash for Handle<D, T, W> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.ptr.hash(state);
    }
}

impl <D, T, W: Handleable<D, T>> PartialEq for Handle<D, T, W> {
    fn eq(&self, other: &Handle<D, T, W>) -> bool {
        self.ptr == other.ptr
    }
}

impl <D, T, W: Handleable<D, T>> Eq for Handle<D, T, W> {}

impl <D: Default, T, W: Handleable<D, T>> Default for Handle<D, T, W> {
    /// Constructs a new handle that is always invalid. Calling `run` on this
    /// will always fail.
    ///
    /// This is useful for pre-filling a value before it's provided by the server, or
    /// for mocking/testing.
    fn default() -> Self {
        Handle { ptr: ptr::null_mut(),
                 handle: Weak::new(),
                 _marker: PhantomData,
                 data: D::default() }
    }
}

impl <D, T, W: Handleable<D, T>> Handle<D, T, W> {
    /// Creates an output::Handle from the raw pointer, using the saved
    /// user data to recreate the memory model.
    ///
    /// # Panics
    /// This function is allowed to panic when attempting to upgrade the handle.
    pub(crate) unsafe fn from_ptr(ptr: *mut T) -> Handle<D, T, W> {
        let wrapped_resource = W::from_ptr(ptr);
        wrapped_resource.weak_reference()
    }

    /// Get the pointer to the resource this manages.
    ///
    /// # Safety
    /// There's no guarantees that this pointer is not dangling.
    #[doc(hidden)]
    pub unsafe fn as_ptr(&self) -> *mut T {
        self.ptr
    }

    /// Run a function with a reference to the resource if it's still alive.
    ///
    /// Returns the result of the function, if successful.
    ///
    /// # Safety
    /// By enforcing a rather harsh limit on the lifetime of the resource
    /// to a short lived scope of an anonymous function,
    /// this function ensures the resource does not live longer
    /// than it exists.
    ///
    /// # Panics
    /// This function will panic if multiple mutable borrows are detected.
    /// This will happen if you call `upgrade` directly within this callback,
    /// or if a handle to the same resource was upgraded some where else up the stack.
    pub fn run<F, R>(&self, runner: F) -> HandleResult<R>
        where F: FnOnce(&mut W) -> R
    {
        let mut wrapped_obj = unsafe { self.upgrade()? };
        // We catch panics here to deal with an extreme edge case.
        //
        // If the library user catches panics from the `run` function then their
        // resource used flag will still be set to `true` when it should be set
        // to `false`.
        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| runner(&mut wrapped_obj)));
        self.handle.upgrade().map(|check| {
            // Sanity check that it hasn't been tampered with. If so, we should just panic.
            // If we are currently panicking this will abort.
            if !check.get() {
                wlr_log!(WLR_ERROR, "After running callback, mutable lock was false");
                panic!("Lock in incorrect state!");
            }
            check.set(false);
        });
        match res {
            Ok(res) => Ok(res),
            Err(err) => panic::resume_unwind(err)
        }
    }

    /// Upgrades a handle to a reference to the backing object.
    ///
    /// # Safety
    /// This returns an "owned" value when really you don't own it all.
    /// Depending on the type, it's possible that the resource will be freed
    /// once this returned value is dropped, causing a possible double free.
    /// Potentially it instead is just unbound, it depends on the resource.
    ///
    /// Regardless, you should not use this interface. Use the `run` method.
    #[doc(hidden)]
    pub unsafe fn upgrade(&self) -> HandleResult<W> {
        self.handle.upgrade()
            .ok_or(HandleErr::AlreadyDropped)
            // NOTE
            // We drop the Rc here because having two would allow a dangling
            // pointer to exist!
            .and_then(|check| {
                let wrapper_obj = W::from_handle(self)?;
                if check.get() {
                    return Err(HandleErr::AlreadyDropped)
                }
                check.set(true);
                Ok(wrapper_obj)
            })

    }
}
<|endoftext|>


<commit_before><commit_msg>Add variables structures<commit_after>pub trait LpElement {
    fn new(name: &str) -> Self;
    fn lower_bound(&self, up: i32) -> Self;
    fn upper_bound(&self, lw: i32) -> Self;
}

pub enum LpVariable {
    BinaryVariable,
    IntegerVariable,
    ContinuousVariable
}

#[derive(Debug)]
pub struct BinaryVariable {
    name: String,
}

#[derive(Debug)]
pub struct IntegerVariable {
    name: String,
    lower_bound: Option<i32>,
    upper_bound: Option<i32>,
}

#[derive(Debug)]
pub struct ContinuousVariable {
    name: String,
    lower_bound: Option<i32>,
    upper_bound: Option<i32>,
}

impl LpElement for BinaryVariable {
    fn new(name: &str) -> Self {
        BinaryVariable { name: name.to_string() }
    }
    fn lower_bound(&self, _lw: i32) -> Self {
        BinaryVariable { name: self.name.clone() }
    }
    fn upper_bound(&self, _up: i32) -> Self {
        BinaryVariable { name: self.name.clone() }
    }
}

impl LpElement for IntegerVariable {
    fn new(name: &str) -> Self {
        IntegerVariable { name: name.to_string(), lower_bound: None, upper_bound: None }
    }
    fn lower_bound(&self, lw: i32) -> Self {
        IntegerVariable { name: self.name.clone(), lower_bound: Some(lw), upper_bound: self.upper_bound}
    }
    fn upper_bound(&self, up: i32) -> Self {
        IntegerVariable { name: self.name.clone(), lower_bound: self.lower_bound, upper_bound: Some(up)}
    }
}

impl LpElement for ContinuousVariable {
    fn new(name: &str) -> Self {
        ContinuousVariable { name: name.to_string(), lower_bound: None, upper_bound: None}
    }
    fn lower_bound(&self, lw: i32) -> Self {
        ContinuousVariable { name: self.name.clone(), lower_bound: Some(lw), upper_bound: self.upper_bound}
    }
    fn upper_bound(&self, up: i32) -> Self {
        ContinuousVariable { name: self.name.clone(), lower_bound: self.lower_bound, upper_bound: Some(up)}
    }
}

<|endoftext|>


<commit_before><commit_msg>Add a string token<commit_after><|endoftext|>


<commit_before><commit_msg>Make processing a single message.<commit_after><|endoftext|>


<commit_before>use super::{Error, Result, raw};
use std;

/// Handle to an ODBC Environment
///
/// Creating an instance of this type is the first thing you do then using ODBC. The environment
/// must outlive all connections created with it
pub struct Environment {
    handle: raw::SQLHENV,
}

/// Struct holding information available on a driver.
///
/// Can be obtained via `Environment::drivers`
#[derive(Clone, Debug)]
pub struct DriverInfo {
    desc: String,
    attributes: String,
}

impl DriverInfo {
    pub fn description(&self) -> &str {
        self.desc.as_str()
    }
}

impl Environment {
    /// Allocates a new ODBC Environment
    ///
    /// Declares the Application's ODBC Version to be 3
    pub fn new() -> Result<Environment> {
        unsafe {
            let mut env = std::ptr::null_mut();
            let mut result =
                match raw::SQLAllocHandle(raw::SQL_HANDLE_ENV, std::ptr::null_mut(), &mut env) {
                    raw::SQL_SUCCESS => Environment { handle: env },
                    raw::SQL_SUCCESS_WITH_INFO => Environment { handle: env },
                    // Driver Manager failed to allocate environment
                    raw::SQL_ERROR => return Err(Error {}),
                    _ => unreachable!(),
                };
            // no leak if we return an error here, env handle is already wrapped and would be
            // dropped
            result.set_attribute(raw::SQL_ATTR_ODBC_VERSION,
                               raw::SQL_OV_ODBC3 as *mut std::os::raw::c_void,
                               0)?;

            Ok(result)
        }
    }

    /// Stores all driver description and attributes in a Vec
    pub fn drivers(&self) -> Result<Vec<DriverInfo>> {
        // Iterate twice, once for reading the maximum required buffer lengths so we can read
        // everything without truncating and a second time for actually storing the values
        let string_buf = std::ptr::null_mut();
        let mut desc_length_out: raw::SQLSMALLINT = 0;
        let mut attr_length_out: raw::SQLSMALLINT = 0;
        let mut max_desc = 0;
        let mut max_attr = 0;
        let mut count = 0;
        let mut result;
        unsafe {
            // although the rather lengthy function call kind of blows the call, let's do the first
            // one using SQL_FETCH_FIRST, so we list all drivers independent from environment state
            result = raw::SQLDrivers(self.handle,
                                     raw::SQL_FETCH_FIRST,
                                     string_buf,
                                     0,
                                     &mut desc_length_out as *mut raw::SQLSMALLINT,
                                     string_buf,
                                     0,
                                     &mut attr_length_out as *mut raw::SQLSMALLINT);
        }
        loop {
            match result {
                raw::SQL_SUCCESS |
                raw::SQL_SUCCESS_WITH_INFO => {
                    count += 1;
                    max_desc = std::cmp::max(max_desc, desc_length_out);
                    max_attr = std::cmp::max(max_attr, attr_length_out);
                }
                raw::SQL_NO_DATA => break,
                raw::SQL_ERROR => return Err(Error {}),
                _ => unreachable!(),
            }
            unsafe {
                result = raw::SQLDrivers(self.handle,
                                         raw::SQL_FETCH_NEXT,
                                         string_buf,
                                         0,
                                         &mut desc_length_out as *mut raw::SQLSMALLINT,
                                         string_buf,
                                         0,
                                         &mut attr_length_out as *mut raw::SQLSMALLINT);
            }
        }

        let mut driver_list = Vec::with_capacity(count);
        loop {
            let mut description_buffer: Vec<_> = (0..(max_desc + 1)).map(|_| 0u8).collect();
            let mut attribute_buffer: Vec<_> = (0..(max_attr + 1)).map(|_| 0u8).collect();
            unsafe {
                result = raw::SQLDrivers(self.handle,
                                         // Its ok to use fetch next here, since we know
                                         // last state has been SQL_NO_DATA
                                         raw::SQL_FETCH_NEXT,
                                         &mut description_buffer[0] as *mut u8,
                                         max_desc + 1,
                                         &mut desc_length_out as *mut raw::SQLSMALLINT,
                                         &mut attribute_buffer[0] as *mut u8,
                                         max_attr + 1,
                                         &mut attr_length_out as *mut raw::SQLSMALLINT);
            }
            match result {
                raw::SQL_SUCCESS |
                raw::SQL_SUCCESS_WITH_INFO => {
                    description_buffer.resize(desc_length_out as usize, 0);
                    driver_list.push(DriverInfo {
                        desc: String::from_utf8(description_buffer).unwrap(),
                        attributes: String::from_utf8(attribute_buffer).unwrap(),
                    })
                }
                raw::SQL_ERROR => return Err(Error {}),
                raw::SQL_NO_DATA => break,
                _ => unreachable!(),
            }
        }
        Ok(driver_list)
    }

    /// Allows access to the raw ODBC handle
    pub unsafe fn raw(&mut self) -> raw::SQLHENV {
        self.handle
    }

    /// Allows setting attributes to Environment
    pub unsafe fn set_attribute(&mut self,
                                attribute: raw::SQLINTEGER,
                                value: raw::SQLPOINTER,
                                length: raw::SQLINTEGER)
                                -> Result<()> {
        match raw::SQLSetEnvAttr(self.handle, attribute, value, length) {
            raw::SQL_SUCCESS => Ok(()),
            raw::SQL_SUCCESS_WITH_INFO => Ok(()),
            _ => Err(Error {}),
        }
    }
}

impl Drop for Environment {
    fn drop(&mut self) {
        unsafe {
            raw::SQLFreeEnv(self.handle);
        }
    }
}<commit_msg>driver description now returns string reference<commit_after>use super::{Error, Result, raw};
use std;

/// Handle to an ODBC Environment
///
/// Creating an instance of this type is the first thing you do then using ODBC. The environment
/// must outlive all connections created with it
pub struct Environment {
    handle: raw::SQLHENV,
}

/// Struct holding information available on a driver.
///
/// Can be obtained via `Environment::drivers`
#[derive(Clone, Debug)]
pub struct DriverInfo {
    desc: String,
    attributes: String,
}

impl DriverInfo {
    pub fn description(&self) -> &String {
        &self.desc
    }
}

impl Environment {
    /// Allocates a new ODBC Environment
    ///
    /// Declares the Application's ODBC Version to be 3
    pub fn new() -> Result<Environment> {
        unsafe {
            let mut env = std::ptr::null_mut();
            let mut result =
                match raw::SQLAllocHandle(raw::SQL_HANDLE_ENV, std::ptr::null_mut(), &mut env) {
                    raw::SQL_SUCCESS => Environment { handle: env },
                    raw::SQL_SUCCESS_WITH_INFO => Environment { handle: env },
                    // Driver Manager failed to allocate environment
                    raw::SQL_ERROR => return Err(Error {}),
                    _ => unreachable!(),
                };
            // no leak if we return an error here, env handle is already wrapped and would be
            // dropped
            result.set_attribute(raw::SQL_ATTR_ODBC_VERSION,
                               raw::SQL_OV_ODBC3 as *mut std::os::raw::c_void,
                               0)?;

            Ok(result)
        }
    }

    /// Stores all driver description and attributes in a Vec
    pub fn drivers(&self) -> Result<Vec<DriverInfo>> {
        // Iterate twice, once for reading the maximum required buffer lengths so we can read
        // everything without truncating and a second time for actually storing the values
        let string_buf = std::ptr::null_mut();
        let mut desc_length_out: raw::SQLSMALLINT = 0;
        let mut attr_length_out: raw::SQLSMALLINT = 0;
        let mut max_desc = 0;
        let mut max_attr = 0;
        let mut count = 0;
        let mut result;
        unsafe {
            // although the rather lengthy function call kind of blows the call, let's do the first
            // one using SQL_FETCH_FIRST, so we list all drivers independent from environment state
            result = raw::SQLDrivers(self.handle,
                                     raw::SQL_FETCH_FIRST,
                                     string_buf,
                                     0,
                                     &mut desc_length_out as *mut raw::SQLSMALLINT,
                                     string_buf,
                                     0,
                                     &mut attr_length_out as *mut raw::SQLSMALLINT);
        }
        loop {
            match result {
                raw::SQL_SUCCESS |
                raw::SQL_SUCCESS_WITH_INFO => {
                    count += 1;
                    max_desc = std::cmp::max(max_desc, desc_length_out);
                    max_attr = std::cmp::max(max_attr, attr_length_out);
                }
                raw::SQL_NO_DATA => break,
                raw::SQL_ERROR => return Err(Error {}),
                _ => unreachable!(),
            }
            unsafe {
                result = raw::SQLDrivers(self.handle,
                                         raw::SQL_FETCH_NEXT,
                                         string_buf,
                                         0,
                                         &mut desc_length_out as *mut raw::SQLSMALLINT,
                                         string_buf,
                                         0,
                                         &mut attr_length_out as *mut raw::SQLSMALLINT);
            }
        }

        let mut driver_list = Vec::with_capacity(count);
        loop {
            let mut description_buffer: Vec<_> = (0..(max_desc + 1)).map(|_| 0u8).collect();
            let mut attribute_buffer: Vec<_> = (0..(max_attr + 1)).map(|_| 0u8).collect();
            unsafe {
                result = raw::SQLDrivers(self.handle,
                                         // Its ok to use fetch next here, since we know
                                         // last state has been SQL_NO_DATA
                                         raw::SQL_FETCH_NEXT,
                                         &mut description_buffer[0] as *mut u8,
                                         max_desc + 1,
                                         &mut desc_length_out as *mut raw::SQLSMALLINT,
                                         &mut attribute_buffer[0] as *mut u8,
                                         max_attr + 1,
                                         &mut attr_length_out as *mut raw::SQLSMALLINT);
            }
            match result {
                raw::SQL_SUCCESS |
                raw::SQL_SUCCESS_WITH_INFO => {
                    description_buffer.resize(desc_length_out as usize, 0);
                    driver_list.push(DriverInfo {
                        desc: String::from_utf8(description_buffer).unwrap(),
                        attributes: String::from_utf8(attribute_buffer).unwrap(),
                    })
                }
                raw::SQL_ERROR => return Err(Error {}),
                raw::SQL_NO_DATA => break,
                _ => unreachable!(),
            }
        }
        Ok(driver_list)
    }

    /// Allows access to the raw ODBC handle
    pub unsafe fn raw(&mut self) -> raw::SQLHENV {
        self.handle
    }

    /// Allows setting attributes to Environment
    pub unsafe fn set_attribute(&mut self,
                                attribute: raw::SQLINTEGER,
                                value: raw::SQLPOINTER,
                                length: raw::SQLINTEGER)
                                -> Result<()> {
        match raw::SQLSetEnvAttr(self.handle, attribute, value, length) {
            raw::SQL_SUCCESS => Ok(()),
            raw::SQL_SUCCESS_WITH_INFO => Ok(()),
            _ => Err(Error {}),
        }
    }
}

impl Drop for Environment {
    fn drop(&mut self) {
        unsafe {
            raw::SQLFreeEnv(self.handle);
        }
    }
}<|endoftext|>


<commit_before><commit_msg>Added ergonomic interface to the query<commit_after><|endoftext|>


<commit_before><commit_msg>Started implementation of neighbor calculation function<commit_after><|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(gl)] pub use self::gl::Device;
#[cfg(gl)] pub use dev = self::gl;
// #[cfg(d3d11)] ... // TODO

use std::comm;
use std::comm::DuplexStream;
use std::kinds::marker;

use GraphicsContext;

pub mod shade;
#[cfg(gl)] mod gl;

pub type Color = [f32, ..4];
pub type VertexCount = u16;
pub type IndexCount = u16;

pub enum Request {
    // Requests that require a reply:
    CallNewVertexBuffer(Vec<f32>),
    CallNewIndexBuffer(Vec<u16>),
    CallNewArrayBuffer,
    CallNewShader(shade::Stage, Vec<u8>),
    CallNewProgram(Vec<dev::Shader>),
    // Requests that don't expect a reply:
    CastClear(Color),
    CastBindProgram(dev::Program),
    CastBindArrayBuffer(dev::ArrayBuffer),
    CastBindAttribute(u8, dev::Buffer, u32, u32, u32),
    CastBindIndex(dev::Buffer),
    CastBindFrameBuffer(dev::FrameBuffer),
    CastDraw(VertexCount, VertexCount),
    CastDrawIndexed(IndexCount, IndexCount),
    CastSwapBuffers,
}

pub enum Reply {
    ReplyNewBuffer(dev::Buffer),
    ReplyNewArrayBuffer(dev::ArrayBuffer),
    ReplyNewShader(Result<dev::Shader, ()>),
    ReplyNewProgram(Result<shade::ProgramMeta, ()>),
}

pub struct Client {
    stream: DuplexStream<Request, Reply>,
}

impl Client {
    pub fn clear(&self, color: Color) {
        self.stream.send(CastClear(color));
    }

    pub fn bind_program(&self, prog: dev::Program) {
        self.stream.send(CastBindProgram(prog));
    }

    pub fn bind_array_buffer(&self, abuf: dev::ArrayBuffer) {
        self.stream.send(CastBindArrayBuffer(abuf));
    }

    pub fn bind_attribute(&self, index: u8, buf: dev::Buffer, count: u32, offset: u32, stride: u32) {
        self.stream.send(CastBindAttribute(index, buf, count, offset, stride));
    }

    pub fn bind_index(&self, buf: dev::Buffer) {
        self.stream.send(CastBindIndex(buf));
    }

    pub fn bind_frame_buffer(&self, fbo: dev::FrameBuffer) {
        self.stream.send(CastBindFrameBuffer(fbo));
    }

    pub fn draw(&self, offset: VertexCount, count: VertexCount) {
        self.stream.send(CastDraw(offset, count));
    }

    pub fn draw_indexed(&self, offset: IndexCount, count: IndexCount) {
        self.stream.send(CastDrawIndexed(offset, count));
    }

    pub fn end_frame(&self) {
        self.stream.send(CastSwapBuffers);
    }

    pub fn new_shader(&self, stage: shade::Stage, code: Vec<u8>) -> Result<dev::Shader, ()> {
        self.stream.send(CallNewShader(stage, code));
        match self.stream.recv() {
            ReplyNewShader(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_program(&self, shaders: Vec<dev::Shader>) -> Result<shade::ProgramMeta, ()> {
        self.stream.send(CallNewProgram(shaders));
        match self.stream.recv() {
            ReplyNewProgram(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_vertex_buffer(&self, data: Vec<f32>) -> dev::Buffer {
        self.stream.send(CallNewVertexBuffer(data));
        match self.stream.recv() {
            ReplyNewBuffer(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_index_buffer(&self, data: Vec<u16>) -> dev::Buffer {
        self.stream.send(CallNewIndexBuffer(data));
        match self.stream.recv() {
            ReplyNewBuffer(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_array_buffer(&self) -> dev::ArrayBuffer {
        self.stream.send(CallNewArrayBuffer);
        match self.stream.recv() {
            ReplyNewArrayBuffer(name) => name,
            _ => fail!("unexpected device reply")
        }
    }
}

pub struct Server<P> {
    no_share: marker::NoShare,
    stream: DuplexStream<Reply, Request>,
    graphics_context: P,
    device: Device,
}

impl<Api, P: GraphicsContext<Api>> Server<P> {
    pub fn make_current(&self) {
        self.graphics_context.make_current();
    }

    /// Update the platform. The client must manually update this on the main
    /// thread.
    pub fn update(&mut self) -> bool {
        // Get updates from the renderer and pass on results
        loop {
            match self.stream.try_recv() {
                Ok(CastClear(color)) => {
                    self.device.clear(color.as_slice());
                },
                Ok(CastBindProgram(prog)) => {
                    self.device.bind_program(prog);
                },
                Ok(CastBindArrayBuffer(abuf)) => {
                    self.device.bind_array_buffer(abuf);
                },
                Ok(CastBindAttribute(index, buf, count, offset, stride)) => {
                    self.device.bind_vertex_buffer(buf);
                    self.device.bind_attribute(index, count as u32, offset, stride);
                },
                Ok(CastBindIndex(buf)) => {
                    self.device.bind_index_buffer(buf);
                },
                Ok(CastBindFrameBuffer(fbo)) => {
                    self.device.bind_frame_buffer(fbo);
                },
                Ok(CastDraw(offset, count)) => {
                    self.device.draw(offset as u32, count as u32);
                },
                Ok(CastDrawIndexed(offset, count)) => {
                    self.device.draw_index(offset, count);
                },
                Ok(CastSwapBuffers) => {
                    break;
                },
                Ok(CallNewVertexBuffer(data)) => {
                    let name = self.device.create_buffer(data.as_slice());
                    self.stream.send(ReplyNewBuffer(name));
                },
                Ok(CallNewIndexBuffer(data)) => {
                    let name = self.device.create_buffer(data.as_slice());
                    self.stream.send(ReplyNewBuffer(name));
                },
                Ok(CallNewArrayBuffer) => {
                    let name = self.device.create_array_buffer();
                    self.stream.send(ReplyNewArrayBuffer(name));
                },
                Ok(CallNewShader(stage, code)) => {
                    let name = self.device.create_shader(stage, code.as_slice());
                    self.stream.send(ReplyNewShader(name));
                },
                Ok(CallNewProgram(code)) => {
                    let name = self.device.create_program(code.as_slice());
                    self.stream.send(ReplyNewProgram(name));
                },
                Err(comm::Empty) => break,
                Err(comm::Disconnected) => return false,
            }
        }
        self.graphics_context.swap_buffers();
        true
    }
}

#[deriving(Show)]
pub enum InitError {}

pub fn init<Api, P: GraphicsContext<Api>>(graphics_context: P, options: super::Options)
        -> Result<(Client, Server<P>), InitError> {
    let (client_stream, server_stream) = comm::duplex();

    let client = Client {
        stream: client_stream,
    };
    let dev = Device::new(options);
    let server = Server {
        no_share: marker::NoShare,
        stream: server_stream,
        graphics_context: graphics_context,
        device: dev,
    };

    Ok((client, server))
}
<commit_msg>swap buffer only on CastSwapBuffers<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[cfg(gl)] pub use self::gl::Device;
#[cfg(gl)] pub use dev = self::gl;
// #[cfg(d3d11)] ... // TODO

use std::comm;
use std::comm::DuplexStream;
use std::kinds::marker;

use GraphicsContext;

pub mod shade;
#[cfg(gl)] mod gl;

pub type Color = [f32, ..4];
pub type VertexCount = u16;
pub type IndexCount = u16;

pub enum Request {
    // Requests that require a reply:
    CallNewVertexBuffer(Vec<f32>),
    CallNewIndexBuffer(Vec<u16>),
    CallNewArrayBuffer,
    CallNewShader(shade::Stage, Vec<u8>),
    CallNewProgram(Vec<dev::Shader>),
    // Requests that don't expect a reply:
    CastClear(Color),
    CastBindProgram(dev::Program),
    CastBindArrayBuffer(dev::ArrayBuffer),
    CastBindAttribute(u8, dev::Buffer, u32, u32, u32),
    CastBindIndex(dev::Buffer),
    CastBindFrameBuffer(dev::FrameBuffer),
    CastDraw(VertexCount, VertexCount),
    CastDrawIndexed(IndexCount, IndexCount),
    CastSwapBuffers,
}

pub enum Reply {
    ReplyNewBuffer(dev::Buffer),
    ReplyNewArrayBuffer(dev::ArrayBuffer),
    ReplyNewShader(Result<dev::Shader, ()>),
    ReplyNewProgram(Result<shade::ProgramMeta, ()>),
}

pub struct Client {
    stream: DuplexStream<Request, Reply>,
}

impl Client {
    pub fn clear(&self, color: Color) {
        self.stream.send(CastClear(color));
    }

    pub fn bind_program(&self, prog: dev::Program) {
        self.stream.send(CastBindProgram(prog));
    }

    pub fn bind_array_buffer(&self, abuf: dev::ArrayBuffer) {
        self.stream.send(CastBindArrayBuffer(abuf));
    }

    pub fn bind_attribute(&self, index: u8, buf: dev::Buffer, count: u32, offset: u32, stride: u32) {
        self.stream.send(CastBindAttribute(index, buf, count, offset, stride));
    }

    pub fn bind_index(&self, buf: dev::Buffer) {
        self.stream.send(CastBindIndex(buf));
    }

    pub fn bind_frame_buffer(&self, fbo: dev::FrameBuffer) {
        self.stream.send(CastBindFrameBuffer(fbo));
    }

    pub fn draw(&self, offset: VertexCount, count: VertexCount) {
        self.stream.send(CastDraw(offset, count));
    }

    pub fn draw_indexed(&self, offset: IndexCount, count: IndexCount) {
        self.stream.send(CastDrawIndexed(offset, count));
    }

    pub fn end_frame(&self) {
        self.stream.send(CastSwapBuffers);
    }

    pub fn new_shader(&self, stage: shade::Stage, code: Vec<u8>) -> Result<dev::Shader, ()> {
        self.stream.send(CallNewShader(stage, code));
        match self.stream.recv() {
            ReplyNewShader(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_program(&self, shaders: Vec<dev::Shader>) -> Result<shade::ProgramMeta, ()> {
        self.stream.send(CallNewProgram(shaders));
        match self.stream.recv() {
            ReplyNewProgram(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_vertex_buffer(&self, data: Vec<f32>) -> dev::Buffer {
        self.stream.send(CallNewVertexBuffer(data));
        match self.stream.recv() {
            ReplyNewBuffer(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_index_buffer(&self, data: Vec<u16>) -> dev::Buffer {
        self.stream.send(CallNewIndexBuffer(data));
        match self.stream.recv() {
            ReplyNewBuffer(name) => name,
            _ => fail!("unexpected device reply")
        }
    }

    pub fn new_array_buffer(&self) -> dev::ArrayBuffer {
        self.stream.send(CallNewArrayBuffer);
        match self.stream.recv() {
            ReplyNewArrayBuffer(name) => name,
            _ => fail!("unexpected device reply")
        }
    }
}

pub struct Server<P> {
    no_share: marker::NoShare,
    stream: DuplexStream<Reply, Request>,
    graphics_context: P,
    device: Device,
}

impl<Api, P: GraphicsContext<Api>> Server<P> {
    pub fn make_current(&self) {
        self.graphics_context.make_current();
    }

    /// Update the platform. The client must manually update this on the main
    /// thread.
    pub fn update(&mut self) -> bool {
        // Get updates from the renderer and pass on results
        loop {
            match self.stream.recv_opt() {
                Ok(CastClear(color)) => {
                    self.device.clear(color.as_slice());
                },
                Ok(CastBindProgram(prog)) => {
                    self.device.bind_program(prog);
                },
                Ok(CastBindArrayBuffer(abuf)) => {
                    self.device.bind_array_buffer(abuf);
                },
                Ok(CastBindAttribute(index, buf, count, offset, stride)) => {
                    self.device.bind_vertex_buffer(buf);
                    self.device.bind_attribute(index, count as u32, offset, stride);
                },
                Ok(CastBindIndex(buf)) => {
                    self.device.bind_index_buffer(buf);
                },
                Ok(CastBindFrameBuffer(fbo)) => {
                    self.device.bind_frame_buffer(fbo);
                },
                Ok(CastDraw(offset, count)) => {
                    self.device.draw(offset as u32, count as u32);
                },
                Ok(CastDrawIndexed(offset, count)) => {
                    self.device.draw_index(offset, count);
                },
                Ok(CastSwapBuffers) => {
                    self.graphics_context.swap_buffers();
                    break;
                },
                Ok(CallNewVertexBuffer(data)) => {
                    let name = self.device.create_buffer(data.as_slice());
                    self.stream.send(ReplyNewBuffer(name));
                },
                Ok(CallNewIndexBuffer(data)) => {
                    let name = self.device.create_buffer(data.as_slice());
                    self.stream.send(ReplyNewBuffer(name));
                },
                Ok(CallNewArrayBuffer) => {
                    let name = self.device.create_array_buffer();
                    self.stream.send(ReplyNewArrayBuffer(name));
                },
                Ok(CallNewShader(stage, code)) => {
                    let name = self.device.create_shader(stage, code.as_slice());
                    self.stream.send(ReplyNewShader(name));
                },
                Ok(CallNewProgram(code)) => {
                    let name = self.device.create_program(code.as_slice());
                    self.stream.send(ReplyNewProgram(name));
                },
                Err(()) => return false,
            }
        }
        true
    }
}

#[deriving(Show)]
pub enum InitError {}

pub fn init<Api, P: GraphicsContext<Api>>(graphics_context: P, options: super::Options)
        -> Result<(Client, Server<P>), InitError> {
    let (client_stream, server_stream) = comm::duplex();

    let client = Client {
        stream: client_stream,
    };
    let dev = Device::new(options);
    let server = Server {
        no_share: marker::NoShare,
        stream: server_stream,
        graphics_context: graphics_context,
        device: dev,
    };

    Ok((client, server))
}
<|endoftext|>


<commit_before><commit_msg>A bit of internal refactoring.<commit_after><|endoftext|>


<commit_before><commit_msg>Explain non-obvious percentile math<commit_after><|endoftext|>


<commit_before><commit_msg>stubbing out a code example..<commit_after>// example1.rs
use std;
use std::task::spawn_sched;
use std::comm::oneshot;
use std::option::{Option, Some, None};

struct HotDog {
    sausage: Sausage,
    toppings: Toppings,
    bun: Bun
}
enum Sausage {
    Bratwurst,
    Tofurkey,
    EverythingElse(~str) // i mean, really
}
enum Toppings {
    Sauerkraut,
    Ketchup(bool) // is it Fair Trade?
}
enum Bun {
    SomethingDecadent,
    EwwwCarbs // high in fiber
}
impl HotDog {
    fn new(s: Sausage) -> Option<HotDog> {
        match Sausage {
            Bratwurst => HotDog {
                sausage: BratWurst,
                toppings: Sauerkraut,
                bun: SomethingDecadent
            },
            Tofurkey => HotDog {
                sausage: Tofurkey,
                toppings: Ketchup(true),
                bun: EwwwCarbs
            },
            _ => None // no hotdog for you!
        }
    }
}
fn main() {
    let (port, chan) = oneshot();
    do spawn_sched {
        let brat = HotDog(Bratwurst);
        chan.send(brat);
    }
    // parallel hotdog assembly!
    let ewww_yuck = HotDog(Tofurkey);
    let brat = port.recv();
}<|endoftext|>