<commit_before>use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");

    if cfg!(feature = "llvm-libunwind")
        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
    {
        // Build the unwinding from libunwind C/C++ source code.
        llvm_libunwind::compile();
    } else if target.contains("linux") {
        if target.contains("musl") {
            // linking for musl is handled in lib.rs
            llvm_libunwind::compile();
        } else if !target.contains("android") {
            println!("cargo:rustc-link-lib=gcc_s");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("rumprun") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("netbsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("openbsd") {
        if target.contains("sparc64") {
            println!("cargo:rustc-link-lib=gcc");
        } else {
            println!("cargo:rustc-link-lib=c++abi");
        }
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("illumos") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=gcc_pic");
    } else if target.contains("pc-windows-gnu") {
        // This is handled in the target spec with late_link_args_[static|dynamic]

        // cfg!(bootstrap) doesn't work in build scripts
        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
            println!("cargo:rustc-link-lib=static-nobundle=pthread");
        }
    } else if target.contains("uwp-windows-gnu") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("haiku") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("redox") {
        // redox is handled in lib.rs
    } else if target.contains("cloudabi") {
        println!("cargo:rustc-link-lib=unwind");
    }
}

mod llvm_libunwind {
    use std::env;
    use std::path::Path;

    /// Compile the libunwind C/C++ source code.
    pub fn compile() {
        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
        let cfg = &mut cc::Build::new();

        cfg.cpp(true);
        cfg.cpp_set_stdlib(None);
        cfg.warnings(false);

        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
        if target_endian_little {
            cfg.define("__LITTLE_ENDIAN__", Some("1"));
        }

        if target_env == "msvc" {
            // Don't pull in extra libraries on MSVC
            cfg.flag("/Zl");
            cfg.flag("/EHsc");
            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        } else {
            cfg.flag("-std=c99");
            cfg.flag("-std=c++11");
            cfg.flag("-nostdinc++");
            cfg.flag("-fno-exceptions");
            cfg.flag("-fno-rtti");
            cfg.flag("-fstrict-aliasing");
            cfg.flag("-funwind-tables");
            cfg.flag("-fvisibility=hidden");
        }

        let mut unwind_sources = vec![
            "Unwind-EHABI.cpp",
            "Unwind-seh.cpp",
            "Unwind-sjlj.c",
            "UnwindLevel1-gcc-ext.c",
            "UnwindLevel1.c",
            "UnwindRegistersRestore.S",
            "UnwindRegistersSave.S",
            "libunwind.cpp",
        ];

        if target_vendor == "apple" {
            unwind_sources.push("Unwind_AppleExtras.cpp");
        }

        let root = Path::new("../llvm-project/libunwind");
        cfg.include(root.join("include"));
        for src in unwind_sources {
            cfg.file(root.join("src").join(src));
        }

        if target_env == "musl" {
            // use the same C compiler command to compile C++ code so we do not need to setup the
            // C++ compiler env variables on the builders
            cfg.cpp(false);
            // linking for musl is handled in lib.rs
            cfg.cargo_metadata(false);
            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
        }

        cfg.compile("unwind");
    }
}
<commit_msg>Make libunwind build hermetic<commit_after>use std::env;

fn main() {
    println!("cargo:rerun-if-changed=build.rs");
    let target = env::var("TARGET").expect("TARGET was not set");

    if cfg!(feature = "llvm-libunwind")
        && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
    {
        // Build the unwinding from libunwind C/C++ source code.
        llvm_libunwind::compile();
    } else if target.contains("linux") {
        if target.contains("musl") {
            // linking for musl is handled in lib.rs
            llvm_libunwind::compile();
        } else if !target.contains("android") {
            println!("cargo:rustc-link-lib=gcc_s");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("rumprun") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("netbsd") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("openbsd") {
        if target.contains("sparc64") {
            println!("cargo:rustc-link-lib=gcc");
        } else {
            println!("cargo:rustc-link-lib=c++abi");
        }
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("illumos") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("dragonfly") {
        println!("cargo:rustc-link-lib=gcc_pic");
    } else if target.contains("pc-windows-gnu") {
        // This is handled in the target spec with late_link_args_[static|dynamic]

        // cfg!(bootstrap) doesn't work in build scripts
        if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) {
            println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
            println!("cargo:rustc-link-lib=static-nobundle=pthread");
        }
    } else if target.contains("uwp-windows-gnu") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("fuchsia") {
        println!("cargo:rustc-link-lib=unwind");
    } else if target.contains("haiku") {
        println!("cargo:rustc-link-lib=gcc_s");
    } else if target.contains("redox") {
        // redox is handled in lib.rs
    } else if target.contains("cloudabi") {
        println!("cargo:rustc-link-lib=unwind");
    }
}

mod llvm_libunwind {
    use std::env;
    use std::path::Path;

    /// Compile the libunwind C/C++ source code.
    pub fn compile() {
        let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
        let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
        let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
        let cfg = &mut cc::Build::new();

        cfg.cpp(true);
        cfg.cpp_set_stdlib(None);
        cfg.warnings(false);

        // libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
        if target_endian_little {
            cfg.define("__LITTLE_ENDIAN__", Some("1"));
        }

        if target_env == "msvc" {
            // Don't pull in extra libraries on MSVC
            cfg.flag("/Zl");
            cfg.flag("/EHsc");
            cfg.define("_CRT_SECURE_NO_WARNINGS", None);
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        } else {
            cfg.flag("-std=c99");
            cfg.flag("-std=c++11");
            cfg.flag("-nostdinc++");
            cfg.flag("-fno-exceptions");
            cfg.flag("-fno-rtti");
            cfg.flag("-fstrict-aliasing");
            cfg.flag("-funwind-tables");
            cfg.flag("-fvisibility=hidden");
            cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
            cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
        }

        let mut unwind_sources = vec![
            "Unwind-EHABI.cpp",
            "Unwind-seh.cpp",
            "Unwind-sjlj.c",
            "UnwindLevel1-gcc-ext.c",
            "UnwindLevel1.c",
            "UnwindRegistersRestore.S",
            "UnwindRegistersSave.S",
            "libunwind.cpp",
        ];

        if target_vendor == "apple" {
            unwind_sources.push("Unwind_AppleExtras.cpp");
        }

        let root = Path::new("../llvm-project/libunwind");
        cfg.include(root.join("include"));
        for src in unwind_sources {
            cfg.file(root.join("src").join(src));
        }

        if target_env == "musl" {
            // use the same C compiler command to compile C++ code so we do not need to setup the
            // C++ compiler env variables on the builders
            cfg.cpp(false);
            // linking for musl is handled in lib.rs
            cfg.cargo_metadata(false);
            println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
        }

        cfg.compile("unwind");
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};

use alga::general::ComplexField;

use crate::allocator::Allocator;
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix};
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
use crate::dimension::{Dim, DimSub, Dynamic, U1};
use crate::storage::{Storage, StorageMut};

/// The Cholesky decomposition of a symmetric-definite-positive matrix.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(serialize = "DefaultAllocator: Allocator<N, D>,
         MatrixN<N, D>: Serialize"))
)]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(deserialize = "DefaultAllocator: Allocator<N, D>,
         MatrixN<N, D>: Deserialize<'de>"))
)]
#[derive(Clone, Debug)]
pub struct Cholesky<N: ComplexField, D: Dim>
where
    DefaultAllocator: Allocator<N, D, D>,
{
    chol: MatrixN<N, D>,
}

impl<N: ComplexField, D: Dim> Copy for Cholesky<N, D>
where
    DefaultAllocator: Allocator<N, D, D>,
    MatrixN<N, D>: Copy,
{
}

