<commit_before>//! Solve Hermitian (or real symmetric) linear problems and invert Hermitian
//! (or real symmetric) matrices
//!
//! **Note that only the upper triangular portion of the matrix is used.**
//!
//! # Examples
//!
//! Solve `A * x = b`, where `A` is a Hermitian (or real symmetric) matrix:
//!
//! ```
//! #[macro_use]
//! extern crate ndarray;
//! extern crate ndarray_linalg;
//!
//! use ndarray::prelude::*;
//! use ndarray_linalg::SolveH;
//! # fn main() {
//!
//! let a: Array2<f64> = array![
//!     [3., 2., -1.],
//!     [2., -2., 4.],
//!     [-1., 4., 5.]
//! ];
//! let b: Array1<f64> = array![11., -12., 1.];
//! let x = a.solveh_into(b).unwrap();
//! assert!(x.all_close(&array![1., 3., -2.], 1e-9));
//!
//! # }
//! ```
//!
//! If you are solving multiple systems of linear equations with the same
//! Hermitian or real symmetric coefficient matrix `A`, it's faster to compute
//! the factorization once at the beginning than solving directly using `A`:
//!
//! ```
//! # extern crate ndarray;
//! # extern crate ndarray_linalg;
//! use ndarray::prelude::*;
//! use ndarray_linalg::*;
//! # fn main() {
//!
//! let a: Array2<f64> = random((3, 3));
//! let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed)
//! for _ in 0..10 {
//!     let b: Array1<f64> = random(3);
//!     let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization
//! }
//!
//! # }
//! ```

use ndarray::*;

use super::convert::*;
use super::error::*;
use super::layout::*;
use super::types::*;

pub use lapack_traits::{Pivot, UPLO};

/// An interface for solving systems of Hermitian (or real symmetric) linear equations.
///
/// If you plan to solve many equations with the same Hermitian (or real
/// symmetric) coefficient matrix `A` but different `b` vectors, it's faster to
/// factor the `A` matrix once using the `FactorizeH` trait, and then solve
/// using the `FactorizedH` struct.
pub trait SolveH<A: Scalar> {
    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
    /// `x` is the successful result.
    fn solveh<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
        let mut b = replicate(b);
        self.solveh_mut(&mut b)?;
        Ok(b)
    }
    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
    /// `x` is the successful result.
    fn solveh_into<S: DataMut<Elem = A>>(&self, mut b: ArrayBase<S, Ix1>) -> Result<ArrayBase<S, Ix1>> {
        self.solveh_mut(&mut b)?;
        Ok(b)
    }
    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
    /// `x` is the successful result. The value of `x` is also assigned to the
    /// argument.
    fn solveh_mut<'a, S: DataMut<Elem = A>>(&self, &'a mut ArrayBase<S, Ix1>) -> Result<&'a mut ArrayBase<S, Ix1>>;
}

/// Represents the Bunch–Kaufman factorization of a Hermitian (or real
/// symmetric) matrix as `A = P * U * D * U^H * P^T`.
pub struct FactorizedH<S: Data> {
    pub a: ArrayBase<S, Ix2>,
    pub ipiv: Pivot,
}

impl<A, S> SolveH<A> for FactorizedH<S>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    fn solveh_mut<'a, Sb>(&self, rhs: &'a mut ArrayBase<Sb, Ix1>) -> Result<&'a mut ArrayBase<Sb, Ix1>>
    where
        Sb: DataMut<Elem = A>,
    {
        unsafe {
            A::solveh(
                self.a.square_layout()?,
                UPLO::Upper,
                self.a.as_allocated()?,
                &self.ipiv,
                rhs.as_slice_mut().unwrap(),
            )?
        };
        Ok(rhs)
    }
}

impl<A, S> SolveH<A> for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    fn solveh_mut<'a, Sb>(&self, mut rhs: &'a mut ArrayBase<Sb, Ix1>) -> Result<&'a mut ArrayBase<Sb, Ix1>>
    where
        Sb: DataMut<Elem = A>,
    {
        let f = self.factorizeh()?;
        f.solveh_mut(rhs)
    }
}

/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
/// real symmetric) matrix refs.
pub trait FactorizeH<S: Data> {
    /// Computes the Bunch–Kaufman factorization of a Hermitian (or real
    /// symmetric) matrix.
    fn factorizeh(&self) -> Result<FactorizedH<S>>;
}

/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
/// real symmetric) matrices.
pub trait FactorizeHInto<S: Data> {
    /// Computes the Bunch–Kaufman factorization of a Hermitian (or real
    /// symmetric) matrix.
    fn factorizeh_into(self) -> Result<FactorizedH<S>>;
}

impl<A, S> FactorizeHInto<S> for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    fn factorizeh_into(mut self) -> Result<FactorizedH<S>> {
        let ipiv = unsafe { A::bk(self.layout()?, UPLO::Upper, self.as_allocated_mut()?)? };
        Ok(FactorizedH {
            a: self,
            ipiv: ipiv,
        })
    }
}

impl<A, Si> FactorizeH<OwnedRepr<A>> for ArrayBase<Si, Ix2>
where
    A: Scalar,
    Si: Data<Elem = A>,
{
    fn factorizeh(&self) -> Result<FactorizedH<OwnedRepr<A>>> {
        let mut a: Array2<A> = replicate(self);
        let ipiv = unsafe { A::bk(a.layout()?, UPLO::Upper, a.as_allocated_mut()?)? };
        Ok(FactorizedH { a: a, ipiv: ipiv })
    }
}

/// An interface for inverting Hermitian (or real symmetric) matrix refs.
pub trait InverseH {
    type Output;
    /// Computes the inverse of the Hermitian (or real symmetric) matrix.
    ///
    /// **Warning: The inverse is stored only in the upper triangular portion
    /// of the result matrix!** If you want the lower triangular portion to be
    /// correct, you must fill it in according to the results in the upper
    /// triangular portion.
    fn invh(&self) -> Result<Self::Output>;
}

/// An interface for inverting Hermitian (or real symmetric) matrices.
pub trait InverseHInto {
    type Output;
    /// Computes the inverse of the Hermitian (or real symmetric) matrix.
    ///
    /// **Warning: The inverse is stored only in the upper triangular portion
    /// of the result matrix!** If you want the lower triangular portion to be
    /// correct, you must fill it in according to the results in the upper
    /// triangular portion.
    fn invh_into(self) -> Result<Self::Output>;
}

impl<A, S> InverseHInto for FactorizedH<S>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type Output = ArrayBase<S, Ix2>;

    fn invh_into(mut self) -> Result<ArrayBase<S, Ix2>> {
        unsafe {
            A::invh(
                self.a.square_layout()?,
                UPLO::Upper,
                self.a.as_allocated_mut()?,
                &self.ipiv,
            )?
        };
        Ok(self.a)
    }
}

impl<A, S> InverseH for FactorizedH<S>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    type Output = Array2<A>;

    fn invh(&self) -> Result<Self::Output> {
        let f = FactorizedH {
            a: replicate(&self.a),
            ipiv: self.ipiv.clone(),
        };
        f.invh_into()
    }
}

impl<A, S> InverseHInto for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type Output = Self;

    fn invh_into(self) -> Result<Self::Output> {
        let f = self.factorizeh_into()?;
        f.invh_into()
    }
}

impl<A, Si> InverseH for ArrayBase<Si, Ix2>
where
    A: Scalar,
    Si: Data<Elem = A>,
{
    type Output = Array2<A>;

    fn invh(&self) -> Result<Self::Output> {
        let f = self.factorizeh()?;
        f.invh_into()
    }
}
<commit_msg>s/FactorizedH/BKFactorized/g<commit_after>//! Solve Hermitian (or real symmetric) linear problems and invert Hermitian
//! (or real symmetric) matrices
//!
//! **Note that only the upper triangular portion of the matrix is used.**
//!
//! # Examples
//!
//! Solve `A * x = b`, where `A` is a Hermitian (or real symmetric) matrix:
//!
//! ```
//! #[macro_use]
//! extern crate ndarray;
//! extern crate ndarray_linalg;
//!
//! use ndarray::prelude::*;
//! use ndarray_linalg::SolveH;
//! # fn main() {
//!
//! let a: Array2<f64> = array![
//!     [3., 2., -1.],
//!     [2., -2., 4.],
//!     [-1., 4., 5.]
//! ];
//! let b: Array1<f64> = array![11., -12., 1.];
//! let x = a.solveh_into(b).unwrap();
//! assert!(x.all_close(&array![1., 3., -2.], 1e-9));
//!
//! # }
//! ```
//!
//! If you are solving multiple systems of linear equations with the same
//! Hermitian or real symmetric coefficient matrix `A`, it's faster to compute
//! the factorization once at the beginning than solving directly using `A`:
//!
//! ```
//! # extern crate ndarray;
//! # extern crate ndarray_linalg;
//! use ndarray::prelude::*;
//! use ndarray_linalg::*;
//! # fn main() {
//!
//! let a: Array2<f64> = random((3, 3));
//! let f = a.factorizeh_into().unwrap(); // Factorize A (A is consumed)
//! for _ in 0..10 {
//!     let b: Array1<f64> = random(3);
//!     let x = f.solveh_into(b).unwrap(); // Solve A * x = b using the factorization
//! }
//!
//! # }
//! ```

use ndarray::*;

use super::convert::*;
use super::error::*;
use super::layout::*;
use super::types::*;

pub use lapack_traits::{Pivot, UPLO};

/// An interface for solving systems of Hermitian (or real symmetric) linear equations.
///
/// If you plan to solve many equations with the same Hermitian (or real
/// symmetric) coefficient matrix `A` but different `b` vectors, it's faster to
/// factor the `A` matrix once using the `FactorizeH` trait, and then solve
/// using the `BKFactorized` struct.
pub trait SolveH<A: Scalar> {
    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
    /// `x` is the successful result.
    fn solveh<S: Data<Elem = A>>(&self, b: &ArrayBase<S, Ix1>) -> Result<Array1<A>> {
        let mut b = replicate(b);
        self.solveh_mut(&mut b)?;
        Ok(b)
    }
    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
    /// `x` is the successful result.
    fn solveh_into<S: DataMut<Elem = A>>(&self, mut b: ArrayBase<S, Ix1>) -> Result<ArrayBase<S, Ix1>> {
        self.solveh_mut(&mut b)?;
        Ok(b)
    }
    /// Solves a system of linear equations `A * x = b` with Hermitian (or real
    /// symmetric) matrix `A`, where `A` is `self`, `b` is the argument, and
    /// `x` is the successful result. The value of `x` is also assigned to the
    /// argument.
    fn solveh_mut<'a, S: DataMut<Elem = A>>(&self, &'a mut ArrayBase<S, Ix1>) -> Result<&'a mut ArrayBase<S, Ix1>>;
}

/// Represents the Bunch–Kaufman factorization of a Hermitian (or real
/// symmetric) matrix as `A = P * U * D * U^H * P^T`.
pub struct BKFactorized<S: Data> {
    pub a: ArrayBase<S, Ix2>,
    pub ipiv: Pivot,
}

impl<A, S> SolveH<A> for BKFactorized<S>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    fn solveh_mut<'a, Sb>(&self, rhs: &'a mut ArrayBase<Sb, Ix1>) -> Result<&'a mut ArrayBase<Sb, Ix1>>
    where
        Sb: DataMut<Elem = A>,
    {
        unsafe {
            A::solveh(
                self.a.square_layout()?,
                UPLO::Upper,
                self.a.as_allocated()?,
                &self.ipiv,
                rhs.as_slice_mut().unwrap(),
            )?
        };
        Ok(rhs)
    }
}

