<commit_before>//! Code for building the standard library.

use crate::core::compiler::UnitInterner;
use crate::core::compiler::{CompileKind, CompileMode, RustcTargetData, Unit};
use crate::core::profiles::{Profiles, UnitFor};
use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};
use crate::core::resolver::{HasDevUnits, ResolveOpts};
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
use crate::ops::{self, Packages};
use crate::util::errors::CargoResult;
use std::collections::{HashMap, HashSet};
use std::env;
use std::fs;
use std::path::PathBuf;

/// Parse the `-Zbuild-std` flag.
pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
    // This is a temporary hack until there is a more principled way to
    // declare dependencies in Cargo.toml.
    let value = value.unwrap_or("std");
    let mut crates: HashSet<&str> = value.split(',').collect();
    if crates.contains("std") {
        crates.insert("core");
        crates.insert("alloc");
        crates.insert("proc_macro");
        crates.insert("panic_unwind");
        crates.insert("compiler_builtins");
    } else if crates.contains("core") {
        crates.insert("compiler_builtins");
    }
    crates.into_iter().map(|s| s.to_string()).collect()
}

/// Resolve the standard library dependencies.
pub fn resolve_std<'cfg>(
    ws: &Workspace<'cfg>,
    target_data: &RustcTargetData,
    requested_targets: &[CompileKind],
    crates: &[String],
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
    let src_path = detect_sysroot_src_path(target_data)?;

    // Special std packages should be pulled from `library/` and should be
    // prefixed with `rustc-std-workspace-` in certain places.
    let libs_prefix = "library/";
    let special_std_prefix = "rustc-std-workspace-";
    let libs_path = src_path.join(libs_prefix);

    // Crates in rust-src to build. libtest is in some sense the "root" package
    // of std, as nothing else depends on it, so it must be explicitly added.
    let mut members = vec![format!("{}test", libs_prefix)];

    // If rust-src contains a "vendor" directory, then patch in all the crates it contains.
    let vendor_path = src_path.join("vendor");
    let vendor_dir = fs::read_dir(vendor_path)?;
    let patches = vendor_dir
        .into_iter()
        .map(|entry| {
            let entry = entry?;
            let name = entry
                .file_name()
                .into_string()
                .map_err(|_| anyhow::anyhow!("package name wasn't utf8"))?;

            // Remap the rustc-std-workspace crates to the actual rust-src libraries
            let path = if let Some(real_name) = name.strip_prefix(special_std_prefix) {
                // Record this crate as something to build in the workspace
                members.push(format!("{}{}", libs_prefix, real_name));
                libs_path.join(&name)
            } else {
                entry.path()
            };
            let source_path = SourceId::for_path(&path)?;
            let dep = Dependency::parse_no_deprecated(&name, None, source_path)?;
            Ok(dep)
        })
        .collect::<CargoResult<Vec<_>>>()?;

    let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap();
    let mut patch = HashMap::new();
    patch.insert(crates_io_url, patches);
    let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new(
        &src_path,
        &Some(members),
        /*default_members*/ &None,
        /*exclude*/ &None,
        /*custom_metadata*/ &None,
    ));
    let virtual_manifest = crate::core::VirtualManifest::new(
        /*replace*/ Vec::new(),
        patch,
        ws_config,
        /*profiles*/ None,
        crate::core::Features::default(),
        None,
    );

    let config = ws.config();
    // This is a delicate hack. In order for features to resolve correctly,
    // the resolver needs to run a specific "current" member of the workspace.
    // Thus, in order to set the features for `std`, we need to set `libtest`
    // to be the "current" member. `libtest` is the root, and all other
    // standard library crates are dependencies from there. Since none of the
    // other crates need to alter their features, this should be fine, for
    // now. Perhaps in the future features will be decoupled from the resolver
    // and it will be easier to control feature selection.
    let current_manifest = src_path.join("library/test/Cargo.toml");
    // TODO: Consider doing something to enforce --locked? Or to prevent the
    // lock file from being written, such as setting ephemeral.
    let mut std_ws = Workspace::new_virtual(src_path, current_manifest, virtual_manifest, config)?;
    // Don't require optional dependencies in this workspace, aka std's own
    // `[dev-dependencies]`. No need for us to generate a `Resolve` which has
    // those included because we'll never use them anyway.
    std_ws.set_require_optional_deps(false);
    // `test` is not in the default set because it is optional, but it needs
    // to be part of the resolve in case we do need it.
    let mut spec_pkgs = Vec::from(crates);
    spec_pkgs.push("test".to_string());
    let spec = Packages::Packages(spec_pkgs);
    let specs = spec.to_package_id_specs(&std_ws)?;
    let features = match &config.cli_unstable().build_std_features {
        Some(list) => list.clone(),
        None => vec![
            "panic-unwind".to_string(),
            "backtrace".to_string(),
            "default".to_string(),
        ],
    };
    // dev_deps setting shouldn't really matter here.
    let opts = ResolveOpts::new(
        /*dev_deps*/ false, &features, /*all_features*/ false,
        /*uses_default_features*/ false,
    );
    let resolve = ops::resolve_ws_with_opts(
        &std_ws,
        target_data,
        requested_targets,
        &opts,
        &specs,
        HasDevUnits::No,
        crate::core::resolver::features::ForceAllTargets::No,
    )?;
    Ok((
        resolve.pkg_set,
        resolve.targeted_resolve,
        resolve.resolved_features,
    ))
}

/// Generate a list of root `Unit`s for the standard library.
///
/// The given slice of crate names is the root set.
pub fn generate_std_roots(
    crates: &[String],
    std_resolve: &Resolve,
    std_features: &ResolvedFeatures,
    kinds: &[CompileKind],
    package_set: &PackageSet<'_>,
    interner: &UnitInterner,
    profiles: &Profiles,
) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {
    // Generate the root Units for the standard library.
    let std_ids = crates
        .iter()
        .map(|crate_name| std_resolve.query(crate_name))
        .collect::<CargoResult<Vec<PackageId>>>()?;
    // Convert PackageId to Package.
    let std_pkgs = package_set.get_many(std_ids)?;
    // Generate a map of Units for each kind requested.
    let mut ret = HashMap::new();
    for pkg in std_pkgs {
        let lib = pkg
            .targets()
            .iter()
            .find(|t| t.is_lib())
            .expect("std has a lib");
        let unit_for = UnitFor::new_normal();
        // I don't think we need to bother with Check here, the difference
        // in time is minimal, and the difference in caching is
        // significant.
        let mode = CompileMode::Build;
        let profile = profiles.get_profile(
            pkg.package_id(),
            /*is_member*/ false,
            /*is_local*/ false,
            unit_for,
            mode,
        );
        let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);

        for kind in kinds {
            let list = ret.entry(*kind).or_insert_with(Vec::new);
            list.push(interner.intern(
                pkg,
                lib,
                profile,
                *kind,
                mode,
                features.clone(),
                /*is_std*/ true,
                /*dep_hash*/ 0,
            ));
        }
    }
    Ok(ret)
}

fn detect_sysroot_src_path(target_data: &RustcTargetData) -> CargoResult<PathBuf> {
    if let Some(s) = env::var_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
        return Ok(s.into());
    }

    // NOTE: This is temporary until we figure out how to acquire the source.
    let src_path = target_data
        .info(CompileKind::Host)
        .sysroot
        .join("lib")
        .join("rustlib")
        .join("src")
        .join("rust");
    let lock = src_path.join("Cargo.lock");
    if !lock.exists() {
        anyhow::bail!(
            "{:?} does not exist, unable to build with the standard \
             library, try:\n        rustup component add rust-src",
            lock
        );
    }
    Ok(src_path)
}
<commit_msg>Add error context for reading vendor dir.<commit_after>//! Code for building the standard library.

use crate::core::compiler::UnitInterner;
use crate::core::compiler::{CompileKind, CompileMode, RustcTargetData, Unit};
use crate::core::profiles::{Profiles, UnitFor};
use crate::core::resolver::features::{FeaturesFor, ResolvedFeatures};
use crate::core::resolver::{HasDevUnits, ResolveOpts};
use crate::core::{Dependency, PackageId, PackageSet, Resolve, SourceId, Workspace};
use crate::ops::{self, Packages};
use crate::util::errors::{CargoResult, CargoResultExt};
use std::collections::{HashMap, HashSet};
use std::env;
use std::fs;
use std::path::PathBuf;

/// Parse the `-Zbuild-std` flag.
pub fn parse_unstable_flag(value: Option<&str>) -> Vec<String> {
    // This is a temporary hack until there is a more principled way to
    // declare dependencies in Cargo.toml.
    let value = value.unwrap_or("std");
    let mut crates: HashSet<&str> = value.split(',').collect();
    if crates.contains("std") {
        crates.insert("core");
        crates.insert("alloc");
        crates.insert("proc_macro");
        crates.insert("panic_unwind");
        crates.insert("compiler_builtins");
    } else if crates.contains("core") {
        crates.insert("compiler_builtins");
    }
    crates.into_iter().map(|s| s.to_string()).collect()
}

