<commit_before>use std::fmt;
use std::rc::Rc;
use std::str::FromStr;

use log::trace;
use semver::ReqParseError;
use semver::VersionReq;
use serde::ser;
use serde::Serialize;
use url::Url;

use crate::core::interning::InternedString;
use crate::core::{PackageId, SourceId, Summary};
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::{Cfg, CfgExpr, Config};

/// Information about a dependency requested by a Cargo manifest.
/// Cheap to copy.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
pub struct Dependency {
    inner: Rc<Inner>,
}

/// The data underlying a `Dependency`.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
struct Inner {
    name: InternedString,
    source_id: SourceId,
    /// Source ID for the registry as specified in the manifest.
    ///
    /// This will be None if it is not specified (crates.io dependency).
    /// This is different from `source_id` for example when both a `path` and
    /// `registry` is specified. Or in the case of a crates.io dependency,
    /// `source_id` will be crates.io and this will be None.
    registry_id: Option<SourceId>,
    req: VersionReq,
    specified_req: bool,
    kind: Kind,
    only_match_name: bool,
    explicit_name_in_toml: Option<InternedString>,

    optional: bool,
    public: bool,
    default_features: bool,
    features: Vec<InternedString>,

    // This dependency should be used only for this platform.
    // `None` means *all platforms*.
    platform: Option<Platform>,
}

#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum Platform {
    Name(String),
    Cfg(CfgExpr),
}

#[derive(Serialize)]
struct SerializedDependency<'a> {
    name: &'a str,
    source: SourceId,
    req: String,
    kind: Kind,
    rename: Option<&'a str>,

    optional: bool,
    uses_default_features: bool,
    features: &'a [InternedString],
    target: Option<&'a Platform>,
    /// The registry URL this dependency is from.
    /// If None, then it comes from the default registry (crates.io).
    #[serde(with = "url_serde")]
    registry: Option<Url>,
}

impl ser::Serialize for Dependency {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        SerializedDependency {
            name: &*self.package_name(),
            source: self.source_id(),
            req: self.version_req().to_string(),
            kind: self.kind(),
            optional: self.is_optional(),
            uses_default_features: self.uses_default_features(),
            features: self.features(),
            target: self.platform(),
            rename: self.explicit_name_in_toml().map(|s| s.as_str()),
            registry: self.registry_id().map(|sid| sid.url().clone()),
        }
        .serialize(s)
    }
}

#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug, Copy)]
pub enum Kind {
    Normal,
    Development,
    Build,
}

fn parse_req_with_deprecated(
    name: &str,
    req: &str,
    extra: Option<(PackageId, &Config)>,
) -> CargoResult<VersionReq> {
    match VersionReq::parse(req) {
        Err(ReqParseError::DeprecatedVersionRequirement(requirement)) => {
            let (inside, config) = match extra {
                Some(pair) => pair,
                None => return Err(ReqParseError::DeprecatedVersionRequirement(requirement).into()),
            };
            let msg = format!(
                "\
parsed version requirement `{}` is no longer valid

Previous versions of Cargo accepted this malformed requirement,
but it is being deprecated. This was found when parsing the manifest
of {} {}, and the correct version requirement is `{}`.

This will soon become a hard error, so it's either recommended to
update to a fixed version or contact the upstream maintainer about
this warning.
",
                req,
                inside.name(),
                inside.version(),
                requirement
            );
            config.shell().warn(&msg)?;

            Ok(requirement)
        }
        Err(e) => {
            let err: CargoResult<VersionReq> = Err(e.into());
            let v: VersionReq = err.chain_err(|| {
                format!(
                    "failed to parse the version requirement `{}` for dependency `{}`",
                    req, name
                )
            })?;
            Ok(v)
        }
        Ok(v) => Ok(v),
    }
}

impl ser::Serialize for Kind {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        match *self {
            Kind::Normal => None,
            Kind::Development => Some("dev"),
            Kind::Build => Some("build"),
        }
        .serialize(s)
    }
}

impl Dependency {
    /// Attempt to create a `Dependency` from an entry in the manifest.
    pub fn parse(
        name: &str,
        version: Option<&str>,
        source_id: SourceId,
        inside: PackageId,
        config: &Config,
    ) -> CargoResult<Dependency> {
        let arg = Some((inside, config));
        let (specified_req, version_req) = match version {
            Some(v) => (true, parse_req_with_deprecated(name, v, arg)?),
            None => (false, VersionReq::any()),
        };

        let mut ret = Dependency::new_override(name, source_id);
        {
            let ptr = Rc::make_mut(&mut ret.inner);
            ptr.only_match_name = false;
            ptr.req = version_req;
            ptr.specified_req = specified_req;
        }
        Ok(ret)
    }

    /// Attempt to create a `Dependency` from an entry in the manifest.
    pub fn parse_no_deprecated(
        name: &str,
        version: Option<&str>,
        source_id: SourceId,
    ) -> CargoResult<Dependency> {
        let (specified_req, version_req) = match version {
            Some(v) => (true, parse_req_with_deprecated(name, v, None)?),
            None => (false, VersionReq::any()),
        };

        let mut ret = Dependency::new_override(name, source_id);
        {
            let ptr = Rc::make_mut(&mut ret.inner);
            ptr.only_match_name = false;
            ptr.req = version_req;
            ptr.specified_req = specified_req;
        }
        Ok(ret)
    }

    pub fn new_override(name: &str, source_id: SourceId) -> Dependency {
        assert!(!name.is_empty());
        Dependency {
            inner: Rc::new(Inner {
                name: InternedString::new(name),
                source_id,
                registry_id: None,
                req: VersionReq::any(),
                kind: Kind::Normal,
                only_match_name: true,
                optional: false,
                public: false,
                features: Vec::new(),
                default_features: true,
                specified_req: false,
                platform: None,
                explicit_name_in_toml: None,
            }),
        }
    }

    pub fn version_req(&self) -> &VersionReq {
        &self.inner.req
    }

    /// This is the name of this `Dependency` as listed in `Cargo.toml`.
    ///
    /// Or in other words, this is what shows up in the `[dependencies]` section
    /// on the left hand side. This is *not* the name of the package that's
    /// being depended on as the dependency can be renamed. For that use
    /// `package_name` below.
    ///
    /// Both of the dependencies below return `foo` for `name_in_toml`:
    ///
    /// ```toml
    /// [dependencies]
    /// foo = "0.1"
    /// ```
    ///
    /// and ...
    ///
    /// ```toml
    /// [dependencies]
    /// foo = { version = "0.1", package = 'bar' }
    /// ```
    pub fn name_in_toml(&self) -> InternedString {
        self.explicit_name_in_toml().unwrap_or(self.inner.name)
    }

    /// The name of the package that this `Dependency` depends on.
    ///
    /// Usually this is what's written on the left hand side of a dependencies
    /// section, but it can also be renamed via the `package` key.
    ///
    /// Both of the dependencies below return `foo` for `package_name`:
    ///
    /// ```toml
    /// [dependencies]
    /// foo = "0.1"
    /// ```
    ///
    /// and ...
    ///
    /// ```toml
    /// [dependencies]
    /// bar = { version = "0.1", package = 'foo' }
    /// ```
    pub fn package_name(&self) -> InternedString {
        self.inner.name
    }

    pub fn source_id(&self) -> SourceId {
        self.inner.source_id
    }

    pub fn registry_id(&self) -> Option<SourceId> {
        self.inner.registry_id
    }

