<commit_before>//! [GET /_matrix/client/r0/login](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-login)

use std::borrow::Cow;

use ruma_api::ruma_api;
#[cfg(feature = "unstable-pre-spec")]
use ruma_identifiers::MxcUri;
#[cfg(feature = "unstable-pre-spec")]
use ruma_serde::StringEnum;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value as JsonValue;

type JsonObject = serde_json::Map<String, JsonValue>;

ruma_api! {
    metadata: {
        description: "Gets the homeserver's supported login types to authenticate users. Clients should pick one of these and supply it as the type when logging in.",
        method: GET,
        name: "get_login_types",
        path: "/_matrix/client/r0/login",
        rate_limited: true,
        authentication: None,
    }

    #[derive(Default)]
    request: {}

    response: {
        /// The homeserver's supported login types.
        pub flows: Vec<LoginType>,
    }

    error: crate::Error
}

impl Request {
    /// Creates an empty `Request`.
    pub fn new() -> Self {
        Self
    }
}

impl Response {
    /// Creates a new `Response` with the given login types.
    pub fn new(flows: Vec<LoginType>) -> Self {
        Self { flows }
    }
}

/// An authentication mechanism.
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum LoginType {
    /// A password is supplied to authenticate.
    Password(PasswordLoginType),

    /// Token-based login.
    Token(TokenLoginType),

    /// SSO-based login.
    Sso(SsoLoginType),

    /// Custom login type.
    #[doc(hidden)]
    _Custom(CustomLoginType),
}

impl LoginType {
    /// Creates a `LoginType` with the given `login_type` string and data.
    ///
    /// Prefer to use the public variants of `LoginType` where possible; this constructor is meant
    /// be used for unsupported login types only and does not allow setting arbitrary data for
    /// supported ones.
    pub fn new(login_type: &str, data: JsonObject) -> serde_json::Result<Self> {
        fn from_json_object<T: DeserializeOwned>(obj: JsonObject) -> serde_json::Result<T> {
            serde_json::from_value(JsonValue::Object(obj))
        }

        Ok(match login_type {
            "m.login.password" => Self::Password(from_json_object(data)?),
            "m.login.token" => Self::Token(from_json_object(data)?),
            "m.login.sso" => Self::Sso(from_json_object(data)?),
            _ => Self::_Custom(CustomLoginType { type_: login_type.to_owned(), data }),
        })
    }

    /// Returns a reference to the `login_type` string.
    pub fn login_type(&self) -> &str {
        match self {
            Self::Password(_) => "m.login.password",
            Self::Token(_) => "m.login.token",
            Self::Sso(_) => "m.login.sso",
            Self::_Custom(c) => &c.type_,
        }
    }

    /// Returns the associated data.
    ///
    /// Prefer to use the public variants of `LoginType` where possible; this method is meant to
    /// be used for unsupported login types only.
    pub fn data(&self) -> Cow<'_, JsonObject> {
        fn serialize<T: Serialize>(obj: &T) -> JsonObject {
            match serde_json::to_value(obj).expect("login type serialization to succeed") {
                JsonValue::Object(obj) => obj,
                _ => panic!("all login types must serialize to objects"),
            }
        }

        match self {
            Self::Password(d) => Cow::Owned(serialize(d)),
            Self::Token(d) => Cow::Owned(serialize(d)),
            Self::Sso(d) => Cow::Owned(serialize(d)),
            Self::_Custom(c) => Cow::Borrowed(&c.data),
        }
    }
}

/// The payload for password login.
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type", rename = "m.login.password")]
pub struct PasswordLoginType {}

impl PasswordLoginType {
    /// Creates a new `PasswordLoginType`.
    pub fn new() -> Self {
        Self {}
    }
}

/// The payload for token-based login.
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type", rename = "m.login.token")]
pub struct TokenLoginType {}

impl TokenLoginType {
    /// Creates a new `PasswordLoginType`.
    pub fn new() -> Self {
        Self {}
    }
}

/// The payload for SSO login.
#[derive(Clone, Debug, Default, PartialEq, Eq, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type", rename = "m.login.sso")]
pub struct SsoLoginType {
    /// The identity provider choices.
    ///
    /// This uses the unstable prefix in
    /// [MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858).
    #[cfg(feature = "unstable-pre-spec")]
    #[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
    #[serde(
        default,
        rename = "org.matrix.msc2858.identity_providers",
        skip_serializing_if = "Vec::is_empty"
    )]
    pub identity_providers: Vec<IdentityProvider>,
}

impl SsoLoginType {
    /// Creates a new `PasswordLoginType`.
    pub fn new() -> Self {
        Self::default()
    }
}

/// An SSO login identity provider.
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct IdentityProvider {
    /// The ID of the provider.
    id: String,

    /// The display name of the provider.
    name: String,

    /// The icon for the provider.
    icon: Option<MxcUri>,

    /// The brand identifier for the provider.
    brand: Option<IdentityProviderBrand>,
}

#[cfg(feature = "unstable-pre-spec")]
impl IdentityProvider {
    /// Creates an `IdentityProvider` with the given `id` and `name`.
    pub fn new(id: String, name: String) -> Self {
        Self { id, name, icon: None, brand: None }
    }
}

/// An SSO login identity provider brand identifier.
///
/// This uses the unstable prefix in
/// [MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858).
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum IdentityProviderBrand {
    /// The [Apple] brand.
    ///
    /// [Apple]: https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/
    #[ruma_enum(rename = "org.matrix.apple")]
    Apple,

    /// The [Facebook](https://developers.facebook.com/docs/facebook-login/web/login-button/) brand.
    #[ruma_enum(rename = "org.matrix.facebook")]
    Facebook,

    /// The [GitHub](https://github.com/logos) brand.
    #[ruma_enum(rename = "org.matrix.github")]
    GitHub,

    /// The [GitLab](https://about.gitlab.com/press/press-kit/) brand.
    #[ruma_enum(rename = "org.matrix.gitlab")]
    GitLab,

    /// The [Google](https://developers.google.com/identity/branding-guidelines) brand.
    #[ruma_enum(rename = "org.matrix.google")]
    Google,

    /// The [Twitter] brand.
    ///
    /// [Twitter]: https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter#tab1
    #[ruma_enum(rename = "org.matrix.twitter")]
    Twitter,

    /// A custom brand.
    #[doc(hidden)]
    _Custom(String),
}

/// A custom login payload.
#[doc(hidden)]
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct CustomLoginType {
    /// A custom type
    ///
    /// This field is named `type_` instead of `type` because the latter is a reserved
    /// keyword in Rust.
    #[serde(rename = "override")]
    pub type_: String,

    /// Remaining type content
    #[serde(flatten)]
    pub data: JsonObject,
}

mod login_type_serde;

#[cfg(test)]
mod tests {
    use serde::{Deserialize, Serialize};
    #[cfg(feature = "unstable-pre-spec")]
    use serde_json::to_value as to_json_value;
    use serde_json::{from_value as from_json_value, json};

    #[cfg(feature = "unstable-pre-spec")]
    use super::{IdentityProvider, IdentityProviderBrand, SsoLoginType, TokenLoginType};
    use super::{LoginType, PasswordLoginType};

    #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
    struct Foo {
        pub flows: Vec<LoginType>,
    }

    #[test]
    fn deserialize_password_login_type() {
        assert_eq!(
            from_json_value::<Foo>(json!({
                "flows": [
                    { "type": "m.login.password" }
                ],
            }))
            .unwrap(),
            Foo { flows: vec![LoginType::Password(PasswordLoginType {})] }
        );
    }

    #[test]
    #[cfg(feature = "unstable-pre-spec")]
    fn deserialize_sso_login_type() {
        let foo = from_json_value::<Foo>(json!({
            "flows": [
                {
                    "type": "m.login.sso",
                    "org.matrix.msc2858.identity_providers": [
                        {
                            "id": "oidc-gitlab",
                            "name": "GitLab",
                            "icon": "mxc://localhost/gitlab-icon",
                            "brand": "org.matrix.gitlab"
                        },
                        {
                            "id": "custom",
                            "name": "Custom",
                        }
                    ]
                }
            ],
        }))
        .unwrap();

        assert_eq!(
            foo,
            Foo {
                flows: vec![LoginType::Sso(SsoLoginType {
                    identity_providers: vec![
                        IdentityProvider {
                            id: "oidc-gitlab".into(),
                            name: "GitLab".into(),
                            icon: Some("mxc://localhost/gitlab-icon".into()),
                            brand: Some(IdentityProviderBrand::GitLab)
                        },
                        IdentityProvider {
                            id: "custom".into(),
                            name: "Custom".into(),
                            icon: None,
                            brand: None
                        }
                    ]
                })]
            }
        )
    }

    #[test]
    #[cfg(feature = "unstable-pre-spec")]
    fn serialize_sso_login_type() {
        let foo = to_json_value(Foo {
            flows: vec![
                LoginType::Token(TokenLoginType {}),
                LoginType::Sso(SsoLoginType {
                    identity_providers: vec![IdentityProvider {
                        id: "oidc-github".into(),
                        name: "GitHub".into(),
                        icon: Some("mxc://localhost/github-icon".into()),
                        brand: Some(IdentityProviderBrand::GitHub),
                    }],
                }),
            ],
        })
        .unwrap();

        assert_eq!(
            foo,
            json!({
                "flows": [
                    {
                        "type": "m.login.token"
                    },
                    {
                        "type": "m.login.sso",
                        "org.matrix.msc2858.identity_providers": [
                            {
                                "id": "oidc-github",
                                "name": "GitHub",
                                "icon": "mxc://localhost/github-icon",
                                "brand": "org.matrix.github"
                            },
                        ]
                    }
                ],
            })
        );
    }
}
<commit_msg>client-api: Remove PartialEq and Eq for most types in get_login_types<commit_after>//! [GET /_matrix/client/r0/login](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-client-r0-login)

use std::borrow::Cow;

use ruma_api::ruma_api;
#[cfg(feature = "unstable-pre-spec")]
use ruma_identifiers::MxcUri;
#[cfg(feature = "unstable-pre-spec")]
use ruma_serde::StringEnum;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value as JsonValue;

type JsonObject = serde_json::Map<String, JsonValue>;

ruma_api! {
    metadata: {
        description: "Gets the homeserver's supported login types to authenticate users. Clients should pick one of these and supply it as the type when logging in.",
        method: GET,
        name: "get_login_types",
        path: "/_matrix/client/r0/login",
        rate_limited: true,
        authentication: None,
    }

    #[derive(Default)]
    request: {}

    response: {
        /// The homeserver's supported login types.
        pub flows: Vec<LoginType>,
    }

    error: crate::Error
}

impl Request {
    /// Creates an empty `Request`.
    pub fn new() -> Self {
        Self
    }
}

impl Response {
    /// Creates a new `Response` with the given login types.
    pub fn new(flows: Vec<LoginType>) -> Self {
        Self { flows }
    }
}

/// An authentication mechanism.
#[derive(Clone, Debug, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(untagged)]
pub enum LoginType {
    /// A password is supplied to authenticate.
    Password(PasswordLoginType),

