<commit_before>use std::collections::{HashMap, HashSet};
use std::rc::Rc;

use core::interning::InternedString;
use core::{Dependency, FeatureValue, PackageId, SourceId, Summary};
use util::CargoResult;
use util::Graph;

use super::types::RegistryQueryer;
use super::types::{ActivateResult, ConflictReason, DepInfo, GraphNode, Method, RcList};

pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
pub use super::encode::{Metadata, WorkspaceResolve};
pub use super::resolve::Resolve;

// A `Context` is basically a bunch of local resolution information which is
// kept around for all `BacktrackFrame` instances. As a result, this runs the
// risk of being cloned *a lot* so we want to make this as cheap to clone as
// possible.
#[derive(Clone)]
pub struct Context {
    // TODO: Both this and the two maps below are super expensive to clone. We should
    //       switch to persistent hash maps if we can at some point or otherwise
    //       make these much cheaper to clone in general.
    pub activations: Activations,
    pub resolve_features: HashMap<PackageId, HashSet<InternedString>>,
    pub links: HashMap<InternedString, PackageId>,

    // These are two cheaply-cloneable lists (O(1) clone) which are effectively
    // hash maps but are built up as "construction lists". We'll iterate these
    // at the very end and actually construct the map that we're making.
    pub resolve_graph: RcList<GraphNode>,
    pub resolve_replacements: RcList<(PackageId, PackageId)>,

    // These warnings are printed after resolution.
    pub warnings: RcList<String>,
}

impl Context {
    pub fn new() -> Context {
        Context {
            resolve_graph: RcList::new(),
            resolve_features: HashMap::new(),
            links: HashMap::new(),
            resolve_replacements: RcList::new(),
            activations: HashMap::new(),
            warnings: RcList::new(),
        }
    }

    /// Activate this summary by inserting it into our list of known activations.
    ///
    /// Returns true if this summary with the given method is already activated.
    pub fn flag_activated(&mut self, summary: &Summary, method: &Method) -> CargoResult<bool> {
        let id = summary.package_id();
        let prev = self.activations
            .entry((id.name(), id.source_id().clone()))
            .or_insert_with(|| Rc::new(Vec::new()));
        if !prev.iter().any(|c| c == summary) {
            self.resolve_graph.push(GraphNode::Add(id.clone()));
            if let Some(link) = summary.links() {
                ensure!(
                    self.links.insert(link, id.clone()).is_none(),
                    "Attempting to resolve a with more then one crate with the links={}. \n\
                     This will not build as is. Consider rebuilding the .lock file.",
                    &*link
                );
            }
            let mut inner: Vec<_> = (**prev).clone();
            inner.push(summary.clone());
            *prev = Rc::new(inner);
            return Ok(false);
        }
        debug!("checking if {} is already activated", summary.package_id());
        let (features, use_default) = match *method {
            Method::Everything
            | Method::Required {
                all_features: true, ..
            } => return Ok(false),
            Method::Required {
                features,
                uses_default_features,
                ..
            } => (features, uses_default_features),
        };

        let has_default_feature = summary.features().contains_key("default");
        Ok(match self.resolve_features.get(id) {
            Some(prev) => {
                features
                    .iter()
                    .all(|f| prev.contains(&InternedString::new(f)))
                    && (!use_default || prev.contains(&InternedString::new("default"))
                        || !has_default_feature)
            }
            None => features.is_empty() && (!use_default || !has_default_feature),
        })
    }

    pub fn build_deps(
        &mut self,
        registry: &mut RegistryQueryer,
        parent: Option<&Summary>,
        candidate: &Summary,
        method: &Method,
    ) -> ActivateResult<Vec<DepInfo>> {
        // First, figure out our set of dependencies based on the requested set
        // of features. This also calculates what features we're going to enable
        // for our own dependencies.
        let deps = self.resolve_features(parent, candidate, method)?;

        // Next, transform all dependencies into a list of possible candidates
        // which can satisfy that dependency.
        let mut deps = deps.into_iter()
            .map(|(dep, features)| {
                let candidates = registry.query(&dep)?;
                Ok((dep, candidates, Rc::new(features)))
            })
            .collect::<CargoResult<Vec<DepInfo>>>()?;

        // Attempt to resolve dependencies with fewer candidates before trying
        // dependencies with more candidates.  This way if the dependency with
        // only one candidate can't be resolved we don't have to do a bunch of
        // work before we figure that out.
        deps.sort_by_key(|&(_, ref a, _)| a.len());

        Ok(deps)
    }

    pub fn prev_active(&self, dep: &Dependency) -> &[Summary] {
        self.activations
            .get(&(dep.name(), dep.source_id().clone()))
            .map(|v| &v[..])
            .unwrap_or(&[])
    }

    fn is_active(&self, id: &PackageId) -> bool {
        self.activations
            .get(&(id.name(), id.source_id().clone()))
            .map(|v| v.iter().any(|s| s.package_id() == id))
            .unwrap_or(false)
    }

    /// checks whether all of `parent` and the keys of `conflicting activations`
    /// are still active
    pub fn is_conflicting(
        &self,
        parent: Option<&PackageId>,
        conflicting_activations: &HashMap<PackageId, ConflictReason>,
    ) -> bool {
        conflicting_activations
            .keys()
            .chain(parent)
            .all(|id| self.is_active(id))
    }

    /// Return all dependencies and the features we want from them.
    fn resolve_features<'b>(
        &mut self,
        parent: Option<&Summary>,
        s: &'b Summary,
        method: &'b Method,
    ) -> ActivateResult<Vec<(Dependency, Vec<InternedString>)>> {
        let dev_deps = match *method {
            Method::Everything => true,
            Method::Required { dev_deps, .. } => dev_deps,
        };

        // First, filter by dev-dependencies
        let deps = s.dependencies();
        let deps = deps.iter().filter(|d| d.is_transitive() || dev_deps);

        // Requested features stored in the Method are stored as string references, but we want to
        // transform them into FeatureValues here. In order to pass the borrow checker with
        // storage of the FeatureValues that outlives the Requirements object, we do the
        // transformation here, and pass the FeatureValues to build_requirements().
        let values = if let Method::Required {
            all_features: false,
            features: requested,
            ..
        } = *method
        {
            requested
                .iter()
                .map(|&f| FeatureValue::new(f, s))
                .collect::<Vec<FeatureValue>>()
        } else {
            vec![]
        };
        let mut reqs = build_requirements(s, method, &values)?;
        let mut ret = Vec::new();

        // Next, collect all actually enabled dependencies and their features.
        for dep in deps {
            // Skip optional dependencies, but not those enabled through a feature
            if dep.is_optional() && !reqs.deps.contains_key(&*dep.name()) {
                continue;
            }
            // So we want this dependency.  Move the features we want from `feature_deps`
            // to `ret`.
            let base = reqs.deps.remove(&*dep.name()).unwrap_or((false, vec![]));
            if !dep.is_optional() && base.0 {
                self.warnings.push(format!(
                    "Package `{}` does not have feature `{}`. It has a required dependency \
                     with that name, but only optional dependencies can be used as features. \
                     This is currently a warning to ease the transition, but it will become an \
                     error in the future.",
                    s.package_id(),
                    dep.name()
                ));
            }
            let mut base = base.1;
            base.extend(dep.features().iter());
            for feature in base.iter() {
                if feature.contains('/') {
                    return Err(
                        format_err!("feature names may not contain slashes: `{}`", feature).into(),
                    );
                }
            }
            ret.push((dep.clone(), base));
        }

        // Any remaining entries in feature_deps are bugs in that the package does not actually
        // have those dependencies.  We classified them as dependencies in the first place
        // because there is no such feature, either.
        if !reqs.deps.is_empty() {
            let unknown = reqs.deps.keys().map(|s| &s[..]).collect::<Vec<&str>>();
            let features = unknown.join(", ");
            return Err(match parent {
                None => format_err!(
                    "Package `{}` does not have these features: `{}`",
                    s.package_id(),
                    features
                ).into(),
                Some(p) => (
                    p.package_id().clone(),
                    ConflictReason::MissingFeatures(features),
                ).into(),
            });
        }

        // Record what list of features is active for this package.
        if !reqs.used.is_empty() {
            let pkgid = s.package_id();

            let set = self.resolve_features
                .entry(pkgid.clone())
                .or_insert_with(HashSet::new);
            for feature in reqs.used {
                set.insert(InternedString::new(feature));
            }
        }

        Ok(ret)
    }

    pub fn resolve_replacements(&self) -> HashMap<PackageId, PackageId> {
        let mut replacements = HashMap::new();
        let mut cur = &self.resolve_replacements;
        while let Some(ref node) = cur.head {
            let (k, v) = node.0.clone();
            replacements.insert(k, v);
            cur = &node.1;
        }
        replacements
    }

    pub fn graph(&self) -> Graph<PackageId> {
        let mut graph = Graph::new();
        let mut cur = &self.resolve_graph;
        while let Some(ref node) = cur.head {
            match node.0 {
                GraphNode::Add(ref p) => graph.add(p.clone(), &[]),
                GraphNode::Link(ref a, ref b) => graph.link(a.clone(), b.clone()),
            }
            cur = &node.1;
        }
        graph
    }
}

/// Takes requested features for a single package from the input Method and
/// recurses to find all requested features, dependencies and requested
/// dependency features in a Requirements object, returning it to the resolver.
fn build_requirements<'a, 'b: 'a>(
    s: &'a Summary,
    method: &'b Method,
    requested: &'a [FeatureValue],
) -> CargoResult<Requirements<'a>> {
    let mut reqs = Requirements::new(s);
    for fv in requested.iter() {
        reqs.require_value(fv)?;
    }
    match *method {
        Method::Everything
        | Method::Required {
            all_features: true, ..
        } => {
            for key in s.features().keys() {
                reqs.require_feature(key)?;
            }
            for dep in s.dependencies().iter().filter(|d| d.is_optional()) {
                reqs.require_dependency(dep.name().as_str());
            }
        }
        _ => {} // Explicitly requested features are handled through `requested`
    }
    match *method {
        Method::Everything
        | Method::Required {
            uses_default_features: true,
            ..
        } => {
            if s.features().get("default").is_some() {
                reqs.require_feature("default")?;
            }
        }
        Method::Required {
            uses_default_features: false,
            ..
        } => {}
    }
    Ok(reqs)
}

struct Requirements<'a> {
    summary: &'a Summary,
    // The deps map is a mapping of package name to list of features enabled.
    // Each package should be enabled, and each package should have the
    // specified set of features enabled. The boolean indicates whether this
    // package was specifically requested (rather than just requesting features
    // *within* this package).
    deps: HashMap<&'a str, (bool, Vec<InternedString>)>,
    // The used features set is the set of features which this local package had
    // enabled, which is later used when compiling to instruct the code what
    // features were enabled.
    used: HashSet<&'a str>,
    visited: HashSet<&'a str>,
}

impl<'r> Requirements<'r> {
    fn new(summary: &Summary) -> Requirements {
        Requirements {
            summary,
            deps: HashMap::new(),
            used: HashSet::new(),
            visited: HashSet::new(),
        }
    }

