<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, 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
                );
            }
            Rc::make_mut(prev).push(summary.clone());
            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 reqs = build_requirements(s, method, &values)?;
        let mut ret = Vec::new();
        let mut used_features = HashSet::new();
        let default_dep = (false, 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` and register ourselves as using this
            // name.
            let base = reqs.deps.get(&*dep.name()).unwrap_or(&default_dep);
            used_features.insert(dep.name().as_str());
            let always_required = !dep.is_optional()
                && !s.dependencies()
                    .iter()
                    .any(|d| d.is_optional() && d.name() == dep.name());
            if always_required && 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.clone();
            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 entries in `reqs.dep` which weren't used 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.
        let remaining = reqs.deps.keys()
            .cloned()
            .filter(|s| !used_features.contains(s))
            .collect::<Vec<_>>();
        if !remaining.is_empty() {
            let features = remaining.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 = Rc::make_mut(
                self.resolve_features
                    .entry(pkgid.clone())
                    .or_insert_with(|| Rc::new(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, Vec<Dependency>> {
        let mut graph: Graph<PackageId, Vec<Dependency>> = 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, ref dep) => {
                    graph.link(a.clone(), b.clone()).push(dep.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))
            }
        }
    }
}
<commit_msg>Auto merge of #5512 - Eh2406:simplify_FeatureValue, r=alexcrichton<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
                );
            }
            Rc::make_mut(prev).push(summary.clone());
            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);

        let reqs = build_requirements(s, method)?;
        let mut ret = Vec::new();
        let mut used_features = HashSet::new();
        let default_dep = (false, 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` and register ourselves as using this
            // name.
            let base = reqs.deps.get(&*dep.name()).unwrap_or(&default_dep);
            used_features.insert(dep.name().as_str());
            let always_required = !dep.is_optional()
                && !s.dependencies()
                    .iter()
                    .any(|d| d.is_optional() && d.name() == dep.name());
            if always_required && 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.clone();
            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 entries in `reqs.dep` which weren't used 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.
        let remaining = reqs.deps.keys()
            .cloned()
            .filter(|s| !used_features.contains(s))
            .collect::<Vec<_>>();
        if !remaining.is_empty() {
            let features = remaining.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 = Rc::make_mut(
                self.resolve_features
                    .entry(pkgid.clone())
                    .or_insert_with(|| Rc::new(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, Vec<Dependency>> {
        let mut graph: Graph<PackageId, Vec<Dependency>> = 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, ref dep) => {
                    graph.link(a.clone(), b.clone()).push(dep.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
) -> CargoResult<Requirements<'a>> {
    let mut reqs = Requirements::new(s);

    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());
            }
        }
        Method::Required {
            all_features: false,
            features: requested,
            ..
        } => {
            for &f in requested.iter() {
                reqs.require_value(&FeatureValue::new(f, s))?;
            }
        }
    }
    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<'f>(&mut self, fv: &'f FeatureValue) -> CargoResult<()> {
        match fv {
            FeatureValue::Feature(feat) => self.require_feature(feat.as_str()),
            FeatureValue::Crate(dep) => Ok(self.require_dependency(dep.as_str())),
            FeatureValue::CrateFeature(dep, dep_feat) => {
                Ok(self.require_crate_feature(dep.as_str(), *dep_feat))
            }
        }
    }
}
<|endoftext|>


<commit_before>use cairo;
use cssparser;
use glib::translate::*;
use glib_sys;
use libc;

use std::ptr;
use std::rc::Rc;

use bbox::RsvgBbox;
use drawing_ctx;
use error::*;
use gradient;
use node::NodeType;
use parsers::{Parse, ParseError};
use pattern;
use util::utf8_cstr;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PaintServerSpread(pub cairo::enums::Extend);

impl Parse for PaintServerSpread {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _: ()) -> Result<PaintServerSpread, AttributeError> {
        match s {
            "pad" => Ok(PaintServerSpread(cairo::enums::Extend::Pad)),
            "reflect" => Ok(PaintServerSpread(cairo::enums::Extend::Reflect)),
            "repeat" => Ok(PaintServerSpread(cairo::enums::Extend::Repeat)),
            _ => Err(AttributeError::Parse(ParseError::new(
                "expected 'pad' | 'reflect' | 'repeat'",
            ))),
        }
    }
}

