<commit_before>//! Calculate the crc64 checksum of the given data, starting with the given crc.
//!
//! Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
//!
//! Specification of this CRC64 variant follows:
//!
//! ```text
//! Name: crc-64-jones
//! Width: 64 bites
//! Poly: 0xad93d23594c935a9
//! Reflected In: True
//! Xor_In: 0xffffffffffffffff
//! Reflected_Out: True
//! Xor_Out: 0x0
//! Check("123456789"): 0xe9c6d914c4b8d9ca
//! ```
//!
//! Example:
//!
//! ```rust
//! let cksum = crc64::crc64(0, "123456789".as_bytes());
//! assert_eq!(16845390139448941002, cksum);
//! ```

use std::io::{self, Write};

use crc_table::CRC64_TAB;

mod crc_table;

fn crc_reflect(data: u64, len: usize) -> u64 {
    let mut data = data;
    let mut ret = data & 0x01;

    let mut i = 1;
    while i < len {
        data >>= 1;
        ret = (ret << 1) | (data & 0x01);
        i += 1;
    }

    ret
}

fn crc64_trivial(crc: u64, in_data: &[u8]) -> u64 {
    let mut crc = crc;
    let len = in_data.len();

    let poly = 0xad93d23594c935a9;

    let mut bit: bool;

    let mut offset = 0;

    while offset < len {
        let c = in_data[offset];
        let mut i = 0x01;
        while i != 0x0 {
            bit = crc & 0x8000000000000000 != 0x0;
            if c & i != 0x0 {
                bit = !bit;
            }
            crc <<= 1;
            if bit {
                crc ^= poly;
            }
            i <<= 1;
        }
        crc &= 0xffffffffffffffff;
        offset += 1;
    }
    crc &= 0xffffffffffffffff;

    crc_reflect(crc, 64)
}

pub fn crc64_init() -> Vec<Vec<u64>> {
    let mut crc;

    let mut table: Vec<Vec<u64>> = Vec::with_capacity(8);

    for _ in 0..8 {
        table.push(Vec::with_capacity(256));
    }

    for n in 0..256 {
        table[0].push(crc64_trivial(0, &[n as u8]));
        table[1].push(0);
        table[2].push(0);
        table[3].push(0);
        table[4].push(0);
        table[5].push(0);
        table[6].push(0);
        table[7].push(0);
    }

    for n in 0..256 {
        crc = table[0][n];
        for k in 1..8 {
            let idx = (crc as usize) & 0xff;
            crc = table[0][idx] ^ (crc >> 8);
            table[k][n] = crc;
        }
    }

    table
}

fn to_u64(data: &[u8]) -> u64 {
    debug_assert!(data.len() == 8);
    let arr: [u8; 8] = data.try_into().expect("incorrect length");
    u64::from_le_bytes(arr)
}