    fn require_crate_feature(&mut self, package: &'r str, feat: InternedString) {
        self.used.insert(package);
        self.deps
            .entry(package)
            .or_insert((false, Vec::new()))
            .1
            .push(feat);
    }

    fn seen(&mut self, feat: &'r str) -> bool {
        if self.visited.insert(feat) {
            self.used.insert(feat);
            false
        } else {
            true
        }
    }

    fn require_dependency(&mut self, pkg: &'r str) {
        if self.seen(pkg) {
            return;
        }
        self.deps.entry(pkg).or_insert((false, Vec::new())).0 = true;
    }

    fn require_feature(&mut self, feat: &'r str) -> CargoResult<()> {
        if feat.is_empty() || self.seen(feat) {
            return Ok(());
        }
        for fv in self.summary
            .features()
            .get(feat)
            .expect("must be a valid feature")
        {
            match *fv {
                FeatureValue::Feature(ref dep_feat) if **dep_feat == *feat => bail!(
                    "Cyclic feature dependency: feature `{}` depends on itself",
                    feat
                ),
                _ => {}
            }
            self.require_value(fv)?;
        }
        Ok(())
    }

    fn require_value(&mut self, fv: &'r FeatureValue) -> CargoResult<()> {
        match *fv {
            FeatureValue::Feature(ref feat) => self.require_feature(feat),
            FeatureValue::Crate(ref dep) => Ok(self.require_dependency(dep)),
            FeatureValue::CrateFeature(ref dep, dep_feat) => {
                Ok(self.require_crate_feature(dep, dep_feat))
            }
        }
    }
}

pub type Activations = HashMap<(InternedString, SourceId), Rc<Vec<Summary>>>;
<commit_msg>use more Rc in the part of resolver that gets cloned a lot<commit_after>use std::collections::{HashMap, HashSet};
use std::rc::Rc;

use core::interning::InternedString;
use core::{Dependency, FeatureValue, PackageId, SourceId, Summary};
use util::CargoResult;
use util::Graph;

use super::types::RegistryQueryer;
use super::types::{ActivateResult, ConflictReason, DepInfo, GraphNode, Method, RcList};

pub use super::encode::{EncodableDependency, EncodablePackageId, EncodableResolve};
pub use super::encode::{Metadata, WorkspaceResolve};
pub use super::resolve::Resolve;

// A `Context` is basically a bunch of local resolution information which is
// kept around for all `BacktrackFrame` instances. As a result, this runs the
// risk of being cloned *a lot* so we want to make this as cheap to clone as
// possible.
#[derive(Clone)]
pub struct Context {
    // TODO: Both this and the two maps below are super expensive to clone. We should
    //       switch to persistent hash maps if we can at some point or otherwise
    //       make these much cheaper to clone in general.
    pub activations: Activations,
    pub resolve_features: HashMap<PackageId, Rc<HashSet<InternedString>>>,
    pub links: HashMap<InternedString, PackageId>,

    // These are two cheaply-cloneable lists (O(1) clone) which are effectively
    // hash maps but are built up as "construction lists". We'll iterate these
    // at the very end and actually construct the map that we're making.
    pub resolve_graph: RcList<GraphNode>,
    pub resolve_replacements: RcList<(PackageId, PackageId)>,

    // These warnings are printed after resolution.
    pub warnings: RcList<String>,
}

pub type Activations = HashMap<(InternedString, SourceId), Rc<Vec<Summary>>>;

impl Context {
    pub fn new() -> Context {
        Context {
            resolve_graph: RcList::new(),
            resolve_features: HashMap::new(),
            links: HashMap::new(),
            resolve_replacements: RcList::new(),
            activations: HashMap::new(),
            warnings: RcList::new(),
        }
    }

    /// Activate this summary by inserting it into our list of known activations.
    ///
    /// Returns true if this summary with the given method is already activated.
    pub fn flag_activated(&mut self, summary: &Summary, method: &Method) -> CargoResult<bool> {
        let id = summary.package_id();
        let prev = self.activations
            .entry((id.name(), id.source_id().clone()))
            .or_insert_with(|| Rc::new(Vec::new()));
        if !prev.iter().any(|c| c == summary) {
            self.resolve_graph.push(GraphNode::Add(id.clone()));
            if let Some(link) = summary.links() {
                ensure!(
                    self.links.insert(link, id.clone()).is_none(),
                    "Attempting to resolve a with more then one crate with the links={}. \n\
                     This will not build as is. Consider rebuilding the .lock file.",
                    &*link
                );
            }
            let mut inner: Vec<_> = (**prev).clone();
            inner.push(summary.clone());
            *prev = Rc::new(inner);
            return Ok(false);
        }
        debug!("checking if {} is already activated", summary.package_id());
        let (features, use_default) = match *method {
            Method::Everything
            | Method::Required {
                all_features: true, ..
            } => return Ok(false),
            Method::Required {
                features,
                uses_default_features,
                ..
            } => (features, uses_default_features),
        };

        let has_default_feature = summary.features().contains_key("default");
        Ok(match self.resolve_features.get(id) {
            Some(prev) => {
                features
                    .iter()
                    .all(|f| prev.contains(&InternedString::new(f)))
                    && (!use_default || prev.contains(&InternedString::new("default"))
                        || !has_default_feature)
            }
            None => features.is_empty() && (!use_default || !has_default_feature),
        })
    }

    pub fn build_deps(
        &mut self,
        registry: &mut RegistryQueryer,
        parent: Option<&Summary>,
        candidate: &Summary,
        method: &Method,
    ) -> ActivateResult<Vec<DepInfo>> {
        // First, figure out our set of dependencies based on the requested set
        // of features. This also calculates what features we're going to enable
        // for our own dependencies.
        let deps = self.resolve_features(parent, candidate, method)?;

        // Next, transform all dependencies into a list of possible candidates
        // which can satisfy that dependency.
        let mut deps = deps.into_iter()
            .map(|(dep, features)| {
                let candidates = registry.query(&dep)?;
                Ok((dep, candidates, Rc::new(features)))
            })
            .collect::<CargoResult<Vec<DepInfo>>>()?;

        // Attempt to resolve dependencies with fewer candidates before trying
        // dependencies with more candidates.  This way if the dependency with
        // only one candidate can't be resolved we don't have to do a bunch of
        // work before we figure that out.
        deps.sort_by_key(|&(_, ref a, _)| a.len());

        Ok(deps)
    }

    pub fn prev_active(&self, dep: &Dependency) -> &[Summary] {
        self.activations
            .get(&(dep.name(), dep.source_id().clone()))
            .map(|v| &v[..])
            .unwrap_or(&[])
    }

    fn is_active(&self, id: &PackageId) -> bool {
        self.activations
            .get(&(id.name(), id.source_id().clone()))
            .map(|v| v.iter().any(|s| s.package_id() == id))
            .unwrap_or(false)
    }

    /// checks whether all of `parent` and the keys of `conflicting activations`
    /// are still active
    pub fn is_conflicting(
        &self,
        parent: Option<&PackageId>,
        conflicting_activations: &HashMap<PackageId, ConflictReason>,
    ) -> bool {
        conflicting_activations
            .keys()
            .chain(parent)
            .all(|id| self.is_active(id))
    }

    /// Return all dependencies and the features we want from them.
    fn resolve_features<'b>(
        &mut self,
        parent: Option<&Summary>,
        s: &'b Summary,
        method: &'b Method,
    ) -> ActivateResult<Vec<(Dependency, Vec<InternedString>)>> {
        let dev_deps = match *method {
            Method::Everything => true,
            Method::Required { dev_deps, .. } => dev_deps,
        };

        // First, filter by dev-dependencies
        let deps = s.dependencies();
        let deps = deps.iter().filter(|d| d.is_transitive() || dev_deps);

        // Requested features stored in the Method are stored as string references, but we want to
        // transform them into FeatureValues here. In order to pass the borrow checker with
        // storage of the FeatureValues that outlives the Requirements object, we do the
        // transformation here, and pass the FeatureValues to build_requirements().
        let values = if let Method::Required {
            all_features: false,
            features: requested,
            ..
        } = *method
        {
            requested
                .iter()
                .map(|&f| FeatureValue::new(f, s))
                .collect::<Vec<FeatureValue>>()
        } else {
            vec![]
        };
        let mut reqs = build_requirements(s, method, &values)?;
        let mut ret = Vec::new();

        // Next, collect all actually enabled dependencies and their features.
        for dep in deps {
            // Skip optional dependencies, but not those enabled through a feature
            if dep.is_optional() && !reqs.deps.contains_key(&*dep.name()) {
                continue;
            }
            // So we want this dependency.  Move the features we want from `feature_deps`
            // to `ret`.
            let base = reqs.deps.remove(&*dep.name()).unwrap_or((false, vec![]));
            if !dep.is_optional() && base.0 {
                self.warnings.push(format!(
                    "Package `{}` does not have feature `{}`. It has a required dependency \
                     with that name, but only optional dependencies can be used as features. \
                     This is currently a warning to ease the transition, but it will become an \
                     error in the future.",
                    s.package_id(),
                    dep.name()
                ));
            }
            let mut base = base.1;
            base.extend(dep.features().iter());
            for feature in base.iter() {
                if feature.contains('/') {
                    return Err(
                        format_err!("feature names may not contain slashes: `{}`", feature).into(),
                    );
                }
            }
            ret.push((dep.clone(), base));
        }

        // Any remaining entries in feature_deps are bugs in that the package does not actually
        // have those dependencies.  We classified them as dependencies in the first place
        // because there is no such feature, either.
        if !reqs.deps.is_empty() {
            let unknown = reqs.deps.keys().map(|s| &s[..]).collect::<Vec<&str>>();
            let features = unknown.join(", ");
            return Err(match parent {
                None => format_err!(
                    "Package `{}` does not have these features: `{}`",
                    s.package_id(),
                    features
                ).into(),
                Some(p) => (
                    p.package_id().clone(),
                    ConflictReason::MissingFeatures(features),
                ).into(),
            });
        }

        // Record what list of features is active for this package.
        if !reqs.used.is_empty() {
            let pkgid = s.package_id();

            let set = self.resolve_features
                .entry(pkgid.clone())
                .or_insert_with(|| Rc::new(HashSet::new()));

            let mut inner: HashSet<_> = (**set).clone();
            for feature in reqs.used {
                inner.insert(InternedString::new(feature));
            }
            *set = Rc::new(inner);
        }

        Ok(ret)
    }

    pub fn resolve_replacements(&self) -> HashMap<PackageId, PackageId> {
        let mut replacements = HashMap::new();
        let mut cur = &self.resolve_replacements;
        while let Some(ref node) = cur.head {
            let (k, v) = node.0.clone();
            replacements.insert(k, v);
            cur = &node.1;
        }
        replacements
    }

    pub fn graph(&self) -> Graph<PackageId> {
        let mut graph = Graph::new();
        let mut cur = &self.resolve_graph;
        while let Some(ref node) = cur.head {
            match node.0 {
                GraphNode::Add(ref p) => graph.add(p.clone(), &[]),
                GraphNode::Link(ref a, ref b) => graph.link(a.clone(), b.clone()),
            }
            cur = &node.1;
        }
        graph
    }
}

