<commit_before>//! The `ndarray-linalg` crate provides linear algebra functionalities for `ArrayBase`, the n-dimensional array data structure provided by [`ndarray`](https://github.com/rust-ndarray/ndarray).
//!
//! `ndarray-linalg` leverages [LAPACK](http://www.netlib.org/lapack/)'s routines using the bindings provided by [blas-lapack-rs/lapack](https://github.com/blas-lapack-rs/lapack).
//!
//! Linear algebra methods
//! -----------------------
//! - Decomposition methods:
//!     - [QR decomposition](qr/index.html)
//!     - [Cholesky/LU decomposition](cholesky/index.html)
//!     - [Eigenvalue decomposition for Hermite matrices](eigh/index.html)
//!     - [**S**ingular **V**alue **D**ecomposition](svd/index.html)
//! - Solution of linear systems:
//!    - [General matrices](solve/index.html)
//!    - [Triangular matrices](triangular/index.html)
//!    - [Hermitian/real symmetric matrices](solveh/index.html)
//! - [Inverse matrix computation](solve/trait.Inverse.html)
//!
//! Naming Convention
//! -----------------------
//! Each routine is usually exposed as a trait, implemented by the relevant types.
//!
//! For each routine there might be multiple "variants": different traits corresponding to the different ownership possibilities of the array you intend to work on.
//!
//! For example, if you are interested in the QR decomposition of a square matrix, you can use:
//! - [QRSquare](qr/trait.QRSquare.html), if you hold an immutable reference (i.e. `&self`) to the matrix you want to decompose;
//! - [QRSquareInplace](qr/trait.QRSquareInplace.html), if you hold a mutable reference (i.e. `&mut self`) to the matrix you want to decompose;
//! - [QRSquareInto](qr/trait.QRSquareInto.html), if you can pass the matrix you want to decompose by value (e.g. `self`).
//!
//! Depending on the algorithm, each variant might require more or less copy operations of the underlying data.
//!
//! Details are provided in the description of each routine.
//!
//!  Utilities
//!  -----------
//!  - [Assertions for array](index.html#macros)
//!  - [Random matrix generators](generate/index.html)
//!  - [Scalar trait](types/trait.Scalar.html)

pub mod assert;
pub mod cholesky;
pub mod convert;
pub mod diagonal;
pub mod eigh;
pub mod error;
pub mod generate;
pub mod inner;
pub mod krylov;
pub mod lapack;
pub mod layout;
pub mod norm;
pub mod operator;
pub mod opnorm;
pub mod qr;
pub mod solve;
pub mod solveh;
pub mod svd;
pub mod trace;
pub mod triangular;
pub mod types;

pub use assert::*;
pub use cholesky::*;
pub use convert::*;
pub use diagonal::*;
pub use eigh::*;
pub use generate::*;
pub use inner::*;
pub use layout::*;
pub use norm::*;
pub use operator::*;
pub use opnorm::*;
pub use qr::*;
pub use solve::*;
pub use solveh::*;
pub use svd::*;
pub use trace::*;
pub use triangular::*;
pub use types::*;
<commit_msg>Link blas,lapack_src explicitly<commit_after>//! The `ndarray-linalg` crate provides linear algebra functionalities for `ArrayBase`, the n-dimensional array data structure provided by [`ndarray`](https://github.com/rust-ndarray/ndarray).
//!
//! `ndarray-linalg` leverages [LAPACK](http://www.netlib.org/lapack/)'s routines using the bindings provided by [blas-lapack-rs/lapack](https://github.com/blas-lapack-rs/lapack).
//!
//! Linear algebra methods
//! -----------------------
//! - Decomposition methods:
//!     - [QR decomposition](qr/index.html)
//!     - [Cholesky/LU decomposition](cholesky/index.html)
//!     - [Eigenvalue decomposition for Hermite matrices](eigh/index.html)
//!     - [**S**ingular **V**alue **D**ecomposition](svd/index.html)
//! - Solution of linear systems:
//!    - [General matrices](solve/index.html)
//!    - [Triangular matrices](triangular/index.html)
//!    - [Hermitian/real symmetric matrices](solveh/index.html)
//! - [Inverse matrix computation](solve/trait.Inverse.html)
//!
//! Naming Convention
//! -----------------------
//! Each routine is usually exposed as a trait, implemented by the relevant types.
//!
//! For each routine there might be multiple "variants": different traits corresponding to the different ownership possibilities of the array you intend to work on.
//!
//! For example, if you are interested in the QR decomposition of a square matrix, you can use:
//! - [QRSquare](qr/trait.QRSquare.html), if you hold an immutable reference (i.e. `&self`) to the matrix you want to decompose;
//! - [QRSquareInplace](qr/trait.QRSquareInplace.html), if you hold a mutable reference (i.e. `&mut self`) to the matrix you want to decompose;
//! - [QRSquareInto](qr/trait.QRSquareInto.html), if you can pass the matrix you want to decompose by value (e.g. `self`).
//!
//! Depending on the algorithm, each variant might require more or less copy operations of the underlying data.
//!
//! Details are provided in the description of each routine.
//!
//!  Utilities
//!  -----------
//!  - [Assertions for array](index.html#macros)
//!  - [Random matrix generators](generate/index.html)
//!  - [Scalar trait](types/trait.Scalar.html)

extern crate blas_src;
extern crate lapack_src;

pub mod assert;
pub mod cholesky;
pub mod convert;
pub mod diagonal;
pub mod eigh;
pub mod error;
pub mod generate;
pub mod inner;
pub mod krylov;
pub mod lapack;
pub mod layout;
pub mod norm;
pub mod operator;
pub mod opnorm;
pub mod qr;
pub mod solve;
pub mod solveh;
pub mod svd;
pub mod trace;
pub mod triangular;
pub mod types;

pub use assert::*;
pub use cholesky::*;
pub use convert::*;
pub use diagonal::*;
pub use eigh::*;
pub use generate::*;
pub use inner::*;
pub use layout::*;
pub use norm::*;
pub use operator::*;
pub use opnorm::*;
pub use qr::*;
pub use solve::*;
pub use solveh::*;
pub use svd::*;
pub use trace::*;
pub use triangular::*;
pub use types::*;
<|endoftext|>


<commit_before>#![allow(dead_code)]
//! This crate provides FastCGI client with supporting multithreaded socket listener and HTTP-instances multiplexed into a single connection.
// object
mod fastcgi;
mod http;

pub use http::{Request, Response};

// Data struct
use std::collections::HashMap;
use std::iter::Iterator;

// net / io
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::io::Write;

// Thread
#[cfg(feature="spawn")]
use std::thread;

pub struct Client
{
    listener: TcpListener,
}

/// TcpListener wrapper
impl Client
{
    pub fn new<A: ToSocketAddrs>(addr: A) -> Client
    {
        Client {
            listener: TcpListener::bind(addr).expect("Bind address"),
        }
    }

    /// Run thread
    /// Accept `Handler` as callback
    #[cfg(feature="spawn")]
    pub fn run<T: Handler + Send + Clone + 'static>(&self, handler: T)
    {
        let listener = self.listener.try_clone().expect("Clone listener");
        let handler = handler.clone();

        thread::spawn(move || {

            for stream in listener.incoming() {
                match stream {
                    Ok(stream) => {
                        let reader = StreamSyntax::new(&stream);
                        for mut pair in reader {
                            // call handler
                            handler.process(&mut pair);
                            pair.response().flush().unwrap();
                        }
                    }
                    Err(e) => panic!("{}", e),
                }
            }
        });
    }

    /// Accept `Handler` as callback
    #[cfg(not(feature="spawn"))]
    pub fn run<T: Handler>(&self, handler: T)
    {
        for stream in self.listener.incoming() {
            match stream {
                Ok(stream) => {
                    let reader = StreamSyntax::new(&stream);
                    for mut pair in reader {
                        // call handler
                        handler.process(&mut pair);
                        pair.response().flush().unwrap();
                    }
                }
                Err(e) => panic!("{}", e),
            }
        }
    }
}

/// HTTP request / response pairs
pub struct HttpPair<'s>(http::Request<'s>, http::Response<'s>);

impl<'s> HttpPair<'s>
{
    pub fn request(&mut self) -> &mut http::Request<'s>
    {
        &mut self.0
    }

    pub fn response(&mut self) -> &mut http::Response<'s>
    {
        &mut self.1
    }
}

/// FasctCGI request parser
pub struct StreamSyntax<'s>
{
    born: bool,
    pair: HashMap<u16, HttpPair<'s>>,
    stream: &'s TcpStream,
}

impl<'s> StreamSyntax<'s>
{
    fn new(stream: &'s TcpStream) -> StreamSyntax
    {
        StreamSyntax {
            born: true,
            pair: HashMap::new(),
            stream: stream,
        }
    }
}

/// Iterator implementation
impl<'s> Iterator for StreamSyntax<'s>
{
    type Item = HttpPair<'s>;

    /// Yield HTTP request / response
    fn next(&mut self) -> Option<Self::Item>
    {
        while !self.pair.is_empty() || self.born {
            let h = http::Request::fcgi_header(self.stream);
            let body = http::Request::fcgi_body(self.stream, &h);

            self.pair.entry(h.request_id)
                .or_insert(HttpPair(
                    http::Request::new(self.stream, h.request_id),
                    http::Response::new(self.stream, h.request_id),
                ));

            match h.type_ {
                fastcgi::ABORT_REQUEST => {
                    self.pair.remove(&h.request_id).unwrap()
                        .response()
                        .flush()
                        .expect("Send end request on abort")
                }
                fastcgi::PARAMS if h.content_length == 0 => {
                    self.born = false;
                    return self.pair.remove(&h.request_id);
                }
                _ => {
                    self.pair.get_mut(&h.request_id).unwrap()
                        .request().fcgi_record(h, body)
                }
            }
        }

        None
    }
}

/// Callback trait
pub trait Handler
{
    /// Run HTTP-request handling
    fn process(&self, &mut HttpPair);
}

<commit_msg>router fcgi wrapper<commit_after>#![allow(dead_code)]
//! This crate provides FastCGI client with supporting multithreaded socket listener and HTTP-instances multiplexed into a single connection.
// object
mod fastcgi;
mod http;

pub use http::{Request, Response};

// Data struct
use std::collections::HashMap;
use std::iter::Iterator;

// net / io
use std::net::{TcpListener, TcpStream, ToSocketAddrs};
use std::io::Write;

// Thread
#[cfg(feature="spawn")]
use std::thread;

pub struct Client
{
    listener: TcpListener,
}

/// TcpListener wrapper
impl Client
{
    pub fn new<A: ToSocketAddrs>(addr: A) -> Client
    {
        Client {
            listener: TcpListener::bind(addr).expect("Bind address"),
        }
    }

    /// Run thread
    /// Accept `Handler` as callback
    #[cfg(feature="spawn")]
    pub fn run<T: Handler + Send + Clone + 'static>(&self, handler: T)
    {
        let listener = self.listener.try_clone().expect("Clone listener");
        let handler = handler.clone();

        thread::spawn(move || {
            self.listen(handler)
        });
    }

    /// Accept `Handler` as callback
    #[cfg(not(feature="spawn"))]
    pub fn run<T: Handler>(&self, handler: T)
    {
        self.listen(handler)
    }

    fn listen<T: Handler>(&self, handler: T)
    {
        for stream in self.listener.incoming() {
            match stream {
                Ok(stream) => {
                    let reader = StreamSyntax::new(&stream);
                    for mut pair in reader {
                        // call handler
                        handler.process(&mut pair);
                        pair.1.flush().unwrap();
                    }
                }
                Err(e) => panic!("{}", e),
            }
        }
    }
}

/// HTTP request / response pairs
pub type HttpPair<'s> = (Request<'s>, Response<'s>);

/// FasctCGI request parser
pub struct StreamSyntax<'s>
{
    born: bool,
    pair: HashMap<u16, HttpPair<'s>>,
    stream: &'s TcpStream,
}

impl<'s> StreamSyntax<'s>
{
    fn new(stream: &'s TcpStream) -> StreamSyntax
    {
        StreamSyntax {
            born: true,
            pair: HashMap::new(),
            stream: stream,
        }
    }
}

/// Iterator implementation
impl<'s> Iterator for StreamSyntax<'s>
{
    type Item = HttpPair<'s>;