pub fn crc64(crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0usize;

    while len >= 8 {
        crc ^= to_u64(&data[offset..(offset + 8)]);
        crc = CRC64_TAB[7][(crc & 0xff) as usize]
            ^ CRC64_TAB[6][((crc >> 8) & 0xff) as usize]
            ^ CRC64_TAB[5][((crc >> 16) & 0xff) as usize]
            ^ CRC64_TAB[4][((crc >> 24) & 0xff) as usize]
            ^ CRC64_TAB[3][((crc >> 32) & 0xff) as usize]
            ^ CRC64_TAB[2][((crc >> 40) & 0xff) as usize]
            ^ CRC64_TAB[1][((crc >> 48) & 0xff) as usize]
            ^ CRC64_TAB[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = CRC64_TAB[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

pub struct Crc64 {
    crc64: u64,
}

impl Crc64 {
    pub fn new() -> Crc64 {
        Crc64 { crc64: 0 }
    }
    pub fn get(&self) -> u64 {
        self.crc64
    }
}

impl Default for Crc64 {
    fn default() -> Self {
        Self::new()
    }
}

impl Write for Crc64 {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.crc64 = crc64(self.crc64, buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[test]
fn test_crc64_works() {
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(0, "123456789".as_bytes()))
}

#[test]
fn test_crc64_write() {
    let step1 = "12345".as_bytes();
    let step2 = "6789".as_bytes();
    let value1 = 17326901458626182669;
    let value2 = 16845390139448941002;
    assert_eq!(value1, crc64(0, step1));
    assert_eq!(value2, crc64(value1, step2));

    let mut crc = Crc64::new();
    assert_eq!(crc.write(step1).unwrap(), step1.len());
    assert_eq!(value1, crc.get());
    assert_eq!(crc.write(step2).unwrap(), step2.len());
    assert_eq!(value2, crc.get());
}
<commit_msg>Remove unused code.<commit_after>//! Calculate the crc64 checksum of the given data, starting with the given crc.
//!
//! Implements the CRC64 used by Redis, which is the variant with "Jones" coefficients and init value of 0.
//!
//! Specification of this CRC64 variant follows:
//!
//! ```text
//! Name: crc-64-jones
//! Width: 64 bites
//! Poly: 0xad93d23594c935a9
//! Reflected In: True
//! Xor_In: 0xffffffffffffffff
//! Reflected_Out: True
//! Xor_Out: 0x0
//! Check("123456789"): 0xe9c6d914c4b8d9ca
//! ```
//!
//! Example:
//!
//! ```rust
//! let cksum = crc64::crc64(0, "123456789".as_bytes());
//! assert_eq!(16845390139448941002, cksum);
//! ```

use std::io::{self, Write};

use crc_table::CRC64_TAB;

mod crc_table;

fn to_u64(data: &[u8]) -> u64 {
    debug_assert!(data.len() == 8);
    let arr: [u8; 8] = data.try_into().expect("incorrect length");
    u64::from_le_bytes(arr)
}

pub fn crc64(crc: u64, data: &[u8]) -> u64 {
    let mut crc = crc;
    let mut len = data.len();
    let mut offset = 0usize;

    while len >= 8 {
        crc ^= to_u64(&data[offset..(offset + 8)]);
        crc = CRC64_TAB[7][(crc & 0xff) as usize]
            ^ CRC64_TAB[6][((crc >> 8) & 0xff) as usize]
            ^ CRC64_TAB[5][((crc >> 16) & 0xff) as usize]
            ^ CRC64_TAB[4][((crc >> 24) & 0xff) as usize]
            ^ CRC64_TAB[3][((crc >> 32) & 0xff) as usize]
            ^ CRC64_TAB[2][((crc >> 40) & 0xff) as usize]
            ^ CRC64_TAB[1][((crc >> 48) & 0xff) as usize]
            ^ CRC64_TAB[0][(crc >> 56) as usize];

        offset += 8;
        len -= 8;
    }

    while len > 0 {
        crc = CRC64_TAB[0][((crc ^ data[offset] as u64) & 0xff) as usize] ^ (crc >> 8);
        offset += 1;
        len -= 1;
    }

    crc
}

pub struct Crc64 {
    crc64: u64,
}

impl Crc64 {
    pub fn new() -> Crc64 {
        Crc64 { crc64: 0 }
    }
    pub fn get(&self) -> u64 {
        self.crc64
    }
}

impl Default for Crc64 {
    fn default() -> Self {
        Self::new()
    }
}

impl Write for Crc64 {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.crc64 = crc64(self.crc64, buf);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

#[test]
fn test_crc64_works() {
    assert_eq!(0xe9c6d914c4b8d9ca, crc64(0, "123456789".as_bytes()))
}

#[test]
fn test_crc64_write() {
    let step1 = "12345".as_bytes();
    let step2 = "6789".as_bytes();
    let value1 = 17326901458626182669;
    let value2 = 16845390139448941002;
    assert_eq!(value1, crc64(0, step1));
    assert_eq!(value2, crc64(value1, step2));

    let mut crc = Crc64::new();
    assert_eq!(crc.write(step1).unwrap(), step1.len());
    assert_eq!(value1, crc.get());
    assert_eq!(crc.write(step2).unwrap(), step2.len());
    assert_eq!(value2, crc.get());
}
<|endoftext|>


<commit_before>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//!
//! This crate provides generic rate-limiting interfaces and implements a
//! few rate-limiting algorithms. The generic rate-limiting interfaces
//! are extendable to persistence-based rate limiting schemes such as
//! databases.
//!
//! This crate currently provides in-memory implementations of a by-key
//! (limits enforced per key, e.g. an IP address or a customer ID) and a
//! simple (one limit per object) state tracker.
//!
//! ## Interface
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also: The
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! The Generic Cell Rate Algorithm can be used by in an in-memory
//! rate limiter like so:
//!
//! ``` rust
//! use std::num::NonZeroU32;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # fn main () {
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32)); // Allow 50 units per second
//! assert_eq!(Ok(()), lim.check());
//! # }
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Deciders return additional
//! information about why a cell should be denied alongside the
//! decision. This allows callers to e.g. provide better error
//! messages to users.
//!
//! As a consequence, the `ratelimit_meter` crate does not provide any
//! facility to wait until a cell would be allowed - if you require
//! this, you should use the
//! [`NonConformance`](struct.NonConformance.html) returned with
//! negative decisions and have the program wait using the method best
//! suited for this, e.g. an event loop.
//!
//! ## Using this crate effectively
//!
//! Many of the parameters in use by this crate are `NonZeroU32` -
//! since they are not very ergonomic to construct from constants
//! using stdlib means, I recommend using the
//! [nonzero_ext](https://crates.io/crates/nonzero_ext) crate, which
//! comes with a macro `nonzero!()`. This macro makes it far easier to
//! construct rate limiters without cluttering your code.
//!
//! ## Rate-limiting Algorithms
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more concise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! The in-memory implementations in this crate use parking_lot
//! mutexes to ensure rate-limiting operations can happen safely
//! across threads.
//!
//! Example:
//!
//! ```
//! use std::thread;
//! use std::num::NonZeroU32;
//! use std::time::Duration;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # fn main () {
//! // Allow 50 units/second across all threads:
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32));
//! let mut thread_lim = lim.clone();
//! thread::spawn(move || { assert_eq!(Ok(()), thread_lim.check());});
//! assert_eq!(Ok(()), lim.check());
//! # }
//! ```

#![cfg_attr(feature = "cargo-clippy", deny(warnings))]

pub mod algorithms;
mod errors;
pub mod example_algorithms;
pub mod state;
pub mod test_utilities;
mod thread_safety;

extern crate evmap;
#[macro_use]
extern crate nonzero_ext;
extern crate parking_lot;

pub use self::algorithms::LeakyBucket;
pub use self::algorithms::NonConformance;
pub use self::algorithms::GCRA;

pub use self::state::DirectRateLimiter;
pub use self::state::KeyedRateLimiter;

pub use self::errors::*;
<commit_msg>Only no_std with no std library present<commit_after>//! # Leaky Bucket Rate-Limiting (as a meter) in Rust
//!
//! This crate provides generic rate-limiting interfaces and implements a
//! few rate-limiting algorithms. The generic rate-limiting interfaces
//! are extendable to persistence-based rate limiting schemes such as
//! databases.
//!
//! This crate currently provides in-memory implementations of a by-key
//! (limits enforced per key, e.g. an IP address or a customer ID) and a
//! simple (one limit per object) state tracker.
//!
//! ## Interface
//!
//! This crate implements two "serious" rate-limiting/traffic-shaping
//! algorithms:
//! [GCRA](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm)
//! and a [Leaky
//! Bucket](https://en.wikipedia.org/wiki/Leaky_bucket#As_a_meter). An
//! "unserious" implementation is provided also: The
//! [`Allower`](example_algorithms/struct.Allower.html), which returns
//! "Yes" to all rate-limiting queries.
//!
//! The Generic Cell Rate Algorithm can be used by in an in-memory
//! rate limiter like so:
//!
//! ``` rust
//! use std::num::NonZeroU32;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # fn main () {
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32)); // Allow 50 units per second
//! assert_eq!(Ok(()), lim.check());
//! # }
//! ```
//!
//! The rate-limiter interface is intentionally geared towards only
//! providing callers with the information they need to make decisions
//! about what to do with each cell. Deciders return additional
//! information about why a cell should be denied alongside the
//! decision. This allows callers to e.g. provide better error
//! messages to users.
//!
//! As a consequence, the `ratelimit_meter` crate does not provide any
//! facility to wait until a cell would be allowed - if you require
//! this, you should use the
//! [`NonConformance`](struct.NonConformance.html) returned with
//! negative decisions and have the program wait using the method best
//! suited for this, e.g. an event loop.
//!
//! ## Using this crate effectively
//!
//! Many of the parameters in use by this crate are `NonZeroU32` -
//! since they are not very ergonomic to construct from constants
//! using stdlib means, I recommend using the
//! [nonzero_ext](https://crates.io/crates/nonzero_ext) crate, which
//! comes with a macro `nonzero!()`. This macro makes it far easier to
//! construct rate limiters without cluttering your code.
//!
//! ## Rate-limiting Algorithms
//!
//! ### Design and implementation of GCRA
//!
//! The GCRA limits the rate of cells by determining when the "next"
//! cell is expected to arrive; any cells that arrive before that time
//! are classified as non-conforming; the methods for checking cells
//! also return an expected arrival time for these cells, so that
//! callers can choose to wait (adding jitter), or reject the cell.
//!
//! Since using the GCRA results in a much smoother usage pattern, it
//! appears to be very useful for "outgoing" traffic behaviors,
//! e.g. throttling API call rates, or emails sent to a person in a
//! period of time.
//!
//! Unlike token or leaky bucket algorithms, the GCRA assumes that all
//! units of work are of the same "weight", and so allows some
//! optimizations which result in much more concise and fast code (it
//! does not even use multiplication or division in the "hot" path).
//!
//! See [the documentation of the GCRA type](algorithms/gcra/struct.GCRA.html) for
//! more details on its implementation and on trade-offs that apply to
//! it.
//!
//! ### Design and implementation of the leaky bucket
//!
//! In contrast to the GCRA, the leaky bucket algorithm does not place
//! any constraints on the next cell's arrival time: Whenever there is
//! capacity left in the bucket, it can be used. This means that the
//! distribution of "yes" decisions from heavy usage on the leaky
//! bucket rate-limiter will be clustered together. On average, the
//! cell rates of both the GCRA and the leaky bucket will be the same,
//! but in terms of observable behavior, the leaky bucket will appear
//! to allow requests at a more predictable rate.
//!
//! This kind of behavior is usually what people of online APIs expect
//! these days, which makes the leaky bucket a very popular technique
//! for rate-limiting on these kinds of services.
//!
//! The leaky bucket algorithm implemented in this crate is fairly
//! standard: It only updates the bucket fill gauge when a cell is
//! checked, and supports checking "batches" of cells in a single call
//! with no problems.
//!
//! ## Thread-safe operation
//!
//! The in-memory implementations in this crate use parking_lot
//! mutexes to ensure rate-limiting operations can happen safely
//! across threads.
//!
//! Example:
//!
//! ```
//! use std::thread;
//! use std::num::NonZeroU32;
//! use std::time::Duration;
//! use ratelimit_meter::{DirectRateLimiter, GCRA};
//!
//! # #[macro_use] extern crate nonzero_ext;
//! # extern crate ratelimit_meter;
//! # fn main () {
//! // Allow 50 units/second across all threads:
//! let mut lim = DirectRateLimiter::<GCRA>::per_second(nonzero!(50u32));
//! let mut thread_lim = lim.clone();
//! thread::spawn(move || { assert_eq!(Ok(()), thread_lim.check());});
//! assert_eq!(Ok(()), lim.check());
//! # }
//! ```

// Allow using ratelimit_meter without std
#![cfg_attr(not(feature = "std"), no_std)]
// Deny warnings
#![cfg_attr(feature = "cargo-clippy", deny(warnings))]

pub mod algorithms;
mod errors;
pub mod example_algorithms;
pub mod state;
pub mod test_utilities;
mod thread_safety;

extern crate evmap;
#[macro_use]
extern crate nonzero_ext;
extern crate parking_lot;

pub use self::algorithms::LeakyBucket;
pub use self::algorithms::NonConformance;
pub use self::algorithms::GCRA;

pub use self::state::DirectRateLimiter;
pub use self::state::KeyedRateLimiter;

pub use self::errors::*;
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fmt;
use std::io::Read;
use std::path::PathBuf;
use std::time::Duration;

use base64;
use hyper::{self, Url};
use hyper::status::StatusCode;
use hyper::header::{Authorization, Accept, Bearer, UserAgent, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::net::HttpsConnector;
use hyper_openssl::OpensslClient;
use serde_json;

use config;
use error::{HubError, HubResult};

const USER_AGENT: &'static str = "Habitat-Builder";
const HTTP_TIMEOUT: u64 = 3_000;
// These OAuth scopes are required for a user to be authenticated. If this list is updated, then
// the front-end also needs to be updated in `components/builder-web/app/util.ts`. Both the
// front-end app and back-end app should have identical requirements to make things easier for
// our users and less cumbersome for us to message out.
// https://developer.github.com/v3/oauth/#scopes
const AUTH_SCOPES: &'static [&'static str] = &["user:email", "read:org"];

#[derive(Clone)]
pub struct GitHubClient {
    pub url: String,
    pub web_url: String,
    pub client_id: String,
    pub client_secret: String,
}

impl GitHubClient {
    pub fn new<T>(config: &T) -> Self
    where
        T: config::GitHubOAuth,
    {
        GitHubClient {
            url: config.github_url().to_string(),
            web_url: config.github_web_url().to_string(),
            client_id: config.github_client_id().to_string(),
            client_secret: config.github_client_secret().to_string(),
        }
    }

