<commit_before>use bytes::{Buf, BufMut, Bytes};

use super::HttpBody;

/// Concatenate the buffers from a body into a single `Bytes` asynchronously.
///
/// This may require copying the data into a single buffer. If you don't need
/// a contiguous buffer, prefer the [`aggregate`](crate::body::aggregate())
/// function.
///
/// # Note
///
/// Care needs to be taken if the remote is untrusted. The function doesn't implement any length
/// checks and an malicious peer might make it consume arbitrary amounts of memory. Checking the
/// `Content-Length` is a possibility, but it is not strictly mandated to be present.
///
/// # Example
///
/// ```
/// # async fn doc() -> hyper::Result<()> {
/// use hyper::{body::HttpBody};
///
/// # let request = hyper::Request::builder()
/// #        .method(hyper::Method::POST)
/// #        .uri("http://httpbin.org/post")
/// #        .header("content-type", "application/json")
/// #        .body(hyper::Body::from(r#"{"library":"hyper"}"#)).unwrap();
/// # let client = hyper::Client::new();
/// let response = client.request(request).await?;
///
/// const MAX_ALLOWED_RESPONSE_SIZE: u64 = 1024;
///
/// let response_content_length = match response.body().size_hint().upper() {
///     Some(v) => v,
///     None => MAX_ALLOWED_RESPONSE_SIZE + 1 // Just to protect ourselves from a malicious response
/// };
///
/// if response_content_length < MAX_ALLOWED_RESPONSE_SIZE {
///     let body_bytes = hyper::body::to_bytes(response.into_body()).await?;
///     println!("body: {:?}", body_bytes);
/// }
///
/// # Ok(())
/// # }
/// ```
pub async fn to_bytes<T>(body: T) -> Result<Bytes, T::Error>
where
    T: HttpBody,
{
    futures_util::pin_mut!(body);

    // If there's only 1 chunk, we can just return Buf::to_bytes()
    let mut first = if let Some(buf) = body.data().await {
        buf?
    } else {
        return Ok(Bytes::new());
    };

    let second = if let Some(buf) = body.data().await {
        buf?
    } else {
        return Ok(first.copy_to_bytes(first.remaining()));
    };

    // With more than 1 buf, we gotta flatten into a Vec first.
    let cap = first.remaining() + second.remaining() + body.size_hint().lower() as usize;
    let mut vec = Vec::with_capacity(cap);
    vec.put(first);
    vec.put(second);

    while let Some(buf) = body.data().await {
        vec.put(buf?);
    }

    Ok(vec.into())
}
<commit_msg>docs(body) fix doctest failing due to missing features<commit_after>use bytes::{Buf, BufMut, Bytes};

use super::HttpBody;

/// Concatenate the buffers from a body into a single `Bytes` asynchronously.
///
/// This may require copying the data into a single buffer. If you don't need
/// a contiguous buffer, prefer the [`aggregate`](crate::body::aggregate())
/// function.
///
/// # Note
///
/// Care needs to be taken if the remote is untrusted. The function doesn't implement any length
/// checks and an malicious peer might make it consume arbitrary amounts of memory. Checking the
/// `Content-Length` is a possibility, but it is not strictly mandated to be present.
///
/// # Example
///
/// ```
/// # #[cfg(all(feature = "client", any(feature = "http1", feature = "http2")))]
/// # async fn doc() -> hyper::Result<()> {
/// use hyper::{body::HttpBody};
///
/// # let request = hyper::Request::builder()
/// #        .method(hyper::Method::POST)
/// #        .uri("http://httpbin.org/post")
/// #        .header("content-type", "application/json")
/// #        .body(hyper::Body::from(r#"{"library":"hyper"}"#)).unwrap();
/// # let client = hyper::Client::new();
/// let response = client.request(request).await?;
///
/// const MAX_ALLOWED_RESPONSE_SIZE: u64 = 1024;
///
/// let response_content_length = match response.body().size_hint().upper() {
///     Some(v) => v,
///     None => MAX_ALLOWED_RESPONSE_SIZE + 1 // Just to protect ourselves from a malicious response
/// };
///
/// if response_content_length < MAX_ALLOWED_RESPONSE_SIZE {
///     let body_bytes = hyper::body::to_bytes(response.into_body()).await?;
///     println!("body: {:?}", body_bytes);
/// }
///
/// # Ok(())
/// # }
/// ```
pub async fn to_bytes<T>(body: T) -> Result<Bytes, T::Error>
where
    T: HttpBody,
{
    futures_util::pin_mut!(body);

    // If there's only 1 chunk, we can just return Buf::to_bytes()
    let mut first = if let Some(buf) = body.data().await {
        buf?
    } else {
        return Ok(Bytes::new());
    };

    let second = if let Some(buf) = body.data().await {
        buf?
    } else {
        return Ok(first.copy_to_bytes(first.remaining()));
    };

    // With more than 1 buf, we gotta flatten into a Vec first.
    let cap = first.remaining() + second.remaining() + body.size_hint().lower() as usize;
    let mut vec = Vec::with_capacity(cap);
    vec.put(first);
    vec.put(second);

    while let Some(buf) = body.data().await {
        vec.put(buf?);
    }

    Ok(vec.into())
}
<|endoftext|>


<commit_before>use std::old_io::{File, Open, ReadWrite};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    file: Option<File>,
}

impl Buffer {
    pub fn data(&self) -> String {
        self.data.to_string()
    }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
///
/// # Examples
///
/// ```rust
///
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, ReadWrite) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);

    // Create a new buffer using the loaded data, file, and other defaults.
    Ok(Buffer{ data: data, file: Some(file) })
}
<commit_msg>Add documentation for buffer data() method. Closes #2.<commit_after>use std::old_io::{File, Open, ReadWrite};
use std::old_io::IoResult;
use super::GapBuffer;
use super::gap_buffer;
use super::Position;
use super::Range;

pub struct Buffer {
    data: GapBuffer,
    file: Option<File>,
}

impl Buffer {
    /// Returns the contents of the buffer as a string.
    ///
    /// # Examples
    ///
    /// ```rust
    ///
    /// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
    /// assert_eq!(buffer.data(), "it works!\n");
    pub fn data(&self) -> String {
        self.data.to_string()
    }
}

/// Creates a new buffer by reading the UTF-8 interpreted file contents of the specified path.
///
/// # Examples
///
/// ```rust
///
/// let buffer = scribe::buffer::from_file(&Path::new("tests/sample/file")).unwrap();
/// assert_eq!(buffer.data(), "it works!\n");
pub fn from_file(path: &Path) -> IoResult<Buffer> {
    // Try to open and read the file, returning any errors encountered.
    let mut file = match File::open_mode(path, Open, ReadWrite) {
        Ok(f) => f,
        Err(error) => return Err(error),
    };
    let mut data = match file.read_to_string() {
        Ok(d) => d,
        Err(error) => return Err(error),
    };

    let data = gap_buffer::new(data);

    // Create a new buffer using the loaded data, file, and other defaults.
    Ok(Buffer{ data: data, file: Some(file) })
}
<|endoftext|>


<commit_before>//! Utility functions for testing

use std::path::PathBuf;

// Expose dependencies for use by other internal crates (e.g. so macros work)
pub use pretty_assertions;
pub use serde_json;
pub use tempfile;

/// Get the path of the home directory of this repository
pub fn home() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../..")
        .canonicalize()
        .expect("Unable to get repository home directory")
}

/// Get the path of the `fixtures` directory
pub fn fixtures() -> PathBuf {
    home().join("fixtures")
}

/// Should test be skipped on CI?
pub fn skip_ci(reason: &str) -> bool {
    if std::env::var("CI").is_ok() {
        eprintln!("Skipping test on CI: {}", reason);
        true
    } else {
        false
    }
}

/// Should test be skipped on the current operating system?
///
/// See https://doc.rust-lang.org/std/env/consts/constant.OS.html for
/// possible values.
pub fn skip_os(os: &str, reason: &str) -> bool {
    if std::env::consts::OS == os {
        eprintln!("Skipping test on OS `{}`: {}", os, reason);
        true
    } else {
        false
    }
}

/// Should test be skipped on CI for an operating system?
pub fn skip_ci_os(os: &str, reason: &str) -> bool {
    if std::env::var("CI").is_ok() && std::env::consts::OS == os {
        eprintln!("Skipping test on CI for OS `{}`: {}", os, reason);
        true
    } else {
        false
    }
}

/// Should slow tests be skipped?
///
/// Use at the start of slow tests to return early except on CI or when
/// the env var `RUN_SLOW_TESTS` is set.
///
/// Inspired by https://github.com/rust-analyzer/rust-analyzer/pull/2491
pub fn skip_slow() -> bool {
    if std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err() {
        eprintln!("Skipping slow test");
        true
    } else {
        false
    }
}

/// Assert that two nodes are equal based on their JSON representation
///
/// This has the advantage over `pretty_assertions::assert_eq` of not requiring the
/// `==` operator to be defined for the types and hiding less usually irrelevant
/// details such as `Box` wrappers.
#[macro_export]
macro_rules! assert_json_eq {
    ($a:expr, $b:expr) => {
        test_utils::pretty_assertions::assert_eq!(
            test_utils::serde_json::to_value(&$a).unwrap(),
            test_utils::serde_json::to_value(&$b).unwrap()
        );
    };
}

/// Assert that two nodes are equal based on their JSON representation
///
/// This is a convenience macro to avoid having to import and use `json!`
/// on the second argument of `assert_json_eq`.
#[macro_export]
macro_rules! assert_json_is {
    ($a:expr, $b:tt) => {
        test_utils::pretty_assertions::assert_eq!(
            test_utils::serde_json::json!($a),
            test_utils::serde_json::json!($b)
        );
    };
}

/// Print log entries
///
/// Many of the sibling crates use `tracing` and seeing log entries can be
/// useful during testing.
/// This prints entries to stderr. Use `cargo test -- --nocapture`.
pub fn print_logs() {
    tracing_subscriber::fmt()
        .pretty()
        .with_max_level(tracing::Level::DEBUG)
        .init()
}
<commit_msg>test(Test utilities): Allow printing of logs at various levels<commit_after>//! Utility functions for testing

