<commit_before>use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::io::{File, IoError};
use std::io;
use std::os::args;
use std::str;
use std::io::TempDir;
use term::color::YELLOW;

use core::{Package, PackageSet, Target, Resolve};
use util;
use util::{CargoResult, ChainError, ProcessBuilder, CargoError, Require, internal, human};
use util::{Config, TaskPool, DependencyQueue, Fresh, Dirty, Freshness};

type Args = Vec<String>;

struct Context<'a, 'b> {
    dest: &'a Path,
    deps_dir: &'a Path,
    primary: bool,
    rustc_version: &'a str,
    resolve: &'a Resolve,
    package_set: &'a PackageSet,
    config: &'b mut Config<'b>,
    dylib: (String, String)
}

type Job = proc():Send -> CargoResult<()>;

// This is a temporary assert that ensures the consistency of the arguments
// given the current limitations of Cargo. The long term fix is to have each
// Target know the absolute path to the build location.
fn uniq_target_dest<'a>(targets: &[&'a Target]) -> Option<&'a str> {
    let mut curr: Option<Option<&str>> = None;

    for t in targets.iter() {
        let dest = t.get_profile().get_dest();

        match curr {
            Some(curr) => assert!(curr == dest),
            None => curr = Some(dest)
        }
    }

    curr.unwrap()
}

pub fn compile_targets<'a>(env: &str, targets: &[&Target], pkg: &Package,
                           deps: &PackageSet, resolve: &'a Resolve,
                           config: &'a mut Config<'a>) -> CargoResult<()>
{
    if targets.is_empty() {
        return Ok(());
    }

    debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);

    let path_fragment = uniq_target_dest(targets);
    let target_dir = pkg.get_absolute_target_dir().join(path_fragment.unwrap_or(""));
    let deps_target_dir = target_dir.join("deps");

    let output = try!(util::process("rustc").arg("-v").exec_with_output());
    let rustc_version = str::from_utf8(output.output.as_slice()).unwrap();

    // First ensure that the destination directory exists
    debug!("creating target dir; path={}", target_dir.display());

    try!(mk_target(&target_dir).chain_error(||
        internal(format!("Couldn't create the target directory for {} at {}",
                 pkg.get_name(), target_dir.display()))));

    try!(mk_target(&deps_target_dir).chain_error(||
        internal(format!("Couldn't create the directory for dependencies for {} at {}",
                 pkg.get_name(), deps_target_dir.display()))));

    let temp: TempDir = try!(TempDir::new_in(&deps_target_dir, "temp")
                             .require(|| internal("Couldn't create a tempdir")));

    let file = temp.path().join("dylib.rs");
    try!(File::create(&file));

    let output = try!(util::process("rustc")
                      .arg(file.display().to_string())
                      .arg("--crate-name").arg("-")
                      .arg("--crate-type").arg("dylib")
                      .arg("--print-file-name")
                      .exec_with_output());

    let output = str::from_utf8(output.output.as_slice()).unwrap();

    let parts: Vec<&str> = output.slice_to(output.len() - 1).split('-').collect();
    assert!(parts.len() == 2, "rustc --print-file-name output has changed");

    let mut cx = Context {
        dest: &deps_target_dir,
        deps_dir: &deps_target_dir,
        primary: false,
        rustc_version: rustc_version.as_slice(),
        resolve: resolve,
        package_set: deps,
        config: config,
        dylib: (parts.get(0).to_string(), parts.get(1).to_string())
    };

    // Build up a list of pending jobs, each of which represent compiling a
    // particular package. No actual work is executed as part of this, that's
    // all done later as part of the `execute` function which will run
    // everything in order with proper parallelism.
    let mut jobs = Vec::new();
    for dep in deps.iter() {
        if dep == pkg { continue; }

        // Only compile lib targets for dependencies
        let targets = dep.get_targets().iter().filter(|target| {
            target.is_lib() && target.get_profile().get_env() == env
        }).collect::<Vec<&Target>>();

        jobs.push((dep, try!(compile(targets.as_slice(), dep, &mut cx))));
    }

    cx.primary = true;
    cx.dest = &target_dir;
    jobs.push((pkg, try!(compile(targets, pkg, &mut cx))));

    // Now that we've figured out everything that we're going to do, do it!
    execute(cx.config, jobs)
}

fn compile(targets: &[&Target], pkg: &Package,
           cx: &mut Context) -> CargoResult<(Freshness, Job)> {
    debug!("compile_pkg; pkg={}; targets={}", pkg, pkg.get_targets());

    if targets.is_empty() {
        return Ok((Fresh, proc() Ok(())))
    }

    // First check to see if this package is fresh.
    //
    // Note that we're compiling things in topological order, so if nothing has
    // been built up to this point and we're fresh, then we can safely skip
    // recompilation. If anything has previously been rebuilt, it may have been
    // a dependency of ours, so just go ahead and rebuild ourselves.
    //
    // This is not quite accurate, we should only trigger forceful
    // recompilations for downstream dependencies of ourselves, not everyone
    // compiled afterwards.a
    //
    // TODO: Figure out how this works with targets
    let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
                                               pkg.get_name()));

    let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx,
                                                targets));

    let mut cmds = Vec::new();

    // TODO: Should this be on the target or the package?
    for build_cmd in pkg.get_manifest().get_build().iter() {
        cmds.push(compile_custom(pkg, build_cmd.as_slice(), cx));
    }

    // After the custom command has run, execute rustc for all targets of our
    // package.
    for &target in targets.iter() {
        cmds.push(rustc(pkg, target, cx));
    }

    cmds.push(proc() {
        // If this job runs, then everything has successfully compiled, so write
        // our new fingerprint to the relevant location to prevent
        // recompilations in the future.
        try!(File::create(&fingerprint_loc).write_str(fingerprint.as_slice()));
        Ok(())
    });

    // TODO: this job itself may internally be parallel, but we're hiding that
    //       currently. How to expose the parallelism among a single target?
    Ok((if is_fresh {Fresh} else {Dirty}, proc() {
        for cmd in cmds.move_iter() {
            try!(cmd());
        }
        Ok(())
    }))
}

fn is_fresh(dep: &Package, loc: &Path,
            cx: &mut Context, targets: &[&Target]) -> CargoResult<(bool, String)>
{
    let new_pkg_fingerprint = format!("{}{}", cx.rustc_version,
                                  try!(dep.get_fingerprint(cx.config)));

    let new_fingerprint = fingerprint(new_pkg_fingerprint, hash_targets(targets));

    let mut file = match File::open(loc) {
        Ok(file) => file,
        Err(..) => return Ok((false, new_fingerprint)),
    };

    let old_fingerprint = try!(file.read_to_string());

    log!(5, "old fingerprint: {}", old_fingerprint);
    log!(5, "new fingerprint: {}", new_fingerprint);

    Ok((old_fingerprint == new_fingerprint, new_fingerprint))
}

fn hash_targets(targets: &[&Target]) -> u64 {
    let hasher = SipHasher::new_with_keys(0,0);
    let targets = targets.iter().map(|t| (*t).clone()).collect::<Vec<Target>>();
    hasher.hash(&targets)
}

fn fingerprint(package: String, profiles: u64) -> String {
    let hasher = SipHasher::new_with_keys(0,0);
    util::to_hex(hasher.hash(&(package, profiles)))
}

fn mk_target(target: &Path) -> Result<(), IoError> {
    io::fs::mkdir_recursive(target, io::UserRWX)
}

fn compile_custom(pkg: &Package, cmd: &str,
                  cx: &Context) -> Job {
    // FIXME: this needs to be smarter about splitting
    let mut cmd = cmd.split(' ');
    let mut p = util::process(cmd.next().unwrap())
                     .cwd(pkg.get_root())
                     .env("OUT_DIR", Some(cx.dest.as_str().expect("non-UTF8 dest path")))
                     .env("DEPS_DIR", Some(cx.dest.join(cx.deps_dir)
                                             .as_str().expect("non-UTF8 deps path")));
    for arg in cmd {
        p = p.arg(arg);
    }
    proc() p.exec_with_output().map(|_| ()).map_err(|e| e.mark_human())
}

fn rustc(package: &Package, target: &Target, cx: &mut Context) -> Job {
    let crate_types = target.rustc_crate_types();
    let root = package.get_root();

    log!(5, "root={}; target={}; crate_types={}; dest={}; deps={}; verbose={}",
         root.display(), target, crate_types, cx.dest.display(),
         cx.deps_dir.display(), cx.primary);

    let primary = cx.primary;
    let rustc = prepare_rustc(package, target, crate_types, cx);

    log!(5, "command={}", rustc);

    let _ = cx.config.shell().verbose(|shell| shell.status("Running", rustc.to_string()));

    proc() {
        if primary {
            log!(5, "executing primary");
            rustc.exec().map_err(|err| human(err.to_string()))
        } else {
            log!(5, "executing deps");
            rustc.exec_with_output().and(Ok(())).map_err(|err| {
                human(err.to_string())
            })
        }
    }
}

fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
                 cx: &Context) -> ProcessBuilder
{
    let root = package.get_root();
    let mut args = Vec::new();

    build_base_args(&mut args, target, crate_types, cx);
    build_deps_args(&mut args, package, cx);

    util::process("rustc")
        .cwd(root.clone())
        .args(args.as_slice())
        .env("RUST_LOG", None) // rustc is way too noisy
}