    pub fn authenticate(&self, code: &str) -> HubResult<String> {
        let url = Url::parse(&format!(
            "{}/login/oauth/access_token?\
                                client_id={}&client_secret={}&code={}",
            self.web_url,
            self.client_id,
            self.client_secret,
            code
        )).map_err(HubError::HttpClientParse)?;
        let mut rep = http_post(url)?;
        if rep.status.is_success() {
            let mut encoded = String::new();
            rep.read_to_string(&mut encoded)?;
            match serde_json::from_str::<AuthOk>(&encoded) {
                Ok(msg) => {
                    let missing = msg.missing_auth_scopes();
                    if missing.is_empty() {
                        Ok(msg.access_token)
                    } else {
                        Err(HubError::AuthScope(missing))
                    }
                }
                Err(_) => {
                    let err = serde_json::from_str::<AuthErr>(&encoded)?;
                    Err(HubError::Auth(err))
                }
            }
        } else {
            Err(HubError::HttpResponse(rep.status))
        }
    }

    /// Returns the contents of a file or directory in a repository.
    pub fn contents(
        &self,
        token: &str,
        owner: &str,
        repo: &str,
        path: &str,
    ) -> HubResult<Contents> {
        let url = Url::parse(&format!(
            "{}/repos/{}/{}/contents/{}",
            self.url,
            owner,
            repo,
            path
        )).map_err(HubError::HttpClientParse)?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let mut contents: Contents = serde_json::from_str(&body)?;

        // We need to strip line feeds as the Github API has started to return
        // base64 content with line feeds.
        if contents.encoding == "base64" {
            contents.content = contents.content.replace("\n", "");
        }

        Ok(contents)
    }

    pub fn repo(&self, token: &str, owner: &str, repo: &str) -> HubResult<Repository> {
        let url = Url::parse(&format!("{}/repos/{}/{}", self.url, owner, repo)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }

        let repo = match serde_json::from_str::<Repository>(&body) {
            Ok(r) => r,
            Err(e) => {
                debug!("github repo decode failed: {}. response body: {}", e, body);
                return Err(HubError::from(e));
            }
        };

        Ok(repo)
    }

