<commit_before>use std::fs::File;
use std::io::Read;
use std::env;
use std::path::{Path,PathBuf};
use util::{path_exists, is_dir};
use std::fs::{read_dir};
use toml;

// otry is 'option try'
macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

// converts errors into None
macro_rules! otry2 {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return None } })
}

// converts errors into message + empty vec
macro_rules! vectry {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return Vec::new() } })
}

/// Gets the branch from a git source string if one is present.
fn get_branch_from_source(source: &str) -> Option<&str> {
    debug!("get_branch_from_source - Finding branch from {:?}", source);
    match source.find("branch=") {
        Some(idx) => {
            let (_start, branch) = source.split_at(idx+7);
            match branch.find("#") {
                Some(idx) => {
                    let (branch, _end) = branch.split_at(idx);
                    Some(branch)
                },
                None => Some(branch),
            }
        },
        None => None
    }
}

#[test]
fn gets_branch_from_git_source_with_hash() {
    let source = "git+https://github.com/phildawes/racer.git?branch=dev#9e04f91f0426c1cf8ec5e5023f74d7261f5a9dd1".to_owned();
    let branch = get_branch_from_source(&source);
    assert_eq!(branch, Some("dev"));
}

#[test]
fn gets_branch_from_git_source_without_hash() {
    let source = "git+https://github.com/phildawes/racer.git?branch=dev".to_owned();
    let branch = get_branch_from_source(&source);
    assert_eq!(branch, Some("dev"));
}

#[test]
fn empty_if_no_branch() {
    let source = "git+https://github.com/phildawes/racer.git#9e04f91f0426c1cf8ec5e5023f74d7261f5a9dd1".to_owned();
    let branch = get_branch_from_source(&source);
    assert_eq!(branch, None);
}

fn find_src_via_lockfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let lock_table = parser.parse().unwrap();

    debug!("find_src_via_lockfile found lock table {:?}", lock_table);

    let t = match lock_table.get("package") {
        Some(&toml::Value::Array(ref t1)) => t1,
        _ => return None
    };

    for item in t {
        if let toml::Value::Table(ref t) = *item {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                if name.replace("-", "_") == kratename {
                    debug!("found matching crate {:?}", t);
                    let version = otry!(getstr(t, "version"));
                    let source = otry!(getstr(t, "source"));

                    if Some("registry") == source.split("+").nth(0) {
                        return get_versioned_cratefile(name, &version, cargofile);
                    } else if Some("git") == source.split("+").nth(0) {
                        let sha1 = otry!(source.split("#").last());
                        let mut d = otry!(get_cargo_rootdir(cargofile));
                        let branch = get_branch_from_source(&source);
                        d.push("git");
                        d.push("checkouts");
                        d = otry!(find_git_src_dir(d, name, &sha1, branch));
                        d.push("src");
                        d.push("lib.rs");
                        return Some(d);
                    }
                }
            }
        }
    }
    None
}

fn get_cargo_rootdir(cargofile: &Path) -> Option<PathBuf> {
    debug!("get_cargo_rootdir. {:?}",cargofile);
    match env::var_os("CARGO_HOME") {
        Some(cargohome) =>
        {
            debug!("get_cargo_rootdir. CARGO_HOME is set: {:?}",cargohome);
            let d = PathBuf::from(cargohome);
            if path_exists(&d) {
                return Some(d)
            } else {
                return None
            };
        },
        None => ()
    };

    let mut d = otry!(env::home_dir());

    // try multirust first, since people with multirust installed will often still
    // have an old .cargo directory lying around
    d.push(".multirust");

    d.push("overrides");
    debug!("get_cargo_rootdir: looking for overrides file. {:?}", d);
    if let Ok(mut multirust_overides) = File::open(&d) {
        debug!("get_cargo_rootdir: found overrides file! {:?}", d);
        let mut s = String::new();
        otry2!(multirust_overides.read_to_string(&mut s));
        for line in s.lines() {
            let overridepath = line.split(";").nth(0).unwrap();
            if cargofile.starts_with(overridepath) {
                let overridepath = line.split(";").nth(1).unwrap();
                d.pop();
                d.push("toolchains");
                d.push(overridepath.trim());
                d.push("cargo");
                debug!("get_cargo_rootdir override root is {:?}",d);
                return Some(d)
            }
        }
    }

    d.pop();
    d.push("default");
    if let Ok(mut multirustdefault) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirustdefault.read_to_string(&mut s));
        d.pop();
        d.push("toolchains");
        d.push(s.trim());
        d.push("cargo");
        debug!("get_cargo_rootdir root is {:?}",d);
        return Some(d)
    }

    d.pop();
    d.pop();
    d.push(".cargo");
    if path_exists(&d) {
        Some(d)
    } else {
        None
    }
}

fn get_versioned_cratefile(kratename: &str, version: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut d = otry!(get_cargo_rootdir(cargofile));

    debug!("get_versioned_cratefile: cargo rootdir is {:?}",d);
    d.push("registry");
    d.push("src");

    for mut d in find_cratesio_src_dirs(d) {

        // if version=* then search for the first matching folder
        if version == "*" {
            use std::fs::read_dir;
            let mut start_path = d.clone();
            start_path.push(kratename);
            let start_name = start_path.to_str().unwrap();

            if let Ok(reader) = read_dir(d) {
                if let Some(path) = reader
                    .map(|entry| entry.unwrap().path())
                    .find(|path| path.to_str().unwrap().starts_with(start_name)) {
                        d = path.clone();
                    } else {
                        continue;
                    }
            } else {
                continue;
            }
        } else {
            d.push(kratename.to_owned() + "-" + &version);
        }

        d.push("src");
        debug!("crate path {:?}",d);

        // First, check for package name at root (src/kratename/lib.rs)
        d.push(kratename);
        d.push("lib.rs");
        if let Err(_) = File::open(&d) {
            // It doesn't exist, so assume src/lib.rs
            d.pop();
            d.pop();
            d.push("lib.rs");
        }
        debug!("crate path with lib.rs {:?}",d);

        if let Err(_) = File::open(&d) {
            // It doesn't exist, so try /lib.rs
            d.pop();
            d.pop();
            d.push("lib.rs");
        }

        if let Err(_) = File::open(&d) {
            continue;
        }

        return Some(d)
    }
    None
 }

fn find_src_via_tomlfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    // only look for 'path' references here.
    // We find the git and crates.io stuff via the lockfile

    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = otry!(parser.parse());

    // is it this lib?  (e.g. you're searching from tests to find the main library crate)
    {
        let package_name = if let Some(&toml::Value::Table(ref t)) = table.get("package") {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                name
            } else {
                // it's invalid for a package to be nameless anyway
                return None;
            }
        } else {
            return None;
        };

        let mut lib_name = package_name;
        let mut lib_path = otry!(cargofile.parent()).join("src").join("lib.rs");
        if let Some(&toml::Value::Table(ref t)) = table.get("lib") {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                lib_name = name;
            }
            if let Some(&toml::Value::String(ref pathstr)) = t.get("path") {
                let p = Path::new(pathstr);
                lib_path = otry!(cargofile.parent()).join(p);
            }
        }

        if lib_name == kratename {
            debug!("found {} as lib entry in Cargo.toml", kratename);
            if ::std::fs::metadata(&lib_path).ok().map(|m| m.is_file()).unwrap_or(false) {
                return Some(lib_path);
            }
        }
    }

    // otherwise search the dependencies
    let t = match table.get("dependencies") {
        Some(&toml::Value::Table(ref t)) => t,
        _ => return None
    };

    let mut name = kratename;
    let value = if kratename.contains('_') {
        t.iter().find(|&(k, _)| k.replace("-", "_") == name).map(|(k,v)| {
            name = k;
            v
        })
    } else {
        t.get(kratename)
    };

    match value {
        Some(&toml::Value::Table(ref t)) => {
            // local directory
            let relative_path = otry!(getstr(t, "path"));
            Some(otry!(cargofile.parent())
                 .join(relative_path)
                 .join("src")
                 .join("lib.rs"))
        },
        Some(&toml::Value::String(ref version)) => {
            // versioned crate
            get_versioned_cratefile(name, version, cargofile)
        }
        _ => None
    }
}

fn find_cratesio_src_dirs(d: PathBuf) -> Vec<PathBuf> {
    let mut out = Vec::new();
    for entry in vectry!(read_dir(d)) {
        let path = vectry!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with("github.com-") {
                    out.push(path.clone());
                }
            }
        }
    }
    out
}

fn find_git_src_dir(d: PathBuf, name: &str, sha1: &str, branch: Option<&str>) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with(name) {
                    let mut d = path.clone();

                    // dirname can be the sha1 or master.
                    d.push(sha1);

                    if !is_dir(d.as_path()) && branch.is_some() {
                        d.pop();
                        d.push(branch.unwrap());
                    }

                    if !is_dir(d.as_path()) {
                        d.pop();
                        d.push("master");
                    }

                    let retval = d.clone();

                    // check that the checkout matches the commit sha1
                    d.push(".git");
                    d.push("refs");
                    d.push("heads");
                    d.push("master");

                    let mut headref = String::new();
                    otry2!(otry2!(File::open(d)).read_to_string(&mut headref));

                    debug!("git headref is {:?}", headref);

                    if headref.ends_with("\n") {
                        headref.pop();
                    }

                    if sha1 == headref {
                        return Some(retval);
                    }
                }
            }
        }
    }
    None
}

fn getstr(t: &toml::Table, k: &str) -> Option<String> {
    match t.get(k) {
        Some(&toml::Value::String(ref s)) => Some(s.clone()),
        _ => None
    }
}

fn find_cargo_tomlfile(currentfile: &Path) -> Option<PathBuf> {
    let mut f = currentfile.to_path_buf();
    f.push("Cargo.toml");
    if path_exists(f.as_path()) {
        Some(f)
    } else {
        if f.pop() && f.pop() {
            find_cargo_tomlfile(&f)
        } else {
            None
        }
    }
}