fn build_base_args(into: &mut Args,
                   target: &Target,
                   crate_types: Vec<&str>,
                   cx: &Context)
{
    let metadata = target.get_metadata();

    // TODO: Handle errors in converting paths into args
    into.push(target.get_src_path().display().to_string());

    into.push("--crate-name".to_string());
    into.push(target.get_name().to_string());

    for crate_type in crate_types.iter() {
        into.push("--crate-type".to_string());
        into.push(crate_type.to_string());
    }

    let out = cx.dest.clone();
    let profile = target.get_profile();

    if profile.get_opt_level() != 0 {
        into.push("--opt-level".to_string());
        into.push(profile.get_opt_level().to_string());
    }

    // Right now -g is a little buggy, so we're not passing -g just yet
    // if profile.get_debug() {
    //     into.push("-g".to_string());
    // }

    if profile.is_test() {
        into.push("--test".to_string());
    }

    match metadata {
        Some(m) => {
            into.push("-C".to_string());
            into.push(format!("metadata={}", m.metadata));

            into.push("-C".to_string());
            into.push(format!("extra-filename={}", m.extra_filename));
        }
        None => {}
    }

    if target.is_lib() {
        into.push("--out-dir".to_string());
        into.push(out.display().to_string());
    } else {
        into.push("-o".to_string());
        into.push(out.join(target.get_name()).display().to_string());
    }
}

fn build_deps_args(dst: &mut Args, package: &Package, cx: &Context) {
    dst.push("-L".to_string());
    dst.push(cx.dest.display().to_string());
    dst.push("-L".to_string());
    dst.push(cx.deps_dir.display().to_string());

    for target in dep_targets(package, cx).iter() {
        dst.push("--extern".to_string());
        dst.push(format!("{}={}/{}",
                 target.get_name(),
                 cx.deps_dir.display(),
                 target_filename(target, cx)));
    }
}

fn target_filename(target: &Target, cx: &Context) -> String {
    let stem = target.file_stem();

    if target.is_dylib() {
        let (ref prefix, ref suffix) = cx.dylib;
        format!("{}{}{}", prefix, stem, suffix)
    } else if target.is_rlib() {
        format!("lib{}.rlib", stem)
    } else {
        unreachable!()
    }
}

fn dep_targets(pkg: &Package, cx: &Context) -> Vec<Target> {
    match cx.resolve.deps(pkg.get_package_id()) {
        None => vec!(),
        Some(deps) => deps
            .map(|pkg_id| {
                cx.package_set.iter()
                  .find(|pkg| pkg_id == pkg.get_package_id())
                  .expect("Should have found package")
            })
            .filter_map(|pkg| {
                pkg.get_targets().iter().find(|&t| t.is_lib() && t.get_profile().is_compile())
            })
            .map(|t| t.clone())
            .collect()
    }
}

/// Execute all jobs necessary to build the dependency graph.
///
/// This function will spawn off `config.jobs()` workers to build all of the
/// necessary dependencies, in order. Freshness is propagated as far as possible
/// along each dependency chain.
fn execute(config: &mut Config,
           jobs: Vec<(&Package, (Freshness, Job))>) -> CargoResult<()> {
    let pool = TaskPool::new(config.jobs());
    let (tx, rx) = channel();
    let mut queue = DependencyQueue::new();
    for &(pkg, _) in jobs.iter() {
        queue.register(pkg);
    }
    for (pkg, (fresh, job)) in jobs.move_iter() {
        queue.enqueue(pkg, fresh, (pkg, job));
    }

    // Iteratively execute the dependency graph. Each turn of this loop will
    // schedule as much work as possible and then wait for one job to finish,
    // possibly scheduling more work afterwards.
    let mut active = 0i;
    while queue.len() > 0 {
        loop {
            match queue.dequeue() {
                Some((name, Fresh, (pkg, _))) => {
                    try!(config.shell().status("Fresh", pkg));
                    tx.send((name, Fresh, Ok(())));
                }
                Some((name, Dirty, (pkg, job))) => {
                    try!(config.shell().status("Compiling", pkg));
                    let my_tx = tx.clone();
                    pool.execute(proc() my_tx.send((name, Dirty, job())));
                }
                None => break,
            }
        }

        // Now that all possible work has been scheduled, wait for a piece of
        // work to finish. If any package fails to build then we stop scheduling
        // work as quickly as possibly.
        active -= 1;
        match rx.recv() {
            (name, fresh, Ok(())) => queue.finish(&name, fresh),
            (_, _, Err(e)) => {
                if active > 0 && config.jobs() > 1 {
                    try!(config.shell().say("Build failed, waiting for other \
                                             jobs to finish...", YELLOW));
                    for _ in rx.iter() {}
                }
                return Err(e)
            }
        }
    }

    log!(5, "rustc jobs completed");

    Ok(())
}
<commit_msg>No need for a TempDir, use `-` as input<commit_after>use std::hash::Hasher;
use std::hash::sip::SipHasher;
use std::io::{File, IoError};
use std::io;
use std::os::args;
use std::str;
use term::color::YELLOW;

use core::{Package, PackageSet, Target, Resolve};
use util;
use util::{CargoResult, ChainError, ProcessBuilder, CargoError, internal, human};
use util::{Config, TaskPool, DependencyQueue, Fresh, Dirty, Freshness};

type Args = Vec<String>;

struct Context<'a, 'b> {
    dest: &'a Path,
    deps_dir: &'a Path,
    primary: bool,
    rustc_version: &'a str,
    resolve: &'a Resolve,
    package_set: &'a PackageSet,
    config: &'b mut Config<'b>,
    dylib: (String, String)
}

type Job = proc():Send -> CargoResult<()>;

// This is a temporary assert that ensures the consistency of the arguments
// given the current limitations of Cargo. The long term fix is to have each
// Target know the absolute path to the build location.
fn uniq_target_dest<'a>(targets: &[&'a Target]) -> Option<&'a str> {
    let mut curr: Option<Option<&str>> = None;

    for t in targets.iter() {
        let dest = t.get_profile().get_dest();

        match curr {
            Some(curr) => assert!(curr == dest),
            None => curr = Some(dest)
        }
    }

    curr.unwrap()
}

pub fn compile_targets<'a>(env: &str, targets: &[&Target], pkg: &Package,
                           deps: &PackageSet, resolve: &'a Resolve,
                           config: &'a mut Config<'a>) -> CargoResult<()>
{
    if targets.is_empty() {
        return Ok(());
    }

    debug!("compile_targets; targets={}; pkg={}; deps={}", targets, pkg, deps);

    let path_fragment = uniq_target_dest(targets);
    let target_dir = pkg.get_absolute_target_dir().join(path_fragment.unwrap_or(""));
    let deps_target_dir = target_dir.join("deps");

    let output = try!(util::process("rustc").arg("-v").exec_with_output());
    let rustc_version = str::from_utf8(output.output.as_slice()).unwrap();

    // First ensure that the destination directory exists
    debug!("creating target dir; path={}", target_dir.display());

    try!(mk_target(&target_dir).chain_error(||
        internal(format!("Couldn't create the target directory for {} at {}",
                 pkg.get_name(), target_dir.display()))));

    try!(mk_target(&deps_target_dir).chain_error(||
        internal(format!("Couldn't create the directory for dependencies for {} at {}",
                 pkg.get_name(), deps_target_dir.display()))));

    let output = try!(util::process("rustc")
                      .arg("-")
                      .arg("--crate-name").arg("-")
                      .arg("--crate-type").arg("dylib")
                      .arg("--print-file-name")
                      .exec_with_output());

    let output = str::from_utf8(output.output.as_slice()).unwrap();

    let parts: Vec<&str> = output.slice_to(output.len() - 1).split('-').collect();
    assert!(parts.len() == 2, "rustc --print-file-name output has changed");

    let mut cx = Context {
        dest: &deps_target_dir,
        deps_dir: &deps_target_dir,
        primary: false,
        rustc_version: rustc_version.as_slice(),
        resolve: resolve,
        package_set: deps,
        config: config,
        dylib: (parts.get(0).to_string(), parts.get(1).to_string())
    };

    // Build up a list of pending jobs, each of which represent compiling a
    // particular package. No actual work is executed as part of this, that's
    // all done later as part of the `execute` function which will run
    // everything in order with proper parallelism.
    let mut jobs = Vec::new();
    for dep in deps.iter() {
        if dep == pkg { continue; }

        // Only compile lib targets for dependencies
        let targets = dep.get_targets().iter().filter(|target| {
            target.is_lib() && target.get_profile().get_env() == env
        }).collect::<Vec<&Target>>();

        jobs.push((dep, try!(compile(targets.as_slice(), dep, &mut cx))));
    }

    cx.primary = true;
    cx.dest = &target_dir;
    jobs.push((pkg, try!(compile(targets, pkg, &mut cx))));

    // Now that we've figured out everything that we're going to do, do it!
    execute(cx.config, jobs)
}

fn compile(targets: &[&Target], pkg: &Package,
           cx: &mut Context) -> CargoResult<(Freshness, Job)> {
    debug!("compile_pkg; pkg={}; targets={}", pkg, pkg.get_targets());

    if targets.is_empty() {
        return Ok((Fresh, proc() Ok(())))
    }

    // First check to see if this package is fresh.
    //
    // Note that we're compiling things in topological order, so if nothing has
    // been built up to this point and we're fresh, then we can safely skip
    // recompilation. If anything has previously been rebuilt, it may have been
    // a dependency of ours, so just go ahead and rebuild ourselves.
    //
    // This is not quite accurate, we should only trigger forceful
    // recompilations for downstream dependencies of ourselves, not everyone
    // compiled afterwards.a
    //
    // TODO: Figure out how this works with targets
    let fingerprint_loc = cx.dest.join(format!(".{}.fingerprint",
                                               pkg.get_name()));

    let (is_fresh, fingerprint) = try!(is_fresh(pkg, &fingerprint_loc, cx,
                                                targets));

    let mut cmds = Vec::new();

    // TODO: Should this be on the target or the package?
    for build_cmd in pkg.get_manifest().get_build().iter() {
        cmds.push(compile_custom(pkg, build_cmd.as_slice(), cx));
    }

    // After the custom command has run, execute rustc for all targets of our
    // package.
    for &target in targets.iter() {
        cmds.push(rustc(pkg, target, cx));
    }

    cmds.push(proc() {
        // If this job runs, then everything has successfully compiled, so write
        // our new fingerprint to the relevant location to prevent
        // recompilations in the future.
        try!(File::create(&fingerprint_loc).write_str(fingerprint.as_slice()));
        Ok(())
    });

    // TODO: this job itself may internally be parallel, but we're hiding that
    //       currently. How to expose the parallelism among a single target?
    Ok((if is_fresh {Fresh} else {Dirty}, proc() {
        for cmd in cmds.move_iter() {
            try!(cmd());
        }
        Ok(())
    }))
}