    pub fn user(&self, token: &str) -> HubResult<User> {
        let url = Url::parse(&format!("{}/user", self.url)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let user: User = serde_json::from_str(&body)?;
        Ok(user)
    }

    pub fn other_user(&self, token: &str, username: &str) -> HubResult<User> {
        let url = Url::parse(&format!("{}/users/{}", self.url, username)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let user: User = serde_json::from_str(&body)?;
        Ok(user)
    }

    pub fn emails(&self, token: &str) -> HubResult<Vec<Email>> {
        let url = Url::parse(&format!("{}/user/emails", self.url)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let emails: Vec<Email> = serde_json::from_str(&body)?;
        Ok(emails)
    }

    pub fn orgs(&self, token: &str) -> HubResult<Vec<Organization>> {
        let url = Url::parse(&format!("{}/user/orgs", self.url)).map_err(
            HubError::HttpClientParse,
        )?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let orgs: Vec<Organization> = serde_json::from_str(&body)?;
        Ok(orgs)
    }

    pub fn search_file(&self, token: &str, repo: &str, file: &str) -> HubResult<Search> {
        let url = Url::parse(&format!(
            "{}/search/code?q={}+in:path+repo:{}",
            self.url,
            file,
            repo
        )).map_err(HubError::HttpClientParse)?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let search = serde_json::from_str::<Search>(&body)?;
        Ok(search)
    }

    pub fn teams(&self, token: &str) -> HubResult<Vec<Team>> {
        let url = Url::parse(&format!("{}/user/teams", self.url)).map_err(
            HubError::HttpClientParse,
        )?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let teams: Vec<Team> = serde_json::from_str(&body)?;
        Ok(teams)
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Contents {
    pub name: String,
    pub path: String,
    pub sha: String,
    pub size: usize,
    pub url: String,
    pub html_url: String,
    pub git_url: String,
    pub download_url: String,
    pub content: String,
    pub encoding: String,
}

impl Contents {
    pub fn decode(&self) -> HubResult<Vec<u8>> {
        base64::decode(&self.content).map_err(HubError::ContentDecode)
    }
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct GitHubOwner {
    /// Public name of commit author
    pub name: String,
    /// Public email of commit author
    pub email: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Repository {
    pub id: u64,
    pub name: String,
    pub full_name: String,
    pub owner: User,
    pub private: bool,
    pub html_url: String,
    pub description: Option<String>,
    pub fork: bool,
    pub url: String,
    pub created_at: u64,
    pub updated_at: String,
    pub pushed_at: u64,
    pub git_url: String,
    pub ssh_url: String,
    pub clone_url: String,
    pub mirror_url: Option<String>,
    default_branch: String,
    master_branch: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Organization {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub url: String,
    pub company: Option<String>,
    pub description: Option<String>,
    pub gravatar_id: Option<String>,
    pub hooks_url: Option<String>,
    pub html_url: Option<String>,
    pub followers_url: Option<String>,
    pub following_url: Option<String>,
    pub gists_url: Option<String>,
    pub starred_url: Option<String>,
    pub subscriptions_url: Option<String>,
    pub organizations_url: Option<String>,
    pub repos_url: Option<String>,
    pub events_url: Option<String>,
    pub received_events_url: Option<String>,
    pub members_url: Option<String>,
    pub site_admin: Option<bool>,
}

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Team {
    pub id: u64,
    pub url: String,
    pub name: String,
    pub slug: String,
    pub description: Option<String>,
    pub privacy: String,
    pub permission: String,
    pub members_url: String,
    pub repositories_url: String,
    pub members_count: u64,
    pub repos_count: u64,
    pub organization: Organization,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    pub site_admin: bool,
    pub name: Option<String>,
    pub company: Option<String>,
    pub blog: Option<String>,
    pub location: Option<String>,
    pub email: Option<String>,
    pub hireable: Option<bool>,
    pub bio: Option<String>,
    pub public_repos: Option<u32>,
    pub public_gists: Option<u32>,
    pub followers: Option<u32>,
    pub following: Option<u32>,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Email {
    pub email: String,
    pub primary: bool,
    pub verified: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuthOk {
    pub access_token: String,
    pub scope: String,
    pub token_type: String,
}

impl AuthOk {
    pub fn missing_auth_scopes(&self) -> Vec<&'static str> {
        let mut scopes = vec![];
        for scope in AUTH_SCOPES.iter() {
            if !self.scope.split(",").collect::<Vec<&str>>().iter().any(
                |p| {
                    p == scope
                },
            )
            {
                scopes.push(*scope);
            }
        }
        scopes
    }
}

#[derive(Deserialize, Serialize, Debug)]
pub struct AuthErr {
    pub error: String,
    pub error_description: String,
    pub error_uri: String,
}

impl fmt::Display for AuthErr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "err={}, desc={}, uri={}",
            self.error,
            self.error_description,
            self.error_uri
        )
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Search {
    total_count: u64,
    incomplete_results: bool,
    items: Vec<SearchItem>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SearchItem {
    name: String,
    path: PathBuf,
    sha: String,
    url: String,
    git_url: String,
    html_url: String,
    repository: Repository,
    score: f64,
}

fn http_get(url: Url, token: &str) -> HubResult<hyper::client::response::Response> {
    hyper_client()
        .get(url)
        .header(Accept(vec![
            qitem(
                Mime(TopLevel::Application, SubLevel::Json, vec![])
            ),
        ]))
        .header(Authorization(Bearer { token: token.to_owned() }))
        .header(UserAgent(USER_AGENT.to_string()))
        .send()
        .map_err(HubError::HttpClient)
}

fn http_post(url: Url) -> HubResult<hyper::client::response::Response> {
    hyper_client()
        .post(url)
        .header(Accept(vec![
            qitem(
                Mime(TopLevel::Application, SubLevel::Json, vec![])
            ),
        ]))
        .header(UserAgent(USER_AGENT.to_string()))
        .send()
        .map_err(HubError::HttpClient)
}

fn hyper_client() -> hyper::Client {
    let ssl = OpensslClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);
    let mut client = hyper::Client::with_connector(connector);
    client.set_read_timeout(Some(Duration::from_millis(HTTP_TIMEOUT)));
    client.set_write_timeout(Some(Duration::from_millis(HTTP_TIMEOUT)));
    client
}
<commit_msg>fix repo deserialization regression<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fmt;
use std::io::Read;
use std::path::PathBuf;
use std::time::Duration;

use base64;
use hyper::{self, Url};
use hyper::status::StatusCode;
use hyper::header::{Authorization, Accept, Bearer, UserAgent, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::net::HttpsConnector;
use hyper_openssl::OpensslClient;
use serde_json;

use config;
use error::{HubError, HubResult};

const USER_AGENT: &'static str = "Habitat-Builder";
const HTTP_TIMEOUT: u64 = 3_000;
// These OAuth scopes are required for a user to be authenticated. If this list is updated, then
// the front-end also needs to be updated in `components/builder-web/app/util.ts`. Both the
// front-end app and back-end app should have identical requirements to make things easier for
// our users and less cumbersome for us to message out.
// https://developer.github.com/v3/oauth/#scopes
const AUTH_SCOPES: &'static [&'static str] = &["user:email", "read:org"];

#[derive(Clone)]
pub struct GitHubClient {
    pub url: String,
    pub web_url: String,
    pub client_id: String,
    pub client_secret: String,
}

impl GitHubClient {
    pub fn new<T>(config: &T) -> Self
    where
        T: config::GitHubOAuth,
    {
        GitHubClient {
            url: config.github_url().to_string(),
            web_url: config.github_web_url().to_string(),
            client_id: config.github_client_id().to_string(),
            client_secret: config.github_client_secret().to_string(),
        }
    }

    pub fn authenticate(&self, code: &str) -> HubResult<String> {
        let url = Url::parse(&format!(
            "{}/login/oauth/access_token?\
                                client_id={}&client_secret={}&code={}",
            self.web_url,
            self.client_id,
            self.client_secret,
            code
        )).map_err(HubError::HttpClientParse)?;
        let mut rep = http_post(url)?;
        if rep.status.is_success() {
            let mut encoded = String::new();
            rep.read_to_string(&mut encoded)?;
            match serde_json::from_str::<AuthOk>(&encoded) {
                Ok(msg) => {
                    let missing = msg.missing_auth_scopes();
                    if missing.is_empty() {
                        Ok(msg.access_token)
                    } else {
                        Err(HubError::AuthScope(missing))
                    }
                }
                Err(_) => {
                    let err = serde_json::from_str::<AuthErr>(&encoded)?;
                    Err(HubError::Auth(err))
                }
            }
        } else {
            Err(HubError::HttpResponse(rep.status))
        }
    }

    /// Returns the contents of a file or directory in a repository.
    pub fn contents(
        &self,
        token: &str,
        owner: &str,
        repo: &str,
        path: &str,
    ) -> HubResult<Contents> {
        let url = Url::parse(&format!(
            "{}/repos/{}/{}/contents/{}",
            self.url,
            owner,
            repo,
            path
        )).map_err(HubError::HttpClientParse)?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let mut contents: Contents = serde_json::from_str(&body)?;

        // We need to strip line feeds as the Github API has started to return
        // base64 content with line feeds.
        if contents.encoding == "base64" {
            contents.content = contents.content.replace("\n", "");
        }

        Ok(contents)
    }

    pub fn repo(&self, token: &str, owner: &str, repo: &str) -> HubResult<Repository> {
        let url = Url::parse(&format!("{}/repos/{}/{}", self.url, owner, repo)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }

        let repo = match serde_json::from_str::<Repository>(&body) {
            Ok(r) => r,
            Err(e) => {
                debug!("github repo decode failed: {}. response body: {}", e, body);
                return Err(HubError::from(e));
            }
        };

        Ok(repo)
    }

    pub fn user(&self, token: &str) -> HubResult<User> {
        let url = Url::parse(&format!("{}/user", self.url)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let user: User = serde_json::from_str(&body)?;
        Ok(user)
    }

    pub fn other_user(&self, token: &str, username: &str) -> HubResult<User> {
        let url = Url::parse(&format!("{}/users/{}", self.url, username)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let user: User = serde_json::from_str(&body)?;
        Ok(user)
    }

    pub fn emails(&self, token: &str) -> HubResult<Vec<Email>> {
        let url = Url::parse(&format!("{}/user/emails", self.url)).unwrap();
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let emails: Vec<Email> = serde_json::from_str(&body)?;
        Ok(emails)
    }

    pub fn orgs(&self, token: &str) -> HubResult<Vec<Organization>> {
        let url = Url::parse(&format!("{}/user/orgs", self.url)).map_err(
            HubError::HttpClientParse,
        )?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let orgs: Vec<Organization> = serde_json::from_str(&body)?;
        Ok(orgs)
    }

    pub fn search_file(&self, token: &str, repo: &str, file: &str) -> HubResult<Search> {
        let url = Url::parse(&format!(
            "{}/search/code?q={}+in:path+repo:{}",
            self.url,
            file,
            repo
        )).map_err(HubError::HttpClientParse)?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let search = serde_json::from_str::<Search>(&body)?;
        Ok(search)
    }

    pub fn teams(&self, token: &str) -> HubResult<Vec<Team>> {
        let url = Url::parse(&format!("{}/user/teams", self.url)).map_err(
            HubError::HttpClientParse,
        )?;
        let mut rep = http_get(url, token)?;
        let mut body = String::new();
        rep.read_to_string(&mut body)?;
        if rep.status != StatusCode::Ok {
            let err: HashMap<String, String> = serde_json::from_str(&body)?;
            return Err(HubError::ApiError(rep.status, err));
        }
        let teams: Vec<Team> = serde_json::from_str(&body)?;
        Ok(teams)
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Contents {
    pub name: String,
    pub path: String,
    pub sha: String,
    pub size: usize,
    pub url: String,
    pub html_url: String,
    pub git_url: String,
    pub download_url: String,
    pub content: String,
    pub encoding: String,
}

impl Contents {
    pub fn decode(&self) -> HubResult<Vec<u8>> {
        base64::decode(&self.content).map_err(HubError::ContentDecode)
    }
}

#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct GitHubOwner {
    /// Public name of commit author
    pub name: String,
    /// Public email of commit author
    pub email: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Repository {
    pub id: u64,
    pub name: String,
    pub full_name: String,
    pub owner: User,
    pub private: bool,
    pub html_url: String,
    pub description: Option<String>,
    pub fork: bool,
    pub url: String,
    pub created_at: String,
    pub updated_at: String,
    pub pushed_at: String,
    pub git_url: String,
    pub ssh_url: String,
    pub clone_url: String,
    pub mirror_url: Option<String>,
    default_branch: String,
    master_branch: String,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Organization {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub url: String,
    pub company: Option<String>,
    pub description: Option<String>,
    pub gravatar_id: Option<String>,
    pub hooks_url: Option<String>,
    pub html_url: Option<String>,
    pub followers_url: Option<String>,
    pub following_url: Option<String>,
    pub gists_url: Option<String>,
    pub starred_url: Option<String>,
    pub subscriptions_url: Option<String>,
    pub organizations_url: Option<String>,
    pub repos_url: Option<String>,
    pub events_url: Option<String>,
    pub received_events_url: Option<String>,
    pub members_url: Option<String>,
    pub site_admin: Option<bool>,
}

#[derive(Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct Team {
    pub id: u64,
    pub url: String,
    pub name: String,
    pub slug: String,
    pub description: Option<String>,
    pub privacy: String,
    pub permission: String,
    pub members_url: String,
    pub repositories_url: String,
    pub members_count: u64,
    pub repos_count: u64,
    pub organization: Organization,
}

#[derive(Clone, Debug, Default, Serialize, Deserialize)]
#[serde(default)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    pub site_admin: bool,
    pub name: Option<String>,
    pub company: Option<String>,
    pub blog: Option<String>,
    pub location: Option<String>,
    pub email: Option<String>,
    pub hireable: Option<bool>,
    pub bio: Option<String>,
    pub public_repos: Option<u32>,
    pub public_gists: Option<u32>,
    pub followers: Option<u32>,
    pub following: Option<u32>,
    pub created_at: Option<String>,
    pub updated_at: Option<String>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Email {
    pub email: String,
    pub primary: bool,
    pub verified: bool,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AuthOk {
    pub access_token: String,
    pub scope: String,
    pub token_type: String,
}

impl AuthOk {
    pub fn missing_auth_scopes(&self) -> Vec<&'static str> {
        let mut scopes = vec![];
        for scope in AUTH_SCOPES.iter() {
            if !self.scope.split(",").collect::<Vec<&str>>().iter().any(
                |p| {
                    p == scope
                },
            )
            {
                scopes.push(*scope);
            }
        }
        scopes
    }
}

#[derive(Deserialize, Serialize, Debug)]
pub struct AuthErr {
    pub error: String,
    pub error_description: String,
    pub error_uri: String,
}

impl fmt::Display for AuthErr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "err={}, desc={}, uri={}",
            self.error,
            self.error_description,
            self.error_uri
        )
    }
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Search {
    total_count: u64,
    incomplete_results: bool,
    items: Vec<SearchItem>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct SearchItem {
    name: String,
    path: PathBuf,
    sha: String,
    url: String,
    git_url: String,
    html_url: String,
    repository: Repository,
    score: f64,
}

fn http_get(url: Url, token: &str) -> HubResult<hyper::client::response::Response> {
    hyper_client()
        .get(url)
        .header(Accept(vec![
            qitem(
                Mime(TopLevel::Application, SubLevel::Json, vec![])
            ),
        ]))
        .header(Authorization(Bearer { token: token.to_owned() }))
        .header(UserAgent(USER_AGENT.to_string()))
        .send()
        .map_err(HubError::HttpClient)
}

fn http_post(url: Url) -> HubResult<hyper::client::response::Response> {
    hyper_client()
        .post(url)
        .header(Accept(vec![
            qitem(
                Mime(TopLevel::Application, SubLevel::Json, vec![])
            ),
        ]))
        .header(UserAgent(USER_AGENT.to_string()))
        .send()
        .map_err(HubError::HttpClient)
}

fn hyper_client() -> hyper::Client {
    let ssl = OpensslClient::new().unwrap();
    let connector = HttpsConnector::new(ssl);
    let mut client = hyper::Client::with_connector(connector);
    client.set_read_timeout(Some(Duration::from_millis(HTTP_TIMEOUT)));
    client.set_write_timeout(Some(Duration::from_millis(HTTP_TIMEOUT)));
    client
}
<|endoftext|>


<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

//! `sysinfo` is a crate used to get a system's information.
//!
//! ## Supported Oses
//!
//! It currently supports the following OSes (alphabetically sorted):
//!  * Android
//!  * iOS
//!  * Linux
//!  * macOS
//!  * Windows
//!
//! You can still use `sysinfo` on non-supported OSes, it'll simply do nothing and always return
//! empty values. You can check in your program directly if an OS is supported by checking the
//! [`SystemExt::IS_SUPPORTED`] constant.
//!
//! ## Usage
//!
//! /!\ Before any attempt to read the different structs' information, you need to update them to
//! get up-to-date information because for most of them, it works on diff between the current value
//! and the old one.
//!
//! Which is why, it's much better to keep the same instance of [`System`] around instead of
//! recreating it multiple times.
//!
//! ## Examples
//!
//! ```
//! use sysinfo::{ProcessExt, SystemExt};
//!
//! let mut system = sysinfo::System::new_all();
//!
//! // First we update all information of our system struct.
//! system.refresh_all();
//!
//! // Now let's print every process' id and name:
//! for (pid, proc_) in system.get_processes() {
//!     println!("{}:{} => status: {:?}", pid, proc_.name(), proc_.status());
//! }
//!
//! // Then let's print the temperature of the different components:
//! for component in system.get_components() {
//!     println!("{:?}", component);
//! }
//!
//! // And then all disks' information:
//! for disk in system.get_disks() {
//!     println!("{:?}", disk);
//! }
//!
//! // And finally the RAM and SWAP information:
//! println!("total memory: {} KB", system.get_total_memory());
//! println!("used memory : {} KB", system.get_used_memory());
//! println!("total swap  : {} KB", system.get_total_swap());
//! println!("used swap   : {} KB", system.get_used_swap());
//!
//! // Display system information:
//! println!("System name:             {:?}", system.get_name());
//! println!("System kernel version:   {:?}", system.get_kernel_version());
//! println!("System OS version:       {:?}", system.get_os_version());
//! println!("System host name:        {:?}", system.get_host_name());
//! ```

#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(renamed_and_removed_lints)]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[cfg(feature = "debug")]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    }
}

pub use common::{
    AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;
pub use utils::get_current_pid;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        if _new_limit < 0 {
            _new_limit = 0;
        }
        let max = sys::system::get_max_nb_fds();
        if _new_limit > max {
            _new_limit = max;
        }
        if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
            // If files are already open, to be sure that the number won't be bigger when those
            // files are closed, we subtract the current number of opened files to the new limit.
            let diff = max - **x;
            **x = _new_limit - diff;
            true
        } else {
            false
        }
    }
    #[cfg(all(not(target_os = "linux"), not(target_os = "android")))]
    {
        false
    }
}

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

    #[test]
    fn check_memory_usage() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let mut s = System::new();
            s.refresh_all();
            assert_eq!(
                s.get_processes()
                    .iter()
                    .all(|(_, proc_)| proc_.memory() == 0),
                false
            );
        }
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_cpu_usage() {
        let mut s = System::new();

        s.refresh_all();
        // All CPU usage will start at zero until the second refresh
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() == 0.0),
            true
        );

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                    && proc_.cpu_usage() <= (s.get_processors().len() as f32) * 100.0),
            true
        );
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        assert!(s.get_users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_all();
        assert!(s.get_users().is_empty());

        let s = System::new_all();
        assert!(s.get_users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        let users = s.get_users();
        assert!(users.len() >= MIN_USERS);

        for user in users {
            match user.get_name() {
                "root" => {
                    assert_eq!(*user.get_uid(), 0);
                    assert_eq!(*user.get_gid(), 0);
                }
                _ => {
                    assert!(*user.get_uid() > 0);
                    #[cfg(not(target_os = "windows"))]
                    assert!(*user.get_gid() > 0);
                }
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(!s.get_name().expect("Failed to get system name").is_empty());

            assert!(!s
                .get_kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s
                .get_os_version()
                .expect("Failed to get os version")
                .is_empty());

            assert!(!s
                .get_long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(!s
                .get_host_name()
                .expect("Failed to get host name")
                .is_empty());
        }
    }

    #[test]
    fn check_refresh_process_return_value() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let pid = get_current_pid().expect("Failed to get current PID");
            let mut s = System::new();

            // First check what happens in case the process isn't already in our process list.
            assert!(s.refresh_process(pid));
            // Then check that it still returns true if the process is already in our process list.
            assert!(s.refresh_process(pid));
        }
    }

    #[test]
    fn ensure_is_supported_is_set_correctly() {
        if MIN_USERS > 0 {
            assert!(System::IS_SUPPORTED);
        } else {
            assert!(!System::IS_SUPPORTED);
        }
    }
}

// Used to check that System is Send and Sync.
#[cfg(doctest)]
doc_comment::doc_comment!(
    "
```
fn is_send<T: Send>() {}
is_send::<sysinfo::System>();
```

```
fn is_sync<T: Sync>() {}
is_sync::<sysinfo::System>();
```"
);
<commit_msg>Check that there is always at least one processor listed<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

//! `sysinfo` is a crate used to get a system's information.
//!
//! ## Supported Oses
//!
//! It currently supports the following OSes (alphabetically sorted):
//!  * Android
//!  * iOS
//!  * Linux
//!  * macOS
//!  * Windows
//!
//! You can still use `sysinfo` on non-supported OSes, it'll simply do nothing and always return
//! empty values. You can check in your program directly if an OS is supported by checking the
//! [`SystemExt::IS_SUPPORTED`] constant.
//!
//! ## Usage
//!
//! /!\ Before any attempt to read the different structs' information, you need to update them to
//! get up-to-date information because for most of them, it works on diff between the current value
//! and the old one.
//!
//! Which is why, it's much better to keep the same instance of [`System`] around instead of
//! recreating it multiple times.
//!
//! ## Examples
//!
//! ```
//! use sysinfo::{ProcessExt, SystemExt};
//!
//! let mut system = sysinfo::System::new_all();
//!
//! // First we update all information of our system struct.
//! system.refresh_all();
//!
//! // Now let's print every process' id and name:
//! for (pid, proc_) in system.get_processes() {
//!     println!("{}:{} => status: {:?}", pid, proc_.name(), proc_.status());
//! }
//!
//! // Then let's print the temperature of the different components:
//! for component in system.get_components() {
//!     println!("{:?}", component);
//! }
//!
//! // And then all disks' information:
//! for disk in system.get_disks() {
//!     println!("{:?}", disk);
//! }
//!
//! // And finally the RAM and SWAP information:
//! println!("total memory: {} KB", system.get_total_memory());
//! println!("used memory : {} KB", system.get_used_memory());
//! println!("total swap  : {} KB", system.get_total_swap());
//! println!("used swap   : {} KB", system.get_used_swap());
//!
//! // Display system information:
//! println!("System name:             {:?}", system.get_name());
//! println!("System kernel version:   {:?}", system.get_kernel_version());
//! println!("System OS version:       {:?}", system.get_os_version());
//! println!("System host name:        {:?}", system.get_host_name());
//! ```

#![crate_name = "sysinfo"]
#![crate_type = "lib"]
#![crate_type = "rlib"]
#![allow(unknown_lints)]
#![deny(missing_docs)]
#![deny(broken_intra_doc_links)]
#![allow(clippy::upper_case_acronyms)]
#![allow(renamed_and_removed_lints)]

#[cfg(doctest)]
doc_comment::doctest!("../README.md");

#[cfg(feature = "debug")]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{
        eprintln!($($x)*);
    }}
}

#[cfg(not(feature = "debug"))]
#[doc(hidden)]
#[allow(unused)]
macro_rules! sysinfo_debug {
    ($($x:tt)*) => {{}};
}

cfg_if::cfg_if! {
    if #[cfg(any(target_os = "macos", target_os = "ios"))] {
        mod apple;
        use apple as sys;
        extern crate core_foundation_sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(windows)] {
        mod windows;
        use windows as sys;
        extern crate winapi;
        extern crate ntapi;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
        mod linux;
        use linux as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 1;
    } else {
        mod unknown;
        use unknown as sys;

        #[cfg(test)]
        pub(crate) const MIN_USERS: usize = 0;
    }
}