impl Default for PaintServerSpread {
    fn default() -> PaintServerSpread {
        PaintServerSpread(cairo::enums::Extend::Pad)
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum PaintServer {
    Inherit,
    Iri {
        iri: String,
        alternate: Option<cssparser::Color>,
    },
    SolidColor(cssparser::Color),
}

impl Parse for PaintServer {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _: ()) -> Result<PaintServer, AttributeError> {
        let mut input = cssparser::ParserInput::new(s);
        let mut parser = cssparser::Parser::new(&mut input);

        if parser.try(|i| i.expect_ident_matching("inherit")).is_ok() {
            Ok(PaintServer::Inherit)
        } else if let Ok(url) = parser.try(|i| i.expect_url()) {
            let alternate = if !parser.is_exhausted() {
                if parser.try(|i| i.expect_ident_matching("none")).is_ok() {
                    None
                } else {
                    Some(parser.try(|i| cssparser::Color::parse(i))?)
                }
            } else {
                None
            };

            Ok(PaintServer::Iri {
                iri: String::from(url.as_ref()),
                alternate,
            })
        } else {
            cssparser::Color::parse(&mut parser)
                .map(PaintServer::SolidColor)
                .map_err(AttributeError::from)
        }
    }
}

fn _set_source_rsvg_solid_color(
    ctx: *mut drawing_ctx::RsvgDrawingCtx,
    color: &cssparser::Color,
    opacity: u8,
    current_color: &cssparser::RGBA,
) {
    let rgba = match *color {
        cssparser::Color::RGBA(ref rgba) => rgba,
        cssparser::Color::CurrentColor => current_color,
    };

    drawing_ctx::get_cairo_context(ctx).set_source_rgba(
        f64::from(rgba.red_f32()),
        f64::from(rgba.green_f32()),
        f64::from(rgba.blue_f32()),
        f64::from(rgba.alpha_f32()) * (f64::from(opacity) / 255.0),
    );
}

/// Parses the paint specification, creating a new paint server object.
/// Return value: (nullable): The newly created paint server, or NULL on error.
///
/// # Arguments
///
/// * `str` - The SVG paint specification string to parse.
#[no_mangle]
pub extern "C" fn rsvg_paint_server_parse(
    inherit: *mut glib_sys::gboolean,
    str: *const libc::c_char,
) -> *const PaintServer {
    if !inherit.is_null() {
        unsafe {
            *inherit = true.to_glib();
        }
    }

    let paint_server = PaintServer::parse(unsafe { utf8_cstr(str) }, ());

    if let Ok(PaintServer::Inherit) = paint_server {
        if !inherit.is_null() {
            unsafe {
                *inherit = false.to_glib();
            }
        }
    }

    match paint_server {
        Ok(m) => Rc::into_raw(Rc::new(m)),
        Err(_) => ptr::null_mut(),
    }
}

/// Increase references counter of `PaintServer`.
///
/// # Arguments
///
/// * `paint_server` - must be constructed with `rsvg_paint_server_parse`.
#[no_mangle]
pub extern "C" fn rsvg_paint_server_ref(paint_server: *const PaintServer) {
    if paint_server.is_null() {
        return;
    }

    let server: Rc<PaintServer> = unsafe { Rc::from_raw(paint_server) };

    // forget about references
    Rc::into_raw(server.clone());
    Rc::into_raw(server);
}

/// Decrease references counter of `PaintServer`.
///
/// # Arguments
///
/// * `paint_server` - must be constructed with `rsvg_paint_server_parse`.
#[no_mangle]
pub extern "C" fn rsvg_paint_server_unref(paint_server: *const PaintServer) {
    if paint_server.is_null() {
        return;
    }

    // drop reference
    unsafe { Rc::from_raw(paint_server) };
}

pub fn _set_source_rsvg_paint_server(
    c_ctx: *mut drawing_ctx::RsvgDrawingCtx,
    ps: &PaintServer,
    opacity: u8,
    bbox: &RsvgBbox,
    current_color: &cssparser::RGBA,
) -> bool {
    let mut had_paint_server = false;

    match *ps {
        PaintServer::Iri {
            ref iri,
            ref alternate,
        } => {
            if let Some(acquired) = drawing_ctx::get_acquired_node(c_ctx, iri.as_str()) {
                let node = acquired.get();

                if node.get_type() == NodeType::LinearGradient
                    || node.get_type() == NodeType::RadialGradient
                {
                    had_paint_server = gradient::gradient_resolve_fallbacks_and_set_pattern(
                        &node, c_ctx, opacity, bbox,
                    );
                } else if node.get_type() == NodeType::Pattern {
                    had_paint_server =
                        pattern::pattern_resolve_fallbacks_and_set_pattern(&node, c_ctx, bbox);
                }
            }

            if !had_paint_server && alternate.is_some() {
                _set_source_rsvg_solid_color(
                    c_ctx,
                    alternate.as_ref().unwrap(),
                    opacity,
                    current_color,
                );
                had_paint_server = true;
            }
        }

        PaintServer::SolidColor(color) => {
            _set_source_rsvg_solid_color(c_ctx, &color, opacity, current_color);
            had_paint_server = true;
        }

        _ => {}
    };

    had_paint_server
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_spread_method() {
        assert_eq!(
            PaintServerSpread::parse("pad", ()),
            Ok(PaintServerSpread(cairo::enums::Extend::Pad))
        );

        assert_eq!(
            PaintServerSpread::parse("reflect", ()),
            Ok(PaintServerSpread(cairo::enums::Extend::Reflect))
        );

        assert_eq!(
            PaintServerSpread::parse("repeat", ()),
            Ok(PaintServerSpread(cairo::enums::Extend::Repeat))
        );

        assert!(PaintServerSpread::parse("foobar", ()).is_err());
    }

    #[test]
    fn catches_invalid_syntax() {
        assert!(PaintServer::parse("", ()).is_err());
        assert!(PaintServer::parse("42", ()).is_err());
        assert!(PaintServer::parse("invalid", ()).is_err());
    }

    #[test]
    fn parses_inherit() {
        assert_eq!(PaintServer::parse("inherit", ()), Ok(PaintServer::Inherit));
    }

    #[test]
    fn parses_solid_color() {
        assert_eq!(
            PaintServer::parse("rgb(255, 128, 64, 0.5)", ()),
            Ok(PaintServer::SolidColor(cssparser::Color::RGBA(
                cssparser::RGBA::new(255, 128, 64, 128)
            )))
        );

        assert_eq!(
            PaintServer::parse("currentColor", ()),
            Ok(PaintServer::SolidColor(cssparser::Color::CurrentColor))
        );
    }

    #[test]
    fn parses_iri() {
        assert_eq!(
            PaintServer::parse("url(#link)", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) none", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) #ff8040", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 255
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) rgb(255, 128, 64, 0.5)", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 128
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) currentColor", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: Some(cssparser::Color::CurrentColor),
            },)
        );

        assert!(PaintServer::parse("url(#link) invalid", ()).is_err());
    }

    #[test]
    fn paint_server_refs_and_unrefs() {
        let rc = Rc::new(PaintServer::parse("#ffffff", ()).unwrap());
        let weak = Rc::downgrade(&rc);
        let ps = Rc::into_raw(rc);

        rsvg_paint_server_ref(ps);
        assert!(weak.upgrade().is_some());

        rsvg_paint_server_unref(ps);
        assert!(weak.upgrade().is_some());

        rsvg_paint_server_unref(ps);
        assert!(weak.upgrade().is_none());
    }
}
<commit_msg>paint_server.rs: Parse "none" for no paint; don't set the paint server on the draw_ctx in that case<commit_after>use cairo;
use cssparser;
use glib::translate::*;
use glib_sys;
use libc;

use std::ptr;
use std::rc::Rc;

use bbox::RsvgBbox;
use drawing_ctx;
use error::*;
use gradient;
use node::NodeType;
use parsers::{Parse, ParseError};
use pattern;
use util::utf8_cstr;

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PaintServerSpread(pub cairo::enums::Extend);

impl Parse for PaintServerSpread {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _: ()) -> Result<PaintServerSpread, AttributeError> {
        match s {
            "pad" => Ok(PaintServerSpread(cairo::enums::Extend::Pad)),
            "reflect" => Ok(PaintServerSpread(cairo::enums::Extend::Reflect)),
            "repeat" => Ok(PaintServerSpread(cairo::enums::Extend::Repeat)),
            _ => Err(AttributeError::Parse(ParseError::new(
                "expected 'pad' | 'reflect' | 'repeat'",
            ))),
        }
    }
}