impl<A, S> SolveH<A> for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    fn solveh_mut<'a, Sb>(&self, mut rhs: &'a mut ArrayBase<Sb, Ix1>) -> Result<&'a mut ArrayBase<Sb, Ix1>>
    where
        Sb: DataMut<Elem = A>,
    {
        let f = self.factorizeh()?;
        f.solveh_mut(rhs)
    }
}

/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
/// real symmetric) matrix refs.
pub trait FactorizeH<S: Data> {
    /// Computes the Bunch–Kaufman factorization of a Hermitian (or real
    /// symmetric) matrix.
    fn factorizeh(&self) -> Result<BKFactorized<S>>;
}

/// An interface for computing the Bunch–Kaufman factorization of Hermitian (or
/// real symmetric) matrices.
pub trait FactorizeHInto<S: Data> {
    /// Computes the Bunch–Kaufman factorization of a Hermitian (or real
    /// symmetric) matrix.
    fn factorizeh_into(self) -> Result<BKFactorized<S>>;
}

impl<A, S> FactorizeHInto<S> for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    fn factorizeh_into(mut self) -> Result<BKFactorized<S>> {
        let ipiv = unsafe { A::bk(self.layout()?, UPLO::Upper, self.as_allocated_mut()?)? };
        Ok(BKFactorized {
            a: self,
            ipiv: ipiv,
        })
    }
}

impl<A, Si> FactorizeH<OwnedRepr<A>> for ArrayBase<Si, Ix2>
where
    A: Scalar,
    Si: Data<Elem = A>,
{
    fn factorizeh(&self) -> Result<BKFactorized<OwnedRepr<A>>> {
        let mut a: Array2<A> = replicate(self);
        let ipiv = unsafe { A::bk(a.layout()?, UPLO::Upper, a.as_allocated_mut()?)? };
        Ok(BKFactorized { a: a, ipiv: ipiv })
    }
}

/// An interface for inverting Hermitian (or real symmetric) matrix refs.
pub trait InverseH {
    type Output;
    /// Computes the inverse of the Hermitian (or real symmetric) matrix.
    ///
    /// **Warning: The inverse is stored only in the upper triangular portion
    /// of the result matrix!** If you want the lower triangular portion to be
    /// correct, you must fill it in according to the results in the upper
    /// triangular portion.
    fn invh(&self) -> Result<Self::Output>;
}

/// An interface for inverting Hermitian (or real symmetric) matrices.
pub trait InverseHInto {
    type Output;
    /// Computes the inverse of the Hermitian (or real symmetric) matrix.
    ///
    /// **Warning: The inverse is stored only in the upper triangular portion
    /// of the result matrix!** If you want the lower triangular portion to be
    /// correct, you must fill it in according to the results in the upper
    /// triangular portion.
    fn invh_into(self) -> Result<Self::Output>;
}

impl<A, S> InverseHInto for BKFactorized<S>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type Output = ArrayBase<S, Ix2>;

    fn invh_into(mut self) -> Result<ArrayBase<S, Ix2>> {
        unsafe {
            A::invh(
                self.a.square_layout()?,
                UPLO::Upper,
                self.a.as_allocated_mut()?,
                &self.ipiv,
            )?
        };
        Ok(self.a)
    }
}

impl<A, S> InverseH for BKFactorized<S>
where
    A: Scalar,
    S: Data<Elem = A>,
{
    type Output = Array2<A>;

    fn invh(&self) -> Result<Self::Output> {
        let f = BKFactorized {
            a: replicate(&self.a),
            ipiv: self.ipiv.clone(),
        };
        f.invh_into()
    }
}

impl<A, S> InverseHInto for ArrayBase<S, Ix2>
where
    A: Scalar,
    S: DataMut<Elem = A>,
{
    type Output = Self;

    fn invh_into(self) -> Result<Self::Output> {
        let f = self.factorizeh_into()?;
        f.invh_into()
    }
}

impl<A, Si> InverseH for ArrayBase<Si, Ix2>
where
    A: Scalar,
    Si: Data<Elem = A>,
{
    type Output = Array2<A>;

    fn invh(&self) -> Result<Self::Output> {
        let f = self.factorizeh()?;
        f.invh_into()
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use proto::raftpb::HardState;
use raft::raft::{Raft, SoftState, StateRole};
use raft::storage::Storage;
use raft::progress::Progress;
use std::collections::HashMap;

#[derive(Default)]
pub struct Status {
    id: u64,
    hs: HardState,
    ss: SoftState,
    applied: u64,
    progress: HashMap<u64, Progress>,
}

impl Status {
    // new gets a copy of the current raft status.
    pub fn new<T: Storage>(raft: &Raft<T>) -> Status {
        let mut s = Status { id: raft.id, ..Default::default() };
        s.hs = raft.hard_state();
        s.ss = raft.soft_state();
        s.applied = raft.raft_log.get_applied();
        if s.ss.raft_state == StateRole::Leader {
            s.progress = raft.prs.clone();
        }
        s
    }
}
<commit_msg>raft: expose raft term for later usage.<commit_after>#![allow(dead_code)]
use proto::raftpb::HardState;
use raft::raft::{Raft, SoftState, StateRole};
use raft::storage::Storage;
use raft::progress::Progress;
use std::collections::HashMap;

#[derive(Default)]
pub struct Status {
    id: u64,
    pub hs: HardState,
    ss: SoftState,
    applied: u64,
    progress: HashMap<u64, Progress>,
}

impl Status {
    // new gets a copy of the current raft status.
    pub fn new<T: Storage>(raft: &Raft<T>) -> Status {
        let mut s = Status { id: raft.id, ..Default::default() };
        s.hs = raft.hard_state();
        s.ss = raft.soft_state();
        s.applied = raft.raft_log.get_applied();
        if s.ss.raft_state == StateRole::Leader {
            s.progress = raft.prs.clone();
        }
        s
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Debug};

use self::thread_id::ThreadId;

/// ThreadBound is a Sync-maker and Send-maker that allows accessing a value
/// of type T only from the original thread on which the ThreadBound was
/// constructed.
pub struct ThreadBound<T> {
    value: T,
    thread_id: ThreadId,
}

unsafe impl<T> Sync for ThreadBound<T> {}

// Send bound requires Copy, as otherwise Drop could run in the wrong place.
unsafe impl<T: Copy> Send for ThreadBound<T> {}

impl<T> ThreadBound<T> {
    pub fn new(value: T) -> Self {
        ThreadBound {
            value: value,
            thread_id: thread_id::current(),
        }
    }

    pub fn get(&self) -> Option<&T> {
        if thread_id::current() == self.thread_id {
            Some(&self.value)
        } else {
            None
        }
    }
}

impl<T: Debug> Debug for ThreadBound<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.get() {
            Some(value) => Debug::fmt(value, formatter),
            None => formatter.write_str("unknown"),
        }
    }
}

#[cfg(syn_can_use_thread_id)]
mod thread_id {
    use std::thread;

    pub use std::thread::ThreadId;

    pub fn current() -> ThreadId {
        thread::current().id()
    }
}

#[cfg(not(syn_can_use_thread_id))]
mod thread_id {
    use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

    thread_local! {
        static THREAD_ID: usize = {
            static NEXT_THREAD_ID: AtomicUsize = ATOMIC_USIZE_INIT;
            NEXT_THREAD_ID.fetch_add(1, Ordering::Relaxed)
        };
    }

    pub type ThreadId = usize;

    pub fn current() -> ThreadId {
        THREAD_ID.with(|id| *id)
    }
}
<commit_msg>Explain the thread id fetch_add<commit_after>use std::fmt::{self, Debug};

use self::thread_id::ThreadId;

/// ThreadBound is a Sync-maker and Send-maker that allows accessing a value
/// of type T only from the original thread on which the ThreadBound was
/// constructed.
pub struct ThreadBound<T> {
    value: T,
    thread_id: ThreadId,
}

unsafe impl<T> Sync for ThreadBound<T> {}

// Send bound requires Copy, as otherwise Drop could run in the wrong place.
unsafe impl<T: Copy> Send for ThreadBound<T> {}

impl<T> ThreadBound<T> {
    pub fn new(value: T) -> Self {
        ThreadBound {
            value: value,
            thread_id: thread_id::current(),
        }
    }

    pub fn get(&self) -> Option<&T> {
        if thread_id::current() == self.thread_id {
            Some(&self.value)
        } else {
            None
        }
    }
}

impl<T: Debug> Debug for ThreadBound<T> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        match self.get() {
            Some(value) => Debug::fmt(value, formatter),
            None => formatter.write_str("unknown"),
        }
    }
}

#[cfg(syn_can_use_thread_id)]
mod thread_id {
    use std::thread;

    pub use std::thread::ThreadId;

    pub fn current() -> ThreadId {
        thread::current().id()
    }
}

#[cfg(not(syn_can_use_thread_id))]
mod thread_id {
    use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};

    thread_local! {
        static THREAD_ID: usize = {
            static NEXT_THREAD_ID: AtomicUsize = ATOMIC_USIZE_INIT;

            // Ordering::Relaxed because our only requirement for the ids is
            // that they are unique. It is okay for the compiler to rearrange
            // other memory reads around this fetch. It's still an atomic
            // fetch_add, so no two threads will be able to read the same value
            // from it.
            //
            // The main thing which these orderings affect is other memory reads
            // around the atomic read, which for our case are irrelevant as this
            // atomic guards nothing.
            NEXT_THREAD_ID.fetch_add(1, Ordering::Relaxed)
        };
    }

    pub type ThreadId = usize;

    pub fn current() -> ThreadId {
        THREAD_ID.with(|id| *id)
    }
}
<|endoftext|>


<commit_before>//! Define trait for vectors

use ndarray::{LinalgScalar, Array, Ix1};
use num_traits::float::Float;

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// L-2 norm
    fn norm(&self) -> Self::Scalar;
}

impl<A: Float + LinalgScalar> Vector for Array<A, Ix1> {
    type Scalar = A;
    fn norm(&self) -> Self::Scalar {
        self.dot(&self).sqrt()
    }
}
<commit_msg>Implement Vector for RcArray<NdFloat, Ix1><commit_after>//! Define trait for vectors

use ndarray::{NdFloat, Array, RcArray, Ix1};

/// Methods for vectors
pub trait Vector {
    type Scalar;
    /// L-2 norm
    fn norm(&self) -> Self::Scalar;
}

impl<A: NdFloat> Vector for Array<A, Ix1> {
    type Scalar = A;
    fn norm(&self) -> Self::Scalar {
        self.dot(&self).sqrt()
    }
}

impl<A: NdFloat> Vector for RcArray<A, Ix1> {
    type Scalar = A;
    fn norm(&self) -> Self::Scalar {
        self.dot(&self).sqrt()
    }
}
<|endoftext|>


<commit_before>use sfml::window::{ContextSettings, VideoMode, Close};
use sfml::window::event::Event;
use sfml::graphics::{RenderWindow, RenderTarget, Color, View};
use sfml::system::vector2::{Vector2f, ToVec};
use sfml::window::keyboard::Key as SfmlKey;

use key::{Key, SpecialKey};

use std::mem;
use std::thread;

/// The event state
///
/// Used for storing information of the events.
/// Is exposed through methods of `Window`.
pub struct EventState {
    pub right: bool,
    pub left: bool,
    pub chars: String,
    pub keys: Vec<SpecialKey>,
}