pub use common::{
    AsU32, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, RefreshKind, Signal, Uid, User,
};
pub use sys::{Component, Disk, NetworkData, Networks, Process, ProcessStatus, Processor, System};
pub use traits::{
    ComponentExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, ProcessorExt, SystemExt, UserExt,
};

#[cfg(feature = "c-interface")]
pub use c_interface::*;
pub use utils::get_current_pid;

#[cfg(feature = "c-interface")]
mod c_interface;
mod common;
mod debug;
mod system;
mod traits;
mod utils;

/// This function is only used on linux targets, on the other platforms it does nothing and returns
/// `false`.
///
/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
/// a maximum number of files open equivalent to half of the system limit.
///
/// The problem is that some users might need all the available file descriptors so we need to
/// allow them to change this limit.
///
/// Note that if you set a limit bigger than the system limit, the system limit will be set.
///
/// Returns `true` if the new value has been set.
///
/// ```no_run
/// use sysinfo::{System, SystemExt, set_open_files_limit};
///
/// // We call the function before any call to the processes update.
/// if !set_open_files_limit(10) {
///     // It'll always return false on non-linux targets.
///     eprintln!("failed to update the open files limit...");
/// }
/// let s = System::new_all();
/// ```
pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
    #[cfg(any(target_os = "linux", target_os = "android"))]
    {
        if _new_limit < 0 {
            _new_limit = 0;
        }
        let max = sys::system::get_max_nb_fds();
        if _new_limit > max {
            _new_limit = max;
        }
        if let Ok(ref mut x) = unsafe { sys::system::REMAINING_FILES.lock() } {
            // If files are already open, to be sure that the number won't be bigger when those
            // files are closed, we subtract the current number of opened files to the new limit.
            let diff = max - **x;
            **x = _new_limit - diff;
            true
        } else {
            false
        }
    }
    #[cfg(all(not(target_os = "linux"), not(target_os = "android")))]
    {
        false
    }
}

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

    #[test]
    fn check_memory_usage() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let mut s = System::new();
            s.refresh_all();
            assert_eq!(
                s.get_processes()
                    .iter()
                    .all(|(_, proc_)| proc_.memory() == 0),
                false
            );
        }
    }

    #[cfg(target_os = "linux")]
    #[test]
    fn check_cpu_usage() {
        let mut s = System::new();

        s.refresh_all();
        // All CPU usage will start at zero until the second refresh
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() == 0.0),
            true
        );

        // Wait a bit to update CPU usage values
        std::thread::sleep(std::time::Duration::from_millis(100));
        s.refresh_all();
        assert_eq!(
            s.get_processes()
                .iter()
                .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
                    && proc_.cpu_usage() <= (s.get_processors().len() as f32) * 100.0),
            true
        );
    }

    #[test]
    fn check_users() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        assert!(s.get_users().len() >= MIN_USERS);

        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_all();
        assert!(s.get_users().is_empty());

        let s = System::new_all();
        assert!(s.get_users().len() >= MIN_USERS);
    }

    #[test]
    fn check_uid_gid() {
        let mut s = System::new();
        assert!(s.get_users().is_empty());
        s.refresh_users_list();
        let users = s.get_users();
        assert!(users.len() >= MIN_USERS);

        for user in users {
            match user.get_name() {
                "root" => {
                    assert_eq!(*user.get_uid(), 0);
                    assert_eq!(*user.get_gid(), 0);
                }
                _ => {
                    assert!(*user.get_uid() > 0);
                    #[cfg(not(target_os = "windows"))]
                    assert!(*user.get_gid() > 0);
                }
            }
        }
    }

    #[test]
    fn check_system_info() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(!s.get_name().expect("Failed to get system name").is_empty());

            assert!(!s
                .get_kernel_version()
                .expect("Failed to get kernel version")
                .is_empty());

            assert!(!s
                .get_os_version()
                .expect("Failed to get os version")
                .is_empty());

            assert!(!s
                .get_long_os_version()
                .expect("Failed to get long OS version")
                .is_empty());
        }
    }

    #[test]
    fn check_host_name() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let s = System::new();
            assert!(!s
                .get_host_name()
                .expect("Failed to get host name")
                .is_empty());
        }
    }

    #[test]
    fn check_refresh_process_return_value() {
        // We don't want to test on unsupported systems.
        if System::IS_SUPPORTED {
            let pid = get_current_pid().expect("Failed to get current PID");
            let mut s = System::new();

            // First check what happens in case the process isn't already in our process list.
            assert!(s.refresh_process(pid));
            // Then check that it still returns true if the process is already in our process list.
            assert!(s.refresh_process(pid));
        }
    }

    #[test]
    fn ensure_is_supported_is_set_correctly() {
        if MIN_USERS > 0 {
            assert!(System::IS_SUPPORTED);
        } else {
            assert!(!System::IS_SUPPORTED);
        }
    }

    #[test]
    fn check_processors_number() {
        let s = System::new();

        if System::IS_SUPPORTED {
            assert!(!s.get_processors().is_empty());
        } else {
            assert!(s.get_processors().is_empty());
        }
    }
}