    /// Token-based login.
    Token(TokenLoginType),

    /// SSO-based login.
    Sso(SsoLoginType),

    /// Custom login type.
    #[doc(hidden)]
    _Custom(CustomLoginType),
}

impl LoginType {
    /// Creates a `LoginType` with the given `login_type` string and data.
    ///
    /// Prefer to use the public variants of `LoginType` where possible; this constructor is meant
    /// be used for unsupported login types only and does not allow setting arbitrary data for
    /// supported ones.
    pub fn new(login_type: &str, data: JsonObject) -> serde_json::Result<Self> {
        fn from_json_object<T: DeserializeOwned>(obj: JsonObject) -> serde_json::Result<T> {
            serde_json::from_value(JsonValue::Object(obj))
        }

        Ok(match login_type {
            "m.login.password" => Self::Password(from_json_object(data)?),
            "m.login.token" => Self::Token(from_json_object(data)?),
            "m.login.sso" => Self::Sso(from_json_object(data)?),
            _ => Self::_Custom(CustomLoginType { type_: login_type.to_owned(), data }),
        })
    }

    /// Returns a reference to the `login_type` string.
    pub fn login_type(&self) -> &str {
        match self {
            Self::Password(_) => "m.login.password",
            Self::Token(_) => "m.login.token",
            Self::Sso(_) => "m.login.sso",
            Self::_Custom(c) => &c.type_,
        }
    }

    /// Returns the associated data.
    ///
    /// Prefer to use the public variants of `LoginType` where possible; this method is meant to
    /// be used for unsupported login types only.
    pub fn data(&self) -> Cow<'_, JsonObject> {
        fn serialize<T: Serialize>(obj: &T) -> JsonObject {
            match serde_json::to_value(obj).expect("login type serialization to succeed") {
                JsonValue::Object(obj) => obj,
                _ => panic!("all login types must serialize to objects"),
            }
        }

        match self {
            Self::Password(d) => Cow::Owned(serialize(d)),
            Self::Token(d) => Cow::Owned(serialize(d)),
            Self::Sso(d) => Cow::Owned(serialize(d)),
            Self::_Custom(c) => Cow::Borrowed(&c.data),
        }
    }
}

/// The payload for password login.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type", rename = "m.login.password")]
pub struct PasswordLoginType {}

impl PasswordLoginType {
    /// Creates a new `PasswordLoginType`.
    pub fn new() -> Self {
        Self {}
    }
}

/// The payload for token-based login.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type", rename = "m.login.token")]
pub struct TokenLoginType {}

impl TokenLoginType {
    /// Creates a new `PasswordLoginType`.
    pub fn new() -> Self {
        Self {}
    }
}

/// The payload for SSO login.
#[derive(Clone, Debug, Default, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(tag = "type", rename = "m.login.sso")]
pub struct SsoLoginType {
    /// The identity provider choices.
    ///
    /// This uses the unstable prefix in
    /// [MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858).
    #[cfg(feature = "unstable-pre-spec")]
    #[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
    #[serde(
        default,
        rename = "org.matrix.msc2858.identity_providers",
        skip_serializing_if = "Vec::is_empty"
    )]
    pub identity_providers: Vec<IdentityProvider>,
}

impl SsoLoginType {
    /// Creates a new `PasswordLoginType`.
    pub fn new() -> Self {
        Self::default()
    }
}

/// An SSO login identity provider.
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct IdentityProvider {
    /// The ID of the provider.
    id: String,

    /// The display name of the provider.
    name: String,

    /// The icon for the provider.
    icon: Option<MxcUri>,

    /// The brand identifier for the provider.
    brand: Option<IdentityProviderBrand>,
}

#[cfg(feature = "unstable-pre-spec")]
impl IdentityProvider {
    /// Creates an `IdentityProvider` with the given `id` and `name`.
    pub fn new(id: String, name: String) -> Self {
        Self { id, name, icon: None, brand: None }
    }
}

/// An SSO login identity provider brand identifier.
///
/// This uses the unstable prefix in
/// [MSC2858](https://github.com/matrix-org/matrix-doc/pull/2858).
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum IdentityProviderBrand {
    /// The [Apple] brand.
    ///
    /// [Apple]: https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/
    #[ruma_enum(rename = "org.matrix.apple")]
    Apple,

    /// The [Facebook](https://developers.facebook.com/docs/facebook-login/web/login-button/) brand.
    #[ruma_enum(rename = "org.matrix.facebook")]
    Facebook,

    /// The [GitHub](https://github.com/logos) brand.
    #[ruma_enum(rename = "org.matrix.github")]
    GitHub,

    /// The [GitLab](https://about.gitlab.com/press/press-kit/) brand.
    #[ruma_enum(rename = "org.matrix.gitlab")]
    GitLab,

    /// The [Google](https://developers.google.com/identity/branding-guidelines) brand.
    #[ruma_enum(rename = "org.matrix.google")]
    Google,

    /// The [Twitter] brand.
    ///
    /// [Twitter]: https://developer.twitter.com/en/docs/authentication/guides/log-in-with-twitter#tab1
    #[ruma_enum(rename = "org.matrix.twitter")]
    Twitter,

    /// A custom brand.
    #[doc(hidden)]
    _Custom(String),
}

/// A custom login payload.
#[doc(hidden)]
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct CustomLoginType {
    /// A custom type
    ///
    /// This field is named `type_` instead of `type` because the latter is a reserved
    /// keyword in Rust.
    #[serde(rename = "override")]
    pub type_: String,

    /// Remaining type content
    #[serde(flatten)]
    pub data: JsonObject,
}

mod login_type_serde;

#[cfg(test)]
mod tests {
    use serde::{Deserialize, Serialize};
    #[cfg(feature = "unstable-pre-spec")]
    use serde_json::to_value as to_json_value;
    use serde_json::{from_value as from_json_value, json};

    #[cfg(feature = "unstable-pre-spec")]
    use super::{IdentityProvider, IdentityProviderBrand, SsoLoginType, TokenLoginType};
    use super::{LoginType, PasswordLoginType};

    #[derive(Debug, Eq, PartialEq, Deserialize, Serialize)]
    struct Foo {
        pub flows: Vec<LoginType>,
    }

    #[test]
    fn deserialize_password_login_type() {
        assert_eq!(
            from_json_value::<Foo>(json!({
                "flows": [
                    { "type": "m.login.password" }
                ],
            }))
            .unwrap(),
            Foo { flows: vec![LoginType::Password(PasswordLoginType {})] }
        );
    }

    #[test]
    #[cfg(feature = "unstable-pre-spec")]
    fn deserialize_sso_login_type() {
        let foo = from_json_value::<Foo>(json!({
            "flows": [
                {
                    "type": "m.login.sso",
                    "org.matrix.msc2858.identity_providers": [
                        {
                            "id": "oidc-gitlab",
                            "name": "GitLab",
                            "icon": "mxc://localhost/gitlab-icon",
                            "brand": "org.matrix.gitlab"
                        },
                        {
                            "id": "custom",
                            "name": "Custom",
                        }
                    ]
                }
            ],
        }))
        .unwrap();

        assert_eq!(
            foo,
            Foo {
                flows: vec![LoginType::Sso(SsoLoginType {
                    identity_providers: vec![
                        IdentityProvider {
                            id: "oidc-gitlab".into(),
                            name: "GitLab".into(),
                            icon: Some("mxc://localhost/gitlab-icon".into()),
                            brand: Some(IdentityProviderBrand::GitLab)
                        },
                        IdentityProvider {
                            id: "custom".into(),
                            name: "Custom".into(),
                            icon: None,
                            brand: None
                        }
                    ]
                })]
            }
        )
    }

    #[test]
    #[cfg(feature = "unstable-pre-spec")]
    fn serialize_sso_login_type() {
        let foo = to_json_value(Foo {
            flows: vec![
                LoginType::Token(TokenLoginType {}),
                LoginType::Sso(SsoLoginType {
                    identity_providers: vec![IdentityProvider {
                        id: "oidc-github".into(),
                        name: "GitHub".into(),
                        icon: Some("mxc://localhost/github-icon".into()),
                        brand: Some(IdentityProviderBrand::GitHub),
                    }],
                }),
            ],
        })
        .unwrap();

        assert_eq!(
            foo,
            json!({
                "flows": [
                    {
                        "type": "m.login.token"
                    },
                    {
                        "type": "m.login.sso",
                        "org.matrix.msc2858.identity_providers": [
                            {
                                "id": "oidc-github",
                                "name": "GitHub",
                                "icon": "mxc://localhost/github-icon",
                                "brand": "org.matrix.github"
                            },
                        ]
                    }
                ],
            })
        );
    }
}
<|endoftext|>


<commit_before>use std::ops::{Add, Mul, Neg, Sub};
use dsl::LpExpression::*;
use dsl::{Constraint, LpBinary, LpConstraint, LpContinuous, LpExpression, LpInteger};

/// Operations trait for any type implementing Into<LpExpressions> trait
pub trait LpOperations<T> where T: Into<LpExpression> {
    /// Less or equal binary syntax for LpExpression
    fn le(&self, lhs_expr: T) -> LpConstraint;
    /// Greater or equal binary syntax for LpExpression
    fn ge(&self, lhs_expr: T) -> LpConstraint;
    /// Equality binary syntax for LpExpression
    fn equal(&self, lhs_expr: T) -> LpConstraint;
}

/// Macro implementing Into<LpExpression> for types
macro_rules! to_into_expr {
    ($type_to:ty) => {
        impl Into<LpExpression> for $type_to {
            fn into(self) -> LpExpression {
                LitVal(self as f32)
            }
        }
    };
    ($type_to:ty, $wrapper: ident) => {
        impl Into<LpExpression> for $type_to {
            fn into(self) -> LpExpression {
                $wrapper(self)
            }
        }
        impl<'a> Into<LpExpression> for &'a $type_to {
            fn into(self) -> LpExpression {
                $wrapper(self.clone())
            }
        }
    };
}
to_into_expr!(f32);
to_into_expr!(i32);
to_into_expr!(LpBinary, ConsBin);
to_into_expr!(LpInteger, ConsInt);
to_into_expr!(LpContinuous, ConsCont);

/// Macro implementing binary operations for Into<LpExpression> or &Into<LpExpression>
macro_rules! operations_for_expr {
    ($trait_name: ident, $f_name: ident, $expr_type: ident) => {
        impl<T> $trait_name<T> for LpExpression
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new(self.clone()), Box::new(_rhs.into()))
            }
        }
        impl<'a, T> $trait_name<T> for &'a LpExpression
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new(self.clone()), Box::new(_rhs.into()))
            }
        }
    };
}

operations_for_expr!(Add, add, AddExpr);
operations_for_expr!(Sub, sub, SubExpr);
operations_for_expr!(Mul, mul, MulExpr);