pub fn get_crate_file(kratename: &str, from_path: &Path) -> Option<PathBuf> {
    if let Some(tomlfile) = find_cargo_tomlfile(from_path) {
        // look in the lockfile first, if there is one
        debug!("get_crate_file tomlfile is {:?}", tomlfile);
        let mut lockfile = tomlfile.clone();
        lockfile.pop();
        lockfile.push("Cargo.lock");
        if path_exists(lockfile.as_path()) {
            if let Some(f) = find_src_via_lockfile(kratename, &lockfile) {
                return Some(f);
            }
        }

        // oh, no luck with the lockfile. Try the tomlfile
        return find_src_via_tomlfile(kratename, &tomlfile)
    }
    None
}
<commit_msg>package reading<commit_after>use std::fs::File;
use std::io::Read;
use std::env;
use std::path::{Path,PathBuf};
use std::collections::BTreeMap;
use util::{path_exists, is_dir};
use std::fs::{read_dir};
use toml;

#[derive(Debug)]
struct PackageInfo {
    name: String,
    version: String,
    source: Option<PathBuf>
}

// otry is 'option try'
macro_rules! otry {
    ($e:expr) => (match $e { Some(e) => e, None => return None })
}

// converts errors into None
macro_rules! otry2 {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return None } })
}

// converts errors into message + empty vec
macro_rules! vectry {
    ($e:expr) => (match $e { Ok(e) => e, Err(e) => { error!("ERROR!: {:?} {} {}", e, file!(), line!()); return Vec::new() } })
}

/// Gets the branch from a git source string if one is present.
fn get_branch_from_source(source: &str) -> Option<&str> {
    debug!("get_branch_from_source - Finding branch from {:?}", source);
    match source.find("branch=") {
        Some(idx) => {
            let (_start, branch) = source.split_at(idx+7);
            match branch.find("#") {
                Some(idx) => {
                    let (branch, _end) = branch.split_at(idx);
                    Some(branch)
                },
                None => Some(branch),
            }
        },
        None => None
    }
}

#[test]
fn gets_branch_from_git_source_with_hash() {
    let source = "git+https://github.com/phildawes/racer.git?branch=dev#9e04f91f0426c1cf8ec5e5023f74d7261f5a9dd1".to_owned();
    let branch = get_branch_from_source(&source);
    assert_eq!(branch, Some("dev"));
}

#[test]
fn gets_branch_from_git_source_without_hash() {
    let source = "git+https://github.com/phildawes/racer.git?branch=dev".to_owned();
    let branch = get_branch_from_source(&source);
    assert_eq!(branch, Some("dev"));
}

#[test]
fn empty_if_no_branch() {
    let source = "git+https://github.com/phildawes/racer.git#9e04f91f0426c1cf8ec5e5023f74d7261f5a9dd1".to_owned();
    let branch = get_branch_from_source(&source);
    assert_eq!(branch, None);
}

fn find_src_via_lockfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    if let Some(packages) = get_cargo_packages(cargofile) {
        for package in packages {
            if let Some(package_source) = package.source.clone() {
                if let Some(tomlfile) = find_cargo_tomlfile(package_source.as_path()) {
                    let package_name = get_package_name(tomlfile.as_path());

                    debug!("find_src_via_lockfile package_name: {}", package_name);

                    if package_name == kratename {
                        return package.source;
                    }
                }
            }
        }
    }

    None
}

fn parse_toml_file(toml_file: &Path) -> Option<BTreeMap<String, toml::Value>> {
    let mut file = otry2!(File::open(toml_file));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);

    parser.parse()
}

fn get_cargo_packages(cargofile: &Path) -> Option<Vec<PackageInfo>> {
    let lock_table = parse_toml_file(cargofile).unwrap();

    debug!("get_cargo_packages found lock_table {:?}", lock_table);

    let packages_array = match lock_table.get("package") {
        Some(&toml::Value::Array(ref t1)) => t1,
        _ => return None
    };

    let mut result = Vec::new();

    for package_element in packages_array {
        if let &toml::Value::Table(ref package_table) = package_element {
            if let Some(&toml::Value::String(ref package_name)) = package_table.get("name") {
                let package_version = otry!(getstr(package_table, "version"));
                let package_source = otry!(getstr(package_table, "source"));

                let package_source = match package_source.split("+").nth(0) {
                    Some("registry") => {
                        get_versioned_cratefile(package_name, &package_version, cargofile)
                    },
                    Some("git") => {
                        let sha1 = otry!(package_source.split("#").last());
                        let mut d = otry!(get_cargo_rootdir(cargofile));
                        let branch = get_branch_from_source(&package_source);
                        d.push("git");
                        d.push("checkouts");
                        d = otry!(find_git_src_dir(d, package_name, &sha1, branch));
                        d.push("src");
                        d.push("lib.rs");

                        Some(d)
                    },
                    _ => return None
                };

                result.push(PackageInfo{
                    name: package_name.to_owned(),
                    version: package_version,
                    source: package_source
                });
            }
        }
    }

    Some(result)
}

fn get_package_name(cargofile: &Path) -> String {
    let lock_table = parse_toml_file(cargofile).unwrap();

    debug!("get_package_name found lock_table {:?}", lock_table);

    let mut name = String::new();

    if let Some(&toml::Value::Table(ref lib_table)) = lock_table.get("lib") {
        if let Some(&toml::Value::String(ref package_name)) = lib_table.get("name") {
            name.push_str(package_name);
            return name;
        }
    }

    if let Some(&toml::Value::Table(ref package_table)) = lock_table.get("package") {
        if let Some(&toml::Value::String(ref package_name)) = package_table.get("name") {
            name.push_str(package_name);
        }
    }

    name
}

fn get_cargo_rootdir(cargofile: &Path) -> Option<PathBuf> {
    debug!("get_cargo_rootdir. {:?}",cargofile);
    match env::var_os("CARGO_HOME") {
        Some(cargohome) =>
        {
            debug!("get_cargo_rootdir. CARGO_HOME is set: {:?}",cargohome);
            let d = PathBuf::from(cargohome);
            if path_exists(&d) {
                return Some(d)
            } else {
                return None
            };
        },
        None => ()
    };

    let mut d = otry!(env::home_dir());

    // try multirust first, since people with multirust installed will often still
    // have an old .cargo directory lying around
    d.push(".multirust");

    d.push("overrides");
    debug!("get_cargo_rootdir: looking for overrides file. {:?}", d);
    if let Ok(mut multirust_overides) = File::open(&d) {
        debug!("get_cargo_rootdir: found overrides file! {:?}", d);
        let mut s = String::new();
        otry2!(multirust_overides.read_to_string(&mut s));
        for line in s.lines() {
            let overridepath = line.split(";").nth(0).unwrap();
            if cargofile.starts_with(overridepath) {
                let overridepath = line.split(";").nth(1).unwrap();
                d.pop();
                d.push("toolchains");
                d.push(overridepath.trim());
                d.push("cargo");
                debug!("get_cargo_rootdir override root is {:?}",d);
                return Some(d)
            }
        }
    }

    d.pop();
    d.push("default");
    if let Ok(mut multirustdefault) = File::open(&d) {
        let mut s = String::new();
        otry2!(multirustdefault.read_to_string(&mut s));
        d.pop();
        d.push("toolchains");
        d.push(s.trim());
        d.push("cargo");
        debug!("get_cargo_rootdir root is {:?}",d);
        return Some(d)
    }

    d.pop();
    d.pop();
    d.push(".cargo");
    if path_exists(&d) {
        Some(d)
    } else {
        None
    }
}

fn get_versioned_cratefile(kratename: &str, version: &str, cargofile: &Path) -> Option<PathBuf> {
    let mut d = otry!(get_cargo_rootdir(cargofile));

    debug!("get_versioned_cratefile: cargo rootdir is {:?}",d);
    d.push("registry");
    d.push("src");

    for mut d in find_cratesio_src_dirs(d) {

        // if version=* then search for the first matching folder
        if version == "*" {
            use std::fs::read_dir;
            let mut start_path = d.clone();
            start_path.push(kratename);
            let start_name = start_path.to_str().unwrap();

            if let Ok(reader) = read_dir(d) {
                if let Some(path) = reader
                    .map(|entry| entry.unwrap().path())
                    .find(|path| path.to_str().unwrap().starts_with(start_name)) {
                        d = path.clone();
                    } else {
                        continue;
                    }
            } else {
                continue;
            }
        } else {
            d.push(kratename.to_owned() + "-" + &version);
        }

        d.push("src");
        debug!("crate path {:?}",d);

        // First, check for package name at root (src/kratename/lib.rs)
        d.push(kratename);
        d.push("lib.rs");
        if let Err(_) = File::open(&d) {
            // It doesn't exist, so assume src/lib.rs
            d.pop();
            d.pop();
            d.push("lib.rs");
        }
        debug!("crate path with lib.rs {:?}",d);

        if let Err(_) = File::open(&d) {
            // It doesn't exist, so try /lib.rs
            d.pop();
            d.pop();
            d.push("lib.rs");
        }

        if let Err(_) = File::open(&d) {
            continue;
        }

        return Some(d)
    }
    None
 }