// Used to check that System is Send and Sync.
#[cfg(doctest)]
doc_comment::doc_comment!(
    "
```
fn is_send<T: Send>() {}
is_send::<sysinfo::System>();
```

```
fn is_sync<T: Sync>() {}
is_sync::<sysinfo::System>();
```"
);
<|endoftext|>


<commit_before>extern crate serial;
#[macro_use] extern crate serde_derive;

pub use serial::Error;

mod enttec;

pub use enttec::{available_enttec_ports, EnttecDmxPort, ENTTEC_NAMESPACE};

/// Trait for the general notion of a DMX port.
/// This enables creation of an "offline" port to slot into place if an API requires an output.
pub trait DmxPort {
    /// Write a DMX frame out to the port.  If the frame is smaller than the minimum universe size,
    /// it will be padded with zeros.  If the frame is larger than the maximum universe size, the
    /// values beyond the max size will be ignored.
    fn write(&mut self, frame: &[u8]) -> Result<(), Error>;

    /// Return the name of this port.  Should only be used for display purposes.
    fn port_name(&self) -> &str;

    /// Return a tuple of (namespace, port_identifier) to be used to try to reopen a port
    /// after deserialization of a saved show or after application restart.
    fn serializable(&self) -> SerializablePort;
}

pub struct OfflineDmxPort {}

const OFFLINE_NAMESPACE: &'static str = "offline";
const OFFLINE_ID: &'static str = "offline";

impl DmxPort for OfflineDmxPort {
    fn write(&mut self, _: &[u8]) -> Result<(), Error> {
        Ok(())
    }
    fn port_name(&self) -> &str {
        OFFLINE_ID
    }
    fn serializable(&self) -> SerializablePort {
        SerializablePort::new(OFFLINE_NAMESPACE, OFFLINE_ID)
    }
}

#[derive(Serialize, Deserialize)]
/// A serializable data structure for persisting a record of a port to disk, also providing
/// for attempted reopening of a port.
pub struct SerializablePort {
    namespace: String,
    id: String,
}

impl SerializablePort {
    fn new<N: Into<String>, I: Into<String>>(namespace: N, id: I) -> Self {
        SerializablePort { namespace: namespace.into(), id: id.into() }
    }
    /// Based on the namespace and id, try to reopen this DMX port.
    /// If we don't know the namespace or the port isn't available, return an offline port.
    fn reopen(self) -> Box<DmxPort> {
        fn offline() -> Box<DmxPort> {
            Box::new(OfflineDmxPort{})
        }
        match self.namespace.as_ref() {
            OFFLINE_NAMESPACE => offline(),
            ENTTEC_NAMESPACE =>
                match EnttecDmxPort::new(self.id) {
                    Ok(port) => Box::new(port),
                    Err(_) => offline()
                },
            _ => offline()
        }
    }
}<commit_msg>ENH: add port serialization support through the trait object<commit_after>extern crate serial;
#[macro_use] extern crate serde_derive;
extern crate serde;

use serde::ser::{Serializer, Serialize};
use serde::de::{self, Deserializer, Deserialize};

pub use serial::Error;

mod enttec;

pub use enttec::{available_enttec_ports, EnttecDmxPort, ENTTEC_NAMESPACE};

/// Trait for the general notion of a DMX port.
/// This enables creation of an "offline" port to slot into place if an API requires an output.
pub trait DmxPort {
    /// Write a DMX frame out to the port.  If the frame is smaller than the minimum universe size,
    /// it will be padded with zeros.  If the frame is larger than the maximum universe size, the
    /// values beyond the max size will be ignored.
    fn write(&mut self, frame: &[u8]) -> Result<(), Error>;

    /// Return the name of this port.  Should only be used for display purposes.
    fn port_name(&self) -> &str;

    /// Return a tuple of (namespace, port_identifier) to be used to try to reopen a port
    /// after deserialization of a saved show or after application restart.
    fn serializable(&self) -> SerializablePort;
}

pub struct OfflineDmxPort {}

const OFFLINE_NAMESPACE: &'static str = "offline";
const OFFLINE_ID: &'static str = "offline";

impl DmxPort for OfflineDmxPort {
    fn write(&mut self, _: &[u8]) -> Result<(), Error> {
        Ok(())
    }
    fn port_name(&self) -> &str {
        OFFLINE_ID
    }
    fn serializable(&self) -> SerializablePort {
        SerializablePort::new(OFFLINE_NAMESPACE, OFFLINE_ID)
    }
}

#[derive(Serialize, Deserialize)]
/// A serializable data structure for persisting a record of a port to disk, also providing
/// for attempted reopening of a port.
pub struct SerializablePort {
    namespace: String,
    id: String,
}