use std::path::PathBuf;

// Expose dependencies for use by other internal crates (e.g. so macros work)
pub use pretty_assertions;
pub use serde_json;
pub use tempfile;

/// Get the path of the home directory of this repository
pub fn home() -> PathBuf {
    PathBuf::from(env!("CARGO_MANIFEST_DIR"))
        .join("../..")
        .canonicalize()
        .expect("Unable to get repository home directory")
}

/// Get the path of the `fixtures` directory
pub fn fixtures() -> PathBuf {
    home().join("fixtures")
}

/// Should test be skipped on CI?
pub fn skip_ci(reason: &str) -> bool {
    if std::env::var("CI").is_ok() {
        eprintln!("Skipping test on CI: {}", reason);
        true
    } else {
        false
    }
}

/// Should test be skipped on the current operating system?
///
/// See https://doc.rust-lang.org/std/env/consts/constant.OS.html for
/// possible values.
pub fn skip_os(os: &str, reason: &str) -> bool {
    if std::env::consts::OS == os {
        eprintln!("Skipping test on OS `{}`: {}", os, reason);
        true
    } else {
        false
    }
}

/// Should test be skipped on CI for an operating system?
pub fn skip_ci_os(os: &str, reason: &str) -> bool {
    if std::env::var("CI").is_ok() && std::env::consts::OS == os {
        eprintln!("Skipping test on CI for OS `{}`: {}", os, reason);
        true
    } else {
        false
    }
}

/// Should slow tests be skipped?
///
/// Use at the start of slow tests to return early except on CI or when
/// the env var `RUN_SLOW_TESTS` is set.
///
/// Inspired by https://github.com/rust-analyzer/rust-analyzer/pull/2491
pub fn skip_slow() -> bool {
    if std::env::var("CI").is_err() && std::env::var("RUN_SLOW_TESTS").is_err() {
        eprintln!("Skipping slow test");
        true
    } else {
        false
    }
}

/// Assert that two nodes are equal based on their JSON representation
///
/// This has the advantage over `pretty_assertions::assert_eq` of not requiring the
/// `==` operator to be defined for the types and hiding less usually irrelevant
/// details such as `Box` wrappers.
#[macro_export]
macro_rules! assert_json_eq {
    ($a:expr, $b:expr) => {
        test_utils::pretty_assertions::assert_eq!(
            test_utils::serde_json::to_value(&$a).unwrap(),
            test_utils::serde_json::to_value(&$b).unwrap()
        );
    };
}

/// Assert that two nodes are equal based on their JSON representation
///
/// This is a convenience macro to avoid having to import and use `json!`
/// on the second argument of `assert_json_eq`.
#[macro_export]
macro_rules! assert_json_is {
    ($a:expr, $b:tt) => {
        test_utils::pretty_assertions::assert_eq!(
            test_utils::serde_json::json!($a),
            test_utils::serde_json::json!($b)
        );
    };
}

/// Print log entries
///
/// Many of the sibling crates use `tracing` and being able to see log entries
/// can be very useful during testing.
///
/// Prints entries to stderr. Use `cargo test -- --nocapture`.
pub fn print_logs_level(level: tracing::Level) {
    tracing_subscriber::fmt()
        .pretty()
        .with_max_level(level)
        .init()
}

/// Print DEBUG and above log entries
pub fn print_logs() {
    print_logs_level(tracing::Level::DEBUG)
}
<|endoftext|>


<commit_before>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line (if any) on the board
/// there was a passing pawn before the move was played.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `promoted_piece_code` is
    /// used only when the `move_type` is pawn promotion, otherwise it
    /// is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Gets the promoted piece type from the raw value of "aux data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

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

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<commit_msg>doc fix<commit_after>use basetypes::*;
use position::castling_rights::*;

/// Represents a move on the chessboard.
///
/// `Move` contains 3 types of information:
///
/// 1. Information about the played move itself.
///
/// 2. Information needed so as to be able to undo the move and
///    restore the board into the exact same state as before.
///
/// 3. The move score -- moves with higher score are tried
///    first. Ideally the best move should have the highest score.
///
/// `Move` is a 32-bit unsigned number. The lowest 16 bits contain the
/// whole needed information about the move itself (type 1). And is
/// laid out the following way:
///
///  ```text
///   15                                                           0
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  | Move  |    Origin square      |   Destination square  | Aux   |
///  | type  |       6 bits          |        6 bits         | data  |
///  | 2 bits|   |   |   |   |   |   |   |   |   |   |   |   | 2 bits|
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |       |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// There are 4 "move type"s: `0`) normal move; `1`) en-passant
/// capture; `2`) pawn promotion; `3`) castling. "Aux data" encodes
/// the type of the promoted piece if the move type is pawn promotion,
/// otherwise it encodes castling rights (see below).
///
/// The highest 16 bits contain the rest ot the info:
///
///  ```text
///   31                                                          16
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |
///  |  Move score   |  Captured |  Played   | Cast- |   En-passant  |
///  |    4 bits     |  piece    |  piece    | ling  |      file     |
///  |   |   |   |   |  3 bits   |  3 bits   | 2 bits|     4 bits    |
///  |   |   |   |   |   |   |   |   |   |   |       |   |   |   |   |
///  +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
///  ```
///
/// "En-passant file" tells on what vertical line on the board there
/// was a passing pawn before the move was played. If there was no
/// passing pawn "en-passant file" is `NO_ENPASSANT_FILE`.
///
/// Castling rights are a bit complex. The castling rights for the side
/// that makes the move, before the move was made, are stored in the
/// "Aux data" field. This is OK, because promoting a pawn never
/// changes the moving player's castling rights. The castling rights
/// for the opposite side are stored in "Castling" field. (A move can
/// change the castling rights for the other side when a rook in the
/// corner is captured.)
///
/// When "Captured piece" is stored, its bits are inverted, so that
/// MVV-LVA (Most valuable victim -- least valuable aggressor) ordering
/// of the moves is preserved, even when the "Move score" field stays
/// the same.
#[derive(Debug)]
#[derive(Clone, Copy)]
#[derive(PartialOrd, Ord, PartialEq, Eq)]
pub struct Move(u32);

impl Move {
    /// Creates a new instance of `Move`.
    ///
    /// `us` is the side that makes the move. `promoted_piece_code` is
    /// used only when the `move_type` is pawn promotion, otherwise it
    /// is ignored.
    #[inline]
    pub fn new(us: Color,
               score: usize,
               move_type: MoveType,
               piece: PieceType,
               orig_square: Square,
               dest_square: Square,
               captured_piece: PieceType,
               en_passant_file: File,
               castling: CastlingRights,
               promoted_piece_code: usize)
               -> Move {
        assert!(us <= 1);
        assert!(score <= 0b1111);
        assert!(move_type <= 0x11);
        assert!(piece < NO_PIECE);
        assert!(orig_square <= 63);
        assert!(dest_square <= 63);
        assert!(captured_piece != KING && captured_piece <= NO_PIECE);
        assert!(en_passant_file <= 0b1000);
        assert!(promoted_piece_code <= 0b11);
        let aux_data = match move_type {
            MOVE_PROMOTION => promoted_piece_code,
            _ => castling.get_for(us),
        };
        Move((score << M_SHIFT_SCORE | (!captured_piece & 0b111) << M_SHIFT_CAPTURED_PIECE |
              piece << M_SHIFT_PIECE |
              castling.get_for(1 ^ us) << M_SHIFT_CASTLING_DATA |
              en_passant_file << M_SHIFT_ENPASSANT_FILE |
              move_type << M_SHIFT_MOVE_TYPE | orig_square << M_SHIFT_ORIG_SQUARE |
              dest_square << M_SHIFT_DEST_SQUARE |
              aux_data << M_SHIFT_AUX_DATA) as u32)
    }

    /// Sets the "move score" field to a particular value.
    #[inline]
    pub fn set_score(&mut self, score: usize) {
        assert!(score <= 0b1111);
        self.0 &= !M_MASK_SCORE;
        self.0 |= (score << M_SHIFT_SCORE) as u32;
    }

    /// Sets a particular bit in the "move score" field to `1`.
    #[inline]
    pub fn set_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 |= 1 << b << M_SHIFT_SCORE;
    }

    /// Sets a particular bit in the "move score" field to `0`.
    #[inline]
    pub fn clear_score_bit(&mut self, b: usize) {
        assert!(b <= 3);
        self.0 &= !(1 << b << M_SHIFT_SCORE);
    }

    #[inline]
    pub fn score(&self) -> usize {
        ((self.0 & M_MASK_SCORE) >> M_SHIFT_SCORE) as usize
    }

    #[inline]
    pub fn move_type(&self) -> MoveType {
        ((self.0 & M_MASK_MOVE_TYPE) >> M_SHIFT_MOVE_TYPE) as MoveType
    }

    #[inline]
    pub fn piece(&self) -> PieceType {
        ((self.0 & M_MASK_PIECE) >> M_SHIFT_PIECE) as PieceType
    }

    #[inline]
    pub fn orig_square(&self) -> Square {
        ((self.0 & M_MASK_ORIG_SQUARE) >> M_SHIFT_ORIG_SQUARE) as Square
    }

    #[inline]
    pub fn dest_square(&self) -> Square {
        ((self.0 & M_MASK_DEST_SQUARE) >> M_SHIFT_DEST_SQUARE) as Square
    }

    #[inline]
    pub fn captured_piece(&self) -> PieceType {
        ((!self.0 & M_MASK_CAPTURED_PIECE) >> M_SHIFT_CAPTURED_PIECE) as PieceType
    }

    #[inline]
    pub fn en_passant_file(&self) -> File {
        ((self.0 & M_MASK_ENPASSANT_FILE) >> M_SHIFT_ENPASSANT_FILE) as File
    }

    #[inline(always)]
    pub fn castling_data(&self) -> usize {
        ((self.0 & M_MASK_CASTLING_DATA) >> M_SHIFT_CASTLING_DATA) as usize
    }

    #[inline(always)]
    pub fn aux_data(&self) -> usize {
        ((self.0 & M_MASK_AUX_DATA) >> M_SHIFT_AUX_DATA) as usize
    }

    /// Gets the promoted piece type from the raw value of "aux data".
    ///
    /// When the "move type" is pawn promotion, "aux data" holds the
    /// promoted piece type encoded with a number from 0 to 3. This
    /// function decodes this number to a piece type.
    #[inline]
    pub fn piece_from_aux_data(pp_code: usize) -> PieceType {
        assert!(pp_code <= 3);
        match pp_code {
            0 => QUEEN,
            1 => ROOK,
            2 => BISHOP,
            _ => KNIGHT,
        }
    }
}