fn find_src_via_tomlfile(kratename: &str, cargofile: &Path) -> Option<PathBuf> {
    // only look for 'path' references here.
    // We find the git and crates.io stuff via the lockfile

    let mut file = otry2!(File::open(cargofile));
    let mut string = String::new();
    otry2!(file.read_to_string(&mut string));
    let mut parser = toml::Parser::new(&string);
    let table = otry!(parser.parse());

    // is it this lib?  (e.g. you're searching from tests to find the main library crate)
    {
        let package_name = if let Some(&toml::Value::Table(ref t)) = table.get("package") {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                name
            } else {
                // it's invalid for a package to be nameless anyway
                return None;
            }
        } else {
            return None;
        };

        let mut lib_name = package_name;
        let mut lib_path = otry!(cargofile.parent()).join("src").join("lib.rs");
        if let Some(&toml::Value::Table(ref t)) = table.get("lib") {
            if let Some(&toml::Value::String(ref name)) = t.get("name") {
                lib_name = name;
            }
            if let Some(&toml::Value::String(ref pathstr)) = t.get("path") {
                let p = Path::new(pathstr);
                lib_path = otry!(cargofile.parent()).join(p);
            }
        }

        if lib_name == kratename {
            debug!("found {} as lib entry in Cargo.toml", kratename);
            if ::std::fs::metadata(&lib_path).ok().map(|m| m.is_file()).unwrap_or(false) {
                return Some(lib_path);
            }
        }
    }

    // otherwise search the dependencies
    let t = match table.get("dependencies") {
        Some(&toml::Value::Table(ref t)) => t,
        _ => return None
    };

    let mut name = kratename;
    let value = if kratename.contains('_') {
        t.iter().find(|&(k, _)| k.replace("-", "_") == name).map(|(k,v)| {
            name = k;
            v
        })
    } else {
        t.get(kratename)
    };

    match value {
        Some(&toml::Value::Table(ref t)) => {
            // local directory
            let relative_path = otry!(getstr(t, "path"));
            Some(otry!(cargofile.parent())
                 .join(relative_path)
                 .join("src")
                 .join("lib.rs"))
        },
        Some(&toml::Value::String(ref version)) => {
            // versioned crate
            get_versioned_cratefile(name, version, cargofile)
        }
        _ => None
    }
}

fn find_cratesio_src_dirs(d: PathBuf) -> Vec<PathBuf> {
    let mut out = Vec::new();
    for entry in vectry!(read_dir(d)) {
        let path = vectry!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with("github.com-") {
                    out.push(path.clone());
                }
            }
        }
    }
    out
}

fn find_git_src_dir(d: PathBuf, name: &str, sha1: &str, branch: Option<&str>) -> Option<PathBuf> {
    for entry in otry2!(read_dir(d)) {
        let path = otry2!(entry).path();
        if is_dir(path.as_path()) {
            if let Some(ref fname) = path.file_name().and_then(|s| s.to_str()) {
                if fname.starts_with(name) {
                    let mut d = path.clone();

                    // dirname can be the sha1 or master.
                    d.push(sha1);

                    if !is_dir(d.as_path()) && branch.is_some() {
                        d.pop();
                        d.push(branch.unwrap());
                    }

                    if !is_dir(d.as_path()) {
                        d.pop();
                        d.push("master");
                    }

                    let retval = d.clone();

                    // check that the checkout matches the commit sha1
                    d.push(".git");
                    d.push("refs");
                    d.push("heads");
                    d.push("master");

                    let mut headref = String::new();
                    otry2!(otry2!(File::open(d)).read_to_string(&mut headref));

                    debug!("git headref is {:?}", headref);

                    if headref.ends_with("\n") {
                        headref.pop();
                    }

                    if sha1 == headref {
                        return Some(retval);
                    }
                }
            }
        }
    }
    None
}

fn getstr(t: &toml::Table, k: &str) -> Option<String> {
    match t.get(k) {
        Some(&toml::Value::String(ref s)) => Some(s.clone()),
        _ => None
    }
}

fn find_cargo_tomlfile(currentfile: &Path) -> Option<PathBuf> {
    let mut f = currentfile.to_path_buf();
    f.push("Cargo.toml");
    if path_exists(f.as_path()) {
        Some(f)
    } else {
        if f.pop() && f.pop() {
            find_cargo_tomlfile(&f)
        } else {
            None
        }
    }
}

pub fn get_crate_file(kratename: &str, from_path: &Path) -> Option<PathBuf> {
    if let Some(tomlfile) = find_cargo_tomlfile(from_path) {
        // look in the lockfile first, if there is one
        debug!("get_crate_file tomlfile is {:?}", tomlfile);
        let mut lockfile = tomlfile.clone();
        lockfile.pop();
        lockfile.push("Cargo.lock");
        if path_exists(lockfile.as_path()) {
            if let Some(f) = find_src_via_lockfile(kratename, &lockfile) {
                return Some(f);
            }
        }

        // oh, no luck with the lockfile. Try the tomlfile
        return find_src_via_tomlfile(kratename, &tomlfile)
    }
    None
}
<|endoftext|>


<commit_before><commit_msg>added test to ensure move_val_init still handles cleanups properly.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This test is checking that the move_val_init intrinsic is
// respecting cleanups for both of its argument expressions.
//
// In other words, if either DEST or SOURCE in
//
//   `intrinsics::move_val_init(DEST, SOURCE)
//
// introduce temporaries that require cleanup, and SOURCE panics, then
// make sure the cleanups still occur.

#![feature(core, std_misc)]

use std::cell::RefCell;
use std::intrinsics;
use std::sync::{Arc, LockResult, Mutex, MutexGuard};
use std::thread;

type LogEntry = (&'static str, i32);
type Guarded = RefCell<Vec<LogEntry>>;
#[derive(Clone)]
struct Log(Arc<Mutex<Guarded>>);
struct Acquired<'a>(MutexGuard<'a, Guarded>);
type LogState = (MutexWas, &'static [LogEntry]);

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
enum MutexWas { Poisoned, NotPoisoned }

impl Log {
    fn lock(&self) -> LockResult<MutexGuard<RefCell<Vec<LogEntry>>>> { self.0.lock() }
    fn acquire(&self) -> Acquired { Acquired(self.0.lock().unwrap()) }
}

impl<'a> Acquired<'a> {
    fn log(&self, s: &'static str, i: i32) { self.0.borrow_mut().push((s, i)); }
}

const TEST1_EXPECT: LogState = (MutexWas::NotPoisoned,
                                &[("double-check non-poisoning path", 1)
                                  ]);

fn test1(log: Log) {
    {
        let acq = log.acquire();
        acq.log("double-check non-poisoning path", 1);
    }
    panic!("every test ends in a panic");
}

const TEST2_EXPECT: LogState = (MutexWas::Poisoned,
                                &[("double-check poisoning path", 1),
                                  ("and multiple log entries", 2),
                                  ]);
fn test2(log: Log) {
    let acq = log.acquire();
    acq.log("double-check poisoning path", 1);
    acq.log("and multiple log entries", 2);
    panic!("every test ends in a panic");
}

struct LogOnDrop<'a>(&'a Acquired<'a>, &'static str, i32);
impl<'a> Drop for LogOnDrop<'a> {
    fn drop(&mut self) {
        self.0.log(self.1, self.2);
    }
}

const TEST3_EXPECT: LogState = (MutexWas::Poisoned,
                                &[("double-check destructors can log", 1),
                                  ("drop d2", 2),
                                  ("drop d1", 3),
                                  ]);
fn test3(log: Log) {
    let acq = log.acquire();
    acq.log("double-check destructors can log", 1);
    let _d1 = LogOnDrop(&acq, "drop d1", 3);
    let _d2 = LogOnDrop(&acq, "drop d2", 2);
    panic!("every test ends in a panic");
}

// The *real* tests of panic-handling for move_val_init intrinsic
// start here.

const TEST4_EXPECT: LogState = (MutexWas::Poisoned,
                                &[("neither arg panics", 1),
                                  ("drop temp LOD", 2),
                                  ("drop temp LOD", 3),
                                  ("drop dest_b", 4),
                                  ("drop dest_a", 5),
                                  ]);
fn test4(log: Log) {
    let acq = log.acquire();
    acq.log("neither arg panics", 1);
    let mut dest_a = LogOnDrop(&acq, "a will be overwritten, not dropped", 0);
    let mut dest_b = LogOnDrop(&acq, "b will be overwritten, not dropped", 0);
    unsafe {
        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
                                  LogOnDrop(&acq, "drop dest_a", 5));
        intrinsics::move_val_init(&mut dest_b, { LogOnDrop(&acq, "drop temp LOD", 3);
                                                 LogOnDrop(&acq, "drop dest_b", 4) });
    }
    panic!("every test ends in a panic");
}

// Check that move_val_init(PANIC, SOURCE_EXPR) never evaluates SOURCE_EXPR
const TEST5_EXPECT: LogState = (MutexWas::Poisoned,
                                &[("first arg panics", 1),
                                  ("drop orig dest_a", 2),
                                  ]);
fn test5(log: Log) {
    let acq = log.acquire();
    acq.log("first arg panics", 1);
    let mut _dest_a = LogOnDrop(&acq, "drop orig dest_a", 2);
    unsafe {
        intrinsics::move_val_init({ panic!("every test ends in a panic") },
                                  LogOnDrop(&acq, "we never get here", 0));
    }
}

// Check that move_val_init(DEST_EXPR, PANIC) cleans up temps from DEST_EXPR.
const TEST6_EXPECT: LogState = (MutexWas::Poisoned,
                                &[("second arg panics", 1),
                                  ("drop temp LOD", 2),
                                  ("drop orig dest_a", 3),
                                  ]);
fn test6(log: Log) {
    let acq = log.acquire();
    acq.log("second arg panics", 1);
    let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 3);
    unsafe {
        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
                                  { panic!("every test ends in a panic"); });
    }
}

// Check that move_val_init(DEST_EXPR, COMPLEX_PANIC) cleans up temps from COMPLEX_PANIC.
const TEST7_EXPECT: LogState = (MutexWas::Poisoned,
                                &[("second arg panics", 1),
                                  ("drop temp LOD", 2),
                                  ("drop temp LOD", 3),
                                  ("drop orig dest_a", 4),
                                  ]);