impl<N: ComplexField, D: DimSub<Dynamic>> Cholesky<N, D>
where
    DefaultAllocator: Allocator<N, D, D>,
{
    /// Attempts to compute the Cholesky decomposition of `matrix`.
    ///
    /// Returns `None` if the input matrix is not definite-positive. The input matrix is assumed
    /// to be symmetric and only the lower-triangular part is read.
    pub fn new(mut matrix: MatrixN<N, D>) -> Option<Self> {
        assert!(matrix.is_square(), "The input matrix must be square.");

        let n = matrix.nrows();

        for j in 0..n {
            for k in 0..j {
                let factor = unsafe { -*matrix.get_unchecked((j, k)) };

                let (mut col_j, col_k) = matrix.columns_range_pair_mut(j, k);
                let mut col_j = col_j.rows_range_mut(j..);
                let col_k = col_k.rows_range(j..);

                col_j.axpy(factor.conjugate(), &col_k, N::one());
            }

            let diag = unsafe { *matrix.get_unchecked((j, j)) };
            if !diag.is_zero() {
                if let Some(denom) = diag.try_sqrt() {
                    unsafe {
                        *matrix.get_unchecked_mut((j, j)) = denom;
                    }

                    let mut col = matrix.slice_range_mut(j + 1.., j);
                    col /= denom;
                    continue;
                }
            }

            // The diagonal element is either zero or its square root could not
            // be taken (e.g. for negative real numbers).
            return None;
        }

        Some(Cholesky { chol: matrix })
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition with its strictly
    /// upper-triangular part filled with zeros.
    pub fn unpack(mut self) -> MatrixN<N, D> {
        self.chol.fill_upper_triangle(N::zero(), 1);
        self.chol
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition, without zeroing-out
    /// its strict upper-triangular part.
    ///
    /// The values of the strict upper-triangular part are garbage and should be ignored by further
    /// computations.
    pub fn unpack_dirty(self) -> MatrixN<N, D> {
        self.chol
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition with its strictly
    /// uppen-triangular part filled with zeros.
    pub fn l(&self) -> MatrixN<N, D> {
        self.chol.lower_triangle()
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition, without zeroing-out
    /// its strict upper-triangular part.
    ///
    /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular
    /// part are garbage and should be ignored by further computations.
    pub fn l_dirty(&self) -> &MatrixN<N, D> {
        &self.chol
    }

    /// Solves the system `self * x = b` where `self` is the decomposed matrix and `x` the unknown.
    ///
    /// The result is stored on `b`.
    pub fn solve_mut<R2: Dim, C2: Dim, S2>(&self, b: &mut Matrix<N, R2, C2, S2>)
    where
        S2: StorageMut<N, R2, C2>,
        ShapeConstraint: SameNumberOfRows<R2, D>,
    {
        let _ = self.chol.solve_lower_triangular_mut(b);
        let _ = self.chol.ad_solve_lower_triangular_mut(b);
    }

    /// Returns the solution of the system `self * x = b` where `self` is the decomposed matrix and
    /// `x` the unknown.
    pub fn solve<R2: Dim, C2: Dim, S2>(&self, b: &Matrix<N, R2, C2, S2>) -> MatrixMN<N, R2, C2>
    where
        S2: Storage<N, R2, C2>,
        DefaultAllocator: Allocator<N, R2, C2>,
        ShapeConstraint: SameNumberOfRows<R2, D>,
    {
        let mut res = b.clone_owned();
        self.solve_mut(&mut res);
        res
    }

    /// Computes the inverse of the decomposed matrix.
    pub fn inverse(&self) -> MatrixN<N, D> {
        let shape = self.chol.data.shape();
        let mut res = MatrixN::identity_generic(shape.0, shape.1);

        self.solve_mut(&mut res);
        res
    }

    /// Given the Cholesky decomposition of a matrix `M`, a scalar `sigma` and a vector `v`,
    /// performs a rank one update such that we end up with the decomposition of `M + sigma * v*v.adjoint()`.
    pub fn rank_one_update<R2: Dim, S2>(&mut self, x: &Matrix<N, R2, U1, S2>, sigma: N::RealField)
    where
        S2: Storage<N, R2, U1>,
        DefaultAllocator: Allocator<N, R2, U1>,
        ShapeConstraint: SameNumberOfRows<R2, D>,
    {
        // heavily inspired by Eigen's `llt_rank_update_lower` implementation https://eigen.tuxfamily.org/dox/LLT_8h_source.html
        let n = x.nrows();
        let mut x = x.clone_owned();
        let mut beta = crate::one::<N::RealField>();
        for j in 0..n {
            // updates the diagonal
            let diag = N::real(unsafe { *self.chol.get_unchecked((j, j)) });
            let diag2 = diag * diag;
            let xj = unsafe { *x.get_unchecked(j) };
            let sigma_xj2 = sigma * N::modulus_squared(xj);
            let gamma = diag2 * beta + sigma_xj2;
            let new_diag = (diag2 + sigma_xj2 / beta).sqrt();
            unsafe { *self.chol.get_unchecked_mut((j, j)) = N::from_real(new_diag) };
            beta += sigma_xj2 / diag2;
            // updates the terms of L
            let mut xjplus = x.rows_range_mut(j + 1..);
            let mut col_j = self.chol.slice_range_mut(j + 1.., j);
            // temp_jplus -= (wj / N::from_real(diag)) * col_j;
            xjplus.axpy(-xj / N::from_real(diag), &col_j, N::one());
            if gamma != crate::zero::<N::RealField>() {
                // col_j = N::from_real(nljj / diag) * col_j  + (N::from_real(nljj * sigma / gamma) * N::conjugate(wj)) * temp_jplus;
                col_j.axpy(
                    N::from_real(new_diag * sigma / gamma) * N::conjugate(xj),
                    &xjplus,
                    N::from_real(new_diag / diag),
                );
            }
        }
    }
}

impl<N: ComplexField, D: DimSub<Dynamic>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
where
    DefaultAllocator: Allocator<N, D, D>,
{
    /// Attempts to compute the Cholesky decomposition of this matrix.
    ///
    /// Returns `None` if the input matrix is not definite-positive. The input matrix is assumed
    /// to be symmetric and only the lower-triangular part is read.
    pub fn cholesky(self) -> Option<Cholesky<N, D>> {
        Cholesky::new(self.into_owned())
    }
}
<commit_msg>added assertion<commit_after>#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};

use alga::general::ComplexField;

use crate::allocator::Allocator;
use crate::base::{DefaultAllocator, Matrix, MatrixMN, MatrixN, SquareMatrix};
use crate::constraint::{SameNumberOfRows, ShapeConstraint};
use crate::dimension::{Dim, DimSub, Dynamic, U1};
use crate::storage::{Storage, StorageMut};

/// The Cholesky decomposition of a symmetric-definite-positive matrix.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(serialize = "DefaultAllocator: Allocator<N, D>,
         MatrixN<N, D>: Serialize"))
)]
#[cfg_attr(
    feature = "serde-serialize",
    serde(bound(deserialize = "DefaultAllocator: Allocator<N, D>,
         MatrixN<N, D>: Deserialize<'de>"))
)]
#[derive(Clone, Debug)]
pub struct Cholesky<N: ComplexField, D: Dim>
where
    DefaultAllocator: Allocator<N, D, D>,
{
    chol: MatrixN<N, D>,
}

impl<N: ComplexField, D: Dim> Copy for Cholesky<N, D>
where
    DefaultAllocator: Allocator<N, D, D>,
    MatrixN<N, D>: Copy,
{
}

impl<N: ComplexField, D: DimSub<Dynamic>> Cholesky<N, D>
where
    DefaultAllocator: Allocator<N, D, D>,
{
    /// Attempts to compute the Cholesky decomposition of `matrix`.
    ///
    /// Returns `None` if the input matrix is not definite-positive. The input matrix is assumed
    /// to be symmetric and only the lower-triangular part is read.
    pub fn new(mut matrix: MatrixN<N, D>) -> Option<Self> {
        assert!(matrix.is_square(), "The input matrix must be square.");

        let n = matrix.nrows();

        for j in 0..n {
            for k in 0..j {
                let factor = unsafe { -*matrix.get_unchecked((j, k)) };

                let (mut col_j, col_k) = matrix.columns_range_pair_mut(j, k);
                let mut col_j = col_j.rows_range_mut(j..);
                let col_k = col_k.rows_range(j..);

                col_j.axpy(factor.conjugate(), &col_k, N::one());
            }

            let diag = unsafe { *matrix.get_unchecked((j, j)) };
            if !diag.is_zero() {
                if let Some(denom) = diag.try_sqrt() {
                    unsafe {
                        *matrix.get_unchecked_mut((j, j)) = denom;
                    }

                    let mut col = matrix.slice_range_mut(j + 1.., j);
                    col /= denom;
                    continue;
                }
            }

            // The diagonal element is either zero or its square root could not
            // be taken (e.g. for negative real numbers).
            return None;
        }

        Some(Cholesky { chol: matrix })
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition with its strictly
    /// upper-triangular part filled with zeros.
    pub fn unpack(mut self) -> MatrixN<N, D> {
        self.chol.fill_upper_triangle(N::zero(), 1);
        self.chol
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition, without zeroing-out
    /// its strict upper-triangular part.
    ///
    /// The values of the strict upper-triangular part are garbage and should be ignored by further
    /// computations.
    pub fn unpack_dirty(self) -> MatrixN<N, D> {
        self.chol
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition with its strictly
    /// uppen-triangular part filled with zeros.
    pub fn l(&self) -> MatrixN<N, D> {
        self.chol.lower_triangle()
    }

    /// Retrieves the lower-triangular factor of the Cholesky decomposition, without zeroing-out
    /// its strict upper-triangular part.
    ///
    /// This is an allocation-less version of `self.l()`. The values of the strict upper-triangular
    /// part are garbage and should be ignored by further computations.
    pub fn l_dirty(&self) -> &MatrixN<N, D> {
        &self.chol
    }

    /// Solves the system `self * x = b` where `self` is the decomposed matrix and `x` the unknown.
    ///
    /// The result is stored on `b`.
    pub fn solve_mut<R2: Dim, C2: Dim, S2>(&self, b: &mut Matrix<N, R2, C2, S2>)
    where
        S2: StorageMut<N, R2, C2>,
        ShapeConstraint: SameNumberOfRows<R2, D>,
    {
        let _ = self.chol.solve_lower_triangular_mut(b);
        let _ = self.chol.ad_solve_lower_triangular_mut(b);
    }

    /// Returns the solution of the system `self * x = b` where `self` is the decomposed matrix and
    /// `x` the unknown.
    pub fn solve<R2: Dim, C2: Dim, S2>(&self, b: &Matrix<N, R2, C2, S2>) -> MatrixMN<N, R2, C2>
    where
        S2: Storage<N, R2, C2>,
        DefaultAllocator: Allocator<N, R2, C2>,
        ShapeConstraint: SameNumberOfRows<R2, D>,
    {
        let mut res = b.clone_owned();
        self.solve_mut(&mut res);
        res
    }

    /// Computes the inverse of the decomposed matrix.
    pub fn inverse(&self) -> MatrixN<N, D> {
        let shape = self.chol.data.shape();
        let mut res = MatrixN::identity_generic(shape.0, shape.1);

        self.solve_mut(&mut res);
        res
    }

    /// Given the Cholesky decomposition of a matrix `M`, a scalar `sigma` and a vector `v`,
    /// performs a rank one update such that we end up with the decomposition of `M + sigma * v*v.adjoint()`.
    pub fn rank_one_update<R2: Dim, S2>(&mut self, x: &Matrix<N, R2, U1, S2>, sigma: N::RealField)
    where
        S2: Storage<N, R2, U1>,
        DefaultAllocator: Allocator<N, R2, U1>,
        ShapeConstraint: SameNumberOfRows<R2, D>,
    {
        // heavily inspired by Eigen's `llt_rank_update_lower` implementation https://eigen.tuxfamily.org/dox/LLT_8h_source.html
        let n = x.nrows();
        assert_eq!(
            n,
            self.chol.nrows(),
            "The input vector must be of the same size as the factorized matrix."
        );
        let mut x = x.clone_owned();
        let mut beta = crate::one::<N::RealField>();
        for j in 0..n {
            // updates the diagonal
            let diag = N::real(unsafe { *self.chol.get_unchecked((j, j)) });
            let diag2 = diag * diag;
            let xj = unsafe { *x.get_unchecked(j) };
            let sigma_xj2 = sigma * N::modulus_squared(xj);
            let gamma = diag2 * beta + sigma_xj2;
            let new_diag = (diag2 + sigma_xj2 / beta).sqrt();
            unsafe { *self.chol.get_unchecked_mut((j, j)) = N::from_real(new_diag) };
            beta += sigma_xj2 / diag2;
            // updates the terms of L
            let mut xjplus = x.rows_range_mut(j + 1..);
            let mut col_j = self.chol.slice_range_mut(j + 1.., j);
            // temp_jplus -= (wj / N::from_real(diag)) * col_j;
            xjplus.axpy(-xj / N::from_real(diag), &col_j, N::one());
            if gamma != crate::zero::<N::RealField>() {
                // col_j = N::from_real(nljj / diag) * col_j  + (N::from_real(nljj * sigma / gamma) * N::conjugate(wj)) * temp_jplus;
                col_j.axpy(
                    N::from_real(new_diag * sigma / gamma) * N::conjugate(xj),
                    &xjplus,
                    N::from_real(new_diag / diag),
                );
            }
        }
    }
}

impl<N: ComplexField, D: DimSub<Dynamic>, S: Storage<N, D, D>> SquareMatrix<N, D, S>
where
    DefaultAllocator: Allocator<N, D, D>,
{
    /// Attempts to compute the Cholesky decomposition of this matrix.
    ///
    /// Returns `None` if the input matrix is not definite-positive. The input matrix is assumed
    /// to be symmetric and only the lower-triangular part is read.
    pub fn cholesky(self) -> Option<Cholesky<N, D>> {
        Cholesky::new(self.into_owned())
    }
}
<|endoftext|>


<commit_before>//! Runs rustfmt on the repository.

use crate::Build;
use build_helper::{output, t};
use ignore::WalkBuilder;
use std::path::Path;
use std::process::{Command, Stdio};

fn rustfmt(src: &Path, rustfmt: &Path, path: &Path, check: bool) {
    let mut cmd = Command::new(&rustfmt);
    // avoid the submodule config paths from coming into play,
    // we only allow a single global config for the workspace for now
    cmd.arg("--config-path").arg(&src.canonicalize().unwrap());
    cmd.arg("--edition").arg("2018");
    cmd.arg("--unstable-features");
    cmd.arg("--skip-children");
    if check {
        cmd.arg("--check");
    }
    cmd.arg(&path);
    let cmd_debug = format!("{:?}", cmd);
    let status = cmd.status().expect("executing rustfmt");
    if !status.success() {
        eprintln!(
            "Running `{}` failed.\nIf you're running `tidy`, \
            try again with `--bless` flag. Or, you just want to format \
            code, run `./x.py fmt` instead.",
            cmd_debug,
        );
        std::process::exit(1);
    }
}

#[derive(serde::Deserialize)]
struct RustfmtConfig {
    ignore: Vec<String>,
}

pub fn format(build: &Build, check: bool) {
    if build.config.dry_run {
        return;
    }
    let mut builder = ignore::types::TypesBuilder::new();
    builder.add_defaults();
    builder.select("rust");
    let matcher = builder.build().unwrap();
    let rustfmt_config = build.src.join("rustfmt.toml");
    if !rustfmt_config.exists() {
        eprintln!("Not running formatting checks; rustfmt.toml does not exist.");
        eprintln!("This may happen in distributed tarballs.");
        return;
    }
    let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config));
    let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config));
    let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src);
    for ignore in rustfmt_config.ignore {
        ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore);
    }
    let git_available = match Command::new("git")
        .arg("--version")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status()
    {
        Ok(status) => status.success(),
        Err(_) => false,
    };
    if git_available {
        let in_working_tree = match Command::new("git")
            .arg("rev-parse")
            .arg("--is-inside-work-tree")
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .status()
        {
            Ok(status) => status.success(),
            Err(_) => false,
        };
        if in_working_tree {
            let untracked_paths_output = output(
                Command::new("git")
                    .arg("status")
                    .arg("--porcelain")
                    .arg("--untracked-files=normal"),
            );
            let untracked_paths = untracked_paths_output
                .lines()
                .filter(|entry| entry.starts_with("??"))
                .map(|entry| {
                    entry.split(" ").nth(1).expect("every git status entry should list a path")
                });
            for untracked_path in untracked_paths {
                eprintln!("skip untracked path {} during rustfmt invocations", untracked_path);
                ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path);
            }
        } else {
            eprintln!("Not in git tree. Skipping git-aware format checks");
        }
    } else {
        eprintln!("Could not find usable git. Skipping git-aware format checks");
    }
    let ignore_fmt = ignore_fmt.build().unwrap();

    let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| {
        eprintln!("./x.py fmt is not supported on this channel");
        std::process::exit(1);
    });
    let src = build.src.clone();
    let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
    walker.run(|| {
        let src = src.clone();
        let rustfmt_path = rustfmt_path.clone();
        Box::new(move |entry| {
            let entry = t!(entry);
            if entry.file_type().map_or(false, |t| t.is_file()) {
                rustfmt(&src, &rustfmt_path, &entry.path(), check);
            }
            ignore::WalkState::Continue
        })
    });
}
<commit_msg>bootstrap: fix typo<commit_after>//! Runs rustfmt on the repository.