/// Represents no en-passant file.
pub const NO_ENPASSANT_FILE: Rank = 8;

// Field shifts
const M_SHIFT_SCORE: u32 = 28;
const M_SHIFT_CAPTURED_PIECE: u32 = 25;
const M_SHIFT_PIECE: u32 = 22;
const M_SHIFT_CASTLING_DATA: u32 = 20;
const M_SHIFT_ENPASSANT_FILE: u32 = 16;
const M_SHIFT_MOVE_TYPE: u32 = 14;
const M_SHIFT_ORIG_SQUARE: u32 = 8;
const M_SHIFT_DEST_SQUARE: u32 = 2;
const M_SHIFT_AUX_DATA: u32 = 0;

// Field masks
const M_MASK_SCORE: u32 = 0b1111 << M_SHIFT_SCORE;
const M_MASK_CAPTURED_PIECE: u32 = 0b111 << M_SHIFT_CAPTURED_PIECE;
const M_MASK_PIECE: u32 = 0b111 << M_SHIFT_PIECE;
const M_MASK_CASTLING_DATA: u32 = 0b11 << M_SHIFT_CASTLING_DATA;
const M_MASK_ENPASSANT_FILE: u32 = 0b1111 << M_SHIFT_ENPASSANT_FILE;
const M_MASK_MOVE_TYPE: u32 = 0b11 << M_SHIFT_MOVE_TYPE;
const M_MASK_ORIG_SQUARE: u32 = 0b111111 << M_SHIFT_ORIG_SQUARE;
const M_MASK_DEST_SQUARE: u32 = 0b111111 << M_SHIFT_DEST_SQUARE;
const M_MASK_AUX_DATA: u32 = 0b11 << M_SHIFT_AUX_DATA;

// TODO: Here does not seem to be the right place for
// "MoveStack". Find it other owner.
pub struct MoveStack {
    stack: [Move; MOVE_STACK_SIZE],
    next_index: usize,
}

impl MoveStack {
    pub fn new() -> MoveStack {
        use std::mem::uninitialized;
        unsafe {
            MoveStack {
                stack: uninitialized(),
                next_index: 0,
            }
        }
    }

    #[inline(always)]
    pub fn push(&mut self, m: Move) {
        self.stack[self.next_index] = m;
        self.next_index += 1;
    }

    #[inline(always)]
    pub fn pop(&mut self) -> Option<Move> {
        if self.next_index == 0 {
            None
        } else {
            self.next_index -= 1;
            Some(self.stack[self.next_index])
        }
    }

    #[inline(always)]
    pub fn remove_all(&mut self) -> usize {
        let count = self.count();
        self.next_index = 0;
        count
    }

    #[inline(always)]
    pub fn count(&self) -> usize {
        self.next_index
    }
}

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

    #[test]
    fn test_move() {
        use basetypes::*;

        let mut cr = CastlingRights::new();
        cr.set_for(WHITE, 0b10);
        cr.set_for(BLACK, 0b11);
        let mut m = Move::new(WHITE,
                              12,
                              MOVE_NORMAL,
                              PAWN,
                              E2,
                              E4,
                              NO_PIECE,
                              NO_ENPASSANT_FILE,
                              cr,
                              0);
        let n1 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           PAWN,
                           F3,
                           E4,
                           KNIGHT,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n2 = Move::new(WHITE,
                           12,
                           MOVE_NORMAL,
                           KING,
                           F3,
                           E4,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           0);
        let n3 = Move::new(BLACK,
                           0,
                           MOVE_PROMOTION,
                           PAWN,
                           F2,
                           F1,
                           NO_PIECE,
                           NO_ENPASSANT_FILE,
                           CastlingRights::new(),
                           1);
        assert!(n1 > m);
        assert!(n2 < m);
        assert_eq!(m.score(), 12);
        assert_eq!(m.piece(), PAWN);
        assert_eq!(m.captured_piece(), NO_PIECE);
        assert_eq!(m.orig_square(), E2);
        assert_eq!(m.dest_square(), E4);
        assert_eq!(m.en_passant_file(), 8);
        assert_eq!(m.aux_data(), 0b10);
        assert_eq!(m.castling_data(), 0b11);
        let m2 = m;
        assert_eq!(m, m2);
        m.set_score(13);
        assert_eq!(m.score(), 13);
        assert!(m > m2);
        m.clear_score_bit(0);
        assert_eq!(m, m2);
        m.set_score_bit(0);
        assert_eq!(m.score(), 13);
        m.set_score(0);
        assert_eq!(m.score(), 0);
        assert_eq!(n3.aux_data(), 1);
    }
}
<|endoftext|>


<commit_before>use crate::{
    config::{self, Mode},
    shell::Shell,
};
use anyhow::{bail, Context as _};
use snowchains_core::web::PlatformVariant;
use std::{cell::RefCell, fs, path::PathBuf};
use structopt::StructOpt;
use strum::VariantNames as _;
use termcolor::WriteColor;

#[derive(StructOpt, Debug)]
pub struct OptInit {
    /// Overwrites the existing config
    #[structopt(short, long)]
    pub force: bool,

    /// Coloring
    #[structopt(
        long,
        possible_values(crate::ColorChoice::VARIANTS),
        default_value("auto")
    )]
    pub color: crate::ColorChoice,

    /// Directory to create a `snowchains.dhall`
    #[structopt(default_value("."))]
    pub directory: PathBuf,
}

pub(crate) fn run<R: Sized, W1: Sized, W2: WriteColor>(
    opt: OptInit,
    ctx: crate::Context<R, W1, W2>,
) -> anyhow::Result<()> {
    let OptInit {
        force,
        color: _,
        directory,
    } = opt;

    let crate::Context {
        cwd,
        stdin: _,
        stdout: _,
        stderr,
        draw_progress,
    } = ctx;

    let stderr = RefCell::new(stderr);
    let mut shell = Shell::new(&stderr, || unreachable!(), draw_progress);

    let path = cwd
        .join(directory.strip_prefix(".").unwrap_or(&directory))
        .join("snowchains.dhall");

    if !force && path.exists() {
        bail!(
            "`{}` exists. Enable to `--force` to overwrite",
            path.display(),
        );
    }

    fs::write(
        &path,
        include_str!("../../resources/config/default-config.dhall"),
    )
    .with_context(|| format!("Could not write `{}`", path.display()))?;
    shell.info(format!("Wrote `{}`", path.display()))?;

    let t = std::time::Instant::now();
    let lang = config::load_language(
        &path,
        Some(&path),
        Some(PlatformVariant::Atcoder),
        Some("practice"),
        Some("a"),
        Some("cpp"),
        Mode::Debug,
    )?;
    let t = std::time::Instant::now() - t;
    dbg!(t);
    dbg!(lang);

    Ok(())
}
<commit_msg>Do not use `Shell` in the `init` command<commit_after>use crate::config::{self, Mode};
use anyhow::{bail, Context as _};
use snowchains_core::web::PlatformVariant;
use std::{fs, path::PathBuf};
use structopt::StructOpt;
use strum::VariantNames as _;
use termcolor::WriteColor;

#[derive(StructOpt, Debug)]
pub struct OptInit {
    /// Overwrites the existing config
    #[structopt(short, long)]
    pub force: bool,

    /// Coloring
    #[structopt(
        long,
        possible_values(crate::ColorChoice::VARIANTS),
        default_value("auto")
    )]
    pub color: crate::ColorChoice,

    /// Directory to create a `snowchains.dhall`
    #[structopt(default_value("."))]
    pub directory: PathBuf,
}

pub(crate) fn run<R: Sized, W1: Sized, W2: WriteColor>(
    opt: OptInit,
    ctx: crate::Context<R, W1, W2>,
) -> anyhow::Result<()> {
    let OptInit {
        force,
        color: _,
        directory,
    } = opt;

    let crate::Context {
        cwd,
        stdin: _,
        stdout: _,
        mut stderr,
        draw_progress: _,
    } = ctx;

    let path = cwd
        .join(directory.strip_prefix(".").unwrap_or(&directory))
        .join("snowchains.dhall");

    if !force && path.exists() {
        bail!(
            "`{}` exists. Enable to `--force` to overwrite",
            path.display(),
        );
    }

    fs::write(
        &path,
        include_str!("../../resources/config/default-config.dhall"),
    )
    .with_context(|| format!("Could not write `{}`", path.display()))?;

    writeln!(stderr, "Wrote `{}`", path.display())?;
    stderr.flush()?;

    let t = std::time::Instant::now();
    let lang = config::load_language(
        &path,
        Some(&path),
        Some(PlatformVariant::Atcoder),
        Some("practice"),
        Some("a"),
        Some("cpp"),
        Mode::Debug,
    )?;
    let t = std::time::Instant::now() - t;
    dbg!(t);
    dbg!(lang);

    Ok(())
}
<|endoftext|>


<commit_before>#![allow(unused_macros)]

macro_rules! gen_hashmap {

    {$($key: expr => $value: expr),*} => {

        {
            let mut hashmap = HashMap::new();

            $(
                hashmap.insert($key, $value);
            )*

            hashmap
        }
    }
}<commit_msg>Fix gen_hashmap! and improve it's performance<commit_after>#![allow(unused_macros)]