fn test7(log: Log) {
    let acq = log.acquire();
    acq.log("second arg panics", 1);
    let mut dest_a = LogOnDrop(&acq, "drop orig dest_a", 4);
    unsafe {
        intrinsics::move_val_init({ LogOnDrop(&acq, "drop temp LOD", 2); &mut dest_a },
                                  { LogOnDrop(&acq, "drop temp LOD", 3);
                                    panic!("every test ends in a panic"); });
    }
}

const TEST_SUITE: &'static [(&'static str, fn (Log), LogState)] =
    &[("test1", test1, TEST1_EXPECT),
      ("test2", test2, TEST2_EXPECT),
      ("test3", test3, TEST3_EXPECT),
      ("test4", test4, TEST4_EXPECT),
      ("test5", test5, TEST5_EXPECT),
      ("test6", test6, TEST6_EXPECT),
      ("test7", test7, TEST7_EXPECT),
      ];

fn main() {
    for &(name, test, expect) in TEST_SUITE {
        let log = Log(Arc::new(Mutex::new(RefCell::new(Vec::new()))));
        let ret = { let log = log.clone(); thread::spawn(move || test(log)).join() };
        assert!(ret.is_err(), "{} must end with panic", name);
        {
            let l = log.lock();
            match l {
                Ok(acq) => {
                    assert_eq!((MutexWas::NotPoisoned, &acq.borrow()[..]), expect);
                    println!("{} (unpoisoned) log: {:?}", name, *acq);
                }
                Err(e) => {
                    let acq = e.into_inner();
                    assert_eq!((MutexWas::Poisoned, &acq.borrow()[..]), expect);
                    println!("{} (poisoned) log: {:?}", name, *acq);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Rollup merge of #81060 - nagisa:nagisa/regression-50041, r=Mark-Simulacrum<commit_after>// build-pass
// compile-flags: -Z mir-opt-level=3

#![crate_type="lib"]
#![feature(lang_items)]
#![no_std]

#[lang = "owned_box"]
pub struct Box<T: ?Sized>(*mut T);

impl<T: ?Sized> Drop for Box<T> {
    fn drop(&mut self) {
    }
}

#[lang = "box_free"]
#[inline(always)]
unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
    dealloc(ptr)
}

#[inline(never)]
fn dealloc<T: ?Sized>(_: *mut T) {
}

pub struct Foo<T>(T);

pub fn foo(a: Option<Box<Foo<usize>>>) -> usize {
    let f = match a {
        None => Foo(0),
        Some(vec) => *vec,
    };
    f.0
}
<|endoftext|>


<commit_before><commit_msg>Add ability to make custom packet without editing RakNet source - Remove 0x80 - 0x8F packet (except for 0x84)<commit_after><|endoftext|>


<commit_before><commit_msg>rust chotto dekiru<commit_after><|endoftext|>


<commit_before><commit_msg>Clippy + Basic documentation<commit_after><|endoftext|>


<commit_before><commit_msg>gridTraits file<commit_after>use rand::XorShiftRng;

use cells::{Cell, Coordinate, Cartesian2DCoordinate};
use units::{RowsCount, RowLength, RowIndex, ColumnsCount, ColumnLength,
            ColumnIndex, NodesCount, EdgesCount};

pub trait GridDimensions {
    fn size(&self) -> NodesCount;
    fn rows(&self) -> RowsCount;
    fn row_length(&self, rowIndex: Option<RowIndex>) -> Option<RowLength>;
    fn columns(&self) -> ColumnsCount;
    fn column_length(&self, columnIndex: Option<ColumnIndex>) -> ColumnLength;
    fn graph_size(&self) -> (NodesCount, EdgesCount);
}

pub trait GridPositions<CellT: Cell> {
    fn grid_coordinate_to_index(&self, coord: CellT::Coord) -> Option<usize>;
    fn random_cell(&self, rng: &mut XorShiftRng) -> CellT::Coord; // consider &Rng simple trait object. Note <R : Rng> meant GridPositions could not be made a trait object
}

pub trait GridIterators<CellT: Cell, Dimensions: GridDimensions> {
    type CellIter: Iterator<Item=CellT::Coord>;
    type BatchIter: Iterator<Item=Vec<CellT::Coord>>; // consider &[CellT::Coord] instead
    fn iter(&self, data: &Dimensions) -> Self::CellIter;
    fn iter_row(&self, data: &Dimensions) -> Self::BatchIter;
    fn iter_column(&self, data: &Dimensions) -> Self::BatchIter;
}

pub trait GridDisplay<CellT: Cell> {
    /// Render the contents of a grid cell as text.
    /// The String should be 3 glyphs long, padded if required.
    fn render_cell_body(&self, _: CellT::Coord) -> String {
        String::from("   ")
    }
}
<|endoftext|>


<commit_before><commit_msg>Added in checking for muli-expression expressions, and started thinking about function call expressions.<commit_after><|endoftext|>


<commit_before><commit_msg>add x86 rbit asm test<commit_after>extern crate bitintr;

#[no_mangle]
pub fn rbit_u8(x: u8) -> u8 {
    bitintr::arm::v7::rbit(x)
}

#[no_mangle]
pub fn rbit_u32(x: u32) -> u32 {
    bitintr::arm::v7::rbit(x)
}

#[no_mangle]
pub fn rbit_u64(x: u64) -> u64 {
    bitintr::arm::v7::rbit(x)
}
<|endoftext|>


<commit_before><commit_msg>Additional fix for #352 (#354)<commit_after><|endoftext|>


<commit_before><commit_msg>util: remove most of the unidiomatic ::std:: paths<commit_after><|endoftext|>


<commit_before><commit_msg>fixed ticker replay test<commit_after><|endoftext|>


<commit_before>#[doc(
  brief = "Communication between tasks",
  desc  = "Communication between tasks is facilitated by ports (in the \
           receiving task), and channels (in the sending task). Any \
           number of channels may feed into a single port. \
           Ports and channels may only transmit values of unique \
           types; that is, values that are statically guaranteed to \
           be accessed by a single 'owner' at a time.  Unique types \
           include scalars, vectors, strings, and records, tags, \
           tuples and unique boxes (~T) thereof. Most notably, \
           shared boxes (@T) may not be transmitted across channels. \
           Example: \
               let p = comm::port(); \
               task::spawn(comm::chan(p), fn (c: chan<str>) { \
                   comm::send(c, \"Hello, World\"); \
               }); \
               io::println(comm::recv(p));"
)];

import sys;
import task;

export send;
export recv;
export chan;
export port;

#[abi = "cdecl"]
native mod rustrt {
    type rust_port;

    fn chan_id_send<T: send>(t: *sys::type_desc,
                            target_task: task::task, target_port: port_id,
                            data: T) -> ctypes::uintptr_t;

    fn new_port(unit_sz: ctypes::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> ctypes::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *ctypes::uintptr_t,
                 killed: *ctypes::uintptr_t);
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
}

type port_id = int;

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc(
  brief = "A communication endpoint that can send messages. \
           Channels send messages to ports.",
  desc = "Each channel is bound to a port when the channel is \
          constructed, so the destination port for a channel \
          must exist before the channel itself. \
          Channels are weak: a channel does not keep the port it \
          is bound to alive. If a channel attempts to send data \
          to a dead port that data will be silently dropped. \
          Channels may be duplicated and themselves transmitted \
          over other channels."
)]
enum chan<T: send> {
    chan_t(task::task, port_id)
}

resource port_ptr<T: send>(po: *rustrt::rust_port) {
    // Once the port is detached it's guaranteed not to receive further
    // messages
    rustrt::rust_port_detach(po);
    // Drain the port so that all the still-enqueued items get dropped
    while rustrt::rust_port_size(po) > 0u {
        // FIXME: For some reason if we don't assign to something here
        // we end up with invalid reads in the drop glue.
        let _t = recv_::<T>(po);
    }
    rustrt::del_port(po);
}

#[doc(
  brief = "A communication endpoint that can receive messages. \
           Ports receive messages from channels.",
  desc = "Each port has a unique per-task identity and may not \
          be replicated or transmitted. If a port value is \
          copied, both copies refer to the same port. \
          Ports may be associated with multiple <chan>s."
)]
enum port<T: send> { port_t(@port_ptr<T>) }

#[doc(
  brief = "Sends data over a channel. The sent data is moved \
           into the channel, whereupon the caller loses \
           access to it."
)]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(t, p) = ch;
    let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::leak(data);
    }
    task::yield();
}

#[doc(
  brief = "Constructs a port."
)]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}

#[doc(
  brief = "Receive from a port. \
           If no data is available on the port then the task will \
           block until data becomes available."
)]
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

#[doc(
  brief = "Receive on a raw port pointer"
)]
fn recv_<T: send>(p: *rustrt::rust_port) -> T {
    // FIXME: Due to issue 1185 we can't use a return pointer when
    // calling C code, and since we can't create our own return
    // pointer on the stack, we're going to call a little intrinsic
    // that will grab the value of the return pointer, then call this
    // function, which we will then use to call the runtime.
    fn recv(dptr: *uint, port: *rustrt::rust_port,
            yield: *ctypes::uintptr_t,
            killed: *ctypes::uintptr_t) unsafe {
        rustrt::port_recv(dptr, port, yield, killed);
    }
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let killed = 0u;
    let killedp = ptr::addr_of(killed);
    let res = rusti::call_with_retptr(bind recv(_, p, yieldp, killedp));
    if killed != 0u {
        fail "killed";
    }
    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    }
    ret res;
}

#[doc(
  brief = "Constructs a channel. The channel is bound to the \
           port used to construct it."
)]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(task::get_task(), rustrt::get_port_id(***p))
}

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

<commit_msg>core: Format comm docs correctly<commit_after>#[doc(
  brief = "Communication between tasks",
  desc  = "

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