impl EventState {
    /// Create new default event state
    pub fn new() -> Self {
        EventState {
            right: false,
            left: false,
            chars: String::new(),
            keys: Vec::new(),
        }
    }
}

/// Window
pub struct Window {
    window: RenderWindow,
    /// The event state
    pub event: EventState,
}

impl Window {
    /// Create new window
    pub fn new(title: &str) -> Window {
        Window {
            window: RenderWindow::new(VideoMode::new_init(800, 600, 32),
                                      title,
                                      Close,
                                      &ContextSettings::default())
                        .expect("Could not construct window"),
            event: EventState::new(),
        }

    }

    /// Set width of the window
    pub fn width(&mut self, width: u32) -> &mut Window {
        let mut s = self.window.get_size();
        s.x = width;

        self.window.set_size(&s);
        self.goto(0.0, 0.0);

        self

    }

    /// Set the height of the window
    pub fn height(&mut self, height: u32) -> &mut Window {
        let mut s = self.window.get_size();
        s.y = height;

        self.window.set_size(&s);
        self.goto(0.0, 0.0);

        self

    }

    /// Get the mouse position
    pub fn mouse(&self) -> (f32, f32) {
        let pos = self.window.get_mouse_position().to_vector2f();

        (pos.x, pos.y)
    }

    /// Get the x coordinate of the mouse
    pub fn mx(&self) -> f32 {
        self.mouse().0
    }

    /// Get the y coordinate of the mouse
    pub fn my(&self) -> f32 {
        self.mouse().1
    }

    /// Check if the window is open
    pub fn is_open(&self) -> bool {
        self.window.is_open()
    }

    /// Is the left mouse button clicked?
    pub fn left_click(&self) -> bool {
        self.event.left
    }

    /// Is the right mouse button clicked?
    pub fn right_click(&self) -> bool {
        self.event.right
    }

    /// Is `k` (char or special key) pressed?
    pub fn key<T: Key>(&self, k: T) -> bool {
        k.is_pressed(self)
    }

    /// Poll the pressed chars
    pub fn poll_char(&mut self) -> String {
        mem::replace(&mut self.event.chars, String::new())
    }

    /// Clear the window
    pub fn clear(&mut self, r: u8, g: u8, b: u8) {
        self.window.clear(&Color::new_rgb(r, g, b));

        self.event.chars.clear();
        self.keys.clear();
        self.event.left = false;
        self.event.right = false;
    }

    /// Listen for events
    pub fn listen(&mut self) {

        for e in self.window.events() {
            match e {
                Event::TextEntered {
                    code: c
                } => self.event.chars.push(c),
                Event::MouseLeft => self.event.left = true,
                Event::MouseEntered => self.event.right = true,
                Event::Closed => self.window.close(),
                Event::Resized {
                    width,
                    height,
                } => {
                    self.width(width);
                    self.height(height);
                }
                Event::KeyPressed {
                    code: c,
                    ..
                } => {
                    match c {
                        SfmlKey::Escape => self.event.keys.push(SpecialKey::Escape),
                        SfmlKey::LControl | SfmlKey::RControl =>
                            self.event.keys.push(SpecialKey::Control),
                        SfmlKey::LShift | SfmlKey::RShift =>
                            self.event.keys.push(SpecialKey::Shift),
                        SfmlKey::LAlt | SfmlKey::RAlt => self.event.keys.push(SpecialKey::Alt),
                        SfmlKey::Return => self.event.keys.push(SpecialKey::Return),
                        SfmlKey::BackSpace => self.event.keys.push(SpecialKey::Backspace),
                        SfmlKey::Left => self.event.keys.push(SpecialKey::Left),
                        SfmlKey::Right => self.event.keys.push(SpecialKey::Right),
                        SfmlKey::Up => self.event.keys.push(SpecialKey::Up),
                        SfmlKey::Down => self.event.keys.push(SpecialKey::Down),
                        _ => {}
                    }
                }
                _ => {}
            }
        }
    }

    /// Update the window
    pub fn update(&mut self) -> bool {
        thread::sleep_ms(50);

        self.window.display();

        self.is_open()

    }

    /// Change view (camera) of the window
    pub fn goto(&mut self, x: f32, y: f32) {
        let size = self.window.get_size().to_vector2f();
        self.window.set_view(&View::new_init(&(Vector2f::new(x, y) + size / 2.0), &size).unwrap());
    }

    /// Convert to SFML (backend) window
    pub fn to_sfml_window(&mut self) -> &mut RenderWindow {
        &mut self.window
    }
}
<commit_msg>Fix error<commit_after>use sfml::window::{ContextSettings, VideoMode, Close};
use sfml::window::event::Event;
use sfml::graphics::{RenderWindow, RenderTarget, Color, View};
use sfml::system::vector2::{Vector2f, ToVec};
use sfml::window::keyboard::Key as SfmlKey;

use key::{Key, SpecialKey};

use std::mem;
use std::thread;

/// The event state
///
/// Used for storing information of the events.
/// Is exposed through methods of `Window`.
pub struct EventState {
    pub right: bool,
    pub left: bool,
    pub chars: String,
    pub keys: Vec<SpecialKey>,
}

impl EventState {
    /// Create new default event state
    pub fn new() -> Self {
        EventState {
            right: false,
            left: false,
            chars: String::new(),
            keys: Vec::new(),
        }
    }
}

/// Window
pub struct Window {
    window: RenderWindow,
    /// The event state
    pub event: EventState,
}

impl Window {
    /// Create new window
    pub fn new(title: &str) -> Window {
        Window {
            window: RenderWindow::new(VideoMode::new_init(800, 600, 32),
                                      title,
                                      Close,
                                      &ContextSettings::default())
                        .expect("Could not construct window"),
            event: EventState::new(),
        }

    }

    /// Set width of the window
    pub fn width(&mut self, width: u32) -> &mut Window {
        let mut s = self.window.get_size();
        s.x = width;

        self.window.set_size(&s);
        self.goto(0.0, 0.0);

        self

    }

    /// Set the height of the window
    pub fn height(&mut self, height: u32) -> &mut Window {
        let mut s = self.window.get_size();
        s.y = height;

        self.window.set_size(&s);
        self.goto(0.0, 0.0);

        self

    }

    /// Get the mouse position
    pub fn mouse(&self) -> (f32, f32) {
        let pos = self.window.get_mouse_position().to_vector2f();

        (pos.x, pos.y)
    }

    /// Get the x coordinate of the mouse
    pub fn mx(&self) -> f32 {
        self.mouse().0
    }

    /// Get the y coordinate of the mouse
    pub fn my(&self) -> f32 {
        self.mouse().1
    }

    /// Check if the window is open
    pub fn is_open(&self) -> bool {
        self.window.is_open()
    }

    /// Is the left mouse button clicked?
    pub fn left_click(&self) -> bool {
        self.event.left
    }

    /// Is the right mouse button clicked?
    pub fn right_click(&self) -> bool {
        self.event.right
    }

    /// Is `k` (char or special key) pressed?
    pub fn key<T: Key>(&self, k: T) -> bool {
        k.is_pressed(self)
    }

    /// Poll the pressed chars
    pub fn poll_char(&mut self) -> String {
        mem::replace(&mut self.event.chars, String::new())
    }

    /// Clear the window
    pub fn clear(&mut self, r: u8, g: u8, b: u8) {
        self.window.clear(&Color::new_rgb(r, g, b));

        self.event.chars.clear();
        self.event.keys.clear();
        self.event.left = false;
        self.event.right = false;
    }

    /// Listen for events
    pub fn listen(&mut self) {

        for e in self.window.events() {
            match e {
                Event::TextEntered {
                    code: c
                } => self.event.chars.push(c),
                Event::MouseLeft => self.event.left = true,
                Event::MouseEntered => self.event.right = true,
                Event::Closed => self.window.close(),
                Event::Resized {
                    width,
                    height,
                } => {
                    self.width(width);
                    self.height(height);
                }
                Event::KeyPressed {
                    code: c,
                    ..
                } => {
                    match c {
                        SfmlKey::Escape => self.event.keys.push(SpecialKey::Escape),
                        SfmlKey::LControl | SfmlKey::RControl =>
                            self.event.keys.push(SpecialKey::Control),
                        SfmlKey::LShift | SfmlKey::RShift =>
                            self.event.keys.push(SpecialKey::Shift),
                        SfmlKey::LAlt | SfmlKey::RAlt => self.event.keys.push(SpecialKey::Alt),
                        SfmlKey::Return => self.event.keys.push(SpecialKey::Return),
                        SfmlKey::BackSpace => self.event.keys.push(SpecialKey::Backspace),
                        SfmlKey::Left => self.event.keys.push(SpecialKey::Left),
                        SfmlKey::Right => self.event.keys.push(SpecialKey::Right),
                        SfmlKey::Up => self.event.keys.push(SpecialKey::Up),
                        SfmlKey::Down => self.event.keys.push(SpecialKey::Down),
                        _ => {}
                    }
                }
                _ => {}
            }
        }
    }

    /// Update the window
    pub fn update(&mut self) -> bool {
        thread::sleep_ms(50);

        self.window.display();

        self.is_open()

    }

    /// Change view (camera) of the window
    pub fn goto(&mut self, x: f32, y: f32) {
        let size = self.window.get_size().to_vector2f();
        self.window.set_view(&View::new_init(&(Vector2f::new(x, y) + size / 2.0), &size).unwrap());
    }

    /// Convert to SFML (backend) window
    pub fn to_sfml_window(&mut self) -> &mut RenderWindow {
        &mut self.window
    }
}
<|endoftext|>


<commit_before>use orbclient::{self, Renderer};
use orbclient::color::Color;
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use super::{Event, Point, Rect, Widget};
use theme::WINDOW_BACKGROUND;

extern crate orbfont;

pub struct WindowRenderer<'a> {
    inner: &'a mut orbclient::Window,
    font: &'a Option<orbfont::Font>
}

impl<'a> WindowRenderer<'a> {
    pub fn new(inner: &'a mut orbclient::Window, font: &'a Option<orbfont::Font>) -> WindowRenderer<'a> {
        WindowRenderer { inner: inner, font: font }
    }
}

impl<'a> Renderer for WindowRenderer<'a> {
    fn width(&self) -> u32 {
        self.inner.width()
    }

    fn height(&self) -> u32 {
        self.inner.height()
    }

    fn data(&self) -> &[Color] {
        self.inner.data()
    }

    fn data_mut(&mut self) -> &mut [Color] {
        self.inner.data_mut()
    }

    fn sync(&mut self) -> bool {
        self.inner.sync()
    }

    fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        if let Some(ref font) = *self.font {
            let mut buf = [0; 4];
            font.render(&c.encode_utf8(&mut buf), 16.0).draw(self.inner, x, y, color)
        }else{
            self.inner.char(x, y, c, color);
        }
    }
}

impl<'a> Drop for WindowRenderer<'a> {
    fn drop(&mut self) {
        self.inner.sync();
    }
}

pub struct Window {
    inner: RefCell<orbclient::Window>,
    font: Option<orbfont::Font>,
    pub widgets: RefCell<Vec<Arc<Widget>>>,
    pub widget_focus: Cell<usize>,
    pub bg: Cell<Color>,
    pub running: Cell<bool>,
    events: Vec<Event>,
    redraw: bool,
}