/// Macro implementing a binary operation with a LpVars and a Into<Expression>
macro_rules! lpvars_operation_for_intoexpr {
    ($trait_name: ident, $f_name: ident, $lp_type: ident, $expr_type: ident, $cons_type: ident) => {
        impl<T> $trait_name<T> for $lp_type
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new($cons_type(self.clone())), Box::new(_rhs.into())).normalize()
            }
        }
        impl<'a, T> $trait_name<T> for &'a $lp_type
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new($cons_type(self.clone())), Box::new(_rhs.into())).normalize()
            }
        }
    };
}

lpvars_operation_for_intoexpr!(Mul, mul, LpBinary, MulExpr, ConsBin);
lpvars_operation_for_intoexpr!(Add, add, LpBinary, AddExpr, ConsBin);
lpvars_operation_for_intoexpr!(Sub, sub, LpBinary, SubExpr, ConsBin);
lpvars_operation_for_intoexpr!(Mul, mul, LpInteger, MulExpr, ConsInt);
lpvars_operation_for_intoexpr!(Add, add, LpInteger, AddExpr, ConsInt);
lpvars_operation_for_intoexpr!(Sub, sub, LpInteger, SubExpr, ConsInt);
lpvars_operation_for_intoexpr!(Mul, mul, LpContinuous, MulExpr, ConsCont);
lpvars_operation_for_intoexpr!(Add, add, LpContinuous, AddExpr, ConsCont);
lpvars_operation_for_intoexpr!(Sub, sub, LpContinuous, SubExpr, ConsCont);

/// Macro implementing binary operations for a numeric type
macro_rules! numeric_operation_for_expr {
    ($num_type: ty, $trait_name: ident, $f_name: ident, $type_expr: ident) => {
        impl $trait_name<LpExpression> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: LpExpression) -> LpExpression {
                $type_expr(Box::new(LitVal(self as f32)), Box::new(_rhs))
            }
        }
        impl<'a> $trait_name<&'a LpExpression> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: &'a LpExpression) -> LpExpression {
                $type_expr(Box::new(LitVal(self as f32)), Box::new(_rhs.clone()))
            }
        }
    };
}
/// Macro implementing add, mul and sub for a specific numeric type
macro_rules! numeric_all_ops_for_expr {
    ($num_type: ty) => {
        numeric_operation_for_expr!($num_type, Add, add, AddExpr);
        numeric_operation_for_expr!($num_type, Mul, mul, MulExpr);
        numeric_operation_for_expr!($num_type, Sub, sub, SubExpr);
    };
}
numeric_all_ops_for_expr!(f32);
numeric_all_ops_for_expr!(i32);

/// &LpExpression to LpExpression
impl<'a> Into<LpExpression> for &'a LpExpression {
    fn into(self) -> LpExpression {
        self.clone()
    }
}

/// Implementing LpOperations trait for any Into<LpExpression>
impl<T: Into<LpExpression> + Clone, U> LpOperations<T> for U where U: Into<LpExpression> + Clone {
    fn le(&self, lhs_expr: T) -> LpConstraint {
        LpConstraint(
            self.clone().into(),
            Constraint::LessOrEqual,
            lhs_expr.clone().into(),
        )
        .generalize()
    }
    fn ge(&self, lhs_expr: T) -> LpConstraint {
        LpConstraint(
            self.clone().into(),
            Constraint::GreaterOrEqual,
            lhs_expr.clone().into(),
        )
        .generalize()
    }
    fn equal(&self, lhs_expr: T) -> LpConstraint {
        LpConstraint(
            self.clone().into(),
            Constraint::Equal,
            lhs_expr.clone().into(),
        )
        .generalize()
    }
}

impl<'a> Neg for &'a LpExpression {
    type Output = LpExpression;
    fn neg(self) -> LpExpression {
        MulExpr(Box::new(LitVal(-1.0)), Box::new(self.clone()))
    }
}
macro_rules! neg_operation_for_lpvars {
    ($lp_var_type: ty, $constr_expr: ident) => {
        impl<'a> Neg for &'a $lp_var_type {
            type Output = LpExpression;
            fn neg(self) -> LpExpression {
                MulExpr(Box::new(LitVal(-1.0)), Box::new($constr_expr(self.clone())))
            }
        }
    };
}
neg_operation_for_lpvars!(LpInteger, ConsInt);
neg_operation_for_lpvars!(LpContinuous, ConsCont);
neg_operation_for_lpvars!(LpBinary, ConsBin);

/// Macro implementing binary operations for a numeric type
macro_rules! numeric_operation_for_lpvars {
    ($num_type: ty, $trait_name: ident, $f_name: ident, $type_expr: ident, $lp_type: ty, $cons_expr: ident) => {
        impl $trait_name<$lp_type> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: $lp_type) -> LpExpression {
                $type_expr(Box::new(LitVal(self as f32)), Box::new($cons_expr(_rhs)))
            }
        }
        impl<'a> $trait_name<&'a $lp_type> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: &'a $lp_type) -> LpExpression {
                $type_expr(
                    Box::new(LitVal(self as f32)),
                    Box::new($cons_expr(_rhs.clone())),
                )
            }
        }
    };
}

/// Macro implementing add, mul and sub for a specific numeric type
macro_rules! numeric_all_ops_for_lpvars {
    ($num_type: ty) => {
        numeric_operation_for_lpvars!($num_type, Add, add, AddExpr, LpInteger, ConsInt);
        numeric_operation_for_lpvars!($num_type, Add, add, AddExpr, LpBinary, ConsBin);
        numeric_operation_for_lpvars!($num_type, Add, add, AddExpr, LpContinuous, ConsCont);
        numeric_operation_for_lpvars!($num_type, Mul, mul, MulExpr, LpInteger, ConsInt);
        numeric_operation_for_lpvars!($num_type, Mul, mul, MulExpr, LpBinary, ConsBin);
        numeric_operation_for_lpvars!($num_type, Mul, mul, MulExpr, LpContinuous, ConsCont);
        numeric_operation_for_lpvars!($num_type, Sub, sub, SubExpr, LpInteger, ConsInt);
        numeric_operation_for_lpvars!($num_type, Sub, sub, SubExpr, LpBinary, ConsBin);
        numeric_operation_for_lpvars!($num_type, Sub, sub, SubExpr, LpContinuous, ConsCont);
    };
}
numeric_all_ops_for_lpvars!(i32);
numeric_all_ops_for_lpvars!(f32);
<commit_msg>Implement AddAssign, SubAssign and MulAssign traits for LpExpression<commit_after>use dsl::LpExpression::*;
use dsl::{Constraint, LpBinary, LpConstraint, LpContinuous, LpExpression, LpInteger};
use std::ops::{Add, AddAssign, Mul, MulAssign, Neg, Sub, SubAssign};

/// Operations trait for any type implementing Into<LpExpressions> trait
pub trait LpOperations<T> where T: Into<LpExpression> {
    /// Less or equal binary syntax for LpExpression
    fn le(&self, lhs_expr: T) -> LpConstraint;
    /// Greater or equal binary syntax for LpExpression
    fn ge(&self, lhs_expr: T) -> LpConstraint;
    /// Equality binary syntax for LpExpression
    fn equal(&self, lhs_expr: T) -> LpConstraint;
}

/// Macro implementing Into<LpExpression> for types
macro_rules! to_into_expr {
    ($type_to:ty) => {
        impl Into<LpExpression> for $type_to {
            fn into(self) -> LpExpression {
                LitVal(self as f32)
            }
        }
    };
    ($type_to:ty, $wrapper: ident) => {
        impl Into<LpExpression> for $type_to {
            fn into(self) -> LpExpression {
                $wrapper(self)
            }
        }
        impl<'a> Into<LpExpression> for &'a $type_to {
            fn into(self) -> LpExpression {
                $wrapper(self.clone())
            }
        }
    };
}
to_into_expr!(f32);
to_into_expr!(i32);
to_into_expr!(LpBinary, ConsBin);
to_into_expr!(LpInteger, ConsInt);
to_into_expr!(LpContinuous, ConsCont);

/// Macro implementing binary operations for Into<LpExpression> or &Into<LpExpression>
macro_rules! operations_for_expr {
    ($trait_name: ident, $f_name: ident, $expr_type: ident) => {
        impl<T> $trait_name<T> for LpExpression
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new(self.clone()), Box::new(_rhs.into()))
            }
        }
        impl<'a, T> $trait_name<T> for &'a LpExpression
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new(self.clone()), Box::new(_rhs.into()))
            }
        }
    };
}

operations_for_expr!(Add, add, AddExpr);
operations_for_expr!(Sub, sub, SubExpr);
operations_for_expr!(Mul, mul, MulExpr);

macro_rules! assign_operations_for_expr {
    ($trait_name: ident, $f_name: ident, $expr_type: ident) => {
        impl<T> $trait_name<T> for LpExpression
        where
            T: Into<LpExpression> + Clone,
        {
            fn $f_name(&mut self, _rhs: T) {
                *self = $expr_type(Box::new(self.clone()), Box::new(_rhs.into()));
            }
        }
    };
}

assign_operations_for_expr!(AddAssign, add_assign, AddExpr);
assign_operations_for_expr!(SubAssign, sub_assign, SubExpr);
assign_operations_for_expr!(MulAssign, mul_assign, MulExpr);

/// Macro implementing a binary operation with a LpVars and a Into<Expression>
macro_rules! lpvars_operation_for_intoexpr {
    ($trait_name: ident, $f_name: ident, $lp_type: ident, $expr_type: ident, $cons_type: ident) => {
        impl<T> $trait_name<T> for $lp_type
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new($cons_type(self.clone())), Box::new(_rhs.into())).normalize()
            }
        }
        impl<'a, T> $trait_name<T> for &'a $lp_type
        where
            T: Into<LpExpression> + Clone,
        {
            type Output = LpExpression;
            fn $f_name(self, _rhs: T) -> LpExpression {
                $expr_type(Box::new($cons_type(self.clone())), Box::new(_rhs.into())).normalize()
            }
        }
    };
}

lpvars_operation_for_intoexpr!(Mul, mul, LpBinary, MulExpr, ConsBin);
lpvars_operation_for_intoexpr!(Add, add, LpBinary, AddExpr, ConsBin);
lpvars_operation_for_intoexpr!(Sub, sub, LpBinary, SubExpr, ConsBin);
lpvars_operation_for_intoexpr!(Mul, mul, LpInteger, MulExpr, ConsInt);
lpvars_operation_for_intoexpr!(Add, add, LpInteger, AddExpr, ConsInt);
lpvars_operation_for_intoexpr!(Sub, sub, LpInteger, SubExpr, ConsInt);
lpvars_operation_for_intoexpr!(Mul, mul, LpContinuous, MulExpr, ConsCont);
lpvars_operation_for_intoexpr!(Add, add, LpContinuous, AddExpr, ConsCont);
lpvars_operation_for_intoexpr!(Sub, sub, LpContinuous, SubExpr, ConsCont);