Example:

    let p = comm::port();
    task::spawn(comm::chan(p), fn (c: chan<str>) {
        comm::send(c, \"Hello, World\");
    });
    io::println(comm::recv(p));

")];

import sys;
import task;

export send;
export recv;
export chan;
export port;

#[abi = "cdecl"]
native mod rustrt {
    type rust_port;

    fn chan_id_send<T: send>(t: *sys::type_desc,
                            target_task: task::task, target_port: port_id,
                            data: T) -> ctypes::uintptr_t;

    fn new_port(unit_sz: ctypes::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> ctypes::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *ctypes::uintptr_t,
                 killed: *ctypes::uintptr_t);
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn call_with_retptr<T: send>(&&f: fn@(*uint)) -> T;
}

type port_id = int;

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc(
  brief = "A communication endpoint that can send messages. \
           Channels send messages to ports.",
  desc = "Each channel is bound to a port when the channel is \
          constructed, so the destination port for a channel \
          must exist before the channel itself. \
          Channels are weak: a channel does not keep the port it \
          is bound to alive. If a channel attempts to send data \
          to a dead port that data will be silently dropped. \
          Channels may be duplicated and themselves transmitted \
          over other channels."
)]
enum chan<T: send> {
    chan_t(task::task, port_id)
}

resource port_ptr<T: send>(po: *rustrt::rust_port) {
    // Once the port is detached it's guaranteed not to receive further
    // messages
    rustrt::rust_port_detach(po);
    // Drain the port so that all the still-enqueued items get dropped
    while rustrt::rust_port_size(po) > 0u {
        // FIXME: For some reason if we don't assign to something here
        // we end up with invalid reads in the drop glue.
        let _t = recv_::<T>(po);
    }
    rustrt::del_port(po);
}

#[doc(
  brief = "A communication endpoint that can receive messages. \
           Ports receive messages from channels.",
  desc = "Each port has a unique per-task identity and may not \
          be replicated or transmitted. If a port value is \
          copied, both copies refer to the same port. \
          Ports may be associated with multiple <chan>s."
)]
enum port<T: send> { port_t(@port_ptr<T>) }

#[doc(
  brief = "Sends data over a channel. The sent data is moved \
           into the channel, whereupon the caller loses \
           access to it."
)]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(t, p) = ch;
    let res = rustrt::chan_id_send(sys::get_type_desc::<T>(), t, p, data);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::leak(data);
    }
    task::yield();
}

#[doc(
  brief = "Constructs a port."
)]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}

#[doc(
  brief = "Receive from a port. \
           If no data is available on the port then the task will \
           block until data becomes available."
)]
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

#[doc(
  brief = "Receive on a raw port pointer"
)]
fn recv_<T: send>(p: *rustrt::rust_port) -> T {
    // FIXME: Due to issue 1185 we can't use a return pointer when
    // calling C code, and since we can't create our own return
    // pointer on the stack, we're going to call a little intrinsic
    // that will grab the value of the return pointer, then call this
    // function, which we will then use to call the runtime.
    fn recv(dptr: *uint, port: *rustrt::rust_port,
            yield: *ctypes::uintptr_t,
            killed: *ctypes::uintptr_t) unsafe {
        rustrt::port_recv(dptr, port, yield, killed);
    }
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let killed = 0u;
    let killedp = ptr::addr_of(killed);
    let res = rusti::call_with_retptr(bind recv(_, p, yieldp, killedp));
    if killed != 0u {
        fail "killed";
    }
    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    }
    ret res;
}

#[doc(
  brief = "Constructs a channel. The channel is bound to the \
           port used to construct it."
)]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(task::get_task(), rustrt::get_port_id(***p))
}

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

<|endoftext|>


<commit_before>#[doc = "
Communication between tasks

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

# Example

~~~
let po = comm::port();
let ch = comm::chan(po);

task::spawn {||
    comm::send(ch, \"Hello, World\");
});

io::println(comm::recv(p));
~~~
"];

import either::either;

export port::{};
export chan::{};
export send;
export recv;
export peek;
export recv_chan;
export select2;
export methods;

#[doc = "
A communication endpoint that can receive messages

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same
port.  Ports may be associated with multiple `chan`s.
"]
enum port<T: send> {
    port_t(@port_ptr<T>)
}

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc = "
A communication endpoint that can send messages

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.  Channels are weak: a channel does not keep the port it is
bound to alive. If a channel attempts to send data to a dead port that
data will be silently dropped.  Channels may be duplicated and
themselves transmitted over other channels.
"]
enum chan<T: send> {
    chan_t(port_id)
}

#[doc = "Constructs a port"]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}

impl methods<T: send> for port<T> {

    fn chan() -> chan<T> { chan(self) }
    fn send(+v: T) { self.chan().send(v) }
    fn recv() -> T { recv(self) }
    fn peek() -> bool { peek(self) }

}

impl methods<T: send> for chan<T> {

    fn chan() -> chan<T> { self }
    fn send(+v: T) { send(self, v) }
    fn recv() -> T { recv_chan(self) }
    fn peek() -> bool { peek_chan(self) }

}

resource port_ptr<T: send>(po: *rust_port) {
    // Once the port is detached it's guaranteed not to receive further
    // messages
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    rustrt::rust_port_begin_detach(po, yieldp);
    if yield != 0u {
        // Need to wait for the port to be detached
        // FIXME: If this fails then we're going to leave our port
        // in a bogus state. (Issue #1988)
        task::yield();
    }
    rustrt::rust_port_end_detach(po);

    // Drain the port so that all the still-enqueued items get dropped
    while rustrt::rust_port_size(po) > 0u {
       recv_::<T>(po);
    }
    rustrt::del_port(po);
}

#[doc = "
Internal function for converting from a channel to a port

# Failure

Fails if the port is detached or dead. Fails if the port
is owned by a different task.
"]
fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {
    resource portref(p: *rust_port) {
        if !ptr::is_null(p) {
            rustrt::rust_port_drop(p);
        }
    }

    let p = portref(rustrt::rust_port_take(*ch));

    if ptr::is_null(*p) {
        fail "unable to locate port for channel"
    } else if rustrt::get_task_id() != rustrt::rust_port_task(*p) {
        fail "unable to access unowned port"
    }

    f(*p)
}

#[doc = "
Constructs a channel. The channel is bound to the port used to
construct it.
"]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(rustrt::get_port_id(***p))
}

#[doc = "
Sends data over a channel. The sent data is moved into the channel,
whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(p) = ch;
    let res = rustrt::rust_port_id_send(p, data);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::forget(data);
    }
    task::yield();
}

#[doc = "
Receive from a port.  If no data is available on the port then the
task will block until data becomes available.
"]
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

#[doc = "Returns true if there are messages available"]
fn peek<T: send>(p: port<T>) -> bool { peek_(***p) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    as_raw_port(ch, recv_(_))
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
    as_raw_port(ch, peek_(_))
}

#[doc = "Receive on a raw port pointer"]
fn recv_<T: send>(p: *rust_port) -> T {
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let mut res;
    res = rusti::init::<T>();
    rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);

    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    } else {
        // In the absense of compiler-generated preemption points
        // this is a good place to yield
        task::yield();
    }
    ret res;
}

fn peek_(p: *rust_port) -> bool unsafe {
    rustrt::rust_port_size(p) != 0u as libc::size_t
}

#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
    -> either<A, B> unsafe {
    let ports = [***p_a, ***p_b];
    let n_ports = 2 as libc::size_t;
    let yield = 0u, yieldp = ptr::addr_of(yield);

    let mut resport: *rust_port;
    resport = rusti::init::<*rust_port>();
    vec::as_buf(ports) {|ports|
        rustrt::rust_port_select(ptr::addr_of(resport), ports, n_ports,
                                 yieldp);
    }

    if yield != 0u {
        // Wait for data
        task::yield();
    } else {
        // As in recv, this is a good place to yield anyway until
        // the compiler generates yield calls
        task::yield();
    }

    // Now we know the port we're supposed to receive from
    assert resport != ptr::null();

    if resport == ***p_a {
        either::left(recv(p_a))
    } else if resport == ***p_b {
        either::right(recv(p_b))
    } else {
        fail "unexpected result from rust_port_select";
    }
}

/* Implementation details */

enum rust_port {}

type port_id = int;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_port_id_send<T: send>(target_port: port_id,
                                  data: T) -> libc::uintptr_t;

    fn new_port(unit_sz: libc::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_begin_detach(po: *rust_port,
                              yield: *libc::uintptr_t);
    fn rust_port_end_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> libc::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *libc::uintptr_t);
    fn rust_port_select(dptr: **rust_port, ports: **rust_port,
                        n_ports: libc::size_t,
                        yield: *libc::uintptr_t);
    fn rust_port_take(port_id: port_id) -> *rust_port;
    fn rust_port_drop(p: *rust_port);
    fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
    fn get_task_id() -> libc::uintptr_t;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn init<T>() -> T;
}

/* Tests */

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn test_peek() {
    let po = port();
    let ch = chan(po);
    assert !peek(po);
    send(ch, ());
    assert peek(po);
    recv(po);
    assert !peek(po);
}

#[test]
fn test_select2_available() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    send(ch_a, "a");

    assert select2(po_a, po_b) == either::left("a");

    send(ch_b, "b");

    assert select2(po_a, po_b) == either::right("b");
}

#[test]
fn test_select2_rendezvous() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    iter::repeat(10u) {||
        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_a, "a");
        };

        assert select2(po_a, po_b) == either::left("a");

        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_b, "b");
        };

        assert select2(po_a, po_b) == either::right("b");
    }
}