    pub fn set_registry_id(&mut self, registry_id: SourceId) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).registry_id = Some(registry_id);
        self
    }

    pub fn kind(&self) -> Kind {
        self.inner.kind
    }

    pub fn is_public(&self) -> bool {
        self.inner.public
    }

    /// Sets whether the dependency is public.
    pub fn set_public(&mut self, public: bool) -> &mut Dependency {
        // Setting 'public' only makes sense for normal dependencies
        assert_eq!(self.kind(), Kind::Normal);
        Rc::make_mut(&mut self.inner).public = public;
        self
    }

    pub fn specified_req(&self) -> bool {
        self.inner.specified_req
    }

    /// If none, this dependencies must be built for all platforms.
    /// If some, it must only be built for the specified platform.
    pub fn platform(&self) -> Option<&Platform> {
        self.inner.platform.as_ref()
    }

    /// The renamed name of this dependency, if any.
    ///
    /// If the `package` key is used in `Cargo.toml` then this returns the same
    /// value as `name_in_toml`.
    pub fn explicit_name_in_toml(&self) -> Option<InternedString> {
        self.inner.explicit_name_in_toml
    }

    pub fn set_kind(&mut self, kind: Kind) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).kind = kind;
        self
    }

    /// Sets the list of features requested for the package.
    pub fn set_features(
        &mut self,
        features: impl IntoIterator<Item = impl AsRef<str>>,
    ) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).features = features
            .into_iter()
            .map(|s| InternedString::new(s.as_ref()))
            .collect();
        self
    }

    /// Sets whether the dependency requests default features of the package.
    pub fn set_default_features(&mut self, default_features: bool) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).default_features = default_features;
        self
    }

    /// Sets whether the dependency is optional.
    pub fn set_optional(&mut self, optional: bool) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).optional = optional;
        self
    }

    /// Sets the source ID for this dependency.
    pub fn set_source_id(&mut self, id: SourceId) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).source_id = id;
        self
    }

    /// Sets the version requirement for this dependency.
    pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).req = req;
        self
    }

    pub fn set_platform(&mut self, platform: Option<Platform>) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).platform = platform;
        self
    }

    pub fn set_explicit_name_in_toml(&mut self, name: &str) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).explicit_name_in_toml = Some(InternedString::new(name));
        self
    }

    /// Locks this dependency to depending on the specified package ID.
    pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency {
        assert_eq!(self.inner.source_id, id.source_id());
        assert!(self.inner.req.matches(id.version()));
        trace!(
            "locking dep from `{}` with `{}` at {} to {}",
            self.package_name(),
            self.version_req(),
            self.source_id(),
            id
        );
        self.set_version_req(VersionReq::exact(id.version()))
            .set_source_id(id.source_id())
    }

    /// Returns `true` if this is a "locked" dependency, basically whether it has
    /// an exact version req.
    pub fn is_locked(&self) -> bool {
        // Kind of a hack to figure this out, but it works!
        self.inner.req.to_string().starts_with('=')
    }

    /// Returns `false` if the dependency is only used to build the local package.
    pub fn is_transitive(&self) -> bool {
        match self.inner.kind {
            Kind::Normal | Kind::Build => true,
            Kind::Development => false,
        }
    }

    pub fn is_build(&self) -> bool {
        match self.inner.kind {
            Kind::Build => true,
            _ => false,
        }
    }

    pub fn is_optional(&self) -> bool {
        self.inner.optional
    }

    /// Returns `true` if the default features of the dependency are requested.
    pub fn uses_default_features(&self) -> bool {
        self.inner.default_features
    }
    /// Returns the list of features that are requested by the dependency.
    pub fn features(&self) -> &[InternedString] {
        &self.inner.features
    }

    /// Returns `true` if the package (`sum`) can fulfill this dependency request.
    pub fn matches(&self, sum: &Summary) -> bool {
        self.matches_id(sum.package_id())
    }

    /// Returns `true` if the package (`sum`) can fulfill this dependency request.
    pub fn matches_ignoring_source(&self, id: PackageId) -> bool {
        self.package_name() == id.name() && self.version_req().matches(id.version())
    }

    /// Returns `true` if the package (`id`) can fulfill this dependency request.
    pub fn matches_id(&self, id: PackageId) -> bool {
        self.inner.name == id.name()
            && (self.inner.only_match_name
                || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id()))
    }

    pub fn map_source(mut self, to_replace: SourceId, replace_with: SourceId) -> Dependency {
        if self.source_id() != to_replace {
            self
        } else {
            self.set_source_id(replace_with);
            self
        }
    }
}

impl Platform {
    pub fn matches(&self, name: &str, cfg: Option<&[Cfg]>) -> bool {
        match *self {
            Platform::Name(ref p) => p == name,
            Platform::Cfg(ref p) => match cfg {
                Some(cfg) => p.matches(cfg),
                None => false,
            },
        }
    }
}

impl ser::Serialize for Platform {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        self.to_string().serialize(s)
    }
}

impl FromStr for Platform {
    type Err = failure::Error;

    fn from_str(s: &str) -> CargoResult<Platform> {
        if s.starts_with("cfg(") && s.ends_with(')') {
            let s = &s[4..s.len() - 1];
            let p = s.parse().map(Platform::Cfg).chain_err(|| {
                failure::format_err!("failed to parse `{}` as a cfg expression", s)
            })?;
            Ok(p)
        } else {
            Ok(Platform::Name(s.to_string()))
        }
    }
}

impl fmt::Display for Platform {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Platform::Name(ref n) => n.fmt(f),
            Platform::Cfg(ref e) => write!(f, "cfg({})", e),
        }
    }
}
<commit_msg>Relax assertion<commit_after>use std::fmt;
use std::rc::Rc;
use std::str::FromStr;

use log::trace;
use semver::ReqParseError;
use semver::VersionReq;
use serde::ser;
use serde::Serialize;
use url::Url;

use crate::core::interning::InternedString;
use crate::core::{PackageId, SourceId, Summary};
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::{Cfg, CfgExpr, Config};

/// Information about a dependency requested by a Cargo manifest.
/// Cheap to copy.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
pub struct Dependency {
    inner: Rc<Inner>,
}

/// The data underlying a `Dependency`.
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug)]
struct Inner {
    name: InternedString,
    source_id: SourceId,
    /// Source ID for the registry as specified in the manifest.
    ///
    /// This will be None if it is not specified (crates.io dependency).
    /// This is different from `source_id` for example when both a `path` and
    /// `registry` is specified. Or in the case of a crates.io dependency,
    /// `source_id` will be crates.io and this will be None.
    registry_id: Option<SourceId>,
    req: VersionReq,
    specified_req: bool,
    kind: Kind,
    only_match_name: bool,
    explicit_name_in_toml: Option<InternedString>,

    optional: bool,
    public: bool,
    default_features: bool,
    features: Vec<InternedString>,

    // This dependency should be used only for this platform.
    // `None` means *all platforms*.
    platform: Option<Platform>,
}

#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum Platform {
    Name(String),
    Cfg(CfgExpr),
}

#[derive(Serialize)]
struct SerializedDependency<'a> {
    name: &'a str,
    source: SourceId,
    req: String,
    kind: Kind,
    rename: Option<&'a str>,

    optional: bool,
    uses_default_features: bool,
    features: &'a [InternedString],
    target: Option<&'a Platform>,
    /// The registry URL this dependency is from.
    /// If None, then it comes from the default registry (crates.io).
    #[serde(with = "url_serde")]
    registry: Option<Url>,
}

impl ser::Serialize for Dependency {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        SerializedDependency {
            name: &*self.package_name(),
            source: self.source_id(),
            req: self.version_req().to_string(),
            kind: self.kind(),
            optional: self.is_optional(),
            uses_default_features: self.uses_default_features(),
            features: self.features(),
            target: self.platform(),
            rename: self.explicit_name_in_toml().map(|s| s.as_str()),
            registry: self.registry_id().map(|sid| sid.url().clone()),
        }
        .serialize(s)
    }
}

#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Debug, Copy)]
pub enum Kind {
    Normal,
    Development,
    Build,
}

fn parse_req_with_deprecated(
    name: &str,
    req: &str,
    extra: Option<(PackageId, &Config)>,
) -> CargoResult<VersionReq> {
    match VersionReq::parse(req) {
        Err(ReqParseError::DeprecatedVersionRequirement(requirement)) => {
            let (inside, config) = match extra {
                Some(pair) => pair,
                None => return Err(ReqParseError::DeprecatedVersionRequirement(requirement).into()),
            };
            let msg = format!(
                "\
parsed version requirement `{}` is no longer valid

Previous versions of Cargo accepted this malformed requirement,
but it is being deprecated. This was found when parsing the manifest
of {} {}, and the correct version requirement is `{}`.

This will soon become a hard error, so it's either recommended to
update to a fixed version or contact the upstream maintainer about
this warning.
",
                req,
                inside.name(),
                inside.version(),
                requirement
            );
            config.shell().warn(&msg)?;

            Ok(requirement)
        }
        Err(e) => {
            let err: CargoResult<VersionReq> = Err(e.into());
            let v: VersionReq = err.chain_err(|| {
                format!(
                    "failed to parse the version requirement `{}` for dependency `{}`",
                    req, name
                )
            })?;
            Ok(v)
        }
        Ok(v) => Ok(v),
    }
}