fn is_fresh(dep: &Package, loc: &Path,
            cx: &mut Context, targets: &[&Target]) -> CargoResult<(bool, String)>
{
    let new_pkg_fingerprint = format!("{}{}", cx.rustc_version,
                                  try!(dep.get_fingerprint(cx.config)));

    let new_fingerprint = fingerprint(new_pkg_fingerprint, hash_targets(targets));

    let mut file = match File::open(loc) {
        Ok(file) => file,
        Err(..) => return Ok((false, new_fingerprint)),
    };

    let old_fingerprint = try!(file.read_to_string());

    log!(5, "old fingerprint: {}", old_fingerprint);
    log!(5, "new fingerprint: {}", new_fingerprint);

    Ok((old_fingerprint == new_fingerprint, new_fingerprint))
}

fn hash_targets(targets: &[&Target]) -> u64 {
    let hasher = SipHasher::new_with_keys(0,0);
    let targets = targets.iter().map(|t| (*t).clone()).collect::<Vec<Target>>();
    hasher.hash(&targets)
}

fn fingerprint(package: String, profiles: u64) -> String {
    let hasher = SipHasher::new_with_keys(0,0);
    util::to_hex(hasher.hash(&(package, profiles)))
}

fn mk_target(target: &Path) -> Result<(), IoError> {
    io::fs::mkdir_recursive(target, io::UserRWX)
}

fn compile_custom(pkg: &Package, cmd: &str,
                  cx: &Context) -> Job {
    // FIXME: this needs to be smarter about splitting
    let mut cmd = cmd.split(' ');
    let mut p = util::process(cmd.next().unwrap())
                     .cwd(pkg.get_root())
                     .env("OUT_DIR", Some(cx.dest.as_str().expect("non-UTF8 dest path")))
                     .env("DEPS_DIR", Some(cx.dest.join(cx.deps_dir)
                                             .as_str().expect("non-UTF8 deps path")));
    for arg in cmd {
        p = p.arg(arg);
    }
    proc() p.exec_with_output().map(|_| ()).map_err(|e| e.mark_human())
}

fn rustc(package: &Package, target: &Target, cx: &mut Context) -> Job {
    let crate_types = target.rustc_crate_types();
    let root = package.get_root();

    log!(5, "root={}; target={}; crate_types={}; dest={}; deps={}; verbose={}",
         root.display(), target, crate_types, cx.dest.display(),
         cx.deps_dir.display(), cx.primary);

    let primary = cx.primary;
    let rustc = prepare_rustc(package, target, crate_types, cx);

    log!(5, "command={}", rustc);

    let _ = cx.config.shell().verbose(|shell| shell.status("Running", rustc.to_string()));

    proc() {
        if primary {
            log!(5, "executing primary");
            rustc.exec().map_err(|err| human(err.to_string()))
        } else {
            log!(5, "executing deps");
            rustc.exec_with_output().and(Ok(())).map_err(|err| {
                human(err.to_string())
            })
        }
    }
}

fn prepare_rustc(package: &Package, target: &Target, crate_types: Vec<&str>,
                 cx: &Context) -> ProcessBuilder
{
    let root = package.get_root();
    let mut args = Vec::new();

    build_base_args(&mut args, target, crate_types, cx);
    build_deps_args(&mut args, package, cx);

    util::process("rustc")
        .cwd(root.clone())
        .args(args.as_slice())
        .env("RUST_LOG", None) // rustc is way too noisy
}

fn build_base_args(into: &mut Args,
                   target: &Target,
                   crate_types: Vec<&str>,
                   cx: &Context)
{
    let metadata = target.get_metadata();

    // TODO: Handle errors in converting paths into args
    into.push(target.get_src_path().display().to_string());

    into.push("--crate-name".to_string());
    into.push(target.get_name().to_string());

    for crate_type in crate_types.iter() {
        into.push("--crate-type".to_string());
        into.push(crate_type.to_string());
    }

    let out = cx.dest.clone();
    let profile = target.get_profile();

    if profile.get_opt_level() != 0 {
        into.push("--opt-level".to_string());
        into.push(profile.get_opt_level().to_string());
    }

    // Right now -g is a little buggy, so we're not passing -g just yet
    // if profile.get_debug() {
    //     into.push("-g".to_string());
    // }

    if profile.is_test() {
        into.push("--test".to_string());
    }

    match metadata {
        Some(m) => {
            into.push("-C".to_string());
            into.push(format!("metadata={}", m.metadata));

            into.push("-C".to_string());
            into.push(format!("extra-filename={}", m.extra_filename));
        }
        None => {}
    }

    if target.is_lib() {
        into.push("--out-dir".to_string());
        into.push(out.display().to_string());
    } else {
        into.push("-o".to_string());
        into.push(out.join(target.get_name()).display().to_string());
    }
}

fn build_deps_args(dst: &mut Args, package: &Package, cx: &Context) {
    dst.push("-L".to_string());
    dst.push(cx.dest.display().to_string());
    dst.push("-L".to_string());
    dst.push(cx.deps_dir.display().to_string());

    for target in dep_targets(package, cx).iter() {
        dst.push("--extern".to_string());
        dst.push(format!("{}={}/{}",
                 target.get_name(),
                 cx.deps_dir.display(),
                 target_filename(target, cx)));
    }
}

fn target_filename(target: &Target, cx: &Context) -> String {
    let stem = target.file_stem();

    if target.is_dylib() {
        let (ref prefix, ref suffix) = cx.dylib;
        format!("{}{}{}", prefix, stem, suffix)
    } else if target.is_rlib() {
        format!("lib{}.rlib", stem)
    } else {
        unreachable!()
    }
}

fn dep_targets(pkg: &Package, cx: &Context) -> Vec<Target> {
    match cx.resolve.deps(pkg.get_package_id()) {
        None => vec!(),
        Some(deps) => deps
            .map(|pkg_id| {
                cx.package_set.iter()
                  .find(|pkg| pkg_id == pkg.get_package_id())
                  .expect("Should have found package")
            })
            .filter_map(|pkg| {
                pkg.get_targets().iter().find(|&t| t.is_lib() && t.get_profile().is_compile())
            })
            .map(|t| t.clone())
            .collect()
    }
}

/// Execute all jobs necessary to build the dependency graph.
///
/// This function will spawn off `config.jobs()` workers to build all of the
/// necessary dependencies, in order. Freshness is propagated as far as possible
/// along each dependency chain.
fn execute(config: &mut Config,
           jobs: Vec<(&Package, (Freshness, Job))>) -> CargoResult<()> {
    let pool = TaskPool::new(config.jobs());
    let (tx, rx) = channel();
    let mut queue = DependencyQueue::new();
    for &(pkg, _) in jobs.iter() {
        queue.register(pkg);
    }
    for (pkg, (fresh, job)) in jobs.move_iter() {
        queue.enqueue(pkg, fresh, (pkg, job));
    }

    // Iteratively execute the dependency graph. Each turn of this loop will
    // schedule as much work as possible and then wait for one job to finish,
    // possibly scheduling more work afterwards.
    let mut active = 0i;
    while queue.len() > 0 {
        loop {
            match queue.dequeue() {
                Some((name, Fresh, (pkg, _))) => {
                    try!(config.shell().status("Fresh", pkg));
                    tx.send((name, Fresh, Ok(())));
                }
                Some((name, Dirty, (pkg, job))) => {
                    try!(config.shell().status("Compiling", pkg));
                    let my_tx = tx.clone();
                    pool.execute(proc() my_tx.send((name, Dirty, job())));
                }
                None => break,
            }
        }

        // Now that all possible work has been scheduled, wait for a piece of
        // work to finish. If any package fails to build then we stop scheduling
        // work as quickly as possibly.
        active -= 1;
        match rx.recv() {
            (name, fresh, Ok(())) => queue.finish(&name, fresh),
            (_, _, Err(e)) => {
                if active > 0 && config.jobs() > 1 {
                    try!(config.shell().say("Build failed, waiting for other \
                                             jobs to finish...", YELLOW));
                    for _ in rx.iter() {}
                }
                return Err(e)
            }
        }
    }

    log!(5, "rustc jobs completed");

    Ok(())
}
<|endoftext|>


<commit_before>#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage> {
    storage: Storage,
}

impl<Storage> __BindgenBitfieldUnit<Storage> {
    #[inline]
    pub const fn new(storage: Storage) -> Self {
        Self { storage }
    }
}

impl<Storage> __BindgenBitfieldUnit<Storage>
where
    Storage: AsRef<[u8]> + AsMut<[u8]>,
{
    #[inline]
    pub fn get_bit(&self, index: usize) -> bool {
        debug_assert!(index / 8 < self.storage.as_ref().len());

        let byte_index = index / 8;
        let byte = self.storage.as_ref()[byte_index];

        let bit_index = if cfg!(target_endian = "big") {
            7 - (index % 8)
        } else {
            index % 8
        };

        let mask = 1 << bit_index;

        byte & mask == mask
    }

    #[inline]
    pub fn set_bit(&mut self, index: usize, val: bool) {
        debug_assert!(index / 8 < self.storage.as_ref().len());

        let byte_index = index / 8;
        let byte = &mut self.storage.as_mut()[byte_index];

        let bit_index = if cfg!(target_endian = "big") {
            7 - (index % 8)
        } else {
            index % 8
        };

        let mask = 1 << bit_index;
        if val {
            *byte |= mask;
        } else {
            *byte &= !mask;
        }
    }

    #[inline]
    pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
        debug_assert!(bit_width <= 64);
        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
        debug_assert!(
            (bit_offset + (bit_width as usize)) / 8 <=
                self.storage.as_ref().len()
        );

        let mut val = 0;

        for i in 0..(bit_width as usize) {
            if self.get_bit(i + bit_offset) {
                let index = if cfg!(target_endian = "big") {
                    bit_width as usize - 1 - i
                } else {
                    i
                };
                val |= 1 << index;
            }
        }

        val
    }

    #[inline]
    pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
        debug_assert!(bit_width <= 64);
        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
        debug_assert!(
            (bit_offset + (bit_width as usize)) / 8 <=
                self.storage.as_ref().len()
        );

        for i in 0..(bit_width as usize) {
            let mask = 1 << i;
            let val_bit_is_set = val & mask == mask;
            let index = if cfg!(target_endian = "big") {
                bit_width as usize - 1 - i
            } else {
                i
            };
            self.set_bit(index + bit_offset, val_bit_is_set);
        }
    }
}
<commit_msg>Fix an erroneous +x bit on a source code file.<commit_after>#[repr(C)]
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct __BindgenBitfieldUnit<Storage> {
    storage: Storage,
}