macro_rules! gen_hashmap {

    (@single $($e: tt)*) => (());

    (@count $($e: expr)*) => (<[()]>::len(&[$(gen_hashmap!(@single $e)),*]));

    ($($key: expr => $value: expr,)+) => (gen_hashmap!($($key => $value),+));

    {$($key: expr => $value: expr),*} => {

        {
            let count = gen_hashmap!(@count $($key)*);
            let mut hashmap = ::std::collections::HashMap::with_capacity(count);

            $(
                hashmap.insert($key, $value);
            )*

            hashmap
        }
    }
}
<|endoftext|>


<commit_before>
mod integration_tests;
extern crate brotli_no_stdlib as brotli;
extern crate core;

#[macro_use]
extern crate alloc_no_stdlib;

use core::ops;
use core::cmp;
use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper,
            StackAllocator, AllocatedStackMemory, bzero};

//use alloc::{SliceWrapper,SliceWrapperMut, StackAllocator, AllocatedStackMemory, Allocator};
use brotli::{BrotliDecompressStream, BrotliState, BrotliResult, HuffmanCode};
pub use brotli::FILE_BUFFER_SIZE;
use std::io::{self, Read, Write, ErrorKind, Error};

declare_stack_allocator_struct!(MemPool, 4096, calloc);

fn _write_all<OutputType> (w : &mut OutputType, buf : &[u8]) -> Result<(), io::Error>
where OutputType: Write {
    let mut total_written : usize = 0;
    while total_written < buf.len() {
        match w.write(&buf[total_written..]) {
            Err(e) => {
                match e.kind() {
                    ErrorKind::Interrupted => continue,
                    _ => return Err(e),
                }
            },
            Ok(cur_written) => {
                if cur_written == 0 {
                     return Err(Error::new(ErrorKind::UnexpectedEof, "Write EOF"));
                }
                total_written += cur_written;
            }
        }
    }
    Ok(())
}

//trace_macros!(true);

define_allocator_memory_pool!(global_buffer, 16, u8, [0; 1024 * 1024 * 100], global);
pub fn decompress<InputType, OutputType> (r : &mut InputType, mut w : &mut OutputType) -> Result<(), io::Error>
where InputType: Read, OutputType: Write {
    return decompress_internal(r, w, FILE_BUFFER_SIZE, FILE_BUFFER_SIZE);
}
pub fn decompress_internal<InputType, OutputType> (r : &mut InputType, mut w : &mut OutputType, input_buffer_limit : usize, output_buffer_limit : usize) -> Result<(), io::Error>
where InputType: Read, OutputType: Write {
  let mut input_fixed = [0u8;FILE_BUFFER_SIZE];
  let mut output_fixed = [0u8;FILE_BUFFER_SIZE];
  let mut input = &mut input_fixed[0 .. cmp::min(FILE_BUFFER_SIZE, input_buffer_limit)];
  let mut output = &mut output_fixed[0 .. cmp::min(FILE_BUFFER_SIZE, output_buffer_limit)];
  let mut available_out : usize = output.len();
  define_allocator_memory_pool!(calloc_u8_buffer, 4096, u8, [0; 32 * 1024 * 1024], calloc);
  define_allocator_memory_pool!(calloc_u32_buffer, 4096, u32, [0; 1024 * 1024], calloc);
  define_allocator_memory_pool!(calloc_hc_buffer, 4096, HuffmanCode, [0; 4 * 1024 * 1024], calloc);
  let calloc_u8_allocator = MemPool::<u8>::new_allocator(calloc_u8_buffer, bzero);
  let calloc_u32_allocator = MemPool::<u32>::new_allocator(calloc_u32_buffer, bzero);
  let calloc_hc_allocator = MemPool::<HuffmanCode>::new_allocator(calloc_hc_buffer, bzero);
  //test(calloc_u8_allocator);
  let mut brotli_state = BrotliState::new(calloc_u8_allocator, calloc_u32_allocator, calloc_hc_allocator);

  //let amount = try!(r.read(&mut buf));
  let mut available_in : usize = 0;
  let mut input_offset : usize = 0;
  let mut output_offset : usize = 0;
  let mut result : BrotliResult = BrotliResult::NeedsMoreInput;
  loop {
      match result {
          BrotliResult::NeedsMoreInput => {
              input_offset = 0;
              match r.read(input) {
                  Err(e) => {
                      match e.kind() {
                          ErrorKind::Interrupted => continue,
                          _ => return Err(e),
                      }
                  },
                  Ok(size) => {
                      if size == 0 {
                          return Err(Error::new(ErrorKind::UnexpectedEof, "Read EOF"));
                      }
                      available_in = size;
                  },
              }
          },
          BrotliResult::NeedsMoreOutput => {
              try!(_write_all(&mut w, &output[..output_offset]));
              output_offset = 0;
          },
          BrotliResult::ResultSuccess => break,
          BrotliResult::ResultFailure => panic!("FAILURE"),
      }
      let mut written :usize = 0;
      result = BrotliDecompressStream(&mut available_in, &mut input_offset, &input[..],
                                      &mut available_out, &mut output_offset, &mut output,
                                      &mut written, &mut brotli_state);

      if output_offset != 0 {
          try!(_write_all(&mut w, &output[..output_offset]));
          output_offset = 0;
          available_out = output.len()
      }
  }
  brotli_state.BrotliStateCleanup();
  Ok(())
}

fn main() {
    match decompress(&mut io::stdin(), &mut io::stdout()) {
        Ok(_) => return,
        Err(e) => panic!("Error {:?}", e),
    }
}
<commit_msg>added some timing to the standard brot binary<commit_after>
mod integration_tests;
extern crate brotli_no_stdlib as brotli;
extern crate core;

#[macro_use]
extern crate alloc_no_stdlib;

use core::ops;
use alloc_no_stdlib::{Allocator, SliceWrapperMut, SliceWrapper,
            StackAllocator, AllocatedStackMemory, bzero};

//use alloc::{SliceWrapper,SliceWrapperMut, StackAllocator, AllocatedStackMemory, Allocator};
use brotli::{BrotliDecompressStream, BrotliState, BrotliResult, HuffmanCode};
pub use brotli::FILE_BUFFER_SIZE;
use std::io::{self, Read, Write, ErrorKind, Error};
use std::time::{Instant, Duration};

declare_stack_allocator_struct!(MemPool, 4096, calloc);

fn _write_all<OutputType> (w : &mut OutputType, buf : &[u8]) -> Result<(), io::Error>
where OutputType: Write {
    let mut total_written : usize = 0;
    while total_written < buf.len() {
        match w.write(&buf[total_written..]) {
            Err(e) => {
                match e.kind() {
                    ErrorKind::Interrupted => continue,
                    _ => return Err(e),
                }
            },
            Ok(cur_written) => {
                if cur_written == 0 {
                     return Err(Error::new(ErrorKind::UnexpectedEof, "Write EOF"));
                }
                total_written += cur_written;
            }
        }
    }
    Ok(())
}

//trace_macros!(true);

pub fn decompress<InputType, OutputType> (r : &mut InputType, mut w : &mut OutputType) -> Result<(), io::Error>
where InputType: Read, OutputType: Write {
    return decompress_internal(r, w, 4096 * 1024, 4096 * 1024);
}
pub fn decompress_internal<InputType, OutputType> (r : &mut InputType, mut w : &mut OutputType, input_buffer_limit : usize, output_buffer_limit : usize) -> Result<(), io::Error>
where InputType: Read, OutputType: Write {
  define_allocator_memory_pool!(calloc_u8_buffer, 4096, u8, [0; 32 * 1024 * 1024], calloc);
  define_allocator_memory_pool!(calloc_u32_buffer, 4096, u32, [0; 1024 * 1024], calloc);
  define_allocator_memory_pool!(calloc_hc_buffer, 4096, HuffmanCode, [0; 4 * 1024 * 1024], calloc);
  let calloc_u8_allocator = MemPool::<u8>::new_allocator(calloc_u8_buffer, bzero);
  let calloc_u32_allocator = MemPool::<u32>::new_allocator(calloc_u32_buffer, bzero);
  let calloc_hc_allocator = MemPool::<HuffmanCode>::new_allocator(calloc_hc_buffer, bzero);
  //test(calloc_u8_allocator);
  let mut brotli_state = BrotliState::new(calloc_u8_allocator, calloc_u32_allocator, calloc_hc_allocator);
  let mut input = brotli_state.alloc_u8.alloc_cell(input_buffer_limit);
  let mut output = brotli_state.alloc_u8.alloc_cell(output_buffer_limit);
  let mut available_out : usize = output.slice().len();

  //let amount = try!(r.read(&mut buf));
  let mut available_in : usize = 0;
  let mut input_offset : usize = 0;
  let mut output_offset : usize = 0;
  let mut result : BrotliResult = BrotliResult::NeedsMoreInput;
  let mut total = Duration::new(0, 0);
  loop {
      match result {
          BrotliResult::NeedsMoreInput => {
              input_offset = 0;
              match r.read(input.slice_mut()) {
                  Err(e) => {
                      match e.kind() {
                          ErrorKind::Interrupted => continue,
                          _ => return Err(e),
                      }
                  },
                  Ok(size) => {
                      if size == 0 {
                          return Err(Error::new(ErrorKind::UnexpectedEof, "Read EOF"));
                      }
                      available_in = size;
                  },
              }
          },
          BrotliResult::NeedsMoreOutput => {
              try!(_write_all(&mut w, &output.slice()[..output_offset]));
              output_offset = 0;
          },
          BrotliResult::ResultSuccess => break,
          BrotliResult::ResultFailure => panic!("FAILURE"),
      }
      let mut written :usize = 0;
      let start = Instant::now();
      result = BrotliDecompressStream(&mut available_in, &mut input_offset, &input.slice(),
                                      &mut available_out, &mut output_offset, &mut output.slice_mut(),
                                      &mut written, &mut brotli_state);
      total = total + Instant::now().duration_since(start);
      if output_offset != 0 {
          try!(_write_all(&mut w, &output.slice()[..output_offset]));
          output_offset = 0;
          available_out = output.slice().len()
      }
  }
  let _r = writeln!(&mut std::io::stderr(), "Total time {:}.{:09}\n", total.as_secs(), total.subsec_nanos());
  brotli_state.BrotliStateCleanup();
  Ok(())
}