    /// Yield HTTP request / response
    fn next(&mut self) -> Option<Self::Item>
    {
        while !self.pair.is_empty() || self.born {
            let h = Request::fcgi_header(self.stream);
            let body = Request::fcgi_body(self.stream, &h);

            self.pair.entry(h.request_id)
                .or_insert((
                    Request::new(self.stream, h.request_id),
                    Response::new(self.stream, h.request_id),
                ));

            match h.type_ {
                fastcgi::ABORT_REQUEST => {
                    self.pair.remove(&h.request_id).unwrap()
                        .1.flush()
                        .expect("Send end request on abort")
                }
                fastcgi::PARAMS if h.content_length == 0 => {
                    self.born = false;
                    return self.pair.remove(&h.request_id);
                }
                _ => {
                    self.pair.get_mut(&h.request_id).unwrap()
                        .0.fcgi_record(h, body)
                }
            }
        }

        None
    }
}

/// Callback trait
pub trait Handler
{
    /// Run HTTP-request handling
    fn process(&self, &mut HttpPair);
}

<|endoftext|>


<commit_before>//! solve ODE with rust-ndarray

#[macro_use]
extern crate derive_new;
extern crate fftw;
extern crate ndarray;
extern crate ndarray_linalg;
extern crate num_complex;
extern crate num_traits;

pub mod adaptor;
pub mod explicit;
pub mod lyapunov;
pub mod ode;
pub mod pde;
pub mod semi_implicit;
pub mod traits;
<commit_msg>Fix doc<commit_after>//! Configurable ODE/PDE solver

#[macro_use]
extern crate derive_new;
extern crate fftw;
extern crate ndarray;
extern crate ndarray_linalg;
extern crate num_complex;
extern crate num_traits;

pub mod adaptor;
pub mod explicit;
pub mod lyapunov;
pub mod ode;
pub mod pde;
pub mod semi_implicit;
pub mod traits;
<|endoftext|>


<commit_before>#![feature(std_misc)]

extern crate xml;

#[macro_use]
extern crate log;

use std::num::{Float};

pub mod document;
mod utils;
mod obj;

pub use obj::*;

pub type Matrix4<T> = [[T; 4]; 4];
pub fn mat4_id<T: Float>() -> Matrix4<T> {
    let _1 = Float::one();
    let _0 = Float::zero();
    [
        [_1, _0, _0, _0],
        [_0, _1, _0, _0],
        [_0, _0, _1, _0],
        [_0, _0, _0, _1],
    ]
}

#[derive(Debug)]
pub struct Skeleton {
    ///
    /// All joints in the skeleton
    ///
    pub joints: Vec<Joint>,

    ///
    /// Default parent-relative transforms for each joint (at time of vertex binding)
    /// Column-major.
    ///
    pub bind_poses: Vec<Matrix4<f32>>,
}

#[derive(Debug)]
pub struct Joint {
    ///
    /// Name of joint
    ///
    pub name: String,

    ///
    /// Index of parent joint in Skeleton's 'joints' vector
    ///
    pub parent_index: JointIndex,

    ///
    /// Matrix transforming vertex coordinates from model-space to joint-space
    /// Column-major.
    ///
    pub inverse_bind_pose: Matrix4<f32>,
}

impl Joint {
    pub fn is_root(&self) -> bool {
        self.parent_index == ROOT_JOINT_PARENT_INDEX
    }
}

///
/// A COLLADA animation consists of mapping of sample times to pose transforms
/// for a single node in the scene (usually a skeleton joint)
///
/// Note - COLLADA supports animating arbitrary 'outputs', not just pose transforms,
/// (eg colors, texture offsets, etc), but we'll leave those unsupported for now.
///
#[derive(Debug)]
pub struct Animation {
    ///
    /// The node (joint) this animation is targeting
    ///
    pub target: String,

    ///
    /// Times for each sample (in seconds)
    ///
    pub sample_times: Vec<f32>,

    ///
    /// Node pose transforms for each sample.
    /// Column-major.
    ///
    pub sample_poses: Vec<Matrix4<f32>>,
}

///
/// Skeleton-Mesh Binding Data
///

#[derive(Debug)]
pub struct BindDataSet {
    pub bind_data: Vec<BindData>,
}

#[derive(Debug)]
pub struct BindData {
    pub object_name: String,
    pub skeleton_name: String,
    pub joint_names: Vec<String>,

    /// Vertex weights, for vertex by index in mesh and joint by index in 'joint_names'
    /// and weight by index in 'weights'
    pub vertex_weights: Vec<VertexWeight>,

    /// Weight values that are indexed by VertexWeights
    pub weights: Vec<f32>,

    /// Inverse bind pose matrices listed in order of joint_names
    /// Column-major
    pub inverse_bind_poses: Vec<Matrix4<f32>>,
}

#[derive(Debug, Copy, Clone)]
pub struct VertexWeight {
    pub vertex: VertexIndex,
    pub joint: JointIndex,
    pub weight: WeightIndex,
}

pub type WeightIndex = usize;

pub type JointIndex = u8;
pub const ROOT_JOINT_PARENT_INDEX: JointIndex  = 255u8;
<commit_msg>Skeleton implements `Clone`<commit_after>#![feature(std_misc)]

extern crate xml;

#[macro_use]
extern crate log;

use std::num::{Float};

pub mod document;
mod utils;
mod obj;

pub use obj::*;

pub type Matrix4<T> = [[T; 4]; 4];
pub fn mat4_id<T: Float>() -> Matrix4<T> {
    let _1 = Float::one();
    let _0 = Float::zero();
    [
        [_1, _0, _0, _0],
        [_0, _1, _0, _0],
        [_0, _0, _1, _0],
        [_0, _0, _0, _1],
    ]
}

#[derive(Debug, Clone)]
pub struct Skeleton {
    ///
    /// All joints in the skeleton
    ///
    pub joints: Vec<Joint>,

    ///
    /// Default parent-relative transforms for each joint (at time of vertex binding)
    /// Column-major.
    ///
    pub bind_poses: Vec<Matrix4<f32>>,
}

#[derive(Debug, Clone)]
pub struct Joint {
    ///
    /// Name of joint
    ///
    pub name: String,

    ///
    /// Index of parent joint in Skeleton's 'joints' vector
    ///
    pub parent_index: JointIndex,

    ///
    /// Matrix transforming vertex coordinates from model-space to joint-space
    /// Column-major.
    ///
    pub inverse_bind_pose: Matrix4<f32>,
}

impl Joint {
    pub fn is_root(&self) -> bool {
        self.parent_index == ROOT_JOINT_PARENT_INDEX
    }
}

///
/// A COLLADA animation consists of mapping of sample times to pose transforms
/// for a single node in the scene (usually a skeleton joint)
///
/// Note - COLLADA supports animating arbitrary 'outputs', not just pose transforms,
/// (eg colors, texture offsets, etc), but we'll leave those unsupported for now.
///
#[derive(Debug)]
pub struct Animation {
    ///
    /// The node (joint) this animation is targeting
    ///
    pub target: String,

    ///
    /// Times for each sample (in seconds)
    ///
    pub sample_times: Vec<f32>,

    ///
    /// Node pose transforms for each sample.
    /// Column-major.
    ///
    pub sample_poses: Vec<Matrix4<f32>>,
}

///
/// Skeleton-Mesh Binding Data
///

#[derive(Debug)]
pub struct BindDataSet {
    pub bind_data: Vec<BindData>,
}

#[derive(Debug)]
pub struct BindData {
    pub object_name: String,
    pub skeleton_name: String,
    pub joint_names: Vec<String>,

    /// Vertex weights, for vertex by index in mesh and joint by index in 'joint_names'
    /// and weight by index in 'weights'
    pub vertex_weights: Vec<VertexWeight>,

    /// Weight values that are indexed by VertexWeights
    pub weights: Vec<f32>,

    /// Inverse bind pose matrices listed in order of joint_names
    /// Column-major
    pub inverse_bind_poses: Vec<Matrix4<f32>>,
}

#[derive(Debug, Copy, Clone)]
pub struct VertexWeight {
    pub vertex: VertexIndex,
    pub joint: JointIndex,
    pub weight: WeightIndex,
}

pub type WeightIndex = usize;

pub type JointIndex = u8;
pub const ROOT_JOINT_PARENT_INDEX: JointIndex  = 255u8;
<|endoftext|>


<commit_before>#![feature(libc, std_misc, core)]

extern crate libc;

use std::marker::PhantomData;

use pin::{Pin, RequiresRoot};

macro_rules! impl_pins {
    ($($name:ident),+) => (
        $(
            #[derive(Clone, Copy)]
            pub struct $name;

            impl Pin for $name {}
        )+
    )
}

macro_rules! require_root {
    ($($name:ident: $pwm:expr),+) => (
        $(
            impl RequiresRoot for $name {
                #[inline]
                fn pwm_pin() -> PwmPin<$name> {
                    PwmPin::new($pwm)
                }
            }
        )+
    )
}

mod bindings;

pub mod time {
    use libc;
    use bindings;
    use std::time::Duration;

/**

This causes program execution to pause for at least the provided duration in
milliseconds.

Due to the multi-tasking nature of Linux it could be longer. Note that the
maximum delay is an unsigned 32-bit integer or approximately 49 days.

*/
    pub fn delay(duration: Duration) {
        let duration = duration.num_milliseconds();
        if duration <= 0 {
            return;
        }

        unsafe {
            bindings::delay(duration as libc::c_uint);
        }
    }

/**

This causes program execution to pause for at least the provided number of
microseconds.

Due to the multi-tasking nature of Linux it could be longer. Note that the
maximum delay is an unsigned 32-bit integer microseconds or approximately 71
minutes.

*/
    pub fn delay_microseconds(microseconds: usize) {
        unsafe {
            bindings::delayMicroseconds(microseconds as libc::c_uint);
        }
    }

/**

This returns a number representing the number if milliseconds since your
program called one of the setup functions.

It returns an unsigned 32-bit number which wraps after 49 days.

*/

    pub fn millis() -> usize {
        unsafe {
            bindings::millis() as usize
        }
    }

/**

This returns a number representing the number if microseconds since your
program called one of the setup functions.

It returns an unsigned 32-bit number which wraps after 71 minutes.

*/

    pub fn micros() -> usize {
        unsafe {
            bindings::micros() as usize
        }
    }
}

pub mod thread {
    use bindings;
    use libc;

/**

This attempts to shift your program (or thread in a multi-threaded
program) to a higher priority and enables a real-time scheduling.

The priority parameter should be from 0 (the default) to 99 (the maximum).
This won’t make your program go any faster, but it will give it a bigger slice
of time when other programs are running. The priority parameter works relative
to others – so you can make one program priority 1 and another priority 2 and
it will have the same effect as setting one to 10 and the other to 90 (as long
as no other programs are running with elevated priorities)

The return value is `true` for success and `false` for error. If an error is returned,
the program should then consult the _errno_ global variable, as per the usual
conventions.

_Note_: Only programs running as root can change their priority. If called from
a non-root program then nothing happens.

*/
    pub fn priority(priority: u8) -> bool {
        unsafe {
            bindings::piHiPri(priority as libc::c_int) >= 0
        }
    }
}

pub mod pin {
    use bindings;
    use libc;
    use self::Value::{Low, High};

    use std::marker::{MarkerTrait, PhantomData};

    impl_pins!(WiringPi, Gpio, Sys);
    require_root!(WiringPi: 1, Gpio: 18);

    pub trait Pin: MarkerTrait {}

    pub trait RequiresRoot: Pin {
        fn pwm_pin() -> PwmPin<Self>;
    }

    #[derive(Clone, Copy)]
    pub enum Value {
        Low = 0,
        High
    }

    #[derive(Clone, Copy)]
    pub enum Pull {
        Off = 0,
        Down,
        Up
    }

    #[derive(Clone, Copy)]
    pub enum PwmMode {
        MarkSpace = 0,
        Balanced
    }

    pub struct InputPin<Pin>(libc::c_int, PhantomData<Pin>);

    impl<P: Pin> InputPin<P> {
        pub fn new(pin: libc::c_int) -> InputPin<P> {
            unsafe {
                bindings::pinMode(pin, 0);
            }

            InputPin(pin, PhantomData)
        }

        #[inline]
        pub fn number(&self) -> libc::c_int {
            let &InputPin(number, _) = self;
            number
        }