impl<Storage> __BindgenBitfieldUnit<Storage> {
    #[inline]
    pub const fn new(storage: Storage) -> Self {
        Self { storage }
    }
}

impl<Storage> __BindgenBitfieldUnit<Storage>
where
    Storage: AsRef<[u8]> + AsMut<[u8]>,
{
    #[inline]
    pub fn get_bit(&self, index: usize) -> bool {
        debug_assert!(index / 8 < self.storage.as_ref().len());

        let byte_index = index / 8;
        let byte = self.storage.as_ref()[byte_index];

        let bit_index = if cfg!(target_endian = "big") {
            7 - (index % 8)
        } else {
            index % 8
        };

        let mask = 1 << bit_index;

        byte & mask == mask
    }

    #[inline]
    pub fn set_bit(&mut self, index: usize, val: bool) {
        debug_assert!(index / 8 < self.storage.as_ref().len());

        let byte_index = index / 8;
        let byte = &mut self.storage.as_mut()[byte_index];

        let bit_index = if cfg!(target_endian = "big") {
            7 - (index % 8)
        } else {
            index % 8
        };

        let mask = 1 << bit_index;
        if val {
            *byte |= mask;
        } else {
            *byte &= !mask;
        }
    }

    #[inline]
    pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
        debug_assert!(bit_width <= 64);
        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
        debug_assert!(
            (bit_offset + (bit_width as usize)) / 8 <=
                self.storage.as_ref().len()
        );

        let mut val = 0;

        for i in 0..(bit_width as usize) {
            if self.get_bit(i + bit_offset) {
                let index = if cfg!(target_endian = "big") {
                    bit_width as usize - 1 - i
                } else {
                    i
                };
                val |= 1 << index;
            }
        }

        val
    }

    #[inline]
    pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
        debug_assert!(bit_width <= 64);
        debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
        debug_assert!(
            (bit_offset + (bit_width as usize)) / 8 <=
                self.storage.as_ref().len()
        );

        for i in 0..(bit_width as usize) {
            let mask = 1 << i;
            let val_bit_is_set = val & mask == mask;
            let index = if cfg!(target_endian = "big") {
                bit_width as usize - 1 - i
            } else {
                i
            };
            self.set_bit(index + bit_offset, val_bit_is_set);
        }
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Communication with the PowerDNS server happens through the http
// server.
// See https://doc.powerdns.com/md/authoritative/backend-remote/ for
// details about the various requests and response.

use config::Config;
use domain_store::{DomainError, DomainRecord};
use errors::*;
use iron::headers::ContentType;
use iron::method::Method;
use iron::prelude::*;
use iron::status::{self, Status};
use serde_json;
use std::io::Read;

#[derive(Deserialize)]
struct PdnsRequestParameters {
    // intialize method
    path: Option<String>,
    timeout: Option<String>,

    // lookup method
    qtype: Option<String>,
    qname: Option<String>,
    #[serde(rename="zone-id")]
    zone_id: Option<i32>,
    remote: Option<String>,
    local: Option<String>,
    real_remote: Option<String>,
}

#[derive(Deserialize)]
struct PdnsRequest {
    method: String,
    parameters: PdnsRequestParameters,
}

#[derive(Serialize)]
struct PdnsLookupResponse {
    qtype: String,
    qname: String,
    content: String,
    ttl: u32,
    #[serde(skip_serializing_if = "Option::is_none")]
    domain_id: Option<String>,
    #[serde(rename="scopeMask")]
    #[serde(skip_serializing_if = "Option::is_none")]
    scope_mask: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    auth: Option<String>,
}

#[derive(Serialize)]
#[serde(untagged)]
enum PdnsResponseParams {
    Lookup(PdnsLookupResponse),
}

#[derive(Serialize)]
struct PdnsResponse {
    result: Vec<PdnsResponseParams>,
}

fn pdns_failure() -> IronResult<Response> {
    let mut response = Response::with("{\"result\":false}");
    response.status = Some(Status::Ok);
    response.headers.set(ContentType::json());
    Ok(response)
}

pub fn pdns_endpoint(req: &mut Request, config: &Config) -> IronResult<Response> {
    // TODO: check where the request is coming from and only allow from pdns.

    // Read the request from the json body.
    let mut s = String::new();
    itry!(req.body.read_to_string(&mut s));

    println!("Body is: {}", s);

    let input: PdnsRequest = match serde_json::from_str(&s) {
        Ok(value) => value,
        Err(err) => {
            error!("Bad request: {}", err);
            return EndpointError::with(status::BadRequest, 400);
        }
    };

    println!("pdns request is {}", input.method);

    if input.method == "lookup" {
        let mut qname = input.parameters.qname.unwrap();
        let qtype = input.parameters.qtype.unwrap();
        println!("lookup for qtype={} qname={}", qtype, qname);

        // Example payload:
        //
        // {"method": "lookup",
        //  "parameters": {"local": "0.0.0.0",
        //                 "qname": "fabrice.box.knilxof.org.",
        //                 "qtype": "SOA",
        //                 "real-remote": "63.245.221.198/32",
        //                 "remote": "63.245.221.198",
        //                 "zone-id": -1}}

        // If the qname starts with `_acme-challenge.` this is a DNS-01 challenge verification,
        // so remove that part of the domain to retrieve our record.
        // See https://tools.ietf.org/html/draft-ietf-acme-acme-06#section-8.4
        if qname.starts_with("_acme-challenge.") {
            qname = qname[16..].to_owned();
        }
        println!("final qname={}", qname);

        // Look for a record with for the qname.
        match config.domain_db
            .get_record_by_name(&qname)
            .recv()
            .unwrap() {
                Ok(record) => {
                    if record.local_ip.is_none() {
                        // No info on this domain, bail out.
                        return pdns_failure();
                    }

                    // Choose either the local or public ip based on the parameters.remote one.
                    let a_record = if record.public_ip.is_some() && input.parameters.remote.unwrap() == record.public_ip.unwrap() {
                        // We are inside of the home network, return the local ip for the A record.
                        record.local_ip.unwrap()
                    } else {
                        // We are outside of the home network, return the ip of the tunnel for the A record.
                        config.tunnel_ip.to_owned()
                    };

                    let mut pdns_response = PdnsResponse {
                        result: Vec::new(),
                    };

                    if qtype == "SOA" {
                        // Add a "SOA" record.
                        // TODO: don't hardcode the content of this record!
                        let ns_record = PdnsLookupResponse {
                            qtype: "SOA".to_owned(),
                            qname: qname.to_owned(),
                            content: "a.dns.gandi.net hostmaster.gandi.net 1476196782 10800 3600 604800 10800".to_owned(),
                            ttl: config.dns_ttl,
                            domain_id: None,
                            scope_mask: None,
                            auth: None,
                        };
                        pdns_response.result.push(PdnsResponseParams::Lookup(ns_record));
                    }

                    if qtype == "ANY" || qtype == "A" {
                        // Add an "A" record.
                        let ns_record = PdnsLookupResponse {
                            qtype: "A".to_owned(),
                            qname: qname.to_owned(),
                            content: a_record,
                            ttl: config.dns_ttl,
                            domain_id: None,
                            scope_mask: None,
                            auth: None,
                        };
                        pdns_response.result.push(PdnsResponseParams::Lookup(ns_record));
                    }

                    if (qtype == "ANY" || qtype == "TXT") && record.dns_challenge.is_some() {
                        // Add a "TXT" record with the dns challenge content.
                        let ns_record = PdnsLookupResponse {
                            qtype: "A".to_owned(),
                            qname: qname.to_owned(),
                            content: record.dns_challenge.unwrap(),
                            ttl: config.dns_ttl,
                            domain_id: None,
                            scope_mask: None,
                            auth: None,
                        };
                        pdns_response.result.push(PdnsResponseParams::Lookup(ns_record));
                    }

                    match serde_json::to_string(&pdns_response) {
                        Ok(serialized) => {
                            println!("{}", serialized);
                            let mut response = Response::with(serialized);
                            response.status = Some(Status::Ok);
                            response.headers.set(ContentType::json());

                            return Ok(response);
                        }
                        Err(_) => return EndpointError::with(status::InternalServerError, 501)
                    }
                },
                Err(_) => {
                    // No such domain, return a `false` result to PowerDNS.
                    return pdns_failure();
                }
            }
    }

    EndpointError::with(status::InternalServerError, 501)
}
<commit_msg>Always return a valid failure to pdns<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Communication with the PowerDNS server happens through the http
// server.
// See https://doc.powerdns.com/md/authoritative/backend-remote/ for
// details about the various requests and response.

use config::Config;
use domain_store::{DomainError, DomainRecord};
use errors::*;
use iron::headers::ContentType;
use iron::method::Method;
use iron::prelude::*;
use iron::status::{self, Status};
use serde_json;
use std::io::Read;

#[derive(Deserialize)]
struct PdnsRequestParameters {
    // intialize method
    path: Option<String>,
    timeout: Option<String>,