/// Takes requested features for a single package from the input Method and
/// recurses to find all requested features, dependencies and requested
/// dependency features in a Requirements object, returning it to the resolver.
fn build_requirements<'a, 'b: 'a>(
    s: &'a Summary,
    method: &'b Method,
    requested: &'a [FeatureValue],
) -> CargoResult<Requirements<'a>> {
    let mut reqs = Requirements::new(s);
    for fv in requested.iter() {
        reqs.require_value(fv)?;
    }
    match *method {
        Method::Everything
        | Method::Required {
            all_features: true, ..
        } => {
            for key in s.features().keys() {
                reqs.require_feature(key)?;
            }
            for dep in s.dependencies().iter().filter(|d| d.is_optional()) {
                reqs.require_dependency(dep.name().as_str());
            }
        }
        _ => {} // Explicitly requested features are handled through `requested`
    }
    match *method {
        Method::Everything
        | Method::Required {
            uses_default_features: true,
            ..
        } => {
            if s.features().get("default").is_some() {
                reqs.require_feature("default")?;
            }
        }
        Method::Required {
            uses_default_features: false,
            ..
        } => {}
    }
    Ok(reqs)
}

struct Requirements<'a> {
    summary: &'a Summary,
    // The deps map is a mapping of package name to list of features enabled.
    // Each package should be enabled, and each package should have the
    // specified set of features enabled. The boolean indicates whether this
    // package was specifically requested (rather than just requesting features
    // *within* this package).
    deps: HashMap<&'a str, (bool, Vec<InternedString>)>,
    // The used features set is the set of features which this local package had
    // enabled, which is later used when compiling to instruct the code what
    // features were enabled.
    used: HashSet<&'a str>,
    visited: HashSet<&'a str>,
}

impl<'r> Requirements<'r> {
    fn new(summary: &Summary) -> Requirements {
        Requirements {
            summary,
            deps: HashMap::new(),
            used: HashSet::new(),
            visited: HashSet::new(),
        }
    }

    fn require_crate_feature(&mut self, package: &'r str, feat: InternedString) {
        self.used.insert(package);
        self.deps
            .entry(package)
            .or_insert((false, Vec::new()))
            .1
            .push(feat);
    }

    fn seen(&mut self, feat: &'r str) -> bool {
        if self.visited.insert(feat) {
            self.used.insert(feat);
            false
        } else {
            true
        }
    }

    fn require_dependency(&mut self, pkg: &'r str) {
        if self.seen(pkg) {
            return;
        }
        self.deps.entry(pkg).or_insert((false, Vec::new())).0 = true;
    }

    fn require_feature(&mut self, feat: &'r str) -> CargoResult<()> {
        if feat.is_empty() || self.seen(feat) {
            return Ok(());
        }
        for fv in self.summary
            .features()
            .get(feat)
            .expect("must be a valid feature")
        {
            match *fv {
                FeatureValue::Feature(ref dep_feat) if **dep_feat == *feat => bail!(
                    "Cyclic feature dependency: feature `{}` depends on itself",
                    feat
                ),
                _ => {}
            }
            self.require_value(fv)?;
        }
        Ok(())
    }

    fn require_value(&mut self, fv: &'r FeatureValue) -> CargoResult<()> {
        match *fv {
            FeatureValue::Feature(ref feat) => self.require_feature(feat),
            FeatureValue::Crate(ref dep) => Ok(self.require_dependency(dep)),
            FeatureValue::CrateFeature(ref dep, dep_feat) => {
                Ok(self.require_crate_feature(dep, dep_feat))
            }
        }
    }
}
<|endoftext|>


<commit_before>//
// base64.rs - base64 implementation
//
// The Base64 Alphabet
//
//  Value Encoding  Value Encoding  Value Encoding  Value Encoding
//   0 A            17 R            34 i            51 z
//   1 B            18 S            35 j            52 0
//   2 C            19 T            36 k            53 1
//   3 D            20 U            37 l            54 2
//   4 E            21 V            38 m            55 3
//   5 F            22 W            39 n            56 4
//   6 G            23 X            40 o            57 5
//   7 H            24 Y            41 p            58 6
//   8 I            25 Z            42 q            59 7
//   9 J            26 a            43 r            60 8
//  10 K            27 b            44 s            61 9
//  11 L            28 c            45 t            62 +
//  12 M            29 d            46 u            63 /
//  13 N            30 e            47 v
//  14 O            31 f            48 w         (pad) =
//  15 P            32 g            49 x
//  16 Q            33 h            50 y
//

use std;

import std::map;

export base64, mk_base64;

const padd: u8 = 61u8;

iface base64 {
    fn encode(src: [u8]) -> [u8];
    fn decode(src: [u8]) -> [u8];
    fn urlsafe_encode(src: [u8]) -> [u8];
    fn urlsafe_decode(src: [u8]) -> [u8];
}

fn mk_base64() -> base64 {
    type _base64 = {table: [u8]};

    impl of base64 for _base64 {
        fn encode(src: [u8]) -> [u8] {
            b64encode(self.table + [43u8, 47u8], src)
        }
        fn decode(src: [u8]) -> [u8] {
            b64decode(self.table + [43u8, 47u8], src)
        }
        fn urlsafe_encode(src: [u8]) -> [u8] {
            b64encode(self.table + [45u8, 95u8], src)
        }
        fn urlsafe_decode(src: [u8]) -> [u8] {
            b64decode(self.table + [45u8, 95u8], src)
        }
    }

    let table = vec::init_elt_mut(62u, 0u8), i = 0u8;
    u8::range(65u8, 91u8)  { |j| table[i] = j; i += 1u8; }
    u8::range(97u8, 123u8) { |j| table[i] = j; i += 1u8; }
    u8::range(48u8, 58u8)  { |j| table[i] = j; i += 1u8; }

    {table: vec::from_mut(table)} as base64
}

inline fn b64idx(x: u8, y: u8, z: u8) -> u8 {
    if 65u8 <= x && x <= 90u8 { x - 65u8 }
    else if 97u8 <= x && x <= 122u8 { x - 97u8 + 26u8 }
    else if 48u8 <= x && x <= 58u8  { x - 48u8 + 52u8 }
    else if x == y { 62u8 }
    else if x == z { 63u8 }
    else { fail "malformed base64 string"; }
}

fn b64encode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);
    let targ = if srclen % 3u == 0u {
        vec::init_elt_mut((srclen / 3u) * 4u, 0u8)
    } else {
        vec::init_elt_mut((srclen / 3u + 1u) * 4u, 0u8)
    };
    let input = vec::init_elt_mut(3u, 0u8);
    let output = vec::init_elt_mut(4u, 0u8);
    let curr = 0u, src_curr = 0u;

    while srclen > 2u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        srclen -= 3u; src_curr += 3u;

        output[0] = input[0] >> 2u8;
        output[1] = ((input[0] &  3u8) << 4u8) | (input[1] >> 4u8);
        output[2] = ((input[1] & 15u8) << 2u8) | (input[2] >> 6u8);
        output[3] = input[2] & 63u8;

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] = table[output[2]]; curr += 1u;
        targ[curr] = table[output[3]]; curr += 1u;
    }

    if srclen != 0u {
        input[0] = 0u8; input[1] = 0u8; input[2] = 0u8;

        alt srclen {
          1u { input[0] = src[src_curr]; }
          2u { input[0] = src[src_curr];
               input[1] = src[src_curr + 1u]; }
          _  { }
        }

        output[0] = input[0] >> 2u8;
        output[1] = ((input[0] &  3u8) << 4u8) | (input[1] >> 4u8);
        output[2] = ((input[1] & 15u8) << 2u8) | (input[2] >> 6u8);

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] = if srclen == 1u { padd } else { table[output[2]] };
        curr += 1u; targ[curr] = padd;
    }

    vec::from_mut(targ)
}

fn b64decode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);

    if srclen % 4u != 0u { fail "malformed base64 string"; }
    if srclen == 0u { ret []; }

    let input  = vec::init_elt_mut(4u, 0u8);
    let output = vec::init_elt_mut(4u, 0u8);
    let targ = if src[srclen - 2u] == padd {
        vec::init_elt_mut(srclen / 4u * 3u - 2u, 0u8)
    } else if src[srclen - 1u] == padd {
        vec::init_elt_mut(srclen / 4u * 3u - 1u, 0u8)
    } else {
        vec::init_elt_mut(srclen / 4u * 3u, 0u8)
    };
    let curr = 0u, src_curr = 0u;

    while srclen > 4u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        input[3] = src[src_curr + 3u];
        srclen -= 4u; src_curr += 4u;

        output[0] = b64idx(input[0], table[62], table[63]);
        output[1] = b64idx(input[1], table[62], table[63]);
        output[2] = b64idx(input[2], table[62], table[63]);
        output[3] = b64idx(input[3], table[62], table[63]);

        targ[curr] = (output[0] << 2u8) | (output[1] >> 4u8);
        curr += 1u;

        targ[curr] =
            ((output[1] & 15u8) << 4u8) | (output[2] >> 2u8);
        curr += 1u;

        targ[curr] = ((output[2] &  3u8) << 6u8) | output[3];
        curr += 1u;
    }

    if srclen == 4u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        input[3] = src[src_curr + 3u];

        output[0] = b64idx(input[0], table[62], table[63]);
        output[1] = b64idx(input[1], table[62], table[63]);

        targ[curr] = (output[0] << 2u8) | (output[1] >> 4u8);
        curr += 1u;

        if input[2] == padd { ret vec::from_mut(targ); }

        output[2] = b64idx(input[2], table[62], table[63]);

        targ[curr] = ((output[1] & 15u8) << 4u8) | (output[2] >> 2u8);
        curr += 1u;

        if input[3] == padd { ret vec::from_mut(targ); }

        output[3] = b64idx(input[3], table[62], table[63]);

        targ[curr] = ((output[2] & 3u8) << 6u8) | output[3];
    }

    vec::from_mut(targ)
}