        pub fn into_output(self) -> OutputPin<P> {
            let InputPin(number, _) = self;
            OutputPin::new(number)
        }

        ///This function returns the value read at the given pin.
        ///
        ///It will be `High` or `Low` (1 or 0) depending on the logic level at the pin.
        pub fn digital_read(&self) -> Value {
            let value = unsafe {
                bindings::digitalRead(self.number())
            };

            if value == 0 {
                Low
            } else {
                High
            }
        }
    }

    impl<P: Pin + RequiresRoot> InputPin<P> {
        pub fn into_pwm(self) -> PwmPin<P> {
            let InputPin(number, _) = self;
            PwmPin::new(number)
        }
/**

This sets the pull-up or pull-down resistor mode on the given pin.

Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors.
The parameter pud should be; `Off`, (no pull up/down), `Down` (pull to ground)
or `Up` (pull to 3.3v)

*/
        pub fn pull_up_dn_control(&self, pud: Pull) {
            unsafe {
                bindings::pullUpDnControl(self.number(), pud as libc::c_int);
            }
        }
    }

    pub struct OutputPin<Pin>(libc::c_int, PhantomData<Pin>);

    impl<P: Pin> OutputPin<P> {
        pub fn new(pin: libc::c_int) -> OutputPin<P> {
            unsafe {
                bindings::pinMode(pin, 1);
            }

            OutputPin(pin, PhantomData)
        }

        #[inline]
        pub fn number(&self) -> libc::c_int {
            let &OutputPin(number, _) = self;
            number
        }

        pub fn into_input(self) -> InputPin<P> {
            let OutputPin(number, _) = self;
            InputPin::new(number)
        }

        ///Writes the value `High` or `Low` (1 or 0) to the given pin which must have been previously set as an output.
        pub fn digital_write(&self, value: Value) {
            unsafe {
                bindings::digitalWrite(self.number(), value as libc::c_int);
            }
        }
    }

    impl<P: Pin + RequiresRoot> OutputPin<P> {
        pub fn into_pwm(self) -> PwmPin<P> {
            let OutputPin(number, _) = self;
            PwmPin::new(number)
        }
    }

    ///To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.
    pub struct PwmPin<Pin>(libc::c_int, PhantomData<Pin>);

    impl<P: Pin + RequiresRoot> PwmPin<P> {
        pub fn new(pin: libc::c_int) -> PwmPin<P> {
            unsafe {
                bindings::pinMode(pin, 2);
            }

            PwmPin(pin, PhantomData)
        }

        #[inline]
        pub fn number(&self) -> libc::c_int {
            let &PwmPin(number, _) = self;
            number
        }

        pub fn into_input(self) -> InputPin<P> {
            let PwmPin(number, _) = self;
            InputPin::new(number)
        }

        pub fn into_output(self) -> OutputPin<P> {
            let PwmPin(number, _) = self;
            OutputPin::new(number)
        }

        ///Writes the value to the PWM register for the given pin.
        ///
        ///The value must be between 0 and 1024.
        pub fn write(&self, value: usize) {
            unsafe {
                bindings::pwmWrite(self.number(), value as libc::c_int);
            }
        }

/**

The PWM generator can run in 2 modes – "balanced" and "mark:space".

The mark:space mode is traditional, however the default mode in the Pi is
"balanced". You can switch modes by supplying the parameter: `Balanced` or
`MarkSpace`.

*/
        pub fn set_mode(&self, mode: PwmMode) {
            unsafe {
                bindings::pwmSetMode(mode as libc::c_int);
            }
        }

        ///This sets the range register in the PWM generator. The default is 1024.
        pub fn set_range(&self, value: usize) {
            unsafe {
                bindings::pwmSetRange(value as libc::c_uint);
            }
        }

        ///This sets the divisor for the PWM clock.
        pub fn set_clock(&self, value: usize) {
            unsafe {
                bindings::pwmSetClock(value as libc::c_int);
            }
        }
    }
}

/**

This initialises the wiringPi system and assumes that the calling program is
going to be using the **wiringPi** pin numbering scheme.

This is a simplified numbering scheme which provides a mapping from virtual
pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. See
the pins page for a table which maps the **wiringPi** pin number to the Broadcom
GPIO pin number to the physical location on the edge connector.

This function needs to be called with root privileges.

*/
pub fn setup() -> Option<WiringPi<pin::WiringPi>> {
    unsafe {
        if bindings::wiringPiSetup() >= 0 {
            Some(WiringPi(PhantomData))
        } else {
            None
        }
    }
}

/**

This is identical `setup()`, however it allows the calling programs to use the
Broadcom GPIO pin numbers directly with no re-mapping.

This function needs to be called with root privileges.

*/
pub fn setup_gpio() -> Option<WiringPi<pin::Gpio>> {
    unsafe {
        if bindings::wiringPiSetupGpio() >= 0 {
            Some(WiringPi(PhantomData))
        } else {
            None
        }
    }
}

/**

This initialises the wiringPi system but uses the /sys/class/gpio interface
rather than accessing the hardware directly.

This can be called as a non-root user provided the GPIO pins have been
exported before-hand using the gpio program. Pin number in this mode is the
native Broadcom GPIO numbers.

_Note_: In this mode you can only use the pins which have been exported via the
/sys/class/gpio interface. You must export these pins before you call your
program. You can do this in a separate shell-script, or by using the system()
function from inside your program.

Also note that some functions have no effect when using this mode as they’re
not currently possible to action unless called with root privileges.

*/
pub fn setup_sys() -> Option<WiringPi<pin::Sys>> {
    unsafe {
        if bindings::wiringPiSetupSys() >= 0 {
            Some(WiringPi(PhantomData))
        } else {
            None
        }
    }
}

/**

This returns the board revision of the Raspberry Pi.

It will be either 1 or 2. Some of the BCM_GPIO pins changed number and
function when moving from board revision 1 to 2, so if you are using BCM_GPIO
pin numbers, then you need to be aware of the differences.

*/
pub fn board_revision() -> usize {
    unsafe {
        bindings::piBoardRev() as usize
    }
}

///This returns the BCM_GPIO pin number of the supplied **wiringPi** pin.
///
///It takes the board revision into account.
pub fn to_gpio_number(wpi_number: usize) -> usize {
    unsafe {
        bindings::wpiPinToGpio(wpi_number as libc::c_int) as usize
    }
}

pub struct WiringPi<Pin>(PhantomData<Pin>);

impl<P: Pin> WiringPi<P> {
    pub fn input_pin(&self, pin: usize) -> pin::InputPin<P> {
        let pin = pin as libc::c_int;
        pin::InputPin::new(pin)
    }

    pub fn output_pin(&self, pin: usize) -> pin::OutputPin<P> {
        let pin = pin as libc::c_int;
        pin::OutputPin::new(pin)
    }
}

impl<P: RequiresRoot + Pin> WiringPi<P> {
    pub fn pwm_pin(&self) -> pin::PwmPin<P> {
        RequiresRoot::pwm_pin()
    }
}<commit_msg>Remove MarkerTrait and unnecessary core feature<commit_after>#![feature(libc, std_misc)]

extern crate libc;

use std::marker::PhantomData;

use pin::{Pin, RequiresRoot};

macro_rules! impl_pins {
    ($($name:ident),+) => (
        $(
            #[derive(Clone, Copy)]
            pub struct $name;

            impl Pin for $name {}
        )+
    )
}

macro_rules! require_root {
    ($($name:ident: $pwm:expr),+) => (
        $(
            impl RequiresRoot for $name {
                #[inline]
                fn pwm_pin() -> PwmPin<$name> {
                    PwmPin::new($pwm)
                }
            }
        )+
    )
}

mod bindings;

pub mod time {
    use libc;
    use bindings;
    use std::time::Duration;

/**

This causes program execution to pause for at least the provided duration in
milliseconds.

Due to the multi-tasking nature of Linux it could be longer. Note that the
maximum delay is an unsigned 32-bit integer or approximately 49 days.

*/
    pub fn delay(duration: Duration) {
        let duration = duration.num_milliseconds();
        if duration <= 0 {
            return;
        }

        unsafe {
            bindings::delay(duration as libc::c_uint);
        }
    }

/**

This causes program execution to pause for at least the provided number of
microseconds.

Due to the multi-tasking nature of Linux it could be longer. Note that the
maximum delay is an unsigned 32-bit integer microseconds or approximately 71
minutes.

*/
    pub fn delay_microseconds(microseconds: usize) {
        unsafe {
            bindings::delayMicroseconds(microseconds as libc::c_uint);
        }
    }

/**

This returns a number representing the number if milliseconds since your
program called one of the setup functions.

It returns an unsigned 32-bit number which wraps after 49 days.

*/

    pub fn millis() -> usize {
        unsafe {
            bindings::millis() as usize
        }
    }

/**

This returns a number representing the number if microseconds since your
program called one of the setup functions.

It returns an unsigned 32-bit number which wraps after 71 minutes.

*/

    pub fn micros() -> usize {
        unsafe {
            bindings::micros() as usize
        }
    }
}

pub mod thread {
    use bindings;
    use libc;

/**

This attempts to shift your program (or thread in a multi-threaded
program) to a higher priority and enables a real-time scheduling.

The priority parameter should be from 0 (the default) to 99 (the maximum).
This won’t make your program go any faster, but it will give it a bigger slice
of time when other programs are running. The priority parameter works relative
to others – so you can make one program priority 1 and another priority 2 and
it will have the same effect as setting one to 10 and the other to 90 (as long
as no other programs are running with elevated priorities)

The return value is `true` for success and `false` for error. If an error is returned,
the program should then consult the _errno_ global variable, as per the usual
conventions.

_Note_: Only programs running as root can change their priority. If called from
a non-root program then nothing happens.

*/
    pub fn priority(priority: u8) -> bool {
        unsafe {
            bindings::piHiPri(priority as libc::c_int) >= 0
        }
    }
}

pub mod pin {
    use bindings;
    use libc;
    use self::Value::{Low, High};

    use std::marker::PhantomData;

    impl_pins!(WiringPi, Gpio, Sys);
    require_root!(WiringPi: 1, Gpio: 18);

    pub trait Pin {}

    pub trait RequiresRoot: Pin {
        fn pwm_pin() -> PwmPin<Self>;
    }

    #[derive(Clone, Copy)]
    pub enum Value {
        Low = 0,
        High
    }

    #[derive(Clone, Copy)]
    pub enum Pull {
        Off = 0,
        Down,
        Up
    }

    #[derive(Clone, Copy)]
    pub enum PwmMode {
        MarkSpace = 0,
        Balanced
    }

    pub struct InputPin<Pin>(libc::c_int, PhantomData<Pin>);

    impl<P: Pin> InputPin<P> {
        pub fn new(pin: libc::c_int) -> InputPin<P> {
            unsafe {
                bindings::pinMode(pin, 0);
            }

            InputPin(pin, PhantomData)
        }

        #[inline]
        pub fn number(&self) -> libc::c_int {
            let &InputPin(number, _) = self;
            number
        }

        pub fn into_output(self) -> OutputPin<P> {
            let InputPin(number, _) = self;
            OutputPin::new(number)
        }

        ///This function returns the value read at the given pin.
        ///
        ///It will be `High` or `Low` (1 or 0) depending on the logic level at the pin.
        pub fn digital_read(&self) -> Value {
            let value = unsafe {
                bindings::digitalRead(self.number())
            };

            if value == 0 {
                Low
            } else {
                High
            }
        }
    }

    impl<P: Pin + RequiresRoot> InputPin<P> {
        pub fn into_pwm(self) -> PwmPin<P> {
            let InputPin(number, _) = self;
            PwmPin::new(number)
        }
/**

This sets the pull-up or pull-down resistor mode on the given pin.

Unlike the Arduino, the BCM2835 has both pull-up an down internal resistors.
The parameter pud should be; `Off`, (no pull up/down), `Down` (pull to ground)
or `Up` (pull to 3.3v)

*/
        pub fn pull_up_dn_control(&self, pud: Pull) {
            unsafe {
                bindings::pullUpDnControl(self.number(), pud as libc::c_int);
            }
        }
    }

    pub struct OutputPin<Pin>(libc::c_int, PhantomData<Pin>);

    impl<P: Pin> OutputPin<P> {
        pub fn new(pin: libc::c_int) -> OutputPin<P> {
            unsafe {
                bindings::pinMode(pin, 1);
            }

            OutputPin(pin, PhantomData)
        }