impl Default for PaintServerSpread {
    fn default() -> PaintServerSpread {
        PaintServerSpread(cairo::enums::Extend::Pad)
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum PaintServer {
    Inherit,
    None,
    Iri {
        iri: String,
        alternate: Option<cssparser::Color>,
    },
    SolidColor(cssparser::Color),
}

impl Parse for PaintServer {
    type Data = ();
    type Err = AttributeError;

    fn parse(s: &str, _: ()) -> Result<PaintServer, AttributeError> {
        let mut input = cssparser::ParserInput::new(s);
        let mut parser = cssparser::Parser::new(&mut input);

        if parser.try(|i| i.expect_ident_matching("inherit")).is_ok() {
            Ok(PaintServer::Inherit)
        } else if parser.try(|i| i.expect_ident_matching("none")).is_ok() {
            Ok(PaintServer::None)
        } else if let Ok(url) = parser.try(|i| i.expect_url()) {
            let alternate = if !parser.is_exhausted() {
                if parser.try(|i| i.expect_ident_matching("none")).is_ok() {
                    None
                } else {
                    Some(parser.try(|i| cssparser::Color::parse(i))?)
                }
            } else {
                None
            };

            Ok(PaintServer::Iri {
                iri: String::from(url.as_ref()),
                alternate,
            })
        } else {
            cssparser::Color::parse(&mut parser)
                .map(PaintServer::SolidColor)
                .map_err(AttributeError::from)
        }
    }
}

fn _set_source_rsvg_solid_color(
    ctx: *mut drawing_ctx::RsvgDrawingCtx,
    color: &cssparser::Color,
    opacity: u8,
    current_color: &cssparser::RGBA,
) {
    let rgba = match *color {
        cssparser::Color::RGBA(ref rgba) => rgba,
        cssparser::Color::CurrentColor => current_color,
    };

    drawing_ctx::get_cairo_context(ctx).set_source_rgba(
        f64::from(rgba.red_f32()),
        f64::from(rgba.green_f32()),
        f64::from(rgba.blue_f32()),
        f64::from(rgba.alpha_f32()) * (f64::from(opacity) / 255.0),
    );
}

/// Parses the paint specification, creating a new paint server object.
/// Return value: (nullable): The newly created paint server, or NULL on error.
///
/// # Arguments
///
/// * `str` - The SVG paint specification string to parse.
#[no_mangle]
pub extern "C" fn rsvg_paint_server_parse(
    inherit: *mut glib_sys::gboolean,
    str: *const libc::c_char,
) -> *const PaintServer {
    if !inherit.is_null() {
        unsafe {
            *inherit = true.to_glib();
        }
    }

    let paint_server = PaintServer::parse(unsafe { utf8_cstr(str) }, ());

    if let Ok(PaintServer::Inherit) = paint_server {
        if !inherit.is_null() {
            unsafe {
                *inherit = false.to_glib();
            }
        }
    }

    match paint_server {
        Ok(m) => Rc::into_raw(Rc::new(m)),
        Err(_) => ptr::null_mut(),
    }
}

/// Increase references counter of `PaintServer`.
///
/// # Arguments
///
/// * `paint_server` - must be constructed with `rsvg_paint_server_parse`.
#[no_mangle]
pub extern "C" fn rsvg_paint_server_ref(paint_server: *const PaintServer) {
    if paint_server.is_null() {
        return;
    }

    let server: Rc<PaintServer> = unsafe { Rc::from_raw(paint_server) };

    // forget about references
    Rc::into_raw(server.clone());
    Rc::into_raw(server);
}

/// Decrease references counter of `PaintServer`.
///
/// # Arguments
///
/// * `paint_server` - must be constructed with `rsvg_paint_server_parse`.
#[no_mangle]
pub extern "C" fn rsvg_paint_server_unref(paint_server: *const PaintServer) {
    if paint_server.is_null() {
        return;
    }

    // drop reference
    unsafe { Rc::from_raw(paint_server) };
}

pub fn _set_source_rsvg_paint_server(
    c_ctx: *mut drawing_ctx::RsvgDrawingCtx,
    ps: &PaintServer,
    opacity: u8,
    bbox: &RsvgBbox,
    current_color: &cssparser::RGBA,
) -> bool {
    let mut had_paint_server;

    match *ps {
        PaintServer::Iri {
            ref iri,
            ref alternate,
        } => {
            had_paint_server = false;

            if let Some(acquired) = drawing_ctx::get_acquired_node(c_ctx, iri.as_str()) {
                let node = acquired.get();

                if node.get_type() == NodeType::LinearGradient
                    || node.get_type() == NodeType::RadialGradient
                {
                    had_paint_server = gradient::gradient_resolve_fallbacks_and_set_pattern(
                        &node, c_ctx, opacity, bbox,
                    );
                } else if node.get_type() == NodeType::Pattern {
                    had_paint_server =
                        pattern::pattern_resolve_fallbacks_and_set_pattern(&node, c_ctx, bbox);
                }
            }

            if !had_paint_server && alternate.is_some() {
                _set_source_rsvg_solid_color(
                    c_ctx,
                    alternate.as_ref().unwrap(),
                    opacity,
                    current_color,
                );
                had_paint_server = true;
            }
        }

        PaintServer::SolidColor(color) => {
            _set_source_rsvg_solid_color(c_ctx, &color, opacity, current_color);
            had_paint_server = true;
        }

        PaintServer::None => {
            had_paint_server = false;
        }

        PaintServer::Inherit => {
            unreachable!();
        }
    };

    had_paint_server
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn parses_spread_method() {
        assert_eq!(
            PaintServerSpread::parse("pad", ()),
            Ok(PaintServerSpread(cairo::enums::Extend::Pad))
        );

        assert_eq!(
            PaintServerSpread::parse("reflect", ()),
            Ok(PaintServerSpread(cairo::enums::Extend::Reflect))
        );

        assert_eq!(
            PaintServerSpread::parse("repeat", ()),
            Ok(PaintServerSpread(cairo::enums::Extend::Repeat))
        );

        assert!(PaintServerSpread::parse("foobar", ()).is_err());
    }

    #[test]
    fn catches_invalid_syntax() {
        assert!(PaintServer::parse("", ()).is_err());
        assert!(PaintServer::parse("42", ()).is_err());
        assert!(PaintServer::parse("invalid", ()).is_err());
    }

    #[test]
    fn parses_inherit() {
        assert_eq!(PaintServer::parse("inherit", ()), Ok(PaintServer::Inherit));
    }

    #[test]
    fn parses_none() {
        assert_eq!(PaintServer::parse("none", ()), Ok(PaintServer::None));
    }

    #[test]
    fn parses_solid_color() {
        assert_eq!(
            PaintServer::parse("rgb(255, 128, 64, 0.5)", ()),
            Ok(PaintServer::SolidColor(cssparser::Color::RGBA(
                cssparser::RGBA::new(255, 128, 64, 128)
            )))
        );

        assert_eq!(
            PaintServer::parse("currentColor", ()),
            Ok(PaintServer::SolidColor(cssparser::Color::CurrentColor))
        );
    }

    #[test]
    fn parses_iri() {
        assert_eq!(
            PaintServer::parse("url(#link)", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) none", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) #ff8040", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 255
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) rgb(255, 128, 64, 0.5)", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 128
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse("url(#link) currentColor", ()),
            Ok(PaintServer::Iri {
                iri: "#link".to_string(),
                alternate: Some(cssparser::Color::CurrentColor),
            },)
        );

        assert!(PaintServer::parse("url(#link) invalid", ()).is_err());
    }

    #[test]
    fn paint_server_refs_and_unrefs() {
        let rc = Rc::new(PaintServer::parse("#ffffff", ()).unwrap());
        let weak = Rc::downgrade(&rc);
        let ps = Rc::into_raw(rc);

        rsvg_paint_server_ref(ps);
        assert!(weak.upgrade().is_some());

        rsvg_paint_server_unref(ps);
        assert!(weak.upgrade().is_some());

        rsvg_paint_server_unref(ps);
        assert!(weak.upgrade().is_none());
    }
}
<|endoftext|>


<commit_before>//! SVG paint servers.

use cssparser::Parser;

use crate::allowed_url::Fragment;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::Parse;
use crate::properties::ComputedValues;
use crate::unit_interval::UnitInterval;

#[derive(Debug, Clone, PartialEq)]
pub enum PaintServer {
    None,
    Iri {
        iri: Fragment,
        alternate: Option<cssparser::Color>,
    },
    SolidColor(cssparser::Color),
}

impl Parse for PaintServer {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<PaintServer, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(PaintServer::None)
        } else if let Ok(url) = parser.try_parse(|i| i.expect_url()) {
            let loc = parser.current_source_location();

            let alternate = if !parser.is_exhausted() {
                if parser
                    .try_parse(|i| i.expect_ident_matching("none"))
                    .is_ok()
                {
                    None
                } else {
                    Some(parser.try_parse(|i| cssparser::Color::parse(i))?)
                }
            } else {
                None
            };

            Ok(PaintServer::Iri {
                iri: Fragment::parse(&url)
                    .map_err(|e: HrefError| -> ValueErrorKind { e.into() })
                    .map_err(|e| loc.new_custom_error(e))?,
                alternate,
            })
        } else {
            Ok(cssparser::Color::parse(parser).map(PaintServer::SolidColor)?)
        }
    }
}