#[test]
fn test_select2_stress() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    let msgs = 100u;
    let times = 4u;

    iter::repeat(times) {||
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_a, "a")
            }
        };
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_b, "b")
            }
        };
    }

    let mut as = 0;
    let mut bs = 0;
    iter::repeat(msgs * times * 2u) {||
        alt check select2(po_a, po_b) {
          either::left("a") { as += 1 }
          either::right("b") { bs += 1 }
        }
    }

    assert as == 400;
    assert bs == 400;
}

#[test]
fn test_recv_chan() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert recv_chan(ch) == "flower";
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(target_os = "win32"))]
fn test_recv_chan_wrong_task() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert result::is_failure(task::try {||
        recv_chan(ch)
    })
}

#[test]
fn test_port_send() {
    let po = port();
    po.send(());
    po.recv();
}

#[test]
fn test_chan_peek() {
    let po = port();
    let ch = po.chan();
    ch.send(());
    assert ch.peek();
}<commit_msg>core: Add comm::listen<commit_after>#[doc = "
Communication between tasks

Communication between tasks is facilitated by ports (in the receiving
task), and channels (in the sending task). Any number of channels may
feed into a single port.  Ports and channels may only transmit values
of unique types; that is, values that are statically guaranteed to be
accessed by a single 'owner' at a time.  Unique types include scalars,
vectors, strings, and records, tags, tuples and unique boxes (`~T`)
thereof. Most notably, shared boxes (`@T`) may not be transmitted
across channels.

# Example

~~~
let po = comm::port();
let ch = comm::chan(po);

task::spawn {||
    comm::send(ch, \"Hello, World\");
});

io::println(comm::recv(p));
~~~
"];

import either::either;

export port::{};
export chan::{};
export send;
export recv;
export peek;
export recv_chan;
export select2;
export methods;
export listen;

#[doc = "
A communication endpoint that can receive messages

Each port has a unique per-task identity and may not be replicated or
transmitted. If a port value is copied, both copies refer to the same
port.  Ports may be associated with multiple `chan`s.
"]
enum port<T: send> {
    port_t(@port_ptr<T>)
}

// It's critical that this only have one variant, so it has a record
// layout, and will work in the rust_task structure in task.rs.
#[doc = "
A communication endpoint that can send messages

Each channel is bound to a port when the channel is constructed, so
the destination port for a channel must exist before the channel
itself.  Channels are weak: a channel does not keep the port it is
bound to alive. If a channel attempts to send data to a dead port that
data will be silently dropped.  Channels may be duplicated and
themselves transmitted over other channels.
"]
enum chan<T: send> {
    chan_t(port_id)
}

#[doc = "Constructs a port"]
fn port<T: send>() -> port<T> {
    port_t(@port_ptr(rustrt::new_port(sys::size_of::<T>())))
}

impl methods<T: send> for port<T> {

    fn chan() -> chan<T> { chan(self) }
    fn send(+v: T) { self.chan().send(v) }
    fn recv() -> T { recv(self) }
    fn peek() -> bool { peek(self) }

}

impl methods<T: send> for chan<T> {

    fn chan() -> chan<T> { self }
    fn send(+v: T) { send(self, v) }
    fn recv() -> T { recv_chan(self) }
    fn peek() -> bool { peek_chan(self) }

}

#[doc = "Open a new receiving channel for the duration of a function"]
fn listen<T: send, U>(f: fn(chan<T>) -> U) -> U {
    let po = port();
    f(po.chan())
}

resource port_ptr<T: send>(po: *rust_port) {
    // Once the port is detached it's guaranteed not to receive further
    // messages
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    rustrt::rust_port_begin_detach(po, yieldp);
    if yield != 0u {
        // Need to wait for the port to be detached
        // FIXME: If this fails then we're going to leave our port
        // in a bogus state. (Issue #1988)
        task::yield();
    }
    rustrt::rust_port_end_detach(po);

    // Drain the port so that all the still-enqueued items get dropped
    while rustrt::rust_port_size(po) > 0u {
       recv_::<T>(po);
    }
    rustrt::del_port(po);
}

#[doc = "
Internal function for converting from a channel to a port

# Failure

Fails if the port is detached or dead. Fails if the port
is owned by a different task.
"]
fn as_raw_port<T: send, U>(ch: comm::chan<T>, f: fn(*rust_port) -> U) -> U {
    resource portref(p: *rust_port) {
        if !ptr::is_null(p) {
            rustrt::rust_port_drop(p);
        }
    }

    let p = portref(rustrt::rust_port_take(*ch));

    if ptr::is_null(*p) {
        fail "unable to locate port for channel"
    } else if rustrt::get_task_id() != rustrt::rust_port_task(*p) {
        fail "unable to access unowned port"
    }

    f(*p)
}

#[doc = "
Constructs a channel. The channel is bound to the port used to
construct it.
"]
fn chan<T: send>(p: port<T>) -> chan<T> {
    chan_t(rustrt::get_port_id(***p))
}

#[doc = "
Sends data over a channel. The sent data is moved into the channel,
whereupon the caller loses access to it.
"]
fn send<T: send>(ch: chan<T>, -data: T) {
    let chan_t(p) = ch;
    let res = rustrt::rust_port_id_send(p, data);
    if res != 0u unsafe {
        // Data sent successfully
        unsafe::forget(data);
    }
    task::yield();
}

#[doc = "
Receive from a port.  If no data is available on the port then the
task will block until data becomes available.
"]
fn recv<T: send>(p: port<T>) -> T { recv_(***p) }

#[doc = "Returns true if there are messages available"]
fn peek<T: send>(p: port<T>) -> bool { peek_(***p) }

#[doc(hidden)]
fn recv_chan<T: send>(ch: comm::chan<T>) -> T {
    as_raw_port(ch, recv_(_))
}

fn peek_chan<T: send>(ch: comm::chan<T>) -> bool {
    as_raw_port(ch, peek_(_))
}

#[doc = "Receive on a raw port pointer"]
fn recv_<T: send>(p: *rust_port) -> T {
    let yield = 0u;
    let yieldp = ptr::addr_of(yield);
    let mut res;
    res = rusti::init::<T>();
    rustrt::port_recv(ptr::addr_of(res) as *uint, p, yieldp);

    if yield != 0u {
        // Data isn't available yet, so res has not been initialized.
        task::yield();
    } else {
        // In the absense of compiler-generated preemption points
        // this is a good place to yield
        task::yield();
    }
    ret res;
}

fn peek_(p: *rust_port) -> bool unsafe {
    rustrt::rust_port_size(p) != 0u as libc::size_t
}

#[doc = "Receive on one of two ports"]
fn select2<A: send, B: send>(p_a: port<A>, p_b: port<B>)
    -> either<A, B> unsafe {
    let ports = [***p_a, ***p_b];
    let n_ports = 2 as libc::size_t;
    let yield = 0u, yieldp = ptr::addr_of(yield);

    let mut resport: *rust_port;
    resport = rusti::init::<*rust_port>();
    vec::as_buf(ports) {|ports|
        rustrt::rust_port_select(ptr::addr_of(resport), ports, n_ports,
                                 yieldp);
    }

    if yield != 0u {
        // Wait for data
        task::yield();
    } else {
        // As in recv, this is a good place to yield anyway until
        // the compiler generates yield calls
        task::yield();
    }

    // Now we know the port we're supposed to receive from
    assert resport != ptr::null();

    if resport == ***p_a {
        either::left(recv(p_a))
    } else if resport == ***p_b {
        either::right(recv(p_b))
    } else {
        fail "unexpected result from rust_port_select";
    }
}

/* Implementation details */

enum rust_port {}

type port_id = int;

#[abi = "cdecl"]
native mod rustrt {
    fn rust_port_id_send<T: send>(target_port: port_id,
                                  data: T) -> libc::uintptr_t;

    fn new_port(unit_sz: libc::size_t) -> *rust_port;
    fn del_port(po: *rust_port);
    fn rust_port_begin_detach(po: *rust_port,
                              yield: *libc::uintptr_t);
    fn rust_port_end_detach(po: *rust_port);
    fn get_port_id(po: *rust_port) -> port_id;
    fn rust_port_size(po: *rust_port) -> libc::size_t;
    fn port_recv(dptr: *uint, po: *rust_port,
                 yield: *libc::uintptr_t);
    fn rust_port_select(dptr: **rust_port, ports: **rust_port,
                        n_ports: libc::size_t,
                        yield: *libc::uintptr_t);
    fn rust_port_take(port_id: port_id) -> *rust_port;
    fn rust_port_drop(p: *rust_port);
    fn rust_port_task(p: *rust_port) -> libc::uintptr_t;
    fn get_task_id() -> libc::uintptr_t;
}

#[abi = "rust-intrinsic"]
native mod rusti {
    fn init<T>() -> T;
}

/* Tests */

#[test]
fn create_port_and_chan() { let p = port::<int>(); chan(p); }

#[test]
fn send_int() {
    let p = port::<int>();
    let c = chan(p);
    send(c, 22);
}

#[test]
fn send_recv_fn() {
    let p = port::<int>();
    let c = chan::<int>(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn send_recv_fn_infer() {
    let p = port();
    let c = chan(p);
    send(c, 42);
    assert (recv(p) == 42);
}

#[test]
fn chan_chan_infer() {
    let p = port(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn chan_chan() {
    let p = port::<chan<int>>(), p2 = port::<int>();
    let c = chan(p);
    send(c, chan(p2));
    recv(p);
}

#[test]
fn test_peek() {
    let po = port();
    let ch = chan(po);
    assert !peek(po);
    send(ch, ());
    assert peek(po);
    recv(po);
    assert !peek(po);
}

#[test]
fn test_select2_available() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    send(ch_a, "a");

    assert select2(po_a, po_b) == either::left("a");

    send(ch_b, "b");

    assert select2(po_a, po_b) == either::right("b");
}

#[test]
fn test_select2_rendezvous() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    iter::repeat(10u) {||
        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_a, "a");
        };

        assert select2(po_a, po_b) == either::left("a");

        task::spawn {||
            iter::repeat(10u) {|| task::yield() }
            send(ch_b, "b");
        };

        assert select2(po_a, po_b) == either::right("b");
    }
}