#[cfg(test)]
mod tests {
    import core::str::{from_bytes, bytes};
    enum mode {
        t_decode,
        t_encode,
        t_urlsafe_encode,
        t_urlsafe_decode
    }
    fn setup(t: mode) -> map::hashmap<str, str> {
        let m = map::new_str_hash::<str>();
        m.insert("", "");
        alt t {
          t_decode | t_urlsafe_decode {
            m.insert("cGxlYXN1cmUu", "pleasure.");
            m.insert("bGVhc3VyZS4=",  "leasure.");
            m.insert("ZWFzdXJlLg==",   "easure.");
            m.insert("YXN1cmUu",        "asure.");
            m.insert("c3VyZS4=",         "sure.");
          }
          t_encode | t_urlsafe_encode {
            m.insert("pleasure.", "cGxlYXN1cmUu");
            m.insert("leasure.",  "bGVhc3VyZS4=");
            m.insert("easure.",   "ZWFzdXJlLg==");
            m.insert("asure.",        "YXN1cmUu");
            m.insert("sure.",         "c3VyZS4=");
          }
        }
        m
    }
    fn do_test(t: mode) {
        let b64 = mk_base64();
        let m = setup(t);
        m.keys { |k|
            let expected = m.get(k);
            let actual = alt t {
              t_decode { from_bytes(b64.decode(bytes(k))) }
              t_encode { from_bytes(b64.encode(bytes(k))) }
              t_urlsafe_decode { from_bytes(b64.urlsafe_decode(bytes(k))) }
              t_urlsafe_encode { from_bytes(b64.urlsafe_encode(bytes(k))) }
            };
            #debug("expected: %s", expected);
            #debug("actual:   %s", actual);
            assert expected == actual;
        }
    }
    #[test]
    fn decode() { do_test(t_decode); }
    #[test]
    fn encode() { do_test(t_encode); }
    #[test]
    fn urlsafe_decode() { do_test(t_urlsafe_decode); }
    #[test]
    fn urlsafe_encode() { do_test(t_urlsafe_encode); }
}
<commit_msg>mk_base64 -> mk<commit_after>//
// base64.rs - base64 implementation
//
// The Base64 Alphabet
//
//  Value Encoding  Value Encoding  Value Encoding  Value Encoding
//   0 A            17 R            34 i            51 z
//   1 B            18 S            35 j            52 0
//   2 C            19 T            36 k            53 1
//   3 D            20 U            37 l            54 2
//   4 E            21 V            38 m            55 3
//   5 F            22 W            39 n            56 4
//   6 G            23 X            40 o            57 5
//   7 H            24 Y            41 p            58 6
//   8 I            25 Z            42 q            59 7
//   9 J            26 a            43 r            60 8
//  10 K            27 b            44 s            61 9
//  11 L            28 c            45 t            62 +
//  12 M            29 d            46 u            63 /
//  13 N            30 e            47 v
//  14 O            31 f            48 w         (pad) =
//  15 P            32 g            49 x
//  16 Q            33 h            50 y
//

use std;

import std::map;

export base64, mk;

const padd: u8 = 61u8;

iface base64 {
    fn encode(src: [u8]) -> [u8];
    fn decode(src: [u8]) -> [u8];
    fn urlsafe_encode(src: [u8]) -> [u8];
    fn urlsafe_decode(src: [u8]) -> [u8];
}

fn mk() -> base64 {
    type _base64 = {table: [u8]};

    impl of base64 for _base64 {
        fn encode(src: [u8]) -> [u8] {
            b64encode(self.table + [43u8, 47u8], src)
        }
        fn decode(src: [u8]) -> [u8] {
            b64decode(self.table + [43u8, 47u8], src)
        }
        fn urlsafe_encode(src: [u8]) -> [u8] {
            b64encode(self.table + [45u8, 95u8], src)
        }
        fn urlsafe_decode(src: [u8]) -> [u8] {
            b64decode(self.table + [45u8, 95u8], src)
        }
    }

    let table = vec::init_elt_mut(62u, 0u8), i = 0u8;
    u8::range(65u8, 91u8)  { |j| table[i] = j; i += 1u8; }
    u8::range(97u8, 123u8) { |j| table[i] = j; i += 1u8; }
    u8::range(48u8, 58u8)  { |j| table[i] = j; i += 1u8; }

    {table: vec::from_mut(table)} as base64
}

inline fn b64idx(x: u8, y: u8, z: u8) -> u8 {
    if 65u8 <= x && x <= 90u8 { x - 65u8 }
    else if 97u8 <= x && x <= 122u8 { x - 97u8 + 26u8 }
    else if 48u8 <= x && x <= 58u8  { x - 48u8 + 52u8 }
    else if x == y { 62u8 }
    else if x == z { 63u8 }
    else { fail "malformed base64 string"; }
}

fn b64encode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);
    let targ = if srclen % 3u == 0u {
        vec::init_elt_mut((srclen / 3u) * 4u, 0u8)
    } else {
        vec::init_elt_mut((srclen / 3u + 1u) * 4u, 0u8)
    };
    let input = vec::init_elt_mut(3u, 0u8);
    let output = vec::init_elt_mut(4u, 0u8);
    let curr = 0u, src_curr = 0u;

    while srclen > 2u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        srclen -= 3u; src_curr += 3u;

        output[0] = input[0] >> 2u8;
        output[1] = ((input[0] &  3u8) << 4u8) | (input[1] >> 4u8);
        output[2] = ((input[1] & 15u8) << 2u8) | (input[2] >> 6u8);
        output[3] = input[2] & 63u8;

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] = table[output[2]]; curr += 1u;
        targ[curr] = table[output[3]]; curr += 1u;
    }

    if srclen != 0u {
        input[0] = 0u8; input[1] = 0u8; input[2] = 0u8;

        alt srclen {
          1u { input[0] = src[src_curr]; }
          2u { input[0] = src[src_curr];
               input[1] = src[src_curr + 1u]; }
          _  { }
        }

        output[0] = input[0] >> 2u8;
        output[1] = ((input[0] &  3u8) << 4u8) | (input[1] >> 4u8);
        output[2] = ((input[1] & 15u8) << 2u8) | (input[2] >> 6u8);

        targ[curr] = table[output[0]]; curr += 1u;
        targ[curr] = table[output[1]]; curr += 1u;
        targ[curr] = if srclen == 1u { padd } else { table[output[2]] };
        curr += 1u; targ[curr] = padd;
    }

    vec::from_mut(targ)
}

fn b64decode(table: [u8], src: [u8]) -> [u8] {
    let srclen = vec::len(src);

    if srclen % 4u != 0u { fail "malformed base64 string"; }
    if srclen == 0u { ret []; }

    let input  = vec::init_elt_mut(4u, 0u8);
    let output = vec::init_elt_mut(4u, 0u8);
    let targ = if src[srclen - 2u] == padd {
        vec::init_elt_mut(srclen / 4u * 3u - 2u, 0u8)
    } else if src[srclen - 1u] == padd {
        vec::init_elt_mut(srclen / 4u * 3u - 1u, 0u8)
    } else {
        vec::init_elt_mut(srclen / 4u * 3u, 0u8)
    };
    let curr = 0u, src_curr = 0u;

    while srclen > 4u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        input[3] = src[src_curr + 3u];
        srclen -= 4u; src_curr += 4u;

        output[0] = b64idx(input[0], table[62], table[63]);
        output[1] = b64idx(input[1], table[62], table[63]);
        output[2] = b64idx(input[2], table[62], table[63]);
        output[3] = b64idx(input[3], table[62], table[63]);

        targ[curr] = (output[0] << 2u8) | (output[1] >> 4u8);
        curr += 1u;

        targ[curr] =
            ((output[1] & 15u8) << 4u8) | (output[2] >> 2u8);
        curr += 1u;

        targ[curr] = ((output[2] &  3u8) << 6u8) | output[3];
        curr += 1u;
    }

    if srclen == 4u {
        input[0] = src[src_curr];
        input[1] = src[src_curr + 1u];
        input[2] = src[src_curr + 2u];
        input[3] = src[src_curr + 3u];

        output[0] = b64idx(input[0], table[62], table[63]);
        output[1] = b64idx(input[1], table[62], table[63]);

        targ[curr] = (output[0] << 2u8) | (output[1] >> 4u8);
        curr += 1u;

        if input[2] == padd { ret vec::from_mut(targ); }

        output[2] = b64idx(input[2], table[62], table[63]);

        targ[curr] = ((output[1] & 15u8) << 4u8) | (output[2] >> 2u8);
        curr += 1u;

        if input[3] == padd { ret vec::from_mut(targ); }

        output[3] = b64idx(input[3], table[62], table[63]);

        targ[curr] = ((output[2] & 3u8) << 6u8) | output[3];
    }

    vec::from_mut(targ)
}

#[cfg(test)]
mod tests {
    import core::str::{from_bytes, bytes};
    enum mode {
        t_decode,
        t_encode,
        t_urlsafe_encode,
        t_urlsafe_decode
    }
    fn setup(t: mode) -> map::hashmap<str, str> {
        let m = map::new_str_hash::<str>();
        m.insert("", "");
        alt t {
          t_decode | t_urlsafe_decode {
            m.insert("cGxlYXN1cmUu", "pleasure.");
            m.insert("bGVhc3VyZS4=",  "leasure.");
            m.insert("ZWFzdXJlLg==",   "easure.");
            m.insert("YXN1cmUu",        "asure.");
            m.insert("c3VyZS4=",         "sure.");
          }
          t_encode | t_urlsafe_encode {
            m.insert("pleasure.", "cGxlYXN1cmUu");
            m.insert("leasure.",  "bGVhc3VyZS4=");
            m.insert("easure.",   "ZWFzdXJlLg==");
            m.insert("asure.",        "YXN1cmUu");
            m.insert("sure.",         "c3VyZS4=");
          }
        }
        m
    }
    fn do_test(t: mode) {
        let b64 = mk();
        let m = setup(t);
        m.keys { |k|
            let expected = m.get(k);
            let actual = alt t {
              t_decode { from_bytes(b64.decode(bytes(k))) }
              t_encode { from_bytes(b64.encode(bytes(k))) }
              t_urlsafe_decode { from_bytes(b64.urlsafe_decode(bytes(k))) }
              t_urlsafe_encode { from_bytes(b64.urlsafe_encode(bytes(k))) }
            };
            #debug("expected: %s", expected);
            #debug("actual:   %s", actual);
            assert expected == actual;
        }
    }
    #[test]
    fn decode() { do_test(t_decode); }
    #[test]
    fn encode() { do_test(t_encode); }
    #[test]
    fn urlsafe_decode() { do_test(t_urlsafe_decode); }
    #[test]
    fn urlsafe_encode() { do_test(t_urlsafe_encode); }
}
<|endoftext|>


<commit_before>use super::{Memory, VectorMemory, Stack, VectorStack, PC, Result, Gas};
use ::account::Account;

pub type VectorMachine<'p> = Machine<'p, VectorMemory, VectorStack>;

pub struct Machine<'p, M, S> {
    available_gas: Gas,
    pub pc: PC<'p>,
    pub memory: M, // Contains i
    pub stack: S,
    pub account: Account,
}

impl<'p, M, S> Machine<'p, M, S> where M: Memory, S: Stack {
    pub fn new(code: &'p [u8], data: &[u8], available_gas: Gas) -> Self {
        Self {
            available_gas: available_gas,
            pc: PC::new(code),
            memory: M::new(),
            stack: S::new(),
            account: Account::default(),
        }
    }

    pub fn available_gas(&self) -> Gas {
        self.available_gas
    }

    pub fn step(&mut self) -> bool {
        if self.pc.is_stopped() || !self.available_gas.is_valid() {
            return false;
        }

        let opcode = self.pc.read_opcode();
        self.available_gas -= opcode.gas_cost_before(self);
        opcode.run(self);
        self.available_gas -= opcode.gas_cost_after(self);

        true
    }