    // lookup method
    qtype: Option<String>,
    qname: Option<String>,
    #[serde(rename="zone-id")]
    zone_id: Option<i32>,
    remote: Option<String>,
    local: Option<String>,
    real_remote: Option<String>,
}

#[derive(Deserialize)]
struct PdnsRequest {
    method: String,
    parameters: PdnsRequestParameters,
}

#[derive(Serialize)]
struct PdnsLookupResponse {
    qtype: String,
    qname: String,
    content: String,
    ttl: u32,
    #[serde(skip_serializing_if = "Option::is_none")]
    domain_id: Option<String>,
    #[serde(rename="scopeMask")]
    #[serde(skip_serializing_if = "Option::is_none")]
    scope_mask: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    auth: Option<String>,
}

#[derive(Serialize)]
#[serde(untagged)]
enum PdnsResponseParams {
    Lookup(PdnsLookupResponse),
}

#[derive(Serialize)]
struct PdnsResponse {
    result: Vec<PdnsResponseParams>,
}

fn pdns_failure() -> IronResult<Response> {
    let mut response = Response::with("{\"result\":false}");
    response.status = Some(Status::Ok);
    response.headers.set(ContentType::json());
    Ok(response)
}

pub fn pdns_endpoint(req: &mut Request, config: &Config) -> IronResult<Response> {
    // TODO: check where the request is coming from and only allow from pdns.

    // Read the request from the json body.
    let mut s = String::new();
    itry!(req.body.read_to_string(&mut s));

    println!("Body is: {}", s);

    let input: PdnsRequest = match serde_json::from_str(&s) {
        Ok(value) => value,
        Err(err) => {
            error!("Bad request: {}", err);
            return EndpointError::with(status::BadRequest, 400);
        }
    };

    println!("pdns request is {}", input.method);

    if input.method == "lookup" {
        let mut qname = input.parameters.qname.unwrap();
        let qtype = input.parameters.qtype.unwrap();
        println!("lookup for qtype={} qname={}", qtype, qname);

        // Example payload:
        //
        // {"method": "lookup",
        //  "parameters": {"local": "0.0.0.0",
        //                 "qname": "fabrice.box.knilxof.org.",
        //                 "qtype": "SOA",
        //                 "real-remote": "63.245.221.198/32",
        //                 "remote": "63.245.221.198",
        //                 "zone-id": -1}}

        // If the qname starts with `_acme-challenge.` this is a DNS-01 challenge verification,
        // so remove that part of the domain to retrieve our record.
        // See https://tools.ietf.org/html/draft-ietf-acme-acme-06#section-8.4
        if qname.starts_with("_acme-challenge.") {
            qname = qname[16..].to_owned();
        }
        println!("final qname={}", qname);

        // Look for a record with for the qname.
        match config.domain_db
            .get_record_by_name(&qname)
            .recv()
            .unwrap() {
                Ok(record) => {
                    if record.local_ip.is_none() {
                        // No info on this domain, bail out.
                        return pdns_failure();
                    }

                    // Choose either the local or public ip based on the parameters.remote one.
                    let a_record = if record.public_ip.is_some() && input.parameters.remote.unwrap() == record.public_ip.unwrap() {
                        // We are inside of the home network, return the local ip for the A record.
                        record.local_ip.unwrap()
                    } else {
                        // We are outside of the home network, return the ip of the tunnel for the A record.
                        config.tunnel_ip.to_owned()
                    };

                    let mut pdns_response = PdnsResponse {
                        result: Vec::new(),
                    };

                    if qtype == "SOA" {
                        // Add a "SOA" record.
                        // TODO: don't hardcode the content of this record!
                        let ns_record = PdnsLookupResponse {
                            qtype: "SOA".to_owned(),
                            qname: qname.to_owned(),
                            content: "a.dns.gandi.net hostmaster.gandi.net 1476196782 10800 3600 604800 10800".to_owned(),
                            ttl: config.dns_ttl,
                            domain_id: None,
                            scope_mask: None,
                            auth: None,
                        };
                        pdns_response.result.push(PdnsResponseParams::Lookup(ns_record));
                    }

                    if qtype == "ANY" || qtype == "A" {
                        // Add an "A" record.
                        let ns_record = PdnsLookupResponse {
                            qtype: "A".to_owned(),
                            qname: qname.to_owned(),
                            content: a_record,
                            ttl: config.dns_ttl,
                            domain_id: None,
                            scope_mask: None,
                            auth: None,
                        };
                        pdns_response.result.push(PdnsResponseParams::Lookup(ns_record));
                    }

                    if (qtype == "ANY" || qtype == "TXT") && record.dns_challenge.is_some() {
                        // Add a "TXT" record with the dns challenge content.
                        let ns_record = PdnsLookupResponse {
                            qtype: "A".to_owned(),
                            qname: qname.to_owned(),
                            content: record.dns_challenge.unwrap(),
                            ttl: config.dns_ttl,
                            domain_id: None,
                            scope_mask: None,
                            auth: None,
                        };
                        pdns_response.result.push(PdnsResponseParams::Lookup(ns_record));
                    }

                    match serde_json::to_string(&pdns_response) {
                        Ok(serialized) => {
                            println!("{}", serialized);
                            let mut response = Response::with(serialized);
                            response.status = Some(Status::Ok);
                            response.headers.set(ContentType::json());

                            return Ok(response);
                        }
                        Err(_) => return EndpointError::with(status::InternalServerError, 501)
                    }
                },
                Err(_) => {
                    // No such domain, return a `false` result to PowerDNS.
                    return pdns_failure();
                }
            }
    }

    pdns_failure()
}
<|endoftext|>


<commit_before>use std::mem;
use jack_sys as j;
use rimd;
use jack_flags::port_flags::{IS_INPUT, IS_OUTPUT, PortFlags};
use port::PortData;

pub trait MidiStream: Sized {
    unsafe fn ptr(&self) -> *mut ::libc::c_void;

    fn iter<'a>(&'a self) -> MidiIter<'a, Self> {
        let n = self.len();
        MidiIter {
            stream: self,
            len: n,
            index: 0,
        }
    }

    fn nth(&self, n: usize) -> Option<MidiEvent> {
        if n < self.len() {
            MidiEvent::from_ptr(unsafe { self.ptr() }, n as u32)
        } else {
            None
        }
    }

    fn len(&self) -> usize {
        let n = unsafe { j::jack_midi_get_event_count(self.ptr()) };
        n as usize
    }
}

/// `MidiStreamReader` implements the `PortData` trait, which defines
/// an endpoint for JACK. In this case, it provides readable midi
/// messages.
#[derive(Debug)]
pub struct MidiStreamReader {
    buffer_ptr: *mut ::libc::c_void,
}

impl MidiStream for MidiStreamReader {
    unsafe fn ptr(&self) -> *mut ::libc::c_void {
        self.buffer_ptr
    }
}

unsafe impl PortData for MidiStreamReader {
    unsafe fn from_ptr(ptr: *mut ::libc::c_void, _: u32) -> Self {
        MidiStreamReader { buffer_ptr: ptr }
    }

    fn jack_port_type() -> &'static str {
        "8 bit raw midi"
    }

    fn jack_flags() -> PortFlags {
        IS_INPUT
    }

    fn jack_buffer_size() -> u64 {
        // Not needed for built in types according to jack api
        0
    }
}

#[derive(Debug)]
pub struct MidiStreamWriter {
    buffer_ptr: *mut ::libc::c_void,
}

impl MidiStreamWriter {
    pub fn write(&mut self, events: &[MidiEvent]) {
        let mut _events_vec = Vec::new();
        unsafe {
            let mut events = events;
            let mut is_sorted = true;
            for i in 0..events.len() - 1 {
                if events[i].time() > events[i + 1].time() {
                    is_sorted = false;
                }
            }
            if !is_sorted {
                _events_vec = events.to_vec();
                _events_vec.sort_by(|a, b| {
                    match (a.time() < b.time(), a.time() > b.time()) {
                        (true, _) => ::std::cmp::Ordering::Less,
                        (_, true) => ::std::cmp::Ordering::Greater,
                        (_, _) => ::std::cmp::Ordering::Equal,
                    }
                });
                events = &_events_vec;
            }
            for e in events.iter() {
                j::jack_midi_event_reserve(self.buffer_ptr, e.time(), e.message().data.len());
                j::jack_midi_event_write(self.buffer_ptr,
                                         e.time(),
                                         e.message().data.as_ptr(),
                                         e.message().data.len());
            }
        }
    }
}

impl MidiStream for MidiStreamWriter {
    unsafe fn ptr(&self) -> *mut ::libc::c_void {
        self.buffer_ptr
    }
}

unsafe impl PortData for MidiStreamWriter {
    unsafe fn from_ptr(ptr: *mut ::libc::c_void, _: u32) -> Self {
        j::jack_midi_clear_buffer(ptr);
        MidiStreamWriter { buffer_ptr: ptr }
    }

    fn jack_port_type() -> &'static str {
        "8 bit raw midi"
    }

    fn jack_flags() -> PortFlags {
        IS_OUTPUT
    }

    fn jack_buffer_size() -> u64 {
        // Not needed for built in types according to jack api
        0
    }
}

/// Iterate over `MidiEvent`.
#[derive(Debug)]
pub struct MidiIter<'a, S: MidiStream + 'a> {
    stream: &'a S,
    len: usize,
    index: usize,
}

impl<'a, S: MidiStream + 'a> Iterator for MidiIter<'a, S> {
    type Item = MidiEvent;

    fn next(&mut self) -> Option<Self::Item> {
        let ret = self.stream.nth(self.index);
        self.index += 1;
        ret
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let elements_left = self.len - self.index;
        (elements_left, Some(elements_left))
    }

    fn count(self) -> usize {
        self.len - self.index
    }

    fn last(self) -> Option<Self::Item> {
        self.stream.nth(self.len - 1)
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        self.index += n;
        self.next()
    }
}