impl Window {
    pub fn new(rect: Rect, title: &str) -> Self {
        Window {
            inner: RefCell::new(orbclient::Window::new(rect.x, rect.y, rect.width, rect.height, title).unwrap()),
            font: orbfont::Font::find(None, None, None).ok(),
            widgets: RefCell::new(Vec::new()),
            widget_focus: Cell::new(0),
            bg: Cell::new(WINDOW_BACKGROUND),
            running: Cell::new(true),
            events: vec![Event::Init],
            redraw: true,
        }
    }

    pub fn set_size(&self, width: u32, height: u32) {
        let mut inner = self.inner.borrow_mut();
        (*inner).set_size(width, height);
    }

    pub fn set_title(&self, title: &str) {
        let mut inner = self.inner.borrow_mut();
        (*inner).set_title(title);
    }

    pub fn close(&self) {
        self.running.set(false);
    }

    pub fn add<T: Widget>(&self, widget: &Arc<T>) -> usize {
        let mut widgets = self.widgets.borrow_mut();
        let id = widgets.len();
        widgets.push(widget.clone());
        id
    }

    pub fn draw(&self) {
        let mut inner = self.inner.borrow_mut();
        inner.set(self.bg.get());

        let mut renderer = WindowRenderer::new(&mut *inner, &self.font);
        for i in 0..self.widgets.borrow().len() {
            if let Some(widget) = self.widgets.borrow().get(i) {
                widget.draw(&mut renderer, self.widget_focus.get() == i);
            }
        }
    }

    pub fn step(&mut self) {
        self.drain_orbital_events();
        self.drain_events();
    }

    pub fn drain_events(&mut self) {
        for event in self.events.drain(..) {
            for i in 0..self.widgets.borrow().len() {
                if let Some(widget) = self.widgets.borrow().get(i) {
                    if widget.event(event, self.widget_focus.get() == i, &mut self.redraw) {
                        if self.widget_focus.get() != i {
                            self.widget_focus.set(i);
                            self.redraw = true;
                        }
                    }
                }
            }
        }
    }

    pub fn drain_orbital_events(&mut self) {
        for orbital_event in self.inner.borrow_mut().events() {
            match orbital_event.to_option() {
                orbclient::EventOption::Mouse(mouse_event) => {
                    self.events.push(Event::Mouse {
                        point: Point::new(mouse_event.x, mouse_event.y),
                        left_button: mouse_event.left_button,
                        middle_button: mouse_event.middle_button,
                        right_button: mouse_event.right_button,
                    })
                }
                orbclient::EventOption::Scroll(scroll_event) => {
                    self.events.push(Event::Scroll {
                        x: scroll_event.x,
                        y: scroll_event.y,
                    })
                }
                orbclient::EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            orbclient::K_BKSP => self.events.push(Event::Backspace),
                            orbclient::K_DEL => self.events.push(Event::Delete),
                            orbclient::K_HOME => self.events.push(Event::Home),
                            orbclient::K_END => self.events.push(Event::End),
                            orbclient::K_UP => self.events.push(Event::UpArrow),
                            orbclient::K_DOWN => self.events.push(Event::DownArrow),
                            orbclient::K_LEFT => self.events.push(Event::LeftArrow),
                            orbclient::K_RIGHT => self.events.push(Event::RightArrow),
                            _ => {
                                match key_event.character {
                                    '\0' => (),
                                    '\x1B' => (),
                                    '\n' => self.events.push(Event::Enter),
                                    _ => self.events.push(Event::Text { c: key_event.character }),
                                }
                            }
                        }
                    }
                }
                orbclient::EventOption::Quit(_quit_event) => { self.running.set(false); },
                _ => (),
            };
        }

    }

    pub fn exec(&mut self) {
        'event: while self.running.get() {
            self.drain_events();
            self.draw_if_needed();
            self.drain_orbital_events();
        }
    }

    pub fn needs_redraw(&mut self) {
        self.redraw = true;
    }

    pub fn draw_if_needed(&mut self) {
        if self.redraw {
            self.draw();
            self.redraw = false;
        }
    }
}
<commit_msg>Update to new events from orbclient<commit_after>use orbclient::{self, Renderer};
use orbclient::color::Color;
use std::cell::{Cell, RefCell};
use std::sync::Arc;

use super::{Event, Point, Rect, Widget};
use theme::WINDOW_BACKGROUND;

extern crate orbfont;

pub struct WindowRenderer<'a> {
    inner: &'a mut orbclient::Window,
    font: &'a Option<orbfont::Font>
}

impl<'a> WindowRenderer<'a> {
    pub fn new(inner: &'a mut orbclient::Window, font: &'a Option<orbfont::Font>) -> WindowRenderer<'a> {
        WindowRenderer { inner: inner, font: font }
    }
}

impl<'a> Renderer for WindowRenderer<'a> {
    fn width(&self) -> u32 {
        self.inner.width()
    }

    fn height(&self) -> u32 {
        self.inner.height()
    }

    fn data(&self) -> &[Color] {
        self.inner.data()
    }

    fn data_mut(&mut self) -> &mut [Color] {
        self.inner.data_mut()
    }

    fn sync(&mut self) -> bool {
        self.inner.sync()
    }

    fn char(&mut self, x: i32, y: i32, c: char, color: Color) {
        if let Some(ref font) = *self.font {
            let mut buf = [0; 4];
            font.render(&c.encode_utf8(&mut buf), 16.0).draw(self.inner, x, y, color)
        }else{
            self.inner.char(x, y, c, color);
        }
    }
}

impl<'a> Drop for WindowRenderer<'a> {
    fn drop(&mut self) {
        self.inner.sync();
    }
}

pub struct Window {
    inner: RefCell<orbclient::Window>,
    font: Option<orbfont::Font>,
    pub widgets: RefCell<Vec<Arc<Widget>>>,
    pub widget_focus: Cell<usize>,
    pub bg: Cell<Color>,
    pub running: Cell<bool>,
    mouse_point: Point,
    mouse_left: bool,
    mouse_middle: bool,
    mouse_right: bool,
    events: Vec<Event>,
    redraw: bool,
}

impl Window {
    pub fn new(rect: Rect, title: &str) -> Self {
        Window {
            inner: RefCell::new(orbclient::Window::new(rect.x, rect.y, rect.width, rect.height, title).unwrap()),
            font: orbfont::Font::find(None, None, None).ok(),
            widgets: RefCell::new(Vec::new()),
            widget_focus: Cell::new(0),
            bg: Cell::new(WINDOW_BACKGROUND),
            running: Cell::new(true),
            mouse_point: Point::new(0, 0),
            mouse_left: false,
            mouse_right: false,
            mouse_middle: false,
            events: vec![Event::Init],
            redraw: true,
        }
    }

    pub fn set_size(&self, width: u32, height: u32) {
        let mut inner = self.inner.borrow_mut();
        (*inner).set_size(width, height);
    }

    pub fn set_title(&self, title: &str) {
        let mut inner = self.inner.borrow_mut();
        (*inner).set_title(title);
    }

    pub fn close(&self) {
        self.running.set(false);
    }

    pub fn add<T: Widget>(&self, widget: &Arc<T>) -> usize {
        let mut widgets = self.widgets.borrow_mut();
        let id = widgets.len();
        widgets.push(widget.clone());
        id
    }

    pub fn draw(&self) {
        let mut inner = self.inner.borrow_mut();
        inner.set(self.bg.get());

        let mut renderer = WindowRenderer::new(&mut *inner, &self.font);
        for i in 0..self.widgets.borrow().len() {
            if let Some(widget) = self.widgets.borrow().get(i) {
                widget.draw(&mut renderer, self.widget_focus.get() == i);
            }
        }
    }

    pub fn step(&mut self) {
        self.drain_orbital_events();
        self.drain_events();
    }

    pub fn drain_events(&mut self) {
        for event in self.events.drain(..) {
            for i in 0..self.widgets.borrow().len() {
                if let Some(widget) = self.widgets.borrow().get(i) {
                    if widget.event(event, self.widget_focus.get() == i, &mut self.redraw) {
                        if self.widget_focus.get() != i {
                            self.widget_focus.set(i);
                            self.redraw = true;
                        }
                    }
                }
            }
        }
    }

    pub fn drain_orbital_events(&mut self) {
        for orbital_event in self.inner.borrow_mut().events() {
            match orbital_event.to_option() {
                orbclient::EventOption::Mouse(mouse_event) => {
                    self.mouse_point.x = mouse_event.x;
                    self.mouse_point.y = mouse_event.y;

                    self.events.push(Event::Mouse {
                        point: self.mouse_point,
                        left_button: self.mouse_left,
                        middle_button: self.mouse_middle,
                        right_button: self.mouse_right,
                    })
                }
                orbclient::EventOption::Button(button_event) => {
                    self.mouse_left = button_event.left;
                    self.mouse_middle = button_event.middle;
                    self.mouse_right = button_event.right;

                    self.events.push(Event::Mouse {
                        point: self.mouse_point,
                        left_button: self.mouse_left,
                        middle_button: self.mouse_middle,
                        right_button: self.mouse_right,
                    })
                }
                orbclient::EventOption::Scroll(scroll_event) => {
                    self.events.push(Event::Scroll {
                        x: scroll_event.x,
                        y: scroll_event.y,
                    })
                }
                orbclient::EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            orbclient::K_BKSP => self.events.push(Event::Backspace),
                            orbclient::K_DEL => self.events.push(Event::Delete),
                            orbclient::K_HOME => self.events.push(Event::Home),
                            orbclient::K_END => self.events.push(Event::End),
                            orbclient::K_UP => self.events.push(Event::UpArrow),
                            orbclient::K_DOWN => self.events.push(Event::DownArrow),
                            orbclient::K_LEFT => self.events.push(Event::LeftArrow),
                            orbclient::K_RIGHT => self.events.push(Event::RightArrow),
                            _ => {
                                match key_event.character {
                                    '\0' => (),
                                    '\x1B' => (),
                                    '\n' => self.events.push(Event::Enter),
                                    _ => self.events.push(Event::Text { c: key_event.character }),
                                }
                            }
                        }
                    }
                }
                orbclient::EventOption::Quit(_quit_event) => { self.running.set(false); },
                _ => (),
            };
        }

    }

    pub fn exec(&mut self) {
        'event: while self.running.get() {
            self.drain_events();
            self.draw_if_needed();
            self.drain_orbital_events();
        }
    }

    pub fn needs_redraw(&mut self) {
        self.redraw = true;
    }

    pub fn draw_if_needed(&mut self) {
        if self.redraw {
            self.draw();
            self.redraw = false;
        }
    }
}
<|endoftext|>


<commit_before>use failure;
use serde;
use serde::ser::SerializeMap;
use serde_json;
use std::collections::HashMap;

use errors::{Error, Result};
use logger::Logger;
use message::{ChunkSize, ChunkedMessage, Message, MessageCompression};

/// WireMessage is the representation of a fully assembled GELF message
///
/// A fully assembled requires information only present in the `Logger`:
/// Both the local hostname and possible missing metadata fields need to be
/// added to the message.
///
/// A WireMessage can be serialized to GELF/JSON (with and without compression)
/// and is the abstraction passed to the transportation backends.
pub struct WireMessage<'a> {
    host: &'a str,
    message: Message<'a>,
}

impl<'a> WireMessage<'a> {
    /// Construct a new wire message
    ///
    /// The logger is required for populating the `host`-field and metadata
    /// fields which were not added to the message.
    pub fn new(mut msg: Message<'a>, logger: &'a Logger) -> Self {
        // Filter all fields missing from the message
        let additionals_from_default: HashMap<&String, &String> = logger
            .default_metadata()
            .iter()
            .filter(|&(key, _)| !msg.metadata.contains_key(key.as_str()))
            .collect();

        // add the missing metadata
        for (key, value) in additionals_from_default {
            msg.set_metadata(key.as_str(), value.as_str()).ok();
        }

        WireMessage {
            host: logger.hostname(),
            message: msg,
        }
    }