    pub fn fire(&mut self) -> Result<Gas> {
        while self.step() { }
        Ok(self.available_gas)
    }
}
<commit_msg>Problem: Machine generics makes it hard to append new types to it Solution: (WIP) use associate types<commit_after>use super::{Memory, VectorMemory, Stack, VectorStack, PC, Result, Gas};
use account::{Account, FakeAccount};

pub type VectorMachine<'p> = Machine<'p, VectorMemory, VectorStack, FakeAccount>;

pub trait Machine {
    type P: PC;
    type M: Memory;
    type Sta: Stack;
    type Sto: Storage;
    type T: Transaction;
    type B: Block;
    type Bc: Blockchain;

    fn pc(&self) -> &P;
    fn pc_mut(&mut self) -> &mut P;
    fn memory(&self) -> &M;
    fn memory_mut(&mut self) -> &mut M;
    fn stack(&self) -> &Sta;
    fn stack_mut(&mut self) -> &mut Sta;
    fn storage(&self) -> &Sto;
    fn storage_mut(&mut self) -> &mut Sto;

    fn transaction(&self) -> &T;
    fn block(&self) -> &B;
    fn blockchain(&self) -> &Bc;
    fn available_gas(&self) -> Gas;
}

pub struct VectorMachine {
    pc: VectorPC,
    memory: VectorMemory,
    stack: VectorStack,
    storage: FakeStorage,
    transaction: FakeTransaction,
    block: FakeBlock,
    blockchain: FakeBlockchain,
    available_gas: Gas,
}

impl VectorMachine {
    pub fn new(code: &[u8], data: &[u8], available_gas: Gas) -> VectorMachine {
        VectorMachine {
            pc: VectorPC::new(code),
            memory: VectorMemory::new(),
            stack: VectorStack::new(),
            storage: FakeStorage::new(),
            transaction: FakeTransaction::message_call(U256::zero(), data),
            block: FakeBlock,
            blockchain: FakeBlockchain,
            available_gas: available_gas,
        }
    }
}

impl Machine for VectorMachine {
    type P = VectorPC;
    type M = VectorMemory;
    type Sta = VectorStack;
    type Sto = FakeStorage;
    type T = FakeTransaction;
    type B = FakeBlock;
    type Bc = FakeBlockchain;

    fn pc(&self) -> &P {
        &self.pc
    }

    fn pc_mut(&mut self) -> &mut P {
        &mut self.pc
    }

    fn memory(&self) -> &M {
        &self.memory
    }

    fn memory_mut(&mut self) -> &mut M {
        &mut self.memory
    }

    fn stack(&self) -> &Sta {
        &self.stack
    }

    fn stack_mut(&mut self) -> &mut Sta {
        &mut self.stack
    }

    fn storage(&self) -> &Sto
}

impl<'p, M, S, A> Machine<'p, M, S, A> where M: Memory, S: Stack, A: Account {
    pub fn available_gas(&self) -> Gas {
        self.available_gas
    }

    pub fn step(&mut self) -> bool {
        if self.pc.is_stopped() || !self.available_gas.is_valid() {
            return false;
        }

        let opcode = self.pc.read_opcode();
        self.available_gas -= opcode.gas_cost_before(self);
        opcode.run(self);
        self.available_gas -= opcode.gas_cost_after(self);

        true
    }

    pub fn fire(&mut self) -> Result<Gas> {
        while self.step() { }
        Ok(self.available_gas)
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate gcc;
extern crate cmake;
extern crate pkg_config;

use std::path::Path;
use std::process::Command;

const GRPC_VERSION: &'static str = "1.2.5";
const ZLIB_VERSION: &'static str = "1.2.8";
const BORINGSSL_GIT_HASH: &'static str = "78684e5b222645828ca302e56b40b9daff2b2d27";

fn wget(url: &str, out: &str) -> Result<(), String> {
    Command::new("wget").args(&["-q", "-c", "-O", out, url])
        .status()
        .map_err(|err| format!("wget execute failed: {}", err))
        .and_then(|status| {
            if status.success() {
                Ok(())
            } else {
                Err(format!("wget exit with {}", status))
            }
        })
}

fn tar_xf(file: &str) -> Result<(), String> {
    Command::new("tar").args(&["zxf", file])
        .status()
        .map_err(|err| format!("tar execute failed: {}", err))
        .and_then(|status| {
            if status.success() {
                Ok(())
            } else {
                Err(format!("tar exit with {}", status))
            }
        })
}

fn build_or_link_grpc(cc: &mut gcc::Config) {
    if let Ok(lib) = pkg_config::Config::new().atleast_version("1.2.5").statik(true).probe("grpc_unsecure") {
        for inc_path in &lib.include_paths {
            cc.include(inc_path);
        }
        return;

    }

    if !Path::new(&format!("grpc-{}", GRPC_VERSION)).exists() {
        wget(&format!("https://github.com/grpc/grpc/archive/v{}.tar.gz", GRPC_VERSION),
             "grpc.tar.gz")
            .and_then(|_| tar_xf("grpc.tar.gz"))
            .unwrap();
    }

    if !Path::new(&format!("zlib-{}", ZLIB_VERSION)).exists() {
        wget(&format!("https://github.com/madler/zlib/archive/v{}.tar.gz", ZLIB_VERSION),
             "zlib.tar.gz")
            .and_then(|_| tar_xf("zlib.tar.gz"))
            .unwrap();
    }

    if !Path::new(&format!("boringssl-{}", BORINGSSL_GIT_HASH)).exists() {
        wget(&format!("https://github.com/google/boringssl/archive/{}.tar.gz", BORINGSSL_GIT_HASH),
             "boringssl.tar.gz")
            .and_then(|_| tar_xf("boringssl.tar.gz"))
            .unwrap();
    }

    let dst = cmake::Config::new(format!("zlib-{}", ZLIB_VERSION))
        .build();

    println!("cargo:rustc-link-search=native={}/lib", dst.display());

    let dst = cmake::Config::new("grpc-1.2.5")
        .define("ZLIB_ROOT_DIR", format!("../zlib-{}", ZLIB_VERSION)) // relative to grpc dir
        .define("BORINGSSL_ROOT_DIR", format!("../boringssl-{}", BORINGSSL_GIT_HASH))
        .build_target("grpc_unsecure")
        .build();

    cc.include("grpc/include");

    println!("cargo:rustc-link-search=native={}/build", dst.display());
    println!("cargo:rustc-link-search=native={}/build/third_party/zlib", dst.display());

    println!("cargo:rustc-link-lib=static=z");
    println!("cargo:rustc-link-lib=static=gpr");
    println!("cargo:rustc-link-lib=static=grpc_unsecure");
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");

    let mut cc = gcc::Config::new();

    build_or_link_grpc(&mut cc);

    cc.file("grpc_wrap.c")
        .flag("-fPIC")
        .flag("-O2")
        .compile("libgrpc_wrap.a");
}
<commit_msg>*: fix typo<commit_after>// Copyright 2017 PingCAP, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate gcc;
extern crate cmake;
extern crate pkg_config;

use std::path::Path;
use std::process::Command;

const GRPC_VERSION: &'static str = "1.2.5";
const ZLIB_VERSION: &'static str = "1.2.8";
const BORINGSSL_GIT_HASH: &'static str = "78684e5b222645828ca302e56b40b9daff2b2d27";

fn wget(url: &str, out: &str) -> Result<(), String> {
    Command::new("wget").args(&["-q", "-c", "-O", out, url])
        .status()
        .map_err(|err| format!("wget execute failed: {}", err))
        .and_then(|status| {
            if status.success() {
                Ok(())
            } else {
                Err(format!("wget exit with {}", status))
            }
        })
}

fn tar_xf(file: &str) -> Result<(), String> {
    Command::new("tar").args(&["zxf", file])
        .status()
        .map_err(|err| format!("tar execute failed: {}", err))
        .and_then(|status| {
            if status.success() {
                Ok(())
            } else {
                Err(format!("tar exit with {}", status))
            }
        })
}

fn build_or_link_grpc(cc: &mut gcc::Config) {
    if let Ok(lib) = pkg_config::Config::new().atleast_version(GRPC_VERSION).statik(true).probe("grpc_unsecure") {
        for inc_path in &lib.include_paths {
            cc.include(inc_path);
        }
        return;

    }

    if !Path::new(&format!("grpc-{}", GRPC_VERSION)).exists() {
        wget(&format!("https://github.com/grpc/grpc/archive/v{}.tar.gz", GRPC_VERSION),
             "grpc.tar.gz")
            .and_then(|_| tar_xf("grpc.tar.gz"))
            .unwrap();
    }

    if !Path::new(&format!("zlib-{}", ZLIB_VERSION)).exists() {
        wget(&format!("https://github.com/madler/zlib/archive/v{}.tar.gz", ZLIB_VERSION),
             "zlib.tar.gz")
            .and_then(|_| tar_xf("zlib.tar.gz"))
            .unwrap();
    }

    if !Path::new(&format!("boringssl-{}", BORINGSSL_GIT_HASH)).exists() {
        wget(&format!("https://github.com/google/boringssl/archive/{}.tar.gz", BORINGSSL_GIT_HASH),
             "boringssl.tar.gz")
            .and_then(|_| tar_xf("boringssl.tar.gz"))
            .unwrap();
    }

    let dst = cmake::Config::new(format!("zlib-{}", ZLIB_VERSION))
        .build();

    println!("cargo:rustc-link-search=native={}/lib", dst.display());

    let dst = cmake::Config::new(format!("grpc-{}", GRPC_VERSION))
        .define("ZLIB_ROOT_DIR", format!("../zlib-{}", ZLIB_VERSION)) // relative to grpc dir
        .define("BORINGSSL_ROOT_DIR", format!("../boringssl-{}", BORINGSSL_GIT_HASH))
        .build_target("grpc_unsecure")
        .build();

    cc.include(format!("grpc-{}/include", GRPC_VERSION));

    println!("cargo:rustc-link-search=native={}/build", dst.display());
    println!("cargo:rustc-link-search=native={}/build/third_party/zlib", dst.display());

    println!("cargo:rustc-link-lib=static=z");
    println!("cargo:rustc-link-lib=static=gpr");
    println!("cargo:rustc-link-lib=static=grpc_unsecure");
}

fn main() {
    println!("cargo:rerun-if-changed=build.rs");

    let mut cc = gcc::Config::new();

    build_or_link_grpc(&mut cc);

    cc.file("grpc_wrap.c")
        .flag("-fPIC")
        .flag("-O2")
        .compile("libgrpc_wrap.a");
}
<|endoftext|>


<commit_before>use core::fmt;
use core::ops::{Deref, DerefMut};

/// Pads and aligns a value to the length of a cache line.
///
/// In concurrent programming, sometimes it is desirable to make sure commonly accessed pieces of
/// data are not placed into the same cache line. Updating an atomic value invalidates the whole
/// cache line it belongs to, which makes the next access to the same cache line slower for other
/// CPU cores. Use `CachePadded` to ensure updating one piece of data doesn't invalidate other
/// cached data.
///
/// # Size and alignment
///
/// Cache lines are assumed to be N bytes long, depending on the architecture:
///
/// * On x86-64 and aarch64, N = 128.
/// * On all others, N = 64.
///
/// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line
/// length of the machine the program is running on. On modern Intel architectures, spatial
/// prefetcher is pulling pairs of 64-byte cache lines at a time, so we pessimistically assume that
/// cache lines are 128 bytes long.
///
/// The size of `CachePadded<T>` is the smallest multiple of N bytes large enough to accommodate
/// a value of type `T`.
///
/// The alignment of `CachePadded<T>` is the maximum of N bytes and the alignment of `T`.
///
/// # Examples
///
/// Alignment and padding:
///
/// ```
/// use crossbeam_utils::CachePadded;
///
/// let array = [CachePadded::new(1i8), CachePadded::new(2i8)];
/// let addr1 = &*array[0] as *const i8 as usize;
/// let addr2 = &*array[1] as *const i8 as usize;
///
/// assert!(addr2 - addr1 >= 64);
/// assert_eq!(addr1 % 64, 0);
/// assert_eq!(addr2 % 64, 0);
/// ```
///
/// When building a concurrent queue with a head and a tail index, it is wise to place them in
/// different cache lines so that concurrent threads pushing and popping elements don't invalidate
/// each other's cache lines:
///
/// ```
/// use crossbeam_utils::CachePadded;
/// use std::sync::atomic::AtomicUsize;
///
/// struct Queue<T> {
///     head: CachePadded<AtomicUsize>,
///     tail: CachePadded<AtomicUsize>,
///     buffer: *mut T,
/// }
/// ```
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq)]
// Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache
// lines at a time, so we have to align to 128 bytes rather than 64.
//
// Sources:
// - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
// - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
//
// ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128 byte cache line size
// Sources:
// - https://www.mono-project.com/news/2016/09/12/arm64-icache/
//
#[cfg_attr(any(target_arch = "x86_64", target_arch = "aarch64"), repr(align(128)))]
#[cfg_attr(
    not(any(target_arch = "x86_64", target_arch = "aarch64")),
    repr(align(64))
)]
pub struct CachePadded<T> {
    value: T,
}