impl ser::Serialize for Kind {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        match *self {
            Kind::Normal => None,
            Kind::Development => Some("dev"),
            Kind::Build => Some("build"),
        }
        .serialize(s)
    }
}

impl Dependency {
    /// Attempt to create a `Dependency` from an entry in the manifest.
    pub fn parse(
        name: &str,
        version: Option<&str>,
        source_id: SourceId,
        inside: PackageId,
        config: &Config,
    ) -> CargoResult<Dependency> {
        let arg = Some((inside, config));
        let (specified_req, version_req) = match version {
            Some(v) => (true, parse_req_with_deprecated(name, v, arg)?),
            None => (false, VersionReq::any()),
        };

        let mut ret = Dependency::new_override(name, source_id);
        {
            let ptr = Rc::make_mut(&mut ret.inner);
            ptr.only_match_name = false;
            ptr.req = version_req;
            ptr.specified_req = specified_req;
        }
        Ok(ret)
    }

    /// Attempt to create a `Dependency` from an entry in the manifest.
    pub fn parse_no_deprecated(
        name: &str,
        version: Option<&str>,
        source_id: SourceId,
    ) -> CargoResult<Dependency> {
        let (specified_req, version_req) = match version {
            Some(v) => (true, parse_req_with_deprecated(name, v, None)?),
            None => (false, VersionReq::any()),
        };

        let mut ret = Dependency::new_override(name, source_id);
        {
            let ptr = Rc::make_mut(&mut ret.inner);
            ptr.only_match_name = false;
            ptr.req = version_req;
            ptr.specified_req = specified_req;
        }
        Ok(ret)
    }

    pub fn new_override(name: &str, source_id: SourceId) -> Dependency {
        assert!(!name.is_empty());
        Dependency {
            inner: Rc::new(Inner {
                name: InternedString::new(name),
                source_id,
                registry_id: None,
                req: VersionReq::any(),
                kind: Kind::Normal,
                only_match_name: true,
                optional: false,
                public: false,
                features: Vec::new(),
                default_features: true,
                specified_req: false,
                platform: None,
                explicit_name_in_toml: None,
            }),
        }
    }

    pub fn version_req(&self) -> &VersionReq {
        &self.inner.req
    }

    /// This is the name of this `Dependency` as listed in `Cargo.toml`.
    ///
    /// Or in other words, this is what shows up in the `[dependencies]` section
    /// on the left hand side. This is *not* the name of the package that's
    /// being depended on as the dependency can be renamed. For that use
    /// `package_name` below.
    ///
    /// Both of the dependencies below return `foo` for `name_in_toml`:
    ///
    /// ```toml
    /// [dependencies]
    /// foo = "0.1"
    /// ```
    ///
    /// and ...
    ///
    /// ```toml
    /// [dependencies]
    /// foo = { version = "0.1", package = 'bar' }
    /// ```
    pub fn name_in_toml(&self) -> InternedString {
        self.explicit_name_in_toml().unwrap_or(self.inner.name)
    }

    /// The name of the package that this `Dependency` depends on.
    ///
    /// Usually this is what's written on the left hand side of a dependencies
    /// section, but it can also be renamed via the `package` key.
    ///
    /// Both of the dependencies below return `foo` for `package_name`:
    ///
    /// ```toml
    /// [dependencies]
    /// foo = "0.1"
    /// ```
    ///
    /// and ...
    ///
    /// ```toml
    /// [dependencies]
    /// bar = { version = "0.1", package = 'foo' }
    /// ```
    pub fn package_name(&self) -> InternedString {
        self.inner.name
    }

    pub fn source_id(&self) -> SourceId {
        self.inner.source_id
    }

    pub fn registry_id(&self) -> Option<SourceId> {
        self.inner.registry_id
    }

    pub fn set_registry_id(&mut self, registry_id: SourceId) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).registry_id = Some(registry_id);
        self
    }

    pub fn kind(&self) -> Kind {
        self.inner.kind
    }

    pub fn is_public(&self) -> bool {
        self.inner.public
    }

    /// Sets whether the dependency is public.
    pub fn set_public(&mut self, public: bool) -> &mut Dependency {
        if !public {
            // Setting 'private' only makes sense for normal dependencies
            assert_eq!(self.kind(), Kind::Normal);
        }
        Rc::make_mut(&mut self.inner).public = public;
        self
    }

    pub fn specified_req(&self) -> bool {
        self.inner.specified_req
    }

    /// If none, this dependencies must be built for all platforms.
    /// If some, it must only be built for the specified platform.
    pub fn platform(&self) -> Option<&Platform> {
        self.inner.platform.as_ref()
    }

    /// The renamed name of this dependency, if any.
    ///
    /// If the `package` key is used in `Cargo.toml` then this returns the same
    /// value as `name_in_toml`.
    pub fn explicit_name_in_toml(&self) -> Option<InternedString> {
        self.inner.explicit_name_in_toml
    }

    pub fn set_kind(&mut self, kind: Kind) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).kind = kind;
        self
    }

    /// Sets the list of features requested for the package.
    pub fn set_features(
        &mut self,
        features: impl IntoIterator<Item = impl AsRef<str>>,
    ) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).features = features
            .into_iter()
            .map(|s| InternedString::new(s.as_ref()))
            .collect();
        self
    }

    /// Sets whether the dependency requests default features of the package.
    pub fn set_default_features(&mut self, default_features: bool) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).default_features = default_features;
        self
    }

    /// Sets whether the dependency is optional.
    pub fn set_optional(&mut self, optional: bool) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).optional = optional;
        self
    }

    /// Sets the source ID for this dependency.
    pub fn set_source_id(&mut self, id: SourceId) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).source_id = id;
        self
    }

    /// Sets the version requirement for this dependency.
    pub fn set_version_req(&mut self, req: VersionReq) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).req = req;
        self
    }

    pub fn set_platform(&mut self, platform: Option<Platform>) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).platform = platform;
        self
    }

    pub fn set_explicit_name_in_toml(&mut self, name: &str) -> &mut Dependency {
        Rc::make_mut(&mut self.inner).explicit_name_in_toml = Some(InternedString::new(name));
        self
    }

    /// Locks this dependency to depending on the specified package ID.
    pub fn lock_to(&mut self, id: PackageId) -> &mut Dependency {
        assert_eq!(self.inner.source_id, id.source_id());
        assert!(self.inner.req.matches(id.version()));
        trace!(
            "locking dep from `{}` with `{}` at {} to {}",
            self.package_name(),
            self.version_req(),
            self.source_id(),
            id
        );
        self.set_version_req(VersionReq::exact(id.version()))
            .set_source_id(id.source_id())
    }

    /// Returns `true` if this is a "locked" dependency, basically whether it has
    /// an exact version req.
    pub fn is_locked(&self) -> bool {
        // Kind of a hack to figure this out, but it works!
        self.inner.req.to_string().starts_with('=')
    }

    /// Returns `false` if the dependency is only used to build the local package.
    pub fn is_transitive(&self) -> bool {
        match self.inner.kind {
            Kind::Normal | Kind::Build => true,
            Kind::Development => false,
        }
    }

    pub fn is_build(&self) -> bool {
        match self.inner.kind {
            Kind::Build => true,
            _ => false,
        }
    }

    pub fn is_optional(&self) -> bool {
        self.inner.optional
    }

    /// Returns `true` if the default features of the dependency are requested.
    pub fn uses_default_features(&self) -> bool {
        self.inner.default_features
    }
    /// Returns the list of features that are requested by the dependency.
    pub fn features(&self) -> &[InternedString] {
        &self.inner.features
    }

    /// Returns `true` if the package (`sum`) can fulfill this dependency request.
    pub fn matches(&self, sum: &Summary) -> bool {
        self.matches_id(sum.package_id())
    }

    /// Returns `true` if the package (`sum`) can fulfill this dependency request.
    pub fn matches_ignoring_source(&self, id: PackageId) -> bool {
        self.package_name() == id.name() && self.version_req().matches(id.version())
    }

    /// Returns `true` if the package (`id`) can fulfill this dependency request.
    pub fn matches_id(&self, id: PackageId) -> bool {
        self.inner.name == id.name()
            && (self.inner.only_match_name
                || (self.inner.req.matches(id.version()) && self.inner.source_id == id.source_id()))
    }

    pub fn map_source(mut self, to_replace: SourceId, replace_with: SourceId) -> Dependency {
        if self.source_id() != to_replace {
            self
        } else {
            self.set_source_id(replace_with);
            self
        }
    }
}