fn main() {
    match decompress(&mut io::stdin(), &mut io::stdout()) {
        Ok(_) => return,
        Err(e) => panic!("Error {:?}", e),
    }
}
<|endoftext|>


<commit_before>extern crate bev;

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use bev::{Bez3o2d};

use gfx::traits::FactoryExt;
use gfx::{Device, Primitive};
use gfx::state::Rasterizer;

use glutin::Event;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_vertex_struct!{ Vertex {
    pos: [f32; 2] = "v_pos",
}}

gfx_pipeline!{ pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    out: gfx::RenderTarget<ColorFormat> = "r_target",
}}

fn main() {
    let builder = glutin::WindowBuilder::new()
        .with_dimensions(720, 720)
        .with_multisampling(16)
        .with_title("Hello Bézier".into());
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let sset = factory.create_shader_set(VERT, FRAG).unwrap();
    let pso = factory.create_pipeline_state(
        &sset,
        Primitive::LineStrip,
        Rasterizer::new_fill(),
        pipe::new()
    ).unwrap();

    let curve = Bez3o2d::new(
        0.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.0, 1.0
    );

    let mut verts = [Vertex{ pos: [0.0, 0.0] }; 31];
    let mut perps = [Vertex{ pos: [0.0, 0.0] }; 62];
    for i in 0..verts.len() {
        let t = i as f32/(verts.len()-1) as f32;

        let interp = curve.interp(t);
        verts[i].pos = interp.into();
        perps[i*2] = verts[i];
        perps[i*2 + 1].pos = (curve.slope(t).normalize().perp()/10.0 + interp).into();
    }

    let (vert_buffer, vert_slice) = factory.create_vertex_buffer_with_slice(&verts, ());
    let (perp_buffer, perp_slice) = factory.create_vertex_buffer_with_slice(&perps, ());
    let mut data = pipe::Data {
        vbuf: vert_buffer.clone(),
        out: main_color
    };

    'main: loop {
        for event in window.poll_events() {
            match event {
                Event::Closed => break 'main,
                _ => ()
            }
        }

        encoder.clear(&data.out, [0.0, 0.0, 0.0, 1.0]);

        data.vbuf = vert_buffer.clone();
        encoder.draw(&vert_slice, &pso, &data);

        data.vbuf = perp_buffer.clone();
        encoder.draw(&perp_slice, &pso, &data);

        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}

const VERT: &'static [u8] = br#"
    #version 150 core

    in vec2 v_pos;

    void main() {
        gl_Position = vec4(v_pos, 0.0, 1.0);
    }
"#;

const FRAG: &'static [u8] = br#"
    #version 150 core

    out vec4 r_target;

    void main() {
        r_target = vec4(1.0, 1.0, 1.0, 1.0);
    }
"#;<commit_msg>Update main.rs to draw thick curves<commit_after>extern crate bev;

#[macro_use]
extern crate gfx;
extern crate gfx_window_glutin;
extern crate glutin;

use bev::{Bez3o2d};

use gfx::traits::FactoryExt;
use gfx::{Device, Primitive};
use gfx::state::Rasterizer;

use glutin::Event;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

gfx_vertex_struct!{ Vertex {
    pos: [f32; 2] = "v_pos",
}}

gfx_pipeline!{ pipe {
    vbuf: gfx::VertexBuffer<Vertex> = (),
    out: gfx::RenderTarget<ColorFormat> = "r_target",
}}

fn main() {
    let builder = glutin::WindowBuilder::new()
        .with_dimensions(720, 720)
        .with_multisampling(16)
        .with_title("Hello Bézier".into());
    let (window, mut device, mut factory, main_color, _) =
        gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
    let mut encoder: gfx::Encoder<_, _> = factory.create_command_buffer().into();
    let sset = factory.create_shader_set(VERT, FRAG).unwrap();
    let pso = factory.create_pipeline_state(
        &sset,
        Primitive::TriangleStrip,
        Rasterizer::new_fill(),
        pipe::new()
    ).unwrap();

    let curve = Bez3o2d::new(
        0.0, 0.0, 1.0, 1.0,
        0.0, 1.0, 0.0, 1.0
    );

    let mut verts = [Vertex{ pos: [0.0, 0.0] }; 31];
    let mut perps = [Vertex{ pos: [0.0, 0.0] }; 62];
    for i in 0..verts.len() {
        let t = i as f32/(verts.len()-1) as f32;

        let interp = curve.interp(t);
        verts[i].pos = interp.into();

        let perp = curve.slope(t).normalize().perp() * 0.01;
        perps[i*2].pos = (-perp + interp).into();
        perps[i*2 + 1].pos = (perp + interp).into();
    }

    // let (vert_buffer, vert_slice) = factory.create_vertex_buffer_with_slice(&verts, ());
    let (perp_buffer, perp_slice) = factory.create_vertex_buffer_with_slice(&perps, ());
    let mut data = pipe::Data {
        vbuf: perp_buffer.clone(),
        out: main_color
    };

    'main: loop {
        for event in window.poll_events() {
            match event {
                Event::Closed => break 'main,
                _ => ()
            }
        }

        encoder.clear(&data.out, [0.0, 0.0, 0.0, 1.0]);

        // data.vbuf = vert_buffer.clone();
        // encoder.draw(&vert_slice, &pso, &data);

        data.vbuf = perp_buffer.clone();
        encoder.draw(&perp_slice, &pso, &data);

        encoder.flush(&mut device);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}

const VERT: &'static [u8] = br#"
    #version 150 core

    in vec2 v_pos;

    void main() {
        gl_Position = vec4(v_pos, 0.0, 1.0);
    }
"#;

const FRAG: &'static [u8] = br#"
    #version 150 core

    out vec4 r_target;

    void main() {
        r_target = vec4(1.0, 1.0, 1.0, 1.0);
    }
"#;<|endoftext|>


<commit_before>use rustc::lint::*;
use rustc_front::hir::*;
use rustc_front::intravisit::*;
use syntax::ast::LitKind;
use utils::{span_lint_and_then, in_macro, snippet_opt};

/// **What it does:** This lint checks for boolean expressions that can be written more concisely
///
/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication
///
/// **Known problems:** None
///
/// **Example:** `if a && b || a` should be `if a`
declare_lint! {
    pub NONMINIMAL_BOOL, Warn,
    "checks for boolean expressions that can be written more concisely"
}

#[derive(Copy,Clone)]
pub struct NonminimalBool;

impl LintPass for NonminimalBool {
    fn get_lints(&self) -> LintArray {
        lint_array!(NONMINIMAL_BOOL)
    }
}

impl LateLintPass for NonminimalBool {
    fn check_crate(&mut self, cx: &LateContext, krate: &Crate) {
        krate.visit_all_items(&mut NonminimalBoolVisitor(cx))
    }
}

struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);

use quine_mc_cluskey::Bool;
struct Hir2Qmm<'tcx>(Vec<&'tcx Expr>);

impl<'tcx> Hir2Qmm<'tcx> {
    fn extract(&mut self, op: BinOp_, a: &[&'tcx Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
        for a in a {
            if let ExprBinary(binop, ref lhs, ref rhs) = a.node {
                if binop.node == op {
                    v = self.extract(op, &[lhs, rhs], v)?;
                    continue;
                }
            }
            v.push(self.run(a)?);
        }
        Ok(v)
    }

    fn run(&mut self, e: &'tcx Expr) -> Result<Bool, String> {
        match e.node {
            ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
            ExprBinary(binop, ref lhs, ref rhs) => {
                match binop.node {
                    BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)),
                    BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)),
                    _ => {},
                }
            },
            ExprLit(ref lit) => {
                match lit.node {
                    LitKind::Bool(true) => return Ok(Bool::True),
                    LitKind::Bool(false) => return Ok(Bool::False),
                    _ => {},
                }
            },
            _ => {},
        }
        let n = self.0.len();
        self.0.push(e);
        if n < 32 {
            #[allow(cast_possible_truncation)]
            Ok(Bool::Term(n as u8))
        } else {
            Err("too many literals".to_owned())
        }
    }
}

fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
    fn recurse(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String {
        use quine_mc_cluskey::Bool::*;
        match *suggestion {
            True => {
                s.extend("true".chars());
                s
            },
            False => {
                s.extend("false".chars());
                s
            },
            Not(ref inner) => {
                s.push('!');
                recurse(cx, inner, terminals, s)
            },
            And(ref v) => {
                s = recurse(cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" && ".chars());
                    s = recurse(cx, inner, terminals, s);
                }
                s
            },
            Or(ref v) => {
                s = recurse(cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" || ".chars());
                    s = recurse(cx, inner, terminals, s);
                }
                s
            },
            Term(n) => {
                s.extend(snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros").chars());
                s
            }
        }
    }
    recurse(cx, suggestion, terminals, String::new())
}

impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
    fn bool_expr(&self, e: &Expr) {
        let mut h2q = Hir2Qmm(Vec::new());
        if let Ok(expr) = h2q.run(e) {
            let simplified = expr.simplify();
            if !simplified.iter().any(|s| *s == expr) {
                span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| {
                    for suggestion in &simplified {
                        db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.0));
                    }
                });
            }
        }
    }
}

impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, e: &'v Expr) {
        if in_macro(self.0, e.span) { return }
        match e.node {
            ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
            ExprUnary(UnNot, ref inner) => {
                if self.0.tcx.node_types()[&inner.id].is_bool() {
                    self.bool_expr(e);
                } else {
                    walk_expr(self, e);
                }
            },
            _ => walk_expr(self, e),
        }
    }
}
<commit_msg>improve bracket display<commit_after>use rustc::lint::*;
use rustc_front::hir::*;
use rustc_front::intravisit::*;
use syntax::ast::LitKind;
use utils::{span_lint_and_then, in_macro, snippet_opt};