use crate::Build;
use build_helper::{output, t};
use ignore::WalkBuilder;
use std::path::Path;
use std::process::{Command, Stdio};

fn rustfmt(src: &Path, rustfmt: &Path, path: &Path, check: bool) {
    let mut cmd = Command::new(&rustfmt);
    // avoid the submodule config paths from coming into play,
    // we only allow a single global config for the workspace for now
    cmd.arg("--config-path").arg(&src.canonicalize().unwrap());
    cmd.arg("--edition").arg("2018");
    cmd.arg("--unstable-features");
    cmd.arg("--skip-children");
    if check {
        cmd.arg("--check");
    }
    cmd.arg(&path);
    let cmd_debug = format!("{:?}", cmd);
    let status = cmd.status().expect("executing rustfmt");
    if !status.success() {
        eprintln!(
            "Running `{}` failed.\nIf you're running `tidy`, \
            try again with `--bless`. Or, if you just want to format \
            code, run `./x.py fmt` instead.",
            cmd_debug,
        );
        std::process::exit(1);
    }
}

#[derive(serde::Deserialize)]
struct RustfmtConfig {
    ignore: Vec<String>,
}

pub fn format(build: &Build, check: bool) {
    if build.config.dry_run {
        return;
    }
    let mut builder = ignore::types::TypesBuilder::new();
    builder.add_defaults();
    builder.select("rust");
    let matcher = builder.build().unwrap();
    let rustfmt_config = build.src.join("rustfmt.toml");
    if !rustfmt_config.exists() {
        eprintln!("Not running formatting checks; rustfmt.toml does not exist.");
        eprintln!("This may happen in distributed tarballs.");
        return;
    }
    let rustfmt_config = t!(std::fs::read_to_string(&rustfmt_config));
    let rustfmt_config: RustfmtConfig = t!(toml::from_str(&rustfmt_config));
    let mut ignore_fmt = ignore::overrides::OverrideBuilder::new(&build.src);
    for ignore in rustfmt_config.ignore {
        ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore);
    }
    let git_available = match Command::new("git")
        .arg("--version")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status()
    {
        Ok(status) => status.success(),
        Err(_) => false,
    };
    if git_available {
        let in_working_tree = match Command::new("git")
            .arg("rev-parse")
            .arg("--is-inside-work-tree")
            .stdout(Stdio::null())
            .stderr(Stdio::null())
            .status()
        {
            Ok(status) => status.success(),
            Err(_) => false,
        };
        if in_working_tree {
            let untracked_paths_output = output(
                Command::new("git")
                    .arg("status")
                    .arg("--porcelain")
                    .arg("--untracked-files=normal"),
            );
            let untracked_paths = untracked_paths_output
                .lines()
                .filter(|entry| entry.starts_with("??"))
                .map(|entry| {
                    entry.split(" ").nth(1).expect("every git status entry should list a path")
                });
            for untracked_path in untracked_paths {
                eprintln!("skip untracked path {} during rustfmt invocations", untracked_path);
                ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path);
            }
        } else {
            eprintln!("Not in git tree. Skipping git-aware format checks");
        }
    } else {
        eprintln!("Could not find usable git. Skipping git-aware format checks");
    }
    let ignore_fmt = ignore_fmt.build().unwrap();

    let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| {
        eprintln!("./x.py fmt is not supported on this channel");
        std::process::exit(1);
    });
    let src = build.src.clone();
    let walker = WalkBuilder::new(&build.src).types(matcher).overrides(ignore_fmt).build_parallel();
    walker.run(|| {
        let src = src.clone();
        let rustfmt_path = rustfmt_path.clone();
        Box::new(move |entry| {
            let entry = t!(entry);
            if entry.file_type().map_or(false, |t| t.is_file()) {
                rustfmt(&src, &rustfmt_path, &entry.path(), check);
            }
            ignore::WalkState::Continue
        })
    });
}
<|endoftext|>