/// Macro implementing binary operations for a numeric type
macro_rules! numeric_operation_for_expr {
    ($num_type: ty, $trait_name: ident, $f_name: ident, $type_expr: ident) => {
        impl $trait_name<LpExpression> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: LpExpression) -> LpExpression {
                $type_expr(Box::new(LitVal(self as f32)), Box::new(_rhs))
            }
        }
        impl<'a> $trait_name<&'a LpExpression> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: &'a LpExpression) -> LpExpression {
                $type_expr(Box::new(LitVal(self as f32)), Box::new(_rhs.clone()))
            }
        }
    };
}
/// Macro implementing add, mul and sub for a specific numeric type
macro_rules! numeric_all_ops_for_expr {
    ($num_type: ty) => {
        numeric_operation_for_expr!($num_type, Add, add, AddExpr);
        numeric_operation_for_expr!($num_type, Mul, mul, MulExpr);
        numeric_operation_for_expr!($num_type, Sub, sub, SubExpr);
    };
}
numeric_all_ops_for_expr!(f32);
numeric_all_ops_for_expr!(i32);

/// &LpExpression to LpExpression
impl<'a> Into<LpExpression> for &'a LpExpression {
    fn into(self) -> LpExpression {
        self.clone()
    }
}

/// Implementing LpOperations trait for any Into<LpExpression>
impl<T: Into<LpExpression> + Clone, U> LpOperations<T> for U where U: Into<LpExpression> + Clone {
    fn le(&self, lhs_expr: T) -> LpConstraint {
        LpConstraint(
            self.clone().into(),
            Constraint::LessOrEqual,
            lhs_expr.clone().into(),
        )
        .generalize()
    }
    fn ge(&self, lhs_expr: T) -> LpConstraint {
        LpConstraint(
            self.clone().into(),
            Constraint::GreaterOrEqual,
            lhs_expr.clone().into(),
        )
        .generalize()
    }
    fn equal(&self, lhs_expr: T) -> LpConstraint {
        LpConstraint(
            self.clone().into(),
            Constraint::Equal,
            lhs_expr.clone().into(),
        )
        .generalize()
    }
}

impl<'a> Neg for &'a LpExpression {
    type Output = LpExpression;
    fn neg(self) -> LpExpression {
        MulExpr(Box::new(LitVal(-1.0)), Box::new(self.clone()))
    }
}
macro_rules! neg_operation_for_lpvars {
    ($lp_var_type: ty, $constr_expr: ident) => {
        impl<'a> Neg for &'a $lp_var_type {
            type Output = LpExpression;
            fn neg(self) -> LpExpression {
                MulExpr(Box::new(LitVal(-1.0)), Box::new($constr_expr(self.clone())))
            }
        }
    };
}
neg_operation_for_lpvars!(LpInteger, ConsInt);
neg_operation_for_lpvars!(LpContinuous, ConsCont);
neg_operation_for_lpvars!(LpBinary, ConsBin);

/// Macro implementing binary operations for a numeric type
macro_rules! numeric_operation_for_lpvars {
    ($num_type: ty, $trait_name: ident, $f_name: ident, $type_expr: ident, $lp_type: ty, $cons_expr: ident) => {
        impl $trait_name<$lp_type> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: $lp_type) -> LpExpression {
                $type_expr(Box::new(LitVal(self as f32)), Box::new($cons_expr(_rhs)))
            }
        }
        impl<'a> $trait_name<&'a $lp_type> for $num_type {
            type Output = LpExpression;
            fn $f_name(self, _rhs: &'a $lp_type) -> LpExpression {
                $type_expr(
                    Box::new(LitVal(self as f32)),
                    Box::new($cons_expr(_rhs.clone())),
                )
            }
        }
    };
}

/// Macro implementing add, mul and sub for a specific numeric type
macro_rules! numeric_all_ops_for_lpvars {
    ($num_type: ty) => {
        numeric_operation_for_lpvars!($num_type, Add, add, AddExpr, LpInteger, ConsInt);
        numeric_operation_for_lpvars!($num_type, Add, add, AddExpr, LpBinary, ConsBin);
        numeric_operation_for_lpvars!($num_type, Add, add, AddExpr, LpContinuous, ConsCont);
        numeric_operation_for_lpvars!($num_type, Mul, mul, MulExpr, LpInteger, ConsInt);
        numeric_operation_for_lpvars!($num_type, Mul, mul, MulExpr, LpBinary, ConsBin);
        numeric_operation_for_lpvars!($num_type, Mul, mul, MulExpr, LpContinuous, ConsCont);
        numeric_operation_for_lpvars!($num_type, Sub, sub, SubExpr, LpInteger, ConsInt);
        numeric_operation_for_lpvars!($num_type, Sub, sub, SubExpr, LpBinary, ConsBin);
        numeric_operation_for_lpvars!($num_type, Sub, sub, SubExpr, LpContinuous, ConsCont);
    };
}
numeric_all_ops_for_lpvars!(i32);
numeric_all_ops_for_lpvars!(f32);
<|endoftext|>


<commit_before>#![allow(unstable)]

extern crate cql_ffi;

use std::ffi::CString;
use std::slice;

use cql_ffi::*;

use std::num::ToPrimitive;

static NUM_CONCURRENT_REQUESTS:usize = 1000;

fn print_error(future:&mut CassFuture) {unsafe{
    let message = cass_future_error_message(future);
    let message = slice::from_raw_buf(&message.data,message.length as usize);
    println!("Error: {:?}", message);
}}

fn create_cluster() -> *mut CassCluster {
    let cluster = unsafe{cass_cluster_new()};
    unsafe{cass_cluster_set_contact_points(cluster, "127.0.0.1,127.0.0.2,127.0.0.3".as_ptr() as *const i8)};
    cluster
}

fn connect_session(session:&mut CassSession, cluster:&mut CassCluster) -> CassError {unsafe{
    let future = &mut *cass_session_connect(session, cluster);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    match rc {
        CASS_OK => {},
        _=> print_error(future)
    }
    cass_future_free(future);
    rc
}}

fn execute_query(session: &mut CassSession, query: &str) -> CassError {unsafe{
    let statement = cass_statement_new(cass_string_init(cass_string_init(CString::from_slice(query.as_bytes()).as_ptr()).data), 0);
    let future = &mut *cass_session_execute(session, statement);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    if rc != CASS_OK {
        print_error(future);
    }
    cass_future_free(future);
    cass_statement_free(statement);
    return rc;
}}

fn insert_into_async(session: &mut CassSession, key:&str) {unsafe{
    let query="INSERT INTO examples.async (key, bln, flt, dbl, i32, i64) VALUES (?, ?, ?, ?, ?, ?);";

    let mut futures = Vec::<CassFuture>::new();
    for i in (0..NUM_CONCURRENT_REQUESTS) {
        let statement = cass_statement_new(cass_string_init(cass_string_init(CString::from_slice(query.as_bytes()).as_ptr()).data), 6);
        let key = format!("{}{}", key, i).as_ptr() as *const i8;
        cass_statement_bind_string(statement, 0, cass_string_init(key));
        cass_statement_bind_bool(statement, 1, if i % 2 == 0 {cass_true} else {cass_false});
        cass_statement_bind_float(statement, 2, i.to_f32().unwrap() / 2.0f32);
        cass_statement_bind_double(statement, 3, i.to_f64().unwrap() / 200.0);
        cass_statement_bind_int32(statement, 4, i.to_i32().unwrap() * 10);
        cass_statement_bind_int64(statement, 5, i.to_i64().unwrap() * 100);
        futures.push(*cass_session_execute(session, statement));
        cass_statement_free(statement);
    }
    for mut future in futures.iter_mut() {
        cass_future_wait(future);
        let rc = cass_future_error_code(future);
        if rc != CASS_OK {
            print_error(&mut*future);
        }
        cass_future_free(future);
    }
}}

pub fn main() {unsafe{
    let (cluster,session) = (create_cluster(),cass_session_new());
    match connect_session(&mut*session, &mut*cluster) {
        CASS_OK => {},
        _ => {
            cass_cluster_free(cluster);
            cass_session_free(session);
            panic!("couldn't connect");
        }
    }
    execute_query(&mut*session, "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '1' };");
    execute_query(&mut*session, "CREATE TABLE IF NOT EXISTS examples.async (key text, bln boolean, flt float, dbl double, i32 int, i64 bigint, PRIMARY KEY (key));");
    execute_query(&mut*session, "USE examples");
    insert_into_async(&mut*session, "test");
    let close_future = cass_session_close(session);
    cass_future_wait(close_future);
    cass_future_free(close_future);
    cass_cluster_free(cluster);
    cass_session_free(session);
}}
<commit_msg>workaround for #20801<commit_after>#![allow(unstable)]

extern crate cql_ffi;

use std::ffi::CString;
use std::slice;

use cql_ffi::*;

use std::num::ToPrimitive;

static NUM_CONCURRENT_REQUESTS:usize = 1000;

fn print_error(future:&mut CassFuture) {unsafe{
    let message = cass_future_error_message(future);
    let message = slice::from_raw_buf(&message.data,message.length as usize);
    println!("Error: {:?}", message);
}}

fn create_cluster() -> *mut CassCluster {
    let cluster = unsafe{cass_cluster_new()};
    unsafe{cass_cluster_set_contact_points(cluster, "127.0.0.1,127.0.0.2,127.0.0.3".as_ptr() as *const i8)};
    cluster
}

fn connect_session(session:&mut CassSession, cluster:&mut CassCluster) -> CassError {unsafe{
    let future = &mut *cass_session_connect(session, cluster);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    match rc {
        CASS_OK => {},
        _=> print_error(future)
    }
    cass_future_free(future);
    rc
}}

fn execute_query(session: &mut CassSession, query: &str) -> CassError {unsafe{
    let statement = cass_statement_new(cass_string_init(cass_string_init(CString::from_slice(query.as_bytes()).as_ptr()).data), 0);
    let future = &mut *cass_session_execute(session, statement);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    if rc != CASS_OK {
        print_error(future);
    }
    cass_future_free(future);
    cass_statement_free(statement);
    return rc;
}}

fn insert_into_async(session: &mut CassSession, key:&str) {unsafe{
    let query="INSERT INTO examples.async (key, bln, flt, dbl, i32, i64) VALUES (?, ?, ?, ?, ?, ?);";

    let mut futures = Vec::<*mut CassFuture>::new();
    for i in (0..NUM_CONCURRENT_REQUESTS) {
        let statement = cass_statement_new(cass_string_init(cass_string_init(CString::from_slice(query.as_bytes()).as_ptr()).data), 6);
        let key = format!("{}{}", key, i).as_ptr() as *const i8;
        cass_statement_bind_string(statement, 0, cass_string_init(key));
        cass_statement_bind_bool(statement, 1, if i % 2 == 0 {cass_true} else {cass_false});
        cass_statement_bind_float(statement, 2, i.to_f32().unwrap() / 2.0f32);
        cass_statement_bind_double(statement, 3, i.to_f64().unwrap() / 200.0);
        cass_statement_bind_int32(statement, 4, i.to_i32().unwrap() * 10);
        cass_statement_bind_int64(statement, 5, i.to_i64().unwrap() * 100);
        futures.push(cass_session_execute(session, statement));
        cass_statement_free(statement);
    }
    for mut future in futures.iter_mut() {
        cass_future_wait(*future);
        let rc = cass_future_error_code(*future);
        if rc != CASS_OK {
            print_error(&mut**future);
        }
        cass_future_free(*future);
    }
}}