pub trait PaintSource {
    type Resolved: AsPaintSource;

    fn resolve(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes,
    ) -> Result<Self::Resolved, AcquireError>;

    fn resolve_fallbacks_and_set_pattern(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes,
        draw_ctx: &mut DrawingCtx,
        opacity: UnitInterval,
        bbox: &BoundingBox,
    ) -> Result<bool, RenderingError> {
        match self.resolve(&node, acquired_nodes) {
            Ok(resolved) => {
                let cascaded = CascadedValues::new_from_node(node);
                let values = cascaded.get();
                resolved.set_as_paint_source(acquired_nodes, values, draw_ctx, opacity, bbox)
            }

            Err(AcquireError::CircularReference(node)) => {
                rsvg_log!("circular reference in paint server {}", node);
                Err(RenderingError::CircularReference)
            }

            Err(AcquireError::MaxReferencesExceeded) => {
                rsvg_log!("maximum number of references exceeded");
                Err(RenderingError::InstancingLimit)
            }

            Err(e) => {
                rsvg_log!("not using paint server {}: {}", node, e);

                // "could not resolve" means caller needs to fall back to color
                Ok(false)
            }
        }
    }
}

pub trait AsPaintSource {
    fn set_as_paint_source(
        self,
        acquired_nodes: &mut AcquiredNodes,
        values: &ComputedValues,
        draw_ctx: &mut DrawingCtx,
        opacity: UnitInterval,
        bbox: &BoundingBox,
    ) -> Result<bool, RenderingError>;
}

// Any of the attributes in gradient and pattern elements may be omitted.
// The missing ones are resolved from the "fallback" IRI. If still missing,
// they are resolved to the default value
pub trait Resolve {
    fn is_resolved(&self) -> bool;

    fn resolve_from_fallback(&self, fallback: &Self) -> Self;

    fn resolve_from_defaults(&self) -> Self;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn catches_invalid_syntax() {
        assert!(PaintServer::parse_str("").is_err());
        assert!(PaintServer::parse_str("42").is_err());
        assert!(PaintServer::parse_str("invalid").is_err());
    }

    #[test]
    fn parses_none() {
        assert_eq!(PaintServer::parse_str("none"), Ok(PaintServer::None));
    }

    #[test]
    fn parses_solid_color() {
        assert_eq!(
            PaintServer::parse_str("rgb(255, 128, 64, 0.5)"),
            Ok(PaintServer::SolidColor(cssparser::Color::RGBA(
                cssparser::RGBA::new(255, 128, 64, 128)
            )))
        );

        assert_eq!(
            PaintServer::parse_str("currentColor"),
            Ok(PaintServer::SolidColor(cssparser::Color::CurrentColor))
        );
    }

    #[test]
    fn parses_iri() {
        assert_eq!(
            PaintServer::parse_str("url(#link)"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(foo#link) none"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(Some("foo".to_string()), "link".to_string()),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) #ff8040"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 255
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 128
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) currentColor"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: Some(cssparser::Color::CurrentColor),
            },)
        );

        assert!(PaintServer::parse_str("url(#link) invalid").is_err());
    }
}
<commit_msg>paint_server: remove leftover trait<commit_after>//! SVG paint servers.

use cssparser::Parser;

use crate::allowed_url::Fragment;
use crate::bbox::BoundingBox;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::error::*;
use crate::node::{CascadedValues, Node};
use crate::parsers::Parse;
use crate::properties::ComputedValues;
use crate::unit_interval::UnitInterval;

#[derive(Debug, Clone, PartialEq)]
pub enum PaintServer {
    None,
    Iri {
        iri: Fragment,
        alternate: Option<cssparser::Color>,
    },
    SolidColor(cssparser::Color),
}

impl Parse for PaintServer {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<PaintServer, ParseError<'i>> {
        if parser
            .try_parse(|i| i.expect_ident_matching("none"))
            .is_ok()
        {
            Ok(PaintServer::None)
        } else if let Ok(url) = parser.try_parse(|i| i.expect_url()) {
            let loc = parser.current_source_location();

            let alternate = if !parser.is_exhausted() {
                if parser
                    .try_parse(|i| i.expect_ident_matching("none"))
                    .is_ok()
                {
                    None
                } else {
                    Some(parser.try_parse(|i| cssparser::Color::parse(i))?)
                }
            } else {
                None
            };

            Ok(PaintServer::Iri {
                iri: Fragment::parse(&url)
                    .map_err(|e: HrefError| -> ValueErrorKind { e.into() })
                    .map_err(|e| loc.new_custom_error(e))?,
                alternate,
            })
        } else {
            Ok(cssparser::Color::parse(parser).map(PaintServer::SolidColor)?)
        }
    }
}