/// Resolve the standard library dependencies.
pub fn resolve_std<'cfg>(
    ws: &Workspace<'cfg>,
    target_data: &RustcTargetData,
    requested_targets: &[CompileKind],
    crates: &[String],
) -> CargoResult<(PackageSet<'cfg>, Resolve, ResolvedFeatures)> {
    let src_path = detect_sysroot_src_path(target_data)?;

    // Special std packages should be pulled from `library/` and should be
    // prefixed with `rustc-std-workspace-` in certain places.
    let libs_prefix = "library/";
    let special_std_prefix = "rustc-std-workspace-";
    let libs_path = src_path.join(libs_prefix);

    // Crates in rust-src to build. libtest is in some sense the "root" package
    // of std, as nothing else depends on it, so it must be explicitly added.
    let mut members = vec![format!("{}test", libs_prefix)];

    // If rust-src contains a "vendor" directory, then patch in all the crates it contains.
    let vendor_path = src_path.join("vendor");
    let vendor_dir = fs::read_dir(&vendor_path)
        .chain_err(|| format!("could not read vendor path {}", vendor_path.display()))?;
    let patches = vendor_dir
        .into_iter()
        .map(|entry| {
            let entry = entry?;
            let name = entry
                .file_name()
                .into_string()
                .map_err(|_| anyhow::anyhow!("package name wasn't utf8"))?;

            // Remap the rustc-std-workspace crates to the actual rust-src libraries
            let path = if let Some(real_name) = name.strip_prefix(special_std_prefix) {
                // Record this crate as something to build in the workspace
                members.push(format!("{}{}", libs_prefix, real_name));
                libs_path.join(&name)
            } else {
                entry.path()
            };
            let source_path = SourceId::for_path(&path)?;
            let dep = Dependency::parse_no_deprecated(&name, None, source_path)?;
            Ok(dep)
        })
        .collect::<CargoResult<Vec<_>>>()
        .chain_err(|| "failed to generate vendor patches")?;

    let crates_io_url = crate::sources::CRATES_IO_INDEX.parse().unwrap();
    let mut patch = HashMap::new();
    patch.insert(crates_io_url, patches);
    let ws_config = crate::core::WorkspaceConfig::Root(crate::core::WorkspaceRootConfig::new(
        &src_path,
        &Some(members),
        /*default_members*/ &None,
        /*exclude*/ &None,
        /*custom_metadata*/ &None,
    ));
    let virtual_manifest = crate::core::VirtualManifest::new(
        /*replace*/ Vec::new(),
        patch,
        ws_config,
        /*profiles*/ None,
        crate::core::Features::default(),
        None,
    );

    let config = ws.config();
    // This is a delicate hack. In order for features to resolve correctly,
    // the resolver needs to run a specific "current" member of the workspace.
    // Thus, in order to set the features for `std`, we need to set `libtest`
    // to be the "current" member. `libtest` is the root, and all other
    // standard library crates are dependencies from there. Since none of the
    // other crates need to alter their features, this should be fine, for
    // now. Perhaps in the future features will be decoupled from the resolver
    // and it will be easier to control feature selection.
    let current_manifest = src_path.join("library/test/Cargo.toml");
    // TODO: Consider doing something to enforce --locked? Or to prevent the
    // lock file from being written, such as setting ephemeral.
    let mut std_ws = Workspace::new_virtual(src_path, current_manifest, virtual_manifest, config)?;
    // Don't require optional dependencies in this workspace, aka std's own
    // `[dev-dependencies]`. No need for us to generate a `Resolve` which has
    // those included because we'll never use them anyway.
    std_ws.set_require_optional_deps(false);
    // `test` is not in the default set because it is optional, but it needs
    // to be part of the resolve in case we do need it.
    let mut spec_pkgs = Vec::from(crates);
    spec_pkgs.push("test".to_string());
    let spec = Packages::Packages(spec_pkgs);
    let specs = spec.to_package_id_specs(&std_ws)?;
    let features = match &config.cli_unstable().build_std_features {
        Some(list) => list.clone(),
        None => vec![
            "panic-unwind".to_string(),
            "backtrace".to_string(),
            "default".to_string(),
        ],
    };
    // dev_deps setting shouldn't really matter here.
    let opts = ResolveOpts::new(
        /*dev_deps*/ false, &features, /*all_features*/ false,
        /*uses_default_features*/ false,
    );
    let resolve = ops::resolve_ws_with_opts(
        &std_ws,
        target_data,
        requested_targets,
        &opts,
        &specs,
        HasDevUnits::No,
        crate::core::resolver::features::ForceAllTargets::No,
    )?;
    Ok((
        resolve.pkg_set,
        resolve.targeted_resolve,
        resolve.resolved_features,
    ))
}

/// Generate a list of root `Unit`s for the standard library.
///
/// The given slice of crate names is the root set.
pub fn generate_std_roots(
    crates: &[String],
    std_resolve: &Resolve,
    std_features: &ResolvedFeatures,
    kinds: &[CompileKind],
    package_set: &PackageSet<'_>,
    interner: &UnitInterner,
    profiles: &Profiles,
) -> CargoResult<HashMap<CompileKind, Vec<Unit>>> {
    // Generate the root Units for the standard library.
    let std_ids = crates
        .iter()
        .map(|crate_name| std_resolve.query(crate_name))
        .collect::<CargoResult<Vec<PackageId>>>()?;
    // Convert PackageId to Package.
    let std_pkgs = package_set.get_many(std_ids)?;
    // Generate a map of Units for each kind requested.
    let mut ret = HashMap::new();
    for pkg in std_pkgs {
        let lib = pkg
            .targets()
            .iter()
            .find(|t| t.is_lib())
            .expect("std has a lib");
        let unit_for = UnitFor::new_normal();
        // I don't think we need to bother with Check here, the difference
        // in time is minimal, and the difference in caching is
        // significant.
        let mode = CompileMode::Build;
        let profile = profiles.get_profile(
            pkg.package_id(),
            /*is_member*/ false,
            /*is_local*/ false,
            unit_for,
            mode,
        );
        let features = std_features.activated_features(pkg.package_id(), FeaturesFor::NormalOrDev);

        for kind in kinds {
            let list = ret.entry(*kind).or_insert_with(Vec::new);
            list.push(interner.intern(
                pkg,
                lib,
                profile,
                *kind,
                mode,
                features.clone(),
                /*is_std*/ true,
                /*dep_hash*/ 0,
            ));
        }
    }
    Ok(ret)
}

fn detect_sysroot_src_path(target_data: &RustcTargetData) -> CargoResult<PathBuf> {
    if let Some(s) = env::var_os("__CARGO_TESTS_ONLY_SRC_ROOT") {
        return Ok(s.into());
    }

    // NOTE: This is temporary until we figure out how to acquire the source.
    let src_path = target_data
        .info(CompileKind::Host)
        .sysroot
        .join("lib")
        .join("rustlib")
        .join("src")
        .join("rust");
    let lock = src_path.join("Cargo.lock");
    if !lock.exists() {
        anyhow::bail!(
            "{:?} does not exist, unable to build with the standard \
             library, try:\n        rustup component add rust-src",
            lock
        );
    }
    Ok(src_path)
}
<|endoftext|>


<commit_before>//xfail-stage0

use std;

fn main() {

    obj a() {
        fn foo() -> int {
            ret 2;
        }
        fn bar() -> int {
            ret self.foo();
        }
    }

    auto my_a = a();

    // An anonymous object that overloads the 'foo' method.
    auto my_b = obj() {
        fn foo() -> int {
            ret 3;
        }

        with my_a
    };

    assert (my_b.foo() == 3);
    assert (my_b.bar() == 3);
}
<commit_msg>Test method overriding a little more.<commit_after>//xfail-stage0

use std;

fn main() {

    obj a() {
        fn foo() -> int {
            ret 2;
        }
        fn bar() -> int {
            ret self.foo();
        }
    }

    auto my_a = a();

    // An anonymous object that overloads the 'foo' method.
    auto my_b = obj() {
        fn foo() -> int {
            ret 3;
        }

        with my_a
    };

    assert (my_b.foo() == 3);
    assert (my_b.bar() == 3);

    auto my_c = obj() {
        fn baz(int x, int y) -> int {
            ret x + y + self.foo();
        }
        with my_b
    };

    auto my_d = obj() {
        fn baz(int x, int y) -> int {
            ret x + y + self.foo();
        }
        with my_a
    };

    assert (my_c.baz(1, 2) == 6);
    assert (my_d.baz(1, 2) == 5);
}
<|endoftext|>


<commit_before>// xfail-stage0
// xfail-stage1
// xfail-stage2
// xfail-stage3

// Test case for issue #763, provided by robarnold.

use std;
import std::task;

tag request {
  quit;
  close(int, chan[bool]);
}

type ctx = chan[request];

fn request_task(c : chan[ctx]) {
    let p = port();
    c <| chan(p);
    let req;
    while (true) {
        p |> req;
        alt (req) {
            quit. {
                ret;
            }
            close(what, status) {
                log "closing now";
                log what;
                status <| true;
            }
        }
    }
}

fn new() -> ctx {
    let p = port();
    let t = spawn request_task(chan(p));
    let cx;
    p |> cx;
    ret cx;
}

fn main() {
    let cx = new();

    let p = port();
    cx <| close(4, chan(p));
    let result;
    p |> result;
    cx <| quit;
}
<commit_msg>Remove task-comm-chan-chan test<commit_after><|endoftext|>


<commit_before><commit_msg>Add test case for #22743.<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.

use std::ops::Mul;

#[derive(Copy)]
pub struct Foo {
    x: f64,
}

impl Mul<Foo> for f64 {
    type Output = Foo;

    fn mul(self, rhs: Foo) -> Foo {
        // intentionally do something that is not *
        Foo { x: self + rhs.x }
    }
}

pub fn main() {
    let f: Foo = Foo { x: 5.0 };
    let val: f64 = 3.0;
    let f2: Foo = val * f;
    assert_eq!(f2.x, 8.0);
}
<|endoftext|>


<commit_before><commit_msg>Using the rs API instead.<commit_after><|endoftext|>


<commit_before><commit_msg>EntitView now use a BitvSet to store entities<commit_after><|endoftext|>


<commit_before><commit_msg>Fix timer bug in Display impl<commit_after><|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.

// Functions dealing with attributes and meta_items

use std::map;
use std::map::HashMap;
use either::Either;
use diagnostic::span_handler;
use ast_util::{spanned, dummy_spanned};
use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
use codemap::BytePos;

// Constructors
export mk_name_value_item_str;
export mk_name_value_item;
export mk_list_item;
export mk_word_item;
export mk_attr;
export mk_sugared_doc_attr;

// Conversion
export attr_meta;
export attr_metas;
export desugar_doc_attr;

// Accessors
export get_attr_name;
export get_meta_item_name;
export get_meta_item_value_str;
export get_meta_item_list;
export get_name_value_str_pair;

// Searching
export find_attrs_by_name;
export find_meta_items_by_name;
export contains;
export contains_name;
export attrs_contains_name;
export first_attr_value_str_by_name;
export last_meta_item_value_str_by_name;
export last_meta_item_list_by_name;

// Higher-level applications
export sort_meta_items;
export remove_meta_items_by_name;
export find_linkage_attrs;
export find_linkage_metas;
export foreign_abi;
export inline_attr;
export find_inline_attr;
export require_unique_names;

/* Constructors */

fn mk_name_value_item_str(name: ~str, +value: ~str) ->
    @ast::meta_item {
    let value_lit = dummy_spanned(ast::lit_str(@value));
    return mk_name_value_item(name, value_lit);
}

fn mk_name_value_item(name: ~str, +value: ast::lit)
        -> @ast::meta_item {
    return @dummy_spanned(ast::meta_name_value(name, value));
}

fn mk_list_item(name: ~str, +items: ~[@ast::meta_item]) ->
   @ast::meta_item {
    return @dummy_spanned(ast::meta_list(name, items));
}

fn mk_word_item(name: ~str) -> @ast::meta_item {
    return @dummy_spanned(ast::meta_word(name));
}

fn mk_attr(item: @ast::meta_item) -> ast::attribute {
    return dummy_spanned({style: ast::attr_inner, value: *item,
                       is_sugared_doc: false});
}

fn mk_sugared_doc_attr(text: ~str,
                       +lo: BytePos, +hi: BytePos) -> ast::attribute {
    let lit = spanned(lo, hi, ast::lit_str(@text));
    let attr = {
        style: doc_comment_style(text),
        value: spanned(lo, hi, ast::meta_name_value(~"doc", lit)),
        is_sugared_doc: true
    };
    return spanned(lo, hi, attr);
}

/* Conversion */