pub fn main() {unsafe{
    let (cluster,session) = (create_cluster(),cass_session_new());
    match connect_session(&mut*session, &mut*cluster) {
        CASS_OK => {},
        _ => {
            cass_cluster_free(cluster);
            cass_session_free(session);
            panic!("couldn't connect");
        }
    }
    execute_query(&mut*session, "CREATE KEYSPACE IF NOT EXISTS examples WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '1' };");
    execute_query(&mut*session, "CREATE TABLE IF NOT EXISTS examples.async (key text, bln boolean, flt float, dbl double, i32 int, i64 bigint, PRIMARY KEY (key));");
    execute_query(&mut*session, "USE examples");
    insert_into_async(&mut*session, "test");
    let close_future = cass_session_close(session);
    cass_future_wait(close_future);
    cass_future_free(close_future);
    cass_cluster_free(cluster);
    cass_session_free(session);
}}
<|endoftext|>


<commit_before>extern crate cql_ffi;
use std::ffi::CString;
use std::slice;
use cql_ffi::*;

struct Pair<'a> {
    key:&'a str,
    value:&'a str
}

fn print_error(future:&mut CassFuture) {unsafe{
    let message = cass_future_error_message(future);
    let message = slice::from_raw_buf(&message.data,message.length as usize);
    println!("Error: {:?}", message);
}}

fn create_cluster() -> *mut CassCluster {unsafe{
    let cluster = cass_cluster_new();
    cass_cluster_set_contact_points(cluster, str2ref("127.0.0.1,127.0.0.2,127.0.0.3"));
    cluster
}}

fn connect_session(session:&mut CassSession, cluster:&mut CassCluster) -> CassError {unsafe{
    let future = &mut *cass_session_connect(session, cluster);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    match rc {
        CASS_OK => {},
        _=> print_error(future)
    }
    cass_future_free(future);
    rc
}}

fn execute_query(session: &mut CassSession, query: &str) -> CassError {unsafe{
    let statement = cass_statement_new(cass_string_init(cass_string_init(CString::from_slice(query.as_bytes()).as_ptr()).data), 0);
    let future = &mut *cass_session_execute(session, statement);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    match rc {
        CASS_OK => {},
        _ => print_error(future)
    }
    cass_future_free(future);
    cass_statement_free(statement);
    return rc;
}}

fn prepare_insert_into_batch(session:&mut CassSession) -> Result<&CassPrepared,CassError> {unsafe{
    let  query = str2cass_string("INSERT INTO examples.pairs (key, value) VALUES (?, ?)");
    let future = cass_session_prepare(session, query);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    let prepared = match rc {
        CASS_OK => {Ok(&*cass_future_get_prepared(future))},
        _ => {
            print_error(&mut*future);
            Err(rc)
        }
    };
    cass_future_free(future);
    prepared
}}

fn insert_into_batch_with_prepared<'a>(session:&mut CassSession, pairs:Vec<Pair>, prepared:&'a CassPrepared)-> Result<&'a CassPrepared,CassError> {unsafe{
    let batch = cass_batch_new(CASS_BATCH_TYPE_LOGGED);
    for pair in pairs.iter() {
        let statement = cass_prepared_bind(prepared);
        cass_statement_bind_string(statement, 0, str2cass_string(pair.key));
        cass_statement_bind_string(statement, 1, str2cass_string(pair.value));
        cass_batch_add_statement(batch, statement);
        cass_statement_free(statement);
    }
    let statement = cass_statement_new(str2cass_string("INSERT INTO examples.pairs (key, value) VALUES ('c', '3')"), 0);
    cass_batch_add_statement(batch, statement);
    cass_statement_free(statement);

    let statement = cass_statement_new(str2cass_string("INSERT INTO examples.pairs (key, value) VALUES (?, ?)"),2);
    cass_statement_bind_string(statement, 0, str2cass_string("d"));
    cass_statement_bind_string(statement, 1, str2cass_string("4"));
    cass_batch_add_statement(batch, statement);
    cass_statement_free(statement);

    let future = cass_session_execute_batch(session, batch);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    if rc != CASS_OK {
        print_error(&mut*future);
    }
    cass_future_free(future);
    cass_batch_free(batch);
    Ok(prepared)
}}

fn main() {unsafe{
    let cluster = create_cluster();
    let session = cass_session_new();
    let pairs = vec!(Pair{key:"a", value:"1"}, Pair{key:"b", value:"2"});
    match connect_session(&mut*session, &mut*cluster) {
        CASS_OK => {},
        _ => {
            cass_cluster_free(cluster);
            cass_session_free(session);
            panic!();
        }
    }
    execute_query(&mut*session, "CREATE KEYSPACE examples WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };");
    execute_query(&mut*session, "CREATE TABLE examples.pairs (key text, value text, PRIMARY KEY (key));");
    let rc = prepare_insert_into_batch(&mut*session);
    match rc {
        Ok(ref prepared) => {
            insert_into_batch_with_prepared(&mut*session, pairs, *prepared);
            cass_prepared_free(*prepared);
        }
        Err(err) => panic!(err)
    };
    let close_future = cass_session_close(session);
    cass_future_wait(close_future);
    cass_future_free(close_future);
    cass_cluster_free(cluster);
    cass_session_free(session);
}}
<commit_msg>slightly cleaner batch<commit_after>#![allow(unstable)]
extern crate cql_ffi;
use std::ffi::CString;
use std::slice;
use cql_ffi::*;

struct Pair<'a> {
    key:&'a str,
    value:&'a str
}

fn print_error(future:&mut CassFuture) {unsafe{
    let message = cass_future_error_message(future);
    let message = slice::from_raw_buf(&message.data,message.length as usize);
    println!("Error: {:?}", message);
}}

fn create_cluster() -> *mut CassCluster {unsafe{
    let cluster = cass_cluster_new();
    cass_cluster_set_contact_points(cluster, str2ref("127.0.0.1,127.0.0.2,127.0.0.3"));
    cluster
}}

fn connect_session(session:&mut CassSession, cluster:&mut CassCluster) -> CassError {unsafe{
    let future = &mut *cass_session_connect(session, cluster);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    match rc {
        CASS_OK => {},
        _=> print_error(future)
    }
    cass_future_free(future);
    rc
}}

fn execute_query(session: &mut CassSession, query: &str) -> CassError {unsafe{
    let statement = cass_statement_new(cass_string_init(cass_string_init(CString::from_slice(query.as_bytes()).as_ptr()).data), 0);
    let future = &mut *cass_session_execute(session, statement);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    match rc {
        CASS_OK => {},
        _ => print_error(future)
    }
    cass_future_free(future);
    cass_statement_free(statement);
    return rc;
}}

fn prepare_insert_into_batch(session:&mut CassSession) -> Result<&CassPrepared,CassError> {unsafe{
    let  query = str2cass_string("INSERT INTO examples.pairs (key, value) VALUES (?, ?)");
    let future = cass_session_prepare(session, query);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    let prepared = match rc {
        CASS_OK => {Ok(&*cass_future_get_prepared(future))},
        _ => {
            print_error(&mut*future);
            Err(rc)
        }
    };
    cass_future_free(future);
    prepared
}}

fn insert_into_batch_with_prepared<'a>(session:&mut CassSession, pairs:Vec<Pair>, prepared:&'a CassPrepared)-> Result<&'a CassPrepared,CassError> {unsafe{
    let batch = cass_batch_new(CASS_BATCH_TYPE_LOGGED);
    for pair in pairs.iter() {
        let statement = cass_prepared_bind(prepared);
        cass_statement_bind_string(statement, 0, str2cass_string(pair.key));
        cass_statement_bind_string(statement, 1, str2cass_string(pair.value));
        cass_batch_add_statement(batch, statement);
        cass_statement_free(statement);
    }
    let statement = cass_statement_new(str2cass_string("INSERT INTO examples.pairs (key, value) VALUES ('c', '3')"), 0);
    cass_batch_add_statement(batch, statement);
    cass_statement_free(statement);

    let statement = cass_statement_new(str2cass_string("INSERT INTO examples.pairs (key, value) VALUES (?, ?)"),2);
    cass_statement_bind_string(statement, 0, str2cass_string("d"));
    cass_statement_bind_string(statement, 1, str2cass_string("4"));
    cass_batch_add_statement(batch, statement);
    cass_statement_free(statement);

    let future = cass_session_execute_batch(session, batch);
    cass_future_wait(future);
    let rc = cass_future_error_code(future);
    if rc != CASS_OK {
        print_error(&mut*future);
    }
    cass_future_free(future);
    cass_batch_free(batch);
    Ok(prepared)
}}

fn main() {unsafe{
    let cluster = create_cluster();
    let session = cass_session_new();
    let pairs = vec!(Pair{key:"a", value:"1"}, Pair{key:"b", value:"2"});
    match connect_session(&mut*session, &mut*cluster) {
        CASS_OK => {},
        _ => {
            cass_cluster_free(cluster);
            cass_session_free(session);
            panic!();
        }
    }
    execute_query(&mut*session, "CREATE KEYSPACE examples WITH replication = { 'class': 'SimpleStrategy', 'replication_factor': '3' };");
    execute_query(&mut*session, "CREATE TABLE examples.pairs (key text, value text, PRIMARY KEY (key));");
    match prepare_insert_into_batch(&mut*session) {
        Ok(ref prepared) => {
            match insert_into_batch_with_prepared(&mut*session, pairs, *prepared) {
                Ok(_) => cass_prepared_free(*prepared),
                _ => {}
            }
        }
        Err(err) => panic!(err)
    };
    let close_future = cass_session_close(session);
    cass_future_wait(close_future);
    cass_future_free(close_future);
    cass_cluster_free(cluster);
    cass_session_free(session);
}}
<|endoftext|>


<commit_before>use gfx_app::{ColorFormat, DepthFormat};
use gfx_app::renderer::EncoderQueue;
use gfx;
use bullet;
use terrain;
use character;
use zombie;
use specs;
use specs::{Fetch, WriteStorage};
use std::time::Instant;
use critter::CharacterSprite;
use graphics::orientation::Stance;
use graphics::DeltaTime;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
    where F: gfx::Factory<D::Resources>
  {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      fire_cool_down: 1.0
    }
  }
}

impl<'a, D> specs::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send,
{
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     Fetch<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut zombies, mut bullets, d): Self::SystemData) {
    use specs::Join;
    let mut encoder = self.encoder_queue.receiver.recv().unwrap();

    let delta = d.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.1;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "fps") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, zs, bs) in (&mut terrain, &mut character, &mut character_sprite, &mut zombies, &mut bullets).join() {
      self.terrain_system.draw(t, &mut encoder);

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }
      self.character_system.draw(c, cs, &mut encoder);
      for mut z in &mut zs.zombies {
        self.zombie_system.draw(&mut z, &mut encoder);
        match z.stance {
          Stance::NormalDeath => z.update_normal_death(),
          Stance::CriticalDeath => z.update_critical_death(),
          Stance::Walking => z.update_walk(),
          Stance::Still => z.update_still(),
          _ => ()
        };
      }
      for b in &mut bs.bullets {
        self.bullet_system.draw(b, &mut encoder);
      }
    }

    if let Err(e) = self.encoder_queue.sender.send(encoder) {
      panic!("Disconnected, cannot return encoder to mpsc: {}", e);
    };
  }
}
<commit_msg>Throttle zombie render update<commit_after>use gfx_app::{ColorFormat, DepthFormat};
use gfx_app::renderer::EncoderQueue;
use gfx;
use bullet;
use terrain;
use character;
use zombie;
use specs;
use specs::{Fetch, WriteStorage};
use std::time::Instant;
use critter::CharacterSprite;
use graphics::orientation::Stance;
use graphics::DeltaTime;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
    where F: gfx::Factory<D::Resources>
  {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      fire_cool_down: 1.0
    }
  }
}