/// **What it does:** This lint checks for boolean expressions that can be written more concisely
///
/// **Why is this bad?** Readability of boolean expressions suffers from unnecesessary duplication
///
/// **Known problems:** None
///
/// **Example:** `if a && b || a` should be `if a`
declare_lint! {
    pub NONMINIMAL_BOOL, Warn,
    "checks for boolean expressions that can be written more concisely"
}

#[derive(Copy,Clone)]
pub struct NonminimalBool;

impl LintPass for NonminimalBool {
    fn get_lints(&self) -> LintArray {
        lint_array!(NONMINIMAL_BOOL)
    }
}

impl LateLintPass for NonminimalBool {
    fn check_crate(&mut self, cx: &LateContext, krate: &Crate) {
        krate.visit_all_items(&mut NonminimalBoolVisitor(cx))
    }
}

struct NonminimalBoolVisitor<'a, 'tcx: 'a>(&'a LateContext<'a, 'tcx>);

use quine_mc_cluskey::Bool;
struct Hir2Qmm<'tcx>(Vec<&'tcx Expr>);

impl<'tcx> Hir2Qmm<'tcx> {
    fn extract(&mut self, op: BinOp_, a: &[&'tcx Expr], mut v: Vec<Bool>) -> Result<Vec<Bool>, String> {
        for a in a {
            if let ExprBinary(binop, ref lhs, ref rhs) = a.node {
                if binop.node == op {
                    v = self.extract(op, &[lhs, rhs], v)?;
                    continue;
                }
            }
            v.push(self.run(a)?);
        }
        Ok(v)
    }

    fn run(&mut self, e: &'tcx Expr) -> Result<Bool, String> {
        match e.node {
            ExprUnary(UnNot, ref inner) => return Ok(Bool::Not(box self.run(inner)?)),
            ExprBinary(binop, ref lhs, ref rhs) => {
                match binop.node {
                    BiOr => return Ok(Bool::Or(self.extract(BiOr, &[lhs, rhs], Vec::new())?)),
                    BiAnd => return Ok(Bool::And(self.extract(BiAnd, &[lhs, rhs], Vec::new())?)),
                    _ => {},
                }
            },
            ExprLit(ref lit) => {
                match lit.node {
                    LitKind::Bool(true) => return Ok(Bool::True),
                    LitKind::Bool(false) => return Ok(Bool::False),
                    _ => {},
                }
            },
            _ => {},
        }
        let n = self.0.len();
        self.0.push(e);
        if n < 32 {
            #[allow(cast_possible_truncation)]
            Ok(Bool::Term(n as u8))
        } else {
            Err("too many literals".to_owned())
        }
    }
}

fn suggest(cx: &LateContext, suggestion: &Bool, terminals: &[&Expr]) -> String {
    fn recurse(brackets: bool, cx: &LateContext, suggestion: &Bool, terminals: &[&Expr], mut s: String) -> String {
        use quine_mc_cluskey::Bool::*;
        match *suggestion {
            True => {
                s.extend("true".chars());
                s
            },
            False => {
                s.extend("false".chars());
                s
            },
            Not(ref inner) => {
                s.push('!');
                recurse(true, cx, inner, terminals, s)
            },
            And(ref v) => {
                if brackets {
                    s.push('(');
                }
                s = recurse(true, cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" && ".chars());
                    s = recurse(true, cx, inner, terminals, s);
                }
                if brackets {
                    s.push(')');
                }
                s
            },
            Or(ref v) => {
                if brackets {
                    s.push('(');
                }
                s = recurse(true, cx, &v[0], terminals, s);
                for inner in &v[1..] {
                    s.extend(" || ".chars());
                    s = recurse(true, cx, inner, terminals, s);
                }
                if brackets {
                    s.push(')');
                }
                s
            },
            Term(n) => {
                s.extend(snippet_opt(cx, terminals[n as usize].span).expect("don't try to improve booleans created by macros").chars());
                s
            }
        }
    }
    recurse(false, cx, suggestion, terminals, String::new())
}

impl<'a, 'tcx> NonminimalBoolVisitor<'a, 'tcx> {
    fn bool_expr(&self, e: &Expr) {
        let mut h2q = Hir2Qmm(Vec::new());
        if let Ok(expr) = h2q.run(e) {
            let simplified = expr.simplify();
            if !simplified.iter().any(|s| *s == expr) {
                span_lint_and_then(self.0, NONMINIMAL_BOOL, e.span, "this boolean expression can be simplified", |db| {
                    for suggestion in &simplified {
                        db.span_suggestion(e.span, "try", suggest(self.0, suggestion, &h2q.0));
                    }
                });
            }
        }
    }
}

impl<'a, 'v, 'tcx> Visitor<'v> for NonminimalBoolVisitor<'a, 'tcx> {
    fn visit_expr(&mut self, e: &'v Expr) {
        if in_macro(self.0, e.span) { return }
        match e.node {
            ExprBinary(binop, _, _) if binop.node == BiOr || binop.node == BiAnd => self.bool_expr(e),
            ExprUnary(UnNot, ref inner) => {
                if self.0.tcx.node_types()[&inner.id].is_bool() {
                    self.bool_expr(e);
                } else {
                    walk_expr(self, e);
                }
            },
            _ => walk_expr(self, e),
        }
    }
}
<|endoftext|>


<commit_before>//! Chat API implementation.
use std::cmp;
use std::str::{self, FromStr};
use std::sync::Arc;
use std::borrow::Cow;
use std::time::{Instant, Duration};

use futures::{Future};
use futures::sync::mpsc::{UnboundedSender as Sender};
use tokio_core::reactor::Handle;
use minihttp::server::{Request};
use minihttp::{OptFuture};
use minihttp::enums::{Version};
use minihttp::client::{Error};
use rustc_serialize::json::{self, Json};

use intern::SessionId;
use websocket::Base64;
use config::{Config, SessionPool, InactivityTimeouts};
use config::chat::Chat;
use super::{Cid, ProcessorPool};
use super::{serialize_cid};
use super::processor::{Action, ConnectionMessage, PoolMessage};
use super::message::{self, Meta, Args, Kwargs};
use super::error::MessageError;
use http_pools::HttpPools;
use json_requests::request_fn_buffered;

// TODO: make ChatAPI Pool
//  bound to session pool config

const INACTIVITY_PAYLOAD: &'static [u8] = b"[{}, [], {}]";

pub struct ChatAPI {
    // shared between connections
    client: HttpPools,
    chat_config: Arc<Chat>,      // singleton per handler endpoint;
    proc_pool: ProcessorPool,   // singleton per handler endpoint;
    inactivity_timeouts: Arc<InactivityTimeouts>,
}

pub struct SessionAPI {
    api: ChatAPI,

    session_id: SessionId,
    auth_token: String,
    conn_id: Cid,   // connection id should not be used here;
    channel: Sender<ConnectionMessage>,
}

impl ChatAPI {

    pub fn new(http_client: HttpPools, chat: Arc<Chat>,
        proc_pool: ProcessorPool, inactivity_timeouts: Arc<InactivityTimeouts>)
        -> ChatAPI
    {
        ChatAPI {
            client: http_client,
            chat_config: chat,
            proc_pool: proc_pool,
            inactivity_timeouts: inactivity_timeouts,
        }
    }

    /// Make instance of Session API (api bound to cid/ssid/tx-channel)
    /// and associate this session with ws connectionuthor
    /// (send `Action::Associate`)
    pub fn session_api(self, session_id: SessionId, conn_id: Cid,
        userinfo: Json, mut channel: Sender<ConnectionMessage>)
        -> SessionAPI
    {

        let userinfo = Arc::new(userinfo);
        channel.send(ConnectionMessage::Hello(userinfo.clone()))
        .expect("message sent");

        self.proc_pool.send(Action::Associate {
            conn_id: conn_id,
            session_id: session_id.clone(),
            metadata: userinfo,
        });

        SessionAPI {
            api: self,
            auth_token: encode_sid(&session_id),
            session_id: session_id,
            conn_id: conn_id,
            channel: channel,
        }
    }

    /// API call to backend.
    fn post(&mut self, method: &str, auth: String, payload: String)
        -> OptFuture<Json, MessageError>
    {
        let dest = self.chat_config.message_handlers.resolve(method);
        // TODO(tailhook) replace here can be optimized
        let path = format!("{}{}", dest.path, method.replace(".", "/"));
        request_fn_buffered(self.client.upstream(&dest.upstream),
            move |mut e| {
                e.request_line("POST", &path, Version::Http11);
                e.add_header("Content-Type", "application/json").unwrap();
                e.add_header("Authorization", auth).unwrap();
                e.add_length(payload.as_bytes().len() as u64).unwrap();
                e.done_headers().unwrap();
                e.write_body(payload.as_bytes());
                e.done().into()
            })
    }

    /// Update session activity timeout.
    fn update_activity(&self, conn_id: Cid, seconds: Duration) {
        let timestamp = Instant::now() + seconds;
        self.proc_pool.send(Action::UpdateActivity {
            conn_id: conn_id,
            timestamp: timestamp,
        })
    }
}

// only difference from ChatAPI -> Bound to concrete SessionId
impl SessionAPI {

    /// Send disconnect to processor.
    pub fn disconnect(&self) {
        self.api.proc_pool.send(Action::Disconnect { conn_id: self.conn_id });
    }

    /// 'Session active' notification for chat processor.
    pub fn update_activity(&self, sec: Option<u64>) {
        let normalized = match sec {
            Some(v) => {
                let v = Duration::from_secs(v);
                let min = *self.api.inactivity_timeouts.client_min;
                let max = *self.api.inactivity_timeouts.client_max;
                cmp::max(cmp::min(v, max), min)
            }
            None => {
                *self.api.inactivity_timeouts.client_default
            }
        };
        self.api.update_activity(self.conn_id.clone(), normalized)
    }