        #[inline]
        pub fn number(&self) -> libc::c_int {
            let &OutputPin(number, _) = self;
            number
        }

        pub fn into_input(self) -> InputPin<P> {
            let OutputPin(number, _) = self;
            InputPin::new(number)
        }

        ///Writes the value `High` or `Low` (1 or 0) to the given pin which must have been previously set as an output.
        pub fn digital_write(&self, value: Value) {
            unsafe {
                bindings::digitalWrite(self.number(), value as libc::c_int);
            }
        }
    }

    impl<P: Pin + RequiresRoot> OutputPin<P> {
        pub fn into_pwm(self) -> PwmPin<P> {
            let OutputPin(number, _) = self;
            PwmPin::new(number)
        }
    }

    ///To understand more about the PWM system, you’ll need to read the Broadcom ARM peripherals manual.
    pub struct PwmPin<Pin>(libc::c_int, PhantomData<Pin>);

    impl<P: Pin + RequiresRoot> PwmPin<P> {
        pub fn new(pin: libc::c_int) -> PwmPin<P> {
            unsafe {
                bindings::pinMode(pin, 2);
            }

            PwmPin(pin, PhantomData)
        }

        #[inline]
        pub fn number(&self) -> libc::c_int {
            let &PwmPin(number, _) = self;
            number
        }

        pub fn into_input(self) -> InputPin<P> {
            let PwmPin(number, _) = self;
            InputPin::new(number)
        }

        pub fn into_output(self) -> OutputPin<P> {
            let PwmPin(number, _) = self;
            OutputPin::new(number)
        }

        ///Writes the value to the PWM register for the given pin.
        ///
        ///The value must be between 0 and 1024.
        pub fn write(&self, value: usize) {
            unsafe {
                bindings::pwmWrite(self.number(), value as libc::c_int);
            }
        }

/**

The PWM generator can run in 2 modes – "balanced" and "mark:space".

The mark:space mode is traditional, however the default mode in the Pi is
"balanced". You can switch modes by supplying the parameter: `Balanced` or
`MarkSpace`.

*/
        pub fn set_mode(&self, mode: PwmMode) {
            unsafe {
                bindings::pwmSetMode(mode as libc::c_int);
            }
        }

        ///This sets the range register in the PWM generator. The default is 1024.
        pub fn set_range(&self, value: usize) {
            unsafe {
                bindings::pwmSetRange(value as libc::c_uint);
            }
        }

        ///This sets the divisor for the PWM clock.
        pub fn set_clock(&self, value: usize) {
            unsafe {
                bindings::pwmSetClock(value as libc::c_int);
            }
        }
    }
}

/**

This initialises the wiringPi system and assumes that the calling program is
going to be using the **wiringPi** pin numbering scheme.

This is a simplified numbering scheme which provides a mapping from virtual
pin numbers 0 through 16 to the real underlying Broadcom GPIO pin numbers. See
the pins page for a table which maps the **wiringPi** pin number to the Broadcom
GPIO pin number to the physical location on the edge connector.

This function needs to be called with root privileges.

*/
pub fn setup() -> Option<WiringPi<pin::WiringPi>> {
    unsafe {
        if bindings::wiringPiSetup() >= 0 {
            Some(WiringPi(PhantomData))
        } else {
            None
        }
    }
}

/**

This is identical `setup()`, however it allows the calling programs to use the
Broadcom GPIO pin numbers directly with no re-mapping.

This function needs to be called with root privileges.

*/
pub fn setup_gpio() -> Option<WiringPi<pin::Gpio>> {
    unsafe {
        if bindings::wiringPiSetupGpio() >= 0 {
            Some(WiringPi(PhantomData))
        } else {
            None
        }
    }
}

/**

This initialises the wiringPi system but uses the /sys/class/gpio interface
rather than accessing the hardware directly.

This can be called as a non-root user provided the GPIO pins have been
exported before-hand using the gpio program. Pin number in this mode is the
native Broadcom GPIO numbers.

_Note_: In this mode you can only use the pins which have been exported via the
/sys/class/gpio interface. You must export these pins before you call your
program. You can do this in a separate shell-script, or by using the system()
function from inside your program.

Also note that some functions have no effect when using this mode as they’re
not currently possible to action unless called with root privileges.

*/
pub fn setup_sys() -> Option<WiringPi<pin::Sys>> {
    unsafe {
        if bindings::wiringPiSetupSys() >= 0 {
            Some(WiringPi(PhantomData))
        } else {
            None
        }
    }
}

/**

This returns the board revision of the Raspberry Pi.

It will be either 1 or 2. Some of the BCM_GPIO pins changed number and
function when moving from board revision 1 to 2, so if you are using BCM_GPIO
pin numbers, then you need to be aware of the differences.

*/
pub fn board_revision() -> usize {
    unsafe {
        bindings::piBoardRev() as usize
    }
}

///This returns the BCM_GPIO pin number of the supplied **wiringPi** pin.
///
///It takes the board revision into account.
pub fn to_gpio_number(wpi_number: usize) -> usize {
    unsafe {
        bindings::wpiPinToGpio(wpi_number as libc::c_int) as usize
    }
}

pub struct WiringPi<Pin>(PhantomData<Pin>);

impl<P: Pin> WiringPi<P> {
    pub fn input_pin(&self, pin: usize) -> pin::InputPin<P> {
        let pin = pin as libc::c_int;
        pin::InputPin::new(pin)
    }

    pub fn output_pin(&self, pin: usize) -> pin::OutputPin<P> {
        let pin = pin as libc::c_int;
        pin::OutputPin::new(pin)
    }
}

impl<P: RequiresRoot + Pin> WiringPi<P> {
    pub fn pwm_pin(&self) -> pin::PwmPin<P> {
        RequiresRoot::pwm_pin()
    }
}<|endoftext|>


<commit_before>//! # Cursive
//!
//! Cursive is a TUI library built on top of ncurses-rs.
//! It allows to easily build layouts for text-based applications.
//!
//! ## Example
//! ```
//! extern crate cursive;
//!
//! use cursive::Cursive;
//! use cursive::view::TextView;
//!
//! fn main() {
//!     let mut siv = Cursive::new();
//!
//!     siv.add_layer(TextView::new("Hello World!\nPress q to quit."));
//!
//!     siv.add_global_callback('q' as i32, |s| s.quit());
//!
//!     siv.run();
//! }
//! ```
extern crate ncurses;
extern crate toml;

pub mod event;
pub mod view;
pub mod printer;
pub mod vec;
pub mod color;

mod div;
mod margins;

pub use margins::Margins;

use std::any::Any;
use std::rc::Rc;
use std::collections::HashMap;
use std::sync::mpsc;

use vec::Vec2;
use view::View;
use printer::Printer;
use view::{StackView,ViewPath};

use event::{EventResult,Callback};

/// Identifies a screen in the cursive ROOT.
pub type ScreenId = usize;

/// Central part of the cursive library.
///
/// It initializes ncurses on creation and cleans up on drop.
/// To use it, you should populate it with views, layouts and callbacks,
/// then start the event loop with run().
///
/// It uses a list of screen, with one screen active at a time.
pub struct Cursive {
    screens: Vec<StackView>,

    active_screen: ScreenId,

    running: bool,

    global_callbacks: HashMap<i32, Rc<Callback>>,
}

impl Cursive {
    /// Creates a new Cursive root, and initialize ncurses.
    pub fn new() -> Self {
        ncurses::setlocale(ncurses::LcCategory::all, "");
        ncurses::initscr();
        ncurses::keypad(ncurses::stdscr, true);
        ncurses::noecho();
        ncurses::cbreak();
        ncurses::start_color();
        ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
        color::load_legacy();
        // color::load_default();
        // color::load_theme("assets/style.toml").ok().unwrap();

        ncurses::wbkgd(ncurses::stdscr, ncurses::COLOR_PAIR(color::BACKGROUND));

        let mut res = Cursive {
            screens: Vec::new(),
            active_screen: 0,
            running: true,
            global_callbacks: HashMap::new(),
        };

        res.screens.push(StackView::new());

        res
    }

    /// Regularly redraws everything, even when no input is given.
    ///
    /// Call with fps=0 to disable (default value).
    pub fn set_fps(&self, fps: u32) {
        if fps == 0 {
            ncurses::timeout(-1);
        } else {
            ncurses::timeout(1000 / fps as i32);
        }
    }

    /// Returns a mutable reference to the currently active screen.
    pub fn screen_mut(&mut self) -> &mut StackView {
        let id = self.active_screen;
        self.screens.get_mut(id).unwrap()
    }

    /// Adds a new screen, and returns its ID.
    pub fn add_screen(&mut self) -> ScreenId {
        let res = self.screens.len();
        self.screens.push(StackView::new());
        res
    }

    /// Convenient method to create a new screen, and set it as active.
    pub fn add_active_screen(&mut self) -> ScreenId {
        let res = self.add_screen();
        self.set_screen(res);
        res
    }

    /// Sets the active screen. Panics if no such screen exist.
    pub fn set_screen(&mut self, screen_id: ScreenId) {
        if screen_id >= self.screens.len() {
            panic!("Tried to set an invalid screen ID: {}, but only {} screens present.", screen_id, self.screens.len());
        }
        self.active_screen = screen_id;
    }

    fn find_any(&mut self, path: &ViewPath) -> Option<&mut Any> {
        // Internal find method that returns a Any object.
        self.screen_mut().find(path)
    }

    /// Tries to find the view pointed to by the given path.
    /// If the view is not found, or if it is not of the asked type,
    /// it returns None.
    pub fn find<V: View + Any>(&mut self, path: &ViewPath) -> Option<&mut V> {
        match self.find_any(path) {
            None => None,
            Some(b) => b.downcast_mut::<V>(),
        }
    }

    /// Adds a global callback, triggered on the given key press when no view catches it.
    pub fn add_global_callback<F>(&mut self, key: i32, cb: F)
        where F: Fn(&mut Cursive, &ViewPath) + 'static
    {
        self.global_callbacks.insert(key, Rc::new(Box::new(cb)));
    }

    /// Convenient method to add a layer to the current screen.
    pub fn add_layer<T: 'static + View>(&mut self, view: T) {
        self.screen_mut().add_layer(view);
    }

    // Handles a key event when it was ignored by the current view
    fn on_key_event(&mut self, ch: i32) {
        let cb = match self.global_callbacks.get(&ch) {
            None => return,
            Some(cb) => cb.clone(),
        };
        // Not from a view, so no viewpath here
        cb(self, &ViewPath::new());
    }

    /// Returns the size of the screen, in characters.
    pub fn screen_size(&self) -> Vec2 {
        let mut x: i32 = 0;
        let mut y: i32 = 0;
        ncurses::getmaxyx(ncurses::stdscr, &mut y, &mut x);

        Vec2 {
            x: x as u32,
            y: y as u32,
        }
    }

    fn layout(&mut self) {
        let size = self.screen_size();
        self.screen_mut().layout(size);
    }

    fn draw(&mut self) {
        let printer = Printer {
            win: ncurses::stdscr,
            offset: Vec2::new(0,0),
            size: self.screen_size(),
        };
        self.screen_mut().draw(&printer, true);
    }

    /// Runs the event loop.
    /// It will wait for user input (key presses) and trigger callbacks accordingly.
    /// Blocks until quit() is called.
    pub fn run(&mut self) {
        // And the big event loop begins!
        while self.running {
            // Do we need to redraw everytime?
            // Probably, actually.
            // TODO: Do we actually need to clear everytime?
            ncurses::clear();
            // TODO: Do we need to re-layout everytime?
            self.layout();
            // TODO: Do we need to redraw every view every time?
            // (Is this getting repetitive? :p)
            self.draw();

            // Blocks until the user press a key.
            // TODO: Add a timeout? Animations?
            let ch = ncurses::getch();

            // If the event was ignored, it is our turn to play with it.
            match self.screen_mut().on_key_event(ch) {
                EventResult::Ignored => self.on_key_event(ch),
                EventResult::Consumed(None, _) => (),
                EventResult::Consumed(Some(cb), path) => cb(self, &path),
            }
        }
    }