impl<'a, D> specs::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send,
{
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     Fetch<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut zombies, mut bullets, d): Self::SystemData) {
    use specs::Join;
    let mut encoder = self.encoder_queue.receiver.recv().unwrap();

    let delta = d.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.1;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "fps") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, zs, bs) in (&mut terrain, &mut character, &mut character_sprite, &mut zombies, &mut bullets).join() {
      self.terrain_system.draw(t, &mut encoder);

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for mut z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_normal_death(),
            Stance::CriticalDeath => z.update_critical_death(),
            Stance::Walking => z.update_walk(),
            Stance::Still => z.update_still(),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }
      for mut z in &mut zs.zombies {
        self.zombie_system.draw(&mut z, &mut encoder);
      }
      self.character_system.draw(c, cs, &mut encoder);
      for b in &mut bs.bullets {
        self.bullet_system.draw(b, &mut encoder);
      }
    }

    if let Err(e) = self.encoder_queue.sender.send(encoder) {
      panic!("Disconnected, cannot return encoder to mpsc: {}", e);
    };
  }
}
<|endoftext|>


<commit_before>use gfx_app::{ColorFormat, DepthFormat};
use gfx_app::renderer::EncoderQueue;
use gfx;
use bullet;
use terrain;
use character;
use house;
use zombie;
use specs;
use specs::{Fetch, WriteStorage};
use std::time::Instant;
use critter::CharacterSprite;
use graphics::orientation::Stance;
use graphics::DeltaTime;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  house_system: house::HouseDrawSystem<D::Resources>,
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
                where F: gfx::Factory<D::Resources>
  {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      house_system: house::HouseDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      fire_cool_down: 1.0,
    }
  }
}

impl<'a, D> specs::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send,
{
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     WriteStorage<'a, house::HouseDrawable>,
                     Fetch<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut zombies, mut bullets, mut house, d): Self::SystemData) {
    use specs::Join;
    let mut encoder = self.encoder_queue.receiver.recv().unwrap();

    let delta = d.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.1;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "fps") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, zs, bs, h) in (&mut terrain, &mut character, &mut character_sprite, &mut zombies, &mut bullets, &mut house).join() {
      self.terrain_system.draw(t, &mut encoder);
      self.house_system.draw(h, &mut encoder);

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for mut z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_normal_death(),
            Stance::CriticalDeath => z.update_critical_death(),
            Stance::Walking => z.update_walk(),
            Stance::Still => z.update_still(),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }
      for mut z in &mut zs.zombies {
        if c.position.position[1] <= z.position.position[1] {
          self.zombie_system.draw(&mut z, &mut encoder);
        }
      }
      self.character_system.draw(c, cs, &mut encoder);
      for mut z in &mut zs.zombies {
        if c.position.position[1] > z.position.position[1] {
          self.zombie_system.draw(&mut z, &mut encoder);
        }
      }

      for b in &mut bs.bullets {
        self.bullet_system.draw(b, &mut encoder);
      }
    }

    if let Err(e) = self.encoder_queue.sender.send(encoder) {
      panic!("Disconnected, cannot return encoder to mpsc: {}", e);
    };
  }
}
<commit_msg>Check Z-index before drawing house and character<commit_after>use gfx_app::{ColorFormat, DepthFormat};
use gfx_app::renderer::EncoderQueue;
use gfx;
use bullet;
use terrain;
use character;
use house;
use zombie;
use specs;
use specs::{Fetch, WriteStorage};
use std::time::Instant;
use critter::CharacterSprite;
use graphics::orientation::Stance;
use graphics::DeltaTime;

pub struct DrawSystem<D: gfx::Device> {
  render_target_view: gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
  depth_stencil_view: gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
  terrain_system: terrain::TerrainDrawSystem<D::Resources>,
  character_system: character::CharacterDrawSystem<D::Resources>,
  zombie_system: zombie::ZombieDrawSystem<D::Resources>,
  bullet_system: bullet::BulletDrawSystem<D::Resources>,
  house_system: house::HouseDrawSystem<D::Resources>,
  encoder_queue: EncoderQueue<D>,
  game_time: Instant,
  frames: u32,
  cool_down: f64,
  fire_cool_down: f64,
}

impl<D: gfx::Device> DrawSystem<D> {
  pub fn new<F>(factory: &mut F,
                rtv: &gfx::handle::RenderTargetView<D::Resources, ColorFormat>,
                dsv: &gfx::handle::DepthStencilView<D::Resources, DepthFormat>,
                encoder_queue: EncoderQueue<D>)
                -> DrawSystem<D>
                where F: gfx::Factory<D::Resources>
  {
    DrawSystem {
      render_target_view: rtv.clone(),
      depth_stencil_view: dsv.clone(),
      terrain_system: terrain::TerrainDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      character_system: character::CharacterDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      zombie_system: zombie::ZombieDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      bullet_system: bullet::BulletDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      house_system: house::HouseDrawSystem::new(factory, rtv.clone(), dsv.clone()),
      encoder_queue,
      game_time: Instant::now(),
      frames: 0,
      cool_down: 1.0,
      fire_cool_down: 1.0,
    }
  }
}

impl<'a, D> specs::System<'a> for DrawSystem<D>
  where D: gfx::Device,
        D::CommandBuffer: Send,
{
  #[cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
  type SystemData = (WriteStorage<'a, terrain::TerrainDrawable>,
                     WriteStorage<'a, character::CharacterDrawable>,
                     WriteStorage<'a, CharacterSprite>,
                     WriteStorage<'a, zombie::zombies::Zombies>,
                     WriteStorage<'a, bullet::bullets::Bullets>,
                     WriteStorage<'a, house::HouseDrawable>,
                     Fetch<'a, DeltaTime>);

  fn run(&mut self, (mut terrain, mut character, mut character_sprite, mut zombies, mut bullets, mut house, d): Self::SystemData) {
    use specs::Join;
    let mut encoder = self.encoder_queue.receiver.recv().unwrap();

    let delta = d.0;

    if self.cool_down == 0.0 {
      self.cool_down += 0.1;
    }
    if self.fire_cool_down == 0.0 {
      self.fire_cool_down += 0.2;
    }
    self.cool_down = (self.cool_down - delta).max(0.0);
    self.fire_cool_down = (self.fire_cool_down - delta).max(0.0);

    let current_time = Instant::now();
    self.frames += 1;
    if cfg!(feature = "fps") && (current_time.duration_since(self.game_time).as_secs()) >= 1 {
      println!("{:?} ms/frames", 1000.0 / f64::from(self.frames));
      self.frames = 0;
      self.game_time = Instant::now();
    }

    encoder.clear(&self.render_target_view, [16.0 / 256.0, 16.0 / 256.0, 20.0 / 256.0, 1.0]);
    encoder.clear_depth(&self.depth_stencil_view, 1.0);

    for (t, c, cs, zs, bs, h) in (&mut terrain, &mut character, &mut character_sprite, &mut zombies, &mut bullets, &mut house).join() {
      self.terrain_system.draw(t, &mut encoder);

      if self.cool_down == 0.0 {
        if c.stance == Stance::Walking {
          cs.update_run();
        }
        for mut z in &mut zs.zombies {
          match z.stance {
            Stance::NormalDeath => z.update_normal_death(),
            Stance::CriticalDeath => z.update_critical_death(),
            Stance::Walking => z.update_walk(),
            Stance::Still => z.update_still(),
            _ => ()
          };
        }
      } else if self.fire_cool_down == 0.0 && c.stance == Stance::Firing {
        cs.update_fire();
      }
      for mut z in &mut zs.zombies {
        if c.position.position[1] <= z.position.position[1] {
          self.zombie_system.draw(&mut z, &mut encoder);
        }
      }
      if c.position.position[1] <= h.position.position[1] {
        self.house_system.draw(h, &mut encoder);
        self.character_system.draw(c, cs, &mut encoder);
      } else {
        self.character_system.draw(c, cs, &mut encoder);
        self.house_system.draw(h, &mut encoder);
      }
      for mut z in &mut zs.zombies {
        if c.position.position[1] > z.position.position[1] {
          self.zombie_system.draw(&mut z, &mut encoder);
        }
      }

      for b in &mut bs.bullets {
        self.bullet_system.draw(b, &mut encoder);
      }
    }

    if let Err(e) = self.encoder_queue.sender.send(encoder) {
      panic!("Disconnected, cannot return encoder to mpsc: {}", e);
    };
  }
}
<|endoftext|>


<commit_before>use decoders::Image;

pub fn gamma(_: &Image, buf: &mut Vec<f32>) {
  let g: f32 = 0.45;
  let f: f32 = 0.099;
  let min: f32 = 0.018;
  let mul: f32 = 4.5;

  let maxvals = 1 << 16; // 2^16 is enough precision for any output format
  let mut glookup: Vec<f32> = vec![0.0; maxvals+1];
  for i in 0..(maxvals+1) {
    let v = (i as f32) / (maxvals as f32);
    glookup[i] = if v <= min {
      mul * v
    } else {
      ((1.0+f) * v).powf(g) - f
    }
  }

  for i in 0..buf.len() {
    let val = buf[i];

    buf[i] = glookup[(val.max(0.0)*(maxvals as f32)).min(maxvals as f32) as usize];
  }
}
<commit_msg>gamma: cleanup loop using chunks_mut<commit_after>use decoders::Image;

pub fn gamma(_: &Image, buf: &mut Vec<f32>) {
  let g: f32 = 0.45;
  let f: f32 = 0.099;
  let min: f32 = 0.018;
  let mul: f32 = 4.5;

  let maxvals = 1 << 16; // 2^16 is enough precision for any output format
  let mut glookup: Vec<f32> = vec![0.0; maxvals+1];
  for i in 0..(maxvals+1) {
    let v = (i as f32) / (maxvals as f32);
    glookup[i] = if v <= min {
      mul * v
    } else {
      ((1.0+f) * v).powf(g) - f
    }
  }

  for pix in buf.chunks_mut(1) {
    pix[0] = glookup[(pix[0].max(0.0)*(maxvals as f32)).min(maxvals as f32) as usize];
  }
}
<|endoftext|>


<commit_before>//! Extended precision "soft float", for internal use only.

// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
#![unstable(
    feature = "core_private_diy_float",
    reason = "internal routines only exposed for testing",
    issue = "none"
)]