#[derive(Clone, Debug)]
pub struct MidiEvent {
    message: rimd::MidiMessage,
    time: u32,
}

impl MidiEvent {
    pub fn new(message: rimd::MidiMessage, time: u32) -> MidiEvent {
        MidiEvent {
            message: message,
            time: time,
        }
    }

    pub fn from_ptr(ptr: *mut ::libc::c_void, i: u32) -> Option<Self> {
        unsafe {
            let mut e: j::jack_midi_event_t = mem::uninitialized();
            let res = j::jack_midi_event_get(&mut e, ptr, i);
            if res != 0 {
                return None;
            }
            let bytes_slice: &[u8] = ::std::slice::from_raw_parts(e.buffer as *const u8, e.size);
            let bytes_vec: Vec<u8> = bytes_slice.to_vec();
            let message = rimd::MidiMessage::from_bytes(bytes_vec);
            Some(MidiEvent {
                message: message,
                time: e.time,
            })
        }
    }

    pub fn message(&self) -> &rimd::MidiMessage {
        &self.message
    }

    pub fn time(&self) -> u32 {
        self.time
    }
}
<commit_msg>Delete unused file<commit_after><|endoftext|>


<commit_before>//! Miscellaneous functions for use in parview.

use std;
use na;
use kiss3d;
use serde;
use serde_json;
use toml;
use rustc_serialize;

use std::fs::File;
use std::path::Path;
use std::io;
use std::io::{Read,Write};
use std::error::Error;
use rustc_serialize::Decodable;
use rand::random;
use kiss3d::window::Window;
use flate2::read::GzDecoder;

use objects;
use palette;

/// A random Vec3<f32>, with coordinates in (-0.5, 0.5)
pub fn rand_vec() -> na::Vec3<f32> {
    na::Vec3::new(random::<f32>(), random(), random()) - na::Vec3::new(0.5f32, 0.5f32, 0.5f32)
}

/// Inconsolata font
pub fn inconsolata(size: i32) -> std::rc::Rc<kiss3d::text::Font> {
    let inconsolata_otf : &[u8] = include_bytes!("Inconsolata.otf");
    kiss3d::text::Font::from_memory(inconsolata_otf, size)
}

/// Deserialize a function from a `.json` or `.json.gz` file
pub fn deserialize_by_ext<T: serde::Deserialize>(path : &Path) -> Result<T, serde_json::error::Error> {
    let mut buf : io::BufReader<File> = io::BufReader::new(try!(File::open(path)));
    // let f = try!(File::open(path));

    //~ let coded = json::from_reader(&mut buf).unwrap();
    //~ let mut decoder =json::Decoder::new(coded);
    //~ let frames: Vec<Frame> = Decodable::decode(&mut decoder).unwrap();

    let ext : Option<&str> = path.extension().and_then(|s| {s.to_str()});

    let coded = match ext {
        Some("gz") => {
            let mut gzbuf = try!(GzDecoder::new(buf));
            try!(serde_json::de::from_reader(&mut gzbuf))
        },
        _ => {
            try!(serde_json::de::from_reader(&mut buf))
            }
    };
    Ok(coded)
}

/// Generate an example json file
pub fn generate_frame(path : &Path) -> Result<Vec<objects::Frame>, serde_json::error::Error> {
    let spheres = (0..16).map(|n| {
        let loc : na::Vec3<f32> = rand_vec();
        let s : f32 = random();
        let names = objects::ObjectID(vec![
            format!("{}", n / 4 + 1),
            format!("{}", n % 4 + 1)
        ]);
        objects::Sphere{loc:(loc.x, loc.y, loc.z), diameter:s*0.2, names:names}
    }).collect();

    let f = objects::Frame {
        spheres : spheres,
        spherocylinders : vec![],
        text : String::new()
    };

    let mut framevec : Vec<objects::Frame> = vec!();

    for i in (0usize..40usize){
        let mut f2 = objects::Frame {
            spheres : f.spheres.iter().enumerate().map(|(n, ref s)| {
                    let mut newr = s.diameter;
                    if n == 0 {
                        newr = random::<f32>() * 0.2f32;
                    }
                    let (sx, sy, sz) = s.loc;
                    let na::Vec3{x, y, z} = na::Vec3::new(sx, sy, sz) +
                        (rand_vec() * 0.1f32);
                    objects::Sphere {
                        loc: (x, y, z),
                        diameter: newr,
                        names: s.names.clone()
                    }
                }).collect(),

            spherocylinders : vec![],
            text : format!("Frame {} with {} spheres", i, f.spheres.len())
        };

        if i > 10 && i < 20 {
            let l = f2.spheres.len();
            f2.spheres.truncate(l - 8);
            f2.text = format!("Frame {} with {} spheres", i, f2.spheres.len());
        }
        framevec.push(f2);
    }

    let mut file = try!(File::create(&path));

    try!(serde_json::ser::to_writer_pretty(&mut file, &framevec));
    Ok(framevec)
}

/// Write a default palette, as an example to be used when creating a new one
pub fn generate_palette(path : &Path) -> Result<palette::Palette, Box<Error>> {
    let mut file : File = try!(File::create(path));
    let mut default_palette = palette::Palette::default();
    let _ = default_palette.assigned.insert(
        objects::ObjectID(vec!("A".into())),
        palette::Color(255, 0, 0),
    );
    let _ = default_palette.assigned.insert(
        objects::ObjectID(vec!("B".into())),
        palette::Color(0, 255, 0),
    );
    let s : String = toml::encode_str(&default_palette);
    try!(write!(file, "{}", s));
    Ok(default_palette)
}

/// Load from a file, using toml-rs and serialize
pub fn load_toml<T: Decodable>(path : &Path) -> Result<T, Box<Error>> {
    let mut file : File = try!(File::open(path));
    let mut s = String::new();
    let _ = try!(file.read_to_string(&mut s));
    let mut parser = toml::Parser::new(s.as_ref());

    let parsed = parser.parse();
    let values = match parsed {
        Some(v) => v,
        None => {
            // We can unwrap here, becase parser.parse() == None means there were errors
            let err : Box<Error> = parser.errors.pop().unwrap().into();
            return Err(err)
        }
    };
    let table : toml::Value = toml::Value::Table(values);
    let mut decoder = toml::Decoder::new(table);
    let p = try!(rustc_serialize::Decodable::decode(&mut decoder));
    Ok(p)
}

/// Draw a cube in the current window. Cube will be a red skeleton.
pub fn draw_cube(window : &mut Window) -> kiss3d::scene::SceneNode {
    let rotations : Vec<Option<na::Vec3<f32>>> = vec!(
        None, Some(na::Vec3::x()), Some(na::Vec3::z()));
    let translations = vec!((-0.5f32, -0.5),
                            (-0.5,0.5),
                            (0.5, -0.5),
                            (0.5, 0.5));
    let translations : Vec<na::Vec3<f32>> = translations
        .iter()
        .map(|&(x,z)| na::Vec3::new(x,0.0,z))
        .collect();

    let mut cube = window.add_group();
    for rot in &rotations {
        for t in &translations {
            let mut caps = cube.add_capsule(0.01, 1.0);
            caps.append_translation(t);
            match *rot {
                Some(r) => {caps.append_rotation(&(r * std::f32::consts::FRAC_PI_2))},
                None => {}
            }
            //caps.append_translation(&Vec3::new(-0.5, 0.0, -0.5));
        }
    }
    // TODO: this color should be configurable
    cube.set_color(1.0, 0.0, 0.0);

    cube
}

/// Turn an error into a print message.
pub fn err_print(err : &Error) {
    println!("Description: {}", err.description());
    println!("Debug version: {:?}", err);

    if let Some(e) = err.cause() {
        println!("Cause.");
        err_print(e);
    }
}
<commit_msg>clippy: convert unwrap -> expect<commit_after>//! Miscellaneous functions for use in parview.

use std;
use na;
use kiss3d;
use serde;
use serde_json;
use toml;
use rustc_serialize;

use std::fs::File;
use std::path::Path;
use std::io;
use std::io::{Read,Write};
use std::error::Error;
use rustc_serialize::Decodable;
use rand::random;
use kiss3d::window::Window;
use flate2::read::GzDecoder;

use objects;
use palette;

/// A random Vec3<f32>, with coordinates in (-0.5, 0.5)
pub fn rand_vec() -> na::Vec3<f32> {
    na::Vec3::new(random::<f32>(), random(), random()) - na::Vec3::new(0.5f32, 0.5f32, 0.5f32)
}

/// Inconsolata font
pub fn inconsolata(size: i32) -> std::rc::Rc<kiss3d::text::Font> {
    let inconsolata_otf : &[u8] = include_bytes!("Inconsolata.otf");
    kiss3d::text::Font::from_memory(inconsolata_otf, size)
}

/// Deserialize a function from a `.json` or `.json.gz` file
pub fn deserialize_by_ext<T: serde::Deserialize>(path : &Path) -> Result<T, serde_json::error::Error> {
    let mut buf : io::BufReader<File> = io::BufReader::new(try!(File::open(path)));
    // let f = try!(File::open(path));

    //~ let coded = json::from_reader(&mut buf).unwrap();
    //~ let mut decoder =json::Decoder::new(coded);
    //~ let frames: Vec<Frame> = Decodable::decode(&mut decoder).unwrap();

    let ext : Option<&str> = path.extension().and_then(|s| {s.to_str()});

    let coded = match ext {
        Some("gz") => {
            let mut gzbuf = try!(GzDecoder::new(buf));
            try!(serde_json::de::from_reader(&mut gzbuf))
        },
        _ => {
            try!(serde_json::de::from_reader(&mut buf))
            }
    };
    Ok(coded)
}