fn attr_meta(attr: ast::attribute) -> @ast::meta_item { @attr.node.value }

// Get the meta_items from inside a vector of attributes
fn attr_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] {
    do attrs.map |a| { attr_meta(*a) }
}

fn desugar_doc_attr(attr: &ast::attribute) -> ast::attribute {
    if attr.node.is_sugared_doc {
        let comment = get_meta_item_value_str(@attr.node.value).get();
        let meta = mk_name_value_item_str(~"doc",
                                     strip_doc_comment_decoration(comment));
        return mk_attr(meta);
    } else {
        *attr
    }
}

/* Accessors */

fn get_attr_name(attr: ast::attribute) -> ~str {
    get_meta_item_name(@attr.node.value)
}

fn get_meta_item_name(meta: @ast::meta_item) -> ~str {
    match meta.node {
      ast::meta_word(ref n) => (*n),
      ast::meta_name_value(ref n, _) => (*n),
      ast::meta_list(ref n, _) => (*n)
    }
}

/**
 * Gets the string value if the meta_item is a meta_name_value variant
 * containing a string, otherwise none
 */
fn get_meta_item_value_str(meta: @ast::meta_item) -> Option<~str> {
    match meta.node {
        ast::meta_name_value(_, v) => match v.node {
            ast::lit_str(s) => option::Some(*s),
            _ => option::None
        },
        _ => option::None
    }
}

/// Gets a list of inner meta items from a list meta_item type
fn get_meta_item_list(meta: @ast::meta_item) -> Option<~[@ast::meta_item]> {
    match meta.node {
      ast::meta_list(_, l) => option::Some(/* FIXME (#2543) */ copy l),
      _ => option::None
    }
}

/**
 * If the meta item is a nam-value type with a string value then returns
 * a tuple containing the name and string value, otherwise `none`
 */
fn get_name_value_str_pair(item: @ast::meta_item) -> Option<(~str, ~str)> {
    match attr::get_meta_item_value_str(item) {
      Some(ref value) => {
        let name = attr::get_meta_item_name(item);
        Some((name, (*value)))
      }
      None => None
    }
}

/* Searching */

/// Search a list of attributes and return only those with a specific name
fn find_attrs_by_name(attrs: ~[ast::attribute], name: ~str) ->
   ~[ast::attribute] {
    let filter = (
        fn@(a: &ast::attribute) -> Option<ast::attribute> {
            if get_attr_name(*a) == name {
                option::Some(*a)
            } else { option::None }
        }
    );
    return vec::filter_map(attrs, filter);
}

/// Searcha list of meta items and return only those with a specific name
fn find_meta_items_by_name(metas: ~[@ast::meta_item], name: ~str) ->
   ~[@ast::meta_item] {
    let filter = fn@(m: &@ast::meta_item) -> Option<@ast::meta_item> {
        if get_meta_item_name(*m) == name {
            option::Some(*m)
        } else { option::None }
    };
    return vec::filter_map(metas, filter);
}

/**
 * Returns true if a list of meta items contains another meta item. The
 * comparison is performed structurally.
 */
fn contains(haystack: ~[@ast::meta_item], needle: @ast::meta_item) -> bool {
    for haystack.each |item| {
        if eq(*item, needle) { return true; }
    }
    return false;
}

fn eq(a: @ast::meta_item, b: @ast::meta_item) -> bool {
    return match a.node {
          ast::meta_word(ref na) => match b.node {
            ast::meta_word(ref nb) => (*na) == (*nb),
            _ => false
          },
          ast::meta_name_value(ref na, va) => match b.node {
            ast::meta_name_value(ref nb, vb) => {
                (*na) == (*nb) && va.node == vb.node
            }
            _ => false
          },
          ast::meta_list(*) => {

            // ~[Fixme-sorting]
            // FIXME (#607): Needs implementing
            // This involves probably sorting the list by name and
            // meta_item variant
            fail ~"unimplemented meta_item variant"
          }
        }
}

fn contains_name(metas: ~[@ast::meta_item], name: ~str) -> bool {
    let matches = find_meta_items_by_name(metas, name);
    return vec::len(matches) > 0u;
}

fn attrs_contains_name(attrs: ~[ast::attribute], name: ~str) -> bool {
    vec::is_not_empty(find_attrs_by_name(attrs, name))
}

fn first_attr_value_str_by_name(attrs: ~[ast::attribute], name: ~str)
    -> Option<~str> {

    let mattrs = find_attrs_by_name(attrs, name);
    if vec::len(mattrs) > 0u {
        return get_meta_item_value_str(attr_meta(mattrs[0]));
    }
    return option::None;
}

fn last_meta_item_by_name(items: ~[@ast::meta_item], name: ~str)
    -> Option<@ast::meta_item> {

    let items = attr::find_meta_items_by_name(items, name);
    vec::last_opt(items)
}

fn last_meta_item_value_str_by_name(items: ~[@ast::meta_item], name: ~str)
    -> Option<~str> {

    match last_meta_item_by_name(items, name) {
      Some(item) => match attr::get_meta_item_value_str(item) {
        Some(ref value) => Some((*value)),
        None => None
      },
      None => None
    }
}

fn last_meta_item_list_by_name(items: ~[@ast::meta_item], name: ~str)
    -> Option<~[@ast::meta_item]> {

    match last_meta_item_by_name(items, name) {
      Some(item) => attr::get_meta_item_list(item),
      None => None
    }
}

/* Higher-level applications */

// FIXME (#607): This needs to sort by meta_item variant in addition to
// the item name (See [Fixme-sorting])
fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
    pure fn lteq(ma: &@ast::meta_item, mb: &@ast::meta_item) -> bool {
        pure fn key(m: &ast::meta_item) -> ~str {
            match m.node {
              ast::meta_word(ref name) => (*name),
              ast::meta_name_value(ref name, _) => (*name),
              ast::meta_list(ref name, _) => (*name)
            }
        }
        key(*ma) <= key(*mb)
    }

    // This is sort of stupid here, converting to a vec of mutables and back
    let v: ~[mut @ast::meta_item] = vec::to_mut(items);
    std::sort::quick_sort(v, lteq);
    vec::from_mut(move v)
}

fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: ~str) ->
   ~[@ast::meta_item] {

    return vec::filter_map(items, |item| {
        if get_meta_item_name(*item) != name {
            option::Some(/* FIXME (#2543) */ copy *item)
        } else {
            option::None
        }
    });
}

/**
 * From a list of crate attributes get only the meta_items that affect crate
 * linkage
 */
fn find_linkage_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] {
    do find_attrs_by_name(attrs, ~"link").flat_map |attr| {
        match attr.node.value.node {
            ast::meta_list(_, items) => /* FIXME (#2543) */ copy items,
            _ => ~[]
        }
    }
}

fn foreign_abi(attrs: ~[ast::attribute]) -> Either<~str, ast::foreign_abi> {
    return match attr::first_attr_value_str_by_name(attrs, ~"abi") {
      option::None => {
        either::Right(ast::foreign_abi_cdecl)
      }
      option::Some(~"rust-intrinsic") => {
        either::Right(ast::foreign_abi_rust_intrinsic)
      }
      option::Some(~"cdecl") => {
        either::Right(ast::foreign_abi_cdecl)
      }
      option::Some(~"stdcall") => {
        either::Right(ast::foreign_abi_stdcall)
      }
      option::Some(ref t) => {
        either::Left(~"unsupported abi: " + (*t))
      }
    };
}

enum inline_attr {
    ia_none,
    ia_hint,
    ia_always,
    ia_never,
}

impl inline_attr : cmp::Eq {
    pure fn eq(&self, other: &inline_attr) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &inline_attr) -> bool { !(*self).eq(other) }
}

/// True if something like #[inline] is found in the list of attrs.
fn find_inline_attr(attrs: ~[ast::attribute]) -> inline_attr {
    // FIXME (#2809)---validate the usage of #[inline] and #[inline(always)]
    do vec::foldl(ia_none, attrs) |ia,attr| {
        match attr.node.value.node {
          ast::meta_word(~"inline") => ia_hint,
          ast::meta_list(~"inline", items) => {
            if !vec::is_empty(find_meta_items_by_name(items, ~"always")) {
                ia_always
            } else if !vec::is_empty(
                find_meta_items_by_name(items, ~"never")) {
                ia_never
            } else {
                ia_hint
            }
          }
          _ => ia
        }
    }
}