pub trait PaintSource {
    type Resolved: AsPaintSource;

    fn resolve(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes,
    ) -> Result<Self::Resolved, AcquireError>;

    fn resolve_fallbacks_and_set_pattern(
        &self,
        node: &Node,
        acquired_nodes: &mut AcquiredNodes,
        draw_ctx: &mut DrawingCtx,
        opacity: UnitInterval,
        bbox: &BoundingBox,
    ) -> Result<bool, RenderingError> {
        match self.resolve(&node, acquired_nodes) {
            Ok(resolved) => {
                let cascaded = CascadedValues::new_from_node(node);
                let values = cascaded.get();
                resolved.set_as_paint_source(acquired_nodes, values, draw_ctx, opacity, bbox)
            }

            Err(AcquireError::CircularReference(node)) => {
                rsvg_log!("circular reference in paint server {}", node);
                Err(RenderingError::CircularReference)
            }

            Err(AcquireError::MaxReferencesExceeded) => {
                rsvg_log!("maximum number of references exceeded");
                Err(RenderingError::InstancingLimit)
            }

            Err(e) => {
                rsvg_log!("not using paint server {}: {}", node, e);

                // "could not resolve" means caller needs to fall back to color
                Ok(false)
            }
        }
    }
}

pub trait AsPaintSource {
    fn set_as_paint_source(
        self,
        acquired_nodes: &mut AcquiredNodes,
        values: &ComputedValues,
        draw_ctx: &mut DrawingCtx,
        opacity: UnitInterval,
        bbox: &BoundingBox,
    ) -> Result<bool, RenderingError>;
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn catches_invalid_syntax() {
        assert!(PaintServer::parse_str("").is_err());
        assert!(PaintServer::parse_str("42").is_err());
        assert!(PaintServer::parse_str("invalid").is_err());
    }

    #[test]
    fn parses_none() {
        assert_eq!(PaintServer::parse_str("none"), Ok(PaintServer::None));
    }

    #[test]
    fn parses_solid_color() {
        assert_eq!(
            PaintServer::parse_str("rgb(255, 128, 64, 0.5)"),
            Ok(PaintServer::SolidColor(cssparser::Color::RGBA(
                cssparser::RGBA::new(255, 128, 64, 128)
            )))
        );

        assert_eq!(
            PaintServer::parse_str("currentColor"),
            Ok(PaintServer::SolidColor(cssparser::Color::CurrentColor))
        );
    }

    #[test]
    fn parses_iri() {
        assert_eq!(
            PaintServer::parse_str("url(#link)"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(foo#link) none"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(Some("foo".to_string()), "link".to_string()),
                alternate: None,
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) #ff8040"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 255
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) rgb(255, 128, 64, 0.5)"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: Some(cssparser::Color::RGBA(cssparser::RGBA::new(
                    255, 128, 64, 128
                ))),
            },)
        );

        assert_eq!(
            PaintServer::parse_str("url(#link) currentColor"),
            Ok(PaintServer::Iri {
                iri: Fragment::new(None, "link".to_string()),
                alternate: Some(cssparser::Color::CurrentColor),
            },)
        );

        assert!(PaintServer::parse_str("url(#link) invalid").is_err());
    }
}
<|endoftext|>


<commit_before>//! The vector module.
//!
//! Currently contains all code
//! relating to the vector linear algebra struct.

use std::ops::{Mul, Add, Div, Sub, Index};
use libnum::{One, Zero, Float, FromPrimitive};
use std::cmp::PartialEq;
use linalg::Metric;
use linalg::utils;

/// The Vector struct.
///
/// Can be instantiated with any type.
pub struct Vector<T> {
	pub size: usize,
	pub data: Vec<T>
}

impl<T: Zero + One + Copy> Vector<T> {

    /// Constructor for Vector struct.
    ///
    /// Requires the vector data.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// ```
    pub fn new(data: Vec<T>) -> Vector<T> {

    	let size = data.len();

        Vector {
            size: size,
            data: data
        }
    }

    /// Constructs Vector of all zeros.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::zeros(10);
    /// ```
    pub fn zeros(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::zero(); size]
        }
    }

    /// Constructs Vector of all ones.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::ones(10);
    /// ```
    pub fn ones(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::one(); size]
        }
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T> + Add<T, Output=T>> Vector<T> {

    /// Compute dot product with specified Vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// let b = Vector::new(vec![2.0; 4]);
    ///
    /// let c = a.dot(&b);
    /// assert_eq!(c, 20.0);
    /// ```
	pub fn dot(&self, v: &Vector<T>) -> T {
    	utils::dot(&self.data, &v.data)
    }
}

impl<T: Copy + Zero + Add<T, Output=T>> Vector<T> {

    /// The sum of the vector.
    ///
    /// Returns the sum of all elements in the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.sum();
    /// assert_eq!(c, 10.0);
    /// ```
    pub fn sum(&self) -> T {
        self.data.iter().fold(T::zero(), |sum, &val| sum + val)
    }
}

impl<T: Copy + Zero + Float + FromPrimitive> Vector<T> {

    /// The mean of the vector.
    ///
    /// Returns the arithmetic mean of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.mean();
    /// assert_eq!(c, 2.5);
    /// ```
    pub fn mean(&self) -> T {
        let sum = self.sum();
        sum / FromPrimitive::from_usize(self.data.len()).unwrap()
    }

    /// The variance of the vector.
    ///
    /// Returns the unbiased sample variance of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.variance();
    /// assert_eq!(c, 5.0/3.0);
    /// ```
    pub fn variance(&self) -> T {
        let m = self.mean();
        let mut var = T::zero();

        for u in &self.data {
            var = var + (*u-m)*(*u-m);
        }

        var / FromPrimitive::from_usize(self.data.len() - 1).unwrap()
    }
}

/// Multiplies vector by scalar.
impl<T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

/// Multiplies vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        let new_data = self.data.iter().map(|v| (*v) * (*f)).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Divides vector by scalar.
impl<T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        (&self) / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        self / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
        (&self) / f
    }
}

/// Divides vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
    	assert!(*f != T::zero());
        let new_data = self.data.iter().map(|v| *v / *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds scalar to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        (&self) + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        self + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: &T) -> Vector<T> {
        (&self) + f
    }
}