    /// Stops the event loop.
    pub fn quit(&mut self) {
        self.running = false;
    }
}

impl Drop for Cursive {
    fn drop(&mut self) {
        ncurses::endwin();
    }
}

<commit_msg>Remove unused mpsc import.<commit_after>//! /// Represents a colorpair from a Theme.
//! # Cursive
//!
//! Cursive is a TUI library built on top of ncurses-rs.
//! It allows to easily build layouts for text-based applications.
//!
//! ## Example
//! ```
//! extern crate cursive;
//!
//! use cursive::Cursive;
//! use cursive::view::TextView;
//!
//! fn main() {
//!     let mut siv = Cursive::new();
//!
//!     siv.add_layer(TextView::new("Hello World!\nPress q to quit."));
//!
//!     siv.add_global_callback('q' as i32, |s| s.quit());
//!
//!     siv.run();
//! }
//! ```
extern crate ncurses;
extern crate toml;

pub mod event;
pub mod view;
pub mod printer;
pub mod vec;
pub mod color;

mod div;
mod margins;

pub use margins::Margins;

use std::any::Any;
use std::rc::Rc;
use std::collections::HashMap;

use vec::Vec2;
use view::View;
use printer::Printer;
use view::{StackView,ViewPath};

use event::{EventResult,Callback};

/// Identifies a screen in the cursive ROOT.
pub type ScreenId = usize;

/// Central part of the cursive library.
///
/// It initializes ncurses on creation and cleans up on drop.
/// To use it, you should populate it with views, layouts and callbacks,
/// then start the event loop with run().
///
/// It uses a list of screen, with one screen active at a time.
pub struct Cursive {
    screens: Vec<StackView>,

    active_screen: ScreenId,

    running: bool,

    global_callbacks: HashMap<i32, Rc<Callback>>,
}

impl Cursive {
    /// Creates a new Cursive root, and initialize ncurses.
    pub fn new() -> Self {
        ncurses::setlocale(ncurses::LcCategory::all, "");
        ncurses::initscr();
        ncurses::keypad(ncurses::stdscr, true);
        ncurses::noecho();
        ncurses::cbreak();
        ncurses::start_color();
        ncurses::curs_set(ncurses::CURSOR_VISIBILITY::CURSOR_INVISIBLE);
        color::load_legacy();
        // color::load_default();
        // color::load_theme("assets/style.toml").ok().unwrap();

        ncurses::wbkgd(ncurses::stdscr, ncurses::COLOR_PAIR(color::BACKGROUND));

        let mut res = Cursive {
            screens: Vec::new(),
            active_screen: 0,
            running: true,
            global_callbacks: HashMap::new(),
        };

        res.screens.push(StackView::new());

        res
    }

    /// Regularly redraws everything, even when no input is given.
    ///
    /// Call with fps=0 to disable (default value).
    pub fn set_fps(&self, fps: u32) {
        if fps == 0 {
            ncurses::timeout(-1);
        } else {
            ncurses::timeout(1000 / fps as i32);
        }
    }

    /// Returns a mutable reference to the currently active screen.
    pub fn screen_mut(&mut self) -> &mut StackView {
        let id = self.active_screen;
        self.screens.get_mut(id).unwrap()
    }

    /// Adds a new screen, and returns its ID.
    pub fn add_screen(&mut self) -> ScreenId {
        let res = self.screens.len();
        self.screens.push(StackView::new());
        res
    }

    /// Convenient method to create a new screen, and set it as active.
    pub fn add_active_screen(&mut self) -> ScreenId {
        let res = self.add_screen();
        self.set_screen(res);
        res
    }

    /// Sets the active screen. Panics if no such screen exist.
    pub fn set_screen(&mut self, screen_id: ScreenId) {
        if screen_id >= self.screens.len() {
            panic!("Tried to set an invalid screen ID: {}, but only {} screens present.", screen_id, self.screens.len());
        }
        self.active_screen = screen_id;
    }

    fn find_any(&mut self, path: &ViewPath) -> Option<&mut Any> {
        // Internal find method that returns a Any object.
        self.screen_mut().find(path)
    }

    /// Tries to find the view pointed to by the given path.
    /// If the view is not found, or if it is not of the asked type,
    /// it returns None.
    pub fn find<V: View + Any>(&mut self, path: &ViewPath) -> Option<&mut V> {
        match self.find_any(path) {
            None => None,
            Some(b) => b.downcast_mut::<V>(),
        }
    }

    /// Adds a global callback, triggered on the given key press when no view catches it.
    pub fn add_global_callback<F>(&mut self, key: i32, cb: F)
        where F: Fn(&mut Cursive, &ViewPath) + 'static
    {
        self.global_callbacks.insert(key, Rc::new(Box::new(cb)));
    }

    /// Convenient method to add a layer to the current screen.
    pub fn add_layer<T: 'static + View>(&mut self, view: T) {
        self.screen_mut().add_layer(view);
    }

    // Handles a key event when it was ignored by the current view
    fn on_key_event(&mut self, ch: i32) {
        let cb = match self.global_callbacks.get(&ch) {
            None => return,
            Some(cb) => cb.clone(),
        };
        // Not from a view, so no viewpath here
        cb(self, &ViewPath::new());
    }

    /// Returns the size of the screen, in characters.
    pub fn screen_size(&self) -> Vec2 {
        let mut x: i32 = 0;
        let mut y: i32 = 0;
        ncurses::getmaxyx(ncurses::stdscr, &mut y, &mut x);

        Vec2 {
            x: x as u32,
            y: y as u32,
        }
    }

    fn layout(&mut self) {
        let size = self.screen_size();
        self.screen_mut().layout(size);
    }

    fn draw(&mut self) {
        let printer = Printer {
            win: ncurses::stdscr,
            offset: Vec2::new(0,0),
            size: self.screen_size(),
        };
        self.screen_mut().draw(&printer, true);
    }

    /// Runs the event loop.
    /// It will wait for user input (key presses) and trigger callbacks accordingly.
    /// Blocks until quit() is called.
    pub fn run(&mut self) {
        // And the big event loop begins!
        while self.running {
            // Do we need to redraw everytime?
            // Probably, actually.
            // TODO: Do we actually need to clear everytime?
            ncurses::clear();
            // TODO: Do we need to re-layout everytime?
            self.layout();
            // TODO: Do we need to redraw every view every time?
            // (Is this getting repetitive? :p)
            self.draw();

            // Blocks until the user press a key.
            // TODO: Add a timeout? Animations?
            let ch = ncurses::getch();

            // If the event was ignored, it is our turn to play with it.
            match self.screen_mut().on_key_event(ch) {
                EventResult::Ignored => self.on_key_event(ch),
                EventResult::Consumed(None, _) => (),
                EventResult::Consumed(Some(cb), path) => cb(self, &path),
            }
        }
    }

    /// Stops the event loop.
    pub fn quit(&mut self) {
        self.running = false;
    }
}

impl Drop for Cursive {
    fn drop(&mut self) {
        ncurses::endwin();
    }
}

<|endoftext|>


<commit_before>extern crate test;
extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate json;
extern crate time;
extern crate bus;

pub mod data;
pub mod actors;
pub mod push;
pub mod error;

#[cfg(test)]
mod tests;

<commit_msg>not importin test<commit_after>extern crate websocket;
extern crate futures;
extern crate tokio_core;
extern crate json;
extern crate time;
extern crate bus;

pub mod data;
pub mod actors;
pub mod push;
pub mod error;

#[cfg(test)]
mod tests;

<|endoftext|>


<commit_before>//! Taken from http://www.itu.int/rec/T-REC-X.680-200811-I

#![allow(dead_code)] // Until parser is complete. Too noisy otherwise

#[macro_use]
extern crate nom;

extern crate regex;

use std::str::FromStr;

/// Parse an `f64`.
///
/// Defined in X.680 §12.9
named!(realnumber<&str, f64>,
   map_res!(
       re_find!(r"^\d+(\.\d*)?([eE]-?(0|[1-9]\d*))?"),
       FromStr::from_str
   )
);

#[cfg(test)]
mod tests {

    use super::realnumber;
    use nom::IResult;
    use nom::IResult::Done;

    /// Simple way of specifying an `IResult::Done` with no remaining input.
    macro_rules! done_result (
        ($res:expr) => (
            IResult::Done("", $res)
        )
    );

    #[test]
    fn test_realnumber() {
        assert_eq!(realnumber("1"), done_result!(1.0));
        assert_eq!(realnumber("0"), done_result!(0.0));

        // Can have a leading zero
        assert_eq!(realnumber("00"), done_result!(0.0));
        assert_eq!(realnumber("01"), done_result!(1.0));

        // Can have a trailing period without a factional part
        assert_eq!(realnumber("1."), done_result!(1.0));
        assert_eq!(realnumber("1.0"), done_result!(1.0));
        assert_eq!(realnumber("1.001"), done_result!(1.001));

        // Exponents
        assert_eq!(realnumber("1.1e3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1e-3"), done_result!(0.0011));
        assert_eq!(realnumber("1.e3"), done_result!(1000.0));
        assert_eq!(realnumber("1e3"), done_result!(1000.0));
        assert_eq!(realnumber("1.1E3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1E-3"), done_result!(0.0011));

        // Leading zero in exponent
        assert_eq!(realnumber("1.1E-03"), Done("3", 1.1));
        assert_eq!(realnumber("1.1E03"), Done("3", 1.1));
    }

}
<commit_msg>Parser for `number`<commit_after>//! Taken from http://www.itu.int/rec/T-REC-X.680-200811-I

#![allow(dead_code)] // Until parser is complete. Too noisy otherwise

#[macro_use]
extern crate nom;

extern crate regex;

use std::str::FromStr;

/// Parse an integer.
///
/// Defined in X.680 §12.8
named!(number<&str, u64>,
    map_res!(
        re_find!(r"^(0|[1-9]\d*)"),
        FromStr::from_str
    )
);

/// Parse an `f64`.
///
/// Defined in X.680 §12.9
named!(realnumber<&str, f64>,
   map_res!(
       re_find!(r"^\d+(\.\d*)?([eE]-?(0|[1-9]\d*))?"),
       FromStr::from_str
   )
);

#[cfg(test)]
mod tests {

    use super::{number, realnumber};
    use nom::IResult;
    use nom::IResult::Done;

    /// Simple way of specifying an `IResult::Done` with no remaining input.
    macro_rules! done_result (
        ($res:expr) => (
            IResult::Done("", $res)
        )
    );

    #[test]
    fn test_newline() {
        assert_eq!(newline("\n"), done_result!("\n"));
        assert_eq!(newline("\x0B"), done_result!("\x0B"));
    }

    #[test]
    fn test_take_until_single_line_comment_end() {
        assert_eq!(take_until_single_line_comment_end(" thing\nmore"), Done("\nmore", " thing"));
        assert_eq!(take_until_single_line_comment_end(" thing\n"), Done("\n", " thing"));
        assert_eq!(take_until_single_line_comment_end(" thing--"), Done("--", " thing"));
        assert_eq!(take_until_single_line_comment_end(" dash-in-middle--"),
                   Done("--", " dash-in-middle"));
        assert_eq!(take_until_single_line_comment_end(" dash-in-middle\x0C"),
                   Done("\x0C", " dash-in-middle"));

        // Empty comments
        assert_eq!(take_until_single_line_comment_end("\n"), Done("\n", ""));
        assert_eq!(take_until_single_line_comment_end("--"), Done("--", ""));

        assert_eq!(take_until_single_line_comment_end("stuff-"), done_result!("stuff-"));
        assert_eq!(take_until_single_line_comment_end("-"), done_result!("-"));
    }

    #[test]
    fn test_single_line_comment() {
        assert_eq!(single_line_comment("-- thing\nmore"), Done("more", " thing"));
        assert_eq!(single_line_comment("-- thing--"), done_result!(" thing"));
        assert_eq!(single_line_comment("-- thing\n"), done_result!(" thing"));
        assert_eq!(single_line_comment("-- dash-in-middle--"), done_result!(" dash-in-middle"));
        assert_eq!(single_line_comment("-- dash-in-middle\x0C"), done_result!(" dash-in-middle"));
        assert_eq!(single_line_comment("--\n"), done_result!(""));
        assert_eq!(single_line_comment("----"), done_result!(""));
    }

    #[test]
    fn test_number() {
        assert_eq!(number("0"), done_result!(0));
        assert_eq!(number("1"), done_result!(1));

        // Matches the first zero, but considers the second digit to be leftover input.
        assert_eq!(number("01"), Done("1", 0));
    }