fn require_unique_names(diagnostic: span_handler,
                        metas: ~[@ast::meta_item]) {
    let map = map::HashMap();
    for metas.each |meta| {
        let name = get_meta_item_name(*meta);

        // FIXME: How do I silence the warnings? --pcw (#2619)
        if map.contains_key(name) {
            diagnostic.span_fatal(meta.span,
                                  fmt!("duplicate meta item `%s`", name));
        }
        map.insert(name, ());
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<commit_msg>re-fix typo<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Functions dealing with attributes and meta_items

use std::map;
use std::map::HashMap;
use either::Either;
use diagnostic::span_handler;
use ast_util::{spanned, dummy_spanned};
use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
use codemap::BytePos;

// Constructors
export mk_name_value_item_str;
export mk_name_value_item;
export mk_list_item;
export mk_word_item;
export mk_attr;
export mk_sugared_doc_attr;

// Conversion
export attr_meta;
export attr_metas;
export desugar_doc_attr;

// Accessors
export get_attr_name;
export get_meta_item_name;
export get_meta_item_value_str;
export get_meta_item_list;
export get_name_value_str_pair;

// Searching
export find_attrs_by_name;
export find_meta_items_by_name;
export contains;
export contains_name;
export attrs_contains_name;
export first_attr_value_str_by_name;
export last_meta_item_value_str_by_name;
export last_meta_item_list_by_name;

// Higher-level applications
export sort_meta_items;
export remove_meta_items_by_name;
export find_linkage_attrs;
export find_linkage_metas;
export foreign_abi;
export inline_attr;
export find_inline_attr;
export require_unique_names;

/* Constructors */

fn mk_name_value_item_str(name: ~str, +value: ~str) ->
    @ast::meta_item {
    let value_lit = dummy_spanned(ast::lit_str(@value));
    return mk_name_value_item(name, value_lit);
}

fn mk_name_value_item(name: ~str, +value: ast::lit)
        -> @ast::meta_item {
    return @dummy_spanned(ast::meta_name_value(name, value));
}

fn mk_list_item(name: ~str, +items: ~[@ast::meta_item]) ->
   @ast::meta_item {
    return @dummy_spanned(ast::meta_list(name, items));
}

fn mk_word_item(name: ~str) -> @ast::meta_item {
    return @dummy_spanned(ast::meta_word(name));
}

fn mk_attr(item: @ast::meta_item) -> ast::attribute {
    return dummy_spanned({style: ast::attr_inner, value: *item,
                       is_sugared_doc: false});
}

fn mk_sugared_doc_attr(text: ~str,
                       +lo: BytePos, +hi: BytePos) -> ast::attribute {
    let lit = spanned(lo, hi, ast::lit_str(@text));
    let attr = {
        style: doc_comment_style(text),
        value: spanned(lo, hi, ast::meta_name_value(~"doc", lit)),
        is_sugared_doc: true
    };
    return spanned(lo, hi, attr);
}

/* Conversion */

fn attr_meta(attr: ast::attribute) -> @ast::meta_item { @attr.node.value }

// Get the meta_items from inside a vector of attributes
fn attr_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] {
    do attrs.map |a| { attr_meta(*a) }
}

fn desugar_doc_attr(attr: &ast::attribute) -> ast::attribute {
    if attr.node.is_sugared_doc {
        let comment = get_meta_item_value_str(@attr.node.value).get();
        let meta = mk_name_value_item_str(~"doc",
                                     strip_doc_comment_decoration(comment));
        return mk_attr(meta);
    } else {
        *attr
    }
}

/* Accessors */

fn get_attr_name(attr: ast::attribute) -> ~str {
    get_meta_item_name(@attr.node.value)
}

fn get_meta_item_name(meta: @ast::meta_item) -> ~str {
    match meta.node {
      ast::meta_word(ref n) => (*n),
      ast::meta_name_value(ref n, _) => (*n),
      ast::meta_list(ref n, _) => (*n)
    }
}

/**
 * Gets the string value if the meta_item is a meta_name_value variant
 * containing a string, otherwise none
 */
fn get_meta_item_value_str(meta: @ast::meta_item) -> Option<~str> {
    match meta.node {
        ast::meta_name_value(_, v) => match v.node {
            ast::lit_str(s) => option::Some(*s),
            _ => option::None
        },
        _ => option::None
    }
}

/// Gets a list of inner meta items from a list meta_item type
fn get_meta_item_list(meta: @ast::meta_item) -> Option<~[@ast::meta_item]> {
    match meta.node {
      ast::meta_list(_, l) => option::Some(/* FIXME (#2543) */ copy l),
      _ => option::None
    }
}

/**
 * If the meta item is a nam-value type with a string value then returns
 * a tuple containing the name and string value, otherwise `none`
 */
fn get_name_value_str_pair(item: @ast::meta_item) -> Option<(~str, ~str)> {
    match attr::get_meta_item_value_str(item) {
      Some(ref value) => {
        let name = attr::get_meta_item_name(item);
        Some((name, (*value)))
      }
      None => None
    }
}

/* Searching */

/// Search a list of attributes and return only those with a specific name
fn find_attrs_by_name(attrs: ~[ast::attribute], name: ~str) ->
   ~[ast::attribute] {
    let filter = (
        fn@(a: &ast::attribute) -> Option<ast::attribute> {
            if get_attr_name(*a) == name {
                option::Some(*a)
            } else { option::None }
        }
    );
    return vec::filter_map(attrs, filter);
}

/// Search a list of meta items and return only those with a specific name
fn find_meta_items_by_name(metas: ~[@ast::meta_item], name: ~str) ->
   ~[@ast::meta_item] {
    let filter = fn@(m: &@ast::meta_item) -> Option<@ast::meta_item> {
        if get_meta_item_name(*m) == name {
            option::Some(*m)
        } else { option::None }
    };
    return vec::filter_map(metas, filter);
}

/**
 * Returns true if a list of meta items contains another meta item. The
 * comparison is performed structurally.
 */
fn contains(haystack: ~[@ast::meta_item], needle: @ast::meta_item) -> bool {
    for haystack.each |item| {
        if eq(*item, needle) { return true; }
    }
    return false;
}

fn eq(a: @ast::meta_item, b: @ast::meta_item) -> bool {
    return match a.node {
          ast::meta_word(ref na) => match b.node {
            ast::meta_word(ref nb) => (*na) == (*nb),
            _ => false
          },
          ast::meta_name_value(ref na, va) => match b.node {
            ast::meta_name_value(ref nb, vb) => {
                (*na) == (*nb) && va.node == vb.node
            }
            _ => false
          },
          ast::meta_list(*) => {

            // ~[Fixme-sorting]
            // FIXME (#607): Needs implementing
            // This involves probably sorting the list by name and
            // meta_item variant
            fail ~"unimplemented meta_item variant"
          }
        }
}

fn contains_name(metas: ~[@ast::meta_item], name: ~str) -> bool {
    let matches = find_meta_items_by_name(metas, name);
    return vec::len(matches) > 0u;
}

fn attrs_contains_name(attrs: ~[ast::attribute], name: ~str) -> bool {
    vec::is_not_empty(find_attrs_by_name(attrs, name))
}

fn first_attr_value_str_by_name(attrs: ~[ast::attribute], name: ~str)
    -> Option<~str> {

    let mattrs = find_attrs_by_name(attrs, name);
    if vec::len(mattrs) > 0u {
        return get_meta_item_value_str(attr_meta(mattrs[0]));
    }
    return option::None;
}

fn last_meta_item_by_name(items: ~[@ast::meta_item], name: ~str)
    -> Option<@ast::meta_item> {

    let items = attr::find_meta_items_by_name(items, name);
    vec::last_opt(items)
}

fn last_meta_item_value_str_by_name(items: ~[@ast::meta_item], name: ~str)
    -> Option<~str> {

    match last_meta_item_by_name(items, name) {
      Some(item) => match attr::get_meta_item_value_str(item) {
        Some(ref value) => Some((*value)),
        None => None
      },
      None => None
    }
}

fn last_meta_item_list_by_name(items: ~[@ast::meta_item], name: ~str)
    -> Option<~[@ast::meta_item]> {

    match last_meta_item_by_name(items, name) {
      Some(item) => attr::get_meta_item_list(item),
      None => None
    }
}

/* Higher-level applications */

// FIXME (#607): This needs to sort by meta_item variant in addition to
// the item name (See [Fixme-sorting])
fn sort_meta_items(+items: ~[@ast::meta_item]) -> ~[@ast::meta_item] {
    pure fn lteq(ma: &@ast::meta_item, mb: &@ast::meta_item) -> bool {
        pure fn key(m: &ast::meta_item) -> ~str {
            match m.node {
              ast::meta_word(ref name) => (*name),
              ast::meta_name_value(ref name, _) => (*name),
              ast::meta_list(ref name, _) => (*name)
            }
        }
        key(*ma) <= key(*mb)
    }

    // This is sort of stupid here, converting to a vec of mutables and back
    let v: ~[mut @ast::meta_item] = vec::to_mut(items);
    std::sort::quick_sort(v, lteq);
    vec::from_mut(move v)
}

fn remove_meta_items_by_name(items: ~[@ast::meta_item], name: ~str) ->
   ~[@ast::meta_item] {

    return vec::filter_map(items, |item| {
        if get_meta_item_name(*item) != name {
            option::Some(/* FIXME (#2543) */ copy *item)
        } else {
            option::None
        }
    });
}

/**
 * From a list of crate attributes get only the meta_items that affect crate
 * linkage
 */
fn find_linkage_metas(attrs: ~[ast::attribute]) -> ~[@ast::meta_item] {
    do find_attrs_by_name(attrs, ~"link").flat_map |attr| {
        match attr.node.value.node {
            ast::meta_list(_, items) => /* FIXME (#2543) */ copy items,
            _ => ~[]
        }
    }
}

fn foreign_abi(attrs: ~[ast::attribute]) -> Either<~str, ast::foreign_abi> {
    return match attr::first_attr_value_str_by_name(attrs, ~"abi") {
      option::None => {
        either::Right(ast::foreign_abi_cdecl)
      }
      option::Some(~"rust-intrinsic") => {
        either::Right(ast::foreign_abi_rust_intrinsic)
      }
      option::Some(~"cdecl") => {
        either::Right(ast::foreign_abi_cdecl)
      }
      option::Some(~"stdcall") => {
        either::Right(ast::foreign_abi_stdcall)
      }
      option::Some(ref t) => {
        either::Left(~"unsupported abi: " + (*t))
      }
    };
}

enum inline_attr {
    ia_none,
    ia_hint,
    ia_always,
    ia_never,
}

impl inline_attr : cmp::Eq {
    pure fn eq(&self, other: &inline_attr) -> bool {
        ((*self) as uint) == ((*other) as uint)
    }
    pure fn ne(&self, other: &inline_attr) -> bool { !(*self).eq(other) }
}

/// True if something like #[inline] is found in the list of attrs.
fn find_inline_attr(attrs: ~[ast::attribute]) -> inline_attr {
    // FIXME (#2809)---validate the usage of #[inline] and #[inline(always)]
    do vec::foldl(ia_none, attrs) |ia,attr| {
        match attr.node.value.node {
          ast::meta_word(~"inline") => ia_hint,
          ast::meta_list(~"inline", items) => {
            if !vec::is_empty(find_meta_items_by_name(items, ~"always")) {
                ia_always
            } else if !vec::is_empty(
                find_meta_items_by_name(items, ~"never")) {
                ia_never
            } else {
                ia_hint
            }
          }
          _ => ia
        }
    }
}

fn require_unique_names(diagnostic: span_handler,
                        metas: ~[@ast::meta_item]) {
    let map = map::HashMap();
    for metas.each |meta| {
        let name = get_meta_item_name(*meta);

        // FIXME: How do I silence the warnings? --pcw (#2619)
        if map.contains_key(name) {
            diagnostic.span_fatal(meta.span,
                                  fmt!("duplicate meta item `%s`", name));
        }
        map.insert(name, ());
    }
}

//
// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//
<|endoftext|>


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

//! # The Unicode Library
//!
//! Unicode-intensive functions for `char` and `str` types.
//!
//! This crate provides a collection of Unicode-related functionality,
//! including decompositions, conversions, etc., and provides traits
//! implementing these functions for the `char` and `str` types.
//!
//! The functionality included here is only that which is necessary to
//! provide for basic string-related manipulations. This crate does not
//! (yet) aim to provide a full set of Unicode tables.

#![crate_id = "unicode#0.11.0"]
#![crate_name = "unicode"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/",
       html_playground_url = "http://play.rust-lang.org/")]
#![no_std]
#![allow(unused_attribute)] // NOTE: remove after stage0

extern crate core;

pub use tables::normalization::canonical_combining_class;
pub use tables::regex;

pub use u_char::UnicodeChar;
pub use u_str::UnicodeStrSlice;
pub use u_str::Words;

mod decompose;
mod tables;
mod u_char;
mod u_str;

