<commit_before>#![feature(phase)]

#[phase(plugin)]
extern crate docopt_macros;

extern crate docopt;
extern crate serialize;

use std::io::process::Command;
use std::io::{File, TempDir};

docopt!(Args, "
Usage: rust-to-apk --sdk SDKPATH -o OUTPUT INPUT

Options:
    -h          Print this message
")

fn main() {
    use std::io::fs;

    let args: Args = docopt::FlagParser::parse().unwrap_or_else(|e| e.exit());

    // TODO: check sdk path in ANDROID_HOME if no command line option
    let sdk_path = Path::new(args.arg_SDKPATH);

    let directory = build_directory(&Path::new(args.arg_INPUT), &sdk_path);

    // executing ant
    if Command::new("ant").arg("debug").stdout(std::io::process::InheritFd(1))
        .stderr(std::io::process::InheritFd(2)).cwd(directory.path())
        .status().unwrap() != std::io::process::ExitStatus(0)
    {
        println!("Error while executing ant debug");
        return;
    }

    // copying apk file to OUTPUT
    fs::copy(&directory.path().join("bin").join("rust-android-debug.apk"),
        &Path::new(args.arg_OUTPUT)).unwrap();
}

fn build_directory(library: &Path, sdk_dir: &Path) -> TempDir {
    use std::io::fs;
    use std::os;

    let library = os::make_absolute(library);

    let build_directory = TempDir::new("android-rs-glue-rust-to-apk")
        .expect("Could not create temporary build directory");

    File::create(&build_directory.path().join("AndroidManifest.xml")).unwrap()
        .write_str(build_manifest().as_slice())
        .unwrap();

    File::create(&build_directory.path().join("build.xml")).unwrap()
        .write_str(build_build_xml().as_slice())
        .unwrap();

    File::create(&build_directory.path().join("local.properties")).unwrap()
        .write_str(build_local_properties(sdk_dir).as_slice())
        .unwrap();

    File::create(&build_directory.path().join("project.properties")).unwrap()
        .write_str(build_project_properties().as_slice())
        .unwrap();

    {
        let src_path = build_directory.path().join("src").join("com").join("example")
            .join("native_activity");
        fs::mkdir_recursive(&src_path, std::io::UserRWX).unwrap();
        File::create(&src_path.join("MyNativeActivity.java")).unwrap()
            .write_str(build_java_class(library.filestem_str().unwrap().slice_from(3)).as_slice())
            .unwrap();
    }

    let libs_path = build_directory.path().join("libs").join("armeabi");
    fs::mkdir_recursive(&libs_path, std::io::UserRWX).unwrap();
    fs::copy(&library, &libs_path.join(library.filename_str().unwrap())).unwrap();

    build_directory
}

fn build_manifest() -> String {
    format!(r#"<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.native_activity"
        android:versionCode="1"
        android:versionName="1.0">

    <uses-sdk android:minSdkVersion="18" />

    <application android:label="NativeActivity" android:hasCode="true">
        <activity android:name="com.example.native_activity.MyNativeActivity"
                android:label="NativeActivity"
                android:configChanges="orientation|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<!-- END_INCLUDE(manifest) -->
"#)
}

fn build_build_xml() -> String {
    format!(r#"<?xml version="1.0" encoding="UTF-8"?>
<project name="rust-android" default="help">
    <property file="local.properties" />
    <loadproperties srcFile="project.properties" />
    <import file="custom_rules.xml" optional="true" />
    <import file="${{sdk.dir}}/tools/ant/build.xml" />
</project>
"#)
}

fn build_local_properties(sdk_dir: &Path) -> String {
    use std::os;
    format!(r"sdk.dir={}", os::make_absolute(sdk_dir).display())
}

fn build_project_properties() -> String {
    format!(r"target=android-18")
}

fn build_java_class(libname: &str) -> String {
    format!(r#"
package com.example.native_activity;

import android.app.NativeActivity;
import android.util.Log;

public class MyNativeActivity extends NativeActivity {{
  static {{
    System.loadLibrary("{}");
  }}

  private static String TAG = "MyNativeActivity";

  public MyNativeActivity() {{
    super();
    Log.v(TAG, "Creating MyNativeActivity");
  }}
}}"#, libname)
}
<commit_msg>The library name is now always "main"<commit_after>#![feature(phase)]

#[phase(plugin)]
extern crate docopt_macros;

extern crate docopt;
extern crate serialize;

use std::io::process::Command;
use std::io::{File, TempDir};

docopt!(Args, "
Usage: rust-to-apk --sdk SDKPATH -o OUTPUT INPUT

Options:
    -h          Print this message
")

fn main() {
    use std::io::fs;

    let args: Args = docopt::FlagParser::parse().unwrap_or_else(|e| e.exit());

    // TODO: check sdk path in ANDROID_HOME if no command line option
    let sdk_path = Path::new(args.arg_SDKPATH);

    let directory = build_directory(&Path::new(args.arg_INPUT), &sdk_path);

    // executing ant
    if Command::new("ant").arg("debug").stdout(std::io::process::InheritFd(1))
        .stderr(std::io::process::InheritFd(2)).cwd(directory.path())
        .status().unwrap() != std::io::process::ExitStatus(0)
    {
        println!("Error while executing ant debug");
        return;
    }

    // copying apk file to OUTPUT
    fs::copy(&directory.path().join("bin").join("rust-android-debug.apk"),
        &Path::new(args.arg_OUTPUT)).unwrap();
}

fn build_directory(library: &Path, sdk_dir: &Path) -> TempDir {
    use std::io::fs;
    use std::os;

    let build_directory = TempDir::new("android-rs-glue-rust-to-apk")
        .expect("Could not create temporary build directory");

    File::create(&build_directory.path().join("AndroidManifest.xml")).unwrap()
        .write_str(build_manifest().as_slice())
        .unwrap();

    File::create(&build_directory.path().join("build.xml")).unwrap()
        .write_str(build_build_xml().as_slice())
        .unwrap();

    File::create(&build_directory.path().join("local.properties")).unwrap()
        .write_str(build_local_properties(sdk_dir).as_slice())
        .unwrap();

    File::create(&build_directory.path().join("project.properties")).unwrap()
        .write_str(build_project_properties().as_slice())
        .unwrap();

    {
        let src_path = build_directory.path().join("src").join("com").join("example")
            .join("native_activity");
        fs::mkdir_recursive(&src_path, std::io::UserRWX).unwrap();
        File::create(&src_path.join("MyNativeActivity.java")).unwrap()
            .write_str(build_java_class().as_slice())
            .unwrap();
    }

    {
        let libs_path = build_directory.path().join("libs").join("armeabi");

        fs::mkdir_recursive(&libs_path, std::io::UserRWX).unwrap();
        fs::copy(library, &libs_path.join("libmain.so")).unwrap();
    }

    build_directory
}

fn build_manifest() -> String {
    format!(r#"<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.native_activity"
        android:versionCode="1"
        android:versionName="1.0">

    <uses-sdk android:minSdkVersion="18" />

    <application android:label="NativeActivity" android:hasCode="true">
        <activity android:name="com.example.native_activity.MyNativeActivity"
                android:label="NativeActivity"
                android:configChanges="orientation|keyboardHidden">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
<!-- END_INCLUDE(manifest) -->
"#)
}

fn build_build_xml() -> String {
    format!(r#"<?xml version="1.0" encoding="UTF-8"?>
<project name="rust-android" default="help">
    <property file="local.properties" />
    <loadproperties srcFile="project.properties" />
    <import file="custom_rules.xml" optional="true" />
    <import file="${{sdk.dir}}/tools/ant/build.xml" />
</project>
"#)
}

fn build_local_properties(sdk_dir: &Path) -> String {
    use std::os;
    format!(r"sdk.dir={}", os::make_absolute(sdk_dir).display())
}

fn build_project_properties() -> String {
    format!(r"target=android-18")
}

fn build_java_class() -> String {
    format!(r#"
package com.example.native_activity;

import android.app.NativeActivity;
import android.util.Log;

public class MyNativeActivity extends NativeActivity {{
  static {{
    System.loadLibrary("main");
  }}

  private static String TAG = "MyNativeActivity";

  public MyNativeActivity() {{
    super();
    Log.v(TAG, "Creating MyNativeActivity");
  }}
}}"#)
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

extern crate hyper;
extern crate hyper_native_tls;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate ring;
extern crate rustc_serialize;
pub extern crate rusoto_credential as credential;
extern crate serde;
extern crate time;
extern crate url;
extern crate xml;

pub mod param;
pub mod region;
pub mod request;
pub mod signature;

#[doc(hidden)]
pub mod serialization;
#[doc(hidden)]
pub mod xmlerror;
#[doc(hidden)]
pub mod xmlutil;

pub use credential::{AwsCredentials, ChainProvider, ContainerProvider, CredentialsError,
                     EnvironmentProvider, InstanceMetadataProvider, ProfileProvider,
                     ProvideAwsCredentials, DefaultCredentialsProvider,
                     DefaultCredentialsProviderSync, claims,
                     AutoRefreshingProviderSync, AutoRefreshingProvider,
                     BaseAutoRefreshingProvider};

pub use region::{ParseRegionError, Region, default_region};
pub use request::{DispatchSignedRequest, HttpResponse, HttpDispatchError, TlsError, default_tls_client};
pub use signature::SignedRequest;
<commit_msg>Translate example from
usoto to
usoto_core docs<commit_after>#![cfg_attr(feature = "unstable", feature(proc_macro))]
#![cfg_attr(feature = "nightly-testing", feature(plugin))]
#![cfg_attr(feature = "nightly-testing", plugin(clippy))]
#![cfg_attr(feature = "nightly-testing", allow(cyclomatic_complexity, used_underscore_binding, ptr_arg, suspicious_else_formatting))]
#![allow(dead_code)]
#![cfg_attr(not(feature = "unstable"), deny(warnings))]

//! Rusoto is an [AWS](https://aws.amazon.com/) SDK for Rust.
//! A high level overview is available in `README.md` at https://github.com/rusoto/rusoto.
//!
//! # Example
//!
//! The following code shows a simple example of using Rusoto's DynamoDB API to
//! list the names of all tables in a database.
//!
//! ```rust,ignore
//! use rusoto_core::{DefaultCredentialsProvider, Region};
//! use rusoto_dynamodb::{DynamoDb, DynamoDbClient, ListTablesInput};
//!
//! let provider = DefaultCredentialsProvider::new().unwrap();
//! let client = DynamoDbClient::new(provider, Region::UsEast1);
//! let list_tables_input: ListTablesInput = Default::default();
//!
//! match client.list_tables(&list_tables_input) {
//!     Ok(output) => {
//!         match output.table_names {
//!             Some(table_name_list) => {
//!                 println!("Tables in database:");
//!
//!                 for table_name in table_name_list {
//!                     println!("{}", table_name);
//!                 }
//!             },
//!             None => println!("No tables in database!"),
//!         }
//!     },
//!     Err(error) => {
//!         println!("Error: {:?}", error);
//!     },
//! }

extern crate hyper;
extern crate hyper_native_tls;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate ring;
extern crate rustc_serialize;
pub extern crate rusoto_credential as credential;
extern crate serde;
extern crate time;
extern crate url;
extern crate xml;

pub mod param;
pub mod region;
pub mod request;
pub mod signature;

#[doc(hidden)]
pub mod serialization;
#[doc(hidden)]
pub mod xmlerror;
#[doc(hidden)]
pub mod xmlutil;

pub use credential::{AwsCredentials, ChainProvider, ContainerProvider, CredentialsError,
                     EnvironmentProvider, InstanceMetadataProvider, ProfileProvider,
                     ProvideAwsCredentials, DefaultCredentialsProvider,
                     DefaultCredentialsProviderSync, claims,
                     AutoRefreshingProviderSync, AutoRefreshingProvider,
                     BaseAutoRefreshingProvider};

pub use region::{ParseRegionError, Region, default_region};
pub use request::{DispatchSignedRequest, HttpResponse, HttpDispatchError, TlsError, default_tls_client};
pub use signature::SignedRequest;
<|endoftext|>


<commit_before>use num::traits::{Zero,One};
use std::ops::{Mul,Add,Sub,Div,Index};

use geometry::vector::Vec3;

#[derive(PartialEq,Debug)]
pub struct Matrix44<T> {
    pub m: [[T; 4]; 4],
}

impl <T> Matrix44<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Div<T, Output = T> + Sub<T, Output = T> + Zero + One + PartialEq + Copy + Clone {
    pub fn zero() -> Matrix44<T> {
        Matrix44 { m: [
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()], ]}
    }

    pub fn diagonal(p: T, q: T, r: T, s: T) -> Matrix44<T> {
        Matrix44 { m: [
            [p, T::zero(), T::zero(), T::zero()],
            [T::zero(), q, T::zero(), T::zero()],
            [T::zero(), T::zero(), r, T::zero()],
            [T::zero(), T::zero(), T::zero(), s], ]}
    }

    pub fn new(mm: [[T; 4]; 4]) -> Matrix44<T> {
        Matrix44 { m : mm }
    }

    #[allow(non_snake_case)]
    pub fn multVecMatrix(self, src: &Vec3<T>, dst: &mut Vec3<T>) {
        dst.x = src.x * self.m[0][0] +  src.y * self.m[1][0] +  src.z * self.m[2][0] +  self.m[3][0];
        dst.y = src.x * self.m[0][1] +  src.y * self.m[1][1] +  src.z * self.m[2][1] +  self.m[3][1];
        dst.z = src.x * self.m[0][2] +  src.y * self.m[1][2] +  src.z * self.m[2][2] +  self.m[3][2];
        let w = src.x * self.m[0][3] +  src.y * self.m[1][3] +  src.z * self.m[2][3] +  self.m[3][3];
        if w != T::one() && w != T::zero() {
            dst.x = dst.x / w;
            dst.y = dst.y / w;
            dst.z = dst.z / w;
        }
    }

    #[allow(non_snake_case)]
    pub fn multDirMatrix(self, src: &Vec3<T>, dst: &mut Vec3<T>) {
        dst.x = src.x * self.m[0][0] +  src.y * self.m[1][0] +  src.z * self.m[2][0];
        dst.y = src.x * self.m[0][1] +  src.y * self.m[1][1] +  src.z * self.m[2][1];
        dst.z = src.x * self.m[0][2] +  src.y * self.m[1][2] +  src.z * self.m[2][2];
    }

    pub fn transpose(self) -> Matrix44<T> {
        let mut result: [[T; 4]; 4] = [[T::zero(); 4]; 4];
        for i in 0..4 {
            for j in 0..4 {
                result[i][j] = self[j][i];
            }
        }
        Matrix44::new(result)
    }
}

impl <T> Index<usize> for Matrix44<T> {
    type Output = [T; 4];

    fn index(&self, index: usize) -> &[T; 4] {
       &(self.m[index])
    }
}

impl <T> Mul<Matrix44<T>> for Matrix44<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Div<T, Output = T> + Sub<T, Output = T> + Zero + One + PartialEq + Copy + Clone {
    type Output = Matrix44<T>;

    fn mul(self, rhs: Matrix44<T>) -> Matrix44<T> {
        let mut result: [[T; 4]; 4] = [[T::zero(); 4]; 4];
        for i in 0..4 {
            for j in 0..4 {
                result[i][j] = self[i][0] * rhs[0][j] +
                    self[i][1] * rhs[1][j] +
                    self[i][2] * rhs[2][j] +
                    self[i][3] * rhs[3][j]
            }
        }
        Matrix44::new(result)
    }
}

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

    #[test]
    fn should_be_initialized_as_zero_matrix() {
        let m: Matrix44<f64> = Matrix44::zero();

        assert_eq!(m, Matrix44::<f64> { m: [
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            ]});
    }

    #[test]
    fn should_be_initialized_by_coefficients() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 2.0, 0.0, 0.0],
            [0.0, 0.0, 3.0, 0.0],
            [0.0, 0.0, 4.0, 0.0],
            ]);

        assert_eq!(m, Matrix44::<f64> { m: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 2.0, 0.0, 0.0],
            [0.0, 0.0, 3.0, 0.0],
            [0.0, 0.0, 4.0, 0.0],
            ]});
    }

    #[test]
    fn should_index_rows() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 2.0, 3.0, 4.0],
            [2.0, 3.0, 4.0, 5.0],
            [3.0, 4.0, 5.0, 6.0],
            [4.0, 5.0, 6.0, 7.0], ]);

        let row = m[1];

        assert_eq!(row, [2.0, 3.0, 4.0, 5.0]);
    }

    #[test]
    fn should_matrix_multiply() {
        let m: Matrix44<f64> = Matrix44::diagonal(1.0, 2.0, 3.0, 4.0);
        let n: Matrix44<f64> = Matrix44::diagonal(4.0, 3.0, 2.0, 1.0);

        let product: Matrix44<f64> = m * n;

        assert_eq!(product, Matrix44::<f64> { m: [
            [4.0, 0.0, 0.0, 0.0],
            [0.0, 6.0, 0.0, 0.0],
            [0.0, 0.0, 6.0, 0.0],
            [0.0, 0.0, 0.0, 4.0],
        ]})
    }

    #[test]
    fn should_transform_a_point() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.5, 0.5, 0.5, 1.0],
            ]);
        let v: Vec3<f64> = Vec3::new(1.0, 2.0, 3.0);
        let mut result: Vec3<f64> = Vec3::zero();

        m.multVecMatrix(&v, &mut result);

        assert_eq!(result, Vec3::new(1.5, 2.5, 3.5));
    }

    #[test]
    fn should_transform_a_vector() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.5, 0.5, 0.5, 1.0],
            ]);
        let v: Vec3<f64> = Vec3::new(1.0, 2.0, 3.0);
        let mut result: Vec3<f64> = Vec3::zero();

        m.multDirMatrix(&v, &mut result);

        assert_eq!(result, Vec3::new(1.0, 2.0, 3.0));
    }

    #[test]
    fn should_know_its_transpose() {
         let m: Matrix44<f64> = Matrix44::new([
            [ 1.0,  2.0,  3.0,  4.0],
            [ 5.0,  6.0,  7.0,  8.0],
            [ 9.0, 10.0, 11.0, 12.0],
            [13.0, 14.0, 15.0, 16.0], ]);

        let m_t = m.transpose();

        assert_eq!(m_t, Matrix44::new([
            [ 1.0,  5.0,  9.0, 13.0],
            [ 2.0,  6.0, 10.0, 14.0],
            [ 3.0,  7.0, 11.0, 15.0],
            [ 4.0,  8.0, 12.0, 16.0], ]));
    }
}
<commit_msg>TODO Determinant & Inverse<commit_after>use num::traits::{Zero,One};
use std::ops::{Mul,Add,Sub,Div,Index};