    /// Return a GELF/JSON string of this message
    pub fn to_gelf(&self) -> Result<String> {
        serde_json::to_string(self).map_err(|e| {
            failure::Error::from(e)
                .context(Error::SerializeMessageFailed)
                .into()
        })
    }

    /// Return a compressed GELF/JSON string of this message
    pub fn to_compressed_gelf(&self, compression: MessageCompression) -> Result<Vec<u8>> {
        compression.compress(&self)
    }

    /// Serialize the messages and prepare it for chunking
    pub fn to_chunked_message(
        &self,
        chunk_size: ChunkSize,
        compression: MessageCompression,
    ) -> Result<ChunkedMessage> {
        ChunkedMessage::new(chunk_size, self.to_compressed_gelf(compression)?)
    }
}

impl<'a> serde::Serialize for WireMessage<'a> {
    /// Serialize the message to a GELF/JSON string
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut map = serializer.serialize_map(None)?;

        map.serialize_key("version")?;
        map.serialize_value("1.1")?;

        map.serialize_key("host")?;
        map.serialize_value(self.host)?;

        map.serialize_key("short_message")?;
        map.serialize_value(&self.message.short_message())?;

        map.serialize_key("level")?;
        let level = self.message.level as u8;
        map.serialize_value(&level)?;

        if self.message.full_message().is_some() {
            map.serialize_key("full_message")?;
            map.serialize_value(&self.message.full_message())?;
        }

        if self.message.timestamp().is_some() {
            let datetime = &self.message.timestamp().unwrap();
            let value = format!("{}.{}", datetime.timestamp(), datetime.timestamp_subsec_millis());

            map.serialize_key("timestamp")?;
            map.serialize_value(&value)?;
        }

        for (key, value) in self.message.all_metadata().iter() {
            let key = "_".to_string() + key;
            map.serialize_key(&key)?;
            map.serialize_value(value)?;
        }

        map.end()
    }
}

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

    use chrono::{TimeZone, Utc};
    use level::Level;

    #[test]
    fn wire_message_serialization() {
        let mut message = Message::new_with_level("short", Level::Alert);
        message.set_full_message("full");

        let datetime = Utc.ymd(2000, 1, 1).and_hms_micro(1, 2, 3, 123_456);
        message.set_timestamp(datetime);

        message.set_metadata("key1", "value1").unwrap();
        message.set_metadata("key2", "value2").unwrap();

        let wire_msg = WireMessage {
            host: "host_value",
            message,
        };

        let json = serde_json::to_value(wire_msg).expect("Failed to serialize WireMessage");

        assert_eq!(Some(json!("1.1")), json.get("version").cloned());
        assert_eq!(Some(json!("host_value")), json.get("host").cloned());
        assert_eq!(Some(json!("short")), json.get("short_message").cloned());
        assert_eq!(Some(json!("full")), json.get("full_message").cloned());
        assert_eq!(Some(json!(1)), json.get("level").cloned()); // Level::Alert = 1

        let timestamp_secs = datetime.timestamp();
        let expected_timestamp = format!("{}.{}", timestamp_secs, 123);
        assert_eq!(
            Some(json!(&expected_timestamp)),
            json.get("timestamp").cloned()
        );

        assert_eq!(Some(json!("value1")), json.get("_key1").cloned());
        assert_eq!(Some(json!("value2")), json.get("_key2").cloned());
    }
}
<commit_msg>Serialize timestamp as a JSON Number, not String<commit_after>use failure;
use serde;
use serde::ser::SerializeMap;
use serde_json;
use std::collections::HashMap;

use errors::{Error, Result};
use logger::Logger;
use message::{ChunkSize, ChunkedMessage, Message, MessageCompression};

/// WireMessage is the representation of a fully assembled GELF message
///
/// A fully assembled requires information only present in the `Logger`:
/// Both the local hostname and possible missing metadata fields need to be
/// added to the message.
///
/// A WireMessage can be serialized to GELF/JSON (with and without compression)
/// and is the abstraction passed to the transportation backends.
pub struct WireMessage<'a> {
    host: &'a str,
    message: Message<'a>,
}

impl<'a> WireMessage<'a> {
    /// Construct a new wire message
    ///
    /// The logger is required for populating the `host`-field and metadata
    /// fields which were not added to the message.
    pub fn new(mut msg: Message<'a>, logger: &'a Logger) -> Self {
        // Filter all fields missing from the message
        let additionals_from_default: HashMap<&String, &String> = logger
            .default_metadata()
            .iter()
            .filter(|&(key, _)| !msg.metadata.contains_key(key.as_str()))
            .collect();

        // add the missing metadata
        for (key, value) in additionals_from_default {
            msg.set_metadata(key.as_str(), value.as_str()).ok();
        }

        WireMessage {
            host: logger.hostname(),
            message: msg,
        }
    }

    /// Return a GELF/JSON string of this message
    pub fn to_gelf(&self) -> Result<String> {
        serde_json::to_string(self).map_err(|e| {
            failure::Error::from(e)
                .context(Error::SerializeMessageFailed)
                .into()
        })
    }

    /// Return a compressed GELF/JSON string of this message
    pub fn to_compressed_gelf(&self, compression: MessageCompression) -> Result<Vec<u8>> {
        compression.compress(&self)
    }

    /// Serialize the messages and prepare it for chunking
    pub fn to_chunked_message(
        &self,
        chunk_size: ChunkSize,
        compression: MessageCompression,
    ) -> Result<ChunkedMessage> {
        ChunkedMessage::new(chunk_size, self.to_compressed_gelf(compression)?)
    }
}

impl<'a> serde::Serialize for WireMessage<'a> {
    /// Serialize the message to a GELF/JSON string
    fn serialize<S>(&self, serializer: S) -> ::std::result::Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        let mut map = serializer.serialize_map(None)?;

        map.serialize_key("version")?;
        map.serialize_value("1.1")?;

        map.serialize_key("host")?;
        map.serialize_value(self.host)?;

        map.serialize_key("short_message")?;
        map.serialize_value(&self.message.short_message())?;

        map.serialize_key("level")?;
        let level = self.message.level as u8;
        map.serialize_value(&level)?;

        if self.message.full_message().is_some() {
            map.serialize_key("full_message")?;
            map.serialize_value(&self.message.full_message())?;
        }

        if let Some(datetime) = self.message.timestamp() {
            let value = datetime.timestamp_millis() as f64 / 1000.0;

            map.serialize_key("timestamp")?;
            map.serialize_value(&value)?;
        }

        for (key, value) in self.message.all_metadata().iter() {
            let key = "_".to_string() + key;
            map.serialize_key(&key)?;
            map.serialize_value(value)?;
        }

        map.end()
    }
}

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

    use chrono::{TimeZone, Utc};
    use level::Level;

    #[test]
    fn wire_message_serialization() {
        let mut message = Message::new_with_level("short", Level::Alert);
        message.set_full_message("full");

        let datetime = Utc.ymd(2000, 1, 1).and_hms_micro(1, 2, 3, 12_345);
        message.set_timestamp(datetime);

        message.set_metadata("key1", "value1").unwrap();
        message.set_metadata("key2", "value2").unwrap();

        let wire_msg = WireMessage {
            host: "host_value",
            message,
        };

        let json = serde_json::to_value(wire_msg).expect("Failed to serialize WireMessage");

        assert_eq!(Some(json!("1.1")), json.get("version").cloned());
        assert_eq!(Some(json!("host_value")), json.get("host").cloned());
        assert_eq!(Some(json!("short")), json.get("short_message").cloned());
        assert_eq!(Some(json!("full")), json.get("full_message").cloned());
        assert_eq!(Some(json!(1)), json.get("level").cloned()); // Level::Alert = 1

        let timestamp_secs = datetime.timestamp();
        let expected_timestamp = timestamp_secs as f64 + 0.012;
        assert_eq!(
            Some(json!(&expected_timestamp)),
            json.get("timestamp").cloned()
        );

        assert_eq!(Some(json!("value1")), json.get("_key1").cloned());
        assert_eq!(Some(json!("value2")), json.get("_key2").cloned());
    }
}
<|endoftext|>


<commit_before>use std::cell::{Ref, RefCell};
use std::error::Error;
use std::ptr;

use cairo::{ImageSurface, Status};
use cairo_sys;
use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
use gio::{Cancellable, File as GFile, InputStream};
use gio_sys;
use glib;
use glib::translate::*;
use glib_sys;
use libc;
use url::Url;

use allowed_url::AllowedUrl;
use css::{self, CssStyles};
use defs::{Defs, RsvgDefs};
use error::{set_gerror, LoadingError, RsvgError};
use io;
use surface_utils::shared_surface::SharedImageSurface;

pub enum RsvgHandle {}

pub enum RsvgHandleRust {}

struct Handle {
    base_url: RefCell<Option<Url>>,
}

impl Handle {
    fn new() -> Handle {
        Handle {
            base_url: RefCell::new(None),
        }
    }
}

#[allow(improper_ctypes)]
extern "C" {
    fn rsvg_handle_get_defs(handle: *const RsvgHandle) -> *const RsvgDefs;

    fn rsvg_handle_load_extern(
        handle: *const RsvgHandle,
        href: *const libc::c_char,
    ) -> *const RsvgHandle;

    fn rsvg_handle_keep_image_data(handle: *const RsvgHandle) -> glib_sys::gboolean;

    fn rsvg_load_handle_xml_xinclude(
        handle: *mut RsvgHandle,
        href: *const libc::c_char,
    ) -> glib_sys::gboolean;

    fn rsvg_handle_get_rust(handle: *const RsvgHandle) -> *mut RsvgHandleRust;

    fn rsvg_handle_get_cancellable(handle: *const RsvgHandle) -> *mut gio_sys::GCancellable;
}

pub fn get_defs<'a>(handle: *const RsvgHandle) -> &'a mut Defs {
    unsafe {
        let d = rsvg_handle_get_defs(handle);
        &mut *(d as *mut Defs)
    }
}

pub fn load_extern(handle: *const RsvgHandle, uri: &str) -> Result<*const RsvgHandle, ()> {
    unsafe {
        let res = rsvg_handle_load_extern(handle, uri.to_glib_none().0);

        if res.is_null() {
            Err(())
        } else {
            Ok(res)
        }
    }
}

pub fn get_base_url<'a>(handle: *const RsvgHandle) -> Ref<'a, Option<Url>> {
    let rhandle = get_rust_handle(handle);

    rhandle.base_url.borrow()
}

fn get_cancellable<'a>(handle: *const RsvgHandle) -> Option<Cancellable> {
    unsafe { from_glib_borrow(rsvg_handle_get_cancellable(handle)) }
}

pub struct BinaryData {
    pub data: Vec<u8>,
    pub content_type: Option<String>,
}

pub fn acquire_data(
    handle: *mut RsvgHandle,
    aurl: &AllowedUrl,
) -> Result<BinaryData, LoadingError> {
    io::acquire_data(aurl, get_cancellable(handle).as_ref())
}

pub fn acquire_stream(
    handle: *mut RsvgHandle,
    aurl: &AllowedUrl,
) -> Result<InputStream, glib::Error> {
    io::acquire_stream(&aurl, get_cancellable(handle).as_ref())
        .map_err(|_| glib::Error::new(RsvgError, "FIXME"))
}