impl Platform {
    pub fn matches(&self, name: &str, cfg: Option<&[Cfg]>) -> bool {
        match *self {
            Platform::Name(ref p) => p == name,
            Platform::Cfg(ref p) => match cfg {
                Some(cfg) => p.matches(cfg),
                None => false,
            },
        }
    }
}

impl ser::Serialize for Platform {
    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
    where
        S: ser::Serializer,
    {
        self.to_string().serialize(s)
    }
}

impl FromStr for Platform {
    type Err = failure::Error;

    fn from_str(s: &str) -> CargoResult<Platform> {
        if s.starts_with("cfg(") && s.ends_with(')') {
            let s = &s[4..s.len() - 1];
            let p = s.parse().map(Platform::Cfg).chain_err(|| {
                failure::format_err!("failed to parse `{}` as a cfg expression", s)
            })?;
            Ok(p)
        } else {
            Ok(Platform::Name(s.to_string()))
        }
    }
}

impl fmt::Display for Platform {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Platform::Name(ref n) => n.fmt(f),
            Platform::Cfg(ref e) => write!(f, "cfg({})", e),
        }
    }
}
<|endoftext|>


<commit_before>use crate::core::compiler::{CompileKind, CompileMode, Layout, RustcTargetData};
use crate::core::profiles::Profiles;
use crate::core::{InternedString, PackageIdSpec, Workspace};
use crate::ops;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::paths;
use crate::util::Config;
use std::fs;
use std::path::Path;

pub struct CleanOptions<'a> {
    pub config: &'a Config,
    /// A list of packages to clean. If empty, everything is cleaned.
    pub spec: Vec<String>,
    /// The target arch triple to clean, or None for the host arch
    pub targets: Vec<String>,
    /// Whether to clean the release directory
    pub profile_specified: bool,
    /// Whether to clean the directory of a certain build profile
    pub requested_profile: InternedString,
    /// Whether to just clean the doc directory
    pub doc: bool,
}

/// Cleans the package's build artifacts.
pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
    let mut target_dir = ws.target_dir();
    let config = ws.config();

    // If the doc option is set, we just want to delete the doc directory.
    if opts.doc {
        target_dir = target_dir.join("doc");
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    let profiles = Profiles::new(ws.profiles(), config, opts.requested_profile, ws.features())?;

    if opts.profile_specified {
        // After parsing profiles we know the dir-name of the profile, if a profile
        // was passed from the command line. If so, delete only the directory of
        // that profile.
        let dir_name = profiles.get_dir_name();
        target_dir = target_dir.join(dir_name);
    }

    // If we have a spec, then we need to delete some packages, otherwise, just
    // remove the whole target directory and be done with it!
    //
    // Note that we don't bother grabbing a lock here as we're just going to
    // blow it all away anyway.
    if opts.spec.is_empty() {
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    // Clean specific packages.
    let requested_kinds = CompileKind::from_requested_targets(config, &opts.targets)?;
    let target_data = RustcTargetData::new(ws, &requested_kinds)?;
    let (pkg_set, resolve) = ops::resolve_ws(ws)?;
    let prof_dir_name = profiles.get_dir_name();
    let host_layout = Layout::new(ws, None, &prof_dir_name)?;
    // Convert requested kinds to a Vec of layouts.
    let target_layouts: Vec<(CompileKind, Layout)> = requested_kinds
        .into_iter()
        .filter_map(|kind| match kind {
            CompileKind::Target(target) => match Layout::new(ws, Some(target), &prof_dir_name) {
                Ok(layout) => Some(Ok((kind, layout))),
                Err(e) => Some(Err(e)),
            },
            CompileKind::Host => None,
        })
        .collect::<CargoResult<_>>()?;
    // A Vec of layouts. This is a little convoluted because there can only be
    // one host_layout.
    let layouts = if opts.targets.is_empty() {
        vec![(CompileKind::Host, &host_layout)]
    } else {
        target_layouts
            .iter()
            .map(|(kind, layout)| (*kind, layout))
            .collect()
    };
    // Create a Vec that also includes the host for things that need to clean both.
    let layouts_with_host: Vec<(CompileKind, &Layout)> =
        std::iter::once((CompileKind::Host, &host_layout))
            .chain(layouts.iter().map(|(k, l)| (*k, *l)))
            .collect();

    // Cleaning individual rustdoc crates is currently not supported.
    // For example, the search index would need to be rebuilt to fully
    // remove it (otherwise you're left with lots of broken links).
    // Doc tests produce no output.

    // Get Packages for the specified specs.
    let mut packages = Vec::new();
    for spec_str in opts.spec.iter() {
        // Translate the spec to a Package.
        let spec = PackageIdSpec::parse(spec_str)?;
        if spec.version().is_some() {
            config.shell().warn(&format!(
                "version qualifier in `-p {}` is ignored, \
                cleaning all versions of `{}` found",
                spec_str,
                spec.name()
            ))?;
        }
        if spec.url().is_some() {
            config.shell().warn(&format!(
                "url qualifier in `-p {}` ignored, \
                cleaning all versions of `{}` found",
                spec_str,
                spec.name()
            ))?;
        }
        let matches: Vec<_> = resolve.iter().filter(|id| spec.matches(*id)).collect();
        if matches.is_empty() {
            anyhow::bail!("package ID specification `{}` matched no packages", spec);
        }
        packages.extend(pkg_set.get_many(matches)?);
    }

    for pkg in packages {
        let pkg_dir = format!("{}-*", pkg.name());

        // Clean fingerprints.
        for (_, layout) in &layouts_with_host {
            rm_rf_glob(&layout.fingerprint().join(&pkg_dir), config)?;
        }

        for target in pkg.targets() {
            if target.is_custom_build() {
                // Get both the build_script_build and the output directory.
                for (_, layout) in &layouts_with_host {
                    rm_rf_glob(&layout.build().join(&pkg_dir), config)?;
                }
                continue;
            }
            let crate_name = target.crate_name();
            for &mode in &[
                CompileMode::Build,
                CompileMode::Test,
                CompileMode::Check { test: false },
            ] {
                for (compile_kind, layout) in &layouts {
                    let triple = target_data.short_name(compile_kind);

                    let (file_types, _unsupported) = target_data
                        .info(*compile_kind)
                        .rustc_outputs(mode, target.kind(), triple)?;
                    let (dir, uplift_dir) = if target.is_example() {
                        (layout.examples(), layout.examples())
                    } else {
                        (layout.deps(), layout.dest())
                    };
                    for file_type in file_types {
                        // Some files include a hash in the filename, some don't.
                        let hashed_name = file_type.output_filename(target, Some("*"));
                        let unhashed_name = file_type.output_filename(target, None);
                        rm_rf_glob(&dir.join(&hashed_name), config)?;
                        rm_rf(&dir.join(&unhashed_name), config)?;
                        // Remove dep-info file generated by rustc. It is not tracked in
                        // file_types. It does not have a prefix.
                        let hashed_dep_info = dir.join(format!("{}-*.d", crate_name));
                        let unhashed_dep_info = dir.join(format!("{}.d", crate_name));
                        rm_rf_glob(&hashed_dep_info, config)?;
                        rm_rf(&unhashed_dep_info, config)?;

                        // Remove the uplifted copy.
                        let uplifted_path = uplift_dir.join(file_type.uplift_filename(target));
                        rm_rf(&uplifted_path, config)?;
                        // Dep-info generated by Cargo itself.
                        let dep_info = uplifted_path.with_extension("d");
                        rm_rf(&dep_info, config)?;
                    }
                    // TODO: what to do about build_script_build?
                    let incremental = layout.incremental().join(format!("{}-*", crate_name));
                    rm_rf_glob(&incremental, config)?;
                }
            }
        }
    }

    Ok(())
}

fn rm_rf_glob(pattern: &Path, config: &Config) -> CargoResult<()> {
    // TODO: Display utf8 warning to user?  Or switch to globset?
    let pattern = pattern
        .to_str()
        .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
    for path in glob::glob(pattern)? {
        rm_rf(&path?, config)?;
    }
    Ok(())
}

fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> {
    let m = fs::symlink_metadata(path);
    if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_dir_all(path)
            .chain_err(|| anyhow::format_err!("could not remove build directory"))?;
    } else if m.is_ok() {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_file(path)
            .chain_err(|| anyhow::format_err!("failed to remove build artifact"))?;
    }
    Ok(())
}
<commit_msg>clean -p: call `get_many` once.<commit_after>use crate::core::compiler::{CompileKind, CompileMode, Layout, RustcTargetData};
use crate::core::profiles::Profiles;
use crate::core::{InternedString, PackageIdSpec, Workspace};
use crate::ops;
use crate::util::errors::{CargoResult, CargoResultExt};
use crate::util::paths;
use crate::util::Config;
use std::fs;
use std::path::Path;