// re-export char so that std et al see it correctly
/// Character manipulation (`char` type, Unicode Scalar Value)
///
/// This module  provides the `Char` and `UnicodeChar` traits, as well as their
/// implementation for the primitive `char` type, in order to allow basic character
/// manipulation.
///
/// A `char` actually represents a
/// *[Unicode Scalar Value](http://www.unicode.org/glossary/#unicode_scalar_value)*,
/// as it can contain any Unicode code point except high-surrogate and
/// low-surrogate code points.
///
/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
/// however the converse is not always true due to the above range limits
/// and, as such, should be performed via the `from_u32` function..
pub mod char {
    pub use core::char::{MAX, from_u32, is_digit_radix, to_digit};
    pub use core::char::{from_digit, escape_unicode, escape_default};
    pub use core::char::{len_utf8_bytes, Char};

    pub use decompose::decompose_canonical;
    pub use decompose::decompose_compatible;

    pub use u_char::{is_alphabetic, is_XID_start, is_XID_continue};
    pub use u_char::{is_lowercase, is_uppercase, is_whitespace};
    pub use u_char::{is_alphanumeric, is_control, is_digit};
    pub use u_char::{to_uppercase, to_lowercase, width, UnicodeChar};
}
<commit_msg>unicode: Remove crate_id attr<commit_after>// Copyright 2012-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.

//! # The Unicode Library
//!
//! Unicode-intensive functions for `char` and `str` types.
//!
//! This crate provides a collection of Unicode-related functionality,
//! including decompositions, conversions, etc., and provides traits
//! implementing these functions for the `char` and `str` types.
//!
//! The functionality included here is only that which is necessary to
//! provide for basic string-related manipulations. This crate does not
//! (yet) aim to provide a full set of Unicode tables.

#![crate_name = "unicode"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/",
       html_playground_url = "http://play.rust-lang.org/")]
#![no_std]
#![allow(unused_attribute)] // NOTE: remove after stage0

extern crate core;

pub use tables::normalization::canonical_combining_class;
pub use tables::regex;

pub use u_char::UnicodeChar;
pub use u_str::UnicodeStrSlice;
pub use u_str::Words;

mod decompose;
mod tables;
mod u_char;
mod u_str;

// re-export char so that std et al see it correctly
/// Character manipulation (`char` type, Unicode Scalar Value)
///
/// This module  provides the `Char` and `UnicodeChar` traits, as well as their
/// implementation for the primitive `char` type, in order to allow basic character
/// manipulation.
///
/// A `char` actually represents a
/// *[Unicode Scalar Value](http://www.unicode.org/glossary/#unicode_scalar_value)*,
/// as it can contain any Unicode code point except high-surrogate and
/// low-surrogate code points.
///
/// As such, only values in the ranges \[0x0,0xD7FF\] and \[0xE000,0x10FFFF\]
/// (inclusive) are allowed. A `char` can always be safely cast to a `u32`;
/// however the converse is not always true due to the above range limits
/// and, as such, should be performed via the `from_u32` function..
pub mod char {
    pub use core::char::{MAX, from_u32, is_digit_radix, to_digit};
    pub use core::char::{from_digit, escape_unicode, escape_default};
    pub use core::char::{len_utf8_bytes, Char};

    pub use decompose::decompose_canonical;
    pub use decompose::decompose_compatible;

    pub use u_char::{is_alphabetic, is_XID_start, is_XID_continue};
    pub use u_char::{is_lowercase, is_uppercase, is_whitespace};
    pub use u_char::{is_alphanumeric, is_control, is_digit};
    pub use u_char::{to_uppercase, to_lowercase, width, UnicodeChar};
}
<|endoftext|>


<commit_before><commit_msg>Add client::Message::FKS test.<commit_after><|endoftext|>


<commit_before><commit_msg>Adds Rust Problem 13<commit_after>/// Problem 13
/// Work out the first ten digits of the sum of the following one-hundred 50-digit numbers.
///
/// 37107287533902102798797998220837590246510135740250
/// ...

fn main() {
    let raw: String = "\
        37107287533902102798797998220837590246510135740250\n\
        46376937677490009712648124896970078050417018260538\n\
        74324986199524741059474233309513058123726617309629\n\
        91942213363574161572522430563301811072406154908250\n\
        23067588207539346171171980310421047513778063246676\n\
        89261670696623633820136378418383684178734361726757\n\
        28112879812849979408065481931592621691275889832738\n\
        44274228917432520321923589422876796487670272189318\n\
        47451445736001306439091167216856844588711603153276\n\
        70386486105843025439939619828917593665686757934951\n\
        62176457141856560629502157223196586755079324193331\n\
        64906352462741904929101432445813822663347944758178\n\
        92575867718337217661963751590579239728245598838407\n\
        58203565325359399008402633568948830189458628227828\n\
        80181199384826282014278194139940567587151170094390\n\
        35398664372827112653829987240784473053190104293586\n\
        86515506006295864861532075273371959191420517255829\n\
        71693888707715466499115593487603532921714970056938\n\
        54370070576826684624621495650076471787294438377604\n\
        53282654108756828443191190634694037855217779295145\n\
        36123272525000296071075082563815656710885258350721\n\
        45876576172410976447339110607218265236877223636045\n\
        17423706905851860660448207621209813287860733969412\n\
        81142660418086830619328460811191061556940512689692\n\
        51934325451728388641918047049293215058642563049483\n\
        62467221648435076201727918039944693004732956340691\n\
        15732444386908125794514089057706229429197107928209\n\
        55037687525678773091862540744969844508330393682126\n\
        18336384825330154686196124348767681297534375946515\n\
        80386287592878490201521685554828717201219257766954\n\
        78182833757993103614740356856449095527097864797581\n\
        16726320100436897842553539920931837441497806860984\n\
        48403098129077791799088218795327364475675590848030\n\
        87086987551392711854517078544161852424320693150332\n\
        59959406895756536782107074926966537676326235447210\n\
        69793950679652694742597709739166693763042633987085\n\
        41052684708299085211399427365734116182760315001271\n\
        65378607361501080857009149939512557028198746004375\n\
        35829035317434717326932123578154982629742552737307\n\
        94953759765105305946966067683156574377167401875275\n\
        88902802571733229619176668713819931811048770190271\n\
        25267680276078003013678680992525463401061632866526\n\
        36270218540497705585629946580636237993140746255962\n\
        24074486908231174977792365466257246923322810917141\n\
        91430288197103288597806669760892938638285025333403\n\
        34413065578016127815921815005561868836468420090470\n\
        23053081172816430487623791969842487255036638784583\n\
        11487696932154902810424020138335124462181441773470\n\
        63783299490636259666498587618221225225512486764533\n\
        67720186971698544312419572409913959008952310058822\n\
        95548255300263520781532296796249481641953868218774\n\
        76085327132285723110424803456124867697064507995236\n\
        37774242535411291684276865538926205024910326572967\n\
        23701913275725675285653248258265463092207058596522\n\
        29798860272258331913126375147341994889534765745501\n\
        18495701454879288984856827726077713721403798879715\n\
        38298203783031473527721580348144513491373226651381\n\
        34829543829199918180278916522431027392251122869539\n\
        40957953066405232632538044100059654939159879593635\n\
        29746152185502371307642255121183693803580388584903\n\
        41698116222072977186158236678424689157993532961922\n\
        62467957194401269043877107275048102390895523597457\n\
        23189706772547915061505504953922979530901129967519\n\
        86188088225875314529584099251203829009407770775672\n\
        11306739708304724483816533873502340845647058077308\n\
        82959174767140363198008187129011875491310547126581\n\
        97623331044818386269515456334926366572897563400500\n\
        42846280183517070527831839425882145521227251250327\n\
        55121603546981200581762165212827652751691296897789\n\
        32238195734329339946437501907836945765883352399886\n\
        75506164965184775180738168837861091527357929701337\n\
        62177842752192623401942399639168044983993173312731\n\
        32924185707147349566916674687634660915035914677504\n\
        99518671430235219628894890102423325116913619626622\n\
        73267460800591547471830798392868535206946944540724\n\
        76841822524674417161514036427982273348055556214818\n\
        97142617910342598647204516893989422179826088076852\n\
        87783646182799346313767754307809363333018982642090\n\
        10848802521674670883215120185883543223812876952786\n\
        71329612474782464538636993009049310363619763878039\n\
        62184073572399794223406235393808339651327408011116\n\
        66627891981488087797941876876144230030984490851411\n\
        60661826293682836764744779239180335110989069790714\n\
        85786944089552990653640447425576083659976645795096\n\
        66024396409905389607120198219976047599490197230297\n\
        64913982680032973156037120041377903785566085089252\n\
        16730939319872750275468906903707539413042652315011\n\
        94809377245048795150954100921645863754710598436791\n\
        78639167021187492431995700641917969777599028300699\n\
        15368713711936614952811305876380278410754449733078\n\
        40789923115535562561142322423255033685442488917353\n\
        44889911501440648020369068063960672322193204149535\n\
        41503128880339536053299340368006977710650566631954\n\
        81234880673210146739058568557934581403627822703280\n\
        82616570773948327592232845941706525094512325230608\n\
        22918802058777319719839450180888072429661980811197\n\
        77158542502016545090413245809786882778948721859617\n\
        72107838435069186155435662884062257473692284509516\n\
        20849603980134001723930671666823555245252804609722\n\
        53503534226472524250874054075591789781264330331690".to_string();

    let first_digits: usize = 10;

    let mut sum: Vec<u8> = Vec::new();
    let mut nums: Vec<Vec<u8>> = Vec::new();

    for line in raw.split('\n') {
        // Push reversed vector of u8 digits
        nums.push(line.chars().map(|x| x.to_digit(10).unwrap() as u8).rev().collect())
    }

    let mut rem:u16 = 0;
    for i in 0..nums[0].len() { //first_digits {
        let mut col_sum:u16 = rem;
        for j in 0..nums.len() {
            col_sum += nums[j][i] as u16;
        }
        sum.push((col_sum % 10u16) as u8);
        // Do remainder and carry with integer division
        rem = col_sum / 10;
    }
    // Drain remainder digits
    while rem > 0 {
        sum.push((rem % 10) as u8);
        rem /= 10;
    }
    let mut i: usize = 0;
    print!("Answer: ");
    for s in sum.iter().rev() {
        i += 1;
        print!("{}", s);
        if i >= first_digits {
            break
        }
    }
    println!("");
}
<|endoftext|>


<commit_before><commit_msg>float: add cmp and sel<commit_after><|endoftext|>


<commit_before><commit_msg>Return Response struct<commit_after><|endoftext|>


<commit_before><commit_msg>arm: Add validation to MUL_MLA<commit_after><|endoftext|>


<commit_before><commit_msg>Add plugin syntax(including macros) support.<commit_after><|endoftext|>


<commit_before><commit_msg>Added big stress test<commit_after>extern crate crossbeam;
extern crate multiqueue;
extern crate time;

use multiqueue::{MultiReader, MultiWriter, multiqueue};
use std::sync::mpsc::TryRecvError;

use crossbeam::scope;

use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread::spawn;

const EACH_READER: usize = 100;
const MAX_READERS: usize = 60;
const WRITERS: usize = 20;