<commit_before>use calx_ecs::{Entity};
use calx::color::*;
use calx::{Rgba};
use content::{Biome, FormType, Brush};
use content::Biome::*;
use world::{Component};
use stats::{Stats, Intrinsic};
use stats::Intrinsic::*;
use components::{Desc, Brain, Health};
use world::{World, Loadout};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Forms {
    Player,
    Dreg,
    Snake,
    Ooze,
}

/// Forms are the prototypes for the entities you create.
pub struct Form {
    /// Types of areas where this entity can spawn.
    pub biome: Biome,
    /// Weight of this entity in the random sampling distribution.
    ///
    /// The convention is that commonness 1000 is the average value. Things
    /// that never spawn randomly have commonness 0.
    pub commonness: u32,
    /// Minimum depth where the entity will show up. More powerful entities
    /// only start showing up in large depths.
    pub min_depth: i32,
    /// Type of thing
    pub category: FormType,
    /// Actual components to set up the thing.
    pub loadout: Loadout,
}

impl Form {
    /// Create a standard form for a living creature.
    pub fn mob(
        name: &str,
        icon: Brush,
        color: Rgba,
        power: i32,
        intrinsics: &[Intrinsic]) -> Form {
        Form {
            biome: Anywhere,
            commonness: 1000,
            min_depth: 0,
            category: FormType::Creature,
            loadout: Loadout::new()
                .c(Stats::new(power, intrinsics))
                .c(Desc::new(name, icon, color))
                .c(Brain::enemy())
                .c(Health::new()),
        }
    }

    pub fn common(mut self, commonness: u32) -> Form {
        self.commonness = commonness;
        self
    }

    pub fn depth(mut self, min_depth: i32) -> Form {
        self.min_depth = min_depth;
        self
    }

    pub fn biome(mut self, biome: Biome) -> Form {
        self.biome = biome;
        self
    }

    /// Build a new entity with this form.
    pub fn build(&self, w: &mut World) -> Entity {
        self.loadout.make(&mut w.ecs)
    }
}

thread_local!(static FORMS: Vec<Form> = init_forms());

fn init_forms() -> Vec<Form> {
    vec![
        Form::mob("player",     Brush::Human,   AZURE,      10, &[Hands]).common(0),
        Form::mob("dreg",       Brush::Dreg,    OLIVE,      1,  &[Hands]),
        Form::mob("snake",      Brush::Snake,   GREEN,      1,  &[]).biome(Overland),
    ]
}
<commit_msg>Forms access function<commit_after>use calx_ecs::{Entity};
use calx::color::*;
use calx::{Rgba};
use content::{Biome, FormType, Brush};
use content::Biome::*;
use world::{Component};
use stats::{Stats, Intrinsic};
use stats::Intrinsic::*;
use components::{Desc, Brain, Health};
use world::{World, Loadout};

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Forms {
    Player,
    Dreg,
    Snake,
    Ooze,
}

/// Forms are the prototypes for the entities you create.
#[derive(Clone, Debug)]
pub struct Form {
    /// Types of areas where this entity can spawn.
    pub biome: Biome,
    /// Weight of this entity in the random sampling distribution.
    ///
    /// The convention is that commonness 1000 is the average value. Things
    /// that never spawn randomly have commonness 0.
    pub commonness: u32,
    /// Minimum depth where the entity will show up. More powerful entities
    /// only start showing up in large depths.
    pub min_depth: i32,
    /// Type of thing
    pub category: FormType,
    /// Actual components to set up the thing.
    pub loadout: Loadout,
}

impl Form {
    /// Create a standard form for a living creature.
    pub fn mob(
        name: &str,
        icon: Brush,
        color: Rgba,
        power: i32,
        intrinsics: &[Intrinsic]) -> Form {
        Form {
            biome: Anywhere,
            commonness: 1000,
            min_depth: 0,
            category: FormType::Creature,
            loadout: Loadout::new()
                .c(Stats::new(power, intrinsics))
                .c(Desc::new(name, icon, color))
                .c(Brain::enemy())
                .c(Health::new()),
        }
    }

    pub fn common(mut self, commonness: u32) -> Form {
        self.commonness = commonness;
        self
    }

    pub fn depth(mut self, min_depth: i32) -> Form {
        self.min_depth = min_depth;
        self
    }

    pub fn biome(mut self, biome: Biome) -> Form {
        self.biome = biome;
        self
    }

    /// Build a new entity with this form.
    pub fn build(&self, w: &mut World) -> Entity {
        self.loadout.make(&mut w.ecs)
    }
}

thread_local!(static FORMS: Vec<Form> = init_forms());

fn init_forms() -> Vec<Form> {
    vec![
        Form::mob("player",     Brush::Human,   AZURE,      10, &[Hands]).common(0),
        Form::mob("dreg",       Brush::Dreg,    OLIVE,      1,  &[Hands]),
        Form::mob("snake",      Brush::Snake,   GREEN,      1,  &[]).biome(Overland),
    ]
}

/// Perform operations on the collection of entity forms.
pub fn with_forms<F, U>(f: F) -> U
  where F: FnOnce(&Vec<Form>) -> U + 'static + Sized {
    FORMS.with(|v| f(v))
}
<|endoftext|>