pub struct CleanOptions<'a> {
    pub config: &'a Config,
    /// A list of packages to clean. If empty, everything is cleaned.
    pub spec: Vec<String>,
    /// The target arch triple to clean, or None for the host arch
    pub targets: Vec<String>,
    /// Whether to clean the release directory
    pub profile_specified: bool,
    /// Whether to clean the directory of a certain build profile
    pub requested_profile: InternedString,
    /// Whether to just clean the doc directory
    pub doc: bool,
}

/// Cleans the package's build artifacts.
pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> {
    let mut target_dir = ws.target_dir();
    let config = ws.config();

    // If the doc option is set, we just want to delete the doc directory.
    if opts.doc {
        target_dir = target_dir.join("doc");
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    let profiles = Profiles::new(ws.profiles(), config, opts.requested_profile, ws.features())?;

    if opts.profile_specified {
        // After parsing profiles we know the dir-name of the profile, if a profile
        // was passed from the command line. If so, delete only the directory of
        // that profile.
        let dir_name = profiles.get_dir_name();
        target_dir = target_dir.join(dir_name);
    }

    // If we have a spec, then we need to delete some packages, otherwise, just
    // remove the whole target directory and be done with it!
    //
    // Note that we don't bother grabbing a lock here as we're just going to
    // blow it all away anyway.
    if opts.spec.is_empty() {
        return rm_rf(&target_dir.into_path_unlocked(), config);
    }

    // Clean specific packages.
    let requested_kinds = CompileKind::from_requested_targets(config, &opts.targets)?;
    let target_data = RustcTargetData::new(ws, &requested_kinds)?;
    let (pkg_set, resolve) = ops::resolve_ws(ws)?;
    let prof_dir_name = profiles.get_dir_name();
    let host_layout = Layout::new(ws, None, &prof_dir_name)?;
    // Convert requested kinds to a Vec of layouts.
    let target_layouts: Vec<(CompileKind, Layout)> = requested_kinds
        .into_iter()
        .filter_map(|kind| match kind {
            CompileKind::Target(target) => match Layout::new(ws, Some(target), &prof_dir_name) {
                Ok(layout) => Some(Ok((kind, layout))),
                Err(e) => Some(Err(e)),
            },
            CompileKind::Host => None,
        })
        .collect::<CargoResult<_>>()?;
    // A Vec of layouts. This is a little convoluted because there can only be
    // one host_layout.
    let layouts = if opts.targets.is_empty() {
        vec![(CompileKind::Host, &host_layout)]
    } else {
        target_layouts
            .iter()
            .map(|(kind, layout)| (*kind, layout))
            .collect()
    };
    // Create a Vec that also includes the host for things that need to clean both.
    let layouts_with_host: Vec<(CompileKind, &Layout)> =
        std::iter::once((CompileKind::Host, &host_layout))
            .chain(layouts.iter().map(|(k, l)| (*k, *l)))
            .collect();

    // Cleaning individual rustdoc crates is currently not supported.
    // For example, the search index would need to be rebuilt to fully
    // remove it (otherwise you're left with lots of broken links).
    // Doc tests produce no output.

    // Get Packages for the specified specs.
    let mut pkg_ids = Vec::new();
    for spec_str in opts.spec.iter() {
        // Translate the spec to a Package.
        let spec = PackageIdSpec::parse(spec_str)?;
        if spec.version().is_some() {
            config.shell().warn(&format!(
                "version qualifier in `-p {}` is ignored, \
                cleaning all versions of `{}` found",
                spec_str,
                spec.name()
            ))?;
        }
        if spec.url().is_some() {
            config.shell().warn(&format!(
                "url qualifier in `-p {}` ignored, \
                cleaning all versions of `{}` found",
                spec_str,
                spec.name()
            ))?;
        }
        let matches: Vec<_> = resolve.iter().filter(|id| spec.matches(*id)).collect();
        if matches.is_empty() {
            anyhow::bail!("package ID specification `{}` matched no packages", spec);
        }
        pkg_ids.extend(matches);
    }
    let packages = pkg_set.get_many(pkg_ids)?;

    for pkg in packages {
        let pkg_dir = format!("{}-*", pkg.name());

        // Clean fingerprints.
        for (_, layout) in &layouts_with_host {
            rm_rf_glob(&layout.fingerprint().join(&pkg_dir), config)?;
        }

        for target in pkg.targets() {
            if target.is_custom_build() {
                // Get both the build_script_build and the output directory.
                for (_, layout) in &layouts_with_host {
                    rm_rf_glob(&layout.build().join(&pkg_dir), config)?;
                }
                continue;
            }
            let crate_name = target.crate_name();
            for &mode in &[
                CompileMode::Build,
                CompileMode::Test,
                CompileMode::Check { test: false },
            ] {
                for (compile_kind, layout) in &layouts {
                    let triple = target_data.short_name(compile_kind);

                    let (file_types, _unsupported) = target_data
                        .info(*compile_kind)
                        .rustc_outputs(mode, target.kind(), triple)?;
                    let (dir, uplift_dir) = if target.is_example() {
                        (layout.examples(), layout.examples())
                    } else {
                        (layout.deps(), layout.dest())
                    };
                    for file_type in file_types {
                        // Some files include a hash in the filename, some don't.
                        let hashed_name = file_type.output_filename(target, Some("*"));
                        let unhashed_name = file_type.output_filename(target, None);
                        rm_rf_glob(&dir.join(&hashed_name), config)?;
                        rm_rf(&dir.join(&unhashed_name), config)?;
                        // Remove dep-info file generated by rustc. It is not tracked in
                        // file_types. It does not have a prefix.
                        let hashed_dep_info = dir.join(format!("{}-*.d", crate_name));
                        let unhashed_dep_info = dir.join(format!("{}.d", crate_name));
                        rm_rf_glob(&hashed_dep_info, config)?;
                        rm_rf(&unhashed_dep_info, config)?;

                        // Remove the uplifted copy.
                        let uplifted_path = uplift_dir.join(file_type.uplift_filename(target));
                        rm_rf(&uplifted_path, config)?;
                        // Dep-info generated by Cargo itself.
                        let dep_info = uplifted_path.with_extension("d");
                        rm_rf(&dep_info, config)?;
                    }
                    // TODO: what to do about build_script_build?
                    let incremental = layout.incremental().join(format!("{}-*", crate_name));
                    rm_rf_glob(&incremental, config)?;
                }
            }
        }
    }

    Ok(())
}

fn rm_rf_glob(pattern: &Path, config: &Config) -> CargoResult<()> {
    // TODO: Display utf8 warning to user?  Or switch to globset?
    let pattern = pattern
        .to_str()
        .ok_or_else(|| anyhow::anyhow!("expected utf-8 path"))?;
    for path in glob::glob(pattern)? {
        rm_rf(&path?, config)?;
    }
    Ok(())
}

fn rm_rf(path: &Path, config: &Config) -> CargoResult<()> {
    let m = fs::symlink_metadata(path);
    if m.as_ref().map(|s| s.is_dir()).unwrap_or(false) {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_dir_all(path)
            .chain_err(|| anyhow::format_err!("could not remove build directory"))?;
    } else if m.is_ok() {
        config
            .shell()
            .verbose(|shell| shell.status("Removing", path.display()))?;
        paths::remove_file(path)
            .chain_err(|| anyhow::format_err!("failed to remove build artifact"))?;
    }
    Ok(())
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use cgmath::{Vector2, Vector3, deg};
use glutin;
use core_types::{Size2, ZInt, MapPos};
use visualizer_types::{ZFloat, Color3, Color4, ColorId, MatId, WorldPos, ScreenPos, VertexCoord};
use zgl::{Zgl, Mesh};
use camera::Camera;
use shader::{Shader};
use geom;
use core_map::{MapPosIter};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &glutin::Window) -> Size2<ZInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as ZInt, h: h as ZInt}
}