#[inline(never)]
fn recv(reader: MultiReader<u64>, how_many_r: Arc<AtomicUsize>) -> u64 {
    let mut cur = 0;
    for _ in 0..2 {
        for _ in 0..EACH_READER {
            match reader.try_recv() {
                Ok(_) => cur += 1,
                Err(TryRecvError::Disconnected) => return cur,
                _ => (),
            }
        }
        if how_many_r.load(Ordering::SeqCst) < MAX_READERS {
            let new_reader = reader.add_reader();
            how_many_r.fetch_add(1, Ordering::SeqCst);
            let newr = how_many_r.clone();
            spawn(move || { recv(new_reader, newr)});
        }
    }
    let current = how_many_r.load(Ordering::SeqCst);
    if current <= 10 {
        let new_reader = reader.add_reader();
        spawn(move || { recv(new_reader, how_many_r) });
    }
    return cur;
}

fn send(writer: MultiWriter<u64>, num_push: usize) {
    for i in 0..num_push as u64 {
        loop {
            let topush = i;
            if let Ok(_) =  writer.try_send(topush) {
                break;
            }
        }
    }
}

fn main() {
    let num_do = 10000000;
    let mytest = Arc::new(AtomicUsize::new(1));
    let (writer, reader) = multiqueue(200);
    scope(|scope| {
        for _ in 0..WRITERS {
            let cwriter = writer.clone();
            scope.spawn(move || {
                send(cwriter, num_do);
            });
        }
        writer.unsubscribe();
        recv(reader, mytest);
    });
}
<|endoftext|>


<commit_before><commit_msg>Add message module<commit_after>use std::io::{self, Read, Write, Error, ErrorKind};
use eetf::{Pid, Term, Reference, Atom, FixInteger, Tuple};

pub const CTRL_TYPE_LINK: u8 = 1;
pub const CTRL_TYPE_SEND: u8 = 2;
pub const CTRL_TYPE_EXIT: u8 = 3;
pub const CTRL_TYPE_UNLINK: u8 = 4;
pub const CTRL_TYPE_NODE_LINK: u8 = 5;
pub const CTRL_TYPE_REG_SEND: u8 = 6;
pub const CTRL_TYPE_GROUP_LEADER: u8 = 7;
pub const CTRL_TYPE_EXIT2: u8 = 8;
pub const CTRL_TYPE_SEND_TT: u8 = 12;
pub const CTRL_TYPE_EXIT_TT: u8 = 13;
pub const CTRL_TYPE_REG_SEND_TT: u8 = 16;
pub const CTRL_TYPE_EXIT2_TT: u8 = 18;
pub const CTRL_TYPE_MONITOR_P: u8 = 19;
pub const CTRL_TYPE_DEMONITOR_P: u8 = 20;
pub const CTRL_TYPE_MONITOR_P_EXIT: u8 = 21;

#[derive(Debug, Clone)]
pub struct DistributionHeader;

#[derive(Debug, Clone)]
pub struct Message {
    distribution_header: Option<DistributionHeader>,
    body: Body,
}
impl Message {
    fn new(body: Body) -> Self {
        Message {
            distribution_header: None,
            body: body,
        }
    }
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        assert!(self.distribution_header.is_none(), "Unimpelemented");
        self.body.write_into(writer)
    }
}
impl From<Body> for Message {
    fn from(f: Body) -> Self {
        Message::new(f)
    }
}

#[derive(Debug, Clone)]
pub enum Body {
    Link(Link),
    Send(Send),
    Exit(Exit),
    Unlink(Unlink),
    NodeLink(NodeLink),
    RegSend(RegSend),
    GroupLeader(GroupLeader),
    Exit2(Exit2),
    SendTt(SendTt),
    ExitTt(ExitTt),
    RegSendTt(RegSendTt),
    Exit2Tt(Exit2Tt),
    MonitorP(MonitorP),
    DemonitorP(DemonitorP),
    MonitorPExit(MonitorPExit),
}
impl Body {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        match self {
            Body::Link(x) => x.write_into(writer),
            Body::Send(x) => x.write_into(writer),
            Body::Exit(x) => x.write_into(writer),
            Body::Unlink(x) => x.write_into(writer),
            Body::NodeLink(x) => x.write_into(writer),
            Body::RegSend(x) => x.write_into(writer),
            Body::GroupLeader(x) => x.write_into(writer),
            Body::Exit2(x) => x.write_into(writer),
            Body::SendTt(x) => x.write_into(writer),
            Body::ExitTt(x) => x.write_into(writer),
            Body::RegSendTt(x) => x.write_into(writer),
            Body::Exit2Tt(x) => x.write_into(writer),
            Body::MonitorP(x) => x.write_into(writer),
            Body::DemonitorP(x) => x.write_into(writer),
            Body::MonitorPExit(x) => x.write_into(writer),
        }
    }
}
macro_rules! impl_from_for_body {
    ($t:ident) => {
        impl From<$t> for Body {
            fn from(f: $t) -> Self {
                Body::$t(f)
            }
        }
    }
}
impl_from_for_body!(Link);
impl_from_for_body!(Send);
impl_from_for_body!(Exit);
impl_from_for_body!(Unlink);
impl_from_for_body!(NodeLink);
impl_from_for_body!(RegSend);
impl_from_for_body!(GroupLeader);
impl_from_for_body!(Exit2);
impl_from_for_body!(SendTt);
impl_from_for_body!(ExitTt);
impl_from_for_body!(RegSendTt);
impl_from_for_body!(Exit2Tt);
impl_from_for_body!(MonitorP);
impl_from_for_body!(DemonitorP);
impl_from_for_body!(MonitorPExit);

#[derive(Debug, Clone)]
pub struct Link {
    pub from_pid: Pid,
    pub to_pid: Pid,
}
impl Link {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple3(CTRL_TYPE_LINK, self.from_pid, self.to_pid);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct Send {
    pub to_pid: Pid,
    pub message: Term,
}
impl Send {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple3(CTRL_TYPE_SEND, Tuple::nil(), self.to_pid);
        write_term(writer, ctrl)?;
        write_term(writer, self.message)?;
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct Exit {
    pub from_pid: Pid,
    pub to_pid: Pid,
    pub reason: Term,
}
impl Exit {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple4(CTRL_TYPE_EXIT, self.from_pid, self.to_pid, self.reason);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct Unlink {
    pub from_pid: Pid,
    pub to_pid: Pid,
}
impl Unlink {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple3(CTRL_TYPE_UNLINK, self.from_pid, self.to_pid);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct NodeLink;
impl NodeLink {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple1(CTRL_TYPE_NODE_LINK);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct RegSend {
    pub from_pid: Pid,
    pub to_name: Atom,
    pub message: Term,
}
impl RegSend {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple4(CTRL_TYPE_REG_SEND,
                                 self.from_pid,
                                 Tuple::nil(),
                                 self.to_name);
        write_term(writer, ctrl)?;
        write_term(writer, self.message)?;
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct GroupLeader {
    pub from_pid: Pid,
    pub to_pid: Pid,
}
impl GroupLeader {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple3(CTRL_TYPE_GROUP_LEADER, self.from_pid, self.to_pid);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct Exit2 {
    pub from_pid: Pid,
    pub to_pid: Pid,
    pub reason: Term,
}
impl Exit2 {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple4(CTRL_TYPE_EXIT2, self.from_pid, self.to_pid, self.reason);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct SendTt {
    pub to_pid: Pid,
    pub trace_token: Term,
    pub message: Term,
}
impl SendTt {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple4(CTRL_TYPE_SEND_TT,
                                 Tuple::nil(),
                                 self.to_pid,
                                 self.trace_token);
        write_term(writer, ctrl)?;
        write_term(writer, self.message)?;
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct ExitTt {
    pub from_pid: Pid,
    pub to_pid: Pid,
    pub trace_token: Term,
    pub reason: Term,
}
impl ExitTt {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple5(CTRL_TYPE_EXIT_TT,
                                 self.from_pid,
                                 self.to_pid,
                                 self.trace_token,
                                 self.reason);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct RegSendTt {
    pub from_pid: Pid,
    pub to_name: Atom,
    pub trace_token: Term,
    pub message: Term,
}
impl RegSendTt {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple5(CTRL_TYPE_REG_SEND_TT,
                                 self.from_pid,
                                 Tuple::nil(),
                                 self.to_name,
                                 self.trace_token);
        write_term(writer, ctrl)?;
        write_term(writer, self.message)?;
        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct Exit2Tt {
    pub from_pid: Pid,
    pub to_pid: Pid,
    pub trace_token: Term,
    pub reason: Term,
}
impl Exit2Tt {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple5(CTRL_TYPE_EXIT2_TT,
                                 self.from_pid,
                                 self.to_pid,
                                 self.trace_token,
                                 self.reason);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct MonitorP {
    pub from_pid: Pid,
    pub to_proc: ProcessRef,
    pub reference: Reference,
}
impl MonitorP {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple4(CTRL_TYPE_MONITOR_P,
                                 self.from_pid,
                                 self.to_proc,
                                 self.reference);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct DemonitorP {
    pub from_pid: Pid,
    pub to_proc: ProcessRef,
    pub reference: Reference,
}
impl DemonitorP {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple4(CTRL_TYPE_DEMONITOR_P,
                                 self.from_pid,
                                 self.to_proc,
                                 self.reference);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub struct MonitorPExit {
    pub from_pid: Pid,
    pub to_pid: Pid,
    pub reference: Reference,
    pub reason: Term,
}
impl MonitorPExit {
    pub fn write_into<W: Write>(self, writer: &mut W) -> io::Result<()> {
        let ctrl = tagged_tuple5(CTRL_TYPE_DEMONITOR_P,
                                 self.from_pid,
                                 self.to_pid,
                                 self.reference,
                                 self.reason);
        write_term(writer, ctrl)
    }
}

#[derive(Debug, Clone)]
pub enum ProcessRef {
    Pid(Pid),
    Name(Atom),
}
impl From<ProcessRef> for Term {
    fn from(f: ProcessRef) -> Self {
        match f {
            ProcessRef::Pid(x) => Term::from(x),
            ProcessRef::Name(x) => Term::from(x),
        }
    }
}

fn write_term<W: Write, T>(writer: &mut W, term: T) -> io::Result<()>
    where Term: From<T>
{
    let term = Term::from(term);
    term.encode(writer).map_err(|e| {
        use eetf::EncodeError;
        if let EncodeError::Io(e) = e {
            e
        } else {
            Error::new(ErrorKind::InvalidInput, Box::new(e))
        }
    })
}

fn tagged_tuple1(tag: u8) -> Tuple {
    Tuple { elements: vec![Term::from(FixInteger { value: tag as i32 })] }
}

fn tagged_tuple3<T1, T2>(tag: u8, t1: T1, t2: T2) -> Tuple
    where Term: From<T1>,
          Term: From<T2>
{
    Tuple {
        elements: vec![Term::from(FixInteger { value: tag as i32 }),
                       Term::from(t1),
                       Term::from(t2)],
    }
}
fn tagged_tuple4<T1, T2, T3>(tag: u8, t1: T1, t2: T2, t3: T3) -> Tuple
    where Term: From<T1>,
          Term: From<T2>,
          Term: From<T3>
{
    Tuple {
        elements: vec![Term::from(FixInteger { value: tag as i32 }),
                       Term::from(t1),
                       Term::from(t2),
                       Term::from(t3)],
    }
}
fn tagged_tuple5<T1, T2, T3, T4>(tag: u8, t1: T1, t2: T2, t3: T3, t4: T4) -> Tuple
    where Term: From<T1>,
          Term: From<T2>,
          Term: From<T3>,
          Term: From<T4>
{
    Tuple {
        elements: vec![Term::from(FixInteger { value: tag as i32 }),
                       Term::from(t1),
                       Term::from(t2),
                       Term::from(t3),
                       Term::from(t4)],
    }
}
<|endoftext|>


<commit_before>
/// A priority queue implemented with a binary heap
use core::cmp::Ord;
use ptr::addr_of;

#[abi = "rust-intrinsic"]
extern "C" mod rusti {
    fn move_val_init<T>(dst: &mut T, -src: T);
}

pub struct PriorityQueue <T: Ord>{
    priv data: ~[T],
}

impl <T: Ord> PriorityQueue<T> {
    /// Returns the greatest item in the queue - fails if empty
    pure fn top(&self) -> &self/T { &self.data[0] }