    /// Backend method call.
    pub fn method_call(&mut self, method: String, mut meta: Meta,
        args: &Args, kwargs: &Kwargs, handle: &Handle)
    {
        let mut tx = self.channel.clone();
        meta.insert("connection_id".to_string(),
            Json::String(serialize_cid(&self.conn_id)));
        let payload = message::encode_call(&meta, &args, &kwargs);
        let call = self.api.post(method.as_str(),
            // TODO(tailhook) optimize this clone?
            self.auth_token.clone(), payload);
        handle.spawn(call
            .then(move |result| {
                meta.remove(&"connection_id".to_string());
                let res = match result {
                    Ok(json) => tx.send(ConnectionMessage::Result(meta, json)),
                    Err(err) => {
                        err.update_meta(&mut meta);
                        tx.send(ConnectionMessage::Error(meta, err))
                    }
                };
                res.map_err(|e| info!("Remote send error: {:?}", e))
            })
        );
    }
}

pub struct MaintenanceAPI {
    config: Arc<Config>,
    sessions_cfg: Arc<SessionPool>,
    http_client: HttpPools,
    handle: Handle,
}

impl MaintenanceAPI {

    pub fn new(cfg: Arc<Config>, sessions_cfg: Arc<SessionPool>,
        http_client: HttpPools, handle: Handle)
        -> MaintenanceAPI
    {
        MaintenanceAPI {
            config: cfg,
            sessions_cfg: sessions_cfg,
            http_client: http_client,
            handle: handle,
        }
    }

    pub fn handle(&self, message: PoolMessage) {
        use super::processor::PoolMessage::*;
        match message {
            InactiveSession { session_id, .. } => {
                info!("Send inactivity: {:?}", session_id);

                let auth = encode_sid(&session_id);

                for dest in &self.sessions_cfg.inactivity_handlers {
                    let path: Cow<_> = if dest.path == "/" {
                        "/tangle/session_inactive".into()
                    } else {
                        (dest.path.to_string() +
                            "/tangle/session_inactive").into()
                    };
                    // TODO(tailhook) optimize this auth.clone()
                    let auth = auth.clone();
                    self.handle.spawn(request_fn_buffered(
                        self.http_client
                            .upstream(&dest.upstream),
                        move |mut e| {
                            e.request_line("POST", &path, Version::Http11);
                            e.add_header("Content-Type", "application/json")
                                .unwrap();
                            e.add_header("Authorization", auth).unwrap();
                            e.add_length(INACTIVITY_PAYLOAD.len() as u64)
                                .unwrap();
                            e.done_headers().unwrap();
                            e.write_body(INACTIVITY_PAYLOAD);
                            e.done()
                        })
                        .map(|r| info!("Resp data: {}", r))
                        .map_err(|e: MessageError| {
                            info!("Error sending inactivity {}", e)
                        })
                    );
                }
            }
        }
    }
}

fn encode_sid(s: &SessionId) -> String {
    #[derive(RustcEncodable)]
    struct Auth<'a> {
        user_id: &'a SessionId,
    }
    format!("Tangle {}", Base64(json::encode(&Auth {
        user_id: s,
    }).unwrap().as_bytes()))
}
<commit_msg>Removes old unused api.rs<commit_after><|endoftext|>


<commit_before>use byteorder::{ByteOrder, LittleEndian};
use log::{debug};
use goblin::{Object};
use failure::{Error, Fail};

use super::super::super::arch::{RVA};
use super::super::super::workspace::Workspace;
use super::super::{Analyzer};

#[derive(Debug, Fail)]
pub enum RelocAnalyzerError {
    #[fail(display = "Invalid relocation type")]
    InvalidRelocType,
}

pub struct RelocAnalyzer {}

impl RelocAnalyzer {
    pub fn new() -> RelocAnalyzer {
        RelocAnalyzer {}
    }
}

struct Section {
    start: RVA,
    end: RVA,
}

fn is_in_insn(ws: &Workspace, rva: RVA) -> bool {
    let start: usize = rva.into();
    // TODO: underflow
    // TODO: remove harded max insn length
    let end: usize = start - 0x10;

    for i in (start..end).rev() {
        let i = RVA::from(i);
        if let Some(meta) = ws.get_meta(i) {
            if !meta.is_insn() {
                continue;
            }

            if let Ok(len) = meta.get_insn_length() {
                if i + len > rva {
                    return true;
                }
            }
        }
    }
    return false;
}

fn is_ptr(ws: &Workspace, rva: RVA) -> bool {
    if let Ok(ptr) = ws.read_va(rva) {
        if let Some(ptr) = ws.rva(ptr) {
            return ws.probe(ptr, 1);
        }
    }
    return false;
}

pub enum RelocationType {
    ImageRelBasedAbsolute,
    ImageRelBasedHigh,
    ImageRelBasedLow,
    ImageRelBasedHighLow,
    ImageRelBasedHighAdj,

    // ImageRelBasedMIPS_JmpAddr,
    // ImageRelBasedARM_MOV32,
    // ImageRelBasedRiscV_High20,
    ImageRelArch1,

    ImageRelReserved,

    // ImageRelBasedTHUMB_MOV32,
    // ImageRelBasedRiscV_Low12I,
    ImageRelArch2,

    ImageRelBasedRiscVLow12S,
    ImageRelBasedMIPSJmpAddr16,
    ImageRelBasedDir64,
}

pub struct Reloc {
    pub typ: RelocationType,
    pub offset: RVA,
}

fn parse_reloc(base: RVA, entry: u16) -> Result<Reloc, Error> {
    let reloc_type   = (entry & 0b1111000000000000) >> 12;
    let reloc_offset =  entry & 0b0000111111111111;

    // TODO: this should probably be on `RelocationType` as a `From` trait.
    let reloc_type = match reloc_type {
        0 => RelocationType::ImageRelBasedAbsolute,
        1 => RelocationType::ImageRelBasedHigh,
        2 => RelocationType::ImageRelBasedLow,
        3 => RelocationType::ImageRelBasedHighLow,
        4 => RelocationType::ImageRelBasedHighAdj,
        5 => RelocationType::ImageRelArch1,
        6 => RelocationType::ImageRelReserved,
        7 => RelocationType::ImageRelArch2,
        8 => RelocationType::ImageRelBasedRiscVLow12S,
        9 => RelocationType::ImageRelBasedMIPSJmpAddr16,
        10 => RelocationType::ImageRelBasedDir64,
        _ => return Err(RelocAnalyzerError::InvalidRelocType.into()),
    };

    Ok(Reloc {
        typ: reloc_type,
        offset: base + RVA::from(reloc_offset as i64),
    })
}

fn split_u32(e: u32) -> (u16, u16) {
    let m = ((e & 0x0000FFFF) >>  0) as u16;
    let n = ((e & 0xFFFF0000) >> 16) as u16;
    (m, n)
}

/// ```
/// use lancelot::rsrc::*;
/// use lancelot::arch::*;
/// use lancelot::workspace::Workspace;
/// use lancelot::analysis::pe::relocs;
///
/// let mut ws = Workspace::from_bytes("k32.dll", &get_buf(Rsrc::K32))
///    .disable_analysis()
///    .load().unwrap();
/// let relocs = relocs::get_relocs(&ws).unwrap();
/// assert_eq!(relocs[0].offset,   RVA(0x76008));
/// assert_eq!(relocs[277].offset, RVA(0xA8000));
/// ```
pub fn get_relocs(ws: &Workspace) -> Result<Vec<Reloc>, Error> {
    let pe = match Object::parse(&ws.buf) {
        Ok(Object::PE(pe)) => pe,
        _ => return Ok(vec![]),
    };

    let opt_header = match pe.header.optional_header {
        Some(opt_header) => opt_header,
        _ => return Ok(vec![]),
    };

    let reloc_directory = match opt_header.data_directories.get_base_relocation_table() {
        Some(reloc_directory) => reloc_directory,
        _ => return Ok(vec![]),
    };

    let dir_start = RVA::from(reloc_directory.virtual_address as i64);
    let buf = ws.read_bytes(dir_start, reloc_directory.size as usize)?;

    let entries: Vec<u32> = buf
        .chunks_exact(0x4)
        .map(|b| LittleEndian::read_u32(b))
        .collect();

    let mut ret = vec![];
    let mut index = 0;
    loop {
        // parse base relocation chunk
        // until there's no data left

        let page_rva = entries.get(index);
        let block_size = entries.get(index+1);
        let (page_rva, block_size) = match (page_rva, block_size) {
            (Some(0),        _               ) => break,
            (_,              Some(0)         ) => break,
            (Some(page_rva), Some(block_size)) => (RVA::from(*page_rva as i64), *block_size),
            _ => break,
        };

        // cast from u32 to usize
        let chunk_entries_count = ((block_size) / 4) as usize;

        for i in 2..chunk_entries_count {
            if let Some(&entry) = entries.get(index + i) {
                let (m, n) = split_u32(entry);

                let reloc1 = parse_reloc(page_rva, m)?;
                if !ws.probe(reloc1.offset, 4) {
                    break
                }
                ret.push(reloc1);

                let reloc2 = parse_reloc(page_rva, n)?;
                if !ws.probe(reloc2.offset, 4) {
                    break
                }
                ret.push(reloc2);
            } else {
                break
            }
        };

        index += chunk_entries_count;
    }

    Ok(ret)
}

impl Analyzer for RelocAnalyzer {
    fn get_name(&self) -> String {
        "PE relocation analyzer".to_string()
    }