fn get_max_camera_pos(map_size: &Size2<ZInt>) -> WorldPos {
    let pos = geom::map_pos_to_world_pos(
        MapPos{v: Vector2{x: map_size.w, y: map_size.h - 1}});
    WorldPos{v: Vector3{x: -pos.v.x, y: -pos.v.y, z: 0.0}}
}

fn generate_mesh(map_size: &Size2<ZInt>, zgl: &Zgl) -> Mesh {
    let mut vertex_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom::map_pos_to_world_pos(tile_pos);
        // TODO: range(0, 6) -> some dir iterator
        for num in range(0i32, 6) {
            let vertex = geom::index_to_hex_vertex(num);
            let next_vertex = geom::index_to_hex_vertex(num + 1);
            vertex_data.push(VertexCoord{v: pos.v + vertex.v});
            vertex_data.push(VertexCoord{v: pos.v + next_vertex.v});
            vertex_data.push(VertexCoord{v: pos.v});
        }
    }
    Mesh::new(zgl, vertex_data.as_slice())
}

pub struct Visualizer {
    zgl: Zgl,
    window: glutin::Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    shader: Shader,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
    mouse_pos: ScreenPos,
    is_lmb_pressed: bool,
    win_size: Size2<ZInt>,
    mesh: Mesh,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = glutin::WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut zgl = Zgl::new(|s| window.get_proc_address(s));
        zgl.print_gl_info();
        let shader = Shader::new(&zgl, VS_SRC, FS_SRC);
        let color_uniform_location = shader.get_uniform_color(&zgl, "col");
        let mvp_uniform_location = shader.get_uniform_mat(&zgl, "mvp_mat");
        zgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        let mut camera = Camera::new(&win_size);
        let map_size = Size2{w: 5, h: 2};
        camera.set_max_pos(get_max_camera_pos(&map_size));
        let mesh = generate_mesh(&map_size, &zgl);
        Visualizer {
            zgl: zgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            shader: shader,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: camera,
            mouse_pos: ScreenPos{v: Vector2::from_value(0)},
            is_lmb_pressed: false,
            win_size: win_size,
            mesh: mesh,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_event_mouse_move(&mut self, pos: &ScreenPos) {
        if self.is_lmb_pressed {
            let diff = pos.v - self.mouse_pos.v;
            let win_w = self.win_size.w as ZFloat;
            let win_h = self.win_size.h as ZFloat;
            self.camera.add_z_angle(
                deg(diff.x as ZFloat * (360.0 / win_w)));
            self.camera.add_x_angle(
                deg(diff.y as ZFloat * (360.0 / win_h)));
        }
        self.mouse_pos = pos.clone();
    }

    fn handle_event_key_press(&mut self, key: glutin::VirtualKeyCode) {
        match key {
            glutin::VirtualKeyCode::Q | glutin::VirtualKeyCode::Escape => {
                self.should_close = true;
            },
            glutin::VirtualKeyCode::W => self.camera.move_camera(deg(270.0), 0.1),
            glutin::VirtualKeyCode::S => self.camera.move_camera(deg(90.0), 0.1),
            glutin::VirtualKeyCode::D => self.camera.move_camera(deg(0.0), 0.1),
            glutin::VirtualKeyCode::A => self.camera.move_camera(deg(180.0), 0.1),
            glutin::VirtualKeyCode::Minus => self.camera.change_zoom(1.3),
            glutin::VirtualKeyCode::Equals => self.camera.change_zoom(0.7),
            _ => {},
        }
    }

    fn handle_event(&mut self, event: &glutin::Event) {
        match *event {
            glutin::Event::Closed => {
                self.should_close = true;
            },
            glutin::Event::Resized(w, h) => {
                self.win_size = Size2{w: w as ZInt, h: h as ZInt};
                self.zgl.set_viewport(&self.win_size);
            },
            glutin::Event::MouseMoved((x, y)) => {
                let pos = ScreenPos{v: Vector2{x: x as ZInt, y: y as ZInt}};
                self.handle_event_mouse_move(&pos);
            },
            glutin::Event::MouseInput(
                glutin::ElementState::Pressed,
                glutin::MouseButton::LeftMouseButton,
            ) => {
                self.is_lmb_pressed = true;
            },
            glutin::Event::MouseInput(
                glutin::ElementState::Released,
                glutin::MouseButton::LeftMouseButton,
            ) => {
                self.is_lmb_pressed = false;
                let (r, g, b, a) = self.zgl.read_pixel_bytes(
                    &self.win_size, &self.mouse_pos);
                println!("r: {}, g: {}, b: {}, a: {}", r, g, b, a);
            },
            glutin::Event::KeyboardInput(
                glutin::ElementState::Released, _, Some(key)) =>
            {
                self.handle_event_key_press(key);
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        // println!("{}", events);
        for event in events.iter() {
            self.handle_event(event);
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color.clone(),
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.zgl.clear_screen();
        self.shader.activate(&self.zgl);
        self.shader.set_uniform_color(
            &self.zgl, &self.color_uniform_location, &self.test_color);
        self.shader.set_uniform_mat4f(
            &self.zgl, &self.mvp_uniform_location, &self.camera.mat(&self.zgl));
        self.mesh.draw(&self.zgl);
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>src/visualizer.rs: 'use glutin;' -> 'use glutin::{..., ...};'<commit_after>// See LICENSE file for copyright and license details.

use cgmath::{Vector2, Vector3, deg};
use glutin::{Window, WindowBuilder, VirtualKeyCode, Event};
use glutin::ElementState::{Pressed, Released};
use glutin::MouseButton::{LeftMouseButton};
use core_types::{Size2, ZInt, MapPos};
use visualizer_types::{ZFloat, Color3, Color4, ColorId, MatId, WorldPos, ScreenPos, VertexCoord};
use zgl::{Zgl, Mesh};
use camera::Camera;
use shader::{Shader};
use geom;
use core_map::{MapPosIter};

static VS_SRC: &'static str = "\
    #version 100\n\
    uniform mat4 mvp_mat;\n\
    attribute vec2 position;\n\
    void main() {\n\
        gl_Position = mvp_mat * vec4(position, 0.0, 1.0);\n\
    }\n\
";

static FS_SRC: &'static str = "\
    #version 100\n\
    precision mediump float;
    uniform vec4 col;\n\
    void main() {\n\
        gl_FragColor = col;\n\
    }\n\
";

fn get_win_size(window: &Window) -> Size2<ZInt> {
    let (w, h) = window.get_inner_size().expect("Can`t get window size");
    Size2{w: w as ZInt, h: h as ZInt}
}

fn get_max_camera_pos(map_size: &Size2<ZInt>) -> WorldPos {
    let pos = geom::map_pos_to_world_pos(
        MapPos{v: Vector2{x: map_size.w, y: map_size.h - 1}});
    WorldPos{v: Vector3{x: -pos.v.x, y: -pos.v.y, z: 0.0}}
}

fn generate_mesh(map_size: &Size2<ZInt>, zgl: &Zgl) -> Mesh {
    let mut vertex_data = Vec::new();
    for tile_pos in MapPosIter::new(map_size) {
        let pos = geom::map_pos_to_world_pos(tile_pos);
        // TODO: range(0, 6) -> some dir iterator
        for num in range(0i32, 6) {
            let vertex = geom::index_to_hex_vertex(num);
            let next_vertex = geom::index_to_hex_vertex(num + 1);
            vertex_data.push(VertexCoord{v: pos.v + vertex.v});
            vertex_data.push(VertexCoord{v: pos.v + next_vertex.v});
            vertex_data.push(VertexCoord{v: pos.v});
        }
    }
    Mesh::new(zgl, vertex_data.as_slice())
}

pub struct Visualizer {
    zgl: Zgl,
    window: Window,
    should_close: bool,
    color_counter: i32, // TODO: remove
    test_color: Color4,
    shader: Shader,
    color_uniform_location: ColorId,
    mvp_uniform_location: MatId,
    camera: Camera,
    mouse_pos: ScreenPos,
    is_lmb_pressed: bool,
    win_size: Size2<ZInt>,
    mesh: Mesh,
}

impl Visualizer {
    pub fn new() -> Visualizer {
        let window_builder = WindowBuilder::new().with_gl_version((2, 0));
        let window = window_builder.build().ok().expect("Can`t create window");
        unsafe {
            window.make_current();
        };
        let win_size = get_win_size(&window);
        let mut zgl = Zgl::new(|s| window.get_proc_address(s));
        zgl.print_gl_info();
        let shader = Shader::new(&zgl, VS_SRC, FS_SRC);
        let color_uniform_location = shader.get_uniform_color(&zgl, "col");
        let mvp_uniform_location = shader.get_uniform_mat(&zgl, "mvp_mat");
        zgl.set_clear_color(Color3{r: 0.0, g: 0.0, b: 0.4});
        let mut camera = Camera::new(&win_size);
        let map_size = Size2{w: 5, h: 2};
        camera.set_max_pos(get_max_camera_pos(&map_size));
        let mesh = generate_mesh(&map_size, &zgl);
        Visualizer {
            zgl: zgl,
            window: window,
            should_close: false,
            color_counter: 0,
            test_color: Color4{r: 0.0, g: 0.0, b: 0.0, a: 0.0},
            shader: shader,
            color_uniform_location: color_uniform_location,
            mvp_uniform_location: mvp_uniform_location,
            camera: camera,
            mouse_pos: ScreenPos{v: Vector2::from_value(0)},
            is_lmb_pressed: false,
            win_size: win_size,
            mesh: mesh,
        }
    }

    pub fn is_running(&self) -> bool {
        !self.should_close
    }

    fn handle_event_mouse_move(&mut self, pos: &ScreenPos) {
        if self.is_lmb_pressed {
            let diff = pos.v - self.mouse_pos.v;
            let win_w = self.win_size.w as ZFloat;
            let win_h = self.win_size.h as ZFloat;
            self.camera.add_z_angle(
                deg(diff.x as ZFloat * (360.0 / win_w)));
            self.camera.add_x_angle(
                deg(diff.y as ZFloat * (360.0 / win_h)));
        }
        self.mouse_pos = pos.clone();
    }

    fn handle_event_key_press(&mut self, key: VirtualKeyCode) {
        match key {
            VirtualKeyCode::Q | VirtualKeyCode::Escape => {
                self.should_close = true;
            },
            VirtualKeyCode::W => self.camera.move_camera(deg(270.0), 0.1),
            VirtualKeyCode::S => self.camera.move_camera(deg(90.0), 0.1),
            VirtualKeyCode::D => self.camera.move_camera(deg(0.0), 0.1),
            VirtualKeyCode::A => self.camera.move_camera(deg(180.0), 0.1),
            VirtualKeyCode::Minus => self.camera.change_zoom(1.3),
            VirtualKeyCode::Equals => self.camera.change_zoom(0.7),
            _ => {},
        }
    }

    fn handle_event(&mut self, event: &Event) {
        match *event {
            Event::Closed => {
                self.should_close = true;
            },
            Event::Resized(w, h) => {
                self.win_size = Size2{w: w as ZInt, h: h as ZInt};
                self.zgl.set_viewport(&self.win_size);
            },
            Event::MouseMoved((x, y)) => {
                let pos = ScreenPos{v: Vector2{x: x as ZInt, y: y as ZInt}};
                self.handle_event_mouse_move(&pos);
            },
            Event::MouseInput(Pressed, LeftMouseButton) => {
                self.is_lmb_pressed = true;
            },
            Event::MouseInput(Released, LeftMouseButton) => {
                self.is_lmb_pressed = false;
                let (r, g, b, a) = self.zgl.read_pixel_bytes(
                    &self.win_size, &self.mouse_pos);
                println!("r: {}, g: {}, b: {}, a: {}", r, g, b, a);
            },
            Event::KeyboardInput(Released, _, Some(key)) => {
                self.handle_event_key_press(key);
            },
            _ => {},
        }
    }

    fn handle_events(&mut self) {
        let events = self.window.poll_events().collect::<Vec<_>>();
        if events.is_empty() {
            return;
        }
        // println!("{}", events);
        for event in events.iter() {
            self.handle_event(event);
        }
    }

    fn update_test_color(&mut self) {
        self.test_color = match self.color_counter {
            0 => Color4{r: 1.0, g: 0.0, b: 0.0, a: 1.0},
            30 => Color4{r: 0.0, g: 1.0, b: 0.0, a: 1.0},
            60 => Color4{r: 0.0, g: 0.0, b: 1.0, a: 1.0},
            _ => self.test_color.clone(),
        };
        self.color_counter += 1;
        if self.color_counter > 90 {
            self.color_counter = -1;
        }
    }

    fn draw(&mut self) {
        self.zgl.clear_screen();
        self.shader.activate(&self.zgl);
        self.shader.set_uniform_color(
            &self.zgl, &self.color_uniform_location, &self.test_color);
        self.shader.set_uniform_mat4f(
            &self.zgl, &self.mvp_uniform_location, &self.camera.mat(&self.zgl));
        self.mesh.draw(&self.zgl);
        self.window.swap_buffers();
    }

    pub fn tick(&mut self) {
        self.handle_events();
        // self.logic();
        self.update_test_color();
        self.draw();
        // self.update_time();
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, SubListRepresentative, ListedType};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {GlobalList::count()}
      fn count_before<T>()->usize {GlobalList::count_before::<T>()}
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn count_before<T>()->usize;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static LIST_ID: TypeId = TypeId::of::<GlobalList>();
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      LIST_ID.with (| id | {
        assert!(id, TypeId::of::<GlobalList>(), "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong")
      });
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

use std::any::Any ;

fn listed_type_id <GlobalList: whatever::SubList> (index: usize)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  use std::any::TypeId;
  use std::cell::{Cell, RefCell};
  use std::mem;
  struct Visitor (Vec<DeterministicallyRandomlyIdentifiedTypeId>);
  impl whatever::Visitor for Visitor {
    fn visit<T>(&mut self) where T: DeterministicallyRandomlyIdentifiedType {self.0.push (T::ID);}
  }
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> =Cell::new (None);
    static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
  TABLE.with (| table | {
    let mut guard = table.borrow_mut();
    if guard.is_empty() {
      mem::replace (&mut*guard, {
        let mut visitor = Visitor (Vec::with_capacity(whatever::Representative::<GlobalList>::count()));
        <GlobalList as whatever::SubList>::visit_all (&mut visitor);
        visitor.0
      });
    }
    guard.get (index).cloned()
  })
}

<commit_msg>Separate out global list uniqueness checking<commit_after>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, SubListRepresentative, ListedType};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {GlobalList::count()}
      fn count_before<T>()->usize {GlobalList::count_before::<T>()}
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn count_before<T>()->usize;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static LIST_ID: TypeId = TypeId::of::<GlobalList>();
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      LIST_ID.with (| id | {
        assert!(id, TypeId::of::<GlobalList>(), "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong")
      });
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

use std::any::Any ;

fn listed_type_id <GlobalList: whatever::SubList> (index: usize)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  assert_unique_global_list::<GlobalList>();
  use std::cell::RefCell;
  use std::mem;
  struct Visitor (Vec<DeterministicallyRandomlyIdentifiedTypeId>);
  impl whatever::Visitor for Visitor {
    fn visit<T>(&mut self) where T: DeterministicallyRandomlyIdentifiedType {self.0.push (T::ID);}
  }
  thread_local! {
    static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
  }
  TABLE.with (| table | {
    let mut guard = table.borrow_mut();
    if guard.is_empty() {
      mem::replace (&mut*guard, {
        let mut visitor = Visitor (Vec::with_capacity(whatever::Representative::<GlobalList>::count()));
        <GlobalList as whatever::SubList>::visit_all (&mut visitor);
        visitor.0
      });
    }
    guard.get (index).cloned()
  })
}

<|endoftext|>


<commit_before>//! Component range error

use core::fmt;

/// An error type indicating that a component provided to a method was out of range, causing a
/// failure.
// i64 is the narrowest type fitting all use cases. This eliminates the need for a type parameter.
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ComponentRange {
    /// Name of the component.
    pub name: &'static str,
    /// Minimum allowed value, inclusive.
    pub minimum: i64,
    /// Maximum allowed value, inclusive.
    pub maximum: i64,
    /// Value that was provided.
    pub value: i64,
    /// The minimum and/or maximum value is conditional on the value of other
    /// parameters.
    pub conditional_range: bool,
}

impl fmt::Display for ComponentRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} must be in the range {}..={}",
            self.name, self.minimum, self.maximum
        )?;

        if self.conditional_range {
            write!(f, ", given values of other parameters")?;
        }

        Ok(())
    }
}