impl SerializablePort {
    fn new<N: Into<String>, I: Into<String>>(namespace: N, id: I) -> Self {
        SerializablePort { namespace: namespace.into(), id: id.into() }
    }
    /// Based on the namespace and id, try to reopen this DMX port.
    /// If we don't know the namespace or the port isn't available, return an offline port.
    fn reopen(self) -> Box<DmxPort> {
        fn offline() -> Box<DmxPort> {
            Box::new(OfflineDmxPort{})
        }
        match self.namespace.as_ref() {
            OFFLINE_NAMESPACE => offline(),
            ENTTEC_NAMESPACE =>
                match EnttecDmxPort::new(self.id) {
                    Ok(port) => Box::new(port),
                    Err(_) => offline()
                },
            _ => offline()
        }
    }
}

// Helper functions to use when serializing and deserializing DmxPort trait objects contained in
// other structs, using Serde attributes.
fn serialize<S>(port: &DmxPort, serializer: S) -> Result<S::Ok, S::Error>
    where S: Serializer
{
    port.serializable().serialize(serializer)
}

fn deserialize<'de, D>(deserializer: D) -> Result<Box<DmxPort>, D::Error>
    where D: Deserializer<'de>
{
    SerializablePort::deserialize(deserializer).map(SerializablePort::reopen)
}<|endoftext|>


<commit_before>#![crate_id = "bodyparser"]
#![license = "MIT"]

extern crate iron;
extern crate serialize;

//use iron::{Iron, Ingot, Furnace, Alloy, Request, Response, ServerT};
use iron::{Ingot, Alloy, Request, Response};
use iron::ingot::{Status, Continue, Unwind};

use serialize::json;
//use serialize::json::{List, Object};

#[deriving(Clone)]
struct Parsed(json::Json);

#[deriving(Clone)]
pub struct BodyParser;

impl BodyParser {
    fn new() -> BodyParser {
        BodyParser
    }
}

impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for BodyParser {
    fn enter(&mut self, _rq: &mut Rq, _rs: &mut Rs, alloy: &mut Alloy) -> Status {
        alloy.insert::<Parsed>(Parsed(parse_body(_rq.body())));
        Continue
    }
}

fn parse_body(x:&str) -> json::Json {
    let json_object = json::from_str(x.as_slice());
    json_object.clone().unwrap()
}<commit_msg>(refactor) Imported JSON data type directly<commit_after>#![crate_id = "bodyparser"]
#![license = "MIT"]

extern crate iron;
extern crate serialize;

use iron::{Ingot, Alloy, Request, Response};
use iron::ingot::{Status, Continue};

use serialize::json;
use serialize::json::Json;

#[deriving(Clone)]
struct Parsed(Json);

#[deriving(Clone)]
pub struct BodyParser;

impl BodyParser {
    fn new() -> BodyParser {
        BodyParser
    }
}

impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for BodyParser {
    fn enter(&mut self, _rq: &mut Rq, _rs: &mut Rs, alloy: &mut Alloy) -> Status {
        alloy.insert::<Parsed>(Parsed(parse_body(_rq.body())));
        Continue
    }
}

fn parse_body(x:&str) -> Json {
    let json_object = json::from_str(x.as_slice());
    json_object.clone().unwrap()
}<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::attr::Attr;
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast, HTMLElementCast, NodeCast, TextDerived};
use dom::bindings::codegen::InheritTypes::{HTMLOptionElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::{AttributeMutation, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeTypeId};
use dom::virtualmethods::VirtualMethods;
use std::cell::Cell;
use util::str::{DOMString, split_html_space_chars};

#[dom_struct]
pub struct HTMLOptionElement {
    htmlelement: HTMLElement,

    /// https://html.spec.whatwg.org/multipage/#attr-option-selected
    selectedness: Cell<bool>,

    /// https://html.spec.whatwg.org/multipage/#concept-option-dirtiness
    dirtiness: Cell<bool>,
}

impl HTMLOptionElementDerived for EventTarget {
    fn is_htmloptionelement(&self) -> bool {
        *self.type_id() ==
            EventTargetTypeId::Node(
                NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)))
    }
}

impl HTMLOptionElement {
    fn new_inherited(localName: DOMString,
                     prefix: Option<DOMString>,
                     document: &Document) -> HTMLOptionElement {
        HTMLOptionElement {
            htmlelement:
                HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptionElement, localName, prefix, document),
            selectedness: Cell::new(false),
            dirtiness: Cell::new(false),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString,
               prefix: Option<DOMString>,
               document: &Document) -> Root<HTMLOptionElement> {
        let element = HTMLOptionElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLOptionElementBinding::Wrap)
    }
}

fn collect_text(node: &&Node, value: &mut DOMString) {
    let elem = ElementCast::to_ref(*node).unwrap();
    let svg_script = *elem.namespace() == ns!(SVG) && elem.local_name() == &atom!("script");
    let html_script = node.is_htmlscriptelement();
    if svg_script || html_script {
        return;
    } else {
        for child in node.children() {
            if child.r().is_text() {
                let characterdata = CharacterDataCast::to_ref(child.r()).unwrap();
                value.push_str(&characterdata.Data());
            } else {
                collect_text(&child.r(), value);
            }
        }
    }
}

impl HTMLOptionElementMethods for HTMLOptionElement {
    // https://www.whatwg.org/html/#dom-option-disabled
    make_bool_getter!(Disabled);

    // https://www.whatwg.org/html/#dom-option-disabled
    fn SetDisabled(&self, disabled: bool) {
        let elem = ElementCast::from_ref(self);
        elem.set_bool_attribute(&atom!("disabled"), disabled)
    }

    // https://www.whatwg.org/html/#dom-option-text
    fn Text(&self) -> DOMString {
        let node = NodeCast::from_ref(self);
        let mut content = String::new();
        collect_text(&node, &mut content);
        let v: Vec<&str> = split_html_space_chars(&content).collect();
        v.join(" ")
    }

    // https://www.whatwg.org/html/#dom-option-text
    fn SetText(&self, value: DOMString) {
        let node = NodeCast::from_ref(self);
        node.SetTextContent(Some(value))
    }

    // https://html.spec.whatwg.org/multipage/#attr-option-value
    fn Value(&self) -> DOMString {
        let element = ElementCast::from_ref(self);
        let attr = &atom!("value");
        if element.has_attribute(attr) {
            element.get_string_attribute(attr)
        } else {
            self.Text()
        }
    }

    // https://html.spec.whatwg.org/multipage/#attr-option-value
    make_setter!(SetValue, "value");

    // https://html.spec.whatwg.org/multipage/#attr-option-label
    fn Label(&self) -> DOMString {
        let element = ElementCast::from_ref(self);
        let attr = &atom!("label");
        if element.has_attribute(attr) {
            element.get_string_attribute(attr)
        } else {
            self.Text()
        }
    }

    // https://html.spec.whatwg.org/multipage/#attr-option-label
    make_setter!(SetLabel, "label");

    // https://html.spec.whatwg.org/multipage/#dom-option-defaultselected
    make_bool_getter!(DefaultSelected, "selected");

    // https://html.spec.whatwg.org/multipage/#dom-option-defaultselected
    make_bool_setter!(SetDefaultSelected, "selected");

    // https://html.spec.whatwg.org/multipage/#dom-option-selected
    fn Selected(&self) -> bool {
        self.selectedness.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-option-selected
    fn SetSelected(&self, selected: bool) {
        self.dirtiness.set(true);
        self.selectedness.set(selected);
        // FIXME: as per the spec, implement 'ask for a reset'
    }
}

impl VirtualMethods for HTMLOptionElement {
    fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
        let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        match attr.local_name() {
            &atom!(disabled) => {
                let node = NodeCast::from_ref(self);
                match mutation {
                    AttributeMutation::Set(_) => {
                        node.set_disabled_state(true);
                        node.set_enabled_state(false);
                    },
                    AttributeMutation::Removed => {
                        node.set_disabled_state(false);
                        node.set_enabled_state(true);
                        node.check_parent_disabled_state_for_option();
                    }
                }
            },
            &atom!(selected) => {
                match mutation {
                    AttributeMutation::Set(_) => {
                        // https://html.spec.whatwg.org/multipage/#concept-option-selectedness
                        if !self.dirtiness.get() {
                            self.selectedness.set(true);
                        }
                    },
                    AttributeMutation::Removed => {
                        // https://html.spec.whatwg.org/multipage/#concept-option-selectedness
                        if !self.dirtiness.get() {
                            self.selectedness.set(false);
                        }
                    },
                }
            },
            _ => {},
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        if let Some(ref s) = self.super_type() {
            s.bind_to_tree(tree_in_doc);
        }

        let node = NodeCast::from_ref(self);
        node.check_parent_disabled_state_for_option();
    }

    fn unbind_from_tree(&self, tree_in_doc: bool) {
        if let Some(ref s) = self.super_type() {
            s.unbind_from_tree(tree_in_doc);
        }

        let node = NodeCast::from_ref(self);
        if node.GetParentNode().is_some() {
            node.check_parent_disabled_state_for_option();
        } else {
            node.check_disabled_attribute();
        }
    }
}
<commit_msg>Auto merge of #7775 - frewsxcv:tracking-issue, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::attr::Attr;
use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding;
use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods;
use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use dom::bindings::codegen::InheritTypes::{CharacterDataCast, ElementCast, HTMLElementCast, NodeCast, TextDerived};
use dom::bindings::codegen::InheritTypes::{HTMLOptionElementDerived};
use dom::bindings::codegen::InheritTypes::{HTMLScriptElementDerived};
use dom::bindings::js::Root;
use dom::document::Document;
use dom::element::{AttributeMutation, ElementTypeId};
use dom::eventtarget::{EventTarget, EventTargetTypeId};
use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeTypeId};
use dom::virtualmethods::VirtualMethods;
use std::cell::Cell;
use util::str::{DOMString, split_html_space_chars};