fn keep_image_data(handle: *const RsvgHandle) -> bool {
    unsafe { from_glib(rsvg_handle_keep_image_data(handle)) }
}

pub fn image_surface_new_from_href(
    handle: *mut RsvgHandle,
    href_str: &str,
) -> Result<ImageSurface, LoadingError> {
    let rhandle = get_rust_handle(handle);

    let aurl = AllowedUrl::from_href(href_str, rhandle.base_url.borrow().as_ref())
        .map_err(|_| glib::Error::new(RsvgError, "FIXME"))?;

    let data = acquire_data(handle, &aurl)?;

    if data.data.len() == 0 {
        return Err(LoadingError::EmptyData);
    }

    let loader = if let Some(ref content_type) = data.content_type {
        PixbufLoader::new_with_mime_type(content_type)?
    } else {
        PixbufLoader::new()
    };

    loader.write(&data.data)?;
    loader.close()?;

    let pixbuf = loader.get_pixbuf().ok_or(LoadingError::Unknown)?;

    let surface = SharedImageSurface::from_pixbuf(&pixbuf)?.into_image_surface()?;

    if keep_image_data(handle) {
        if let Some(mime_type) = data.content_type {
            extern "C" {
                fn cairo_surface_set_mime_data(
                    surface: *mut cairo_sys::cairo_surface_t,
                    mime_type: *const libc::c_char,
                    data: *mut libc::c_char,
                    length: libc::c_ulong,
                    destroy: cairo_sys::cairo_destroy_func_t,
                    closure: *mut libc::c_void,
                ) -> Status;
            }

            let data_ptr = ToGlibContainerFromSlice::to_glib_full_from_slice(&data.data);

            unsafe {
                let status = cairo_surface_set_mime_data(
                    surface.to_glib_none().0,
                    mime_type.to_glib_none().0,
                    data_ptr as *mut _,
                    data.data.len() as libc::c_ulong,
                    Some(glib_sys::g_free),
                    data_ptr as *mut _,
                );

                if status != Status::Success {
                    return Err(LoadingError::Cairo(status));
                }
            }
        }
    }

    Ok(surface)
}

// FIXME: distinguish between "file not found" and "invalid XML"
pub fn load_xml_xinclude(handle: *mut RsvgHandle, aurl: &AllowedUrl) -> bool {
    let href = aurl.url().as_str();

    unsafe { from_glib(rsvg_load_handle_xml_xinclude(handle, href.to_glib_none().0)) }
}