impl From<ComponentRange> for crate::Error {
    fn from(original: ComponentRange) -> Self {
        Self::ComponentRange(original)
    }
}

#[cfg(feature = "serde")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "serde")))]
impl serde::de::Expected for ComponentRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "a value in the range {}..={}",
            self.minimum, self.maximum
        )
    }
}

#[cfg(feature = "serde")]
impl ComponentRange {
    /// Obtain an "invalid value" error type for the deserializer.
    pub(crate) fn to_invalid_serde_value<'a, D: serde::Deserializer<'a>>(self) -> D::Error {
        <D::Error as serde::de::Error>::invalid_value(
            serde::de::Unexpected::Signed(self.value),
            &self,
        )
    }
}

#[cfg(feature = "std")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "std")))]
impl std::error::Error for ComponentRange {}
<commit_msg>Avoid expensive formatting behavior<commit_after>//! Component range error

use core::fmt;

/// An error type indicating that a component provided to a method was out of range, causing a
/// failure.
// i64 is the narrowest type fitting all use cases. This eliminates the need for a type parameter.
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ComponentRange {
    /// Name of the component.
    pub name: &'static str,
    /// Minimum allowed value, inclusive.
    pub minimum: i64,
    /// Maximum allowed value, inclusive.
    pub maximum: i64,
    /// Value that was provided.
    pub value: i64,
    /// The minimum and/or maximum value is conditional on the value of other
    /// parameters.
    pub conditional_range: bool,
}