    /// ```
    /// use lancelot::rsrc::*;
    /// use lancelot::arch::*;
    /// use lancelot::analysis::Analyzer;
    /// use lancelot::workspace::Workspace;
    /// use lancelot::analysis::pe::RelocAnalyzer;
    ///
    /// let mut ws = Workspace::from_bytes("k32.dll", &get_buf(Rsrc::K32))
    ///    .disable_analysis()
    ///    .load().unwrap();
    /// let anal = RelocAnalyzer::new();
    /// anal.analyze(&mut ws).unwrap();
    /// let meta = ws.get_meta(RVA(0xC7F0)).unwrap();
    /// assert!(meta.is_insn());
    /// ```
    fn analyze(&self, ws: &mut Workspace)-> Result<(), Error> {
        let text_section = match ws.module.sections.iter()
            // currently limited to the text section.
            // TODO: accept any writable section.
            .filter(|&sec| sec.name == ".text")
            .next() {
                None => return Ok(()),
                Some(s) => s,
            };

        let text_bounds = Section {
            start: text_section.addr,
            end: text_section.addr + RVA::from(text_section.buf.len()),
        };

        // scan the relocations
        // looking for pointers into the .text section
        // to things that
        //   1. are not already in an instruction
        //   2. don't appear to be a pointer
        // and assume this is code.
        let o: Vec<RVA> = get_relocs(ws)?
            .iter()
            .map(|reloc| reloc.offset)
            .map(|rva| ws.read_va(rva))
            .filter_map(Result::ok)
            .filter_map(|va| ws.rva(va))
            .filter(|&rva| text_bounds.start <= rva)
            .filter(|&rva| rva < text_bounds.end)
            .filter(|&rva| !is_in_insn(ws, rva))
            .filter(|&rva| !is_ptr(ws, rva))
            // TODO: maybe ensure that the insn decodes.
            .collect();

        o.iter().for_each(|&rva| {
            debug!("found ptr from .text section to .text section at {:#x}", rva);

            // TODO: consume result
            ws.make_insn(rva).unwrap();
            // TODO: consume result
            ws.analyze().unwrap();
        });
        Ok(())
    }
}
<commit_msg>relocs: improve performance<commit_after>use byteorder::{ByteOrder, LittleEndian};
use log::{debug};
use goblin::{Object};
use failure::{Error, Fail};

use super::super::super::arch::{RVA};
use super::super::super::loader::Permissions;
use super::super::super::workspace::Workspace;
use super::super::{Analyzer};
use std::collections::{HashSet};

#[derive(Debug, Fail)]
pub enum RelocAnalyzerError {
    #[fail(display = "Invalid relocation type")]
    InvalidRelocType,
}

pub struct RelocAnalyzer {}

impl RelocAnalyzer {
    pub fn new() -> RelocAnalyzer {
        RelocAnalyzer {}
    }
}

struct Section {
    start: RVA,
    end: RVA,
}

// TODO: make this much faster
fn is_in_insn(ws: &Workspace, rva: RVA) -> bool {
    let start: usize = rva.into();
    // TODO: underflow
    // TODO: remove harded max insn length
    let end: usize = start - 0x10;

    for i in (start..end).rev() {
        let i = RVA::from(i);
        if let Some(meta) = ws.get_meta(i) {
            if !meta.is_insn() {
                continue;
            }

            if let Ok(len) = meta.get_insn_length() {
                if i + len > rva {
                    return true;
                }
            }
        }
    }
    return false;
}

fn is_ptr(ws: &Workspace, rva: RVA) -> bool {
    if let Ok(ptr) = ws.read_va(rva) {
        if let Some(ptr) = ws.rva(ptr) {
            return ws.probe(ptr, 1);
        }
    }
    return false;
}

pub enum RelocationType {
    ImageRelBasedAbsolute,
    ImageRelBasedHigh,
    ImageRelBasedLow,
    ImageRelBasedHighLow,
    ImageRelBasedHighAdj,

    // ImageRelBasedMIPS_JmpAddr,
    // ImageRelBasedARM_MOV32,
    // ImageRelBasedRiscV_High20,
    ImageRelArch1,

    ImageRelReserved,

    // ImageRelBasedTHUMB_MOV32,
    // ImageRelBasedRiscV_Low12I,
    ImageRelArch2,

    ImageRelBasedRiscVLow12S,
    ImageRelBasedMIPSJmpAddr16,
    ImageRelBasedDir64,
}

pub struct Reloc {
    pub typ: RelocationType,
    pub offset: RVA,
}

fn parse_reloc(base: RVA, entry: u16) -> Result<Reloc, Error> {
    let reloc_type   = (entry & 0b1111000000000000) >> 12;
    let reloc_offset =  entry & 0b0000111111111111;

    // TODO: this should probably be on `RelocationType` as a `From` trait.
    let reloc_type = match reloc_type {
        0 => RelocationType::ImageRelBasedAbsolute,
        1 => RelocationType::ImageRelBasedHigh,
        2 => RelocationType::ImageRelBasedLow,
        3 => RelocationType::ImageRelBasedHighLow,
        4 => RelocationType::ImageRelBasedHighAdj,
        5 => RelocationType::ImageRelArch1,
        6 => RelocationType::ImageRelReserved,
        7 => RelocationType::ImageRelArch2,
        8 => RelocationType::ImageRelBasedRiscVLow12S,
        9 => RelocationType::ImageRelBasedMIPSJmpAddr16,
        10 => RelocationType::ImageRelBasedDir64,
        _ => return Err(RelocAnalyzerError::InvalidRelocType.into()),
    };

    Ok(Reloc {
        typ: reloc_type,
        offset: base + RVA::from(reloc_offset as i64),
    })
}

fn split_u32(e: u32) -> (u16, u16) {
    let m = ((e & 0x0000FFFF) >>  0) as u16;
    let n = ((e & 0xFFFF0000) >> 16) as u16;
    (m, n)
}

/// ```
/// use lancelot::rsrc::*;
/// use lancelot::arch::*;
/// use lancelot::workspace::Workspace;
/// use lancelot::analysis::pe::relocs;
///
/// let mut ws = Workspace::from_bytes("k32.dll", &get_buf(Rsrc::K32))
///    .disable_analysis()
///    .load().unwrap();
/// let relocs = relocs::get_relocs(&ws).unwrap();
/// assert_eq!(relocs[0].offset,   RVA(0x76008));
/// assert_eq!(relocs[277].offset, RVA(0xA8000));
/// ```
pub fn get_relocs(ws: &Workspace) -> Result<Vec<Reloc>, Error> {
    let pe = match Object::parse(&ws.buf) {
        Ok(Object::PE(pe)) => pe,
        _ => return Ok(vec![]),
    };

    let opt_header = match pe.header.optional_header {
        Some(opt_header) => opt_header,
        _ => return Ok(vec![]),
    };

    let reloc_directory = match opt_header.data_directories.get_base_relocation_table() {
        Some(reloc_directory) => reloc_directory,
        _ => return Ok(vec![]),
    };

    let dir_start = RVA::from(reloc_directory.virtual_address as i64);
    let buf = ws.read_bytes(dir_start, reloc_directory.size as usize)?;

    let entries: Vec<u32> = buf
        .chunks_exact(0x4)
        .map(|b| LittleEndian::read_u32(b))
        .collect();

    let mut ret = vec![];
    let mut index = 0;
    loop {
        // parse base relocation chunk
        // until there's no data left

        let page_rva = entries.get(index);
        let block_size = entries.get(index+1);
        let (page_rva, block_size) = match (page_rva, block_size) {
            (Some(0),        _               ) => break,
            (_,              Some(0)         ) => break,
            (Some(page_rva), Some(block_size)) => (RVA::from(*page_rva as i64), *block_size),
            _ => break,
        };

        // cast from u32 to usize
        let chunk_entries_count = ((block_size) / 4) as usize;

        for i in 2..chunk_entries_count {
            if let Some(&entry) = entries.get(index + i) {
                let (m, n) = split_u32(entry);

                let reloc1 = parse_reloc(page_rva, m)?;
                if !ws.probe(reloc1.offset, 4) {
                    break
                }
                ret.push(reloc1);

                let reloc2 = parse_reloc(page_rva, n)?;
                if !ws.probe(reloc2.offset, 4) {
                    break
                }
                ret.push(reloc2);
            } else {
                break
            }
        };

        index += chunk_entries_count;
    }

    Ok(ret)
}

fn sections_contain(sections: &[Section], rva: RVA) -> bool {
    sections.iter().find(|section| section.start <= rva && section.end < rva).is_some()
}

impl Analyzer for RelocAnalyzer {
    fn get_name(&self) -> String {
        "PE relocation analyzer".to_string()
    }

    /// ```
    /// use lancelot::rsrc::*;
    /// use lancelot::arch::*;
    /// use lancelot::analysis::Analyzer;
    /// use lancelot::workspace::Workspace;
    /// use lancelot::analysis::pe::RelocAnalyzer;
    ///
    /// let mut ws = Workspace::from_bytes("k32.dll", &get_buf(Rsrc::K32))
    ///    .disable_analysis()
    ///    .load().unwrap();
    /// let anal = RelocAnalyzer::new();
    /// anal.analyze(&mut ws).unwrap();
    /// let meta = ws.get_meta(RVA(0xC7F0)).unwrap();
    /// assert!(meta.is_insn());
    /// ```
    fn analyze(&self, ws: &mut Workspace)-> Result<(), Error> {
        let x_sections: Vec<Section> = ws.module.sections.iter()
            .filter(|section| section.perms.intersects(Permissions::X))
            .map(|section| Section {
                start: section.addr,
                end: section.addr + RVA::from(section.buf.len()),
            })
            .collect();

        let relocs = get_relocs(ws)?;
        debug!("found {} total relocs", relocs.len());

        let mut unique_targets: HashSet<RVA> = HashSet::new();
        unique_targets.extend(relocs
            .iter()
            .map(|reloc| reloc.offset)
            .map(|rva| ws.read_va(rva))
            .filter_map(Result::ok)
            .filter_map(|va| ws.rva(va)));

        debug!("reduced to {} unique reloc targets", unique_targets.len());

        // scan the relocations
        // looking for pointers into the .text section
        // to things that
        //   1. are not already in an instruction
        //   2. don't appear to be a pointer
        // and assume this is code.
        let o: Vec<RVA> = unique_targets
            .iter()
            .filter(|&&rva| sections_contain(&x_sections, rva))
            .filter(|&&rva| !is_in_insn(ws, rva))
            .filter(|&&rva| !is_ptr(ws, rva))
            .map(|&rva| rva)
            // TODO: maybe ensure that the insn decodes.
            .collect();

        println!("found {} relocs that point to instructions", o.len());

        o.iter().for_each(|&rva| {
            debug!("found ptr from .text section to .text section at {:#x}", rva);

            // TODO: consume result
            ws.make_insn(rva).unwrap();
            // TODO: consume result
            ws.analyze().unwrap();
        });
        Ok(())
    }
}
<|endoftext|>