#[test]
fn test_select2_stress() {
    let po_a = port();
    let po_b = port();
    let ch_a = chan(po_a);
    let ch_b = chan(po_b);

    let msgs = 100u;
    let times = 4u;

    iter::repeat(times) {||
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_a, "a")
            }
        };
        task::spawn {||
            iter::repeat(msgs) {||
                send(ch_b, "b")
            }
        };
    }

    let mut as = 0;
    let mut bs = 0;
    iter::repeat(msgs * times * 2u) {||
        alt check select2(po_a, po_b) {
          either::left("a") { as += 1 }
          either::right("b") { bs += 1 }
        }
    }

    assert as == 400;
    assert bs == 400;
}

#[test]
fn test_recv_chan() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert recv_chan(ch) == "flower";
}

#[test]
#[should_fail]
#[ignore(cfg(target_os = "win32"))]
fn test_recv_chan_dead() {
    let ch = chan(port());
    send(ch, "flower");
    recv_chan(ch);
}

#[test]
#[ignore(cfg(target_os = "win32"))]
fn test_recv_chan_wrong_task() {
    let po = port();
    let ch = chan(po);
    send(ch, "flower");
    assert result::is_failure(task::try {||
        recv_chan(ch)
    })
}

#[test]
fn test_port_send() {
    let po = port();
    po.send(());
    po.recv();
}

#[test]
fn test_chan_peek() {
    let po = port();
    let ch = po.chan();
    ch.send(());
    assert ch.peek();
}

#[test]
fn test_listen() {
    listen {|parent|
        task::spawn {||
            parent.send("oatmeal-salad");
        }
        assert parent.recv() == "oatmeal-salad";
    }
}<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The iteration traits and common implementation

*/

use cmp::{Eq, Ord};
use kinds::Copy;
use option::{None, Option, Some};
use vec;

/// A function used to initialize the elements of a sequence
pub type InitOp<T> = &fn(uint) -> T;

pub trait BaseIter<A> {
    pure fn each(&self, blk: fn(v: &A) -> bool);
    pure fn size_hint(&self) -> Option<uint>;
}

pub trait ReverseIter<A>: BaseIter<A> {
    pure fn each_reverse(&self, blk: fn(&A) -> bool);
}

pub trait ExtendedIter<A> {
    pure fn eachi(&self, blk: fn(uint, v: &A) -> bool);
    pure fn all(&self, blk: fn(&A) -> bool) -> bool;
    pure fn any(&self, blk: fn(&A) -> bool) -> bool;
    pure fn foldl<B>(&self, b0: B, blk: fn(&B, &A) -> B) -> B;
    pure fn position(&self, f: fn(&A) -> bool) -> Option<uint>;
    pure fn map_to_vec<B>(&self, op: fn(&A) -> B) -> ~[B];
    pure fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: fn(&A) -> IB)
        -> ~[B];
}

pub trait EqIter<A:Eq> {
    pure fn contains(&self, x: &A) -> bool;
    pure fn count(&self, x: &A) -> uint;
}

pub trait Times {
    pure fn times(&self, it: fn() -> bool);
}

pub trait CopyableIter<A:Copy> {
    pure fn filter_to_vec(&self, pred: fn(&A) -> bool) -> ~[A];
    pure fn to_vec(&self) -> ~[A];
    pure fn find(&self, p: fn(&A) -> bool) -> Option<A>;
}

pub trait CopyableOrderedIter<A:Copy + Ord> {
    pure fn min(&self) -> A;
    pure fn max(&self) -> A;
}

pub trait CopyableNonstrictIter<A:Copy> {
    // Like "each", but copies out the value. If the receiver is mutated while
    // iterating over it, the semantics must not be memory-unsafe but are
    // otherwise undefined.
    pure fn each_val(&const self, f: &fn(A) -> bool);
}

// A trait for sequences that can be by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It receives
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     static pure fn build_sized(size: uint,
                                builder: fn(push: pure fn(A))) -> Self;
}

#[inline(always)]
pub pure fn eachi<A,IA:BaseIter<A>>(self: &IA,
                                    blk: fn(uint, &A) -> bool) {
    let mut i = 0;
    for self.each |a| {
        if !blk(i, a) { break; }
        i += 1;
    }
}

#[inline(always)]
pub pure fn all<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if !blk(a) { return false; }
    }
    return true;
}

#[inline(always)]
pub pure fn any<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if blk(a) { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(
    self: &IA, prd: fn(&A) -> bool) -> ~[A] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            if prd(a) { push(*a); }
        }
    }
}

#[inline(always)]
pub pure fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA,
                                           op: fn(&A) -> B)
    -> ~[B] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            push(op(a));
        }
    }
}

#[inline(always)]
pub pure fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(
    self: &IA, op: fn(&A) -> IB) -> ~[B] {
    do vec::build |push| {
        for self.each |a| {
            for op(a).each |&b| {
                push(b);
            }
        }
    }
}

#[inline(always)]
pub pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B,
                                      blk: fn(&B, &A) -> B)
    -> B {
    let mut b = b0;
    for self.each |a| {
        b = blk(&b, a);
    }
    b
}

#[inline(always)]
pub pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
    foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
}

#[inline(always)]
pub pure fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
    for self.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
    do foldl(self, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

#[inline(always)]
pub pure fn position<A,IA:BaseIter<A>>(self: &IA, f: fn(&A) -> bool)
    -> Option<uint>
{
    let mut i = 0;
    for self.each |a| {
        if f(a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". as is,
// it would have to be implemented with foldr, which is too inefficient.

#[inline(always)]
pub pure fn repeat(times: uint, blk: fn() -> bool) {
    let mut i = 0;
    while i < times {
        if !blk() { break }
        i += 1;
    }
}

#[inline(always)]
pub pure fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ < *b => {
             *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"min called on empty iterator")
    }
}

#[inline(always)]
pub pure fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ > *b => {
              *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"max called on empty iterator")
    }
}

#[inline(always)]
pub pure fn find<A:Copy,IA:BaseIter<A>>(self: &IA,
                                   f: fn(&A) -> bool) -> Option<A> {
    for self.each |i| {
        if f(i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(A)))
    -> B {
    Buildable::build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build_sized_opt<A,B: Buildable<A>>(
    size: Option<uint>,
    builder: fn(push: pure fn(A))) -> B {

    Buildable::build_sized(size.get_or_default(4), builder)
}

// Functions that combine iteration and building

/// Apply a function to each element of an iterable and return the results
#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: fn(&T) -> U)
    -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
#[inline(always)]
pub pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint,
                                        op: InitOp<T>) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some element
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
#[inline(always)]
pub pure fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint,
                                                t: T) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0;
        while i < n_elts { push(t); i += 1; }
    }
}

/// Appending two generic sequences
#[inline(always)]
pub pure fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    lhs: &IT, rhs: &IT) -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pub pure fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    v: &IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<commit_msg>auto merge of #5114 : osaut/rust/incoming, r=brson<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*!

The iteration traits and common implementation

*/

use cmp::{Eq, Ord};
use kinds::Copy;
use option::{None, Option, Some};
use vec;

/// A function used to initialize the elements of a sequence
pub type InitOp<T> = &fn(uint) -> T;

pub trait BaseIter<A> {
    pure fn each(&self, blk: fn(v: &A) -> bool);
    pure fn size_hint(&self) -> Option<uint>;
}

pub trait ReverseIter<A>: BaseIter<A> {
    pure fn each_reverse(&self, blk: fn(&A) -> bool);
}

pub trait ExtendedIter<A> {
    pure fn eachi(&self, blk: fn(uint, v: &A) -> bool);
    pure fn all(&self, blk: fn(&A) -> bool) -> bool;
    pure fn any(&self, blk: fn(&A) -> bool) -> bool;
    pure fn foldl<B>(&self, b0: B, blk: fn(&B, &A) -> B) -> B;
    pure fn position(&self, f: fn(&A) -> bool) -> Option<uint>;
    pure fn map_to_vec<B>(&self, op: fn(&A) -> B) -> ~[B];
    pure fn flat_map_to_vec<B,IB: BaseIter<B>>(&self, op: fn(&A) -> IB)
        -> ~[B];
}

pub trait EqIter<A:Eq> {
    pure fn contains(&self, x: &A) -> bool;
    pure fn count(&self, x: &A) -> uint;
}

pub trait Times {
    pure fn times(&self, it: fn() -> bool);
}

pub trait CopyableIter<A:Copy> {
    pure fn filter_to_vec(&self, pred: fn(&A) -> bool) -> ~[A];
    pure fn to_vec(&self) -> ~[A];
    pure fn find(&self, p: fn(&A) -> bool) -> Option<A>;
}

pub trait CopyableOrderedIter<A:Copy + Ord> {
    pure fn min(&self) -> A;
    pure fn max(&self) -> A;
}

pub trait CopyableNonstrictIter<A:Copy> {
    // Like "each", but copies out the value. If the receiver is mutated while
    // iterating over it, the semantics must not be memory-unsafe but are
    // otherwise undefined.
    pure fn each_val(&const self, f: &fn(A) -> bool);
}

// A trait for sequences that can be built by imperatively pushing elements
// onto them.
pub trait Buildable<A> {
    /**
     * Builds a buildable sequence by calling a provided function with
     * an argument function that pushes an element onto the back of
     * the sequence.
     * This version takes an initial size for the sequence.
     *
     * # Arguments
     *
     * * size - A hint for an initial size of the sequence
     * * builder - A function that will construct the sequence. It receives
     *             as an argument a function that will push an element
     *             onto the sequence being constructed.
     */
     static pure fn build_sized(size: uint,
                                builder: fn(push: pure fn(A))) -> Self;
}