/// Generate an example json file
pub fn generate_frame(path : &Path) -> Result<Vec<objects::Frame>, serde_json::error::Error> {
    let spheres = (0..16).map(|n| {
        let loc : na::Vec3<f32> = rand_vec();
        let s : f32 = random();
        let names = objects::ObjectID(vec![
            format!("{}", n / 4 + 1),
            format!("{}", n % 4 + 1)
        ]);
        objects::Sphere{loc:(loc.x, loc.y, loc.z), diameter:s*0.2, names:names}
    }).collect();

    let f = objects::Frame {
        spheres : spheres,
        spherocylinders : vec![],
        text : String::new()
    };

    let mut framevec : Vec<objects::Frame> = vec!();

    for i in (0usize..40usize){
        let mut f2 = objects::Frame {
            spheres : f.spheres.iter().enumerate().map(|(n, ref s)| {
                    let mut newr = s.diameter;
                    if n == 0 {
                        newr = random::<f32>() * 0.2f32;
                    }
                    let (sx, sy, sz) = s.loc;
                    let na::Vec3{x, y, z} = na::Vec3::new(sx, sy, sz) +
                        (rand_vec() * 0.1f32);
                    objects::Sphere {
                        loc: (x, y, z),
                        diameter: newr,
                        names: s.names.clone()
                    }
                }).collect(),

            spherocylinders : vec![],
            text : format!("Frame {} with {} spheres", i, f.spheres.len())
        };

        if i > 10 && i < 20 {
            let l = f2.spheres.len();
            f2.spheres.truncate(l - 8);
            f2.text = format!("Frame {} with {} spheres", i, f2.spheres.len());
        }
        framevec.push(f2);
    }

    let mut file = try!(File::create(&path));

    try!(serde_json::ser::to_writer_pretty(&mut file, &framevec));
    Ok(framevec)
}

/// Write a default palette, as an example to be used when creating a new one
pub fn generate_palette(path : &Path) -> Result<palette::Palette, Box<Error>> {
    let mut file : File = try!(File::create(path));
    let mut default_palette = palette::Palette::default();
    let _ = default_palette.assigned.insert(
        objects::ObjectID(vec!("A".into())),
        palette::Color(255, 0, 0),
    );
    let _ = default_palette.assigned.insert(
        objects::ObjectID(vec!("B".into())),
        palette::Color(0, 255, 0),
    );
    let s : String = toml::encode_str(&default_palette);
    try!(write!(file, "{}", s));
    Ok(default_palette)
}

/// Load from a file, using toml-rs and serialize
pub fn load_toml<T: Decodable>(path : &Path) -> Result<T, Box<Error>> {
    let mut file : File = try!(File::open(path));
    let mut s = String::new();
    let _ = try!(file.read_to_string(&mut s));
    let mut parser = toml::Parser::new(s.as_ref());

    let parsed = parser.parse();
    let values = match parsed {
        Some(v) => v,
        None => {
            // We can unwrap here, becase parser.parse() == None means there were errors
            let err : Box<Error> = parser.errors.pop().expect("Toml parser failed, yet provided no error. Unsure how to proceed.").into();
            return Err(err)
        }
    };
    let table : toml::Value = toml::Value::Table(values);
    let mut decoder = toml::Decoder::new(table);
    let p = try!(rustc_serialize::Decodable::decode(&mut decoder));
    Ok(p)
}

/// Draw a cube in the current window. Cube will be a red skeleton.
pub fn draw_cube(window : &mut Window) -> kiss3d::scene::SceneNode {
    let rotations : Vec<Option<na::Vec3<f32>>> = vec!(
        None, Some(na::Vec3::x()), Some(na::Vec3::z()));
    let translations = vec!((-0.5f32, -0.5),
                            (-0.5,0.5),
                            (0.5, -0.5),
                            (0.5, 0.5));
    let translations : Vec<na::Vec3<f32>> = translations
        .iter()
        .map(|&(x,z)| na::Vec3::new(x,0.0,z))
        .collect();

    let mut cube = window.add_group();
    for rot in &rotations {
        for t in &translations {
            let mut caps = cube.add_capsule(0.01, 1.0);
            caps.append_translation(t);
            match *rot {
                Some(r) => {caps.append_rotation(&(r * std::f32::consts::FRAC_PI_2))},
                None => {}
            }
            //caps.append_translation(&Vec3::new(-0.5, 0.0, -0.5));
        }
    }
    // TODO: this color should be configurable
    cube.set_color(1.0, 0.0, 0.0);

    cube
}

/// Turn an error into a print message.
pub fn err_print(err : &Error) {
    println!("Description: {}", err.description());
    println!("Debug version: {:?}", err);

    if let Some(e) = err.cause() {
        println!("Cause.");
        err_print(e);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::cmp::{max, min};
use std::iter;
use std::fmt;
use std::num;
use std::num::{Bounded, Zero};

/// An index type to be used by a `Range`
pub trait RangeIndex: Copy
                    + Clone
                    + fmt::Show
                    + Eq
                    + Ord
                    + TotalEq
                    + TotalOrd
                    + Add<Self, Self>
                    + Sub<Self, Self>
                    + Neg<Self>
                    + Zero {}

pub trait IntRangeIndex<T>: RangeIndex + Copy {
    fn new(x: T) -> Self;
    fn get(self) -> T;
}

impl RangeIndex for int {}

impl IntRangeIndex<int> for int {
    #[inline]
    fn new(x: int) -> int { x }

    #[inline]
    fn get(self) -> int { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self:ident($T:ty)) => (
        #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Show, Zero)]
        $(#[$attr])*
        pub struct $Self(pub $T);

        impl $Self {
            #[inline]
            pub fn to_uint(self) -> uint {
                self.get() as uint
            }
        }

        impl RangeIndex for $Self {}

        impl IntRangeIndex<$T> for $Self  {
            #[inline]
            fn new(x: $T) -> $Self {
                $Self(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self(x) => x }
            }
        }

        impl Add<$Self, $Self> for $Self {
            #[inline]
            fn add(&self, other: &$Self) -> $Self {
                $Self(self.get() + other.get())
            }
        }

        impl Sub<$Self, $Self> for $Self {
            #[inline]
            fn sub(&self, other: &$Self) -> $Self {
                $Self(self.get() - other.get())
            }
        }

        impl Neg<$Self> for $Self {
            #[inline]
            fn neg(&self) -> $Self {
                $Self(-self.get())
            }
        }
    )
}

#[deriving(Show)]
pub enum RangeRelation<I> {
    OverlapsBegin(/* overlap */ I),
    OverlapsEnd(/* overlap */ I),
    ContainedBy,
    Contains,
    Coincides,
    EntirelyBefore,
    EntirelyAfter
}

/// A range of indices
#[deriving(Clone)]
pub struct Range<I> {
    off: I,
    len: I,
}

impl<I: RangeIndex> fmt::Show for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f.buf, "[{} .. {})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<T, I> {
    it: iter::Range<T>,
}

pub fn each_index<T: Int, I: IntRangeIndex<T>>(start: I, stop: I) -> EachIndex<T, I> {
    EachIndex { it: iter::range(start.get(), stop.get()) }
}

impl<T: Int, I: IntRangeIndex<T>> Iterator<I> for EachIndex<T, I> {
    #[inline]
    fn next(&mut self) -> Option<I> {
        self.it.next().map(|i| IntRangeIndex::new(i))
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        self.it.size_hint()
    }
}

impl<I: RangeIndex> Range<I> {
    #[inline]
    pub fn new(off: I, len: I) -> Range<I> {
        Range { off: off, len: len }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(num::zero(), num::zero())
    }

    #[inline]
    pub fn begin(&self) -> I { self.off  }
    #[inline]
    pub fn length(&self) -> I { self.len }
    #[inline]
    pub fn end(&self) -> I { self.off + self.len }

    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len.is_zero()
    }

    #[inline]
    pub fn shift_by(&mut self, i: I) {
        self.off = self.off + i;
    }

    #[inline]
    pub fn extend_by(&mut self, i: I) {
        self.len = self.len + i;
    }

    #[inline]
    pub fn extend_to(&mut self, i: I) {
        self.len = i - self.off;
    }

    #[inline]
    pub fn adjust_by(&mut self, off_i: I, len_i: I) {
        self.off = self.off + off_i;
        self.len = self.len + len_i;
    }

    #[inline]
    pub fn reset(&mut self, off_i: I, len_i: I) {
        self.off = off_i;
        self.len = len_i;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }

    /// Computes the relationship between two ranges (`self` and `other`),
    /// from the point of view of `self`. So, 'EntirelyBefore' means
    /// that the `self` range is entirely before `other` range.
    #[inline]
    pub fn relation_to_range(&self, other: &Range<I>) -> RangeRelation<I> {
        if other.begin() > self.end() {
            return EntirelyBefore;
        }
        if self.begin() > other.end() {
            return EntirelyAfter;
        }
        if self.begin() == other.begin() && self.end() == other.end() {
            return Coincides;
        }
        if self.begin() <= other.begin() && self.end() >= other.end() {
            return Contains;
        }
        if self.begin() >= other.begin() && self.end() <= other.end() {
            return ContainedBy;
        }
        if self.begin() < other.begin() && self.end() < other.end() {
            let overlap = self.end() - other.begin();
            return OverlapsBegin(overlap);
        }
        if self.begin() > other.begin() && self.end() > other.end() {
            let overlap = other.end() - self.begin();
            return OverlapsEnd(overlap);
        }
        fail!("relation_to_range(): didn't classify self={}, other={}",
              self, other);
    }
}

/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: IntRangeIndex<T>> Range<I> {
    #[inline]
    pub fn each_index(&self) -> EachIndex<T, I> {
        each_index(self.off, self.off + self.len)
    }

    #[inline]
    pub fn is_valid_for_string(&self, s: &str) -> bool {
        let s_len = s.len();
        match num::cast::<uint, T>(s_len) {
            Some(len) => {
                let len = IntRangeIndex::new(len);
                self.begin() < len
                && self.end() <= len
                && self.length() <= len
            },
            None => {
                debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the \
                        max value for the range index (max={})", s_len,
                        {
                            let max: T = Bounded::max_value();
                            let val: I = IntRangeIndex::new(max);
                            val
                        });
                false
            },
        }
    }

    #[inline]
    pub fn repair_after_coalesced_range(&mut self, other: &Range<I>) {
        let relation = self.relation_to_range(other);
        debug!("repair_after_coalesced_range: possibly repairing range {}", *self);
        debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}",
               *other, relation);
        let _1: I = IntRangeIndex::new(num::one::<T>());
        match relation {
            EntirelyBefore => {},
            EntirelyAfter => { self.shift_by(-other.length()); },
            Coincides | ContainedBy => { self.reset(other.begin(), _1); },
            Contains => { self.extend_by(-other.length()); },
            OverlapsBegin(overlap) => { self.extend_by(_1 - overlap); },
            OverlapsEnd(overlap) => {
                let len = self.length() - overlap + _1;
                self.reset(other.begin(), len);
            }
        };
        debug!("repair_after_coalesced_range: new range: ---- {}", *self);
    }
}
<commit_msg>Improve Range method documentation and field and parameter names<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::cmp::{max, min};
use std::iter;
use std::fmt;
use std::num;
use std::num::{Bounded, Zero};