unsafe impl<T: Send> Send for CachePadded<T> {}
unsafe impl<T: Sync> Sync for CachePadded<T> {}

impl<T> CachePadded<T> {
    /// Pads and aligns a value to the length of a cache line.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(1);
    /// ```
    pub const fn new(t: T) -> CachePadded<T> {
        CachePadded::<T> { value: t }
    }

    /// Returns the inner value.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(7);
    /// let value = padded_value.into_inner();
    /// assert_eq!(value, 7);
    /// ```
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T> Deref for CachePadded<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for CachePadded<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T: fmt::Debug> fmt::Debug for CachePadded<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("CachePadded")
            .field("value", &self.value)
            .finish()
    }
}

impl<T> From<T> for CachePadded<T> {
    fn from(t: T) -> Self {
        CachePadded::new(t)
    }
}
<commit_msg>CachePadded: update alignment based on golang's CacheLinePadSize<commit_after>use core::fmt;
use core::ops::{Deref, DerefMut};

/// Pads and aligns a value to the length of a cache line.
///
/// In concurrent programming, sometimes it is desirable to make sure commonly accessed pieces of
/// data are not placed into the same cache line. Updating an atomic value invalidates the whole
/// cache line it belongs to, which makes the next access to the same cache line slower for other
/// CPU cores. Use `CachePadded` to ensure updating one piece of data doesn't invalidate other
/// cached data.
///
/// # Size and alignment
///
/// Cache lines are assumed to be N bytes long, depending on the architecture:
///
/// * On x86-64, aarch64, and powerpc64, N = 128.
/// * On arm, mips, mips64, and riscv64, N = 32.
/// * On s390x, N = 256.
/// * On all others, N = 64.
///
/// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line
/// length of the machine the program is running on. On modern Intel architectures, spatial
/// prefetcher is pulling pairs of 64-byte cache lines at a time, so we pessimistically assume that
/// cache lines are 128 bytes long.
///
/// The size of `CachePadded<T>` is the smallest multiple of N bytes large enough to accommodate
/// a value of type `T`.
///
/// The alignment of `CachePadded<T>` is the maximum of N bytes and the alignment of `T`.
///
/// # Examples
///
/// Alignment and padding:
///
/// ```
/// use crossbeam_utils::CachePadded;
///
/// let array = [CachePadded::new(1i8), CachePadded::new(2i8)];
/// let addr1 = &*array[0] as *const i8 as usize;
/// let addr2 = &*array[1] as *const i8 as usize;
///
/// assert!(addr2 - addr1 >= 64);
/// assert_eq!(addr1 % 64, 0);
/// assert_eq!(addr2 % 64, 0);
/// ```
///
/// When building a concurrent queue with a head and a tail index, it is wise to place them in
/// different cache lines so that concurrent threads pushing and popping elements don't invalidate
/// each other's cache lines:
///
/// ```
/// use crossbeam_utils::CachePadded;
/// use std::sync::atomic::AtomicUsize;
///
/// struct Queue<T> {
///     head: CachePadded<AtomicUsize>,
///     tail: CachePadded<AtomicUsize>,
///     buffer: *mut T,
/// }
/// ```
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq)]
// Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache
// lines at a time, so we have to align to 128 bytes rather than 64.
//
// Sources:
// - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
// - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
//
// ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128-byte cache line size.
//
// Sources:
// - https://www.mono-project.com/news/2016/09/12/arm64-icache/
//
// powerpc64 has 128-byte cache line size.
//
// Sources:
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_ppc64x.go#L9
#[cfg_attr(
    any(
        target_arch = "x86_64",
        target_arch = "aarch64",
        target_arch = "powerpc64",
    ),
    repr(align(128))
)]
// arm, mips, mips64, and riscv64 have 32-byte cache line size.
//
// Sources:
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
#[cfg_attr(
    any(
        target_arch = "arm",
        target_arch = "mips",
        target_arch = "mips64",
        target_arch = "riscv64",
    ),
    repr(align(32))
)]
// s390x has 256-byte cache line size.
//
// Sources:
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7
#[cfg_attr(target_arch = "s390x", repr(align(256)))]
// x86 and wasm have 64-byte cache line size.
//
// Sources:
// - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9
// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7
//
// All others are assumed to have 64-byte cache line size.
#[cfg_attr(
    not(any(
        target_arch = "x86_64",
        target_arch = "aarch64",
        target_arch = "powerpc64",
        target_arch = "arm",
        target_arch = "mips",
        target_arch = "mips64",
        target_arch = "riscv64",
        target_arch = "s390x",
    )),
    repr(align(64))
)]
pub struct CachePadded<T> {
    value: T,
}

unsafe impl<T: Send> Send for CachePadded<T> {}
unsafe impl<T: Sync> Sync for CachePadded<T> {}

impl<T> CachePadded<T> {
    /// Pads and aligns a value to the length of a cache line.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(1);
    /// ```
    pub const fn new(t: T) -> CachePadded<T> {
        CachePadded::<T> { value: t }
    }

    /// Returns the inner value.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(7);
    /// let value = padded_value.into_inner();
    /// assert_eq!(value, 7);
    /// ```
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T> Deref for CachePadded<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for CachePadded<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T: fmt::Debug> fmt::Debug for CachePadded<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("CachePadded")
            .field("value", &self.value)
            .finish()
    }
}

impl<T> From<T> for CachePadded<T> {
    fn from(t: T) -> Self {
        CachePadded::new(t)
    }
}
<|endoftext|>


<commit_before>
#![feature(globs)]

extern crate graphics;
extern crate piston;

use piston::{
    AssetStore,
    Game,
    GameWindow,
    GameWindowSDL2,
    GameWindowSettings,
    keyboard,
};

pub struct App;

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App
    }
}

impl Game for App {
    fn key_press(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        println!("{}", key);
    }

}

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "Keycode".to_owned(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            background_color: [1.0, 1.0, 1.0, 1.0],
        }
    );

    let mut asset_store = AssetStore::empty();

    let mut app = App::new();
    app.run(&mut window, &mut asset_store);
}

<commit_msg>Print keycode when released a key<commit_after>
#![feature(globs)]

extern crate graphics;
extern crate piston;

use piston::{
    AssetStore,
    Game,
    GameWindow,
    GameWindowSDL2,
    GameWindowSettings,
    keyboard,
};

pub struct App;

impl App {
    /// Creates a new application.
    pub fn new() -> App {
        App
    }
}

impl Game for App {
    fn key_press(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        println!("PRESSED  [{}]", key);
    }

    fn key_release(
        &mut self,
        key: keyboard::Key,
        _asset_store: &mut AssetStore
    ) {
        println!("RELEASED [{}]", key);
    }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "Keycode".to_owned(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            background_color: [1.0, 1.0, 1.0, 1.0],
        }
    );

    let mut asset_store = AssetStore::empty();

    let mut app = App::new();
    app.run(&mut window, &mut asset_store);
}

<|endoftext|>


<commit_before>/* Sample bubble sort program in Rust.
   Tested to compile with rust-0.6-f1ddb8d.

   $ rustc bubble-sort.rs
   $ time ./bubble-sort

   real 1m2.749s
   user 1m2.580s
   sys  0m0.008s
*/
use core::rand;
use core::vec;

fn generate_random_array(size: uint) -> ~[uint] {
    let ret = vec::build_sized(size, |push| {
        for size.times {
            push(rand::random());
        }
    });

    return ret;
}

fn bubble_sort(mut arr: ~[uint]) -> ~[uint] {
    let mut left = 0;
    let mut right: uint;
    let max = arr.len();
    while left < max {
        right = left + 1;
        while right < max {
            if arr[right] < arr[left] {
                // swap the two values
                arr[left] <-> arr[right];
            }
            right += 1;
        }

        left += 1;
    }

    return arr;
}

fn main() {
    let vals = generate_random_array(100000);
    let sorted_vals = bubble_sort(vals);
    /*for sorted_vals.each |v| {
        core::io::println(fmt!("%?", *v));
    }*/
}
<commit_msg>Updated bubble-sort program to correctly time the sort.<commit_after>/* Sample bubble sort program in Rust.
   Tested to compile with rust-0.6-f1ddb8d.

   $ rustc bubble-sort.rs
   $ time ./bubble-sort

   real 1m2.749s
   user 1m2.580s
   sys  0m0.008s
*/
extern mod std;
use core::rand;
use core::vec;
use core::cell;

fn generate_random_array(size: uint) -> ~[uint] {
    let ret = vec::build_sized(size, |push| {
        for size.times {
            push(rand::random());
        }
    });

    return ret;
}

struct Timer {
    mut start_time: u64,
    mut end_time: u64
}