    #[test]
    fn test_realnumber() {
        assert_eq!(realnumber("1"), done_result!(1.0));
        assert_eq!(realnumber("0"), done_result!(0.0));

        // Can have a leading zero
        assert_eq!(realnumber("00"), done_result!(0.0));
        assert_eq!(realnumber("01"), done_result!(1.0));

        // Can have a trailing period without a factional part
        assert_eq!(realnumber("1."), done_result!(1.0));
        assert_eq!(realnumber("1.0"), done_result!(1.0));
        assert_eq!(realnumber("1.001"), done_result!(1.001));

        // Exponents
        assert_eq!(realnumber("1.1e3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1e-3"), done_result!(0.0011));
        assert_eq!(realnumber("1.e3"), done_result!(1000.0));
        assert_eq!(realnumber("1e3"), done_result!(1000.0));
        assert_eq!(realnumber("1.1E3"), done_result!(1100.0));
        assert_eq!(realnumber("1.1E-3"), done_result!(0.0011));

        // Leading zero in exponent
        assert_eq!(realnumber("1.1E-03"), Done("3", 1.1));
        assert_eq!(realnumber("1.1E03"), Done("3", 1.1));
    }

}
<|endoftext|>


<commit_before>#![recursion_limit = "150"]

#[macro_use]
extern crate nom;

pub use self::common::{FieldExpression, Operator, TableKey};
pub use self::column::{Column, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::insert::InsertStatement;
pub use self::parser::*;
pub use self::select::SelectStatement;
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod keywords;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod select;
mod table;
<commit_msg>Expose more public types<commit_after>#![recursion_limit = "150"]

#[macro_use]
extern crate nom;

pub use self::common::{FieldExpression, Operator, TableKey};
pub use self::column::{Column, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::insert::InsertStatement;
pub use self::parser::*;
pub use self::select::{SelectStatement, GroupByClause, LimitClause, OrderClause, OrderType};
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod keywords;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod select;
mod table;
<|endoftext|>


<commit_before>#![crate_name = "nickel"]
#![crate_type = "rlib"]
#![feature(slicing_syntax, plugin, core, collections, io, path, hash)]
#![plugin(regex_macros)]

//!Nickel is supposed to be a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework for JavaScript.
//!
//!Some of the features are:
//!
//!* Easy handlers: A handler is just a function that takes a `Request` and `ResponseWriter`
//!* Variables in routes. Just write `my/route/:someid`
//!* Easy parameter access: `request.params.get(&"someid")`
//!* simple wildcard routes: `/some/*/route`
//!* double wildcard routes: `/a/**/route`
//!* middleware

extern crate time;
extern crate http;
extern crate "rustc-serialize" as serialize;
extern crate regex;
extern crate typemap;
extern crate plugin;
extern crate url;
extern crate mustache;
extern crate groupable;
#[macro_use]
extern crate log;

pub use nickel::Nickel;
pub use request::Request;
pub use response::Response;
pub use middleware::{Action, Continue, Halt, Middleware, ErrorHandler, MiddlewareResult};
pub use static_files_handler::StaticFilesHandler;
pub use favicon_handler::FaviconHandler;
pub use default_error_handler::DefaultErrorHandler;
pub use json_body_parser::JsonBody;
pub use query_string::QueryString;
pub use router::{Router, Route, RouteResult, HttpRouter};
pub use nickel_error::{ NickelError, NickelErrorKind, ErrorWithStatusCode, UserDefinedError, Other };
pub use mimes::get_media_type;
pub use middleware_handler::ResponseFinalizer;

pub mod router;
mod server;
mod nickel;
mod request;
mod response;
mod middleware;
mod middleware_handler;
mod favicon_handler;
mod static_files_handler;
mod json_body_parser;
pub mod mimes;
mod query_string;
mod urlencoded;
mod nickel_error;
mod default_error_handler;
<commit_msg>fix(response): use feature std_misc for Entry::{Occupied, Vacant}<commit_after>#![crate_name = "nickel"]
#![crate_type = "rlib"]
#![feature(slicing_syntax, plugin, core, collections, io, path, hash, std_misc)]
#![plugin(regex_macros)]

//!Nickel is supposed to be a simple and lightweight foundation for web applications written in Rust. Its API is inspired by the popular express framework for JavaScript.
//!
//!Some of the features are:
//!
//!* Easy handlers: A handler is just a function that takes a `Request` and `ResponseWriter`
//!* Variables in routes. Just write `my/route/:someid`
//!* Easy parameter access: `request.params.get(&"someid")`
//!* simple wildcard routes: `/some/*/route`
//!* double wildcard routes: `/a/**/route`
//!* middleware

extern crate time;
extern crate http;
extern crate "rustc-serialize" as serialize;
extern crate regex;
extern crate typemap;
extern crate plugin;
extern crate url;
extern crate mustache;
extern crate groupable;
#[macro_use]
extern crate log;

pub use nickel::Nickel;
pub use request::Request;
pub use response::Response;
pub use middleware::{Action, Continue, Halt, Middleware, ErrorHandler, MiddlewareResult};
pub use static_files_handler::StaticFilesHandler;
pub use favicon_handler::FaviconHandler;
pub use default_error_handler::DefaultErrorHandler;
pub use json_body_parser::JsonBody;
pub use query_string::QueryString;
pub use router::{Router, Route, RouteResult, HttpRouter};
pub use nickel_error::{ NickelError, NickelErrorKind, ErrorWithStatusCode, UserDefinedError, Other };
pub use mimes::get_media_type;
pub use middleware_handler::ResponseFinalizer;

pub mod router;
mod server;
mod nickel;
mod request;
mod response;
mod middleware;
mod middleware_handler;
mod favicon_handler;
mod static_files_handler;
mod json_body_parser;
pub mod mimes;
mod query_string;
mod urlencoded;
mod nickel_error;
mod default_error_handler;
<|endoftext|>


<commit_before>#[allow(unstable)]
extern crate libc;
extern crate "posix-ipc" as ipc;

use std::os;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;
use std::iter;
use std::num::FromPrimitive;

pub type Address = u64;
pub type Word = u64;

#[derive(Copy)]
pub enum Action {
  Allow,
  Kill
}

#[derive(Show, Copy)]
pub enum Request {
  TraceMe = 0,
  PeekText = 1,
  PeekData = 2,
  PeekUser = 3,
  PokeText = 4,
  PokeData = 5,
  PokeUser = 6,
  Continue = 7,
  Kill = 8,
  SingleStep = 9,
  GetRegs = 12,
  SetRegs = 13,
  Attach = 16,
  Detatch = 17,
  SetOptions = 0x4200,
  Seize = 0x4206
}

#[derive(Copy, Show, FromPrimitive)]
pub enum Event {
  Fork = 1,
  VFork = 2,
  Clone = 3,
  Exec = 4,
  VForkDone = 5,
  Exit = 6,
  Seccomp = 7,
  Stop = 128
}

impl Event {
    pub fn from_wait_status(st: i32) -> Option<Event> {
        let e: Option<Event> = FromPrimitive::from_i32(((st >> 8) & !5) >> 8);
        return e;
    }
}

#[derive(Copy, Default, Show)]
pub struct Registers {
  pub r15: Word,
  pub r14: Word,
  pub r13: Word,
  pub r12: Word,
  pub rbp: Word,
  pub rbx: Word,
  pub r11: Word,
  pub r10: Word,
  pub r9: Word,
  pub r8: Word,
  pub rax: Word,
  pub rcx: Word,
  pub rdx: Word,
  pub rsi: Word,
  pub rdi: Word,
  pub orig_rax: Word,
  pub rip: Word,
  pub cs: Word,
  pub eflags: Word,
  pub rsp: Word,
  pub ss: Word,
  pub fs_base: Word,
  pub gs_base: Word,
  pub ds: Word,
  pub es: Word,
  pub fs: Word,
  pub gs: Word
}

bitflags! {
  flags Options: u32 {
    const SysGood = 1,
    const TraceFork = 1 << 1,
    const TraceVFork = 1 << 2,
    const TraceClone = 1 << 3,
    const TraceExec = 1 << 4,
    const TraceVForkDone = 1 << 5,
    const TraceExit = 1 << 6,
    const TraceSeccomp = 1 << 7,
    const ExitKill = 1 << 20
  }
}

pub fn setoptions(pid: libc::pid_t, opts: Options) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::SetOptions, pid, ptr::null_mut(), opts.bits as *mut
    libc::c_void)
  }
}

pub fn getregs(pid: libc::pid_t) -> Registers {
  let mut buf: Registers = Default::default();
  let buf_mut: *mut Registers = &mut buf;

  unsafe {
    raw (Request::GetRegs, pid, ptr::null_mut(), buf_mut as *mut libc::c_void);
  }

  return buf;
}

pub fn setregs(pid: libc::pid_t, regs: &Registers) -> Result<libc::c_long, usize> {
    unsafe {
        let mut buf: *mut libc::c_void = mem::transmute(regs);
        raw (Request::SetRegs, pid, ptr::null_mut(), buf)
    }
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, usize> {
    unsafe {
        raw (Request::Seize, pid, ptr::null_mut(), ptr::null_mut())
    }
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Attach, pid, ptr::null_mut(), ptr::null_mut())
  }
}

pub fn release(pid: libc::pid_t, signal: ipc::signals::Signal) {
  unsafe {
    raw (Request::Detatch, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void);
  }
}

pub fn cont(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Continue, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
  }
}

pub fn traceme() -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::TraceMe, 0, ptr::null_mut(), ptr::null_mut())
  }
}

unsafe fn raw(request: Request,
       pid: libc::pid_t,
       addr: *mut libc::c_void,
       data: *mut libc::c_void) -> Result<libc::c_long, usize> {
  let v = ptrace (request as libc::c_int, pid, addr, data);
  match v {
      -1 => Result::Err(os::errno()),
      _ => Result::Ok(v)
  }
}

extern {
  fn ptrace(request: libc::c_int,
            pid: libc::pid_t,
            addr: *mut libc::c_void,
            data: *mut libc::c_void) -> libc::c_long;
}

#[derive(Copy, Show)]
pub struct Syscall {
  pub args: [Word; 6],
  pub call: u64,
  pub pid: libc::pid_t,
  pub returnVal: Word
}

impl Syscall {
  pub fn from_pid(pid: libc::pid_t) -> Syscall {
    let regs = getregs (pid);
    Syscall {
      pid: pid,
      call: regs.orig_rax,
      args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
      returnVal: 0
    }
  }

  pub fn write(&self) -> Result<libc::c_long, usize> {
      let mut regs = getregs(self.pid);
      regs.rdi = self.args[0];
      regs.rsi = self.args[1];
      regs.rdx = self.args[2];
      regs.rcx = self.args[3];
      regs.r8 = self.args[4];
      regs.r9 = self.args[5];
      regs.orig_rax = self.call;
      regs.rax = self.returnVal;
      setregs(self.pid, &regs)
  }
}

pub struct Reader {
  pub pid: libc::pid_t
}

impl Reader {
  pub fn new(pid: libc::pid_t) -> Reader {
    Reader {
      pid: pid
    }
  }

    pub fn peek_data(&self, address: Address) -> Result<Word, usize> {
        let l;
        unsafe {
            l = raw (Request::PeekData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        }
        match l {
            Result::Err(e) => Result::Err(e),
            _ => Result::Ok(l.unwrap() as Word)
        }
    }

    pub fn read_string(&self, address: Address) -> Vec<u8> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in iter::range_step(address, align_end, mem::size_of::<Word>() as Address) {
            let d = self.peek_data(read_addr).ok().expect("Could not read");
            for word_idx in iter::range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as usize) & 0xff) as u8;
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
                buf.push (chr);
            }
        }
        if !end_of_str {
            let d = self.peek_data(align_end).ok().expect("Could not read");
            for word_idx in range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as usize) & 0xff) as u8;
                if chr == 0 {
                    break;
                }
                buf.push (chr);
            }
        }
        return buf;
    }
}
<commit_msg>Implement a Writer<commit_after>#[allow(unstable)]
extern crate libc;
extern crate "posix-ipc" as ipc;

use std::os;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;
use std::iter;
use std::num::FromPrimitive;

pub type Address = u64;
pub type Word = u64;

#[derive(Copy)]
pub enum Action {
  Allow,
  Kill
}