impl fmt::Display for ComponentRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{} must be in the range {}..={}",
            self.name, self.minimum, self.maximum
        )?;

        if self.conditional_range {
            f.write_str(", given values of other parameters")?;
        }

        Ok(())
    }
}

impl From<ComponentRange> for crate::Error {
    fn from(original: ComponentRange) -> Self {
        Self::ComponentRange(original)
    }
}

#[cfg(feature = "serde")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "serde")))]
impl serde::de::Expected for ComponentRange {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "a value in the range {}..={}",
            self.minimum, self.maximum
        )
    }
}

#[cfg(feature = "serde")]
impl ComponentRange {
    /// Obtain an "invalid value" error type for the deserializer.
    pub(crate) fn to_invalid_serde_value<'a, D: serde::Deserializer<'a>>(self) -> D::Error {
        <D::Error as serde::de::Error>::invalid_value(
            serde::de::Unexpected::Signed(self.value),
            &self,
        )
    }
}

#[cfg(feature = "std")]
#[cfg_attr(__time_03_docs, doc(cfg(feature = "std")))]
impl std::error::Error for ComponentRange {}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A bar that can used as a level indicator

use libc::c_double;
use std::ffi::CString;

use gtk::{self, ffi};
use gtk::{LevelBarMode};
use gtk::cast::GTK_LEVELBAR;

/// LevelBar — A bar that can used as a level indicator
/*
* # Signal availables:
* * `offset-changed` : Has Details
*/
struct_Widget!(LevelBar);

impl LevelBar {
    pub fn new() -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new() };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn new_for_interval(min: f64, max: f64) -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new_for_interval(min as c_double, max as c_double) };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn set_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_value(GTK_LEVELBAR(self.pointer)) as f64
        }
    }

    pub fn set_mode(&mut self, mode: LevelBarMode) -> () {
        unsafe {
            ffi::gtk_level_bar_set_mode(GTK_LEVELBAR(self.pointer), mode);
        }
    }

    pub fn get_mode(&self) -> LevelBarMode {
        unsafe {
            ffi::gtk_level_bar_get_mode(GTK_LEVELBAR(self.pointer))
        }
    }

    pub fn set_min_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_min_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_min_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_min_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    pub fn set_max_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_max_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_max_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_max_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn set_inverted(&mut self, inverted: bool) -> () {
        match inverted {
            true    => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GTRUE) },
            false   => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GFALSE) }
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn get_inverted(&self) -> bool {
        match unsafe { ffi::gtk_level_bar_get_inverted(GTK_LEVELBAR(self.pointer)) } {
            ffi::GFALSE => false,
            _ => true
        }
    }

    pub fn add_offset_value(&mut self, name: &str, value: f64) -> () {
        let c_str = CString::from_slice(name.as_bytes());
        unsafe {
            ffi::gtk_level_bar_add_offset_value(GTK_LEVELBAR(self.pointer), c_str, value as c_double)
        }
    }

    pub fn remove_offset_value(&mut self, name: &str) -> () {
        let c_str = CString::from_slice(name.as_bytes());
        unsafe {
            ffi::gtk_level_bar_remove_offset_value(GTK_LEVELBAR(self.pointer), c_str);
        }
    }

    pub fn get_offset_value(&self, name: &str) -> Option<f64> {
        let value = 0.;
        let c_str = CString::from_slice(name.as_bytes());

        match unsafe { ffi::gtk_level_bar_get_offset_value(GTK_LEVELBAR(self.pointer), c_str, &value) }{
            0132     => None,
            _        => Some(value)
        }
    }
}

impl_drop!(LevelBar);
impl_TraitWidget!(LevelBar);

impl gtk::OrientableTrait for LevelBar {}

impl_widget_events!(LevelBar);
<commit_msg>Still fixing travis build errors<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A bar that can used as a level indicator

use libc::c_double;
use std::ffi::CString;

use gtk::{self, ffi};
use gtk::{LevelBarMode};
use gtk::cast::GTK_LEVELBAR;

/// LevelBar — A bar that can used as a level indicator
/*
* # Signal availables:
* * `offset-changed` : Has Details
*/
struct_Widget!(LevelBar);

impl LevelBar {
    pub fn new() -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new() };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn new_for_interval(min: f64, max: f64) -> Option<LevelBar> {
        let tmp_pointer = unsafe { ffi::gtk_level_bar_new_for_interval(min as c_double, max as c_double) };
        check_pointer!(tmp_pointer, LevelBar)
    }

    pub fn set_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_value(GTK_LEVELBAR(self.pointer)) as f64
        }
    }

    pub fn set_mode(&mut self, mode: LevelBarMode) -> () {
        unsafe {
            ffi::gtk_level_bar_set_mode(GTK_LEVELBAR(self.pointer), mode);
        }
    }

    pub fn get_mode(&self) -> LevelBarMode {
        unsafe {
            ffi::gtk_level_bar_get_mode(GTK_LEVELBAR(self.pointer))
        }
    }

    pub fn set_min_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_min_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_min_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_min_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    pub fn set_max_value(&mut self, value: f64) -> () {
        unsafe {
            ffi::gtk_level_bar_set_max_value(GTK_LEVELBAR(self.pointer), value as c_double);
        }
    }

    pub fn get_max_value(&self) -> f64 {
        unsafe {
            ffi::gtk_level_bar_get_max_value(GTK_LEVELBAR(self.pointer)) as c_double
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn set_inverted(&mut self, inverted: bool) -> () {
        match inverted {
            true    => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GTRUE) },
            false   => unsafe { ffi::gtk_level_bar_set_inverted(GTK_LEVELBAR(self.pointer), ffi::GFALSE) }
        }
    }

    #[cfg(any(feature = "GTK_3_8", feature = "GTK_3_10",feature = "GTK_3_12", feature = "GTK_3_14"))]
    pub fn get_inverted(&self) -> bool {
        match unsafe { ffi::gtk_level_bar_get_inverted(GTK_LEVELBAR(self.pointer)) } {
            ffi::GFALSE => false,
            _ => true
        }
    }

    pub fn add_offset_value(&mut self, name: &str, value: f64) -> () {
        let c_str = CString::from_slice(name.as_bytes());
        unsafe {
            ffi::gtk_level_bar_add_offset_value(GTK_LEVELBAR(self.pointer), c_str.as_ptr(), value as c_double)
        }
    }

    pub fn remove_offset_value(&mut self, name: &str) -> () {
        let c_str = CString::from_slice(name.as_bytes());

        unsafe {
            ffi::gtk_level_bar_remove_offset_value(GTK_LEVELBAR(self.pointer), c_str.as_ptr());
        }
    }

    pub fn get_offset_value(&self, name: &str) -> Option<f64> {
        let value = 0.;
        let c_str = CString::from_slice(name.as_bytes());

        match unsafe { ffi::gtk_level_bar_get_offset_value(GTK_LEVELBAR(self.pointer), c_str.as_ptr(), &value) }{
            0132     => None,
            _        => Some(value)
        }
    }
}

impl_drop!(LevelBar);
impl_TraitWidget!(LevelBar);

impl gtk::OrientableTrait for LevelBar {}

impl_widget_events!(LevelBar);
<|endoftext|>