impl Timer {
    fn new() -> Timer {
        Timer { start_time: 0, end_time: 0}
    }
    fn start(&mut self) -> () {
        self.start_time = std::time::precise_time_ns();
    }
    fn end(&mut self) -> () {
        self.end_time = std::time::precise_time_ns();
    }
    fn get_time_string(&mut self) -> ~str {
        let MIN_MULTIPLIER:u64 = 60 * 1000 * 1000 * 1000;
        let SEC_MULTIPLIER:u64 = 1000 * 1000 * 1000;

        let total_time = self.end_time - self.start_time;
        let minutes = total_time / MIN_MULTIPLIER;
        let seconds = (total_time - minutes * MIN_MULTIPLIER) / SEC_MULTIPLIER;
        let nanoseconds = (total_time - minutes * MIN_MULTIPLIER - seconds * SEC_MULTIPLIER);

        let mut time_string = ~"";
        if minutes > 0 {
            time_string += fmt!("%?:", minutes);
        }
        if minutes > 0 || seconds > 0 {
            if seconds < 10 {
                // HACK: fmt!("%02?.", seconds) doesn't zero pad
                time_string += "0";
            }
            time_string += fmt!("%2?.", seconds);
        }
        time_string += fmt!("%.5?", nanoseconds);

        if minutes > 0 {
            time_string += " min";
        } else if seconds > 0 {
            time_string += " sec";
        } else {
            time_string += " ns";
        }

        //time_string += fmt!(" (%?)", total_time);

        return time_string;
    }
    fn show_time(&mut self) -> () {
        core::io::println(fmt!("Total time: %s", self.get_time_string()));
    }
    fn run(&mut self, operation: &fn()) -> () {
        self.start();
        operation();
        self.end();
    }
}

fn bubble_sort(arr: &mut [uint]) -> () {
    let mut left = 0;
    let mut right: uint;
    let mut modified: bool;
    let max = arr.len();
    while left < max {
        right = left + 1;
        modified = false;
        while right < max {
            if arr[right] < arr[left] {
                // swap the two values
                let old_right = arr[right];
                arr[right] = arr[left];
                arr[left] = old_right;
                modified = true;
            }
            right += 1;
        }
        if !modified {
            // early exit if we have everything in place already
            return;
        }

        left += 1;
    }

    return;
}

fn ensure_sorted(arr: &[uint]) -> bool {
    let mut left = 0;
    let mut previous_value = 0;
    let max = arr.len();
    while left < max {
        if arr[left] < previous_value {
            return false
        }
        previous_value = arr[left];
        left += 1;
    }
    true
}

fn run(num: uint) -> () {
    let mut vals = generate_random_array(num);
    let sorted_vals:cell::Cell<~[uint]> = cell::Cell(~[]);
    let mut timer = Timer::new();

    let runner = || {
        bubble_sort(vals);
    };

    /* Run the sort and record the timing */
    core::io::println("Starting sort ...");
    timer.run(runner);
    core::io::println("Sort finished, verifying ...");

    /* Check that it actually is sorted */
    if !ensure_sorted(vals) {
        /* Print the values so we can see what they actually look like.
           Note: Should probably only do this if the array is small */
        for sorted_vals.take().each |v| {
            core::io::println(fmt!("%?", v));
        }
        fail!("Array was not sorted correctly");
    }

    /* Show the time it took */
    core::io::println("Sort was correct.");
    timer.show_time();
}

fn main() {
    run(100000);
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![crate_name="mathx"]
#![crate_type="dylib"]

extern crate libc;
extern crate lua;

// import low level lua_State
use lua::ffi::lua_State;

// import high level lua_State wrapper and a type we'll need for library
// registration
use lua::{State, Function};

// import c_int since we need this to interface with Lua
use libc::c_int;

// sin/cos/tan
use std::num::Float;

// simple binding to Rust's sin function
#[allow(non_snake_case)]
extern "C" fn sin(L: *mut lua_State) -> c_int {
  let mut state = State::from_ptr(L);
  // convert the value on top of the stack to a number
  let num = state.to_number(-1);
  // push the sine of that number onto the stack
  state.push_number(num.sin());
  // return one value to Lua
  1
}

// simple binding to Rust's cos function
#[allow(non_snake_case)]
extern "C" fn cos(L: *mut lua_State) -> c_int {
  let mut state = State::from_ptr(L);
  let num = state.to_number(-1);
  state.push_number(num.cos());
  1
}

// simple binding to Rust's tan function
#[allow(non_snake_case)]
extern "C" fn tan(L: *mut lua_State) -> c_int {
  let mut state = State::from_ptr(L);
  let num = state.to_number(-1);
  state.push_number(num.tan());
  1
}

// mapping of function name to function pointer
const MATHX_LIB: [(&'static str, Function); 3] = [
  ("sin", Some::<extern "C" fn(*mut lua_State) -> c_int>(sin)),
  ("cos", Some::<extern "C" fn(*mut lua_State) -> c_int>(cos)),
  ("tan", Some::<extern "C" fn(*mut lua_State) -> c_int>(tan)),
];

// the format of this function name is defined by the Lua manual; the Lua
// interpreter will call into this when you require() this library
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn luaopen_mathx(L: *mut lua_State) -> c_int {
  // construct a state wrapper object from the pointer we were given
  let mut state = State::from_ptr(L);
  // create a new table and set fields for each function defined in MATHX_LIB
  state.new_lib(&MATHX_LIB);
  // return it on the stack
  1
}

<commit_msg>Update example<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![crate_name="mathx"]
#![crate_type="dylib"]

extern crate libc;
extern crate lua;

// import low level lua_State
use lua::ffi::lua_State;

// import high level lua_State wrapper and a type we'll need for library
// registration
use lua::{State, Function};

// import c_int since we need this to interface with Lua
use libc::c_int;

// sin/cos/tan
use std::num::Float;

// simple binding to Rust's sin function
#[allow(non_snake_case)]
extern "C" fn sin(L: *mut lua_State) -> c_int {
  let mut state = State::from_ptr(L);
  // convert the value on top of the stack to a number
  let num = state.to_number(-1);
  // push the sine of that number onto the stack
  state.push_number(num.sin());
  // return one value to Lua
  1
}

// simple binding to Rust's cos function
#[allow(non_snake_case)]
extern "C" fn cos(L: *mut lua_State) -> c_int {
  let mut state = State::from_ptr(L);
  let num = state.to_number(-1);
  state.push_number(num.cos());
  1
}

// simple binding to Rust's tan function
#[allow(non_snake_case)]
extern "C" fn tan(L: *mut lua_State) -> c_int {
  let mut state = State::from_ptr(L);
  let num = state.to_number(-1);
  state.push_number(num.tan());
  1
}

// mapping of function name to function pointer
const MATHX_LIB: [(&'static str, Function); 3] = [
  ("sin", Some(sin)),
  ("cos", Some(cos)),
  ("tan", Some(tan)),
];

// the format of this function name is defined by the Lua manual; the Lua
// interpreter will call into this when you require() this library
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn luaopen_mathx(L: *mut lua_State) -> c_int {
  // construct a state wrapper object from the pointer we were given
  let mut state = State::from_ptr(L);
  // create a new table and set fields for each function defined in MATHX_LIB
  state.new_lib(&MATHX_LIB);
  // return it on the stack
  1
}

<|endoftext|>


<commit_before><commit_msg>fix ambiguity_check<commit_after><|endoftext|>


<commit_before>use std::sync::atomic::{AtomicBool, Ordering};
use std::cmp::max;

use game::{Position, Move, Score, ScoreUnit, NumPlies};
use types::{Data};

use transposition_table::TranspositionTable;

#[derive(Copy, Clone, Debug)]
pub enum Bound {
    Exact(Score),
    Lower(Score),
    Upper(Score),
}
impl Bound {
    pub fn as_score(self) -> Score {
        match self {
            Bound::Exact(x) => x,
            Bound::Lower(x) => x,
            Bound::Upper(x) => x,
        }
    }
    pub fn is_exact(self) -> bool {
        if let Bound::Exact(_) = self { true } else { false }
    }
    pub fn is_lower(self) -> bool {
        if let Bound::Lower(_) = self { true } else { false }
    }
    pub fn is_upper(self) -> bool {
        if let Bound::Upper(_) = self { true } else { false }
    }
}

// TODO put more parameters here
#[derive(Clone)]
pub struct Param {
    pub draw_val: ScoreUnit,
    pub depth: Option<NumPlies>,
}

pub fn negamax(pos: &mut Position,
               alpha: Option<Score>,
               beta: Option<Score>,
               param: Param,
               table: &mut TranspositionTable,
               is_killed: &AtomicBool) -> (Bound, Option<Move>, Data) {
    negamax_generic(pos, alpha, beta, param, table, is_killed,
                    &mut |x| Box::new(x.legal_iter()),
                    &mut |x, draw_val, inner_alpha, inner_beta, table| {
                        let quiescence_param = Param {
                            draw_val: draw_val,
                            depth: None,
                        };
                        let (bound, _, data) = quiescence(x, inner_alpha, inner_beta, quiescence_param,
                                                          table, is_killed);
                        (bound, data)
                    },
                    &mut |_, _| None)
}

fn quiescence(pos: &mut Position,
              alpha: Option<Score>,
              beta: Option<Score>,
              param: Param,
              table: &mut TranspositionTable,
              is_killed: &AtomicBool) -> (Bound, Option<Move>, Data) {
    negamax_generic(pos, alpha, beta, param, table, is_killed,
                    &mut |x| Box::new(x.legal_noisy_iter()),
                    &mut |x, draw_val, _, _, _| (Bound::Exact(x.eval(draw_val)), Data::one_node()),
                    &mut |x, draw_val| Some(x.eval(draw_val)))
}

// TODO somehow eliminate the Box
fn negamax_generic<F, G, H>(pos: &mut Position,
                            alpha: Option<Score>,
                            beta: Option<Score>,
                            param: Param,
                            table: &mut TranspositionTable,
                            is_killed: &AtomicBool,
                            move_gen_fn: &mut F,
                            eval_fn: &mut G,
                            stand_pat_fn: &mut H) -> (Bound, Option<Move>, Data) where
for<'a> F: FnMut(&'a Position) -> Box<Iterator<Item = Move> + 'a>,
for<'b> G: FnMut(&'b mut Position, ScoreUnit, Option<Score>, Option<Score>,
                 &mut TranspositionTable) -> (Bound, Data),
for<'c> H: FnMut(&'c mut Position, ScoreUnit) -> Option<Score> {
    if is_killed.load(Ordering::Relaxed) {
        return (Bound::Exact(Score::Value(ScoreUnit(0))), None, Data::one_node());
    }

    if let Some(data_ref) = table.get(pos) {
        if data_ref.depth >= param.depth.unwrap_or(NumPlies(0)) {
            let table_bound = data_ref.bound;
            let table_best_move_opt = data_ref.best_move_opt.clone();
            let lower_than_alpha = alpha.is_some() &&
                                   !table_bound.is_lower() &&
                                   table_bound.as_score() <= alpha.unwrap();
            if lower_than_alpha { return (Bound::Upper(alpha.unwrap()), table_best_move_opt, Data::one_node()); }
            let higher_than_beta = beta.is_some() &&
                                   !table_bound.is_upper() &&
                                   table_bound.as_score() >= beta.unwrap();
            if higher_than_beta { return (Bound::Lower(beta.unwrap()), table_best_move_opt, Data::one_node()); }
            if table_bound.is_exact() { return (table_bound, table_best_move_opt, Data::one_node()); }
        }
    }

    if param.depth == Some(NumPlies(0)) {
        let (bound, data) = eval_fn(pos, param.draw_val, alpha, beta, table);
        table.set(pos, NumPlies(0), None, bound);
        return (bound, None, data);
    }

    let (has_legal, score_opt, best_move_opt, data): (bool, Option<Score>, Option<Move>, Data) = (|| {
        let temp = pos.clone();
        let move_iter = move_gen_fn(&temp);

        let mut has_legal = false;
        let mut prev_score_opt: Option<Score> = alpha;
        let mut prev_best_move_opt: Option<Move> = None;

        if let Some(stand_pat_score) = stand_pat_fn(pos, param.draw_val) {
            let new_score = match prev_score_opt {
                None => stand_pat_score,
                Some(prev_score) => max(prev_score, stand_pat_score),
            };

            has_legal = true;
            prev_score_opt = Some(new_score);

            if let Some(beta_val) = beta {
                if new_score >= beta_val {
                    return (true, beta, None, Data::one_node());
                }
            }
        }

        let mut prev_data = Data::one_node();

        for curr_move in move_iter {

            let new_alpha = beta.map(|x| x.decrement());
            let new_beta = prev_score_opt.map(|x| x.decrement());
            let new_param = Param {
                draw_val: -param.draw_val,
                depth: param.depth.map(|x| NumPlies(x.0 - 1))
            };
            let (temp_bound, _, temp_data) = pos.with_move(&curr_move, |new_pos|
                negamax_generic(new_pos,
                                new_alpha,
                                new_beta,
                                new_param,
                                table,
                                is_killed,
                                move_gen_fn,
                                eval_fn,
                                stand_pat_fn));
            let curr_score = temp_bound.as_score().increment();
            let curr_data = temp_data.increment();

            let (new_score, new_best_move_opt) = match prev_score_opt {
                None => (curr_score, Some(curr_move)),
                Some(prev_score) => {
                    if curr_score <= prev_score {
                        (prev_score, prev_best_move_opt)
                    } else {
                        (curr_score, Some(curr_move))
                    }
                }
            };
            let new_data = prev_data.combine(curr_data);

            has_legal = true;
            prev_score_opt = Some(new_score);
            prev_best_move_opt = new_best_move_opt;
            prev_data = new_data;

            if let Some(beta_val) = beta {
                if new_score >= beta_val {
                    prev_score_opt = beta;
                    break;
                }
            }
        }

        (has_legal, prev_score_opt, prev_best_move_opt, prev_data)
    })();

    if has_legal {
        let score = score_opt.unwrap();
        let bound = {
            if alpha.is_some() && score <= alpha.unwrap() {
                Bound::Upper(alpha.unwrap())
            } else if beta.is_some() && score >= beta.unwrap() {
                Bound::Lower(beta.unwrap())
            } else {
                Bound::Exact(score)
            }
        };
        table.set(pos, param.depth.unwrap_or(NumPlies(0)), best_move_opt.clone(), bound);
        (bound, best_move_opt, data)
    } else {
        let (bound, data) = eval_fn(pos, param.draw_val, alpha, beta, table);
        table.set(pos, param.depth.unwrap_or(NumPlies(0)), None, bound);
        (bound, None, data)
    }
}
<commit_msg>Search best move first<commit_after>use std::sync::atomic::{AtomicBool, Ordering};
use std::cmp::max;