/// Adds scalar to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v + *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds vector to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        (&self) + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        self + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: &Vector<T>) -> Vector<T> {
        (&self) + v
    }
}

/// Adds vector to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sum(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Subtracts scalar from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        (&self) - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        self - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: &T) -> Vector<T> {
            (&self) - f
        }
    }

/// Subtracts scalar from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v - *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Subtracts vector from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        (&self) - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        self - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: &Vector<T>) -> Vector<T> {
        (&self) - v
    }
}

/// Subtracts vector from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sub(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Indexes vector.
impl<T> Index<usize> for Vector<T> {
	type Output = T;

	fn index(&self, idx : usize) -> &T {
		assert!(idx < self.size);
        unsafe {
            &self.data.get_unchecked(idx)
        }
	}
}

impl<T: Float> Metric<T> for Vector<T> {

    /// Compute euclidean norm for vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    /// use rusty_machine::linalg::Metric;
    ///
    /// let a = Vector::new(vec![3.0,4.0]);
    /// let c = a.norm();
    ///
    /// assert_eq!(c, 5.0);
    /// ```
    fn norm(&self) -> T {
        let mut s = T::zero();

        for u in &self.data {
            s = s + (*u) * (*u);
        }

        s.sqrt()
    }
}<commit_msg>Implemented elementwise operations.<commit_after>//! The vector module.
//!
//! Currently contains all code
//! relating to the vector linear algebra struct.

use std::ops::{Mul, Add, Div, Sub, Index};
use libnum::{One, Zero, Float, FromPrimitive};
use std::cmp::PartialEq;
use linalg::Metric;
use linalg::utils;

/// The Vector struct.
///
/// Can be instantiated with any type.
pub struct Vector<T> {
	pub size: usize,
	pub data: Vec<T>
}

impl<T> Vector<T> {
    /// Constructor for Vector struct.
    ///
    /// Requires the vector data.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// ```
    pub fn new(data: Vec<T>) -> Vector<T> {

        let size = data.len();

        Vector {
            size: size,
            data: data
        }
    }
}

impl<T: Zero + One + Copy> Vector<T> {

    /// Constructs Vector of all zeros.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::zeros(10);
    /// ```
    pub fn zeros(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::zero(); size]
        }
    }

    /// Constructs Vector of all ones.
    ///
    /// Requires the size of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let vec = Vector::<f64>::ones(10);
    /// ```
    pub fn ones(size: usize) -> Vector<T> {
    	Vector {
            size: size,
            data: vec![T::one(); size]
        }
    }
}

impl<T: Copy + One + Zero + Mul<T, Output=T> + Add<T, Output=T>> Vector<T> {

    /// Compute dot product with specified Vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// let b = Vector::new(vec![2.0; 4]);
    ///
    /// let c = a.dot(&b);
    /// assert_eq!(c, 20.0);
    /// ```
	pub fn dot(&self, v: &Vector<T>) -> T {
    	utils::dot(&self.data, &v.data)
    }
}

impl<T: Copy + Zero + Add<T, Output=T>> Vector<T> {

    /// The sum of the vector.
    ///
    /// Returns the sum of all elements in the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.sum();
    /// assert_eq!(c, 10.0);
    /// ```
    pub fn sum(&self) -> T {
        self.data.iter().fold(T::zero(), |sum, &val| sum + val)
    }
}

impl<T: Copy + Zero + Mul<T, Output=T>> Vector<T> {

    /// The elementwise product of two vectors.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// let b = Vector::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = &a.elemul(&b);
    /// assert_eq!(c.data, vec![1.0, 4.0, 9.0, 16.0]);
    /// ```
    pub fn elemul(&self, v: &Vector<T>) -> Vector<T> {
        assert_eq!(self.size, v.size);
        Vector::new(utils::ele_mul(&self.data, &v.data))
    }
}

impl<T: Copy + Zero + Div<T, Output=T>> Vector<T> {

    /// The elementwise division of two vectors.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::new(vec![1.0,2.0,3.0,4.0]);
    /// let b = Vector::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = &a.elediv(&b);
    /// assert_eq!(c.data, vec![1.0; 4]);
    /// ```
    pub fn elediv(&self, v: &Vector<T>) -> Vector<T> {
        assert_eq!(self.size, v.size);
        Vector::new(utils::ele_div(&self.data, &v.data))
    }
}

impl<T: Copy + Zero + Float + FromPrimitive> Vector<T> {

    /// The mean of the vector.
    ///
    /// Returns the arithmetic mean of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.mean();
    /// assert_eq!(c, 2.5);
    /// ```
    pub fn mean(&self) -> T {
        let sum = self.sum();
        sum / FromPrimitive::from_usize(self.data.len()).unwrap()
    }

    /// The variance of the vector.
    ///
    /// Returns the unbiased sample variance of the vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    ///
    /// let a = Vector::<f32>::new(vec![1.0,2.0,3.0,4.0]);
    ///
    /// let c = a.variance();
    /// assert_eq!(c, 5.0/3.0);
    /// ```
    pub fn variance(&self) -> T {
        let m = self.mean();
        let mut var = T::zero();

        for u in &self.data {
            var = var + (*u-m)*(*u-m);
        }

        var / FromPrimitive::from_usize(self.data.len() - 1).unwrap()
    }
}

/// Multiplies vector by scalar.
impl<T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        (&self) * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: T) -> Vector<T> {
        self * (&f)
    }
}

/// Multiplies vector by scalar.
impl<'a, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        (&self) * f
    }
}

/// Multiplies vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + Mul<T, Output=T>> Mul<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn mul(self, f: &T) -> Vector<T> {
        let new_data = self.data.iter().map(|v| (*v) * (*f)).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Divides vector by scalar.
impl<T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        (&self) / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: T) -> Vector<T> {
        self / (&f)
    }
}

/// Divides vector by scalar.
impl<'a, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
        (&self) / f
    }
}

/// Divides vector by scalar.
impl<'a, 'b, T: Copy + One + Zero + PartialEq + Div<T, Output=T>> Div<&'b T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn div(self, f: &T) -> Vector<T> {
    	assert!(*f != T::zero());
        let new_data = self.data.iter().map(|v| *v / *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds scalar to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        (&self) + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: T) -> Vector<T> {
        self + (&f)
    }
}

/// Adds scalar to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, f: &T) -> Vector<T> {
        (&self) + f
    }
}

/// Adds scalar to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v + *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Adds vector to vector.
impl<T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        (&self) + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: Vector<T>) -> Vector<T> {
        self + (&v)
    }
}

/// Adds vector to vector.
impl<'a, T: Copy + One + Zero + Add<T, Output=T>> Add<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn add(self, v: &Vector<T>) -> Vector<T> {
        (&self) + v
    }
}