// This function just slurps CSS data from a possibly-relative href
// and parses it.  We'll move it to a better place in the end.
pub fn load_css(css_styles: &mut CssStyles, handle: *mut RsvgHandle, href_str: &str) {
    let rhandle = get_rust_handle(handle);

    let aurl = match AllowedUrl::from_href(href_str, rhandle.base_url.borrow().as_ref()) {
        Ok(a) => a,
        Err(_) => {
            rsvg_log!("Could not load \"{}\" for CSS data", href_str);
            // FIXME: report errors; this should be a fatal error
            return;
        }
    };

    if let Ok(data) = acquire_data(handle, &aurl) {
        let BinaryData {
            data: bytes,
            content_type,
        } = data;

        if content_type.as_ref().map(String::as_ref) != Some("text/css") {
            rsvg_log!("\"{}\" is not of type text/css; ignoring", href_str);
            // FIXME: report errors
            return;
        }

        if let Ok(utf8) = String::from_utf8(bytes) {
            css::parse_into_css_styles(css_styles, handle, &utf8);
        } else {
            rsvg_log!(
                "\"{}\" does not contain valid UTF-8 CSS data; ignoring",
                href_str
            );
            // FIXME: report errors
            return;
        }
    } else {
        rsvg_log!("Could not load \"{}\" for CSS data", href_str);
        // FIXME: report errors from not being to acquire data; this should be a fatal error
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_new() -> *mut RsvgHandleRust {
    Box::into_raw(Box::new(Handle::new())) as *mut RsvgHandleRust
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_free(raw_handle: *mut RsvgHandleRust) {
    assert!(!raw_handle.is_null());

    Box::from_raw(raw_handle as *mut Handle);
}

fn get_rust_handle<'a>(handle: *const RsvgHandle) -> &'a mut Handle {
    unsafe { &mut *(rsvg_handle_get_rust(handle) as *mut Handle) }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_set_base_url(
    raw_handle: *const RsvgHandleRust,
    uri: *const libc::c_char,
) {
    let handle = &*(raw_handle as *const Handle);

    assert!(!uri.is_null());
    let uri: String = from_glib_none(uri);

    let url = match Url::parse(&uri) {
        Ok(u) => u,

        Err(e) => {
            rsvg_log!(
                "not setting base_uri to \"{}\" since it is invalid: {}",
                uri,
                e
            );
            return;
        }
    };

    rsvg_log!("setting base_uri to \"{}\"", url);
    *handle.base_url.borrow_mut() = Some(url);
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_get_base_gfile(
    raw_handle: *const RsvgHandleRust,
) -> *mut gio_sys::GFile {
    let handle = &*(raw_handle as *const Handle);

    match *handle.base_url.borrow() {
        None => ptr::null_mut(),

        Some(ref url) => GFile::new_for_uri(url.as_str()).to_glib_full(),
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_acquire_data(
    handle: *mut RsvgHandle,
    href_str: *const libc::c_char,
    out_len: *mut usize,
    error: *mut *mut glib_sys::GError,
) -> *mut libc::c_char {
    assert!(!href_str.is_null());
    assert!(!out_len.is_null());

    let href_str: String = from_glib_none(href_str);

    let rhandle = get_rust_handle(handle);

    let aurl = match AllowedUrl::from_href(&href_str, rhandle.base_url.borrow().as_ref()) {
        Ok(a) => a,
        Err(e) => {
            set_gerror(error, 0, &format!("{}", e));
            return ptr::null_mut();
        }
    };

    match acquire_data(handle, &aurl) {
        Ok(binary) => {
            if !error.is_null() {
                *error = ptr::null_mut();
            }

            *out_len = binary.data.len();
            io::binary_data_to_glib(&binary, ptr::null_mut(), out_len)
        }

        Err(e) => {
            set_gerror(error, 0, e.description());
            *out_len = 0;
            ptr::null_mut()
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_acquire_stream(
    handle: *mut RsvgHandle,
    href_str: *const libc::c_char,
    error: *mut *mut glib_sys::GError,
) -> *mut gio_sys::GInputStream {
    assert!(!href_str.is_null());

    let href_str: String = from_glib_none(href_str);

    let rhandle = get_rust_handle(handle);

    let aurl = match AllowedUrl::from_href(&href_str, rhandle.base_url.borrow().as_ref()) {
        Ok(a) => a,
        Err(e) => {
            set_gerror(error, 0, &format!("{}", e));
            return ptr::null_mut();
        }
    };

    match acquire_stream(handle, &aurl) {
        Ok(stream) => {
            if !error.is_null() {
                *error = ptr::null_mut();
            }

            stream.to_glib_full()
        }

        Err(e) => {
            set_gerror(error, 0, e.description());
            ptr::null_mut()
        }
    }
}
<commit_msg>handle::acquire_stream(): Return a LoadingError<commit_after>use std::cell::{Ref, RefCell};
use std::error::Error;
use std::ptr;

use cairo::{ImageSurface, Status};
use cairo_sys;
use gdk_pixbuf::{PixbufLoader, PixbufLoaderExt};
use gio::{Cancellable, File as GFile, InputStream};
use gio_sys;
use glib;
use glib::translate::*;
use glib_sys;
use libc;
use url::Url;

use allowed_url::AllowedUrl;
use css::{self, CssStyles};
use defs::{Defs, RsvgDefs};
use error::{set_gerror, LoadingError, RsvgError};
use io;
use surface_utils::shared_surface::SharedImageSurface;

pub enum RsvgHandle {}

pub enum RsvgHandleRust {}

struct Handle {
    base_url: RefCell<Option<Url>>,
}

impl Handle {
    fn new() -> Handle {
        Handle {
            base_url: RefCell::new(None),
        }
    }
}

#[allow(improper_ctypes)]
extern "C" {
    fn rsvg_handle_get_defs(handle: *const RsvgHandle) -> *const RsvgDefs;

    fn rsvg_handle_load_extern(
        handle: *const RsvgHandle,
        href: *const libc::c_char,
    ) -> *const RsvgHandle;

    fn rsvg_handle_keep_image_data(handle: *const RsvgHandle) -> glib_sys::gboolean;

    fn rsvg_load_handle_xml_xinclude(
        handle: *mut RsvgHandle,
        href: *const libc::c_char,
    ) -> glib_sys::gboolean;

    fn rsvg_handle_get_rust(handle: *const RsvgHandle) -> *mut RsvgHandleRust;

    fn rsvg_handle_get_cancellable(handle: *const RsvgHandle) -> *mut gio_sys::GCancellable;
}

pub fn get_defs<'a>(handle: *const RsvgHandle) -> &'a mut Defs {
    unsafe {
        let d = rsvg_handle_get_defs(handle);
        &mut *(d as *mut Defs)
    }
}

pub fn load_extern(handle: *const RsvgHandle, uri: &str) -> Result<*const RsvgHandle, ()> {
    unsafe {
        let res = rsvg_handle_load_extern(handle, uri.to_glib_none().0);

        if res.is_null() {
            Err(())
        } else {
            Ok(res)
        }
    }
}

pub fn get_base_url<'a>(handle: *const RsvgHandle) -> Ref<'a, Option<Url>> {
    let rhandle = get_rust_handle(handle);

    rhandle.base_url.borrow()
}

fn get_cancellable<'a>(handle: *const RsvgHandle) -> Option<Cancellable> {
    unsafe { from_glib_borrow(rsvg_handle_get_cancellable(handle)) }
}

pub struct BinaryData {
    pub data: Vec<u8>,
    pub content_type: Option<String>,
}

pub fn acquire_data(
    handle: *mut RsvgHandle,
    aurl: &AllowedUrl,
) -> Result<BinaryData, LoadingError> {
    io::acquire_data(aurl, get_cancellable(handle).as_ref())
}

pub fn acquire_stream(
    handle: *mut RsvgHandle,
    aurl: &AllowedUrl,
) -> Result<InputStream, LoadingError> {
    io::acquire_stream(&aurl, get_cancellable(handle).as_ref())
}

fn keep_image_data(handle: *const RsvgHandle) -> bool {
    unsafe { from_glib(rsvg_handle_keep_image_data(handle)) }
}

pub fn image_surface_new_from_href(
    handle: *mut RsvgHandle,
    href_str: &str,
) -> Result<ImageSurface, LoadingError> {
    let rhandle = get_rust_handle(handle);

    let aurl = AllowedUrl::from_href(href_str, rhandle.base_url.borrow().as_ref())
        .map_err(|_| glib::Error::new(RsvgError, "FIXME"))?;

    let data = acquire_data(handle, &aurl)?;

    if data.data.len() == 0 {
        return Err(LoadingError::EmptyData);
    }

    let loader = if let Some(ref content_type) = data.content_type {
        PixbufLoader::new_with_mime_type(content_type)?
    } else {
        PixbufLoader::new()
    };

    loader.write(&data.data)?;
    loader.close()?;

    let pixbuf = loader.get_pixbuf().ok_or(LoadingError::Unknown)?;

    let surface = SharedImageSurface::from_pixbuf(&pixbuf)?.into_image_surface()?;

    if keep_image_data(handle) {
        if let Some(mime_type) = data.content_type {
            extern "C" {
                fn cairo_surface_set_mime_data(
                    surface: *mut cairo_sys::cairo_surface_t,
                    mime_type: *const libc::c_char,
                    data: *mut libc::c_char,
                    length: libc::c_ulong,
                    destroy: cairo_sys::cairo_destroy_func_t,
                    closure: *mut libc::c_void,
                ) -> Status;
            }

            let data_ptr = ToGlibContainerFromSlice::to_glib_full_from_slice(&data.data);

            unsafe {
                let status = cairo_surface_set_mime_data(
                    surface.to_glib_none().0,
                    mime_type.to_glib_none().0,
                    data_ptr as *mut _,
                    data.data.len() as libc::c_ulong,
                    Some(glib_sys::g_free),
                    data_ptr as *mut _,
                );

                if status != Status::Success {
                    return Err(LoadingError::Cairo(status));
                }
            }
        }
    }

    Ok(surface)
}

// FIXME: distinguish between "file not found" and "invalid XML"
pub fn load_xml_xinclude(handle: *mut RsvgHandle, aurl: &AllowedUrl) -> bool {
    let href = aurl.url().as_str();

    unsafe { from_glib(rsvg_load_handle_xml_xinclude(handle, href.to_glib_none().0)) }
}

// This function just slurps CSS data from a possibly-relative href
// and parses it.  We'll move it to a better place in the end.
pub fn load_css(css_styles: &mut CssStyles, handle: *mut RsvgHandle, href_str: &str) {
    let rhandle = get_rust_handle(handle);

    let aurl = match AllowedUrl::from_href(href_str, rhandle.base_url.borrow().as_ref()) {
        Ok(a) => a,
        Err(_) => {
            rsvg_log!("Could not load \"{}\" for CSS data", href_str);
            // FIXME: report errors; this should be a fatal error
            return;
        }
    };

    if let Ok(data) = acquire_data(handle, &aurl) {
        let BinaryData {
            data: bytes,
            content_type,
        } = data;

        if content_type.as_ref().map(String::as_ref) != Some("text/css") {
            rsvg_log!("\"{}\" is not of type text/css; ignoring", href_str);
            // FIXME: report errors
            return;
        }

        if let Ok(utf8) = String::from_utf8(bytes) {
            css::parse_into_css_styles(css_styles, handle, &utf8);
        } else {
            rsvg_log!(
                "\"{}\" does not contain valid UTF-8 CSS data; ignoring",
                href_str
            );
            // FIXME: report errors
            return;
        }
    } else {
        rsvg_log!("Could not load \"{}\" for CSS data", href_str);
        // FIXME: report errors from not being to acquire data; this should be a fatal error
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_new() -> *mut RsvgHandleRust {
    Box::into_raw(Box::new(Handle::new())) as *mut RsvgHandleRust
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_free(raw_handle: *mut RsvgHandleRust) {
    assert!(!raw_handle.is_null());

    Box::from_raw(raw_handle as *mut Handle);
}

fn get_rust_handle<'a>(handle: *const RsvgHandle) -> &'a mut Handle {
    unsafe { &mut *(rsvg_handle_get_rust(handle) as *mut Handle) }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_set_base_url(
    raw_handle: *const RsvgHandleRust,
    uri: *const libc::c_char,
) {
    let handle = &*(raw_handle as *const Handle);

    assert!(!uri.is_null());
    let uri: String = from_glib_none(uri);

    let url = match Url::parse(&uri) {
        Ok(u) => u,

        Err(e) => {
            rsvg_log!(
                "not setting base_uri to \"{}\" since it is invalid: {}",
                uri,
                e
            );
            return;
        }
    };

    rsvg_log!("setting base_uri to \"{}\"", url);
    *handle.base_url.borrow_mut() = Some(url);
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_rust_get_base_gfile(
    raw_handle: *const RsvgHandleRust,
) -> *mut gio_sys::GFile {
    let handle = &*(raw_handle as *const Handle);

    match *handle.base_url.borrow() {
        None => ptr::null_mut(),

        Some(ref url) => GFile::new_for_uri(url.as_str()).to_glib_full(),
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_acquire_data(
    handle: *mut RsvgHandle,
    href_str: *const libc::c_char,
    out_len: *mut usize,
    error: *mut *mut glib_sys::GError,
) -> *mut libc::c_char {
    assert!(!href_str.is_null());
    assert!(!out_len.is_null());

    let href_str: String = from_glib_none(href_str);

    let rhandle = get_rust_handle(handle);

    let aurl = match AllowedUrl::from_href(&href_str, rhandle.base_url.borrow().as_ref()) {
        Ok(a) => a,
        Err(e) => {
            set_gerror(error, 0, &format!("{}", e));
            return ptr::null_mut();
        }
    };

    match acquire_data(handle, &aurl) {
        Ok(binary) => {
            if !error.is_null() {
                *error = ptr::null_mut();
            }

            *out_len = binary.data.len();
            io::binary_data_to_glib(&binary, ptr::null_mut(), out_len)
        }

        Err(e) => {
            set_gerror(error, 0, e.description());
            *out_len = 0;
            ptr::null_mut()
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn rsvg_handle_acquire_stream(
    handle: *mut RsvgHandle,
    href_str: *const libc::c_char,
    error: *mut *mut glib_sys::GError,
) -> *mut gio_sys::GInputStream {
    assert!(!href_str.is_null());

    let href_str: String = from_glib_none(href_str);

    let rhandle = get_rust_handle(handle);

    let aurl = match AllowedUrl::from_href(&href_str, rhandle.base_url.borrow().as_ref()) {
        Ok(a) => a,
        Err(e) => {
            set_gerror(error, 0, &format!("{}", e));
            return ptr::null_mut();
        }
    };

    match acquire_stream(handle, &aurl) {
        Ok(stream) => {
            if !error.is_null() {
                *error = ptr::null_mut();
            }

            stream.to_glib_full()
        }

        Err(e) => {
            set_gerror(error, 0, e.description());
            ptr::null_mut()
        }
    }
}
<|endoftext|>


<commit_before>use crate::clean;
use crate::core::DocContext;
use crate::html::item_type::ItemType;
use crate::fold::{self, DocFolder};
use crate::passes::Pass;

use syntax::attr;

use std::collections::BTreeMap;
use std::fmt;
use std::ops;

pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
    name: "calculate-doc-coverage",
    pass: calculate_doc_coverage,
    description: "counts the number of items with and without documentation",
};

fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
    let mut calc = CoverageCalculator::default();
    let krate = calc.fold_crate(krate);

    calc.print_results();

    krate
}

#[derive(Default, Copy, Clone)]
struct ItemCount {
    total: u64,
    with_docs: u64,
}

impl ItemCount {
    fn count_item(&mut self, has_docs: bool) {
        self.total += 1;

        if has_docs {
            self.with_docs += 1;
        }
    }

    fn percentage(&self) -> Option<f64> {
        if self.total > 0 {
            Some((self.with_docs as f64 * 100.0) / self.total as f64)
        } else {
            None
        }
    }
}

impl ops::Sub for ItemCount {
    type Output = Self;

    fn sub(self, rhs: Self) -> Self {
        ItemCount {
            total: self.total - rhs.total,
            with_docs: self.with_docs - rhs.with_docs,
        }
    }
}

impl ops::AddAssign for ItemCount {
    fn add_assign(&mut self, rhs: Self) {
        self.total += rhs.total;
        self.with_docs += rhs.with_docs;
    }
}

impl fmt::Display for ItemCount {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}/{}", self.with_docs, self.total)
    }
}

#[derive(Default)]
struct CoverageCalculator {
    items: BTreeMap<ItemType, ItemCount>,
}

impl CoverageCalculator {
    fn print_results(&self) {
        use crate::html::item_type::ItemType::*;

        let mut total = ItemCount::default();

        let main_types = [
            Module, Function,
            Struct, StructField,
            Enum, Variant,
            Union,
            Method,
            Trait, TyMethod,
            AssociatedType, AssociatedConst,
            Macro,
            Static, Constant,
            ForeignType, Existential,
            Typedef, TraitAlias,
            Primitive, Keyword,
        ];

        println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
        println!("| {:<25} | {:>10} | {:>10} | {:>10} |",
                 "Item Type", "Documented", "Total", "Percentage");
        println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");

        for item_type in &main_types {
            let count = self.items.get(item_type).cloned().unwrap_or_default();

            if let Some(percentage) = count.percentage() {
                println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |",
                         table_name(item_type), count.with_docs, count.total, percentage);

                total += count;
            }
        }

        println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");

        if let Some(count) = self.items.get(&Impl) {
            if let Some(percentage) = count.percentage() {
                if let Some(percentage) = total.percentage() {
                    println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |",
                             "Total (non trait impls)", total.with_docs, total.total, percentage);
                }

                println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");

                println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |",
                         table_name(&Impl), count.with_docs, count.total, percentage);

                println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");

                total += *count;
            }
        }

        println!("| {:<25} | {:>10} | {:>10} | {:>9.1}% |",
                 "Total", total.with_docs, total.total, total.percentage().unwrap_or(0.0));
        println!("+-{0:->25}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
    }
}

impl fold::DocFolder for CoverageCalculator {
    fn fold_item(&mut self, mut i: clean::Item) -> Option<clean::Item> {
        let has_docs = !i.attrs.doc_strings.is_empty();

        match i.inner {
            _ if !i.def_id.is_local() => {
                // non-local items are skipped because they can be out of the users control,
                // especially in the case of trait impls, which rustdoc eagerly inlines
                return Some(i);
            }
            clean::StrippedItem(..) => {
                // don't count items in stripped modules
                return Some(i);
            }
            clean::ImportItem(..) | clean::ExternCrateItem(..) => {
                // docs on `use` and `extern crate` statements are not displayed, so they're not
                // worth counting
                return Some(i);
            }
            clean::ImplItem(ref impl_)
                if attr::contains_name(&i.attrs.other_attrs, "automatically_derived")
                    || impl_.synthetic || impl_.blanket_impl.is_some() =>
            {
                // built-in derives get the `#[automatically_derived]` attribute, and
                // synthetic/blanket impls are made up by rustdoc and can't be documented
                // FIXME(misdreavus): need to also find items that came out of a derive macro
                return Some(i);
            }
            clean::ImplItem(ref impl_) => {
                if let Some(ref tr) = impl_.trait_ {
                    debug!("counting impl {:#} for {:#}", tr, impl_.for_);

                    // trait impls inherit their docs from the trait definition, so documenting
                    // them can be considered optional
                    self.items.entry(ItemType::Impl).or_default().count_item(has_docs);

                    for it in &impl_.items {
                        let has_docs = !it.attrs.doc_strings.is_empty();
                        self.items.entry(ItemType::Impl).or_default().count_item(has_docs);
                    }

                    // now skip recursing, so that we don't double-count this impl's items
                    return Some(i);
                } else {
                    // inherent impls *can* be documented, and those docs show up, but in most
                    // cases it doesn't make sense, as all methods on a type are in one single
                    // impl block
                    debug!("not counting impl {:#}", impl_.for_);
                }
            }
            clean::MacroItem(..) | clean::ProcMacroItem(..) => {
                // combine `macro_rules!` macros and proc-macros in the same count
                debug!("counting macro {:?}", i.name);
                self.items.entry(ItemType::Macro).or_default().count_item(has_docs);
            }
            clean::TraitItem(ref mut trait_) => {
                // because both trait methods with a default impl and struct methods are
                // ItemType::Method, we need to properly tag trait methods as TyMethod instead
                debug!("counting trait {:?}", i.name);
                self.items.entry(ItemType::Trait).or_default().count_item(has_docs);

                // since we're not going on to document the crate, it doesn't matter if we discard
                // the item after counting it
                trait_.items.retain(|it| {
                    if it.type_() == ItemType::Method {
                        let has_docs = !it.attrs.doc_strings.is_empty();
                        self.items.entry(ItemType::TyMethod).or_default().count_item(has_docs);
                        false
                    } else {
                        true
                    }
                });
            }
            _ => {
                debug!("counting {} {:?}", i.type_(), i.name);
                self.items.entry(i.type_()).or_default().count_item(has_docs);
            }
        }

        self.fold_item_recur(i)
    }
}

fn table_name(type_: &ItemType) -> &'static str {
        match *type_ {
            ItemType::Module          => "Modules",
            ItemType::Struct          => "Structs",
            ItemType::Union           => "Unions",
            ItemType::Enum            => "Enums",
            ItemType::Function        => "Functions",
            ItemType::Typedef         => "Type Aliases",
            ItemType::Static          => "Statics",
            ItemType::Trait           => "Traits",
            // inherent impls aren't counted, and trait impls get all their items thrown into this
            // counter
            ItemType::Impl            => "Trait Impl Items",
            // even though trait methods with a default impl get cleaned as Method, we convert them
            // to TyMethod when counting
            ItemType::TyMethod        => "Trait Methods",
            ItemType::Method          => "Methods",
            ItemType::StructField     => "Struct Fields",
            ItemType::Variant         => "Enum Variants",
            ItemType::Macro           => "Macros",
            ItemType::Primitive       => "Primitives",
            ItemType::AssociatedType  => "Associated Types",
            ItemType::Constant        => "Constants",
            ItemType::AssociatedConst => "Associated Constants",
            ItemType::ForeignType     => "Extern Types",
            ItemType::Keyword         => "Keywords",
            ItemType::Existential     => "Existential Types",
            ItemType::TraitAlias      => "Trait Aliases",
            _                         => panic!("unanticipated ItemType: {}", type_),
        }
}
<commit_msg>track items per-file instead of per-type<commit_after>use crate::clean;
use crate::core::DocContext;
use crate::fold::{self, DocFolder};
use crate::passes::Pass;

use syntax::attr;
use syntax_pos::FileName;

use std::collections::BTreeMap;
use std::fmt;
use std::ops;

pub const CALCULATE_DOC_COVERAGE: Pass = Pass {
    name: "calculate-doc-coverage",
    pass: calculate_doc_coverage,
    description: "counts the number of items with and without documentation",
};

fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_, '_, '_>) -> clean::Crate {
    let mut calc = CoverageCalculator::default();
    let krate = calc.fold_crate(krate);

    calc.print_results();

    krate
}

#[derive(Default, Copy, Clone)]
struct ItemCount {
    total: u64,
    with_docs: u64,
}

impl ItemCount {
    fn count_item(&mut self, has_docs: bool) {
        self.total += 1;

        if has_docs {
            self.with_docs += 1;
        }
    }

    fn percentage(&self) -> Option<f64> {
        if self.total > 0 {
            Some((self.with_docs as f64 * 100.0) / self.total as f64)
        } else {
            None
        }
    }
}

impl ops::Sub for ItemCount {
    type Output = Self;

    fn sub(self, rhs: Self) -> Self {
        ItemCount {
            total: self.total - rhs.total,
            with_docs: self.with_docs - rhs.with_docs,
        }
    }
}

impl ops::AddAssign for ItemCount {
    fn add_assign(&mut self, rhs: Self) {
        self.total += rhs.total;
        self.with_docs += rhs.with_docs;
    }
}

impl fmt::Display for ItemCount {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}/{}", self.with_docs, self.total)
    }
}

#[derive(Default)]
struct CoverageCalculator {
    items: BTreeMap<FileName, ItemCount>,
}

impl CoverageCalculator {
    fn print_results(&self) {
        let mut total = ItemCount::default();

        fn print_table_line() {
            println!("+-{0:->35}-+-{0:->10}-+-{0:->10}-+-{0:->10}-+", "");
        }

        fn print_table_record(name: &str, count: ItemCount, percentage: f64) {
            println!("| {:<35} | {:>10} | {:>10} | {:>9.1}% |",
                     name, count.with_docs, count.total, percentage);
        }

        print_table_line();
        println!("| {:<35} | {:>10} | {:>10} | {:>10} |",
                 "File", "Documented", "Total", "Percentage");
        print_table_line();

        for (file, &count) in &self.items {
            if let Some(percentage) = count.percentage() {
                let mut name = file.to_string();
                // if a filename is too long, shorten it so we don't blow out the table
                // FIXME(misdreavus): this needs to count graphemes, and probably also track
                // double-wide characters...
                if name.len() > 35 {
                    name = "...".to_string() + &name[name.len()-32..];
                }

                print_table_record(&name, count, percentage);

                total += count;
            }
        }

        print_table_line();
        print_table_record("Total", total, total.percentage().unwrap_or(0.0));
        print_table_line();
    }
}

impl fold::DocFolder for CoverageCalculator {
    fn fold_item(&mut self, i: clean::Item) -> Option<clean::Item> {
        let has_docs = !i.attrs.doc_strings.is_empty();

        match i.inner {
            _ if !i.def_id.is_local() => {
                // non-local items are skipped because they can be out of the users control,
                // especially in the case of trait impls, which rustdoc eagerly inlines
                return Some(i);
            }
            clean::StrippedItem(..) => {
                // don't count items in stripped modules
                return Some(i);
            }
            clean::ImportItem(..) | clean::ExternCrateItem(..) => {
                // docs on `use` and `extern crate` statements are not displayed, so they're not
                // worth counting
                return Some(i);
            }
            clean::ImplItem(ref impl_)
                if attr::contains_name(&i.attrs.other_attrs, "automatically_derived")
                    || impl_.synthetic || impl_.blanket_impl.is_some() =>
            {
                // built-in derives get the `#[automatically_derived]` attribute, and
                // synthetic/blanket impls are made up by rustdoc and can't be documented
                // FIXME(misdreavus): need to also find items that came out of a derive macro
                return Some(i);
            }
            clean::ImplItem(ref impl_) => {
                if let Some(ref tr) = impl_.trait_ {
                    debug!("impl {:#} for {:#} in {}", tr, impl_.for_, i.source.filename);

                    // don't count trait impls, the missing-docs lint doesn't so we shouldn't
                    // either
                    return Some(i);
                } else {
                    // inherent impls *can* be documented, and those docs show up, but in most
                    // cases it doesn't make sense, as all methods on a type are in one single
                    // impl block
                    debug!("impl {:#} in {}", impl_.for_, i.source.filename);
                }
            }
            _ => {
                debug!("counting {} {:?} in {}", i.type_(), i.name, i.source.filename);
                self.items.entry(i.source.filename.clone())
                          .or_default()
                          .count_item(has_docs);
            }
        }

        self.fold_item_recur(i)
    }
}
<|endoftext|>


<commit_before>use std::str::from_utf8;

use crate::{
    net::connection::{Connection, RequestId},
    Result,
};
use bytes::{Buf, BufMut, BytesMut, IntoBuf};
use futures::{channel::oneshot::Canceled, prelude::*};

const HEADER_LEN: usize = 8 + 4;

#[derive(Debug, Clone, Copy)]
pub(crate) struct Session<'a> {
    id: RequestId,
    conn: &'a Connection,
}

impl<'a> Session<'a> {
    pub(crate) fn new(id: RequestId, conn: &'a Connection) -> Self {
        Session { id, conn }
    }

    pub(crate) async fn write(self, data: &'a [u8]) -> Result<()> {
        let data_len = data.len();
        let mut buf = BytesMut::with_capacity(HEADER_LEN + data_len);
        buf.put_u64_le(self.id as u64);
        buf.put_u32_le(data_len as u32);
        buf.put(data);
        log::debug!(
            "session => {}; sending query; data => {}",
            self.id,
            from_utf8(data).unwrap()
        );
        let mut stream = self.conn.stream();
        await!(stream.write_all(&buf))?;
        log::debug!("session => {}; query sent", self.id);
        Ok(())
    }

    pub(crate) fn read(self) -> impl Future<Output = Result<()>> + 'a {
        async move {
            let mut buf = BytesMut::new();
            buf.resize(HEADER_LEN, 0);
            let mut reader = self.conn.stream();
            let mut guard = await!(self.conn.senders().lock());
            log::debug!("session => {}; peeking socket data", self.id);
            await!(reader.read_exact(&mut buf))?;
            let mut header = buf.take().into_buf();
            let id = header.get_u64_le() as usize;
            log::debug!(
                "session => {}; peeked successfully, got data for {}",
                self.id,
                id
            );
            let len = header.get_u32_le() as usize;
            buf.resize(len, 0);
            log::debug!("session => {}; retrieving data", self.id);
            await!(reader.read_exact(&mut buf))?;
            let resp = buf.freeze();
            log::debug!(
                "session => {}; data retrieved; data => {}",
                self.id,
                from_utf8(&resp).unwrap()
            );
            let sender = guard.remove(id);
            sender.send(resp).map_err(|_| Canceled)?;
            Ok(())
        }
    }
}
<commit_msg>rename session to id in logs<commit_after>use std::str::from_utf8;

use crate::{
    net::connection::{Connection, RequestId},
    Result,
};
use bytes::{Buf, BufMut, BytesMut, IntoBuf};
use futures::{channel::oneshot::Canceled, prelude::*};

const HEADER_LEN: usize = 8 + 4;

#[derive(Debug, Clone, Copy)]
pub(crate) struct Session<'a> {
    id: RequestId,
    conn: &'a Connection,
}

impl<'a> Session<'a> {
    pub(crate) fn new(id: RequestId, conn: &'a Connection) -> Self {
        Session { id, conn }
    }

    pub(crate) async fn write(self, data: &'a [u8]) -> Result<()> {
        let data_len = data.len();
        let mut buf = BytesMut::with_capacity(HEADER_LEN + data_len);
        buf.put_u64_le(self.id as u64);
        buf.put_u32_le(data_len as u32);
        buf.put(data);
        log::debug!(
            "id => {}; sending query; data => {}",
            self.id,
            from_utf8(data).unwrap()
        );
        let mut stream = self.conn.stream();
        await!(stream.write_all(&buf))?;
        log::debug!("id => {}; query sent", self.id);
        Ok(())
    }

    pub(crate) fn read(self) -> impl Future<Output = Result<()>> + 'a {
        async move {
            let mut buf = BytesMut::new();
            buf.resize(HEADER_LEN, 0);
            let mut reader = self.conn.stream();
            let mut guard = await!(self.conn.senders().lock());
            log::debug!("id => {}; peeking socket data", self.id);
            await!(reader.read_exact(&mut buf))?;
            let mut header = buf.take().into_buf();
            let id = header.get_u64_le() as usize;
            log::debug!(
                "id => {}; peeked successfully, got data for {}",
                self.id,
                id
            );
            let len = header.get_u32_le() as usize;
            buf.resize(len, 0);
            log::debug!("id => {}; retrieving data", self.id);
            await!(reader.read_exact(&mut buf))?;
            let resp = buf.freeze();
            log::debug!(
                "id => {}; data retrieved; data => {}",
                self.id,
                from_utf8(&resp).unwrap()
            );
            let sender = guard.remove(id);
            sender.send(resp).map_err(|_| Canceled)?;
            Ok(())
        }
    }
}
<|endoftext|>