/// A custom 64-bit floating point type, representing `f * 2^e`.
#[derive(Copy, Clone, Debug)]
#[doc(hidden)]
pub struct Fp {
    /// The integer mantissa.
    pub f: u64,
    /// The exponent in base 2.
    pub e: i16,
}

impl Fp {
    /// Returns a correctly rounded product of itself and `other`.
    pub fn mul(&self, other: &Fp) -> Fp {
        const MASK: u64 = 0xffffffff;
        let a = self.f >> 32;
        let b = self.f & MASK;
        let c = other.f >> 32;
        let d = other.f & MASK;
        let ac = a * c;
        let bc = b * c;
        let ad = a * d;
        let bd = b * d;
        let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */;
        let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
        let e = self.e + other.e + 64;
        Fp { f, e }
    }

    /// Normalizes itself so that the resulting mantissa is at least `2^63`.
    pub fn normalize(&self) -> Fp {
        let mut f = self.f;
        let mut e = self.e;
        if f >> (64 - 32) == 0 {
            f <<= 32;
            e -= 32;
        }
        if f >> (64 - 16) == 0 {
            f <<= 16;
            e -= 16;
        }
        if f >> (64 - 8) == 0 {
            f <<= 8;
            e -= 8;
        }
        if f >> (64 - 4) == 0 {
            f <<= 4;
            e -= 4;
        }
        if f >> (64 - 2) == 0 {
            f <<= 2;
            e -= 2;
        }
        if f >> (64 - 1) == 0 {
            f <<= 1;
            e -= 1;
        }
        debug_assert!(f >= (1 >> 63));
        Fp { f, e }
    }

    /// Normalizes itself to have the shared exponent.
    /// It can only decrease the exponent (and thus increase the mantissa).
    pub fn normalize_to(&self, e: i16) -> Fp {
        let edelta = self.e - e;
        assert!(edelta >= 0);
        let edelta = edelta as usize;
        assert_eq!(self.f << edelta >> edelta, self.f);
        Fp { f: self.f << edelta, e }
    }
}
<commit_msg>Rollup merge of #87522 - frogtd:patch-1, r=yaahc<commit_after>//! Extended precision "soft float", for internal use only.

// This module is only for dec2flt and flt2dec, and only public because of coretests.
// It is not intended to ever be stabilized.
#![doc(hidden)]
#![unstable(
    feature = "core_private_diy_float",
    reason = "internal routines only exposed for testing",
    issue = "none"
)]

/// A custom 64-bit floating point type, representing `f * 2^e`.
#[derive(Copy, Clone, Debug)]
#[doc(hidden)]
pub struct Fp {
    /// The integer mantissa.
    pub f: u64,
    /// The exponent in base 2.
    pub e: i16,
}

impl Fp {
    /// Returns a correctly rounded product of itself and `other`.
    pub fn mul(&self, other: &Fp) -> Fp {
        const MASK: u64 = 0xffffffff;
        let a = self.f >> 32;
        let b = self.f & MASK;
        let c = other.f >> 32;
        let d = other.f & MASK;
        let ac = a * c;
        let bc = b * c;
        let ad = a * d;
        let bd = b * d;
        let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */;
        let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
        let e = self.e + other.e + 64;
        Fp { f, e }
    }

    /// Normalizes itself so that the resulting mantissa is at least `2^63`.
    pub fn normalize(&self) -> Fp {
        let mut f = self.f;
        let mut e = self.e;
        if f >> (64 - 32) == 0 {
            f <<= 32;
            e -= 32;
        }
        if f >> (64 - 16) == 0 {
            f <<= 16;
            e -= 16;
        }
        if f >> (64 - 8) == 0 {
            f <<= 8;
            e -= 8;
        }
        if f >> (64 - 4) == 0 {
            f <<= 4;
            e -= 4;
        }
        if f >> (64 - 2) == 0 {
            f <<= 2;
            e -= 2;
        }
        if f >> (64 - 1) == 0 {
            f <<= 1;
            e -= 1;
        }
        debug_assert!(f >= (1 << 63));
        Fp { f, e }
    }

    /// Normalizes itself to have the shared exponent.
    /// It can only decrease the exponent (and thus increase the mantissa).
    pub fn normalize_to(&self, e: i16) -> Fp {
        let edelta = self.e - e;
        assert!(edelta >= 0);
        let edelta = edelta as usize;
        assert_eq!(self.f << edelta >> edelta, self.f);
        Fp { f: self.f << edelta, e }
    }
}
<|endoftext|>


<commit_before>use super::*;
use super::internal::*;
use std;

pub struct VecIter<T: Send> {
    vec: Vec<T>,
    consumed: bool,
}

impl<T: Send> IntoParallelIterator for Vec<T> {
    type Item = T;
    type Iter = VecIter<T>;

    fn into_par_iter(self) -> Self::Iter {
        VecIter { vec: self, consumed: false }
    }
}

impl<T: Send> ParallelIterator for VecIter<T> {
    type Item = T;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge(self, consumer)
    }
}

impl<T: Send> BoundedParallelIterator for VecIter<T> {
    fn upper_bound(&mut self) -> usize {
        ExactParallelIterator::len(self)
    }

    fn drive<C>(self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        bridge(self, consumer)
    }
}

impl<T: Send> ExactParallelIterator for VecIter<T> {
    fn len(&mut self) -> usize {
        self.vec.len()
    }
}

impl<T: Send> IndexedParallelIterator for VecIter<T> {
    fn with_producer<CB>(mut self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        // The producer will move or drop each item from the slice.
        let producer = VecProducer { slice: &mut self.vec };
        self.consumed = true;
        callback.callback(producer)
    }
}

impl<T: Send> Drop for VecIter<T> {
    fn drop(&mut self) {
        if self.consumed {
            // only need vec to free its buffer now
            unsafe { self.vec.set_len(0) };
        }
    }
}

///////////////////////////////////////////////////////////////////////////

pub struct VecProducer<'data, T: 'data + Send> {
    slice: &'data mut [T]
}

impl<'data, T: 'data + Send> Producer for VecProducer<'data, T> {
    fn cost(&mut self, len: usize) -> f64 {
        len as f64
    }

    fn split_at(mut self, index: usize) -> (Self, Self) {
        // replace the slice so we don't drop it twice
        let slice = std::mem::replace(&mut self.slice, &mut []);
        let (left, right) = slice.split_at_mut(index);
        (VecProducer { slice: left }, VecProducer { slice: right })
    }
}

impl<'data, T: 'data + Send> IntoIterator for VecProducer<'data, T> {
    type Item = T;
    type IntoIter = SliceDrain<'data, T>;

    fn into_iter(mut self) -> Self::IntoIter {
        // replace the slice so we don't drop it twice
        let slice = std::mem::replace(&mut self.slice, &mut []);
        SliceDrain { iter: slice.iter_mut() }
    }
}

impl<'data, T: 'data + Send> Drop for VecProducer<'data, T> {
    fn drop(&mut self) {
        SliceDrain { iter: self.slice.iter_mut() };
    }
}

///////////////////////////////////////////////////////////////////////////

// like std::vec::Drain, without updating a source Vec
pub struct SliceDrain<'data, T: 'data> {
    iter: std::slice::IterMut<'data, T>
}

impl<'data, T: 'data> Iterator for SliceDrain<'data, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.iter.next()
            .map(|ptr| unsafe { std::ptr::read(ptr) })
    }
}

impl<'data, T: 'data> Drop for SliceDrain<'data, T> {
    fn drop(&mut self) {
        for ptr in &mut self.iter {
            // use drop_in_place once stable
            unsafe { std::ptr::read(ptr); }
        }
    }
}
<commit_msg>Refactor VecIter unsafety so it doesn't need Drop<commit_after>use super::*;
use super::internal::*;
use std;

pub struct VecIter<T: Send> {
    vec: Vec<T>,
}

impl<T: Send> IntoParallelIterator for Vec<T> {
    type Item = T;
    type Iter = VecIter<T>;

    fn into_par_iter(self) -> Self::Iter {
        VecIter { vec: self }
    }
}

impl<T: Send> ParallelIterator for VecIter<T> {
    type Item = T;

    fn drive_unindexed<C>(self, consumer: C) -> C::Result
        where C: UnindexedConsumer<Self::Item>
    {
        bridge(self, consumer)
    }
}

impl<T: Send> BoundedParallelIterator for VecIter<T> {
    fn upper_bound(&mut self) -> usize {
        ExactParallelIterator::len(self)
    }

    fn drive<C>(self, consumer: C) -> C::Result
        where C: Consumer<Self::Item>
    {
        bridge(self, consumer)
    }
}

impl<T: Send> ExactParallelIterator for VecIter<T> {
    fn len(&mut self) -> usize {
        self.vec.len()
    }
}

impl<T: Send> IndexedParallelIterator for VecIter<T> {
    fn with_producer<CB>(mut self, callback: CB) -> CB::Output
        where CB: ProducerCallback<Self::Item>
    {
        // The producer will move or drop each item from its slice, effectively taking ownership of
        // them.  When we're done, the vector only needs to free its buffer.
        unsafe {
            // Make the vector forget about the actual items.
            let len = self.vec.len();
            self.vec.set_len(0);

            // Get a correct borrow, then extend it to the original length.
            let mut slice = self.vec.as_mut_slice();
            slice = std::slice::from_raw_parts_mut(slice.as_mut_ptr(), len);

            callback.callback(VecProducer { slice: slice })
        }
    }
}

///////////////////////////////////////////////////////////////////////////

pub struct VecProducer<'data, T: 'data + Send> {
    slice: &'data mut [T]
}

impl<'data, T: 'data + Send> Producer for VecProducer<'data, T> {
    fn cost(&mut self, len: usize) -> f64 {
        len as f64
    }

    fn split_at(mut self, index: usize) -> (Self, Self) {
        // replace the slice so we don't drop it twice
        let slice = std::mem::replace(&mut self.slice, &mut []);
        let (left, right) = slice.split_at_mut(index);
        (VecProducer { slice: left }, VecProducer { slice: right })
    }
}

impl<'data, T: 'data + Send> IntoIterator for VecProducer<'data, T> {
    type Item = T;
    type IntoIter = SliceDrain<'data, T>;

    fn into_iter(mut self) -> Self::IntoIter {
        // replace the slice so we don't drop it twice
        let slice = std::mem::replace(&mut self.slice, &mut []);
        SliceDrain { iter: slice.iter_mut() }
    }
}

impl<'data, T: 'data + Send> Drop for VecProducer<'data, T> {
    fn drop(&mut self) {
        SliceDrain { iter: self.slice.iter_mut() };
    }
}

///////////////////////////////////////////////////////////////////////////

// like std::vec::Drain, without updating a source Vec
pub struct SliceDrain<'data, T: 'data> {
    iter: std::slice::IterMut<'data, T>
}

impl<'data, T: 'data> Iterator for SliceDrain<'data, T> {
    type Item = T;

    fn next(&mut self) -> Option<T> {
        self.iter.next()
            .map(|ptr| unsafe { std::ptr::read(ptr) })
    }
}