/// Adds vector to vector.
impl<'a, 'b, T: Copy + One + Zero + Add<T, Output=T>> Add<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn add(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sum(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Subtracts scalar from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        (&self) - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<T> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: T) -> Vector<T> {
        self - (&f)
    }
}

/// Subtracts scalar from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a T> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, f: &T) -> Vector<T> {
            (&self) - f
        }
    }

/// Subtracts scalar from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b T> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, f: &T) -> Vector<T> {
		let new_data = self.data.iter().map(|v| *v - *f).collect();

        Vector {
            size: self.size,
            data: new_data
        }
    }
}

/// Subtracts vector from vector.
impl<T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        (&self) - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<Vector<T>> for &'a Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: Vector<T>) -> Vector<T> {
        self - (&v)
    }
}

/// Subtracts vector from vector.
impl<'a, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'a Vector<T>> for Vector<T> {
    type Output = Vector<T>;

    fn sub(self, v: &Vector<T>) -> Vector<T> {
        (&self) - v
    }
}

/// Subtracts vector from vector.
impl<'a, 'b, T: Copy + One + Zero + Sub<T, Output=T>> Sub<&'b Vector<T>> for &'a Vector<T> {
	type Output = Vector<T>;

	fn sub(self, v: &Vector<T>) -> Vector<T> {
		assert!(self.size == v.size);

		let new_data = utils::vec_sub(&self.data, &v.data);

        Vector {
            size: self.size,
            data: new_data
        }
	}
}

/// Indexes vector.
impl<T> Index<usize> for Vector<T> {
	type Output = T;

	fn index(&self, idx : usize) -> &T {
		assert!(idx < self.size);
        unsafe {
            &self.data.get_unchecked(idx)
        }
	}
}

impl<T: Float> Metric<T> for Vector<T> {

    /// Compute euclidean norm for vector.
    ///
    /// # Examples
    ///
    /// ```
    /// use rusty_machine::linalg::vector::Vector;
    /// use rusty_machine::linalg::Metric;
    ///
    /// let a = Vector::new(vec![3.0,4.0]);
    /// let c = a.norm();
    ///
    /// assert_eq!(c, 5.0);
    /// ```
    fn norm(&self) -> T {
        let mut s = T::zero();

        for u in &self.data {
            s = s + (*u) * (*u);
        }

        s.sqrt()
    }
}<|endoftext|>


<commit_before>use clap::{Arg, App, ArgGroup, SubCommand};

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app
        .arg(Arg::with_name("id")
            .long("id")
            .short("i")
            .takes_value(true)
            .required(true)
            .help("View this entry at this store path")
            .value_name("ID"))

        .arg(Arg::with_name("version")
            .long("version")
            .short("V")
            .takes_value(true)
            .required(true)
            .help("View this version (youngest if not specified)")
            .value_name("VERSION"))

        .arg(Arg::with_name("versions")
            .long("versions")
            .takes_value(false)
            .required(false)
            .help("Only print available versions for this file"))

        .arg(Arg::with_name("view-header")
            .long("header")
            .short("h")
            .takes_value(false)
            .required(false)
            .help("View header"))
        .arg(Arg::with_name("view-content")
            .long("content")
            .short("C")
            .takes_value(false)
            .required(false)
            .help("View content"))

        .subcommand(SubCommand::with_name("view-in")
                   .about("View the entry in ...")
                   .version("0.1")

                   .arg(Arg::with_name("view-in-stdout")
                        .long("stdout")
                        .short("s")
                        .takes_value(false)
                        .required(false)
                        .help("View by printing to stdout"))

                   .arg(Arg::with_name("view-in-ui")
                        .long("ui")
                        .short("u")
                        .takes_value(false)
                        .required(false)
                        .help("View by opening own curses-like UI (default)"))

                   .arg(Arg::with_name("view-in-browser")
                        .long("browser")
                        .short("b")
                        .takes_value(true) // optional, which browser
                        .required(false)
                        .help("View content in $BROWSER (fails if no env variable $BROWSER)")
                        .value_name("BROWSER"))

                   .arg(Arg::with_name("view-in-texteditor")
                        .long("editor")
                        .short("e")
                        .takes_value(true) // optional, which editor
                        .required(false)
                        .help("View content in $EDITOR")
                        .value_name("EDITOR"))

                   .arg(Arg::with_name("view-in-custom")
                        .long("custom")
                        .short("c")
                        .takes_value(true) // non-optional, call-string
                        .required(false)
                        .help("View content in custom program, for example 'libreoffice %e', replace '%e' with entry path")
                        .value_name("PROGRAM"))

                   .group(ArgGroup::with_name("viewer")
                          .args(&["view-in-stdout",
                                  "view-in-ui",
                                  "view-in-browser",
                                  "view-in-texteditor",
                                  "view-in-custom",
                          ])
                          .required(false))
                   )

        .subcommand(SubCommand::with_name("compile")
                   .about("Compile content to other format for viewing, implies that the entry gets copied to /tmp")
                   .version("0.1")
                   .arg(Arg::with_name("from")
                        .long("from")
                        .short("f")
                        .takes_value(true) // "markdown" or "textile" or "restructuredtex"
                        .required(true)
                        .help("Compile from")
                        .value_name("FORMAT"))

                   .arg(Arg::with_name("to")
                        .long("to")
                        .short("t")
                        .takes_value(true) // "html" or "HTML" or ... json maybe?
                        .required(true)
                        .help("Compile to")
                        .value_name("FORMAT"))
                   )
}
<commit_msg>Remove seperate version passing<commit_after>use clap::{Arg, App, ArgGroup, SubCommand};