use geometry::vector::Vec3;

#[derive(PartialEq,Debug)]
pub struct Matrix44<T> {
    pub m: [[T; 4]; 4],
}

impl <T> Matrix44<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Div<T, Output = T> + Sub<T, Output = T> + Zero + One + PartialEq + Copy + Clone {
    pub fn zero() -> Matrix44<T> {
        Matrix44 { m: [
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()],
            [T::zero(), T::zero(), T::zero(), T::zero()], ]}
    }

    pub fn diagonal(p: T, q: T, r: T, s: T) -> Matrix44<T> {
        Matrix44 { m: [
            [p, T::zero(), T::zero(), T::zero()],
            [T::zero(), q, T::zero(), T::zero()],
            [T::zero(), T::zero(), r, T::zero()],
            [T::zero(), T::zero(), T::zero(), s], ]}
    }

    pub fn new(mm: [[T; 4]; 4]) -> Matrix44<T> {
        Matrix44 { m : mm }
    }

    #[allow(non_snake_case)]
    pub fn multVecMatrix(self, src: &Vec3<T>, dst: &mut Vec3<T>) {
        dst.x = src.x * self.m[0][0] +  src.y * self.m[1][0] +  src.z * self.m[2][0] +  self.m[3][0];
        dst.y = src.x * self.m[0][1] +  src.y * self.m[1][1] +  src.z * self.m[2][1] +  self.m[3][1];
        dst.z = src.x * self.m[0][2] +  src.y * self.m[1][2] +  src.z * self.m[2][2] +  self.m[3][2];
        let w = src.x * self.m[0][3] +  src.y * self.m[1][3] +  src.z * self.m[2][3] +  self.m[3][3];
        if w != T::one() && w != T::zero() {
            dst.x = dst.x / w;
            dst.y = dst.y / w;
            dst.z = dst.z / w;
        }
    }

    #[allow(non_snake_case)]
    pub fn multDirMatrix(self, src: &Vec3<T>, dst: &mut Vec3<T>) {
        dst.x = src.x * self.m[0][0] +  src.y * self.m[1][0] +  src.z * self.m[2][0];
        dst.y = src.x * self.m[0][1] +  src.y * self.m[1][1] +  src.z * self.m[2][1];
        dst.z = src.x * self.m[0][2] +  src.y * self.m[1][2] +  src.z * self.m[2][2];
    }

    pub fn transpose(self) -> Matrix44<T> {
        let mut result: [[T; 4]; 4] = [[T::zero(); 4]; 4];
        for i in 0..4 {
            for j in 0..4 {
                result[i][j] = self[j][i];
            }
        }
        Matrix44::new(result)
    }

    // TODO Determinant & Inverse
}

impl <T> Index<usize> for Matrix44<T> {
    type Output = [T; 4];

    fn index(&self, index: usize) -> &[T; 4] {
       &(self.m[index])
    }
}

impl <T> Mul<Matrix44<T>> for Matrix44<T> where T: Mul<T, Output = T> + Add<T, Output = T> + Div<T, Output = T> + Sub<T, Output = T> + Zero + One + PartialEq + Copy + Clone {
    type Output = Matrix44<T>;