#[derive(Show, Copy)]
pub enum Request {
  TraceMe = 0,
  PeekText = 1,
  PeekData = 2,
  PeekUser = 3,
  PokeText = 4,
  PokeData = 5,
  PokeUser = 6,
  Continue = 7,
  Kill = 8,
  SingleStep = 9,
  GetRegs = 12,
  SetRegs = 13,
  Attach = 16,
  Detatch = 17,
  SetOptions = 0x4200,
  Seize = 0x4206
}

#[derive(Copy, Show, FromPrimitive)]
pub enum Event {
  Fork = 1,
  VFork = 2,
  Clone = 3,
  Exec = 4,
  VForkDone = 5,
  Exit = 6,
  Seccomp = 7,
  Stop = 128
}

impl Event {
    pub fn from_wait_status(st: i32) -> Option<Event> {
        let e: Option<Event> = FromPrimitive::from_i32(((st >> 8) & !5) >> 8);
        return e;
    }
}

#[derive(Copy, Default, Show)]
pub struct Registers {
  pub r15: Word,
  pub r14: Word,
  pub r13: Word,
  pub r12: Word,
  pub rbp: Word,
  pub rbx: Word,
  pub r11: Word,
  pub r10: Word,
  pub r9: Word,
  pub r8: Word,
  pub rax: Word,
  pub rcx: Word,
  pub rdx: Word,
  pub rsi: Word,
  pub rdi: Word,
  pub orig_rax: Word,
  pub rip: Word,
  pub cs: Word,
  pub eflags: Word,
  pub rsp: Word,
  pub ss: Word,
  pub fs_base: Word,
  pub gs_base: Word,
  pub ds: Word,
  pub es: Word,
  pub fs: Word,
  pub gs: Word
}

bitflags! {
  flags Options: u32 {
    const SysGood = 1,
    const TraceFork = 1 << 1,
    const TraceVFork = 1 << 2,
    const TraceClone = 1 << 3,
    const TraceExec = 1 << 4,
    const TraceVForkDone = 1 << 5,
    const TraceExit = 1 << 6,
    const TraceSeccomp = 1 << 7,
    const ExitKill = 1 << 20
  }
}

pub fn setoptions(pid: libc::pid_t, opts: Options) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::SetOptions, pid, ptr::null_mut(), opts.bits as *mut
    libc::c_void)
  }
}

pub fn getregs(pid: libc::pid_t) -> Registers {
  let mut buf: Registers = Default::default();
  let buf_mut: *mut Registers = &mut buf;

  unsafe {
    raw (Request::GetRegs, pid, ptr::null_mut(), buf_mut as *mut libc::c_void);
  }

  return buf;
}

pub fn setregs(pid: libc::pid_t, regs: &Registers) -> Result<libc::c_long, usize> {
    unsafe {
        let mut buf: *mut libc::c_void = mem::transmute(regs);
        raw (Request::SetRegs, pid, ptr::null_mut(), buf)
    }
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, usize> {
    unsafe {
        raw (Request::Seize, pid, ptr::null_mut(), ptr::null_mut())
    }
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Attach, pid, ptr::null_mut(), ptr::null_mut())
  }
}

pub fn release(pid: libc::pid_t, signal: ipc::signals::Signal) {
  unsafe {
    raw (Request::Detatch, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void);
  }
}

pub fn cont(pid: libc::pid_t, signal: ipc::signals::Signal) -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::Continue, pid, ptr::null_mut(), (signal as u32) as *mut libc::c_void)
  }
}

pub fn traceme() -> Result<libc::c_long, usize> {
  unsafe {
    raw (Request::TraceMe, 0, ptr::null_mut(), ptr::null_mut())
  }
}

unsafe fn raw(request: Request,
       pid: libc::pid_t,
       addr: *mut libc::c_void,
       data: *mut libc::c_void) -> Result<libc::c_long, usize> {
  let v = ptrace (request as libc::c_int, pid, addr, data);
  match v {
      -1 => Result::Err(os::errno()),
      _ => Result::Ok(v)
  }
}

extern {
  fn ptrace(request: libc::c_int,
            pid: libc::pid_t,
            addr: *mut libc::c_void,
            data: *mut libc::c_void) -> libc::c_long;
}

#[derive(Copy, Show)]
pub struct Syscall {
  pub args: [Word; 6],
  pub call: u64,
  pub pid: libc::pid_t,
  pub returnVal: Word
}

impl Syscall {
  pub fn from_pid(pid: libc::pid_t) -> Syscall {
    let regs = getregs (pid);
    Syscall {
      pid: pid,
      call: regs.orig_rax,
      args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
      returnVal: 0
    }
  }

  pub fn write(&self) -> Result<libc::c_long, usize> {
      let mut regs = getregs(self.pid);
      regs.rdi = self.args[0];
      regs.rsi = self.args[1];
      regs.rdx = self.args[2];
      regs.rcx = self.args[3];
      regs.r8 = self.args[4];
      regs.r9 = self.args[5];
      regs.orig_rax = self.call;
      regs.rax = self.returnVal;
      setregs(self.pid, &regs)
  }
}

pub struct Reader {
  pub pid: libc::pid_t
}

pub struct Writer {
    pub pid: libc::pid_t
}

impl Writer {
    pub fn new(pid: libc::pid_t) -> Self {
        Writer {
            pid: pid
        }
    }

    pub fn poke_data(&self, address: Address, data: Word) -> Result<Word, usize> {
        match unsafe {
            raw (Request::PokeData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        } {
            Err(e) => Err(e),
            Ok(r) => Ok(r as Word)
        }
    }

    pub fn write_object<T: Sized>(&self, address: Address, data: &T) -> Result<(), usize> {
        let mut buf = Vec::with_capacity(mem::size_of::<T>());
        unsafe {
            let tptr: *const T = data;
            let p: *const u8 = mem::transmute(tptr);
            for i in range(0, buf.capacity()) {
                buf.push(*p.offset(i as isize));
            }
        }

        Ok(())
    }

    pub fn write_data(&self, address: Address, buf: &Vec<u8>) -> Result<(), usize> {
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        for write_addr in iter::range_step(address as usize, align_end as usize, mem::size_of::<Word>()) {
            let mut d: Word = 0;
            for word_idx in iter::range(0, mem::size_of::<Word>()) {
                d = d << mem::size_of::<u8>();
                d += (buf[write_addr + word_idx] & 0xff) as Word;
            }
            self.poke_data(write_addr as Address, d).ok().expect("Could not poke");
        }
        if max_addr > align_end {
            let mut d: Word = 0;
            for word_idx in iter::range(0, mem::size_of::<Word>()) {
                d = d << mem::size_of::<u8>();
                d += (buf[align_end as usize + word_idx] & 0xff) as Word;
            }
            self.poke_data(align_end, d).ok().expect("Could not poke last byte");
        }
        Ok(())
    }
}

impl Reader {
  pub fn new(pid: libc::pid_t) -> Reader {
    Reader {
      pid: pid
    }
  }

    pub fn peek_data(&self, address: Address) -> Result<Word, usize> {
        let l;
        unsafe {
            l = raw (Request::PeekData, self.pid, address as *mut libc::c_void, ptr::null_mut())
        }
        match l {
            Result::Err(e) => Result::Err(e),
            _ => Result::Ok(l.unwrap() as Word)
        }
    }

    pub fn read_string(&self, address: Address) -> Vec<u8> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in iter::range_step(address, align_end, mem::size_of::<Word>() as Address) {
            let d = self.peek_data(read_addr).ok().expect("Could not read");
            for word_idx in iter::range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as usize) & 0xff) as u8;
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
                buf.push (chr);
            }
        }
        if !end_of_str {
            let d = self.peek_data(align_end).ok().expect("Could not read");
            for word_idx in range(0, mem::size_of::<Word>()) {
                let chr = ((d >> (word_idx*8) as usize) & 0xff) as u8;
                if chr == 0 {
                    break;
                }
                buf.push (chr);
            }
        }
        return buf;
    }
}
<|endoftext|>


<commit_before>//! [Sidekiq](https://github.com/mperham/sidekiq) client allowing to push jobs.
//! Using the [Sidekiq job
//! format](https://github.com/mperham/sidekiq/wiki/Job-Format) as reference.
//!
//! # Default environment variables
//!
//! `REDIS_URL`="redis://127.0.0.1/"
//!
#![doc(html_root_url = "https://docs.rs/sidekiq/0.9.0")]
#![deny(warnings)]
#![crate_name = "sidekiq"]

extern crate r2d2;
extern crate r2d2_redis;
extern crate rand;
extern crate serde;
extern crate serde_json;

mod sidekiq;
pub use crate::sidekiq::{
    create_redis_pool, Client, ClientError, ClientOpts, Job, JobOpts, RedisPool, RedisPooledConnection,
};
pub use serde_json::value::Value;
<commit_msg>Cargo fmt<commit_after>//! [Sidekiq](https://github.com/mperham/sidekiq) client allowing to push jobs.
//! Using the [Sidekiq job
//! format](https://github.com/mperham/sidekiq/wiki/Job-Format) as reference.
//!
//! # Default environment variables
//!
//! `REDIS_URL`="redis://127.0.0.1/"
//!
#![doc(html_root_url = "https://docs.rs/sidekiq/0.9.0")]
#![deny(warnings)]
#![crate_name = "sidekiq"]

extern crate r2d2;
extern crate r2d2_redis;
extern crate rand;
extern crate serde;
extern crate serde_json;

mod sidekiq;
pub use crate::sidekiq::{
    create_redis_pool, Client, ClientError, ClientOpts, Job, JobOpts, RedisPool,
    RedisPooledConnection,
};
pub use serde_json::value::Value;
<|endoftext|>


<commit_before>#[macro_use]
extern crate emit;
#[macro_use]
extern crate hyper;
extern crate chrono;
extern crate serde_json;

use hyper::header::Connection;
use std::io::Read;
use std::error::Error;
use std::fmt::Write;
use emit::LogLevel;
use emit::events::Event;
use std::convert::Into;
use std::borrow::Cow;

pub const DEFAULT_EVENT_BODY_LIMIT_BYTES: usize = 1024 * 256;
pub const DEFAULT_BATCH_LIMIT_BYTES: usize = 1024 * 1024 * 10;
pub const LOCAL_SERVER_URL: &'static str = "http://localhost:5341/";

header! { (XSeqApiKey, "X-Seq-ApiKey") => [String] }

pub struct SeqCollectorBuilder {
    api_key: Option<Cow<'static, str>>,
    event_body_limit_bytes: usize,
    batch_limit_bytes: usize,
    server_url: Cow<'static, str>
}

impl SeqCollectorBuilder {
    pub fn new() -> Self {
        SeqCollectorBuilder {
            api_key: None,
            event_body_limit_bytes: DEFAULT_EVENT_BODY_LIMIT_BYTES,
            batch_limit_bytes: DEFAULT_BATCH_LIMIT_BYTES,
            server_url: LOCAL_SERVER_URL.into()
        }
    }

    pub fn server_url<T: Into<String>>(mut self, server_url: T) -> Self {
        self.server_url = Cow::Owned(server_url.into());
        self
    }

    pub fn api_key<T: Into<String>>(mut self, api_key: T) -> Self {
        self.api_key = Some(Cow::Owned(api_key.into()));
        self
    }

    pub fn event_body_limit_bytes(mut self, event_body_limit_bytes: usize) -> Self {
        self.event_body_limit_bytes = event_body_limit_bytes;
        self
    }

    pub fn batch_limit_bytes(mut self, batch_limit_bytes: usize) -> Self {
        self.batch_limit_bytes = batch_limit_bytes;
        self
    }

    pub fn build(self) -> SeqCollector {
        SeqCollector {
            api_key: self.api_key.map(|k| k.into_owned()),
            event_body_limit_bytes: self.event_body_limit_bytes,
            batch_limit_bytes: self.batch_limit_bytes,
            endpoint: format!("{}api/events/raw/", self.server_url)
        }
    }
}