    /// Returns the greatest item in the queue - None if empty
    pure fn maybe_top(&self) -> Option<&self/T> {
        if self.is_empty() { None } else { Some(self.top()) }
    }

    /// Returns the length of the queue
    pure fn len(&self) -> uint { self.data.len() }

    /// Returns true if a queue contains no elements
    pure fn is_empty(&self) -> bool { self.data.is_empty() }

    /// Returns true if a queue contains some elements
    pure fn is_not_empty(&self) -> bool { self.data.is_not_empty() }

    /// Returns the number of elements the queue can hold without reallocating
    pure fn capacity(&self) -> uint { vec::capacity(&self.data) }

    fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }

    fn reserve_at_least(&mut self, n: uint) {
        vec::reserve_at_least(&mut self.data, n)
    }

    /// Drop all items from the queue
    fn clear(&mut self) { self.data.truncate(0) }

    /// Pop the greatest item from the queue - fails if empty
    fn pop(&mut self) -> T {
        let mut item = self.data.pop();
        if self.is_not_empty() { item <-> self.data[0]; self.siftdown(0); }
        item
    }

    /// Pop the greatest item from the queue - None if empty
    fn maybe_pop(&mut self) -> Option<T> {
        if self.is_empty() { None } else { Some(self.pop()) }
    }

    /// Push an item onto the queue
    fn push(&mut self, item: T) {
        self.data.push(item);
        self.siftup(0, self.len() - 1);
    }

    /// Optimized version of a push followed by a pop
    fn push_pop(&mut self, item: T) -> T {
        let mut item = item;
        if self.is_not_empty() && self.data[0] > item {
            item <-> self.data[0];
            self.siftdown(0);
        }
        item
    }

    /// Optimized version of a pop followed by a push - fails if empty
    fn replace(&mut self, item: T) -> T {
        let mut item = item;
        item <-> self.data[0];
        self.siftdown(0);
        item
    }

    /// Consume the PriorityQueue and return the underlying vector
    pure fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v }

    /// Consume the PriorityQueue and return a vector in sorted (ascending) order
    pure fn to_sorted_vec(self) -> ~[T] {
        let mut q = self;
        let mut end = q.len();
        while end > 1 {
            end -= 1;
            q.data[end] <-> q.data[0];
            unsafe { q.siftdown_range(0, end) } // purity-checking workaround
        }
        q.to_vec()
    }

    static pub pure fn from_vec(xs: ~[T]) -> PriorityQueue<T> {
        let mut q = PriorityQueue{data: xs,};
        let mut n = q.len() / 2;
        while n > 0 {
            n -= 1;
            unsafe { q.siftdown(n) }; // purity-checking workaround
        }
        q
    }

    // The implementations of siftup and siftdown use unsafe blocks in order to
    // move an element out of the vector (leaving behind a junk element), shift
    // along the others and move it back into the vector over the junk element.
    // This reduces the constant factor compared to using swaps, which involves
    // twice as many moves.

    priv fn siftup(&mut self, start: uint, pos: uint) unsafe {
        let mut pos = pos;
        let new = move *addr_of(&self.data[pos]);

        while pos > start {
            let parent = (pos - 1) >> 1;
            if new > self.data[parent] {
                rusti::move_val_init(&mut self.data[pos],
                                     move *addr_of(&self.data[parent]));
                pos = parent;
                loop
            }
            break
        }
        rusti::move_val_init(&mut self.data[pos], move new);
    }

    priv fn siftdown_range(&mut self, pos: uint, end: uint) unsafe {
        let mut pos = pos;
        let start = pos;
        let new = move *addr_of(&self.data[pos]);

        let mut child = 2 * pos + 1;
        while child < end {
            let right = child + 1;
            if right < end && !(self.data[child] > self.data[right]) {
                child = right;
            }
            rusti::move_val_init(&mut self.data[pos],
                                 move *addr_of(&self.data[child]));
            pos = child;
            child = 2 * pos + 1;
        }
        rusti::move_val_init(&mut self.data[pos], move new);
        self.siftup(start, pos);
    }

    priv fn siftdown(&mut self, pos: uint) {
        self.siftdown_range(pos, self.len());
    }
}

#[cfg(test)]
mod tests {
    use sort::merge_sort;
    use core::cmp::le;
    use priority_queue::PriorityQueue::from_vec;

    #[test]
    fn test_top_and_pop() {
        let data = ~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
        let mut sorted = merge_sort(data, le);
        let mut heap = from_vec(data);
        while heap.is_not_empty() {
            assert *heap.top() == sorted.last();
            assert heap.pop() == sorted.pop();
        }
    }

    #[test]
    fn test_push() {
        let mut heap = from_vec(~[2, 4, 9]);
        assert heap.len() == 3;
        assert *heap.top() == 9;
        heap.push(11);
        assert heap.len() == 4;
        assert *heap.top() == 11;
        heap.push(5);
        assert heap.len() == 5;
        assert *heap.top() == 11;
        heap.push(27);
        assert heap.len() == 6;
        assert *heap.top() == 27;
        heap.push(3);
        assert heap.len() == 7;
        assert *heap.top() == 27;
        heap.push(103);
        assert heap.len() == 8;
        assert *heap.top() == 103;
    }

    #[test]
    fn test_push_pop() {
        let mut heap = from_vec(~[5, 5, 2, 1, 3]);
        assert heap.len() == 5;
        assert heap.push_pop(6) == 6;
        assert heap.len() == 5;
        assert heap.push_pop(0) == 5;
        assert heap.len() == 5;
        assert heap.push_pop(4) == 5;
        assert heap.len() == 5;
        assert heap.push_pop(1) == 4;
        assert heap.len() == 5;
    }

    #[test]
    fn test_replace() {
        let mut heap = from_vec(~[5, 5, 2, 1, 3]);
        assert heap.len() == 5;
        assert heap.replace(6) == 5;
        assert heap.len() == 5;
        assert heap.replace(0) == 6;
        assert heap.len() == 5;
        assert heap.replace(4) == 5;
        assert heap.len() == 5;
        assert heap.replace(1) == 4;
        assert heap.len() == 5;
    }

    fn check_to_vec(data: ~[int]) {
        let heap = from_vec(data);
        assert merge_sort(heap.to_vec(), le) == merge_sort(data, le);
        assert heap.to_sorted_vec() == merge_sort(data, le);
    }