#[inline(always)]
pub pure fn eachi<A,IA:BaseIter<A>>(self: &IA,
                                    blk: fn(uint, &A) -> bool) {
    let mut i = 0;
    for self.each |a| {
        if !blk(i, a) { break; }
        i += 1;
    }
}

#[inline(always)]
pub pure fn all<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if !blk(a) { return false; }
    }
    return true;
}

#[inline(always)]
pub pure fn any<A,IA:BaseIter<A>>(self: &IA,
                                  blk: fn(&A) -> bool) -> bool {
    for self.each |a| {
        if blk(a) { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn filter_to_vec<A:Copy,IA:BaseIter<A>>(
    self: &IA, prd: fn(&A) -> bool) -> ~[A] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            if prd(a) { push(*a); }
        }
    }
}

#[inline(always)]
pub pure fn map_to_vec<A,B,IA:BaseIter<A>>(self: &IA,
                                           op: fn(&A) -> B)
    -> ~[B] {
    do vec::build_sized_opt(self.size_hint()) |push| {
        for self.each |a| {
            push(op(a));
        }
    }
}

#[inline(always)]
pub pure fn flat_map_to_vec<A,B,IA:BaseIter<A>,IB:BaseIter<B>>(
    self: &IA, op: fn(&A) -> IB) -> ~[B] {
    do vec::build |push| {
        for self.each |a| {
            for op(a).each |&b| {
                push(b);
            }
        }
    }
}

#[inline(always)]
pub pure fn foldl<A,B,IA:BaseIter<A>>(self: &IA, b0: B,
                                      blk: fn(&B, &A) -> B)
    -> B {
    let mut b = b0;
    for self.each |a| {
        b = blk(&b, a);
    }
    b
}

#[inline(always)]
pub pure fn to_vec<A:Copy,IA:BaseIter<A>>(self: &IA) -> ~[A] {
    foldl::<A,~[A],IA>(self, ~[], |r, a| vec::append(copy (*r), ~[*a]))
}

#[inline(always)]
pub pure fn contains<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> bool {
    for self.each |a| {
        if *a == *x { return true; }
    }
    return false;
}

#[inline(always)]
pub pure fn count<A:Eq,IA:BaseIter<A>>(self: &IA, x: &A) -> uint {
    do foldl(self, 0) |count, value| {
        if *value == *x {
            *count + 1
        } else {
            *count
        }
    }
}

#[inline(always)]
pub pure fn position<A,IA:BaseIter<A>>(self: &IA, f: fn(&A) -> bool)
    -> Option<uint>
{
    let mut i = 0;
    for self.each |a| {
        if f(a) { return Some(i); }
        i += 1;
    }
    return None;
}

// note: 'rposition' would only make sense to provide with a bidirectional
// iter interface, such as would provide "reach" in addition to "each". As is,
// it would have to be implemented with foldr, which is too inefficient.

#[inline(always)]
pub pure fn repeat(times: uint, blk: fn() -> bool) {
    let mut i = 0;
    while i < times {
        if !blk() { break }
        i += 1;
    }
}

#[inline(always)]
pub pure fn min<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ < *b => {
             *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"min called on empty iterator")
    }
}

#[inline(always)]
pub pure fn max<A:Copy + Ord,IA:BaseIter<A>>(self: &IA) -> A {
    match do foldl::<A,Option<A>,IA>(self, None) |a, b| {
        match a {
          &Some(ref a_) if *a_ > *b => {
              *(a)
          }
          _ => Some(*b)
        }
    } {
        Some(val) => val,
        None => fail!(~"max called on empty iterator")
    }
}

#[inline(always)]
pub pure fn find<A:Copy,IA:BaseIter<A>>(self: &IA,
                                   f: fn(&A) -> bool) -> Option<A> {
    for self.each |i| {
        if f(i) { return Some(*i) }
    }
    return None;
}

// Some functions for just building

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of a sequence.
 *
 * # Arguments
 *
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build<A,B: Buildable<A>>(builder: fn(push: pure fn(A)))
    -> B {
    Buildable::build_sized(4, builder)
}

/**
 * Builds a sequence by calling a provided function with an argument
 * function that pushes an element to the back of the sequence.
 * This version takes an initial size for the sequence.
 *
 * # Arguments
 *
 * * size - An option, maybe containing initial size of the sequence
 *          to reserve.
 * * builder - A function that will construct the sequence. It receives
 *             as an argument a function that will push an element
 *             onto the sequence being constructed.
 */
#[inline(always)]
pub pure fn build_sized_opt<A,B: Buildable<A>>(
    size: Option<uint>,
    builder: fn(push: pure fn(A))) -> B {

    Buildable::build_sized(size.get_or_default(4), builder)
}

// Functions that combine iteration and building

/// Applies a function to each element of an iterable and returns the results.
#[inline(always)]
pub fn map<T,IT: BaseIter<T>,U,BU: Buildable<U>>(v: &IT, f: fn(&T) -> U)
    -> BU {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each() |elem| {
            push(f(elem));
        }
    }
}

/**
 * Creates and initializes a generic sequence from a function.
 *
 * Creates a generic sequence of size `n_elts` and initializes the elements
 * to the value returned by the function `op`.
 */
#[inline(always)]
pub pure fn from_fn<T,BT: Buildable<T>>(n_elts: uint,
                                        op: InitOp<T>) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0u;
        while i < n_elts { push(op(i)); i += 1u; }
    }
}

/**
 * Creates and initializes a generic sequence with some elements.
 *
 * Creates an immutable vector of size `n_elts` and initializes the elements
 * to the value `t`.
 */
#[inline(always)]
pub pure fn from_elem<T:Copy,BT:Buildable<T>>(n_elts: uint,
                                                t: T) -> BT {
    do Buildable::build_sized(n_elts) |push| {
        let mut i: uint = 0;
        while i < n_elts { push(t); i += 1; }
    }
}

/// Appends two generic sequences.
#[inline(always)]
pub pure fn append<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    lhs: &IT, rhs: &IT) -> BT {
    let size_opt = lhs.size_hint().chain_ref(
        |sz1| rhs.size_hint().map(|sz2| *sz1+*sz2));
    do build_sized_opt(size_opt) |push| {
        for lhs.each |x| { push(*x); }
        for rhs.each |x| { push(*x); }
    }
}

/// Copies a generic sequence, possibly converting it to a different
/// type of sequence.
#[inline(always)]
pub pure fn copy_seq<T:Copy,IT:BaseIter<T>,BT:Buildable<T>>(
    v: &IT) -> BT {
    do build_sized_opt(v.size_hint()) |push| {
        for v.each |x| { push(*x); }
    }
}
<|endoftext|>


<commit_before><commit_msg>Add test of Display and Debug impls<commit_after>use anyhow::{bail, Context, Result};

fn f() -> Result<()> {
    bail!("oh no!");
}

fn g() -> Result<()> {
    f().context("f failed")
}

fn h() -> Result<()> {
    g().context("g failed")
}

const EXPECTED_DEBUG_F: &str = "\
oh no!

Backtrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace
";

const EXPECTED_DEBUG_G: &str = "\
f failed

Caused by:
    oh no!

Backtrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace
";

const EXPECTED_DEBUG_H: &str = "\
g failed

Caused by:
    0: f failed
    1: oh no!

Backtrace disabled; run with RUST_LIB_BACKTRACE=1 environment variable to display a backtrace
";

#[test]
fn test_display() {
    assert_eq!("g failed", h().unwrap_err().to_string());
}

#[test]
fn test_debug() {
    assert_eq!(EXPECTED_DEBUG_F, format!("{:?}", f().unwrap_err()));
    assert_eq!(EXPECTED_DEBUG_G, format!("{:?}", g().unwrap_err()));
    assert_eq!(EXPECTED_DEBUG_H, format!("{:?}", h().unwrap_err()));
}
<|endoftext|>


<commit_before>#![cfg(any(target_arch="x86", target_arch="x86_64"))]

#![no_std]
#![crate_name="cpu"]
#![crate_type="rlib"]
#![feature(asm)]

#[allow(unstable)] #[macro_use]
extern crate core;
#[macro_use]
extern crate bitflags;

pub use cpu::*;

#[cfg(target_arch="x86")]
#[path = "x86.rs"]
mod cpu;
#[cfg(target_arch="x86_64")]
#[path = "x86_64.rs"]
mod cpu;

pub mod std { pub use core::*; }
<commit_msg>Solve warnings<commit_after>#![cfg(any(target_arch="x86", target_arch="x86_64"))]

#![no_std]
#![crate_name="cpu"]
#![crate_type="rlib"]
#![feature(asm)]
#![feature(core)]
#![feature(hash)]

#[macro_use]
extern crate core;
#[macro_use]
extern crate bitflags;

pub use cpu::*;

#[cfg(target_arch="x86")]
#[path = "x86.rs"]
mod cpu;
#[cfg(target_arch="x86_64")]
#[path = "x86_64.rs"]
mod cpu;

pub mod std { pub use core::*; }
<|endoftext|>


<commit_before><commit_msg>added os specific install<commit_after><|endoftext|>


<commit_before><commit_msg>Update docs URL<commit_after><|endoftext|>


<commit_before><commit_msg>updated build.rs to use 'git describe --all'<commit_after><|endoftext|>


<commit_before><commit_msg>auto merge of #16697 : Sawyer47/rust/new-test, r=huonw<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// issues #10618 and #16382
static SIZE: int = 25;

fn main() {
    let _a: [bool, ..1 as uint];
    let _b: [int, ..SIZE as uint] = [1, ..SIZE as uint];
    let _c: [bool, ..'\n' as uint] = [true, ..'\n' as uint];
}
<|endoftext|>