<commit_before>/// Creates a [`Vec`] containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a [`Vec`] containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a [`Vec`] from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement [`Clone`] and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// Also, note that `vec![expr; 0]` is allowed, and produces an empty vector.
/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
/// be mindful of side effects.
///
/// [`Vec`]: crate::vec::Vec
#[cfg(not(test))]
#[doc(alias = "alloc")]
#[doc(alias = "malloc")]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax, liballoc_internals)]
macro_rules! vec {
    () => (
        $crate::__rust_force_expr!($crate::vec::Vec::new())
    );
    ($elem:expr; $n:expr) => (
        $crate::__rust_force_expr!($crate::vec::from_elem($elem, $n))
    );
    ($($x:expr),+ $(,)?) => (
        $crate::__rust_force_expr!(<[_]>::into_vec(box [$($x),+]))
    );
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    () => (
        $crate::vec::Vec::new()
    );
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Creates a `String` using interpolation of runtime expressions.
///
/// The first argument `format!` receives is a format string. This must be a string
/// literal. The power of the formatting string is in the `{}`s contained.
///
/// Additional parameters passed to `format!` replace the `{}`s within the
/// formatting string in the order given unless named or positional parameters
/// are used; see [`std::fmt`] for more information.
///
/// A common use for `format!` is concatenation and interpolation of strings.
/// The same convention is used with [`print!`] and [`write!`] macros,
/// depending on the intended destination of the string.
///
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [`std::fmt`]: ../std/fmt/index.html
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: core::write
/// [`to_string`]: crate::string::ToString
/// [`Display`]: core::fmt::Display
///
/// # Panics
///
/// `format!` panics if a formatting trait implementation returns an error.
/// This indicates an incorrect implementation
/// since `fmt::Write for String` never returns an error itself.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "format_macro"]
macro_rules! format {
    ($($arg:tt)*) => {{
        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
        res
    }}
}

/// Force AST node to an expression to improve diagnostics in pattern position.
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
macro_rules! __rust_force_expr {
    ($e:expr) => {
        $e
    };
}
<commit_msg>Only define rustc_diagnostic_item format_macro in not(test).<commit_after>/// Creates a [`Vec`] containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a [`Vec`] containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a [`Vec`] from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement [`Clone`] and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
///
/// Also, note that `vec![expr; 0]` is allowed, and produces an empty vector.
/// This will still evaluate `expr`, however, and immediately drop the resulting value, so
/// be mindful of side effects.
///
/// [`Vec`]: crate::vec::Vec
#[cfg(not(test))]
#[doc(alias = "alloc")]
#[doc(alias = "malloc")]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(box_syntax, liballoc_internals)]
macro_rules! vec {
    () => (
        $crate::__rust_force_expr!($crate::vec::Vec::new())
    );
    ($elem:expr; $n:expr) => (
        $crate::__rust_force_expr!($crate::vec::from_elem($elem, $n))
    );
    ($($x:expr),+ $(,)?) => (
        $crate::__rust_force_expr!(<[_]>::into_vec(box [$($x),+]))
    );
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    () => (
        $crate::vec::Vec::new()
    );
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec(box [$($x),*])
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Creates a `String` using interpolation of runtime expressions.
///
/// The first argument `format!` receives is a format string. This must be a string
/// literal. The power of the formatting string is in the `{}`s contained.
///
/// Additional parameters passed to `format!` replace the `{}`s within the
/// formatting string in the order given unless named or positional parameters
/// are used; see [`std::fmt`] for more information.
///
/// A common use for `format!` is concatenation and interpolation of strings.
/// The same convention is used with [`print!`] and [`write!`] macros,
/// depending on the intended destination of the string.
///
/// To convert a single value to a string, use the [`to_string`] method. This
/// will use the [`Display`] formatting trait.
///
/// [`std::fmt`]: ../std/fmt/index.html
/// [`print!`]: ../std/macro.print.html
/// [`write!`]: core::write
/// [`to_string`]: crate::string::ToString
/// [`Display`]: core::fmt::Display
///
/// # Panics
///
/// `format!` panics if a formatting trait implementation returns an error.
/// This indicates an incorrect implementation
/// since `fmt::Write for String` never returns an error itself.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")]
macro_rules! format {
    ($($arg:tt)*) => {{
        let res = $crate::fmt::format($crate::__export::format_args!($($arg)*));
        res
    }}
}

/// Force AST node to an expression to improve diagnostics in pattern position.
#[doc(hidden)]
#[macro_export]
#[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
macro_rules! __rust_force_expr {
    ($e:expr) => {
        $e
    };
}
<|endoftext|>


<commit_before>use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_keyboard::{self, WlKeyboard, KeyState, KeymapFormat};
use wayland_client::protocol::wl_surface::WlSurface;

use std::fs::File;
use std::ptr;
use std::os::unix::io::{FromRawFd, RawFd};

use memmap::{Mmap, Protection};

use ffi;
use ffi::XKBCOMMON_HANDLE as XKBH;

struct KbState {
    xkb_context: *mut ffi::xkb_context,
    xkb_keymap: *mut ffi::xkb_keymap,
    xkb_state: *mut ffi::xkb_state
}

impl KbState {
    fn update_modifiers(&mut self, mods_depressed: u32, mods_latched: u32, mods_locked: u32, group: u32) {
        unsafe {
            (XKBH.xkb_state_update_mask)(
                self.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
        }
    }

    pub fn get_one_sym(&self, keycode: u32) -> u32 {
        unsafe {
            (XKBH.xkb_state_key_get_one_sym)(
                self.xkb_state, keycode + 8)
        }
    }

    pub fn get_utf8(&self, keycode: u32) -> Option<String> {
        let size = unsafe {
            (XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode + 8, ptr::null_mut(), 0)
        } + 1;
        if size <= 1 { return None };
        let mut buffer = Vec::with_capacity(size as usize);
        unsafe {
            buffer.set_len(size as usize);
            (XKBH.xkb_state_key_get_utf8)(
                self.xkb_state, keycode + 8, buffer.as_mut_ptr() as *mut _, size as usize);
        };
        // remove the final `\0`
        buffer.pop();
        // libxkbcommon will always provide valid UTF8
        Some(unsafe { String::from_utf8_unchecked(buffer) } )
    }
}

impl Drop for KbState {
    fn drop(&mut self) {
        unsafe {
            (XKBH.xkb_state_unref)(self.xkb_state);
            (XKBH.xkb_keymap_unref)(self.xkb_keymap);
            (XKBH.xkb_context_unref)(self.xkb_context);
        }
    }
}

/// A wayland keyboard mapped to its keymap
///
/// It wraps an event iterator on this keyboard, catching the Keymap, Key, and Modifiers
/// events of the keyboard to handle them using libxkbcommon. All other events are directly
/// forwarded.
pub struct MappedKeyboard<H: Handler> {
    state: KbState,
    handler: H
}

pub enum MappedKeyboardError {
    XKBNotFound,
    NoKeyboardOnSeat
}

impl<H: Handler> MappedKeyboard<H> {
    pub fn new(handler: H) -> Result<MappedKeyboard<H>, MappedKeyboardError> {
        let xkbh = match ffi::XKBCOMMON_OPTION.as_ref() {
            Some(h) => h,
            None => return Err(MappedKeyboardError::XKBNotFound)
        };
        let xkb_context = unsafe {
            (xkbh.xkb_context_new)(ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS)
        };
        if xkb_context.is_null() { return Err(MappedKeyboardError::XKBNotFound) }

        Ok(MappedKeyboard {
            state: KbState {
                xkb_context: xkb_context,
                xkb_keymap: ptr::null_mut(),
                xkb_state: ptr::null_mut()
            },
            handler: handler
        })
    }

    fn init(&mut self, fd: RawFd, size: usize) {
        let mut state = &mut self.state;

        let map = unsafe {
            Mmap::open_with_offset(&File::from_raw_fd(fd), Protection::Read, 0, size).unwrap()
        };

        let xkb_keymap = {
            unsafe {
                (XKBH.xkb_keymap_new_from_string)(
                    state.xkb_context,
                    map.ptr() as *const _,
                    ffi::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
                    ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS
                )
            }
        };

        if xkb_keymap.is_null() {
            panic!("Failed to load keymap!");
        }

        let xkb_state = unsafe {
            (XKBH.xkb_state_new)(xkb_keymap)
        };

        state.xkb_keymap = xkb_keymap;
        state.xkb_state = xkb_state;
    }
}

#[allow(unused_variables)]
pub trait Handler {
    fn enter(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface, rawkeys: &[u32], keysyms: &[u32]) {
    }

    fn leave(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface) {
    }

    fn key(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, time: u32, rawkey: u32, keysym: u32, state: KeyState, utf8: Option<String>) {
    }

    fn repeat_info(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, rate: i32, delay: i32) {
    }
}

impl<H: Handler> wl_keyboard::Handler for MappedKeyboard<H> {
    fn keymap(&mut self, _: &mut EventQueueHandle, _: &WlKeyboard, _: KeymapFormat, fd: RawFd, size: u32) {
        self.init(fd, size as usize)
    }

    fn enter(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface, keys: Vec<u8>) {
        let rawkeys: &[u32] = unsafe { ::std::slice::from_raw_parts(keys.as_ptr() as *const u32, keys.len()/4) };
        let keys: Vec<u32> = rawkeys.iter().map(|k| self.state.get_one_sym(*k)).collect();
        self.handler.enter(evqh, proxy, serial, surface, rawkeys, &keys)
    }

    fn leave(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface) {
        self.handler.leave(evqh, proxy, serial, surface)
    }

    fn key(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, time: u32, key: u32, state: KeyState) {
        let sym = self.state.get_one_sym(key);
        let utf8 = self.state.get_utf8(key);
        self.handler.key(evqh, proxy, serial, time, key, sym, state, utf8)
    }

    fn modifiers(&mut self, _: &mut EventQueueHandle, _: &WlKeyboard, _: u32, mods_depressed: u32, mods_latched: u32, mods_locked: u32, group: u32) {
        self.state.update_modifiers(mods_depressed, mods_latched, mods_locked, group)
    }

    fn repeat_info(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, rate: i32, delay: i32) {
        self.handler.repeat_info(evqh, proxy, rate, delay)
    }
}

unsafe impl<H: Handler> ::wayland_client::Handler<WlKeyboard> for MappedKeyboard<H> {
    unsafe fn message(&mut self, evq: &mut EventQueueHandle, proxy: &WlKeyboard, opcode: u32, args: *const ::wayland_client::sys::wl_argument) -> Result<(),()> {
        <MappedKeyboard<H> as ::wayland_client::protocol::wl_keyboard::Handler>::__message(self, evq, proxy, opcode, args)
    }
}
<commit_msg>Add access to handler<commit_after>use wayland_client::EventQueueHandle;
use wayland_client::protocol::wl_keyboard::{self, WlKeyboard, KeyState, KeymapFormat};
use wayland_client::protocol::wl_surface::WlSurface;

use std::fs::File;
use std::ptr;
use std::os::unix::io::{FromRawFd, RawFd};

use memmap::{Mmap, Protection};

use ffi;
use ffi::XKBCOMMON_HANDLE as XKBH;

struct KbState {
    xkb_context: *mut ffi::xkb_context,
    xkb_keymap: *mut ffi::xkb_keymap,
    xkb_state: *mut ffi::xkb_state
}

impl KbState {
    fn update_modifiers(&mut self, mods_depressed: u32, mods_latched: u32, mods_locked: u32, group: u32) {
        unsafe {
            (XKBH.xkb_state_update_mask)(
                self.xkb_state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
        }
    }

    pub fn get_one_sym(&self, keycode: u32) -> u32 {
        unsafe {
            (XKBH.xkb_state_key_get_one_sym)(
                self.xkb_state, keycode + 8)
        }
    }

    pub fn get_utf8(&self, keycode: u32) -> Option<String> {
        let size = unsafe {
            (XKBH.xkb_state_key_get_utf8)(self.xkb_state, keycode + 8, ptr::null_mut(), 0)
        } + 1;
        if size <= 1 { return None };
        let mut buffer = Vec::with_capacity(size as usize);
        unsafe {
            buffer.set_len(size as usize);
            (XKBH.xkb_state_key_get_utf8)(
                self.xkb_state, keycode + 8, buffer.as_mut_ptr() as *mut _, size as usize);
        };
        // remove the final `\0`
        buffer.pop();
        // libxkbcommon will always provide valid UTF8
        Some(unsafe { String::from_utf8_unchecked(buffer) } )
    }
}

impl Drop for KbState {
    fn drop(&mut self) {
        unsafe {
            (XKBH.xkb_state_unref)(self.xkb_state);
            (XKBH.xkb_keymap_unref)(self.xkb_keymap);
            (XKBH.xkb_context_unref)(self.xkb_context);
        }
    }
}

/// A wayland keyboard mapped to its keymap
///
/// It wraps an event iterator on this keyboard, catching the Keymap, Key, and Modifiers
/// events of the keyboard to handle them using libxkbcommon. All other events are directly
/// forwarded.
pub struct MappedKeyboard<H: Handler> {
    state: KbState,
    handler: H
}

pub enum MappedKeyboardError {
    XKBNotFound,
    NoKeyboardOnSeat
}

impl<H: Handler> MappedKeyboard<H> {
    pub fn new(handler: H) -> Result<MappedKeyboard<H>, MappedKeyboardError> {
        let xkbh = match ffi::XKBCOMMON_OPTION.as_ref() {
            Some(h) => h,
            None => return Err(MappedKeyboardError::XKBNotFound)
        };
        let xkb_context = unsafe {
            (xkbh.xkb_context_new)(ffi::xkb_context_flags::XKB_CONTEXT_NO_FLAGS)
        };
        if xkb_context.is_null() { return Err(MappedKeyboardError::XKBNotFound) }

        Ok(MappedKeyboard {
            state: KbState {
                xkb_context: xkb_context,
                xkb_keymap: ptr::null_mut(),
                xkb_state: ptr::null_mut()
            },
            handler: handler
        })
    }

    fn init(&mut self, fd: RawFd, size: usize) {
        let mut state = &mut self.state;

        let map = unsafe {
            Mmap::open_with_offset(&File::from_raw_fd(fd), Protection::Read, 0, size).unwrap()
        };

        let xkb_keymap = {
            unsafe {
                (XKBH.xkb_keymap_new_from_string)(
                    state.xkb_context,
                    map.ptr() as *const _,
                    ffi::xkb_keymap_format::XKB_KEYMAP_FORMAT_TEXT_V1,
                    ffi::xkb_keymap_compile_flags::XKB_KEYMAP_COMPILE_NO_FLAGS
                )
            }
        };

        if xkb_keymap.is_null() {
            panic!("Failed to load keymap!");
        }

        let xkb_state = unsafe {
            (XKBH.xkb_state_new)(xkb_keymap)
        };

        state.xkb_keymap = xkb_keymap;
        state.xkb_state = xkb_state;
    }

    pub fn handler(&mut self) -> &mut H {
        &mut self.handler
    }
}

#[allow(unused_variables)]
pub trait Handler {
    fn enter(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface, rawkeys: &[u32], keysyms: &[u32]) {
    }

    fn leave(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface) {
    }

    fn key(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, time: u32, rawkey: u32, keysym: u32, state: KeyState, utf8: Option<String>) {
    }

    fn repeat_info(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, rate: i32, delay: i32) {
    }
}

impl<H: Handler> wl_keyboard::Handler for MappedKeyboard<H> {
    fn keymap(&mut self, _: &mut EventQueueHandle, _: &WlKeyboard, _: KeymapFormat, fd: RawFd, size: u32) {
        self.init(fd, size as usize)
    }

    fn enter(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface, keys: Vec<u8>) {
        let rawkeys: &[u32] = unsafe { ::std::slice::from_raw_parts(keys.as_ptr() as *const u32, keys.len()/4) };
        let keys: Vec<u32> = rawkeys.iter().map(|k| self.state.get_one_sym(*k)).collect();
        self.handler.enter(evqh, proxy, serial, surface, rawkeys, &keys)
    }

    fn leave(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, surface: &WlSurface) {
        self.handler.leave(evqh, proxy, serial, surface)
    }

    fn key(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, serial: u32, time: u32, key: u32, state: KeyState) {
        let sym = self.state.get_one_sym(key);
        let utf8 = self.state.get_utf8(key);
        self.handler.key(evqh, proxy, serial, time, key, sym, state, utf8)
    }

    fn modifiers(&mut self, _: &mut EventQueueHandle, _: &WlKeyboard, _: u32, mods_depressed: u32, mods_latched: u32, mods_locked: u32, group: u32) {
        self.state.update_modifiers(mods_depressed, mods_latched, mods_locked, group)
    }

    fn repeat_info(&mut self, evqh: &mut EventQueueHandle, proxy: &WlKeyboard, rate: i32, delay: i32) {
        self.handler.repeat_info(evqh, proxy, rate, delay)
    }
}

unsafe impl<H: Handler> ::wayland_client::Handler<WlKeyboard> for MappedKeyboard<H> {
    unsafe fn message(&mut self, evq: &mut EventQueueHandle, proxy: &WlKeyboard, opcode: u32, args: *const ::wayland_client::sys::wl_argument) -> Result<(),()> {
        <MappedKeyboard<H> as ::wayland_client::protocol::wl_keyboard::Handler>::__message(self, evq, proxy, opcode, args)
    }
}
<|endoftext|>


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

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use math::Vec3;
use qw::{self, ClCmd, Message, PacketEntities, QwSocket, SockType, SvCmd, UserCmd, UserInfo};
use std;
use std::default::Default;
use std::io::{Cursor, Read, Write};
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::str::{self, FromStr};
use time::{Duration, PreciseTime};

const RETRY_INTERVAL: i64 = 5;
const MAX_CLIENTS: usize = 32;
const MAX_QUEUED_UPDATES: usize = 64;

#[derive(Copy, Clone, PartialEq, PartialOrd)]
pub enum CxnStatus {
    Disconnected = 0,
    DemoStart = 1,
    Connected = 2,
    OnServer = 3,
    Active = 4,
}

#[derive(Copy, Clone)]
pub struct PlayerState {
    message: usize,
    time: PreciseTime,
    cmd: UserCmd,
    origin: Vec3,
    angles: Vec3,
    velocity: Vec3, // TODO: finish this up
}

pub struct Update {
    // main content of the update
    cmd: UserCmd,

    // when this update was initially sent
    time_sent: Duration,

    // sequence number to delta from, or None if full update
    delta: Option<usize>,

    // when this update was received, or None if it hasn't been
    time_received: Option<Duration>,

    // last updated position of each player
    player_state: [Option<PlayerState>; MAX_CLIENTS],

    packet_entities: PacketEntities,

    // whether the packet_entities delta was valid
    valid: bool,
}

impl Default for Update {
    fn default() -> Update {
        Update {
            cmd: UserCmd::default(),
            time_sent: Duration::zero(),
            delta: None,
            time_received: None,
            player_state: [None; MAX_CLIENTS],
            packet_entities: Box::default(),
            valid: false,
        }
    }
}

pub struct Client {
    socket: QwSocket,
    challenge: i32,
    cxn_status: CxnStatus,

    /// The last time this client sent a connection request to the server.
    cxn_time: Option<PreciseTime>,
    user_info: UserInfo,

    /// The last MAX_QUEUED_UPDATES updates the client received.
    updates: Vec<Update>,
}

impl Client {
    /// Create a new `Client` by initiating a connection to `server`. The client
    /// will request a challenge from the server and then begin normal operation.
    pub fn connect(server: Ipv4Addr) -> Client {
        let remote = SocketAddr::V4(SocketAddrV4::new(server, qw::PORT_SERVER));

        let mut client = Client {
            socket: QwSocket::bind(remote, SockType::Client).unwrap(),
            challenge: 0,
            cxn_status: CxnStatus::Disconnected,
            cxn_time: None,
            user_info: UserInfo::default(),
            updates: Vec::new(),
        };

        client
            .socket
            .out_of_band("getchallenge\n".as_bytes())
            .unwrap();
        client
    }

    /// Sends a connection message to the server.
    ///
    /// Connection messages are out-band-messages of the form:
    ///
    /// ```text
    /// connect <qw> <qport> <challenge> <userinfo>
    /// ```
    ///
    /// If all goes well, the server will reply with an out-of-band message
    /// containing a single 'j'.
    pub fn send_connect(&mut self) {
        let connect = format!(
            "connect {} {} {} \"{}\"",
            qw::VERSION,
            27001,
            self.challenge,
            self.user_info.serialize()
        );
        debug!("Sending connect message: {}", connect);
        self.socket.out_of_band(connect.as_bytes()).unwrap();
        self.cxn_time = Some(PreciseTime::now());
    }

    pub fn retry_connect(&mut self) {
        if let Some(x) = self.cxn_time {
            if x.to(PreciseTime::now()) > Duration::seconds(RETRY_INTERVAL) {
                debug!("Five seconds elapsed, retrying...");
                self.send_connect();
            }
        }
    }

    pub fn read_packets(&mut self) -> Result<(), qw::NetworkError> {
        loop {
            match self.socket.process()? {
                Message::InBand => self.parse_msg(),
                Message::OutOfBand(mut msg) => self.proc_outofband(&mut *msg),
                Message::None => break,
            }
        }

        Ok(())
    }

    pub fn parse_msg(&mut self) {
        loop {
            use num::FromPrimitive;

            let first = self.socket.read_u8().unwrap();

            if first == std::u8::MAX {
                // self.parse_readcount++
                break;
            }

            let cmd: SvCmd = match FromPrimitive::from_u8(first) {
                Some(c) => c,
                None => break,
            };

            match cmd {
                SvCmd::ServerData => self.parse_serverdata(),
                _ => panic!("No handler for {:?}", cmd),
            };
        }
    }

    /// Parse data sent by the server in a SvCmd::ServerData message.
    ///
    /// see Quake/QW/client/cl_parse.c:525
    ///
    /// Server data is sent in the following format:
    ///
    /// ```text
    /// qw version: u32
    /// server count: u32
    /// game directory: null-terminated string
    /// player number: u8
    /// level name: null-terminated string
    /// gravity: f32
    /// max speed: f32
    /// max spec speed: f32
    /// acceleration: f32
    /// air acceleration: f32
    /// water acceleration: f32
    /// friction: f32
    /// water friction: f32
    /// entity gravity: f32
    /// ```
    pub fn parse_serverdata(&mut self) {
        let qw = self.socket.read_u32::<LittleEndian>().unwrap();

        if qw != qw::VERSION {
            // TODO: allow demo playback on versions 26-29
            // otherwise end the game
            panic!("Bad version handler unimplemented");
        }

        let servcount = self.socket.read_u32::<LittleEndian>().unwrap();

        let mut gamedir_bytes: Vec<u8> = Vec::new();
        loop {
            match self.socket.read_u8().unwrap() {
                0 => break,
                c => gamedir_bytes.push(c),
            }
        }
        let gamedir_str = String::from_utf8(gamedir_bytes).unwrap();

        // TODO: if current game dir differs, do host_writeconfig
    }

    pub fn proc_outofband(&mut self, msg: &[u8]) {
        let mut curs = Cursor::new(msg);

        match curs.read_u8().unwrap() as char {
            'c' => {
                // challenge
                debug!("Received challenge from server");
                let mut challenge_bytes = Vec::new();
                curs.read_to_end(&mut challenge_bytes).unwrap();

                let challenge_str = match str::from_utf8(&challenge_bytes) {
                    Ok(s) => s,
                    Err(why) => {
                        warn!("Bad challenge from server.");
                        ""
                    }
                };

                debug!("{:?}", challenge_str);

                let challenge = match i32::from_str(&challenge_str) {
                    Ok(n) => n,
                    Err(why) => {
                        warn!("Bad challenge from server ({}): \"{}\"", why, challenge_str);
                        0
                    }
                };

                self.challenge = challenge;
                self.send_connect();
            }

            'j' => {
                // connection
                if self.cxn_status >= CxnStatus::Connected {
                    return;
                }

                debug!("Server accepted connection request");
                self.cxn_status = CxnStatus::Connected;

                self.socket.write_u8(ClCmd::StringCmd as u8).unwrap();
                self.socket.write("new".as_bytes()).unwrap();
                self.socket.write_u8(0).unwrap();
                self.socket.transmit().unwrap();
            }

            'k' => {
                // ping
                debug!("Received ping");
                self.socket.out_of_band(&['l' as u8, 0]);
            }

            _ => panic!("Unrecognized out-of-band message"),
        }
    }

    pub fn get_cxn_status(&self) -> CxnStatus {
        self.cxn_status
    }
}
<commit_msg>Remove QuakeWorld client module<commit_after><|endoftext|>


<commit_before>use hyper::Client as HttpClient;
use hyper::header::{Connection, ContentType};
use hyper::client::response::Response;
use hyper::status::StatusCode;
use rustc_serialize::json;
use rustc_serialize::{Decodable, Encodable};

use Error;

use std::io::Read;
use std::string::ToString;
use std::error::Error as StdError;

pub const APP_KEY_URL: &'static str = "https://trello.com/app-key";
const BASE_URL: &'static str = "https://api.trello.com/1/";
const DEFAULT_SCOPE: &'static str = "read,write,account";
const DEFAULT_EXPIRATION: &'static str = "30days";

pub struct Client {
    app_key: String,
    token: String
}

impl Client {
    pub fn new(app_key: String, token: String) -> Client {
        Client {
            app_key: app_key,
            token: token
        }
    }

    pub fn authorize_url(app_name: &str, app_key: &str, scope: Option<&str>, expiration: Option<&str>) -> String {
        let mut url = BASE_URL.to_string() + "authorize?response_type=token";
        url = url + "&name=" + app_name;
        url = url + "&key=" + app_key;
        url = url + "&scope=" + scope.unwrap_or(DEFAULT_SCOPE);
        url = url + "&expiration=" + expiration.unwrap_or(DEFAULT_EXPIRATION);

        url
    }

    pub fn get<D: Decodable>(&self, path: &str) -> Result<D, Error> {
        let url = self.url_from_path(&path);

        let client = HttpClient::new();
        let mut res = client.get(&url)
            .header(Connection::close())
            .send()
            .unwrap();

        Self::handle_response(&mut res)
    }

    pub fn post<E: Encodable, D: Decodable>(&self, path: &str, obj: E) -> Result<D, Error> {
        let url  = self.url_from_path(&path);
        let body = json::encode(&obj).unwrap();

        let client  = HttpClient::new();
        let mut res = client.post(&url)
            .header(Connection::close())
            .header(ContentType::json())
            .body(&body)
            .send()
            .unwrap();

        Self::handle_response(&mut res)
    }

    pub fn delete(&self, path: &str) -> Result<(), Error> {
        let url  = self.url_from_path(&path);

        let client  = HttpClient::new();
        let mut res = client.delete(&url)
            .header(Connection::close())
            .header(ContentType::json())
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        match res.status {
            StatusCode::Ok | StatusCode::Created => Ok(()),
            StatusCode::Unauthorized             => Err(Error::Unauthorized),
            StatusCode::TooManyRequests          => Err(Error::TooManyRequests),
            StatusCode::BadRequest               => Err(Error::InvalidRequest(body)),
            _                                    => Err(Error::Unknown(body))
        }
    }

    fn url_from_path(&self, path: &str) -> String {
        let mut url = BASE_URL.to_string() + path;
        url = url + "?key=" + &self.app_key;
        url = url + "&token=" + &self.token;

        url
    }

    fn handle_response<D: Decodable>(response: &mut Response) -> Result<D, Error> {
        let mut body = String::new();
        response.read_to_string(&mut body).unwrap();

        match response.status {
            StatusCode::Ok | StatusCode::Created => Self::handle_json_response(&body),
            StatusCode::Unauthorized             => Err(Error::Unauthorized),
            StatusCode::TooManyRequests          => Err(Error::TooManyRequests),
            StatusCode::BadRequest               => Err(Error::InvalidRequest(body)),
            _                                    => Err(Error::Unknown(body))
        }
    }

    fn handle_json_response<D: Decodable>(body: &str) -> Result<D, Error> {
        match json::decode(body) {
            Ok(decodable)      => Ok(decodable),
            Err(decoder_error) => Err(Error::Json(decoder_error.description().to_string()))
        }
    }
}
<commit_msg>Print JSON body on Error::Json instead of useless description<commit_after>use hyper::Client as HttpClient;
use hyper::header::{Connection, ContentType};
use hyper::client::response::Response;
use hyper::status::StatusCode;
use rustc_serialize::json;
use rustc_serialize::{Decodable, Encodable};

use Error;

use std::io::Read;
use std::string::ToString;

pub const APP_KEY_URL: &'static str = "https://trello.com/app-key";
const BASE_URL: &'static str = "https://api.trello.com/1/";
const DEFAULT_SCOPE: &'static str = "read,write,account";
const DEFAULT_EXPIRATION: &'static str = "30days";

pub struct Client {
    app_key: String,
    token: String
}

impl Client {
    pub fn new(app_key: String, token: String) -> Client {
        Client {
            app_key: app_key,
            token: token
        }
    }

    pub fn authorize_url(app_name: &str, app_key: &str, scope: Option<&str>, expiration: Option<&str>) -> String {
        let mut url = BASE_URL.to_string() + "authorize?response_type=token";
        url = url + "&name=" + app_name;
        url = url + "&key=" + app_key;
        url = url + "&scope=" + scope.unwrap_or(DEFAULT_SCOPE);
        url = url + "&expiration=" + expiration.unwrap_or(DEFAULT_EXPIRATION);

        url
    }

    pub fn get<D: Decodable>(&self, path: &str) -> Result<D, Error> {
        let url = self.url_from_path(&path);

        let client = HttpClient::new();
        let mut res = client.get(&url)
            .header(Connection::close())
            .send()
            .unwrap();

        Self::handle_response(&mut res)
    }

    pub fn post<E: Encodable, D: Decodable>(&self, path: &str, obj: E) -> Result<D, Error> {
        let url  = self.url_from_path(&path);
        let body = json::encode(&obj).unwrap();

        let client  = HttpClient::new();
        let mut res = client.post(&url)
            .header(Connection::close())
            .header(ContentType::json())
            .body(&body)
            .send()
            .unwrap();

        Self::handle_response(&mut res)
    }

    pub fn delete(&self, path: &str) -> Result<(), Error> {
        let url  = self.url_from_path(&path);

        let client  = HttpClient::new();
        let mut res = client.delete(&url)
            .header(Connection::close())
            .header(ContentType::json())
            .send()
            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        match res.status {
            StatusCode::Ok | StatusCode::Created => Ok(()),
            StatusCode::Unauthorized             => Err(Error::Unauthorized),
            StatusCode::TooManyRequests          => Err(Error::TooManyRequests),
            StatusCode::BadRequest               => Err(Error::InvalidRequest(body)),
            _                                    => Err(Error::Unknown(body))
        }
    }

    fn url_from_path(&self, path: &str) -> String {
        let mut url = BASE_URL.to_string() + path;
        url = url + "?key=" + &self.app_key;
        url = url + "&token=" + &self.token;

        url
    }

    fn handle_response<D: Decodable>(response: &mut Response) -> Result<D, Error> {
        let mut body = String::new();
        response.read_to_string(&mut body).unwrap();

        match response.status {
            StatusCode::Ok | StatusCode::Created => Self::handle_json_response(&body),
            StatusCode::Unauthorized             => Err(Error::Unauthorized),
            StatusCode::TooManyRequests          => Err(Error::TooManyRequests),
            StatusCode::BadRequest               => Err(Error::InvalidRequest(body)),
            _                                    => Err(Error::Unknown(body))
        }
    }

    fn handle_json_response<D: Decodable>(body: &str) -> Result<D, Error> {
        match json::decode(body) {
            Ok(decodable)      => Ok(decodable),
            Err(_)             => Err(Error::Json(body.to_string()))
        }
    }
}
<|endoftext|>


<commit_before>use consumer::StompConfig;
use record_backend::MysqlConfig;
use monitor::Config as MonitorConfig;

pub static VERSION: &'static str = "0.5.0";

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct LogConfig {
  pub directory: String,
  pub levels: String
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct Config {
  pub log: LogConfig,
  pub threads: u32,
  pub stomp: StompConfig,
  pub mysql: MysqlConfig,
  pub monitor: MonitorConfig
}<commit_msg>show correct version number in server response<commit_after>use consumer::StompConfig;
use record_backend::MysqlConfig;
use monitor::Config as MonitorConfig;

pub static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct LogConfig {
  pub directory: String,
  pub levels: String
}

#[derive(Debug, Clone, RustcDecodable, RustcEncodable)]
pub struct Config {
  pub log: LogConfig,
  pub threads: u32,
  pub stomp: StompConfig,
  pub mysql: MysqlConfig,
  pub monitor: MonitorConfig
}<|endoftext|>


<commit_before>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use zdaemon::ConfigFile;

#[derive(Debug)]
#[derive(RustcDecodable, RustcEncodable)]
pub struct Config {
    pub language: String,
    pub artifact: String,
    pub auth_server: String,
}

impl ConfigFile for Config {}

impl Config {
    pub fn new(language: &str, artifact: &str, auth_server: &str) -> Config {
        Config {
            language: language.into(),
            artifact: artifact.into(),
            auth_server: auth_server.into(),
        }
    }
}
<commit_msg>Code cleanup<commit_after>// Copyright 2015-2016 Intecture Developers. See the COPYRIGHT file at the
// top-level directory of this distribution and at
// https://intecture.io/COPYRIGHT.
//
// Licensed under the Mozilla Public License 2.0 <LICENSE or
// https://www.tldrlegal.com/l/mpl-2.0>. This file may not be copied,
// modified, or distributed except according to those terms.

use zdaemon::ConfigFile;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Config {
    pub language: String,
    pub artifact: String,
    pub auth_server: String,
}

impl ConfigFile for Config {}

impl Config {
    pub fn new(language: &str, artifact: &str, auth_server: &str) -> Config {
        Config {
            language: language.into(),
            artifact: artifact.into(),
            auth_server: auth_server.into(),
        }
    }
}
<|endoftext|>