// 0 is "OFF", but fatal is the best effort for rendering this if we ever get an
// event with that level.
static SEQ_LEVEL_NAMES: [&'static str; 6] = ["Fatal", "Error", "Warning", "Information", "Debug", "Verbose"];

pub struct SeqCollector {
    api_key: Option<String>,
    event_body_limit_bytes: usize,
    batch_limit_bytes: usize,
    endpoint: String
}

impl SeqCollector {
    pub fn new_local() -> SeqCollector {
        Self::builder().build()
    }

    pub fn builder() -> SeqCollectorBuilder {
        SeqCollectorBuilder::new()
    }

    fn send_batch(&self, payload: &String)  -> Result<(), Box<Error>> {
        let client = hyper::Client::new();
        let mut req = client.post(&self.endpoint)
            .body(payload)
            .header(Connection::close());

        if let Some(ref api_key) = self.api_key {
            req = req.header(XSeqApiKey(api_key.clone()));
        }

        let mut res = try!(req.send());

        let mut body = String::new();
        try!(res.read_to_string(&mut body));
        Ok(())
    }
}

const HEADER: &'static str = "{\"Events\":[";
const HEADER_LEN: usize = 11;
const FOOTER: &'static str = "]}";
const FOOTER_LEN: usize = 2;

impl emit::collectors::AcceptEvents for SeqCollector {
    fn accept_events(&self, events: &[Event<'static>]) -> Result<(), Box<Error>> {
        let mut next = HEADER.to_owned();
        let mut count = HEADER_LEN + FOOTER_LEN;
        let mut delim = "";

        for event in events {
            let mut payload = format_payload(event);
            if payload.len() > self.event_body_limit_bytes {
                payload = format_oversize_placeholder(event);
                if payload.len() > self.event_body_limit_bytes {
                    // TODO - self-log
                    // error!("An oversize event was detected but the size limit is so low a placeholder cannot be substituted");
                    continue;
                }
            }

            // Make sure at least one event is included in each batch
            if delim != "" && count + delim.len() + payload.len() > self.batch_limit_bytes {
                write!(next, "{}", FOOTER).is_ok();
                try!(self.send_batch(&next));

                next = format!("{}{}", HEADER, payload);
                count = HEADER_LEN + FOOTER_LEN + payload.len();
                delim = ",";
            } else {
                write!(next, "{}{}", delim, payload).is_ok();
                count += delim.len() + payload.len();
                delim = ",";
            }
        }

        write!(next, "{}", FOOTER).is_ok();
        try!(self.send_batch(&next));

        Ok(())
    }
}

fn format_payload(event: &Event) -> String {
    let mut body = format!("{{\"Timestamp\":\"{}\",\"Level\":\"{}\",\"MessageTemplate\":{},\"Properties\":{{",
        event.timestamp().format("%FT%TZ"),
        to_seq_level(event.level()),
        serde_json::to_string(event.message_template().text()).unwrap());

    let mut first = true;
    for (n,v) in event.properties() {

        if !first {
            body.push_str(",");
        } else {
            first = false;
        }

        write!(&mut body, "\"{}\":{}", n, v.to_json()).is_ok();
    }

    body.push_str("}}");
    body
}

fn format_oversize_placeholder(event: &Event) -> String {
    let initial: String = if event.message_template().text().len() > 64 {
        event.message_template().text().chars().take(64).into_iter().collect()
    } else {
        event.message_template().text().clone()
    };

    format!("{{\"Timestamp\":\"{}\",\"Level\":\"{}\",\"MessageTemplate\":\"(Event too large) {{initial}}...\",\"Properties\":{{\"target\":\"emit::collectors::seq\",\"initial\":{}}}}}",
        event.timestamp().format("%FT%TZ"),
        to_seq_level(event.level()),
        serde_json::to_string(&initial).unwrap())
}

fn to_seq_level(level: LogLevel) -> &'static str {
    SEQ_LEVEL_NAMES[level as usize]
}

#[cfg(test)]
mod tests {
    use std::collections;
    use chrono::UTC;
    use chrono::offset::TimeZone;
    use emit::events::Event;
    use emit::templates;
    use emit::{LogLevel,PipelineBuilder};
    use std::env;
    use super::{format_payload,SeqCollector};

    #[test]
    fn events_are_formatted() {
        let timestamp = UTC.ymd(2014, 7, 8).and_hms(9, 10, 11);
        let mut properties = collections::BTreeMap::new();
        properties.insert("number", "42".into());
        let evt = Event::new(timestamp, LogLevel::Warn, templates::MessageTemplate::new("The number is {number}"), properties);
        let payload = format_payload(&evt);
        assert_eq!(payload, "{\"Timestamp\":\"2014-07-08T09:10:11Z\",\"Level\":\"Warning\",\"MessageTemplate\":\"The number is {number}\",\"Properties\":{\"number\":42}}".to_owned());
    }

    #[test]
    fn pipeline_example() {
        let _flush = PipelineBuilder::new()
            .write_to(SeqCollector::new_local())
            .init();

        info!("Hello, {} at {} in {}!", name: env::var("USERNAME").unwrap_or("User".to_string()), time: 2139, room: "office");
    }
}
<commit_msg>Bring back the simple new(server_url) constructor:<commit_after>#[macro_use]
extern crate emit;
#[macro_use]
extern crate hyper;
extern crate chrono;
extern crate serde_json;

use hyper::header::Connection;
use std::io::Read;
use std::error::Error;
use std::fmt::Write;
use emit::LogLevel;
use emit::events::Event;
use std::convert::Into;
use std::borrow::Cow;

pub const DEFAULT_EVENT_BODY_LIMIT_BYTES: usize = 1024 * 256;
pub const DEFAULT_BATCH_LIMIT_BYTES: usize = 1024 * 1024 * 10;
pub const LOCAL_SERVER_URL: &'static str = "http://localhost:5341/";

header! { (XSeqApiKey, "X-Seq-ApiKey") => [String] }

pub struct SeqCollectorBuilder {
    api_key: Option<Cow<'static, str>>,
    event_body_limit_bytes: usize,
    batch_limit_bytes: usize,
    server_url: Cow<'static, str>
}

impl SeqCollectorBuilder {
    pub fn new() -> Self {
        SeqCollectorBuilder {
            api_key: None,
            event_body_limit_bytes: DEFAULT_EVENT_BODY_LIMIT_BYTES,
            batch_limit_bytes: DEFAULT_BATCH_LIMIT_BYTES,
            server_url: LOCAL_SERVER_URL.into()
        }
    }

    pub fn server_url<T: Into<String>>(mut self, server_url: T) -> Self {
        self.server_url = Cow::Owned(server_url.into());
        self
    }

    pub fn api_key<T: Into<String>>(mut self, api_key: T) -> Self {
        self.api_key = Some(Cow::Owned(api_key.into()));
        self
    }

    pub fn event_body_limit_bytes(mut self, event_body_limit_bytes: usize) -> Self {
        self.event_body_limit_bytes = event_body_limit_bytes;
        self
    }

    pub fn batch_limit_bytes(mut self, batch_limit_bytes: usize) -> Self {
        self.batch_limit_bytes = batch_limit_bytes;
        self
    }

    pub fn build(self) -> SeqCollector {
        SeqCollector {
            api_key: self.api_key.map(|k| k.into_owned()),
            event_body_limit_bytes: self.event_body_limit_bytes,
            batch_limit_bytes: self.batch_limit_bytes,
            endpoint: format!("{}api/events/raw/", self.server_url)
        }
    }
}

// 0 is "OFF", but fatal is the best effort for rendering this if we ever get an
// event with that level.
static SEQ_LEVEL_NAMES: [&'static str; 6] = ["Fatal", "Error", "Warning", "Information", "Debug", "Verbose"];

pub struct SeqCollector {
    api_key: Option<String>,
    event_body_limit_bytes: usize,
    batch_limit_bytes: usize,
    endpoint: String
}

impl SeqCollector {
    pub fn new<T: Into<String>>(server_url: T) -> SeqCollector {
        Self::builder().server_url(server_url).build()
    }

    pub fn new_local() -> SeqCollector {
        Self::builder().build()
    }

    pub fn builder() -> SeqCollectorBuilder {
        SeqCollectorBuilder::new()
    }

    fn send_batch(&self, payload: &String)  -> Result<(), Box<Error>> {
        let client = hyper::Client::new();
        let mut req = client.post(&self.endpoint)
            .body(payload)
            .header(Connection::close());

        if let Some(ref api_key) = self.api_key {
            req = req.header(XSeqApiKey(api_key.clone()));
        }

        let mut res = try!(req.send());

        let mut body = String::new();
        try!(res.read_to_string(&mut body));
        Ok(())
    }
}

const HEADER: &'static str = "{\"Events\":[";
const HEADER_LEN: usize = 11;
const FOOTER: &'static str = "]}";
const FOOTER_LEN: usize = 2;

impl emit::collectors::AcceptEvents for SeqCollector {
    fn accept_events(&self, events: &[Event<'static>]) -> Result<(), Box<Error>> {
        let mut next = HEADER.to_owned();
        let mut count = HEADER_LEN + FOOTER_LEN;
        let mut delim = "";

        for event in events {
            let mut payload = format_payload(event);
            if payload.len() > self.event_body_limit_bytes {
                payload = format_oversize_placeholder(event);
                if payload.len() > self.event_body_limit_bytes {
                    // TODO - self-log
                    // error!("An oversize event was detected but the size limit is so low a placeholder cannot be substituted");
                    continue;
                }
            }

            // Make sure at least one event is included in each batch
            if delim != "" && count + delim.len() + payload.len() > self.batch_limit_bytes {
                write!(next, "{}", FOOTER).is_ok();
                try!(self.send_batch(&next));

                next = format!("{}{}", HEADER, payload);
                count = HEADER_LEN + FOOTER_LEN + payload.len();
                delim = ",";
            } else {
                write!(next, "{}{}", delim, payload).is_ok();
                count += delim.len() + payload.len();
                delim = ",";
            }
        }

        write!(next, "{}", FOOTER).is_ok();
        try!(self.send_batch(&next));

        Ok(())
    }
}

fn format_payload(event: &Event) -> String {
    let mut body = format!("{{\"Timestamp\":\"{}\",\"Level\":\"{}\",\"MessageTemplate\":{},\"Properties\":{{",
        event.timestamp().format("%FT%TZ"),
        to_seq_level(event.level()),
        serde_json::to_string(event.message_template().text()).unwrap());

    let mut first = true;
    for (n,v) in event.properties() {

        if !first {
            body.push_str(",");
        } else {
            first = false;
        }

        write!(&mut body, "\"{}\":{}", n, v.to_json()).is_ok();
    }

    body.push_str("}}");
    body
}

fn format_oversize_placeholder(event: &Event) -> String {
    let initial: String = if event.message_template().text().len() > 64 {
        event.message_template().text().chars().take(64).into_iter().collect()
    } else {
        event.message_template().text().clone()
    };

    format!("{{\"Timestamp\":\"{}\",\"Level\":\"{}\",\"MessageTemplate\":\"(Event too large) {{initial}}...\",\"Properties\":{{\"target\":\"emit::collectors::seq\",\"initial\":{}}}}}",
        event.timestamp().format("%FT%TZ"),
        to_seq_level(event.level()),
        serde_json::to_string(&initial).unwrap())
}

fn to_seq_level(level: LogLevel) -> &'static str {
    SEQ_LEVEL_NAMES[level as usize]
}

#[cfg(test)]
mod tests {
    use std::collections;
    use chrono::UTC;
    use chrono::offset::TimeZone;
    use emit::events::Event;
    use emit::templates;
    use emit::{LogLevel,PipelineBuilder};
    use std::env;
    use super::{format_payload,SeqCollector};

    #[test]
    fn events_are_formatted() {
        let timestamp = UTC.ymd(2014, 7, 8).and_hms(9, 10, 11);
        let mut properties = collections::BTreeMap::new();
        properties.insert("number", "42".into());
        let evt = Event::new(timestamp, LogLevel::Warn, templates::MessageTemplate::new("The number is {number}"), properties);
        let payload = format_payload(&evt);
        assert_eq!(payload, "{\"Timestamp\":\"2014-07-08T09:10:11Z\",\"Level\":\"Warning\",\"MessageTemplate\":\"The number is {number}\",\"Properties\":{\"number\":42}}".to_owned());
    }

    #[test]
    fn pipeline_example() {
        let _flush = PipelineBuilder::new()
            .write_to(SeqCollector::new_local())
            .init();

        info!("Hello, {} at {} in {}!", name: env::var("USERNAME").unwrap_or("User".to_string()), time: 2139, room: "office");
    }
}
<|endoftext|>