    fn mul(self, rhs: Matrix44<T>) -> Matrix44<T> {
        let mut result: [[T; 4]; 4] = [[T::zero(); 4]; 4];
        for i in 0..4 {
            for j in 0..4 {
                result[i][j] = self[i][0] * rhs[0][j] +
                    self[i][1] * rhs[1][j] +
                    self[i][2] * rhs[2][j] +
                    self[i][3] * rhs[3][j]
            }
        }
        Matrix44::new(result)
    }
}

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

    #[test]
    fn should_be_initialized_as_zero_matrix() {
        let m: Matrix44<f64> = Matrix44::zero();

        assert_eq!(m, Matrix44::<f64> { m: [
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            ]});
    }

    #[test]
    fn should_be_initialized_by_coefficients() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 2.0, 0.0, 0.0],
            [0.0, 0.0, 3.0, 0.0],
            [0.0, 0.0, 4.0, 0.0],
            ]);

        assert_eq!(m, Matrix44::<f64> { m: [
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 2.0, 0.0, 0.0],
            [0.0, 0.0, 3.0, 0.0],
            [0.0, 0.0, 4.0, 0.0],
            ]});
    }

    #[test]
    fn should_index_rows() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 2.0, 3.0, 4.0],
            [2.0, 3.0, 4.0, 5.0],
            [3.0, 4.0, 5.0, 6.0],
            [4.0, 5.0, 6.0, 7.0], ]);

        let row = m[1];

        assert_eq!(row, [2.0, 3.0, 4.0, 5.0]);
    }

    #[test]
    fn should_matrix_multiply() {
        let m: Matrix44<f64> = Matrix44::diagonal(1.0, 2.0, 3.0, 4.0);
        let n: Matrix44<f64> = Matrix44::diagonal(4.0, 3.0, 2.0, 1.0);

        let product: Matrix44<f64> = m * n;

        assert_eq!(product, Matrix44::<f64> { m: [
            [4.0, 0.0, 0.0, 0.0],
            [0.0, 6.0, 0.0, 0.0],
            [0.0, 0.0, 6.0, 0.0],
            [0.0, 0.0, 0.0, 4.0],
        ]})
    }

    #[test]
    fn should_transform_a_point() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.5, 0.5, 0.5, 1.0],
            ]);
        let v: Vec3<f64> = Vec3::new(1.0, 2.0, 3.0);
        let mut result: Vec3<f64> = Vec3::zero();

        m.multVecMatrix(&v, &mut result);

        assert_eq!(result, Vec3::new(1.5, 2.5, 3.5));
    }

    #[test]
    fn should_transform_a_vector() {
        let m: Matrix44<f64> = Matrix44::new([
            [1.0, 0.0, 0.0, 0.0],
            [0.0, 1.0, 0.0, 0.0],
            [0.0, 0.0, 1.0, 0.0],
            [0.5, 0.5, 0.5, 1.0],
            ]);
        let v: Vec3<f64> = Vec3::new(1.0, 2.0, 3.0);
        let mut result: Vec3<f64> = Vec3::zero();

        m.multDirMatrix(&v, &mut result);

        assert_eq!(result, Vec3::new(1.0, 2.0, 3.0));
    }

    #[test]
    fn should_know_its_transpose() {
         let m: Matrix44<f64> = Matrix44::new([
            [ 1.0,  2.0,  3.0,  4.0],
            [ 5.0,  6.0,  7.0,  8.0],
            [ 9.0, 10.0, 11.0, 12.0],
            [13.0, 14.0, 15.0, 16.0], ]);

        let m_t = m.transpose();

        assert_eq!(m_t, Matrix44::new([
            [ 1.0,  5.0,  9.0, 13.0],
            [ 2.0,  6.0, 10.0, 14.0],
            [ 3.0,  7.0, 11.0, 15.0],
            [ 4.0,  8.0, 12.0, 16.0], ]));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ops::Deref;

use util::BufferFromTree;
use uil_shared::asset::ImageData;
use uil_shared::properties::PropertyName;
use uil_shared::properties::STYLE_PROPERTIES;
use uil_shared::style::Value;
use uil_shared::style::KwValue;
use uil_shared::style::Stylesheet;
use uil_shared::style::SelectorState;
use uil_shared::style::Unit;
use uil_shared::style::Rule;
use uil_shared::markup::Node;
use rendering::TextureRule;

pub struct StateBuffer {
    state_data: BufferFromTree<StateData>,
}

impl Deref for StateBuffer {
    type Target = BufferFromTree<StateData>;

    fn deref<'a>(&'a self) -> &'a BufferFromTree<StateData> {
        &self.state_data
    }
}

impl StateBuffer {

    pub fn new(tree: &Node, style_sheet: &Stylesheet) -> StateBuffer {

        let size = tree.tree_size();

        let converter = |node: &Node| {
            Some(StateData::new(node, style_sheet))
        };

        StateBuffer {
            state_data: BufferFromTree::new(tree, size, converter)
        }
    }
}

pub struct StateData {
    default_properties: HashMap<PropertyName, Value>,
    focus_properties: HashMap<PropertyName, Value>,
    hover_properties: HashMap<PropertyName, Value>,
    creation_properties: HashMap<PropertyName, Value>,
}

// ======================================== //
//                  HELPERS                 //
// ======================================== //

// Thanks to lastest rustc nightly macros can't be
// defined at the end of the file anymore. Shame.
macro_rules! return_length_or_zero {

    ($this:ident try $prop_name:ident) => {
        return_length_or_zero!(rec $this try $prop_name else { 0f32 });
    };

    ($this:ident try $prop_name:ident else $other:ident) => {
        return_length_or_zero!(rec $this try $prop_name else {
            return_length_or_zero!(rec $this try $other else { 0f32 })
        });
    };

    (rec $this:ident try $prop_name:ident else $none_case:block) => {
        match $this.default_properties.get(&$prop_name) {
            Some(v) => {
                if let Value::Length(val, Unit::Px) = *v {
                    val
                } else {
                    0f32
                }
            }
            None => $none_case
        }
    };
}

impl StateData {

    fn new(node: &Node, style: &Stylesheet) -> StateData {

        let mut state = StateData {
            default_properties: HashMap::new(),
            focus_properties: HashMap::new(),
            hover_properties: HashMap::new(),
            creation_properties: HashMap::new(),
        };

        state.set_properties(node, style);

        state
    }

    pub fn has_property_expand(&self, prop_name: PropertyName) -> bool {
        self.has_property_eq_kw(prop_name, KwValue::Expand)
    }

    pub fn has_property_auto(&self, prop_name: PropertyName) -> bool {
        self.has_property_eq_kw(prop_name, KwValue::Auto)
    }

    pub fn has_property_eq_kw(&self, prop_name: PropertyName, kw: KwValue) -> bool {
        match self.default_properties.get(&prop_name) {
            Some(&Value::Keyword(v)) if v == kw => {
                true
            },
            _ => false
        }
    }

    pub fn get_background_rule(&self) -> Option<TextureRule> {
        match self.default_properties.get(&PropertyName::BACKGROUND_IMAGE_RULE) {
            Some(&Value::Keyword(v)) => match v {
                KwValue::Fit => Some(TextureRule::Fit),
                KwValue::Repeat => Some(TextureRule::Repeat),
                _ => None
            },
            _ => None
        }
    }

    pub fn get_background_image(&self) -> Option<ImageData> {
        match self.default_properties.get(&PropertyName::BACKGROUND_IMAGE) {
            Some(&Value::Image(ref id)) => Some(id.clone()),
            _ => None
        }
    }

    pub fn size_prop_as_opt(&self, prop_name: PropertyName) -> Option<f32> {
        match self.default_properties.get(&prop_name) {
            Some(v) => {
                if let Value::Length(val, Unit::Px) = *v {
                    Some(val)
                } else {
                    None
                }
            }
            None => None
        }
    }

    pub fn size_of_prop(&self, prop_name: PropertyName) -> f32 {
        use uil_shared::properties::PropertyName::MARGIN;
        use uil_shared::properties::PropertyName::PADDING;
        use uil_shared::properties::PropertyName::BORDER;

        match prop_name {
            PropertyName::LEFT
            | PropertyName::RIGHT
            | PropertyName::TOP
            | PropertyName::BOTTOM
            | PropertyName::HEIGHT
            | PropertyName::WIDTH => {
                return_length_or_zero!(self try prop_name)
            }
            PropertyName::MARGIN_LEFT
            | PropertyName::MARGIN_RIGHT
            | PropertyName::MARGIN_TOP
            | PropertyName::MARGIN_BOTTOM => {
                return_length_or_zero!(self try prop_name else MARGIN)
            }
            PropertyName::PADDING_LEFT
            | PropertyName::PADDING_RIGHT
            | PropertyName::PADDING_TOP
            | PropertyName::PADDING_BOTTOM => {
                return_length_or_zero!(self try prop_name else PADDING)
            }
            PropertyName::BORDER_LEFT
            | PropertyName::BORDER_RIGHT
            | PropertyName::BORDER_TOP
            | PropertyName::BORDER_BOTTOM => {
                return_length_or_zero!(self try prop_name else BORDER)
            }
            _ => panic!()
        }
    }

    fn set_properties(&mut self, node: &Node, style: &Stylesheet) {
        let classes = node.classes();
        // We loop over rules because at some
        // point, we might want to sort them based
        // on specificity in the same way that it is done
        // in CSS. It would help understanding which
        // rule does define a particular property.
        // Thus the code below wouldn't change.
        for rule in style.rules.iter() {
            // FIXME:
            // using deref instead of as_ref because
            // of an inference problem.
            if classes.contains(rule.selector.name.deref()) {

                let ref mut properties = match rule.selector.state {
                    SelectorState::Focus => &mut self.focus_properties,
                    SelectorState::Hover => &mut self.hover_properties,
                    SelectorState::Creation => &mut self.creation_properties,
                    SelectorState::Default => &mut self.default_properties
                };
                // Loop over declaration in the rule.
                // If some properties are declared multiple times
                // the order matters here.
                StateData::set_properties_for_hashmap(
                    properties,
                    rule
                );
            }
        }
    }

    fn set_properties_for_hashmap(
        properties: &mut HashMap<PropertyName, Value>,
        rule: &Rule)
    {
        for dec in rule.declarations.iter() {

            if let Some(property) = STYLE_PROPERTIES.get(dec.name.deref()) {

                properties.insert(*property, dec.value.clone());
            }
        }
    }
}
<commit_msg>Added set_current_state to StateData.<commit_after>use std::collections::HashMap;
use std::ops::Deref;

use util::BufferFromTree;
use uil_shared::asset::ImageData;
use uil_shared::properties::PropertyName;
use uil_shared::properties::STYLE_PROPERTIES;
use uil_shared::style::Value;
use uil_shared::style::KwValue;
use uil_shared::style::Stylesheet;
use uil_shared::style::SelectorState;
use uil_shared::style::Unit;
use uil_shared::style::Rule;
use uil_shared::markup::Node;
use rendering::TextureRule;

pub struct StateBuffer {
    state_data: BufferFromTree<StateData>,
}

impl Deref for StateBuffer {
    type Target = BufferFromTree<StateData>;

    fn deref<'a>(&'a self) -> &'a BufferFromTree<StateData> {
        &self.state_data
    }
}

impl StateBuffer {

    pub fn new(tree: &Node, style_sheet: &Stylesheet) -> StateBuffer {

        let size = tree.tree_size();

        let converter = |node: &Node| {
            Some(StateData::new(node, style_sheet))
        };

        StateBuffer {
            state_data: BufferFromTree::new(tree, size, converter)
        }
    }
}