#[dom_struct]
pub struct HTMLOptionElement {
    htmlelement: HTMLElement,

    /// https://html.spec.whatwg.org/multipage/#attr-option-selected
    selectedness: Cell<bool>,

    /// https://html.spec.whatwg.org/multipage/#concept-option-dirtiness
    dirtiness: Cell<bool>,
}

impl HTMLOptionElementDerived for EventTarget {
    fn is_htmloptionelement(&self) -> bool {
        *self.type_id() ==
            EventTargetTypeId::Node(
                NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)))
    }
}

impl HTMLOptionElement {
    fn new_inherited(localName: DOMString,
                     prefix: Option<DOMString>,
                     document: &Document) -> HTMLOptionElement {
        HTMLOptionElement {
            htmlelement:
                HTMLElement::new_inherited(HTMLElementTypeId::HTMLOptionElement, localName, prefix, document),
            selectedness: Cell::new(false),
            dirtiness: Cell::new(false),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString,
               prefix: Option<DOMString>,
               document: &Document) -> Root<HTMLOptionElement> {
        let element = HTMLOptionElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLOptionElementBinding::Wrap)
    }
}

fn collect_text(node: &&Node, value: &mut DOMString) {
    let elem = ElementCast::to_ref(*node).unwrap();
    let svg_script = *elem.namespace() == ns!(SVG) && elem.local_name() == &atom!("script");
    let html_script = node.is_htmlscriptelement();
    if svg_script || html_script {
        return;
    } else {
        for child in node.children() {
            if child.r().is_text() {
                let characterdata = CharacterDataCast::to_ref(child.r()).unwrap();
                value.push_str(&characterdata.Data());
            } else {
                collect_text(&child.r(), value);
            }
        }
    }
}

impl HTMLOptionElementMethods for HTMLOptionElement {
    // https://www.whatwg.org/html/#dom-option-disabled
    make_bool_getter!(Disabled);

    // https://www.whatwg.org/html/#dom-option-disabled
    fn SetDisabled(&self, disabled: bool) {
        let elem = ElementCast::from_ref(self);
        elem.set_bool_attribute(&atom!("disabled"), disabled)
    }

    // https://www.whatwg.org/html/#dom-option-text
    fn Text(&self) -> DOMString {
        let node = NodeCast::from_ref(self);
        let mut content = String::new();
        collect_text(&node, &mut content);
        let v: Vec<&str> = split_html_space_chars(&content).collect();
        v.join(" ")
    }

    // https://www.whatwg.org/html/#dom-option-text
    fn SetText(&self, value: DOMString) {
        let node = NodeCast::from_ref(self);
        node.SetTextContent(Some(value))
    }

    // https://html.spec.whatwg.org/multipage/#attr-option-value
    fn Value(&self) -> DOMString {
        let element = ElementCast::from_ref(self);
        let attr = &atom!("value");
        if element.has_attribute(attr) {
            element.get_string_attribute(attr)
        } else {
            self.Text()
        }
    }

    // https://html.spec.whatwg.org/multipage/#attr-option-value
    make_setter!(SetValue, "value");

    // https://html.spec.whatwg.org/multipage/#attr-option-label
    fn Label(&self) -> DOMString {
        let element = ElementCast::from_ref(self);
        let attr = &atom!("label");
        if element.has_attribute(attr) {
            element.get_string_attribute(attr)
        } else {
            self.Text()
        }
    }

    // https://html.spec.whatwg.org/multipage/#attr-option-label
    make_setter!(SetLabel, "label");

    // https://html.spec.whatwg.org/multipage/#dom-option-defaultselected
    make_bool_getter!(DefaultSelected, "selected");

    // https://html.spec.whatwg.org/multipage/#dom-option-defaultselected
    make_bool_setter!(SetDefaultSelected, "selected");

    // https://html.spec.whatwg.org/multipage/#dom-option-selected
    fn Selected(&self) -> bool {
        self.selectedness.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-option-selected
    fn SetSelected(&self, selected: bool) {
        self.dirtiness.set(true);
        self.selectedness.set(selected);
        // FIXME: as per the spec, implement 'ask for a reset'
        // https://github.com/servo/servo/issues/7774
    }
}

impl VirtualMethods for HTMLOptionElement {
    fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
        let htmlelement: &HTMLElement = HTMLElementCast::from_ref(self);
        Some(htmlelement as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        match attr.local_name() {
            &atom!(disabled) => {
                let node = NodeCast::from_ref(self);
                match mutation {
                    AttributeMutation::Set(_) => {
                        node.set_disabled_state(true);
                        node.set_enabled_state(false);
                    },
                    AttributeMutation::Removed => {
                        node.set_disabled_state(false);
                        node.set_enabled_state(true);
                        node.check_parent_disabled_state_for_option();
                    }
                }
            },
            &atom!(selected) => {
                match mutation {
                    AttributeMutation::Set(_) => {
                        // https://html.spec.whatwg.org/multipage/#concept-option-selectedness
                        if !self.dirtiness.get() {
                            self.selectedness.set(true);
                        }
                    },
                    AttributeMutation::Removed => {
                        // https://html.spec.whatwg.org/multipage/#concept-option-selectedness
                        if !self.dirtiness.get() {
                            self.selectedness.set(false);
                        }
                    },
                }
            },
            _ => {},
        }
    }

    fn bind_to_tree(&self, tree_in_doc: bool) {
        if let Some(ref s) = self.super_type() {
            s.bind_to_tree(tree_in_doc);
        }

        let node = NodeCast::from_ref(self);
        node.check_parent_disabled_state_for_option();
    }

    fn unbind_from_tree(&self, tree_in_doc: bool) {
        if let Some(ref s) = self.super_type() {
            s.unbind_from_tree(tree_in_doc);
        }

        let node = NodeCast::from_ref(self);
        if node.GetParentNode().is_some() {
            node.check_parent_disabled_state_for_option();
        } else {
            node.check_disabled_attribute();
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Guillaume Pinot <texitoi(a)texitoi.eu>
//
// This work is free. You can redistribute it and/or modify it under
// the terms of the Do What The Fuck You Want To Public License,
// Version 2, as published by Sam Hocevar. See the COPYING file for
// more details.

#![deny(missing_docs)]

//! `StructOpt` trait definition
//!
//! This crate defines the `StructOpt` trait.  Alone, this crate is of
//! little interest.  See the `structopt-derive` crate to
//! automatically generate implementation of this trait.

extern crate clap as _clap;

/// Re-export of clap
pub mod clap {
    pub use _clap::*;
}

/// A struct that is converted from command line arguments.
pub trait StructOpt {
    /// Returns the corresponding `clap::App`.
    fn clap<'a, 'b>() -> clap::App<'a, 'b>;

    /// Add this app's arguments/subcommands to another `clap::App`.
    fn augment_clap<'a, 'b>(clap::App<'a, 'b>) -> clap::App<'a, 'b>;

    /// Creates the struct from `clap::ArgMatches`.
    fn from_clap(clap::ArgMatches) -> Self;

    /// Gets the struct from the command line arguments.  Print the
    /// error message and quit the program in case of failure.
    fn from_args() -> Self where Self: Sized {
        Self::from_clap(Self::clap().get_matches())
    }
}
<commit_msg>add link to structopt-derive documentation from structopt crate<commit_after>// Copyright (c) 2017 Guillaume Pinot <texitoi(a)texitoi.eu>
//
// This work is free. You can redistribute it and/or modify it under
// the terms of the Do What The Fuck You Want To Public License,
// Version 2, as published by Sam Hocevar. See the COPYING file for
// more details.

#![deny(missing_docs)]

//! `StructOpt` trait definition
//!
//! This crate defines the `StructOpt` trait.  Alone, this crate is of
//! little interest.  See the
//! [`structopt-derive`](https://docs.rs/structopt-derive) crate to
//! automatically generate an implementation of this trait.

extern crate clap as _clap;

/// Re-export of clap
pub mod clap {
    pub use _clap::*;
}

/// A struct that is converted from command line arguments.
pub trait StructOpt {
    /// Returns the corresponding `clap::App`.
    fn clap<'a, 'b>() -> clap::App<'a, 'b>;

    /// Add this app's arguments/subcommands to another `clap::App`.
    fn augment_clap<'a, 'b>(clap::App<'a, 'b>) -> clap::App<'a, 'b>;

    /// Creates the struct from `clap::ArgMatches`.
    fn from_clap(clap::ArgMatches) -> Self;

    /// Gets the struct from the command line arguments.  Print the
    /// error message and quit the program in case of failure.
    fn from_args() -> Self where Self: Sized {
        Self::from_clap(Self::clap().get_matches())
    }
}
<|endoftext|>