use game::{Position, Move, Score, ScoreUnit, NumPlies};
use types::{Data};

use transposition_table::TranspositionTable;

#[derive(Copy, Clone, Debug)]
pub enum Bound {
    Exact(Score),
    Lower(Score),
    Upper(Score),
}
impl Bound {
    pub fn as_score(self) -> Score {
        match self {
            Bound::Exact(x) => x,
            Bound::Lower(x) => x,
            Bound::Upper(x) => x,
        }
    }
    pub fn is_exact(self) -> bool {
        if let Bound::Exact(_) = self { true } else { false }
    }
    pub fn is_lower(self) -> bool {
        if let Bound::Lower(_) = self { true } else { false }
    }
    pub fn is_upper(self) -> bool {
        if let Bound::Upper(_) = self { true } else { false }
    }
}

// TODO put more parameters here
#[derive(Clone)]
pub struct Param {
    pub draw_val: ScoreUnit,
    pub depth: Option<NumPlies>,
}

pub fn negamax(pos: &mut Position,
               alpha: Option<Score>,
               beta: Option<Score>,
               param: Param,
               table: &mut TranspositionTable,
               is_killed: &AtomicBool) -> (Bound, Option<Move>, Data) {
    negamax_generic(pos, alpha, beta, param, table, is_killed,
                    &mut |x| Box::new(x.legal_iter()),
                    &mut |x, draw_val, inner_alpha, inner_beta, table| {
                        let quiescence_param = Param {
                            draw_val: draw_val,
                            depth: None,
                        };
                        let (bound, _, data) = quiescence(x, inner_alpha, inner_beta, quiescence_param,
                                                          table, is_killed);
                        (bound, data)
                    },
                    &mut |_, _| None)
}

fn quiescence(pos: &mut Position,
              alpha: Option<Score>,
              beta: Option<Score>,
              param: Param,
              table: &mut TranspositionTable,
              is_killed: &AtomicBool) -> (Bound, Option<Move>, Data) {
    negamax_generic(pos, alpha, beta, param, table, is_killed,
                    &mut |x| Box::new(x.legal_noisy_iter()),
                    &mut |x, draw_val, _, _, _| (Bound::Exact(x.eval(draw_val)), Data::one_node()),
                    &mut |x, draw_val| Some(x.eval(draw_val)))
}

// TODO somehow eliminate the Box
fn negamax_generic<F, G, H>(pos: &mut Position,
                            alpha: Option<Score>,
                            beta: Option<Score>,
                            param: Param,
                            table: &mut TranspositionTable,
                            is_killed: &AtomicBool,
                            move_gen_fn: &mut F,
                            eval_fn: &mut G,
                            stand_pat_fn: &mut H) -> (Bound, Option<Move>, Data) where
for<'a> F: FnMut(&'a Position) -> Box<Iterator<Item = Move> + 'a>,
for<'b> G: FnMut(&'b mut Position, ScoreUnit, Option<Score>, Option<Score>,
                 &mut TranspositionTable) -> (Bound, Data),
for<'c> H: FnMut(&'c mut Position, ScoreUnit) -> Option<Score> {
    if is_killed.load(Ordering::Relaxed) {
        return (Bound::Exact(Score::Value(ScoreUnit(0))), None, Data::one_node());
    }

    let mut table_best_move_opt = None;
    if let Some(data_ref) = table.get(pos) {
        table_best_move_opt = data_ref.best_move_opt.clone();
        if data_ref.depth >= param.depth.unwrap_or(NumPlies(0)) {
            let table_bound = data_ref.bound;
            let lower_than_alpha = alpha.is_some() &&
                                   !table_bound.is_lower() &&
                                   table_bound.as_score() <= alpha.unwrap();
            if lower_than_alpha { return (Bound::Upper(alpha.unwrap()), table_best_move_opt, Data::one_node()); }
            let higher_than_beta = beta.is_some() &&
                                   !table_bound.is_upper() &&
                                   table_bound.as_score() >= beta.unwrap();
            if higher_than_beta { return (Bound::Lower(beta.unwrap()), table_best_move_opt, Data::one_node()); }
            if table_bound.is_exact() { return (table_bound, table_best_move_opt, Data::one_node()); }
        }
    }
    let table_best_move_opt = table_best_move_opt;

    if param.depth == Some(NumPlies(0)) {
        let (bound, data) = eval_fn(pos, param.draw_val, alpha, beta, table);
        table.set(pos, NumPlies(0), None, bound);
        return (bound, None, data);
    }

    let (has_legal, score_opt, best_move_opt, data): (bool, Option<Score>, Option<Move>, Data) = (|| {
        let temp = pos.clone();
        let move_iter: Box<Iterator<Item = Move>> = {
            let normal_iter = move_gen_fn(&temp);
            if let Some(ref table_move) = table_best_move_opt {
                let is_table_move_valid = move_gen_fn(&temp).any(|y| y == *table_move);
                if is_table_move_valid {
                    Box::new(Some(table_move.clone()).into_iter()
                                            .chain(normal_iter.filter(move |x| *x != *table_move)))
                } else {
                    normal_iter
                }
            } else {
                normal_iter
            }
        };

        let mut has_legal = false;
        let mut prev_score_opt: Option<Score> = alpha;
        let mut prev_best_move_opt: Option<Move> = None;

        if let Some(stand_pat_score) = stand_pat_fn(pos, param.draw_val) {
            let new_score = match prev_score_opt {
                None => stand_pat_score,
                Some(prev_score) => max(prev_score, stand_pat_score),
            };

            has_legal = true;
            prev_score_opt = Some(new_score);

            if let Some(beta_val) = beta {
                if new_score >= beta_val {
                    return (true, beta, None, Data::one_node());
                }
            }
        }

        let mut prev_data = Data::one_node();

        for curr_move in move_iter {

            let new_alpha = beta.map(|x| x.decrement());
            let new_beta = prev_score_opt.map(|x| x.decrement());
            let new_param = Param {
                draw_val: -param.draw_val,
                depth: param.depth.map(|x| NumPlies(x.0 - 1))
            };
            let (temp_bound, _, temp_data) = pos.with_move(&curr_move, |new_pos|
                negamax_generic(new_pos,
                                new_alpha,
                                new_beta,
                                new_param,
                                table,
                                is_killed,
                                move_gen_fn,
                                eval_fn,
                                stand_pat_fn));
            let curr_score = temp_bound.as_score().increment();
            let curr_data = temp_data.increment();

            let (new_score, new_best_move_opt) = match prev_score_opt {
                None => (curr_score, Some(curr_move)),
                Some(prev_score) => {
                    if curr_score <= prev_score {
                        (prev_score, prev_best_move_opt)
                    } else {
                        (curr_score, Some(curr_move))
                    }
                }
            };
            let new_data = prev_data.combine(curr_data);

            has_legal = true;
            prev_score_opt = Some(new_score);
            prev_best_move_opt = new_best_move_opt;
            prev_data = new_data;

            if let Some(beta_val) = beta {
                if new_score >= beta_val {
                    prev_score_opt = beta;
                    break;
                }
            }
        }

        (has_legal, prev_score_opt, prev_best_move_opt, prev_data)
    })();

    if has_legal {
        let score = score_opt.unwrap();
        let bound = {
            if alpha.is_some() && score <= alpha.unwrap() {
                Bound::Upper(alpha.unwrap())
            } else if beta.is_some() && score >= beta.unwrap() {
                Bound::Lower(beta.unwrap())
            } else {
                Bound::Exact(score)
            }
        };
        table.set(pos, param.depth.unwrap_or(NumPlies(0)), best_move_opt.clone(), bound);
        (bound, best_move_opt, data)
    } else {
        let (bound, data) = eval_fn(pos, param.draw_val, alpha, beta, table);
        table.set(pos, param.depth.unwrap_or(NumPlies(0)), None, bound);
        (bound, None, data)
    }
}
<|endoftext|>