    #[test]
    fn test_to_vec() {
        check_to_vec(~[]);
        check_to_vec(~[5]);
        check_to_vec(~[3, 2]);
        check_to_vec(~[2, 3]);
        check_to_vec(~[5, 1, 2]);
        check_to_vec(~[1, 100, 2, 3]);
        check_to_vec(~[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
        check_to_vec(~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
        check_to_vec(~[9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        check_to_vec(~[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
        check_to_vec(~[5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
    }

    #[test]
    #[should_fail]
    fn test_empty_pop() { let mut heap = from_vec::<int>(~[]); heap.pop(); }

    #[test]
    fn test_empty_maybe_pop() {
        let mut heap = from_vec::<int>(~[]);
        assert heap.maybe_pop().is_none();
    }

    #[test]
    #[should_fail]
    fn test_empty_top() { let empty = from_vec::<int>(~[]); empty.top(); }

    #[test]
    fn test_empty_maybe_top() {
        let empty = from_vec::<int>(~[]);
        assert empty.maybe_top().is_none();
    }

    #[test]
    #[should_fail]
    fn test_empty_replace() {
        let mut heap = from_vec::<int>(~[]);
        heap.replace(5);
    }
}
<commit_msg>priority_queue: add docstring for from_vec<commit_after>
/// A priority queue implemented with a binary heap
use core::cmp::Ord;
use ptr::addr_of;

#[abi = "rust-intrinsic"]
extern "C" mod rusti {
    fn move_val_init<T>(dst: &mut T, -src: T);
}

pub struct PriorityQueue <T: Ord>{
    priv data: ~[T],
}

impl <T: Ord> PriorityQueue<T> {
    /// Returns the greatest item in the queue - fails if empty
    pure fn top(&self) -> &self/T { &self.data[0] }

    /// Returns the greatest item in the queue - None if empty
    pure fn maybe_top(&self) -> Option<&self/T> {
        if self.is_empty() { None } else { Some(self.top()) }
    }

    /// Returns the length of the queue
    pure fn len(&self) -> uint { self.data.len() }

    /// Returns true if a queue contains no elements
    pure fn is_empty(&self) -> bool { self.data.is_empty() }

    /// Returns true if a queue contains some elements
    pure fn is_not_empty(&self) -> bool { self.data.is_not_empty() }

    /// Returns the number of elements the queue can hold without reallocating
    pure fn capacity(&self) -> uint { vec::capacity(&self.data) }

    fn reserve(&mut self, n: uint) { vec::reserve(&mut self.data, n) }

    fn reserve_at_least(&mut self, n: uint) {
        vec::reserve_at_least(&mut self.data, n)
    }

    /// Drop all items from the queue
    fn clear(&mut self) { self.data.truncate(0) }

    /// Pop the greatest item from the queue - fails if empty
    fn pop(&mut self) -> T {
        let mut item = self.data.pop();
        if self.is_not_empty() { item <-> self.data[0]; self.siftdown(0); }
        item
    }

    /// Pop the greatest item from the queue - None if empty
    fn maybe_pop(&mut self) -> Option<T> {
        if self.is_empty() { None } else { Some(self.pop()) }
    }

    /// Push an item onto the queue
    fn push(&mut self, item: T) {
        self.data.push(item);
        self.siftup(0, self.len() - 1);
    }

    /// Optimized version of a push followed by a pop
    fn push_pop(&mut self, item: T) -> T {
        let mut item = item;
        if self.is_not_empty() && self.data[0] > item {
            item <-> self.data[0];
            self.siftdown(0);
        }
        item
    }

    /// Optimized version of a pop followed by a push - fails if empty
    fn replace(&mut self, item: T) -> T {
        let mut item = item;
        item <-> self.data[0];
        self.siftdown(0);
        item
    }

    /// Consume the PriorityQueue and return the underlying vector
    pure fn to_vec(self) -> ~[T] { let PriorityQueue{data: v} = self; v }

    /// Consume the PriorityQueue and return a vector in sorted (ascending) order
    pure fn to_sorted_vec(self) -> ~[T] {
        let mut q = self;
        let mut end = q.len();
        while end > 1 {
            end -= 1;
            q.data[end] <-> q.data[0];
            unsafe { q.siftdown_range(0, end) } // purity-checking workaround
        }
        q.to_vec()
    }

    /// Create a PriorityQueue from a vector (heapify)
    static pub pure fn from_vec(xs: ~[T]) -> PriorityQueue<T> {
        let mut q = PriorityQueue{data: xs,};
        let mut n = q.len() / 2;
        while n > 0 {
            n -= 1;
            unsafe { q.siftdown(n) }; // purity-checking workaround
        }
        q
    }

    // The implementations of siftup and siftdown use unsafe blocks in order to
    // move an element out of the vector (leaving behind a junk element), shift
    // along the others and move it back into the vector over the junk element.
    // This reduces the constant factor compared to using swaps, which involves
    // twice as many moves.

    priv fn siftup(&mut self, start: uint, pos: uint) unsafe {
        let mut pos = pos;
        let new = move *addr_of(&self.data[pos]);

        while pos > start {
            let parent = (pos - 1) >> 1;
            if new > self.data[parent] {
                rusti::move_val_init(&mut self.data[pos],
                                     move *addr_of(&self.data[parent]));
                pos = parent;
                loop
            }
            break
        }
        rusti::move_val_init(&mut self.data[pos], move new);
    }

    priv fn siftdown_range(&mut self, pos: uint, end: uint) unsafe {
        let mut pos = pos;
        let start = pos;
        let new = move *addr_of(&self.data[pos]);

        let mut child = 2 * pos + 1;
        while child < end {
            let right = child + 1;
            if right < end && !(self.data[child] > self.data[right]) {
                child = right;
            }
            rusti::move_val_init(&mut self.data[pos],
                                 move *addr_of(&self.data[child]));
            pos = child;
            child = 2 * pos + 1;
        }
        rusti::move_val_init(&mut self.data[pos], move new);
        self.siftup(start, pos);
    }

    priv fn siftdown(&mut self, pos: uint) {
        self.siftdown_range(pos, self.len());
    }
}

#[cfg(test)]
mod tests {
    use sort::merge_sort;
    use core::cmp::le;
    use priority_queue::PriorityQueue::from_vec;

    #[test]
    fn test_top_and_pop() {
        let data = ~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1];
        let mut sorted = merge_sort(data, le);
        let mut heap = from_vec(data);
        while heap.is_not_empty() {
            assert *heap.top() == sorted.last();
            assert heap.pop() == sorted.pop();
        }
    }

    #[test]
    fn test_push() {
        let mut heap = from_vec(~[2, 4, 9]);
        assert heap.len() == 3;
        assert *heap.top() == 9;
        heap.push(11);
        assert heap.len() == 4;
        assert *heap.top() == 11;
        heap.push(5);
        assert heap.len() == 5;
        assert *heap.top() == 11;
        heap.push(27);
        assert heap.len() == 6;
        assert *heap.top() == 27;
        heap.push(3);
        assert heap.len() == 7;
        assert *heap.top() == 27;
        heap.push(103);
        assert heap.len() == 8;
        assert *heap.top() == 103;
    }

    #[test]
    fn test_push_pop() {
        let mut heap = from_vec(~[5, 5, 2, 1, 3]);
        assert heap.len() == 5;
        assert heap.push_pop(6) == 6;
        assert heap.len() == 5;
        assert heap.push_pop(0) == 5;
        assert heap.len() == 5;
        assert heap.push_pop(4) == 5;
        assert heap.len() == 5;
        assert heap.push_pop(1) == 4;
        assert heap.len() == 5;
    }

    #[test]
    fn test_replace() {
        let mut heap = from_vec(~[5, 5, 2, 1, 3]);
        assert heap.len() == 5;
        assert heap.replace(6) == 5;
        assert heap.len() == 5;
        assert heap.replace(0) == 6;
        assert heap.len() == 5;
        assert heap.replace(4) == 5;
        assert heap.len() == 5;
        assert heap.replace(1) == 4;
        assert heap.len() == 5;
    }

    fn check_to_vec(data: ~[int]) {
        let heap = from_vec(data);
        assert merge_sort(heap.to_vec(), le) == merge_sort(data, le);
        assert heap.to_sorted_vec() == merge_sort(data, le);
    }

    #[test]
    fn test_to_vec() {
        check_to_vec(~[]);
        check_to_vec(~[5]);
        check_to_vec(~[3, 2]);
        check_to_vec(~[2, 3]);
        check_to_vec(~[5, 1, 2]);
        check_to_vec(~[1, 100, 2, 3]);
        check_to_vec(~[1, 3, 5, 7, 9, 2, 4, 6, 8, 0]);
        check_to_vec(~[2, 4, 6, 2, 1, 8, 10, 3, 5, 7, 0, 9, 1]);
        check_to_vec(~[9, 11, 9, 9, 9, 9, 11, 2, 3, 4, 11, 9, 0, 0, 0, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
        check_to_vec(~[10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]);
        check_to_vec(~[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 1, 2]);
        check_to_vec(~[5, 4, 3, 2, 1, 5, 4, 3, 2, 1, 5, 4, 3, 2, 1]);
    }

    #[test]
    #[should_fail]
    fn test_empty_pop() { let mut heap = from_vec::<int>(~[]); heap.pop(); }

    #[test]
    fn test_empty_maybe_pop() {
        let mut heap = from_vec::<int>(~[]);
        assert heap.maybe_pop().is_none();
    }

    #[test]
    #[should_fail]
    fn test_empty_top() { let empty = from_vec::<int>(~[]); empty.top(); }

    #[test]
    fn test_empty_maybe_top() {
        let empty = from_vec::<int>(~[]);
        assert empty.maybe_top().is_none();
    }

    #[test]
    #[should_fail]
    fn test_empty_replace() {
        let mut heap = from_vec::<int>(~[]);
        heap.replace(5);
    }
}
<|endoftext|>


<commit_before><commit_msg>Refine some VIP states<commit_after><|endoftext|>


<commit_before><commit_msg>test: Add a test for the hover functionality<commit_after>
extern crate gluon_language_server;
extern crate vscode_languageserver_types;

extern crate jsonrpc_core;
extern crate serde_json;
extern crate serde;

use std::env;
use std::io::{self, Write};
use std::path::Path;
use std::process::{Command, Stdio};
use std::str;

use jsonrpc_core::request::{Call, MethodCall, Notification};
use jsonrpc_core::version::Version;
use jsonrpc_core::params::Params;
use jsonrpc_core::response::{SyncOutput, SyncResponse};
use jsonrpc_core::id::Id;

use serde::Serialize;
use serde_json::ser::Serializer;
use serde_json::{Value, to_value, from_str, from_value};

use gluon_language_server::read_message;
use vscode_languageserver_types::{DidOpenTextDocumentParams, Hover, MarkedString, Position,
                                  TextDocumentIdentifier, TextDocumentItem,
                                  TextDocumentPositionParams};

fn write_message<W, V>(mut writer: W, value: V) -> io::Result<()>
    where W: Write,
          V: Serialize,
{
    let mut vec = Vec::new();
    value.serialize(&mut Serializer::new(&mut vec)).unwrap();
    write!(writer,
           "Content-Length: {}\r\n\r\n{}",
           vec.len(),
           str::from_utf8(&vec).unwrap())
}

fn method_call<T>(method: &str, id: u64, value: T) -> Call
    where T: Serialize,
{
    let value = to_value(value);
    let params = match value {
        Value::Object(map) => Params::Map(map),
        _ => panic!("Expected map"),
    };
    Call::MethodCall(MethodCall {
        jsonrpc: Version::V2,
        method: method.into(),
        id: Id::Num(id),
        params: Some(params),
    })
}

fn notification<T>(method: &str, value: T) -> Call
    where T: Serialize,
{
    let value = to_value(value);
    let params = match value {
        Value::Object(map) => Params::Map(map),
        _ => panic!("Expected map"),
    };
    Call::Notification(Notification {
        jsonrpc: Version::V2,
        method: method.into(),
        params: Some(params),
    })
}

#[test]
fn hover() {
    let args: Vec<_> = env::args().collect();
    let server_path =
        Path::new(&args[0][..]).parent().expect("folder").join("gluon_language-server");

    let mut child = Command::new(server_path)
        .arg("--quiet")
        .stdin(Stdio::piped())
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    {
        let mut stdin = child.stdin.as_mut().expect("stdin");

        let did_open = notification("textDocument/didOpen",
                                    DidOpenTextDocumentParams {
                                        text_document: TextDocumentItem {
                                            uri: "test".into(),
                                            language_id: "gluon".into(),
                                            text: "123".into(),
                                            version: 1,
                                        },
                                    });

        write_message(&mut stdin, did_open).unwrap();

        let hover = method_call("textDocument/hover",
                                2,
                                TextDocumentPositionParams {
                                    text_document: TextDocumentIdentifier { uri: "test".into() },
                                    position: Position {
                                        line: 0,
                                        character: 2,
                                    },
                                });

        write_message(&mut stdin, hover).unwrap();

        let exit = Call::Notification(Notification {
            jsonrpc: Version::V2,
            method: "exit".into(),
            params: None,
        });
        write_message(&mut stdin, exit).unwrap();
    }

    let result = child.wait_with_output().unwrap();
    assert!(result.status.success());

    let mut hover = None;
    let mut output = &result.stdout[..];
    while let Some(json) = read_message(&mut output).unwrap() {
        if let Ok(SyncResponse::Single(SyncOutput::Success(response))) = from_str(&json) {
            hover = from_value(response.result).ok();
        }
    }
    assert_eq!(hover,
               Some(Hover {
                   contents: vec![MarkedString::String("Int".into())],
                   range: None,
               }),
               "{}",
               str::from_utf8(&result.stdout).expect("UTF8"));
}
<|endoftext|>