pub struct StateData {
    default_properties: HashMap<PropertyName, Value>,
    focus_properties: HashMap<PropertyName, Value>,
    hover_properties: HashMap<PropertyName, Value>,
    creation_properties: HashMap<PropertyName, Value>,
    current_state: SelectorState,
}

// ======================================== //
//                  HELPERS                 //
// ======================================== //

// Thanks to lastest rustc nightly macros can't be
// defined at the end of the file anymore. Shame.
macro_rules! return_length_or_zero {

    ($this:ident try $prop_name:ident) => {
        return_length_or_zero!(rec $this try $prop_name else {
            return_length_or_zero!(rec_default $this try $prop_name else { 0f32 })
        });
    };

    ($this:ident try $prop_name:ident else $other:ident) => {
        return_length_or_zero!(rec $this try $prop_name else {
            return_length_or_zero!(rec $this try $other else {
                return_length_or_zero!(rec_default $this try $prop_name else {
                    return_length_or_zero!(rec_default $this try $other else { 0f32 })
                })
            })
        });
    };

    (rec $this:ident try $prop_name:ident else $none_case:block) => {
        match $this.current_properties().get(&$prop_name) {
            Some(v) => {
                if let Value::Length(val, Unit::Px) = *v {
                    val
                } else {
                    0f32
                }
            }
            None => $none_case
        }
    };

    (rec_default $this:ident try $prop_name:ident else $none_case:block) => {
        match $this.default_properties.get(&$prop_name) {
            Some(v) => {
                if let Value::Length(val, Unit::Px) = *v {
                    val
                } else {
                    0f32
                }
            }
            None => $none_case
        }
    };
}

impl StateData {

    fn new(node: &Node, style: &Stylesheet) -> StateData {

        let mut state = StateData {
            default_properties: HashMap::new(),
            focus_properties: HashMap::new(),
            hover_properties: HashMap::new(),
            creation_properties: HashMap::new(),
            current_state: SelectorState::Default
        };

        state.set_properties(node, style);

        state
    }

    pub fn set_current_state(&mut self, new_state: SelectorState) {
        self.current_state = new_state;
    }

    pub fn has_property_expand(&self, prop_name: PropertyName) -> bool {
        self.has_property_eq_kw(prop_name, KwValue::Expand)
    }

    pub fn has_property_auto(&self, prop_name: PropertyName) -> bool {
        self.has_property_eq_kw(prop_name, KwValue::Auto)
    }

    pub fn has_property_eq_kw(&self, prop_name: PropertyName, kw: KwValue) -> bool {
        match self.current_properties().get(&prop_name) {
            Some(&Value::Keyword(v)) if v == kw => {
                true
            },
            _ => match self.default_properties.get(&prop_name) {
                Some(&Value::Keyword(v)) if v == kw => {
                    true
                },
                _ => false
            }
        }
    }

    pub fn get_background_rule(&self) -> Option<TextureRule> {
        match self.current_properties().get(&PropertyName::BACKGROUND_IMAGE_RULE) {
            Some(&Value::Keyword(v)) => match v {
                KwValue::Fit => Some(TextureRule::Fit),
                KwValue::Repeat => Some(TextureRule::Repeat),
                _ => None
            },
            _ => match self.default_properties.get(&PropertyName::BACKGROUND_IMAGE_RULE) {
                Some(&Value::Keyword(v)) => match v {
                    KwValue::Fit => Some(TextureRule::Fit),
                    KwValue::Repeat => Some(TextureRule::Repeat),
                    _ => None
                },
                _ => None
            }
        }
    }

    pub fn get_background_image(&self) -> Option<ImageData> {
        match self.current_properties().get(&PropertyName::BACKGROUND_IMAGE) {
            Some(&Value::Image(ref id)) => Some(id.clone()),
            _ => match self.default_properties.get(&PropertyName::BACKGROUND_IMAGE) {
                Some(&Value::Image(ref id)) => Some(id.clone()),
                _ => None
            }
        }
    }

    pub fn size_prop_as_opt(&self, prop_name: PropertyName) -> Option<f32> {
        match self.current_properties().get(&prop_name) {
            Some(v) => {
                if let Value::Length(val, Unit::Px) = *v {
                    Some(val)
                } else {
                    None
                }
            }
            None => match self.default_properties.get(&prop_name) {
                Some(v) => {
                    if let Value::Length(val, Unit::Px) = *v {
                        Some(val)
                    } else {
                        None
                    }
                }
                None => None
            }
        }
    }

    pub fn size_of_prop(&self, prop_name: PropertyName) -> f32 {
        use uil_shared::properties::PropertyName::MARGIN;
        use uil_shared::properties::PropertyName::PADDING;
        use uil_shared::properties::PropertyName::BORDER;

        match prop_name {
            PropertyName::LEFT
            | PropertyName::RIGHT
            | PropertyName::TOP
            | PropertyName::BOTTOM
            | PropertyName::HEIGHT
            | PropertyName::WIDTH => {
                return_length_or_zero!(self try prop_name)
            }
            PropertyName::MARGIN_LEFT
            | PropertyName::MARGIN_RIGHT
            | PropertyName::MARGIN_TOP
            | PropertyName::MARGIN_BOTTOM => {
                return_length_or_zero!(self try prop_name else MARGIN)
            }
            PropertyName::PADDING_LEFT
            | PropertyName::PADDING_RIGHT
            | PropertyName::PADDING_TOP
            | PropertyName::PADDING_BOTTOM => {
                return_length_or_zero!(self try prop_name else PADDING)
            }
            PropertyName::BORDER_LEFT
            | PropertyName::BORDER_RIGHT
            | PropertyName::BORDER_TOP
            | PropertyName::BORDER_BOTTOM => {
                return_length_or_zero!(self try prop_name else BORDER)
            }
            _ => panic!()
        }
    }

    fn current_properties<'a>(&'a self) -> &HashMap<PropertyName, Value> {
        match self.current_state {
            SelectorState::Focus => &self.focus_properties,
            SelectorState::Hover => &self.hover_properties,
            SelectorState::Creation => &self.creation_properties,
            SelectorState::Default => &self.default_properties,
        }
    }

    fn set_properties(&mut self, node: &Node, style: &Stylesheet) {
        let classes = node.classes();
        // We loop over rules because at some
        // point, we might want to sort them based
        // on specificity in the same way that it is done
        // in CSS. It would help understanding which
        // rule does define a particular property.
        // Thus the code below wouldn't change.
        for rule in style.rules.iter() {
            // FIXME:
            // using deref instead of as_ref because
            // of an inference problem.
            if classes.contains(rule.selector.name.deref()) {

                let ref mut properties = match rule.selector.state {
                    SelectorState::Focus => &mut self.focus_properties,
                    SelectorState::Hover => &mut self.hover_properties,
                    SelectorState::Creation => &mut self.creation_properties,
                    SelectorState::Default => &mut self.default_properties
                };
                // Loop over declaration in the rule.
                // If some properties are declared multiple times
                // the order matters here.
                StateData::set_properties_for_hashmap(
                    properties,
                    rule
                );
            }
        }
    }

    fn set_properties_for_hashmap(
        properties: &mut HashMap<PropertyName, Value>,
        rule: &Rule)
    {
        for dec in rule.declarations.iter() {

            if let Some(property) = STYLE_PROPERTIES.get(dec.name.deref()) {

                properties.insert(*property, dec.value.clone());
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Checks for needless address of operations (`&`)
//!
//! This lint is **warn** by default

use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet_opt, snippet_with_applicability, snippet_with_context};
use clippy_utils::{get_parent_expr, in_macro, path_to_local};
use if_chain::if_chain;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for address of operations (`&`) that are going to
    /// be dereferenced immediately by the compiler.
    ///
    /// ### Why is this bad?
    /// Suggests that the receiver of the expression borrows
    /// the expression.
    ///
    /// ### Example
    /// ```rust
    /// fn fun(_a: &i32) {}
    ///
    /// // Bad
    /// let x: &i32 = &&&&&&5;
    /// fun(&x);
    ///
    /// // Good
    /// let x: &i32 = &5;
    /// fun(x);
    /// ```
    pub NEEDLESS_BORROW,
    style,
    "taking a reference that is going to be automatically dereferenced"
}

declare_clippy_lint! {
    /// ### What it does
    /// Checks for `ref` bindings which create a reference to a reference.
    ///
    /// ### Why is this bad?
    /// The address-of operator at the use site is clearer about the need for a reference.
    ///
    /// ### Example
    /// ```rust
    /// // Bad
    /// let x = Some("");
    /// if let Some(ref x) = x {
    ///     // use `x` here
    /// }
    ///
    /// // Good
    /// let x = Some("");
    /// if let Some(x) = x {
    ///     // use `&x` here
    /// }
    /// ```
    pub REF_BINDING_TO_REFERENCE,
    pedantic,
    "`ref` binding to a reference"
}

impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE]);
#[derive(Default)]
pub struct NeedlessBorrow {
    /// The body the first local was found in. Used to emit lints when the traversal of the body has
    /// been finished. Note we can't lint at the end of every body as they can be nested within each
    /// other.
    current_body: Option<BodyId>,
    /// The list of locals currently being checked by the lint.
    /// If the value is `None`, then the binding has been seen as a ref pattern, but is not linted.
    /// This is needed for or patterns where one of the branches can be linted, but another can not
    /// be.
    ///
    /// e.g. `m!(x) | Foo::Bar(ref x)`
    ref_locals: FxIndexMap<HirId, Option<RefPat>>,
}

struct RefPat {
    /// Whether every usage of the binding is dereferenced.
    always_deref: bool,
    /// The spans of all the ref bindings for this local.
    spans: Vec<Span>,
    /// The applicability of this suggestion.
    app: Applicability,
    /// All the replacements which need to be made.
    replacements: Vec<(Span, String)>,
}

impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
        if let Some(local) = path_to_local(e) {
            self.check_local_usage(cx, e, local);
        }

        if e.span.from_expansion() {
            return;
        }
        if let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = e.kind {
            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() {
                for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) {
                    if let [Adjustment {
                        kind: Adjust::Deref(_), ..
                    }, Adjustment {
                        kind: Adjust::Deref(_), ..
                    }, Adjustment {
                        kind: Adjust::Borrow(_),
                        ..
                    }] = *adj3
                    {
                        span_lint_and_then(
                            cx,
                            NEEDLESS_BORROW,
                            e.span,
                            &format!(
                                "this expression borrows a reference (`&{}`) that is immediately dereferenced \
                             by the compiler",
                                ty
                            ),
                            |diag| {
                                if let Some(snippet) = snippet_opt(cx, inner.span) {
                                    diag.span_suggestion(
                                        e.span,
                                        "change this to",
                                        snippet,
                                        Applicability::MachineApplicable,
                                    );
                                }
                            },
                        );
                    }
                }
            }
        }
    }

    fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
        if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind {
            if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
                // This binding id has been seen before. Add this pattern to the list of changes.
                if let Some(prev_pat) = opt_prev_pat {
                    if in_macro(pat.span) {
                        // Doesn't match the context of the previous pattern. Can't lint here.
                        *opt_prev_pat = None;
                    } else {
                        prev_pat.spans.push(pat.span);
                        prev_pat.replacements.push((
                            pat.span,
                            snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut prev_pat.app)
                                .0
                                .into(),
                        ));
                    }
                }
                return;
            }

            if_chain! {
                if !in_macro(pat.span);
                if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
                // only lint immutable refs, because borrowed `&mut T` cannot be moved out
                if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
                then {
                    let mut app = Applicability::MachineApplicable;
                    let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
                    self.current_body = self.current_body.or(cx.enclosing_body);
                    self.ref_locals.insert(
                        id,
                        Some(RefPat {
                            always_deref: true,
                            spans: vec![pat.span],
                            app,
                            replacements: vec![(pat.span, snip.into())],
                        }),
                    );
                }
            }
        }
    }

    fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
        if Some(body.id()) == self.current_body {
            for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) {
                let replacements = pat.replacements;
                let app = pat.app;
                span_lint_and_then(
                    cx,
                    if pat.always_deref {
                        NEEDLESS_BORROW
                    } else {
                        REF_BINDING_TO_REFERENCE
                    },
                    pat.spans,
                    "this pattern creates a reference to a reference",
                    |diag| {
                        diag.multipart_suggestion("try this", replacements, app);
                    },
                );
            }
            self.current_body = None;
        }
    }
}
impl NeedlessBorrow {
    fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, local: HirId) {
        if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
            if let Some(pat) = outer_pat {
                // Check for auto-deref
                if !matches!(
                    cx.typeck_results().expr_adjustments(e),
                    [
                        Adjustment {
                            kind: Adjust::Deref(_),
                            ..
                        },
                        Adjustment {
                            kind: Adjust::Deref(_),
                            ..
                        },
                        ..
                    ]
                ) {
                    match get_parent_expr(cx, e) {
                        // Field accesses are the same no matter the number of references.
                        Some(Expr {
                            kind: ExprKind::Field(..),
                            ..
                        }) => (),
                        Some(&Expr {
                            span,
                            kind: ExprKind::Unary(UnOp::Deref, _),
                            ..
                        }) if !in_macro(span) => {
                            // Remove explicit deref.
                            let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
                            pat.replacements.push((span, snip.into()));
                        },
                        Some(parent) if !in_macro(parent.span) => {
                            // Double reference might be needed at this point.
                            if parent.precedence().order() == PREC_POSTFIX {
                                // Parentheses would be needed here, don't lint.
                                *outer_pat = None;
                            } else {
                                pat.always_deref = false;
                                let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
                                pat.replacements.push((e.span, format!("&{}", snip)));
                            }
                        },
                        _ if !in_macro(e.span) => {
                            // Double reference might be needed at this point.
                            pat.always_deref = false;
                            let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
                            pat.replacements.push((e.span, format!("&{}", snip)));
                        },
                        // Edge case for macros. The span of the identifier will usually match the context of the
                        // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
                        // macros
                        _ => *outer_pat = None,
                    }
                }
            }
        }
    }
}
<commit_msg>Fix `needless_borrow` not linting mutable reference<commit_after>//! Checks for needless address of operations (`&`)
//!
//! This lint is **warn** by default