pub fn build_ui<'a>(app: App<'a, 'a>) -> App<'a, 'a> {
    app
        .arg(Arg::with_name("id")
            .long("id")
            .short("i")
            .takes_value(true)
            .required(true)
            .help("View this entry at this store path")
            .value_name("ID"))

        .arg(Arg::with_name("versions")
            .long("versions")
            .takes_value(false)
            .required(false)
            .help("Only print available versions for this file"))

        .arg(Arg::with_name("view-header")
            .long("header")
            .short("h")
            .takes_value(false)
            .required(false)
            .help("View header"))
        .arg(Arg::with_name("view-content")
            .long("content")
            .short("C")
            .takes_value(false)
            .required(false)
            .help("View content"))

        .subcommand(SubCommand::with_name("view-in")
                   .about("View the entry in ...")
                   .version("0.1")

                   .arg(Arg::with_name("view-in-stdout")
                        .long("stdout")
                        .short("s")
                        .takes_value(false)
                        .required(false)
                        .help("View by printing to stdout"))

                   .arg(Arg::with_name("view-in-ui")
                        .long("ui")
                        .short("u")
                        .takes_value(false)
                        .required(false)
                        .help("View by opening own curses-like UI (default)"))

                   .arg(Arg::with_name("view-in-browser")
                        .long("browser")
                        .short("b")
                        .takes_value(true) // optional, which browser
                        .required(false)
                        .help("View content in $BROWSER (fails if no env variable $BROWSER)")
                        .value_name("BROWSER"))

                   .arg(Arg::with_name("view-in-texteditor")
                        .long("editor")
                        .short("e")
                        .takes_value(true) // optional, which editor
                        .required(false)
                        .help("View content in $EDITOR")
                        .value_name("EDITOR"))

                   .arg(Arg::with_name("view-in-custom")
                        .long("custom")
                        .short("c")
                        .takes_value(true) // non-optional, call-string
                        .required(false)
                        .help("View content in custom program, for example 'libreoffice %e', replace '%e' with entry path")
                        .value_name("PROGRAM"))

                   .group(ArgGroup::with_name("viewer")
                          .args(&["view-in-stdout",
                                  "view-in-ui",
                                  "view-in-browser",
                                  "view-in-texteditor",
                                  "view-in-custom",
                          ])
                          .required(false))
                   )

        .subcommand(SubCommand::with_name("compile")
                   .about("Compile content to other format for viewing, implies that the entry gets copied to /tmp")
                   .version("0.1")
                   .arg(Arg::with_name("from")
                        .long("from")
                        .short("f")
                        .takes_value(true) // "markdown" or "textile" or "restructuredtex"
                        .required(true)
                        .help("Compile from")
                        .value_name("FORMAT"))

                   .arg(Arg::with_name("to")
                        .long("to")
                        .short("t")
                        .takes_value(true) // "html" or "HTML" or ... json maybe?
                        .required(true)
                        .help("Compile to")
                        .value_name("FORMAT"))
                   )
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Node manager.

use super::{encode_contract_name, to_address_vec};
use super::ContractCallExt;
use libexecutor::executor::Executor;
use rand::{Rng, SeedableRng, StdRng};
use rustc_hex::ToHex;
use std::str::FromStr;
use util::{Address, H160};

const LIST_NODE: &'static [u8] = &*b"listNode()";

lazy_static! {
    static ref LIST_NODE_ENCODED: Vec<u8> = encode_contract_name(LIST_NODE);
    static ref CONTRACT_ADDRESS: H160 = H160::from_str("00000000000000000000000000000000013241a2").unwrap();
}

pub struct NodeManager;

impl NodeManager {
    pub fn nodes(executor: &Executor) -> Vec<Address> {
        let output = executor.call_method_latest(&*CONTRACT_ADDRESS, &*LIST_NODE_ENCODED.as_slice());
        trace!("nodemanager output: {:?}", ToHex::to_hex(output.as_slice()));

        let nodes: Vec<Address> = to_address_vec(&output);
        trace!("nodemanager nodes: {:?}", nodes);
        nodes
    }

    pub fn shuffle_nodes(node_vec: &Vec<Address>, rng_seed: u64) -> Vec<Address> {
        let mut ret: Vec<Address> = vec![];

        let seed: &[_] = &[rng_seed as usize];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        for i in 0..node_vec.len() {
            let j: usize = rng.gen::<usize>() % (i + 1);
            if j != i {
                ret[i] = ret[j];
            }
            ret[j] = node_vec[i];
        }
        ret
    }
}

#[cfg(test)]
mod tests {
    extern crate logger;
    extern crate mktemp;

    use super::NodeManager;
    use std::str::FromStr;
    use tests::helpers::init_executor;
    use util::H160;

    #[test]
    fn test_node_manager_contract() {
        let executor = init_executor();
        let nodes = NodeManager::nodes(&executor);

        assert_eq!(
            nodes,
            vec![
                H160::from_str("50ad2b9d6946d9c75ae978534043e3021ee1bfb1").unwrap(),
                H160::from_str("eeb3a71c4046f63a941013f826fccc503be26b77").unwrap(),
                H160::from_str("a2bbb65d4f8c3ada29f7471abe416e18061127f3").unwrap(),
                H160::from_str("72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b").unwrap(),
            ]
        )
    }
}
<commit_msg>change it to generic version<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! Node manager.

use super::{encode_contract_name, to_address_vec};
use super::ContractCallExt;
use libexecutor::executor::Executor;
use rand::{Rng, SeedableRng, StdRng};
use rustc_hex::ToHex;
use std::str::FromStr;
use util::{Address, H160};

const LIST_NODE: &'static [u8] = &*b"listNode()";

lazy_static! {
    static ref LIST_NODE_ENCODED: Vec<u8> = encode_contract_name(LIST_NODE);
    static ref CONTRACT_ADDRESS: H160 = H160::from_str("00000000000000000000000000000000013241a2").unwrap();
}

pub struct NodeManager;

impl NodeManager {
    pub fn nodes(executor: &Executor) -> Vec<Address> {
        let output = executor.call_method_latest(&*CONTRACT_ADDRESS, &*LIST_NODE_ENCODED.as_slice());
        trace!("nodemanager output: {:?}", ToHex::to_hex(output.as_slice()));

        let nodes: Vec<Address> = to_address_vec(&output);
        trace!("nodemanager nodes: {:?}", nodes);
        nodes
    }

    pub fn shuffle_node<T>(node_vec: &mut Vec<T>, rng_seed: u64) {
        let seed: &[_] = &[rng_seed as usize];
        let mut rng: StdRng = SeedableRng::from_seed(seed);

        for i in 0..node_vec.len() {
            let j: usize = rng.gen::<usize>() % (i + 1);
            node_vec.swap(i, j);
        }
    }
}

#[cfg(test)]
mod tests {
    extern crate logger;
    extern crate mktemp;

    use super::NodeManager;
    use std::str::FromStr;
    use tests::helpers::init_executor;
    use util::H160;

    #[test]
    fn test_node_manager_contract() {
        let executor = init_executor();
        let nodes = NodeManager::nodes(&executor);

        assert_eq!(
            nodes,
            vec![
                H160::from_str("50ad2b9d6946d9c75ae978534043e3021ee1bfb1").unwrap(),
                H160::from_str("eeb3a71c4046f63a941013f826fccc503be26b77").unwrap(),
                H160::from_str("a2bbb65d4f8c3ada29f7471abe416e18061127f3").unwrap(),
                H160::from_str("72eb1e258c9cdccebb7b62930a35cfb6ef4cd24b").unwrap(),
            ]
        )
    }
}
<|endoftext|>