/// An index type to be used by a `Range`
pub trait RangeIndex: Copy
                    + Clone
                    + fmt::Show
                    + Eq
                    + Ord
                    + TotalEq
                    + TotalOrd
                    + Add<Self, Self>
                    + Sub<Self, Self>
                    + Neg<Self>
                    + Zero {}

pub trait IntRangeIndex<T>: RangeIndex + Copy {
    fn new(x: T) -> Self;
    fn get(self) -> T;
}

impl RangeIndex for int {}

impl IntRangeIndex<int> for int {
    #[inline]
    fn new(x: int) -> int { x }

    #[inline]
    fn get(self) -> int { self }
}

/// Implements a range index type with operator overloads
#[macro_export]
macro_rules! int_range_index {
    ($(#[$attr:meta])* struct $Self:ident($T:ty)) => (
        #[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Show, Zero)]
        $(#[$attr])*
        pub struct $Self(pub $T);

        impl $Self {
            #[inline]
            pub fn to_uint(self) -> uint {
                self.get() as uint
            }
        }

        impl RangeIndex for $Self {}

        impl IntRangeIndex<$T> for $Self  {
            #[inline]
            fn new(x: $T) -> $Self {
                $Self(x)
            }

            #[inline]
            fn get(self) -> $T {
                match self { $Self(x) => x }
            }
        }

        impl Add<$Self, $Self> for $Self {
            #[inline]
            fn add(&self, other: &$Self) -> $Self {
                $Self(self.get() + other.get())
            }
        }

        impl Sub<$Self, $Self> for $Self {
            #[inline]
            fn sub(&self, other: &$Self) -> $Self {
                $Self(self.get() - other.get())
            }
        }

        impl Neg<$Self> for $Self {
            #[inline]
            fn neg(&self) -> $Self {
                $Self(-self.get())
            }
        }
    )
}

#[deriving(Show)]
pub enum RangeRelation<I> {
    OverlapsBegin(/* overlap */ I),
    OverlapsEnd(/* overlap */ I),
    ContainedBy,
    Contains,
    Coincides,
    EntirelyBefore,
    EntirelyAfter
}

/// A range of indices
#[deriving(Clone)]
pub struct Range<I> {
    begin: I,
    length: I,
}

impl<I: RangeIndex> fmt::Show for Range<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f.buf, "[{} .. {})", self.begin(), self.end())
    }
}

/// An iterator over each index in a range
pub struct EachIndex<T, I> {
    it: iter::Range<T>,
}

pub fn each_index<T: Int, I: IntRangeIndex<T>>(start: I, stop: I) -> EachIndex<T, I> {
    EachIndex { it: iter::range(start.get(), stop.get()) }
}

impl<T: Int, I: IntRangeIndex<T>> Iterator<I> for EachIndex<T, I> {
    #[inline]
    fn next(&mut self) -> Option<I> {
        self.it.next().map(|i| IntRangeIndex::new(i))
    }

    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        self.it.size_hint()
    }
}

impl<I: RangeIndex> Range<I> {
    /// Create a new range from beginning and length offsets. This could be
    /// denoted as `[begin, begin + length)`.
    ///
    /// ~~~
    ///    |-- begin ->|-- length ->|
    ///    |           |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn new(begin: I, length: I) -> Range<I> {
        Range { begin: begin, length: length }
    }

    #[inline]
    pub fn empty() -> Range<I> {
        Range::new(num::zero(), num::zero())
    }

    /// The index offset to the beginning of the range.
    ///
    /// ~~~
    ///    |-- begin ->|
    ///    |           |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn begin(&self) -> I { self.begin  }

    /// The index offset from the beginning to the end of the range.
    ///
    /// ~~~
    ///                |-- length ->|
    ///                |            |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn length(&self) -> I { self.length }

    /// The index offset to the end of the range.
    ///
    /// ~~~
    ///    |--------- end --------->|
    ///    |                        |
    /// <- o - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn end(&self) -> I { self.begin + self.length }

    /// `true` if the index is between the beginning and the end of the range.
    ///
    /// ~~~
    ///        false        true      false
    ///          |           |          |
    /// <- o - - + - - +=====+======+ - + - ->
    /// ~~~
    #[inline]
    pub fn contains(&self, i: I) -> bool {
        i >= self.begin() && i < self.end()
    }

    /// `true` if the offset from the beginning to the end of the range is zero.
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.length().is_zero()
    }

    /// Shift the entire range by the supplied index delta.
    ///
    /// ~~~
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - +============+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - - - +============+ - - - ->
    /// ~~~
    #[inline]
    pub fn shift_by(&mut self, delta: I) {
        self.begin = self.begin + delta;
    }

    /// Extend the end of the range by the supplied index delta.
    ///
    /// ~~~
    ///                     |-- delta ->|
    ///                     |           |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_by(&mut self, delta: I) {
        self.length = self.length + delta;
    }

    /// Move the end of the range to the target index.
    ///
    /// ~~~
    ///                               target
    ///                                 |
    /// <- o - - - - - +====+ - - - - - | - - - ->
    ///                                 |
    /// <- o - - - - - +================+ - - - ->
    /// ~~~
    #[inline]
    pub fn extend_to(&mut self, target: I) {
        self.length = target - self.begin;
    }

    /// Adjust the beginning offset and the length by the supplied deltas.
    #[inline]
    pub fn adjust_by(&mut self, begin_delta: I, length_delta: I) {
        self.begin = self.begin + begin_delta;
        self.length = self.length + length_delta;
    }

    /// Set the begin and length values.
    #[inline]
    pub fn reset(&mut self, begin: I, length: I) {
        self.begin = begin;
        self.length = length;
    }

    #[inline]
    pub fn intersect(&self, other: &Range<I>) -> Range<I> {
        let begin = max(self.begin(), other.begin());
        let end = min(self.end(), other.end());

        if end < begin {
            Range::empty()
        } else {
            Range::new(begin, end - begin)
        }
    }

    /// Computes the relationship between two ranges (`self` and `other`),
    /// from the point of view of `self`. So, 'EntirelyBefore' means
    /// that the `self` range is entirely before `other` range.
    #[inline]
    pub fn relation_to_range(&self, other: &Range<I>) -> RangeRelation<I> {
        if other.begin() > self.end() {
            return EntirelyBefore;
        }
        if self.begin() > other.end() {
            return EntirelyAfter;
        }
        if self.begin() == other.begin() && self.end() == other.end() {
            return Coincides;
        }
        if self.begin() <= other.begin() && self.end() >= other.end() {
            return Contains;
        }
        if self.begin() >= other.begin() && self.end() <= other.end() {
            return ContainedBy;
        }
        if self.begin() < other.begin() && self.end() < other.end() {
            let overlap = self.end() - other.begin();
            return OverlapsBegin(overlap);
        }
        if self.begin() > other.begin() && self.end() > other.end() {
            let overlap = other.end() - self.begin();
            return OverlapsEnd(overlap);
        }
        fail!("relation_to_range(): didn't classify self={}, other={}",
              self, other);
    }
}

/// Methods for `Range`s with indices based on integer values
impl<T: Int, I: IntRangeIndex<T>> Range<I> {
    /// Returns an iterater that increments over `[begin, end)`.
    #[inline]
    pub fn each_index(&self) -> EachIndex<T, I> {
        each_index(self.begin(), self.end())
    }

    #[inline]
    pub fn is_valid_for_string(&self, s: &str) -> bool {
        let s_len = s.len();
        match num::cast::<uint, T>(s_len) {
            Some(len) => {
                let len = IntRangeIndex::new(len);
                self.begin() < len
                && self.end() <= len
                && self.length() <= len
            },
            None => {
                debug!("Range<T>::is_valid_for_string: string length (len={}) is longer than the \
                        max value for the range index (max={})", s_len,
                        {
                            let max: T = Bounded::max_value();
                            let val: I = IntRangeIndex::new(max);
                            val
                        });
                false
            },
        }
    }

    #[inline]
    pub fn repair_after_coalesced_range(&mut self, other: &Range<I>) {
        let relation = self.relation_to_range(other);
        debug!("repair_after_coalesced_range: possibly repairing range {}", *self);
        debug!("repair_after_coalesced_range: relation of original range and coalesced range {}: {}",
               *other, relation);
        let _1: I = IntRangeIndex::new(num::one::<T>());
        match relation {
            EntirelyBefore => {},
            EntirelyAfter => { self.shift_by(-other.length()); },
            Coincides | ContainedBy => { self.reset(other.begin(), _1); },
            Contains => { self.extend_by(-other.length()); },
            OverlapsBegin(overlap) => { self.extend_by(_1 - overlap); },
            OverlapsEnd(overlap) => {
                let len = self.length() - overlap + _1;
                self.reset(other.begin(), len);
            }
        };
        debug!("repair_after_coalesced_range: new range: ---- {}", *self);
    }
}
<|endoftext|>