use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{snippet_opt, snippet_with_applicability, snippet_with_context};
use clippy_utils::{get_parent_expr, in_macro, path_to_local};
use if_chain::if_chain;
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::Applicability;
use rustc_hir::{BindingAnnotation, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;

declare_clippy_lint! {
    /// ### What it does
    /// Checks for address of operations (`&`) that are going to
    /// be dereferenced immediately by the compiler.
    ///
    /// ### Why is this bad?
    /// Suggests that the receiver of the expression borrows
    /// the expression.
    ///
    /// ### Example
    /// ```rust
    /// fn fun(_a: &i32) {}
    ///
    /// // Bad
    /// let x: &i32 = &&&&&&5;
    /// fun(&x);
    ///
    /// // Good
    /// let x: &i32 = &5;
    /// fun(x);
    /// ```
    pub NEEDLESS_BORROW,
    style,
    "taking a reference that is going to be automatically dereferenced"
}

declare_clippy_lint! {
    /// ### What it does
    /// Checks for `ref` bindings which create a reference to a reference.
    ///
    /// ### Why is this bad?
    /// The address-of operator at the use site is clearer about the need for a reference.
    ///
    /// ### Example
    /// ```rust
    /// // Bad
    /// let x = Some("");
    /// if let Some(ref x) = x {
    ///     // use `x` here
    /// }
    ///
    /// // Good
    /// let x = Some("");
    /// if let Some(x) = x {
    ///     // use `&x` here
    /// }
    /// ```
    pub REF_BINDING_TO_REFERENCE,
    pedantic,
    "`ref` binding to a reference"
}

impl_lint_pass!(NeedlessBorrow => [NEEDLESS_BORROW, REF_BINDING_TO_REFERENCE]);
#[derive(Default)]
pub struct NeedlessBorrow {
    /// The body the first local was found in. Used to emit lints when the traversal of the body has
    /// been finished. Note we can't lint at the end of every body as they can be nested within each
    /// other.
    current_body: Option<BodyId>,
    /// The list of locals currently being checked by the lint.
    /// If the value is `None`, then the binding has been seen as a ref pattern, but is not linted.
    /// This is needed for or patterns where one of the branches can be linted, but another can not
    /// be.
    ///
    /// e.g. `m!(x) | Foo::Bar(ref x)`
    ref_locals: FxIndexMap<HirId, Option<RefPat>>,
}

struct RefPat {
    /// Whether every usage of the binding is dereferenced.
    always_deref: bool,
    /// The spans of all the ref bindings for this local.
    spans: Vec<Span>,
    /// The applicability of this suggestion.
    app: Applicability,
    /// All the replacements which need to be made.
    replacements: Vec<(Span, String)>,
}

impl<'tcx> LateLintPass<'tcx> for NeedlessBorrow {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
        if let Some(local) = path_to_local(e) {
            self.check_local_usage(cx, e, local);
        }

        if e.span.from_expansion() {
            return;
        }
        if let ExprKind::AddrOf(BorrowKind::Ref, mutability, inner) = e.kind {
            if let ty::Ref(_, ty, _) = cx.typeck_results().expr_ty(inner).kind() {
                for adj3 in cx.typeck_results().expr_adjustments(e).windows(3) {
                    if let [Adjustment {
                        kind: Adjust::Deref(_), ..
                    }, Adjustment {
                        kind: Adjust::Deref(_), ..
                    }, Adjustment {
                        kind: Adjust::Borrow(_),
                        ..
                    }] = *adj3
                    {
                        let help_msg_ty = if matches!(mutability, Mutability::Not) {
                            format!("&{}", ty)
                        } else {
                            format!("&mut {}", ty)
                        };

                        span_lint_and_then(
                            cx,
                            NEEDLESS_BORROW,
                            e.span,
                            &format!(
                                "this expression borrows a reference (`{}`) that is immediately dereferenced \
                             by the compiler",
                                help_msg_ty
                            ),
                            |diag| {
                                if let Some(snippet) = snippet_opt(cx, inner.span) {
                                    diag.span_suggestion(
                                        e.span,
                                        "change this to",
                                        snippet,
                                        Applicability::MachineApplicable,
                                    );
                                }
                            },
                        );
                    }
                }
            }
        }
    }

    fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
        if let PatKind::Binding(BindingAnnotation::Ref, id, name, _) = pat.kind {
            if let Some(opt_prev_pat) = self.ref_locals.get_mut(&id) {
                // This binding id has been seen before. Add this pattern to the list of changes.
                if let Some(prev_pat) = opt_prev_pat {
                    if in_macro(pat.span) {
                        // Doesn't match the context of the previous pattern. Can't lint here.
                        *opt_prev_pat = None;
                    } else {
                        prev_pat.spans.push(pat.span);
                        prev_pat.replacements.push((
                            pat.span,
                            snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut prev_pat.app)
                                .0
                                .into(),
                        ));
                    }
                }
                return;
            }

            if_chain! {
                if !in_macro(pat.span);
                if let ty::Ref(_, tam, _) = *cx.typeck_results().pat_ty(pat).kind();
                // only lint immutable refs, because borrowed `&mut T` cannot be moved out
                if let ty::Ref(_, _, Mutability::Not) = *tam.kind();
                then {
                    let mut app = Applicability::MachineApplicable;
                    let snip = snippet_with_context(cx, name.span, pat.span.ctxt(), "..", &mut app).0;
                    self.current_body = self.current_body.or(cx.enclosing_body);
                    self.ref_locals.insert(
                        id,
                        Some(RefPat {
                            always_deref: true,
                            spans: vec![pat.span],
                            app,
                            replacements: vec![(pat.span, snip.into())],
                        }),
                    );
                }
            }
        }
    }

    fn check_body_post(&mut self, cx: &LateContext<'tcx>, body: &'tcx Body<'_>) {
        if Some(body.id()) == self.current_body {
            for pat in self.ref_locals.drain(..).filter_map(|(_, x)| x) {
                let replacements = pat.replacements;
                let app = pat.app;
                span_lint_and_then(
                    cx,
                    if pat.always_deref {
                        NEEDLESS_BORROW
                    } else {
                        REF_BINDING_TO_REFERENCE
                    },
                    pat.spans,
                    "this pattern creates a reference to a reference",
                    |diag| {
                        diag.multipart_suggestion("try this", replacements, app);
                    },
                );
            }
            self.current_body = None;
        }
    }
}
impl NeedlessBorrow {
    fn check_local_usage(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>, local: HirId) {
        if let Some(outer_pat) = self.ref_locals.get_mut(&local) {
            if let Some(pat) = outer_pat {
                // Check for auto-deref
                if !matches!(
                    cx.typeck_results().expr_adjustments(e),
                    [
                        Adjustment {
                            kind: Adjust::Deref(_),
                            ..
                        },
                        Adjustment {
                            kind: Adjust::Deref(_),
                            ..
                        },
                        ..
                    ]
                ) {
                    match get_parent_expr(cx, e) {
                        // Field accesses are the same no matter the number of references.
                        Some(Expr {
                            kind: ExprKind::Field(..),
                            ..
                        }) => (),
                        Some(&Expr {
                            span,
                            kind: ExprKind::Unary(UnOp::Deref, _),
                            ..
                        }) if !in_macro(span) => {
                            // Remove explicit deref.
                            let snip = snippet_with_context(cx, e.span, span.ctxt(), "..", &mut pat.app).0;
                            pat.replacements.push((span, snip.into()));
                        },
                        Some(parent) if !in_macro(parent.span) => {
                            // Double reference might be needed at this point.
                            if parent.precedence().order() == PREC_POSTFIX {
                                // Parentheses would be needed here, don't lint.
                                *outer_pat = None;
                            } else {
                                pat.always_deref = false;
                                let snip = snippet_with_context(cx, e.span, parent.span.ctxt(), "..", &mut pat.app).0;
                                pat.replacements.push((e.span, format!("&{}", snip)));
                            }
                        },
                        _ if !in_macro(e.span) => {
                            // Double reference might be needed at this point.
                            pat.always_deref = false;
                            let snip = snippet_with_applicability(cx, e.span, "..", &mut pat.app);
                            pat.replacements.push((e.span, format!("&{}", snip)));
                        },
                        // Edge case for macros. The span of the identifier will usually match the context of the
                        // binding, but not if the identifier was created in a macro. e.g. `concat_idents` and proc
                        // macros
                        _ => *outer_pat = None,
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate rgen3_save;
extern crate env_logger;

use rgen3_save::Save;
use std::io::prelude::*;
use std::io::Cursor;
use std::fs::File;

#[test]
fn identity() {
    env_logger::init().unwrap();
    let paths = std::env::var("RGEN3_TEST_SAVES")
        .expect("Need RGEN3_TEST_SAVES env var set to a path");
    let paths = paths.split(';');
    for path in paths {
        let mut file = File::open(path).unwrap();
        const SAVE_LEN: usize = 131072;
        // Rust's test runner has small stacks, so gotta use vec instead of array.
        let mut data = vec![0; SAVE_LEN];
        file.read_exact(&mut data[..]).unwrap();
        let mut save = Save::read(&mut Cursor::new(&data[..])).unwrap();
        let mut writeout = vec![0; SAVE_LEN];
        {
            let mut writer = &mut writeout[..];
            save.write(&mut writer).unwrap();
        }
        for (i, (&b1, &b2)) in data.iter().zip(&writeout[..]).enumerate() {
            if b1 != b2 {
                panic!("Mismatch: {} (orig) vs {} (new) @ {} (0x{:X})",
                    b1,
                    b2,
                    i,
                    i);
            }
        }
    }
}
<commit_msg>tests/identity: Factor out data comparison into a function<commit_after>extern crate rgen3_save;
extern crate env_logger;

use rgen3_save::Save;
use std::io::prelude::*;
use std::io::Cursor;
use std::fs::File;

fn cmp(a: &[u8], b: &[u8]) {
    assert_eq!(a.len(), b.len());
    for (i, (&b1, &b2)) in a.iter().zip(b).enumerate() {
        if b1 != b2 {
            panic!("Mismatch: {} (orig) vs {} (new) @ {} (0x{:X})",
                   b1,
                   b2,
                   i,
                   i);
        }
    }
}

#[test]
fn identity() {
    env_logger::init().unwrap();
    let paths = std::env::var("RGEN3_TEST_SAVES")
        .expect("Need RGEN3_TEST_SAVES env var set to a path");
    let paths = paths.split(';');
    for path in paths {
        let mut file = File::open(path).unwrap();
        const SAVE_LEN: usize = 131072;
        // Rust's test runner has small stacks, so gotta use vec instead of array.
        let mut data = vec![0; SAVE_LEN];
        file.read_exact(&mut data[..]).unwrap();
        let mut save = Save::read(&mut Cursor::new(&data[..])).unwrap();
        let mut writeout = vec![0; SAVE_LEN];
        {
            let mut writer = &mut writeout[..];
            save.write(&mut writer).unwrap();
        }
        cmp(&data, &writeout);
    }
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! A `mod` containing constructs useful in infix operator parsing with the precedence climbing
//! method.

use std::collections::HashMap;
use std::iter::Peekable;
use std::ops::BitOr;

use super::inputs::Input;
use super::iterators::Pair;
use super::RuleType;

/// An `enum` describing an `Operator`'s associativity.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Assoc {
    /// Left `Operator` associativity
    Left,
    /// Right `Operator` associativity
    Right
}

/// A `struct` defining an infix operator used in [PrecClimber](struct.PrecClimber.html).
#[derive(Debug)]
pub struct Operator<R: RuleType> {
    rule: R,
    assoc: Assoc,
    next: Option<Box<Operator<R>>>
}

impl<R: RuleType> Operator<R> {
    /// Creates a new `Operator` from a `Rule` and `Assoc`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::prec_climber::{Assoc, Operator};
    /// # #[allow(non_camel_case_types)]
    /// # #[allow(dead_code)]
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    /// # enum Rule {
    /// #     plus,
    /// #     minus
    /// # }
    /// let additive = Operator::new(Rule::plus, Assoc::Left) |
    ///                Operator::new(Rule::minus, Assoc::Right);
    /// ```
    pub fn new(rule: R, assoc: Assoc) -> Operator<R> {
        Operator {
            rule,
            assoc,
            next: None
        }
    }
}

impl<R: RuleType> BitOr for Operator<R> {
    type Output = Self;

    fn bitor(mut self, rhs: Self) -> Self {
        self.next = Some(Box::new(rhs));
        self
    }
}

/// A `struct` useful in order to perform [precedence climbing][1] on infix expressions contained in
/// a [`Pairs`](../iterators/struct.Pairs.html). The token pairs contained in the `Pairs` should
/// start with a *primary* pair and then alternate between an *operator* and a *primary*.
///
/// [1]: https://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method
#[derive(Debug)]
pub struct PrecClimber<R: RuleType> {
    ops: HashMap<R, (u32, Assoc)>
}

impl<R: RuleType> PrecClimber<R> {
    /// Creates a new `PrecClimber` from the `Operator`s contained in `ops`. Every entry in the
    /// `Vec` has precedence *index + 1*. In order to have operators with same precedence, they need
    /// to be chained with `|` between them.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::prec_climber::{Assoc, Operator, PrecClimber};
    /// # #[allow(non_camel_case_types)]
    /// # #[allow(dead_code)]
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    /// # enum Rule {
    /// #     plus,
    /// #     minus,
    /// #     times,
    /// #     divide,
    /// #     power
    /// # }
    /// let climber = PrecClimber::new(vec![
    ///     Operator::new(Rule::plus, Assoc::Left) | Operator::new(Rule::minus, Assoc::Left),
    ///     Operator::new(Rule::times, Assoc::Left) | Operator::new(Rule::divide, Assoc::Left),
    ///     Operator::new(Rule::power, Assoc::Right)
    /// ]);
    /// ```
    pub fn new(ops: Vec<Operator<R>>) -> PrecClimber<R> {
        let ops = ops.into_iter().zip((1..)).fold(HashMap::new(), |mut map, (op, prec)| {
            let mut next = Some(op);

            while let Some(op) = next.take() {
                match op {
                    Operator { rule, assoc, next: op_next } => {
                        map.insert(rule, (prec, assoc));
                        next = op_next.map(|op| *op);
                    }
                }
            }

            map
        });

        PrecClimber {
            ops
        }
    }

    /// Performs the precedence climbing algorithm on the `pairs` in a similar manner to map-reduce.
    /// *Primary* pairs are mapped with `primary` and then reduced to one single result with
    /// `infix`.
    ///
    /// # Panics
    ///
    /// Panics will occur when `pairs` is empty or when the alternating *primary*, *operator*,
    /// *primary* order is not respected.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// let primary = |pair| {
    ///     consume(pair, climber)
    /// };
    /// let infix = |lhs: i32, op: Pair<Rule, StringInput>, rhs: i32| {
    ///     match op.rule() {
    ///         Rule::plus => lhs + rhs,
    ///         Rule::minus => lhs - rhs,
    ///         Rule::times => lhs * rhs,
    ///         Rule::divide => lhs / rhs,
    ///         Rule::power => lhs.pow(rhs as u32),
    ///         _ => unreachable!()
    ///     }
    /// };
    ///
    /// let result = climber.climb(pairs, primary, infix);
    /// ```
    pub fn climb<I: Input, P, F, G, T>(
        &self,
        mut pairs: P,
        mut primary: F,
        mut infix: G
    ) -> T
    where
        P: Iterator<Item=Pair<R, I>>,
        F: FnMut(Pair<R, I>) -> T,
        G: FnMut(T, Pair<R, I>, T) -> T
    {
        let lhs = primary(pairs.next().expect("precedence climbing requires a non-empty Pairs"));
        self.climb_rec(lhs, 0, &mut pairs.peekable(), &mut primary, &mut infix)
    }

    fn climb_rec<I: Input, P, F, G, T>(
        &self,
        mut lhs: T,
        min_prec: u32,
        pairs: &mut Peekable<P>,
        primary: &mut F,
        infix: &mut G
    ) -> T
    where
        P: Iterator<Item=Pair<R, I>>,
        F: FnMut(Pair<R, I>) -> T,
        G: FnMut(T, Pair<R, I>, T) -> T
    {
        while pairs.peek().is_some() {
            let rule = pairs.peek().unwrap().as_rule();
            if let Some(&(prec, _)) = self.ops.get(&rule) {
                if prec >= min_prec {
                    let op = pairs.next().unwrap();
                    let mut rhs = primary(pairs.next().expect("infix operator must be followed by \
                                                               a primary expression"));

                    while pairs.peek().is_some() {
                        let rule = pairs.peek().unwrap().as_rule();
                        if let Some(&(new_prec, assoc)) = self.ops.get(&rule) {
                            if new_prec > prec || assoc == Assoc::Right && new_prec == prec {
                                rhs = self.climb_rec(rhs, new_prec, pairs, primary, infix);
                            } else {
                                break;
                            }
                        } else {
                            break;
                        }
                    }

                    lhs = infix(lhs, op, rhs);
                }
            } else {
                break;
            }
        }

        lhs
    }
}
<commit_msg>Fixed prec climbing hang.<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

//! A `mod` containing constructs useful in infix operator parsing with the precedence climbing
//! method.

use std::collections::HashMap;
use std::iter::Peekable;
use std::ops::BitOr;

use super::inputs::Input;
use super::iterators::Pair;
use super::RuleType;

/// An `enum` describing an `Operator`'s associativity.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Assoc {
    /// Left `Operator` associativity
    Left,
    /// Right `Operator` associativity
    Right
}

/// A `struct` defining an infix operator used in [PrecClimber](struct.PrecClimber.html).
#[derive(Debug)]
pub struct Operator<R: RuleType> {
    rule: R,
    assoc: Assoc,
    next: Option<Box<Operator<R>>>
}

impl<R: RuleType> Operator<R> {
    /// Creates a new `Operator` from a `Rule` and `Assoc`.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::prec_climber::{Assoc, Operator};
    /// # #[allow(non_camel_case_types)]
    /// # #[allow(dead_code)]
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    /// # enum Rule {
    /// #     plus,
    /// #     minus
    /// # }
    /// let additive = Operator::new(Rule::plus, Assoc::Left) |
    ///                Operator::new(Rule::minus, Assoc::Right);
    /// ```
    pub fn new(rule: R, assoc: Assoc) -> Operator<R> {
        Operator {
            rule,
            assoc,
            next: None
        }
    }
}

impl<R: RuleType> BitOr for Operator<R> {
    type Output = Self;

    fn bitor(mut self, rhs: Self) -> Self {
        self.next = Some(Box::new(rhs));
        self
    }
}

/// A `struct` useful in order to perform [precedence climbing][1] on infix expressions contained in
/// a [`Pairs`](../iterators/struct.Pairs.html). The token pairs contained in the `Pairs` should
/// start with a *primary* pair and then alternate between an *operator* and a *primary*.
///
/// [1]: https://en.wikipedia.org/wiki/Operator-precedence_parser#Precedence_climbing_method
#[derive(Debug)]
pub struct PrecClimber<R: RuleType> {
    ops: HashMap<R, (u32, Assoc)>
}

impl<R: RuleType> PrecClimber<R> {
    /// Creates a new `PrecClimber` from the `Operator`s contained in `ops`. Every entry in the
    /// `Vec` has precedence *index + 1*. In order to have operators with same precedence, they need
    /// to be chained with `|` between them.
    ///
    /// # Examples
    ///
    /// ```
    /// # use pest::prec_climber::{Assoc, Operator, PrecClimber};
    /// # #[allow(non_camel_case_types)]
    /// # #[allow(dead_code)]
    /// # #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
    /// # enum Rule {
    /// #     plus,
    /// #     minus,
    /// #     times,
    /// #     divide,
    /// #     power
    /// # }
    /// let climber = PrecClimber::new(vec![
    ///     Operator::new(Rule::plus, Assoc::Left) | Operator::new(Rule::minus, Assoc::Left),
    ///     Operator::new(Rule::times, Assoc::Left) | Operator::new(Rule::divide, Assoc::Left),
    ///     Operator::new(Rule::power, Assoc::Right)
    /// ]);
    /// ```
    pub fn new(ops: Vec<Operator<R>>) -> PrecClimber<R> {
        let ops = ops.into_iter().zip((1..)).fold(HashMap::new(), |mut map, (op, prec)| {
            let mut next = Some(op);

            while let Some(op) = next.take() {
                match op {
                    Operator { rule, assoc, next: op_next } => {
                        map.insert(rule, (prec, assoc));
                        next = op_next.map(|op| *op);
                    }
                }
            }

            map
        });

        PrecClimber {
            ops
        }
    }

    /// Performs the precedence climbing algorithm on the `pairs` in a similar manner to map-reduce.
    /// *Primary* pairs are mapped with `primary` and then reduced to one single result with
    /// `infix`.
    ///
    /// # Panics
    ///
    /// Panics will occur when `pairs` is empty or when the alternating *primary*, *operator*,
    /// *primary* order is not respected.
    ///
    /// # Examples
    ///
    /// ```ignore
    /// let primary = |pair| {
    ///     consume(pair, climber)
    /// };
    /// let infix = |lhs: i32, op: Pair<Rule, StringInput>, rhs: i32| {
    ///     match op.rule() {
    ///         Rule::plus => lhs + rhs,
    ///         Rule::minus => lhs - rhs,
    ///         Rule::times => lhs * rhs,
    ///         Rule::divide => lhs / rhs,
    ///         Rule::power => lhs.pow(rhs as u32),
    ///         _ => unreachable!()
    ///     }
    /// };
    ///
    /// let result = climber.climb(pairs, primary, infix);
    /// ```
    pub fn climb<I: Input, P, F, G, T>(
        &self,
        mut pairs: P,
        mut primary: F,
        mut infix: G
    ) -> T
    where
        P: Iterator<Item=Pair<R, I>>,
        F: FnMut(Pair<R, I>) -> T,
        G: FnMut(T, Pair<R, I>, T) -> T
    {
        let lhs = primary(pairs.next().expect("precedence climbing requires a non-empty Pairs"));
        self.climb_rec(lhs, 0, &mut pairs.peekable(), &mut primary, &mut infix)
    }

    fn climb_rec<I: Input, P, F, G, T>(
        &self,
        mut lhs: T,
        min_prec: u32,
        pairs: &mut Peekable<P>,
        primary: &mut F,
        infix: &mut G
    ) -> T
    where
        P: Iterator<Item=Pair<R, I>>,
        F: FnMut(Pair<R, I>) -> T,
        G: FnMut(T, Pair<R, I>, T) -> T
    {
        while pairs.peek().is_some() {
            let rule = pairs.peek().unwrap().as_rule();
            if let Some(&(prec, _)) = self.ops.get(&rule) {
                if prec >= min_prec {
                    let op = pairs.next().unwrap();
                    let mut rhs = primary(pairs.next().expect("infix operator must be followed by \
                                                               a primary expression"));

                    while pairs.peek().is_some() {
                        let rule = pairs.peek().unwrap().as_rule();
                        if let Some(&(new_prec, assoc)) = self.ops.get(&rule) {
                            if new_prec > prec || assoc == Assoc::Right && new_prec == prec {
                                rhs = self.climb_rec(rhs, new_prec, pairs, primary, infix);
                            } else {
                                break;
                            }
                        } else {
                            break;
                        }
                    }

                    lhs = infix(lhs, op, rhs);
                } else {
                    break;
                }
            } else {
                break;
            }
        }

        lhs
    }
}
<|endoftext|>


<commit_before>//! Errors that can be sent from the homeserver.

use std::fmt::{self, Display, Formatter};

use ruma_api::{error::ResponseDeserializationError, EndpointError};
use ruma_identifiers::RoomVersionId;
use serde::{Deserialize, Serialize};
use serde_json::{from_slice as from_json_slice, to_vec as to_json_vec};
use strum::{AsRefStr, Display};

/// An enum for the error kind. Items may contain additional information.
#[derive(Debug, Clone, Serialize, Deserialize, AsRefStr, Display)]
#[serde(tag = "errcode")]
#[cfg_attr(test, derive(PartialEq))]
pub enum ErrorKind {
    /// M_FORBIDDEN
    #[serde(rename = "M_FORBIDDEN")]
    #[strum(to_string = "M_FORBIDDEN")]
    Forbidden,

    /// M_UNKNOWN_TOKEN
    #[serde(rename = "M_UNKNOWN_TOKEN")]
    #[strum(to_string = "M_UNKNOWN_TOKEN")]
    UnknownToken {
        /// If this is `true`, the client can acquire a new access token by specifying the device ID
        /// it is already using to the login API. For more information, see [the spec].
        ///
        /// [the spec]: https://matrix.org/docs/spec/client_server/r0.6.1#soft-logout
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        soft_logout: bool,
    },

    /// M_MISSING_TOKEN
    #[serde(rename = "M_MISSING_TOKEN")]
    #[strum(to_string = "M_MISSING_TOKEN")]
    MissingToken,

    /// M_BAD_JSON
    #[serde(rename = "M_BAD_JSON")]
    #[strum(to_string = "M_BAD_JSON")]
    BadJson,

    /// M_NOT_JSON
    #[serde(rename = "M_NOT_JSON")]
    #[strum(to_string = "M_NOT_JSON")]
    NotJson,

    /// M_NOT_FOUND
    #[serde(rename = "M_NOT_FOUND")]
    #[strum(to_string = "M_NOT_FOUND")]
    NotFound,

    /// M_LIMIT_EXCEEDED
    #[serde(rename = "M_LIMIT_EXCEEDED")]
    #[strum(to_string = "M_LIMIT_EXCEEDED")]
    LimitExceeded,

    /// M_UNKNOWN
    #[serde(rename = "M_UNKNOWN")]
    #[strum(to_string = "M_UNKNOWN")]
    Unknown,

    /// M_UNRECOGNIZED
    #[serde(rename = "M_UNRECOGNIZED")]
    #[strum(to_string = "M_UNRECOGNIZED")]
    Unrecognized,

    /// M_UNAUTHORIZED
    #[serde(rename = "M_UNAUTHORIZED")]
    #[strum(to_string = "M_UNAUTHORIZED")]
    Unauthorized,

    /// M_USER_DEACTIVATED
    #[serde(rename = "M_USER_DEACTIVATED")]
    #[strum(to_string = "M_USER_DEACTIVATED")]
    UserDeactivated,

    /// M_USER_IN_USE
    #[serde(rename = "M_USER_IN_USE")]
    #[strum(to_string = "M_USER_IN_USE")]
    UserInUse,

    /// M_INVALID_USERNAME
    #[serde(rename = "M_INVALID_USERNAME")]
    #[strum(to_string = "M_INVALID_USERNAME")]
    InvalidUsername,

    /// M_ROOM_IN_USE
    #[serde(rename = "M_ROOM_IN_USE")]
    #[strum(to_string = "M_ROOM_IN_USE")]
    RoomInUse,

    /// M_INVALID_ROOM_STATE
    #[serde(rename = "M_INVALID_ROOM_STATE")]
    #[strum(to_string = "M_INVALID_ROOM_STATE")]
    InvalidRoomState,

    /// M_THREEPID_IN_USE
    #[serde(rename = "M_THREEPID_IN_USE")]
    #[strum(to_string = "M_THREEPID_IN_USE")]
    ThreepidInUse,

    /// M_THREEPID_NOT_FOUND
    #[serde(rename = "M_THREEPID_NOT_FOUND")]
    #[strum(to_string = "M_THREEPID_NOT_FOUND")]
    ThreepidNotFound,

    /// M_THREEPID_AUTH_FAILED
    #[serde(rename = "M_THREEPID_AUTH_FAILED")]
    #[strum(to_string = "M_THREEPID_AUTH_FAILED")]
    ThreepidAuthFailed,

    /// M_THREEPID_DENIED
    #[serde(rename = "M_THREEPID_DENIED")]
    #[strum(to_string = "M_THREEPID_DENIED")]
    ThreepidDenied,

    /// M_SERVER_NOT_TRUSTED
    #[serde(rename = "M_SERVER_NOT_TRUSTED")]
    #[strum(to_string = "M_SERVER_NOT_TRUSTED")]
    ServerNotTrusted,

    /// M_UNSUPPORTED_ROOM_VERSION
    #[serde(rename = "M_UNSUPPORTED_ROOM_VERSION")]
    #[strum(to_string = "M_UNSUPPORTED_ROOM_VERSION")]
    UnsupportedRoomVersion,

    /// M_INCOMPATIBLE_ROOM_VERSION
    #[serde(rename = "M_INCOMPATIBLE_ROOM_VERSION")]
    #[strum(to_string = "M_INCOMPATIBLE_ROOM_VERSION")]
    IncompatibleRoomVersion {
        /// The room's version.
        room_version: RoomVersionId,
    },

    /// M_BAD_STATE
    #[serde(rename = "M_BAD_STATE")]
    #[strum(to_string = "M_BAD_STATE")]
    BadState,

    /// M_GUEST_ACCESS_FORBIDDEN
    #[serde(rename = "M_GUEST_ACCESS_FORBIDDEN")]
    #[strum(to_string = "M_GUEST_ACCESS_FORBIDDEN")]
    GuestAccessForbidden,

    /// M_CAPTCHA_NEEDED
    #[serde(rename = "M_CAPTCHA_NEEDED")]
    #[strum(to_string = "M_CAPTCHA_NEEDED")]
    CaptchaNeeded,

    /// M_CAPTCHA_INVALID
    #[serde(rename = "M_CAPTCHA_INVALID")]
    #[strum(to_string = "M_CAPTCHA_INVALID")]
    CaptchaInvalid,

    /// M_MISSING_PARAM
    #[serde(rename = "M_MISSING_PARAM")]
    #[strum(to_string = "M_MISSING_PARAM")]
    MissingParam,

    /// M_INVALID_PARAM
    #[serde(rename = "M_INVALID_PARAM")]
    #[strum(to_string = "M_INVALID_PARAM")]
    InvalidParam,

    /// M_TOO_LARGE
    #[serde(rename = "M_TOO_LARGE")]
    #[strum(to_string = "M_TOO_LARGE")]
    TooLarge,

    /// M_EXCLUSIVE
    #[serde(rename = "M_EXCLUSIVE")]
    #[strum(to_string = "M_EXCLUSIVE")]
    Exclusive,
}

/// A Matrix Error without a status code
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(test, derive(PartialEq))]
pub struct ErrorBody {
    /// A value which can be used to handle an error message
    #[serde(flatten)]
    pub kind: ErrorKind,

    /// A human-readable error message, usually a sentence explaining what went wrong.
    #[serde(rename = "error")]
    pub message: String,
}

/// A Matrix Error
#[derive(Debug, Clone)]
pub struct Error {
    /// A value which can be used to handle an error message
    pub kind: ErrorKind,

    /// A human-readable error message, usually a sentence explaining what went wrong.
    pub message: String,

    /// The http status code
    pub status_code: http::StatusCode,
}

impl EndpointError for Error {
    fn try_from_response(
        response: http::Response<Vec<u8>>,
    ) -> Result<Self, ResponseDeserializationError> {
        match from_json_slice::<ErrorBody>(response.body()) {
            Ok(error_body) => Ok(error_body.into_error(response.status())),
            Err(de_error) => Err(ResponseDeserializationError::new(de_error, response)),
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "[{} / {}] {}", self.status_code.as_u16(), self.kind, self.message)
    }
}

impl std::error::Error for Error {}

impl From<Error> for ErrorBody {
    fn from(error: Error) -> Self {
        Self { kind: error.kind, message: error.message }
    }
}

impl ErrorBody {
    /// Convert the ErrorBody into an Error by adding the http status code.
    pub fn into_error(self, status_code: http::StatusCode) -> Error {
        Error { kind: self.kind, message: self.message, status_code }
    }
}

impl From<Error> for http::Response<Vec<u8>> {
    fn from(error: Error) -> http::Response<Vec<u8>> {
        http::Response::builder()
            .header(http::header::CONTENT_TYPE, "application/json")
            .status(error.status_code)
            .body(to_json_vec(&ErrorBody::from(error)).unwrap())
            .unwrap()
    }
}
<commit_msg>client-api: Add ErrorKind::ResourceLimitExceeded<commit_after>//! Errors that can be sent from the homeserver.

use std::fmt::{self, Display, Formatter};

use ruma_api::{error::ResponseDeserializationError, EndpointError};
use ruma_identifiers::RoomVersionId;
use serde::{Deserialize, Serialize};
use serde_json::{from_slice as from_json_slice, to_vec as to_json_vec};
use strum::{AsRefStr, Display};

/// An enum for the error kind. Items may contain additional information.
#[derive(Debug, Clone, Serialize, Deserialize, AsRefStr, Display)]
#[serde(tag = "errcode")]
#[cfg_attr(test, derive(PartialEq))]
pub enum ErrorKind {
    /// M_FORBIDDEN
    #[serde(rename = "M_FORBIDDEN")]
    #[strum(to_string = "M_FORBIDDEN")]
    Forbidden,

    /// M_UNKNOWN_TOKEN
    #[serde(rename = "M_UNKNOWN_TOKEN")]
    #[strum(to_string = "M_UNKNOWN_TOKEN")]
    UnknownToken {
        /// If this is `true`, the client can acquire a new access token by specifying the device ID
        /// it is already using to the login API. For more information, see [the spec].
        ///
        /// [the spec]: https://matrix.org/docs/spec/client_server/r0.6.1#soft-logout
        #[serde(default, skip_serializing_if = "ruma_serde::is_default")]
        soft_logout: bool,
    },

    /// M_MISSING_TOKEN
    #[serde(rename = "M_MISSING_TOKEN")]
    #[strum(to_string = "M_MISSING_TOKEN")]
    MissingToken,

    /// M_BAD_JSON
    #[serde(rename = "M_BAD_JSON")]
    #[strum(to_string = "M_BAD_JSON")]
    BadJson,

    /// M_NOT_JSON
    #[serde(rename = "M_NOT_JSON")]
    #[strum(to_string = "M_NOT_JSON")]
    NotJson,

    /// M_NOT_FOUND
    #[serde(rename = "M_NOT_FOUND")]
    #[strum(to_string = "M_NOT_FOUND")]
    NotFound,

    /// M_LIMIT_EXCEEDED
    #[serde(rename = "M_LIMIT_EXCEEDED")]
    #[strum(to_string = "M_LIMIT_EXCEEDED")]
    LimitExceeded,

    /// M_UNKNOWN
    #[serde(rename = "M_UNKNOWN")]
    #[strum(to_string = "M_UNKNOWN")]
    Unknown,

    /// M_UNRECOGNIZED
    #[serde(rename = "M_UNRECOGNIZED")]
    #[strum(to_string = "M_UNRECOGNIZED")]
    Unrecognized,

    /// M_UNAUTHORIZED
    #[serde(rename = "M_UNAUTHORIZED")]
    #[strum(to_string = "M_UNAUTHORIZED")]
    Unauthorized,

    /// M_USER_DEACTIVATED
    #[serde(rename = "M_USER_DEACTIVATED")]
    #[strum(to_string = "M_USER_DEACTIVATED")]
    UserDeactivated,

    /// M_USER_IN_USE
    #[serde(rename = "M_USER_IN_USE")]
    #[strum(to_string = "M_USER_IN_USE")]
    UserInUse,

    /// M_INVALID_USERNAME
    #[serde(rename = "M_INVALID_USERNAME")]
    #[strum(to_string = "M_INVALID_USERNAME")]
    InvalidUsername,

    /// M_ROOM_IN_USE
    #[serde(rename = "M_ROOM_IN_USE")]
    #[strum(to_string = "M_ROOM_IN_USE")]
    RoomInUse,

    /// M_INVALID_ROOM_STATE
    #[serde(rename = "M_INVALID_ROOM_STATE")]
    #[strum(to_string = "M_INVALID_ROOM_STATE")]
    InvalidRoomState,

    /// M_THREEPID_IN_USE
    #[serde(rename = "M_THREEPID_IN_USE")]
    #[strum(to_string = "M_THREEPID_IN_USE")]
    ThreepidInUse,

    /// M_THREEPID_NOT_FOUND
    #[serde(rename = "M_THREEPID_NOT_FOUND")]
    #[strum(to_string = "M_THREEPID_NOT_FOUND")]
    ThreepidNotFound,

    /// M_THREEPID_AUTH_FAILED
    #[serde(rename = "M_THREEPID_AUTH_FAILED")]
    #[strum(to_string = "M_THREEPID_AUTH_FAILED")]
    ThreepidAuthFailed,

    /// M_THREEPID_DENIED
    #[serde(rename = "M_THREEPID_DENIED")]
    #[strum(to_string = "M_THREEPID_DENIED")]
    ThreepidDenied,

    /// M_SERVER_NOT_TRUSTED
    #[serde(rename = "M_SERVER_NOT_TRUSTED")]
    #[strum(to_string = "M_SERVER_NOT_TRUSTED")]
    ServerNotTrusted,

    /// M_UNSUPPORTED_ROOM_VERSION
    #[serde(rename = "M_UNSUPPORTED_ROOM_VERSION")]
    #[strum(to_string = "M_UNSUPPORTED_ROOM_VERSION")]
    UnsupportedRoomVersion,

    /// M_INCOMPATIBLE_ROOM_VERSION
    #[serde(rename = "M_INCOMPATIBLE_ROOM_VERSION")]
    #[strum(to_string = "M_INCOMPATIBLE_ROOM_VERSION")]
    IncompatibleRoomVersion {
        /// The room's version.
        room_version: RoomVersionId,
    },

    /// M_BAD_STATE
    #[serde(rename = "M_BAD_STATE")]
    #[strum(to_string = "M_BAD_STATE")]
    BadState,

    /// M_GUEST_ACCESS_FORBIDDEN
    #[serde(rename = "M_GUEST_ACCESS_FORBIDDEN")]
    #[strum(to_string = "M_GUEST_ACCESS_FORBIDDEN")]
    GuestAccessForbidden,

    /// M_CAPTCHA_NEEDED
    #[serde(rename = "M_CAPTCHA_NEEDED")]
    #[strum(to_string = "M_CAPTCHA_NEEDED")]
    CaptchaNeeded,

    /// M_CAPTCHA_INVALID
    #[serde(rename = "M_CAPTCHA_INVALID")]
    #[strum(to_string = "M_CAPTCHA_INVALID")]
    CaptchaInvalid,

    /// M_MISSING_PARAM
    #[serde(rename = "M_MISSING_PARAM")]
    #[strum(to_string = "M_MISSING_PARAM")]
    MissingParam,

    /// M_INVALID_PARAM
    #[serde(rename = "M_INVALID_PARAM")]
    #[strum(to_string = "M_INVALID_PARAM")]
    InvalidParam,

    /// M_TOO_LARGE
    #[serde(rename = "M_TOO_LARGE")]
    #[strum(to_string = "M_TOO_LARGE")]
    TooLarge,

    /// M_EXCLUSIVE
    #[serde(rename = "M_EXCLUSIVE")]
    #[strum(to_string = "M_EXCLUSIVE")]
    Exclusive,

    /// M_RESOURCE_LIMIT_EXCEEDED
    #[serde(rename = "M_RESOURCE_LIMIT_EXCEEDED")]
    #[strum(to_string = "M_RESOURCE_LIMIT_EXCEEDED")]
    ResourceLimitExceeded {
        /// A URI giving a contact method for the server administrator.
        admin_contact: String,
    },
}

/// A Matrix Error without a status code
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(test, derive(PartialEq))]
pub struct ErrorBody {
    /// A value which can be used to handle an error message
    #[serde(flatten)]
    pub kind: ErrorKind,

    /// A human-readable error message, usually a sentence explaining what went wrong.
    #[serde(rename = "error")]
    pub message: String,
}

/// A Matrix Error
#[derive(Debug, Clone)]
pub struct Error {
    /// A value which can be used to handle an error message
    pub kind: ErrorKind,

    /// A human-readable error message, usually a sentence explaining what went wrong.
    pub message: String,

    /// The http status code
    pub status_code: http::StatusCode,
}

impl EndpointError for Error {
    fn try_from_response(
        response: http::Response<Vec<u8>>,
    ) -> Result<Self, ResponseDeserializationError> {
        match from_json_slice::<ErrorBody>(response.body()) {
            Ok(error_body) => Ok(error_body.into_error(response.status())),
            Err(de_error) => Err(ResponseDeserializationError::new(de_error, response)),
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "[{} / {}] {}", self.status_code.as_u16(), self.kind, self.message)
    }
}

impl std::error::Error for Error {}

impl From<Error> for ErrorBody {
    fn from(error: Error) -> Self {
        Self { kind: error.kind, message: error.message }
    }
}

impl ErrorBody {
    /// Convert the ErrorBody into an Error by adding the http status code.
    pub fn into_error(self, status_code: http::StatusCode) -> Error {
        Error { kind: self.kind, message: self.message, status_code }
    }
}

impl From<Error> for http::Response<Vec<u8>> {
    fn from(error: Error) -> http::Response<Vec<u8>> {
        http::Response::builder()
            .header(http::header::CONTENT_TYPE, "application/json")
            .status(error.status_code)
            .body(to_json_vec(&ErrorBody::from(error)).unwrap())
            .unwrap()
    }
}
<|endoftext|>