impl<'data, T: 'data> Drop for SliceDrain<'data, T> {
    fn drop(&mut self) {
        for ptr in &mut self.iter {
            // use drop_in_place once stable
            unsafe { std::ptr::read(ptr); }
        }
    }
}
<|endoftext|>


<commit_before>use parser::combinators::{Parser, ParseTo, Consumer, ErrConsumer, character, character_match};
use self::Token::{Begin, End, Identifier, Number, Whitespace};
use self::LexError::{ShouldntHappen};
use std::num::ParseIntError;

#[derive(Copy, Clone, Eq, Hash, Ord, PartialOrd, Debug)]
pub enum Token<'a> {
    Begin(&'a str),
    End,
    Identifier(&'a str),
    Number(usize),
    Whitespace(&'a str),
}

impl<'a,'b> PartialEq<Token<'a>> for Token<'b> {
    fn eq(&self, other: &Token<'a>) -> bool {
        match (*self, *other) {
            (Begin(s),      Begin(t))      => s == t,
            (End,           End)           => true,
            (Identifier(x), Identifier(y)) => x == y,
            (Number(m),     Number(n))     => m == n,
            (Whitespace(s), Whitespace(t)) => s == t,
            _                              => false,
        }
    }
}

impl<'a> From<Token<'a>> for String {
    fn from(tok: Token<'a>) -> String {
        match tok {
            Begin(kw)     => String::from("(") + kw,
            End           => String::from(")"),
            Identifier(x) => String::from(x),
            Number(n)     => n.to_string(),
            Whitespace(s) => String::from(s),
        }
    }
}

#[derive(Clone, Debug)]
pub enum LexError {
    ShouldntHappen(ParseIntError),
}

impl From<ParseIntError> for LexError {
    fn from(err: ParseIntError) -> LexError {
        ShouldntHappen(err)
    }
}

pub trait LexerConsumer<D> where D: ErrConsumer<LexError>+for<'a> Consumer<Token<'a>> {
    fn accept<L>(self, lexer: L) where L: for<'a> ParseTo<&'a str,D>;
}

fn is_keyword_char(ch: char) -> bool { ch.is_alphanumeric() || (ch == '.') }
fn is_identifier_char(ch: char) -> bool { ch.is_alphanumeric() || (ch == '.') || (ch == '$') }

fn mk_begin<'a>(s: &'a str) -> Token<'a> { Begin(s) }
fn mk_end<'a>(_: char) -> Token<'a> { End }
fn mk_identifier<'a>(s: &'a str) -> Token<'a> { Identifier(s) }
fn mk_number<'a>(s: &'a str) -> Result<Token<'a>,LexError> { Ok(Number(try!(usize::from_str_radix(s,10)))) }
fn mk_whitespace<'a>(s: &'a str) -> Token<'a> { Whitespace(s) }

#[allow(non_snake_case)]
pub fn lexer<C,D>(consumer: C) where C: LexerConsumer<D>, D: ErrConsumer<LexError>+for<'a> Consumer<Token<'a>> {
    let BEGIN = character('(').ignore().and_then(character_match(is_keyword_char).plus().buffer().map(mk_begin));
    let END = character(')').map(mk_end);
    let WHITESPACE = character_match(char::is_whitespace).plus().buffer().map(mk_whitespace);
    let IDENTIFIER = character_match(is_identifier_char).plus().buffer().map(mk_identifier);
    let NUMBER = character_match(char::is_numeric).plus().buffer().map(mk_number).results();
    consumer.accept(BEGIN.or_else(END).or_else(IDENTIFIER).or_else(NUMBER).or_else(WHITESPACE).star())
}

#[test]
fn test_lexer() {
    struct TestConsumer(Vec<String>,Vec<LexError>);
    impl<'a> Consumer<Token<'a>> for TestConsumer {
        fn accept(&mut self, tok: Token<'a>) {
            self.0.push(String::from(tok));
        }
    }
    impl ErrConsumer<LexError> for TestConsumer {
        fn error(&mut self, err: LexError) {
            self.1.push(err);
        }
    }
    impl LexerConsumer<TestConsumer> for TestConsumer {
        fn accept<L>(mut self, mut lex: L) where L: for<'a> ParseTo<&'a str,TestConsumer> {
            lex.push_to("(a123 $bcd f32 \t 37)", &mut self);
            assert_eq!(self.0, ["(a123", " ", "$bcd", " ", "f32", " \t ", "37", ")"]);
            assert_eq!(self.1.len(), 0);
        }
    }
    lexer(TestConsumer(Vec::new(),Vec::new()));
}
<commit_msg>Added string literals to the lexer.<commit_after>use parser::combinators::{Parser, ParseTo, Consumer, ErrConsumer, character, character_match};
use self::Token::{Begin, End, Identifier, Number, Text, Whitespace};
use self::LexError::{ShouldntHappen};
use std::num::ParseIntError;

#[derive(Copy, Clone, Eq, Hash, Ord, PartialOrd, Debug)]
pub enum Token<'a> {
    Begin(&'a str),
    End,
    Identifier(&'a str),
    Number(usize),
    Text(&'a str),
    Whitespace(&'a str),
}

impl<'a,'b> PartialEq<Token<'a>> for Token<'b> {
    fn eq(&self, other: &Token<'a>) -> bool {
        match (*self, *other) {
            (Begin(s),      Begin(t))      => s == t,
            (End,           End)           => true,
            (Identifier(x), Identifier(y)) => x == y,
            (Number(m),     Number(n))     => m == n,
            (Text(s),       Text(t))       => s == t,
            (Whitespace(s), Whitespace(t)) => s == t,
            _                              => false,
        }
    }
}

impl<'a> From<Token<'a>> for String {
    fn from(tok: Token<'a>) -> String {
        match tok {
            Begin(kw)     => String::from("(") + kw,
            End           => String::from(")"),
            Identifier(x) => String::from(x),
            Number(n)     => n.to_string(),
            Text(s)       => String::from("\"") + s + "\"",
            Whitespace(s) => String::from(s),
        }
    }
}

#[derive(Clone, Debug)]
pub enum LexError {
    ShouldntHappen(ParseIntError),
}

impl From<ParseIntError> for LexError {
    fn from(err: ParseIntError) -> LexError {
        ShouldntHappen(err)
    }
}

pub trait LexerConsumer<D> where D: ErrConsumer<LexError>+for<'a> Consumer<Token<'a>> {
    fn accept<L>(self, lexer: L) where L: for<'a> ParseTo<&'a str,D>;
}

fn is_keyword_char(ch: char) -> bool { ch.is_alphanumeric() || (ch == '.') }
fn is_identifier_char(ch: char) -> bool { ch.is_alphanumeric() || (ch == '.') || (ch == '$') }
fn is_unescaped_char(ch: char) -> bool { ch != '"' && ch != '\\' && ch != '\r' && ch != '\n' }
fn is_escape_char(ch: char) -> bool { ch == 'n' || ch == 'r' || ch == 't' || ch == '\\' || ch == '"' || ch == '\'' }

fn mk_begin<'a>(s: &'a str) -> Token<'a> { Begin(s) }
fn mk_end<'a>(_: char) -> Token<'a> { End }
fn mk_identifier<'a>(s: &'a str) -> Token<'a> { Identifier(s) }
fn mk_number<'a>(s: &'a str) -> Result<Token<'a>,LexError> { Ok(Number(try!(usize::from_str_radix(s,10)))) }
fn mk_text<'a>(s: &'a str) -> Token<'a> { Text(s) }
fn mk_whitespace<'a>(s: &'a str) -> Token<'a> { Whitespace(s) }

#[allow(non_snake_case)]
pub fn lexer<C,D>(consumer: C) where C: LexerConsumer<D>, D: ErrConsumer<LexError>+for<'a> Consumer<Token<'a>> {
    let BEGIN = character('(').ignore()
        .and_then(character_match(is_keyword_char).plus().buffer())
        .map(mk_begin);
    let END = character(')')
        .map(mk_end);
    let WHITESPACE = character_match(char::is_whitespace).plus().buffer()
        .map(mk_whitespace);
    let IDENTIFIER = character_match(is_identifier_char).plus().buffer()
        .map(mk_identifier);
    let NUMBER = character_match(char::is_numeric).plus().buffer()
        .map(mk_number).results();
    let CHAR = character_match(is_unescaped_char)
        .or_else(character('\\').and_then(character_match(is_escape_char)));
    let TEXT = character('"').ignore()
        .and_then(CHAR.star().buffer())
        .and_then(character('"').ignore())
        .map(mk_text);
    let TOKEN = BEGIN
        .or_else(END)
        .or_else(IDENTIFIER)
        .or_else(NUMBER)
        .or_else(TEXT)
        .or_else(WHITESPACE);
    consumer.accept(TOKEN.star())
}

#[test]
fn test_lexer() {
    struct TestConsumer(Vec<String>,Vec<LexError>);
    impl<'a> Consumer<Token<'a>> for TestConsumer {
        fn accept(&mut self, tok: Token<'a>) {
            self.0.push(String::from(tok));
        }
    }
    impl ErrConsumer<LexError> for TestConsumer {
        fn error(&mut self, err: LexError) {
            self.1.push(err);
        }
    }
    impl LexerConsumer<TestConsumer> for TestConsumer {
        fn accept<L>(mut self, mut lex: L) where L: for<'a> ParseTo<&'a str,TestConsumer> {
            lex.push_to("(a123 $bcd f32 \t \"cd\\r\\nef\\\"gh\" 37)", &mut self);
            assert_eq!(self.0, ["(a123", " ", "$bcd", " ", "f32", " \t ", "\"cd\\r\\nef\\\"gh\"", " ", "37", ")"]);
            assert_eq!(self.1.len(), 0);
        }
    }
    lexer(TestConsumer(Vec::new(),Vec::new()));
}
<|endoftext|>


<commit_before>use std::io::timer;
use std::time::duration;
use std::rand;

use client::PluginRegister;
use events::CommandEvent;

fn help(event: &CommandEvent) {
    let plugins = event.client.plugins.read();
    let commands = plugins.commands.keys().collect::<Vec<&String>>().connect(", ");
    event.client.send_message(event.channel(), format!("Available commands: {}", commands).as_slice());
    event.client.send_message(event.channel(), format!("Use a command with `{}command_name` or `{}, command_name`", event.client.command_prefix, event.client.state.read().nick).as_slice());
}

pub fn register(register: &mut PluginRegister) {
    register.register_command("help", help);
}
<commit_msg>Oops, included some remnants from debugging in help.rs. Removed!<commit_after>use client::PluginRegister;
use events::CommandEvent;

fn help(event: &CommandEvent) {
    let plugins = event.client.plugins.read();
    let commands = plugins.commands.keys().collect::<Vec<&String>>().connect(", ");
    event.client.send_message(event.channel(), format!("Available commands: {}", commands).as_slice());
    event.client.send_message(event.channel(), format!("Use a command with `{}command_name` or `{}, command_name`", event.client.command_prefix, event.client.state.read().nick).as_slice());
}

pub fn register(register: &mut PluginRegister) {
    register.register_command("help", help);
}
<|endoftext|>