<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(path_ext)]
#![feature(rustc_private)]
#![cfg(not(test))]

#[macro_use]
extern crate log;
extern crate rustfmt;
extern crate toml;

use rustfmt::{WriteMode, run};
use rustfmt::config::Config;

use std::env;
use std::fs::{File, PathExt};
use std::io::{self, Read};
use std::path::PathBuf;
use std::str::FromStr;

// Try to find a project file in the current directory and its parents.
fn lookup_project_file() -> io::Result<PathBuf> {
    let mut current = try!(env::current_dir());
    loop {
        let config_file = current.join("rustfmt.toml");
        if config_file.exists() {
            return Ok(config_file);
        } else {
            current = match current.parent() {
                // if the current directory has no parent, we're done searching
                None => return Err(io::Error::new(io::ErrorKind::NotFound, "config not found")),
                Some(path) => path.to_path_buf(),
            };
        }
    }
}

// Try to find a project file. If it's found, read it.
fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> {
    let path = try!(lookup_project_file());
    let mut file = try!(File::open(&path));
    let mut toml = String::new();
    try!(file.read_to_string(&mut toml));
    Ok((path, toml))
}

fn execute() -> i32 {
    let (args, write_mode) = match determine_params(std::env::args()) {
        Some((args, write_mode)) => (args, write_mode),
        None => return 1,
    };

    let config = match lookup_and_read_project_file() {
        Ok((path, toml)) => {
            println!("Project config file: {}", path.display());
            Config::from_toml(&toml)
        }
        Err(_) => Default::default(),
    };

    run(args, write_mode, Box::new(config));
    0
}

fn main() {
    use std::io::Write;
    let exit_code = execute();
    // Make sure standard output is flushed before we exit
    std::io::stdout().flush().unwrap();
    // Exit with given exit code.
    //
    // NOTE: This immediately terminates the process without doing any cleanup,
    // so make sure to finish all necessary cleanup before this is called.
    std::process::exit(exit_code);
}

fn print_usage<S: Into<String>>(reason: S) {
    println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[true/false]] <file_name>", reason.into());
}

fn determine_params<I>(args: I) -> Option<(Vec<String>, WriteMode)>
    where I: Iterator<Item = String>
{
    let arg_prefix = "-";
    let write_mode_prefix = "--write-mode=";
    let help_mode = "-h";
    let long_help_mode = "--help";
    let mut write_mode = WriteMode::Replace;
    let mut rustc_args = Vec::new();

    // The NewFile option currently isn't supported because it requires another
    // parameter, but it can be added later.
    for arg in args {
        if arg.starts_with(write_mode_prefix) {
            match FromStr::from_str(&arg[write_mode_prefix.len()..]) {
                Ok(mode) => write_mode = mode,
                Err(_) => {
                    print_usage("Unrecognized write mode");
                    return None;
                }
            }
        } else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) {
            print_usage("");
            return None;
        } else if arg.starts_with(arg_prefix) {
            print_usage("Invalid argument");
            return None;
        } else {
            // Pass everything else to rustc
            rustc_args.push(arg);
        }
    }

    if rustc_args.len() < 2 {
        print_usage("Please provide a file to be formatted");
        return None;
    }

    Some((rustc_args, write_mode))
}
<commit_msg>Simplify match expression<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(path_ext)]
#![feature(rustc_private)]
#![cfg(not(test))]

#[macro_use]
extern crate log;
extern crate rustfmt;
extern crate toml;

use rustfmt::{WriteMode, run};
use rustfmt::config::Config;

use std::env;
use std::fs::{File, PathExt};
use std::io::{self, Read};
use std::path::PathBuf;
use std::str::FromStr;

// Try to find a project file in the current directory and its parents.
fn lookup_project_file() -> io::Result<PathBuf> {
    let mut current = try!(env::current_dir());
    loop {
        let config_file = current.join("rustfmt.toml");
        if config_file.exists() {
            return Ok(config_file);
        } else {
            current = match current.parent() {
                // if the current directory has no parent, we're done searching
                None => return Err(io::Error::new(io::ErrorKind::NotFound, "config not found")),
                Some(path) => path.to_path_buf(),
            };
        }
    }
}

// Try to find a project file. If it's found, read it.
fn lookup_and_read_project_file() -> io::Result<(PathBuf, String)> {
    let path = try!(lookup_project_file());
    let mut file = try!(File::open(&path));
    let mut toml = String::new();
    try!(file.read_to_string(&mut toml));
    Ok((path, toml))
}

fn execute() -> i32 {
    let (args, write_mode) = match determine_params(std::env::args()) {
        Some(params) => params,
        None => return 1,
    };

    let config = match lookup_and_read_project_file() {
        Ok((path, toml)) => {
            println!("Project config file: {}", path.display());
            Config::from_toml(&toml)
        }
        Err(_) => Default::default(),
    };

    run(args, write_mode, Box::new(config));
    0
}

fn main() {
    use std::io::Write;
    let exit_code = execute();
    // Make sure standard output is flushed before we exit
    std::io::stdout().flush().unwrap();
    // Exit with given exit code.
    //
    // NOTE: This immediately terminates the process without doing any cleanup,
    // so make sure to finish all necessary cleanup before this is called.
    std::process::exit(exit_code);
}

fn print_usage<S: Into<String>>(reason: S) {
    println!("{}\n\r usage: rustfmt [-h Help] [--write-mode=[true/false]] <file_name>", reason.into());
}

fn determine_params<I>(args: I) -> Option<(Vec<String>, WriteMode)>
    where I: Iterator<Item = String>
{
    let arg_prefix = "-";
    let write_mode_prefix = "--write-mode=";
    let help_mode = "-h";
    let long_help_mode = "--help";
    let mut write_mode = WriteMode::Replace;
    let mut rustc_args = Vec::new();

    // The NewFile option currently isn't supported because it requires another
    // parameter, but it can be added later.
    for arg in args {
        if arg.starts_with(write_mode_prefix) {
            match FromStr::from_str(&arg[write_mode_prefix.len()..]) {
                Ok(mode) => write_mode = mode,
                Err(_) => {
                    print_usage("Unrecognized write mode");
                    return None;
                }
            }
        } else if arg.starts_with(help_mode) || arg.starts_with(long_help_mode) {
            print_usage("");
            return None;
        } else if arg.starts_with(arg_prefix) {
            print_usage("Invalid argument");
            return None;
        } else {
            // Pass everything else to rustc
            rustc_args.push(arg);
        }
    }

    if rustc_args.len() < 2 {
        print_usage("Please provide a file to be formatted");
        return None;
    }

    Some((rustc_args, write_mode))
}
<|endoftext|>


<commit_before>use std::io;
use std::io::Write;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use na::Point2;

#[derive(Debug)]
pub struct Block {
    start: Point2<usize>,
    current: Point2<usize>,
    end: Point2<usize>,
}

impl Block {
    fn new(start: (usize, usize), size: usize) -> Block {
        Block {
            start: Point2::new(start.0, start.1),
            current: Point2::new(start.0, start.1),
            end: Point2::new(start.0 + size - 1, start.1 + size - 1),
        }
    }
}

impl Iterator for Block {
    type Item = Point2<usize>;

    fn next(&mut self) -> Option<Point2<usize>> {
        if self.current.x > self.end.x || self.current.y > self.end.y {
            None
        } else {

            let cur = self.current;

            if self.current.x == self.end.x {
                self.current.x = self.start.x;
                self.current.y += 1;
            } else {
                self.current.x += 1;
            }

            Some(cur)
        }
    }
}

pub struct BlockQueue {
    dims: (usize, usize),
    block_size: usize,
    counter: AtomicUsize,
    pub num_blocks: usize,
}

impl BlockQueue {
    pub fn new(dims: (usize, usize), block_size: usize) -> BlockQueue {
        BlockQueue {
            dims: dims,
            block_size: block_size,
            counter: ATOMIC_USIZE_INIT,
            num_blocks: (dims.0 / block_size) * (dims.1 / block_size),
        }
    }

    pub fn next(&self) -> Option<Block> {
        let c = self.counter.fetch_add(1, Ordering::AcqRel);
        if c >= self.num_blocks {
            None
        } else {
            let num_blocks_width = self.dims.0 / self.block_size;
            Some(Block::new((c % num_blocks_width * self.block_size,
                             c / num_blocks_width * self.block_size),
                            self.block_size))
        }
    }

    pub fn report_progress(&self) {
        print!("\rRendering block {}/{}...  ",
               self.counter.load(Ordering::Relaxed),
               self.num_blocks);
        io::stdout().flush().expect("Could not flush stdout");;
    }
}
<commit_msg>Add block.area() method<commit_after>use std::io;
use std::io::Write;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

use na::Point2;

#[derive(Debug)]
pub struct Block {
    start: Point2<usize>,
    current: Point2<usize>,
    end: Point2<usize>,
}

impl Block {
    pub fn new(start: (usize, usize), size: usize) -> Block {
        Block {
            start: Point2::new(start.0, start.1),
            current: Point2::new(start.0, start.1),
            end: Point2::new(start.0 + size, start.1 + size),
        }
    }

    pub fn area(&self) -> usize {
        (self.end.x - self.start.x) * (self.end.y - self.start.y)
    }
}

impl Iterator for Block {
    type Item = Point2<usize>;

    fn next(&mut self) -> Option<Point2<usize>> {
        if self.current.x >= self.end.x || self.current.y >= self.end.y {
            None
        } else {

            let cur = self.current;

            if self.current.x == self.end.x - 1 {
                self.current.x = self.start.x;
                self.current.y += 1;
            } else {
                self.current.x += 1;
            }

            Some(cur)
        }
    }
}

pub struct BlockQueue {
    dims: (usize, usize),
    block_size: usize,
    counter: AtomicUsize,
    pub num_blocks: usize,
}

impl BlockQueue {
    pub fn new(dims: (usize, usize), block_size: usize) -> BlockQueue {
        BlockQueue {
            dims: dims,
            block_size: block_size,
            counter: ATOMIC_USIZE_INIT,
            num_blocks: (dims.0 / block_size) * (dims.1 / block_size),
        }
    }

    pub fn next(&self) -> Option<Block> {
        let c = self.counter.fetch_add(1, Ordering::AcqRel);
        if c >= self.num_blocks {
            None
        } else {
            let num_blocks_width = self.dims.0 / self.block_size;
            Some(Block::new((c % num_blocks_width * self.block_size,
                             c / num_blocks_width * self.block_size),
                            self.block_size))
        }
    }

    pub fn report_progress(&self) {
        print!("\rRendering block {}/{}...  ",
               self.counter.load(Ordering::Relaxed),
               self.num_blocks);
        io::stdout().flush().expect("Could not flush stdout");;
    }
}

#[test]
fn test_area() {
    let block = Block::new((12, 12), 8);
    assert_eq!(block.area(), 64);
}

#[test]
fn test_iter() {
    let block = Block::new((12, 12), 8);
    let pixels: Vec<Point2<usize>> = block.into_iter().collect();

    assert_eq!(pixels.len(), 64);
    assert_eq!(pixels[0].x, 12);
    assert_eq!(pixels[0].y, 12);
    assert_eq!(pixels[63].x, 19);
    assert_eq!(pixels[63].y, 19);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::fmt;
use std::ops::{Deref, DerefMut};
use std::iter::FromIterator;
use std::char;

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Stone {
    Empty,
    White,
    Black,
}

impl Default for Stone {
    fn default() -> Stone {
        Stone::Empty
    }
}

impl fmt::Display for Stone {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}",
               match *self {
                   Stone::Empty => ".",
                   Stone::White => "O",
                   Stone::Black => "X",
               })
    }
}
#[derive(Clone, Copy, Debug)]
pub struct Point {
    pub x: u32,
    pub y: u32,
}

#[derive(Copy, Clone)]
pub struct BoardMarker {
    pub point: Point,
    pub color: Stone,
}

impl fmt::Debug for BoardMarker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "|[{:>2}, {} ]{:?}|", ((self.point.x as u8 + 65u8) as char), self.point.y, self.color)
    }
}

impl fmt::Display for BoardMarker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}",
               match self.color {
                   Stone::Empty => ".",
                   Stone::White => "O",
                   Stone::Black => "X",
               })
    }
}

impl Point {
    pub fn new(x: u32, y: u32) -> Point {
        Point { x: x, y: y }
    }
    pub fn from_1d(idx: u32, width: u32) -> Point {
        Point {
            x: idx % width,
            y: idx / width,
        }
    }
    pub fn to_1d(self, width: u32) -> u32 {
        self.x + self.y * width
    }
}

#[derive(Debug)]
pub struct BoardArr(Vec<BoardMarker>);

impl BoardArr {
    fn new() -> BoardArr {
        BoardArr(Vec::new())
    }

    fn add(&mut self, elem: BoardMarker) {
        self.0.push(elem);
    }
}

impl Deref for BoardArr {
    type Target = Vec<BoardMarker>;

    fn deref(&self) -> &Vec<BoardMarker> {
        &self.0
    }
}

impl DerefMut for BoardArr {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Vec<BoardMarker> {
        &mut self.0
    }
}

#[derive(Debug)]
pub struct Board {
    pub boardsize: u32,
    pub last_move: Option<Point>,
    pub board: BoardArr,
}

impl fmt::Display for BoardArr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Not sure if needed - let vec: Vec<BoardMarker> = *self;
        let mut dy: u32 = 0;
        let width: u32 = self.last().clone().unwrap().point.y + 1;
        write!(f, " 0:")?;
        for marker in self.iter() {
            if marker.point.y == dy {
                if marker.point.x != width {
                    write!(f, "{} ", marker)?;
                } else {
                    write!(f, "{}", marker)?;
                }
            } else {
                dy += 1;
                write!(f, "\n{:2}:{} ", dy, marker)?;
            }
        }
        write!(f, "\n   {}", (b'A' .. b'A' + 15)
                .map(|d| (d as char).to_string())
                .collect::<Vec<_>>().join(" "))
    }
}

impl Board {
    pub fn new(boardsize: u32) -> Board {
        let board: BoardArr = (0..boardsize * boardsize)
            .map(|idx|
                    BoardMarker { point: Point::from_1d(idx, boardsize),
                                color: Stone::Empty }
            ).collect();

        Board {
            boardsize: boardsize,
            last_move: None,
            board: board,
        }
    }
    pub fn clear(&mut self) {
        self.board = (0..self.boardsize * self.boardsize)
            .map(|idx|
                {
                     BoardMarker { point: Point::from_1d(idx, self.boardsize),  color: Stone::Empty,
                             }
                         })
                         .collect();
    }
    // FIXME: Use `Result` instead of Option
    pub fn get(&self, pos: Point) -> Option<&BoardMarker> {
        self.board.get(pos.to_1d(self.boardsize) as usize)
    }

    pub fn getxy(&self, x: u32, y: u32) -> Option<&BoardMarker> {
        self.board.get((x + y * self.boardsize) as usize)
    }
    pub fn get_mut(&mut self, pos: Point) -> Option<&mut BoardMarker> {
        self.board.get_mut(pos.to_1d(self.boardsize) as usize)
    }

    pub fn set_point(&mut self, pos: Point, color: Stone) {
        self.board[pos.to_1d(self.boardsize) as usize].color = color;
    }
}

impl FromIterator<BoardMarker> for BoardArr {
    fn from_iter<I: IntoIterator<Item = BoardMarker>>(iterator: I) -> Self {
        let mut c = BoardArr::new();

        for i in iterator {
            c.add(i);
        }
        c
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn check_if_board_works() {
        let mut board = Board::new(15);
        assert_eq!(board.board.len(), 15 * 15);
        let p = Point { x: 0, y: 0 };
        board.set_point(p, Stone::White);
        assert_eq!(board.get(p).unwrap().color, Stone::White);
        let p = Point { x: 3, y: 2 };
        board.set_point(p, Stone::Black);
        assert_eq!(board.get(p).unwrap().color, Stone::Black);
        // println!("{:?}", board);
        println!("Board\n{}", board.board);
    }

    #[test]
    fn clear_board() {
        let mut board = Board::new(15);
        let p = Point { x: 7, y: 7 };
        board.set_point(p, Stone::White);
        println!("Board:\n{}", board.board);
        board.clear();
        println!("Board - Cleared:\n{}", board.board);
        assert_eq!(board.get(p).unwrap().color, Stone::Empty);
    }
}
<commit_msg>Added documentation.<commit_after>#![allow(dead_code)]

use std::fmt;
use std::ops::{Deref, DerefMut};
use std::iter::FromIterator;
use std::char;

/// Enum for `Stone`,
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum Stone {
    Empty,
    White,
    Black,
}

impl Default for Stone {
    fn default() -> Stone {
        Stone::Empty
    }
}

impl fmt::Display for Stone {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}",
               match *self {
                   Stone::Empty => ".",
                   Stone::White => "O",
                   Stone::Black => "X",
               })
    }
}
/// A coordinate located at (`x`, `y`)
#[derive(Clone, Copy, Debug)]
pub struct Point {
    pub x: u32,
    pub y: u32,
}

/// Holds info about the marker at `Point`.
///
/// # Notes
/// This will hopefully have more fields in the future, planned for is support for comments on each
/// marker.
#[derive(Copy, Clone)]
pub struct BoardMarker {
    pub point: Point,
    pub color: Stone,
}

impl fmt::Debug for BoardMarker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "|[{:>2}, {} ]{:?}|", ((self.point.x as u8 + 65u8) as char), self.point.y, self.color)
    }
}

impl fmt::Display for BoardMarker {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}",
               match self.color {
                   Stone::Empty => ".",
                   Stone::White => "O",
                   Stone::Black => "X",
               })
    }
}

impl Point {
    /// Makes a `Point` at (`x`, `y`)
    pub fn new(x: u32, y: u32) -> Point {
        Point { x: x, y: y }
    }

    /// Converts a 1D coord to a `Point`
    pub fn from_1d(idx: u32, width: u32) -> Point {
        Point {
            x: idx % width,
            y: idx / width,
        }
    }
    /// Convert back a `Point` to a 1D coord
    pub fn to_1d(self, width: u32) -> u32 {
        self.x + self.y * width
    }
}

/// Holds all `BoardMarker`'s in a `Board`.
#[derive(Debug)]
pub struct BoardArr(Vec<BoardMarker>);

impl BoardArr {
    fn new() -> BoardArr {
        BoardArr(Vec::new())
    }

    fn add(&mut self, elem: BoardMarker) {
        self.0.push(elem);
    }
}

impl Deref for BoardArr {
    type Target = Vec<BoardMarker>;

    fn deref(&self) -> &Vec<BoardMarker> {
        &self.0
    }
}

impl DerefMut for BoardArr {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Vec<BoardMarker> {
        &mut self.0
    }
}

#[derive(Debug)]
/// Board type. Holds the data for a game.
pub struct Board {
    pub boardsize: u32,
    pub last_move: Option<Point>,
    pub board: BoardArr,
}

impl fmt::Display for BoardArr {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Not sure if needed - let vec: Vec<BoardMarker> = *self;
        let mut dy: u32 = 0;
        let width: u32 = self.last().clone().unwrap().point.y + 1;
        write!(f, " 0:")?;
        for marker in self.iter() {
            if marker.point.y == dy {
                if marker.point.x != width {
                    write!(f, "{} ", marker)?;
                } else {
                    write!(f, "{}", marker)?;
                }
            } else {
                dy += 1;
                write!(f, "\n{:2}:{} ", dy, marker)?;
            }
        }
        write!(f, "\n   {}", (b'A' .. b'A' + 15)
                .map(|d| (d as char).to_string())
                .collect::<Vec<_>>().join(" "))
    }
}

impl Board {
    /// Makes a new Board of size `boardsize`.
    ///
    /// # Examples
    /// ```
    /// # use renju_board::board_logic::Board;
    /// let mut board = Board::new(15);
    /// ```
    pub fn new(boardsize: u32) -> Board {
        let board: BoardArr = (0..boardsize * boardsize)
            .map(|idx|
                    BoardMarker { point: Point::from_1d(idx, boardsize),
                                color: Stone::Empty }
            ).collect();

        Board {
            boardsize: boardsize,
            last_move: None,
            board: board,
        }
    }
    /// Sets all `BoardMarker`'s to `Stone::Empty`
    pub fn clear(&mut self) {
        self.board = (0..self.boardsize * self.boardsize)
            .map(|idx|
                {
                     BoardMarker { point: Point::from_1d(idx, self.boardsize),  color: Stone::Empty,
                             }
                         })
                         .collect();
    }
    /// Returns a immutable reference to the `BoardMarker` at `pos`
    pub fn get(&self, pos: Point) -> Option<&BoardMarker> {
        self.board.get(pos.to_1d(self.boardsize) as usize)
    }
    /// Returns a immutable reference to the `BoardMarker` at (`x`,`y`)
    pub fn getxy(&self, x: u32, y: u32) -> Option<&BoardMarker> {
        self.board.get((x + y * self.boardsize) as usize)
    }
    /// Returns a mutable reference to the `BoardMarker` at `pos`
    pub fn get_mut(&mut self, pos: Point) -> Option<&mut BoardMarker> {
        self.board.get_mut(pos.to_1d(self.boardsize) as usize)
    }
    /// Sets the `BoardMarker` at `pos` to `color`
    pub fn set_point(&mut self, pos: Point, color: Stone) {
        self.board[pos.to_1d(self.boardsize) as usize].color = color;
    }
}

impl FromIterator<BoardMarker> for BoardArr {
    fn from_iter<I: IntoIterator<Item = BoardMarker>>(iterator: I) -> Self {
        let mut c = BoardArr::new();

        for i in iterator {
            c.add(i);
        }
        c
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn check_if_board_works() {
        let mut board = Board::new(15);
        assert_eq!(board.board.len(), 15 * 15);
        let p = Point { x: 0, y: 0 };
        board.set_point(p, Stone::White);
        assert_eq!(board.get(p).unwrap().color, Stone::White);
        let p = Point { x: 3, y: 2 };
        board.set_point(p, Stone::Black);
        assert_eq!(board.get(p).unwrap().color, Stone::Black);
        // println!("{:?}", board);
        println!("Board\n{}", board.board);
    }

    #[test]
    fn clear_board() {
        let mut board = Board::new(15);
        let p = Point { x: 7, y: 7 };
        board.set_point(p, Stone::White);
        println!("Board:\n{}", board.board);
        board.clear();
        println!("Board - Cleared:\n{}", board.board);
        assert_eq!(board.get(p).unwrap().color, Stone::Empty);
    }
}
<|endoftext|>


<commit_before>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! use enum_map::{enum_map, Enum, EnumMap};
//!
//! #[derive(Debug, Enum)]
//! enum Example {
//!     A(bool),
//!     B,
//!     C,
//! }
//!
//! let mut map = enum_map! {
//!     Example::A(false) => 0,
//!     Example::A(true) => 1,
//!     Example::B => 2,
//!     Example::C => 3,
//! };
//! map[Example::C] = 4;
//!
//! assert_eq!(map[Example::A(true)], 1);
//!
//! for (key, &value) in &map {
//!     println!("{:?} has {} as value.", key, value);
//! }
//! ```

#![no_std]
#![deny(missing_docs)]
#![warn(clippy::pedantic)]

#[cfg(feature = "arbitrary")]
mod arbitrary;
mod enum_map_impls;
mod internal;
mod iter;
#[cfg(feature = "serde")]
mod serde;

#[doc(hidden)]
pub use core::mem::{self, ManuallyDrop, MaybeUninit};
#[doc(hidden)]
pub use core::ptr;
use core::slice;
pub use enum_map_derive::Enum;
use internal::Array;
pub use internal::{Enum, EnumArray};
pub use iter::{IntoIter, IntoValues, Iter, IterMut, Values, ValuesMut};

// SAFETY: initialized needs to represent number of initialized elements
#[doc(hidden)]
pub struct Guard<'a, K, V>
where
    K: EnumArray<V>,
{
    array_mut: &'a mut MaybeUninit<K::Array>,
    initialized: usize,
}

impl<K, V> Drop for Guard<'_, K, V>
where
    K: EnumArray<V>,
{
    fn drop(&mut self) {
        // This is safe as arr[..len] is initialized due to
        // Guard's type invariant.
        unsafe {
            ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.initialized).drop_in_place();
        }
    }
}

impl<'a, K, V> Guard<'a, K, V>
where
    K: EnumArray<V>,
{
    #[doc(hidden)]
    pub fn as_mut_ptr(&mut self) -> *mut V {
        self.array_mut.as_mut_ptr().cast::<V>()
    }

    #[doc(hidden)]
    #[must_use]
    pub fn new(array_mut: &'a mut MaybeUninit<K::Array>) -> Self {
        Self {
            array_mut,
            initialized: 0,
        }
    }

    #[doc(hidden)]
    #[must_use]
    #[allow(clippy::unused_self)]
    pub fn storage_length(&self) -> usize {
        // SAFETY: We need to use LENGTH from K::Array, as K::LENGTH is
        // untrustworthy.
        K::Array::LENGTH
    }

    #[doc(hidden)]
    #[must_use]
    pub fn get_key(&self) -> K {
        K::from_usize(self.initialized)
    }

    #[doc(hidden)]
    // Unsafe as it can write out of bounds.
    pub unsafe fn push(&mut self, value: V) {
        self.as_mut_ptr().add(self.initialized).write(value);
        self.initialized += 1;
    }
}

#[doc(hidden)]
pub struct TypeEqualizer<'a, K, V>
where
    K: EnumArray<V>,
{
    pub enum_map: [EnumMap<K, V>; 0],
    pub guard: Guard<'a, K, V>,
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// The iteration order when using this macro is not guaranteed to be
/// consistent. Future releases of this crate may change it, and this is not
/// considered to be a breaking change.
///
/// # Examples
///
/// ```
/// use enum_map::{enum_map, Enum};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// let enum_map = enum_map! {
///     Example::A | Example::B => 1,
///     Example::C => 2,
///     _ => 3,
/// };
/// assert_eq!(enum_map[Example::A], 1);
/// assert_eq!(enum_map[Example::B], 1);
/// assert_eq!(enum_map[Example::C], 2);
/// assert_eq!(enum_map[Example::D], 3);
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {{
        let mut uninit = $crate::MaybeUninit::uninit();
        let mut eq = $crate::TypeEqualizer {
            enum_map: [],
            guard: $crate::Guard::new(&mut uninit),
        };
        if false {
            // Safe because this code is unreachable
            unsafe { (&mut eq.enum_map).as_mut_ptr().read() }
        } else {
            for _ in 0..(&eq.guard).storage_length() {
                struct __PleaseDoNotUseBreakWithoutLabel;
                let _please_do_not_use_continue_without_label;
                let value;
                #[allow(unreachable_code)]
                loop {
                    _please_do_not_use_continue_without_label = ();
                    value = match (&eq.guard).get_key() { $($t)* };
                    break __PleaseDoNotUseBreakWithoutLabel;
                };

                unsafe { (&mut eq.guard).push(value); }
            }
            $crate::mem::forget(eq);
            // Safe because the array was fully initialized.
            $crate::EnumMap::from_array(unsafe { uninit.assume_init() })
        }
    }};
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(Enum)]` macro.
///
/// Additionally, `bool` and `u8` automatically derives from `Enum`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// use enum_map::{enum_map, Enum, EnumMap};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// let mut map = EnumMap::default();
/// // new initializes map with default values
/// assert_eq!(map[Example::A], 0);
/// map[Example::A] = 3;
/// assert_eq!(map[Example::A], 3);
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
pub struct EnumMap<K: EnumArray<V>, V> {
    array: K::Array,
}

impl<K: EnumArray<V>, V: Default> EnumMap<K, V> {
    /// Clear enum map with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Example {
    ///     A,
    ///     B,
    /// }
    ///
    /// let mut enum_map = EnumMap::<_, String>::default();
    /// enum_map[Example::B] = "foo".into();
    /// enum_map.clear();
    /// assert_eq!(enum_map[Example::A], "");
    /// assert_eq!(enum_map[Example::B], "");
    /// ```
    #[inline]
    pub fn clear(&mut self) {
        for v in self.as_mut_slice() {
            *v = V::default();
        }
    }
}

#[allow(clippy::len_without_is_empty)]
impl<K: EnumArray<V>, V> EnumMap<K, V> {
    /// Creates an enum map from array.
    #[inline]
    pub const fn from_array(array: K::Array) -> EnumMap<K, V> {
        EnumMap { array }
    }

    /// Returns an iterator over enum map.
    #[inline]
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Returns number of elements in enum map.
    #[inline]
    pub fn len(&self) -> usize {
        self.as_slice().len()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// use enum_map::enum_map;
    ///
    /// let mut map = enum_map! { false => 0, true => 1 };
    /// map.swap(false, true);
    /// assert_eq!(map[false], 1);
    /// assert_eq!(map[true], 0);
    /// ```
    #[inline]
    pub fn swap(&mut self, a: K, b: K) {
        self.as_mut_slice().swap(a.into_usize(), b.into_usize());
    }

    /// Converts an enum map to a slice representing values.
    #[inline]
    pub fn as_slice(&self) -> &[V] {
        unsafe { slice::from_raw_parts(ptr::addr_of!(self.array).cast(), K::Array::LENGTH) }
    }

    /// Converts a mutable enum map to a mutable slice representing values.
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [V] {
        unsafe { slice::from_raw_parts_mut(ptr::addr_of_mut!(self.array).cast(), K::Array::LENGTH) }
    }

    /// Returns an enum map with function `f` applied to each element in order.
    ///
    /// # Examples
    ///
    /// ```
    /// use enum_map::enum_map;
    ///
    /// let a = enum_map! { false => 0, true => 1 };
    /// let b = a.map(|_, x| f64::from(x) + 0.5);
    /// assert_eq!(b, enum_map! { false => 0.5, true => 1.5 });
    /// ```
    pub fn map<F, T>(self, mut f: F) -> EnumMap<K, T>
    where
        F: FnMut(K, V) -> T,
        K: EnumArray<T>,
    {
        struct DropOnPanic<K, V>
        where
            K: EnumArray<V>,
        {
            position: usize,
            map: ManuallyDrop<EnumMap<K, V>>,
        }
        impl<K, V> Drop for DropOnPanic<K, V>
        where
            K: EnumArray<V>,
        {
            fn drop(&mut self) {
                unsafe {
                    ptr::drop_in_place(&mut self.map.as_mut_slice()[self.position..]);
                }
            }
        }
        let mut drop_protect = DropOnPanic {
            position: 0,
            map: ManuallyDrop::new(self),
        };
        enum_map! {
            k => {
                let value = unsafe { ptr::read(&drop_protect.map.as_slice()[drop_protect.position]) };
                drop_protect.position += 1;
                f(k, value)
            }
        }
    }
}
<commit_msg>Mark EnumMap::len as const fn<commit_after>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! use enum_map::{enum_map, Enum, EnumMap};
//!
//! #[derive(Debug, Enum)]
//! enum Example {
//!     A(bool),
//!     B,
//!     C,
//! }
//!
//! let mut map = enum_map! {
//!     Example::A(false) => 0,
//!     Example::A(true) => 1,
//!     Example::B => 2,
//!     Example::C => 3,
//! };
//! map[Example::C] = 4;
//!
//! assert_eq!(map[Example::A(true)], 1);
//!
//! for (key, &value) in &map {
//!     println!("{:?} has {} as value.", key, value);
//! }
//! ```

#![no_std]
#![deny(missing_docs)]
#![warn(clippy::pedantic)]

#[cfg(feature = "arbitrary")]
mod arbitrary;
mod enum_map_impls;
mod internal;
mod iter;
#[cfg(feature = "serde")]
mod serde;

#[doc(hidden)]
pub use core::mem::{self, ManuallyDrop, MaybeUninit};
#[doc(hidden)]
pub use core::ptr;
use core::slice;
pub use enum_map_derive::Enum;
use internal::Array;
pub use internal::{Enum, EnumArray};
pub use iter::{IntoIter, IntoValues, Iter, IterMut, Values, ValuesMut};

// SAFETY: initialized needs to represent number of initialized elements
#[doc(hidden)]
pub struct Guard<'a, K, V>
where
    K: EnumArray<V>,
{
    array_mut: &'a mut MaybeUninit<K::Array>,
    initialized: usize,
}

impl<K, V> Drop for Guard<'_, K, V>
where
    K: EnumArray<V>,
{
    fn drop(&mut self) {
        // This is safe as arr[..len] is initialized due to
        // Guard's type invariant.
        unsafe {
            ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.initialized).drop_in_place();
        }
    }
}

impl<'a, K, V> Guard<'a, K, V>
where
    K: EnumArray<V>,
{
    #[doc(hidden)]
    pub fn as_mut_ptr(&mut self) -> *mut V {
        self.array_mut.as_mut_ptr().cast::<V>()
    }

    #[doc(hidden)]
    #[must_use]
    pub fn new(array_mut: &'a mut MaybeUninit<K::Array>) -> Self {
        Self {
            array_mut,
            initialized: 0,
        }
    }

    #[doc(hidden)]
    #[must_use]
    #[allow(clippy::unused_self)]
    pub fn storage_length(&self) -> usize {
        // SAFETY: We need to use LENGTH from K::Array, as K::LENGTH is
        // untrustworthy.
        K::Array::LENGTH
    }

    #[doc(hidden)]
    #[must_use]
    pub fn get_key(&self) -> K {
        K::from_usize(self.initialized)
    }

    #[doc(hidden)]
    // Unsafe as it can write out of bounds.
    pub unsafe fn push(&mut self, value: V) {
        self.as_mut_ptr().add(self.initialized).write(value);
        self.initialized += 1;
    }
}

#[doc(hidden)]
pub struct TypeEqualizer<'a, K, V>
where
    K: EnumArray<V>,
{
    pub enum_map: [EnumMap<K, V>; 0],
    pub guard: Guard<'a, K, V>,
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// The iteration order when using this macro is not guaranteed to be
/// consistent. Future releases of this crate may change it, and this is not
/// considered to be a breaking change.
///
/// # Examples
///
/// ```
/// use enum_map::{enum_map, Enum};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// let enum_map = enum_map! {
///     Example::A | Example::B => 1,
///     Example::C => 2,
///     _ => 3,
/// };
/// assert_eq!(enum_map[Example::A], 1);
/// assert_eq!(enum_map[Example::B], 1);
/// assert_eq!(enum_map[Example::C], 2);
/// assert_eq!(enum_map[Example::D], 3);
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {{
        let mut uninit = $crate::MaybeUninit::uninit();
        let mut eq = $crate::TypeEqualizer {
            enum_map: [],
            guard: $crate::Guard::new(&mut uninit),
        };
        if false {
            // Safe because this code is unreachable
            unsafe { (&mut eq.enum_map).as_mut_ptr().read() }
        } else {
            for _ in 0..(&eq.guard).storage_length() {
                struct __PleaseDoNotUseBreakWithoutLabel;
                let _please_do_not_use_continue_without_label;
                let value;
                #[allow(unreachable_code)]
                loop {
                    _please_do_not_use_continue_without_label = ();
                    value = match (&eq.guard).get_key() { $($t)* };
                    break __PleaseDoNotUseBreakWithoutLabel;
                };

                unsafe { (&mut eq.guard).push(value); }
            }
            $crate::mem::forget(eq);
            // Safe because the array was fully initialized.
            $crate::EnumMap::from_array(unsafe { uninit.assume_init() })
        }
    }};
}

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(Enum)]` macro.
///
/// Additionally, `bool` and `u8` automatically derives from `Enum`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// use enum_map::{enum_map, Enum, EnumMap};
///
/// #[derive(Enum)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// let mut map = EnumMap::default();
/// // new initializes map with default values
/// assert_eq!(map[Example::A], 0);
/// map[Example::A] = 3;
/// assert_eq!(map[Example::A], 3);
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
pub struct EnumMap<K: EnumArray<V>, V> {
    array: K::Array,
}

impl<K: EnumArray<V>, V: Default> EnumMap<K, V> {
    /// Clear enum map with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// use enum_map::{Enum, EnumMap};
    ///
    /// #[derive(Enum)]
    /// enum Example {
    ///     A,
    ///     B,
    /// }
    ///
    /// let mut enum_map = EnumMap::<_, String>::default();
    /// enum_map[Example::B] = "foo".into();
    /// enum_map.clear();
    /// assert_eq!(enum_map[Example::A], "");
    /// assert_eq!(enum_map[Example::B], "");
    /// ```
    #[inline]
    pub fn clear(&mut self) {
        for v in self.as_mut_slice() {
            *v = V::default();
        }
    }
}

#[allow(clippy::len_without_is_empty)]
impl<K: EnumArray<V>, V> EnumMap<K, V> {
    /// Creates an enum map from array.
    #[inline]
    pub const fn from_array(array: K::Array) -> EnumMap<K, V> {
        EnumMap { array }
    }

    /// Returns an iterator over enum map.
    #[inline]
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    #[inline]
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Returns number of elements in enum map.
    #[inline]
    pub const fn len(&self) -> usize {
        K::Array::LENGTH
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// use enum_map::enum_map;
    ///
    /// let mut map = enum_map! { false => 0, true => 1 };
    /// map.swap(false, true);
    /// assert_eq!(map[false], 1);
    /// assert_eq!(map[true], 0);
    /// ```
    #[inline]
    pub fn swap(&mut self, a: K, b: K) {
        self.as_mut_slice().swap(a.into_usize(), b.into_usize());
    }

    /// Converts an enum map to a slice representing values.
    #[inline]
    pub fn as_slice(&self) -> &[V] {
        unsafe { slice::from_raw_parts(ptr::addr_of!(self.array).cast(), K::Array::LENGTH) }
    }

    /// Converts a mutable enum map to a mutable slice representing values.
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [V] {
        unsafe { slice::from_raw_parts_mut(ptr::addr_of_mut!(self.array).cast(), K::Array::LENGTH) }
    }

    /// Returns an enum map with function `f` applied to each element in order.
    ///
    /// # Examples
    ///
    /// ```
    /// use enum_map::enum_map;
    ///
    /// let a = enum_map! { false => 0, true => 1 };
    /// let b = a.map(|_, x| f64::from(x) + 0.5);
    /// assert_eq!(b, enum_map! { false => 0.5, true => 1.5 });
    /// ```
    pub fn map<F, T>(self, mut f: F) -> EnumMap<K, T>
    where
        F: FnMut(K, V) -> T,
        K: EnumArray<T>,
    {
        struct DropOnPanic<K, V>
        where
            K: EnumArray<V>,
        {
            position: usize,
            map: ManuallyDrop<EnumMap<K, V>>,
        }
        impl<K, V> Drop for DropOnPanic<K, V>
        where
            K: EnumArray<V>,
        {
            fn drop(&mut self) {
                unsafe {
                    ptr::drop_in_place(&mut self.map.as_mut_slice()[self.position..]);
                }
            }
        }
        let mut drop_protect = DropOnPanic {
            position: 0,
            map: ManuallyDrop::new(self),
        };
        enum_map! {
            k => {
                let value = unsafe { ptr::read(&drop_protect.map.as_slice()[drop_protect.position]) };
                drop_protect.position += 1;
                f(k, value)
            }
        }
    }
}
<|endoftext|>


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

use std::borrow::BorrowMut;
use std::ffi::CString;
use libc::{self, c_char, c_float, c_uint, c_void, pid_t, size_t};
use ::{NetworkExt, Process, ProcessExt, ProcessorExt, System, SystemExt};

/// Equivalent of `System` struct.
pub type CSystem = *mut c_void;
/// Equivalent of `Process` struct.
pub type CProcess = *const c_void;
/// C string returned from `CString::into_raw`.
pub type RString = *const c_char;
/// Callback used by `get_process_list`.
pub type ProcessLoop = extern "C" fn(pid: pid_t, process: CProcess, data: *mut c_void) -> bool;

/// Equivalent of `System::new()`.
#[no_mangle]
pub extern "C" fn sysinfo_init() -> CSystem {
    let system = Box::new(System::new());
    Box::into_raw(system) as CSystem
}

/// Equivalent of `System::drop`. Important in C to cleanup memory.
#[no_mangle]
pub extern "C" fn sysinfo_destroy(system: CSystem) {
    assert!(!system.is_null());
    unsafe { Box::from_raw(system as *mut System); }
}

/// Equivalent of `System.refresh_system()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_system(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_system();
    }
    Box::into_raw(system);
}

/// Equivalent of `System.refresh_all()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_all(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_all();
    }
    Box::into_raw(system);
}

/// Equivalent of `System.refresh_processes()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_processes(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_processes();
    }
    Box::into_raw(system);
}

/// Equivalent of `System.refresh_process()`.
#[cfg(target_os = "linux")]
#[no_mangle]
pub extern "C" fn sysinfo_refresh_process(system: CSystem, pid: pid_t) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_process(pid);
    }
    Box::into_raw(system);
}

/// Equivalent of `System.refresh_disks()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_disks(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_disks();
    }
    Box::into_raw(system);
}

/// Equivalent of `System.refresh_disk_list()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_disk_list(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_disk_list();
    }
    Box::into_raw(system);
}

/// Equivalent of `System.get_total_memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_total_memory(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_total_memory() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System.get_free_memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_free_memory(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_free_memory() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System.get_used_memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_used_memory(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_used_memory() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System.get_total_swap()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_total_swap(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_total_swap() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System.get_free_swap()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_free_swap(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_free_swap() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System.get_used_swap()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_used_swap(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_used_swap() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `system.get_network().get_income()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_network_income(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_network().get_income() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `system.get_network().get_outcome()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_network_outcome(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_network().get_outcome() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System.get_processors_usage()`.
///
/// * `length` will contain the number of cpu usage added into `procs`.
/// * `procs` will be allocated if it's null and will contain of cpu usage.
#[no_mangle]
pub extern "C" fn sysinfo_get_processors_usage(system: CSystem,
                                               length: *mut c_uint,
                                               procs: *mut *mut c_float) {
    assert!(!system.is_null());
    if procs.is_null() || length.is_null() {
        return;
    }
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let processors = system.get_processor_list();
        unsafe {
            if (*procs).is_null() {
                (*procs) = libc::malloc(::std::mem::size_of::<c_float>() * processors.len()) as *mut c_float;
            }
            for (pos, processor) in processors.iter().skip(1).enumerate() {
                (*(*procs).offset(pos as isize)) = processor.get_cpu_usage();
            }
            *length = processors.len() as c_uint - 1;
        }
    }
    Box::into_raw(system);
}

/// Equivalent of `System.get_process_list()`. Returns an array ended by a null pointer. Must
/// be freed.
///
/// # /!\ WARNING /!\
///
/// While having this method returned processes, you should *never* call any refresh method!
#[no_mangle]
pub extern "C" fn sysinfo_get_processes(system: CSystem, fn_pointer: Option<ProcessLoop>,
                                        data: *mut c_void) -> size_t {
    assert!(!system.is_null());
    if let Some(fn_pointer) = fn_pointer {
        let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
        let len = {
            let entries = system.get_process_list();
            for (pid, process) in entries {
                if !fn_pointer(*pid, process as *const Process as CProcess, data) {
                    break
                }
            }
            entries.len() as size_t
        };
        Box::into_raw(system);
        len
    } else {
        0
    }
}

/// Equivalent of `System.get_process`.
///
/// # /!\ WARNING /!\
///
/// While having this method returned process, you should *never* call any
/// refresh method!
#[no_mangle]
pub extern "C" fn sysinfo_get_process_by_pid(system: CSystem, pid: pid_t) -> CProcess {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = if let Some(process) = system.get_process(pid) {
        process as *const Process as CProcess
    } else {
        ::std::ptr::null()
    };
    Box::into_raw(system);
    ret
}

/// Equivalent of iterating over `Process.tasks`.
///
/// # /!\ WARNING /!\
///
/// While having this method processes, you should *never* call any refresh method!
#[cfg(target_os = "linux")]
#[no_mangle]
pub extern "C" fn sysinfo_process_get_tasks(process: CProcess, fn_pointer: Option<ProcessLoop>,
                                            data: *mut c_void) -> size_t {
    assert!(!process.is_null());
    if let Some(fn_pointer) = fn_pointer {
        let process = process as *const Process;
        for (pid, process) in unsafe { (*process).tasks.iter() } {
            if !fn_pointer(*pid, process as *const Process as CProcess, data) {
                break
            }
        }
        unsafe { (*process).tasks.len() as size_t }
    } else {
        0
    }
}

/// Equivalent of `Process.pid`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_pid(process: CProcess) -> pid_t {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).pid() }
}

/// Equivalent of `Process.parent`.
///
/// In case there is no known parent, it returns `0`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_parent_pid(process: CProcess) -> pid_t {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).parent().unwrap_or_else(|| 0) }
}

/// Equivalent of `Process.cpu_usage`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_cpu_usage(process: CProcess) -> c_float {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).cpu_usage() }
}

/// Equivalent of `Process.memory`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_memory(process: CProcess) -> size_t {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).memory() as usize }
}

/// Equivalent of `Process.exe`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_executable_path(process: CProcess) -> RString {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe {
        if let Some(p) = (*process).exe().to_str() {
            if let Ok(c) = CString::new(p) {
                return c.into_raw() as _;
            }
        }
        ::std::ptr::null()
    }
}

/// Equivalent of `Process.root`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_root_directory(process: CProcess) -> RString {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe {
        if let Some(p) = (*process).root().to_str() {
            if let Ok(c) = CString::new(p) {
                return c.into_raw() as _;
            }
        }
        ::std::ptr::null()
    }
}

/// Equivalent of `Process.cwd`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_current_directory(process: CProcess) -> RString {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe {
        if let Some(p) = (*process).cwd().to_str() {
            if let Ok(c) = CString::new(p) {
                return c.into_raw() as _;
            }
        }
        ::std::ptr::null()
    }
}

/// Frees a C string creating with `CString::into_raw`.
#[no_mangle]
pub extern "C" fn sysinfo_rstring_free(s: RString) {
    if !s.is_null() {
        unsafe { let _ = CString::from_raw(s as usize as *mut i8); }
    }
}
<commit_msg>Improve C interface documentation<commit_after>//
// Sysinfo
//
// Copyright (c) 2017 Guillaume Gomez
//

use std::borrow::BorrowMut;
use std::ffi::CString;
use libc::{self, c_char, c_float, c_uint, c_void, pid_t, size_t};
use ::{NetworkExt, Process, ProcessExt, ProcessorExt, System, SystemExt};

/// Equivalent of `System` struct.
pub type CSystem = *mut c_void;
/// Equivalent of `Process` struct.
pub type CProcess = *const c_void;
/// C string returned from `CString::into_raw`.
pub type RString = *const c_char;
/// Callback used by `get_process_list`.
pub type ProcessLoop = extern "C" fn(pid: pid_t, process: CProcess, data: *mut c_void) -> bool;

/// Equivalent of `System::new()`.
#[no_mangle]
pub extern "C" fn sysinfo_init() -> CSystem {
    let system = Box::new(System::new());
    Box::into_raw(system) as CSystem
}

/// Equivalent of `System::drop()`. Important in C to cleanup memory.
#[no_mangle]
pub extern "C" fn sysinfo_destroy(system: CSystem) {
    assert!(!system.is_null());
    unsafe { Box::from_raw(system as *mut System); }
}

/// Equivalent of `System::refresh_system()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_system(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_system();
    }
    Box::into_raw(system);
}

/// Equivalent of `System::refresh_all()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_all(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_all();
    }
    Box::into_raw(system);
}

/// Equivalent of `System::refresh_processes()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_processes(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_processes();
    }
    Box::into_raw(system);
}

/// Equivalent of `System::refresh_process()`.
#[cfg(target_os = "linux")]
#[no_mangle]
pub extern "C" fn sysinfo_refresh_process(system: CSystem, pid: pid_t) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_process(pid);
    }
    Box::into_raw(system);
}

/// Equivalent of `System::refresh_disks()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_disks(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_disks();
    }
    Box::into_raw(system);
}

/// Equivalent of `System::refresh_disk_list()`.
#[no_mangle]
pub extern "C" fn sysinfo_refresh_disk_list(system: CSystem) {
    assert!(!system.is_null());
    let mut system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let system: &mut System = system.borrow_mut();
        system.refresh_disk_list();
    }
    Box::into_raw(system);
}

/// Equivalent of `System::get_total_memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_total_memory(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_total_memory() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System::get_free_memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_free_memory(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_free_memory() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System::get_used_memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_used_memory(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_used_memory() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System::get_total_swap()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_total_swap(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_total_swap() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System::get_free_swap()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_free_swap(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_free_swap() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System::get_used_swap()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_used_swap(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_used_swap() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `system::get_network().get_income()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_network_income(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_network().get_income() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `system::get_network().get_outcome()`.
#[no_mangle]
pub extern "C" fn sysinfo_get_network_outcome(system: CSystem) -> size_t {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = system.get_network().get_outcome() as size_t;
    Box::into_raw(system);
    ret
}

/// Equivalent of `System::get_processors_usage()`.
///
/// * `length` will contain the number of cpu usage added into `procs`.
/// * `procs` will be allocated if it's null and will contain of cpu usage.
#[no_mangle]
pub extern "C" fn sysinfo_get_processors_usage(system: CSystem,
                                               length: *mut c_uint,
                                               procs: *mut *mut c_float) {
    assert!(!system.is_null());
    if procs.is_null() || length.is_null() {
        return;
    }
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    {
        let processors = system.get_processor_list();
        unsafe {
            if (*procs).is_null() {
                (*procs) = libc::malloc(::std::mem::size_of::<c_float>() * processors.len()) as *mut c_float;
            }
            for (pos, processor) in processors.iter().skip(1).enumerate() {
                (*(*procs).offset(pos as isize)) = processor.get_cpu_usage();
            }
            *length = processors.len() as c_uint - 1;
        }
    }
    Box::into_raw(system);
}

/// Equivalent of `System::get_process_list()`. Returns an array ended by a null pointer. Must
/// be freed.
///
/// # /!\ WARNING /!\
///
/// While having this method returned processes, you should *never* call any refresh method!
#[no_mangle]
pub extern "C" fn sysinfo_get_processes(system: CSystem, fn_pointer: Option<ProcessLoop>,
                                        data: *mut c_void) -> size_t {
    assert!(!system.is_null());
    if let Some(fn_pointer) = fn_pointer {
        let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
        let len = {
            let entries = system.get_process_list();
            for (pid, process) in entries {
                if !fn_pointer(*pid, process as *const Process as CProcess, data) {
                    break
                }
            }
            entries.len() as size_t
        };
        Box::into_raw(system);
        len
    } else {
        0
    }
}

/// Equivalent of `System::get_process()`.
///
/// # /!\ WARNING /!\
///
/// While having this method returned process, you should *never* call any
/// refresh method!
#[no_mangle]
pub extern "C" fn sysinfo_get_process_by_pid(system: CSystem, pid: pid_t) -> CProcess {
    assert!(!system.is_null());
    let system: Box<System> = unsafe { Box::from_raw(system as *mut System) };
    let ret = if let Some(process) = system.get_process(pid) {
        process as *const Process as CProcess
    } else {
        ::std::ptr::null()
    };
    Box::into_raw(system);
    ret
}

/// Equivalent of iterating over `Process::tasks()`.
///
/// # /!\ WARNING /!\
///
/// While having this method processes, you should *never* call any refresh method!
#[cfg(target_os = "linux")]
#[no_mangle]
pub extern "C" fn sysinfo_process_get_tasks(process: CProcess, fn_pointer: Option<ProcessLoop>,
                                            data: *mut c_void) -> size_t {
    assert!(!process.is_null());
    if let Some(fn_pointer) = fn_pointer {
        let process = process as *const Process;
        for (pid, process) in unsafe { (*process).tasks.iter() } {
            if !fn_pointer(*pid, process as *const Process as CProcess, data) {
                break
            }
        }
        unsafe { (*process).tasks.len() as size_t }
    } else {
        0
    }
}

/// Equivalent of `Process::pid()`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_pid(process: CProcess) -> pid_t {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).pid() }
}

/// Equivalent of `Process::parent()`.
///
/// In case there is no known parent, it returns `0`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_parent_pid(process: CProcess) -> pid_t {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).parent().unwrap_or_else(|| 0) }
}

/// Equivalent of `Process::cpu_usage()`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_cpu_usage(process: CProcess) -> c_float {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).cpu_usage() }
}

/// Equivalent of `Process::memory()`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_memory(process: CProcess) -> size_t {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe { (*process).memory() as usize }
}

/// Equivalent of `Process::exe()`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_executable_path(process: CProcess) -> RString {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe {
        if let Some(p) = (*process).exe().to_str() {
            if let Ok(c) = CString::new(p) {
                return c.into_raw() as _;
            }
        }
        ::std::ptr::null()
    }
}

/// Equivalent of `Process::root()`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_root_directory(process: CProcess) -> RString {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe {
        if let Some(p) = (*process).root().to_str() {
            if let Ok(c) = CString::new(p) {
                return c.into_raw() as _;
            }
        }
        ::std::ptr::null()
    }
}

/// Equivalent of `Process::cwd()`.
#[no_mangle]
pub extern "C" fn sysinfo_process_get_current_directory(process: CProcess) -> RString {
    assert!(!process.is_null());
    let process = process as *const Process;
    unsafe {
        if let Some(p) = (*process).cwd().to_str() {
            if let Ok(c) = CString::new(p) {
                return c.into_raw() as _;
            }
        }
        ::std::ptr::null()
    }
}

/// Frees a C string created with `CString::into_raw()`.
#[no_mangle]
pub extern "C" fn sysinfo_rstring_free(s: RString) {
    if !s.is_null() {
        unsafe { let _ = CString::from_raw(s as usize as *mut i8); }
    }
}
<|endoftext|>


<commit_before>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use std::str;
use hyper::{Method, HttpVersion, StatusCode, Headers, Body};
use futures::{Future, Stream};

use APP_CONF;
use APP_CACHE_STORE;
use header::janitor::HeaderJanitor;
use header::response_ignore::HeaderResponseBloomResponseIgnore;
use header::response_ttl::HeaderResponseBloomResponseTTL;

pub struct CacheWrite;

pub struct CacheWriteResult {
    pub body: Result<String, Option<String>>,
    pub value: Option<String>,
}

impl CacheWrite {
    pub fn save(
        key: &str,
        method: &Method,
        version: &HttpVersion,
        status: &StatusCode,
        headers: &Headers,
        body: Body,
    ) -> CacheWriteResult {
        // TODO: wait() is unsafe for event loop, see: \
        // https://docs.rs/futures/0.1.14/futures/stream/trait.Stream.html\
        //   #method.wait
        // FIX: green-threads?

        // TODO: fix next() chunk infinite wait (if no. chunk > 1)

        let body_result = body.map_err(|_| ())
            .concat2()
            .and_then(|chunk| String::from_utf8(chunk.to_vec()).map_err(|_| ()))
            .wait();

        match body_result {
            Ok(body_value) => {
                debug!("checking whether to write cache for key: {}", key);

                if Self::is_cacheable(method, status, headers) == true {
                    debug!("key: {} cacheable, writing cache", key);

                    // Acquire TTL from response, or fallback to default TTL
                    let ttl = match headers.get::<HeaderResponseBloomResponseTTL>() {
                        None => APP_CONF.cache.ttl_default,
                        Some(value) => value.0,
                    };

                    // Generate storable value
                    let value = format!(
                        "{}\n{}\n{}",
                        CacheWrite::generate_chain_banner(version, status),
                        CacheWrite::generate_chain_headers(headers),
                        body_value
                    );

                    // Write to cache
                    match APP_CACHE_STORE.set(key, &value, ttl).wait() {
                        Ok(_) => {
                            debug!("wrote cache for key: {}", key);

                            CacheWriteResult {
                                body: Ok(body_value),
                                value: Some(value),
                            }
                        }
                        Err(err) => {
                            warn!(
                                "could not write cache for key: {} \
                                    because: {:?}",
                                key,
                                err
                            );

                            CacheWriteResult {
                                body: Err(Some(body_value)),
                                value: Some(value),
                            }
                        }
                    }
                } else {
                    debug!("key: {} not cacheable, ignoring", key);

                    // Not cacheable, ignore
                    CacheWriteResult {
                        body: Err(Some(body_value)),
                        value: None,
                    }
                }
            }
            _ => {
                error!("failed unwrapping body value for key: {}, ignoring", key);

                CacheWriteResult {
                    body: Err(None),
                    value: None,
                }
            }
        }
    }

    fn is_cacheable(method: &Method, status: &StatusCode, headers: &Headers) -> bool {
        Self::is_cacheable_method(method) == true && Self::is_cacheable_status(status) == true &&
            Self::is_cacheable_response(headers) == true
    }

    fn is_cacheable_method(method: &Method) -> bool {
        match *method {
            Method::Get | Method::Head => true,
            _ => false,
        }
    }

    fn is_cacheable_status(status: &StatusCode) -> bool {
        match *status {
            StatusCode::Ok |
            StatusCode::NonAuthoritativeInformation |
            StatusCode::NoContent |
            StatusCode::ResetContent |
            StatusCode::PartialContent |
            StatusCode::MultiStatus |
            StatusCode::AlreadyReported |
            StatusCode::MultipleChoices |
            StatusCode::MovedPermanently |
            StatusCode::Found |
            StatusCode::SeeOther |
            StatusCode::PermanentRedirect |
            StatusCode::Unauthorized |
            StatusCode::PaymentRequired |
            StatusCode::Forbidden |
            StatusCode::NotFound |
            StatusCode::MethodNotAllowed |
            StatusCode::Gone |
            StatusCode::UriTooLong |
            StatusCode::Locked |
            StatusCode::FailedDependency |
            StatusCode::NotImplemented => true,
            _ => false,
        }
    }

    fn is_cacheable_response(headers: &Headers) -> bool {
        // Ignore responses with 'Bloom-Response-Ignore'
        headers.has::<HeaderResponseBloomResponseIgnore>() == false
    }

    fn generate_chain_banner(version: &HttpVersion, status: &StatusCode) -> String {
        format!("{} {}", version, status)
    }

    fn generate_chain_headers(headers: &Headers) -> String {
        headers
            .iter()
            .filter(|header_view| {
                HeaderJanitor::is_contextual(&header_view) == false
            })
            .map(|header_view| {
                format!("{}: {}\n", header_view.name(), header_view.value_string())
            })
            .collect()
    }
}

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

    #[test]
    #[should_panic]
    fn it_fails_saving_cache() {
        assert!(
            CacheWrite::save(
                "bloom:0:90d52bc6:f773d6f1",
                &Request::new(Method::Get, "/".parse().unwrap()),
                &StatusCode::Ok,
                &Headers::new(),
                Body::empty(),
            ).body
                .is_err()
        );
    }

    #[test]
    fn it_asserts_valid_cacheable_method() {
        assert_eq!(CacheWrite::is_cacheable_method(&Method::Get), true, "GET");
        assert_eq!(CacheWrite::is_cacheable_method(&Method::Head), true, "HEAD");
        assert_eq!(
            CacheWrite::is_cacheable_method(&Method::Options),
            false,
            "OPTIONS"
        );
        assert_eq!(
            CacheWrite::is_cacheable_method(&Method::Post),
            false,
            "POST"
        );
    }

    #[test]
    fn it_asserts_valid_cacheable_status() {
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::Ok),
            true,
            "200 OK"
        );
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::Unauthorized),
            true,
            "401 OK"
        );
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::BadRequest),
            false,
            "400 Bad Request"
        );
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::InternalServerError),
            false,
            "500 Internal Server Error"
        );
    }
}
<commit_msg>Fix tests<commit_after>// Bloom
//
// HTTP REST API caching middleware
// Copyright: 2017, Valerian Saliou <valerian@valeriansaliou.name>
// License: Mozilla Public License v2.0 (MPL v2.0)

use std::str;
use hyper::{Method, HttpVersion, StatusCode, Headers, Body};
use futures::{Future, Stream};

use APP_CONF;
use APP_CACHE_STORE;
use header::janitor::HeaderJanitor;
use header::response_ignore::HeaderResponseBloomResponseIgnore;
use header::response_ttl::HeaderResponseBloomResponseTTL;

pub struct CacheWrite;

pub struct CacheWriteResult {
    pub body: Result<String, Option<String>>,
    pub value: Option<String>,
}

impl CacheWrite {
    pub fn save(
        key: &str,
        method: &Method,
        version: &HttpVersion,
        status: &StatusCode,
        headers: &Headers,
        body: Body,
    ) -> CacheWriteResult {
        // TODO: wait() is unsafe for event loop, see: \
        // https://docs.rs/futures/0.1.14/futures/stream/trait.Stream.html\
        //   #method.wait
        // FIX: green-threads?

        // TODO: fix next() chunk infinite wait (if no. chunk > 1)

        let body_result = body.map_err(|_| ())
            .concat2()
            .and_then(|chunk| String::from_utf8(chunk.to_vec()).map_err(|_| ()))
            .wait();

        match body_result {
            Ok(body_value) => {
                debug!("checking whether to write cache for key: {}", key);

                if Self::is_cacheable(method, status, headers) == true {
                    debug!("key: {} cacheable, writing cache", key);

                    // Acquire TTL from response, or fallback to default TTL
                    let ttl = match headers.get::<HeaderResponseBloomResponseTTL>() {
                        None => APP_CONF.cache.ttl_default,
                        Some(value) => value.0,
                    };

                    // Generate storable value
                    let value = format!(
                        "{}\n{}\n{}",
                        CacheWrite::generate_chain_banner(version, status),
                        CacheWrite::generate_chain_headers(headers),
                        body_value
                    );

                    // Write to cache
                    match APP_CACHE_STORE.set(key, &value, ttl).wait() {
                        Ok(_) => {
                            debug!("wrote cache for key: {}", key);

                            CacheWriteResult {
                                body: Ok(body_value),
                                value: Some(value),
                            }
                        }
                        Err(err) => {
                            warn!(
                                "could not write cache for key: {} \
                                    because: {:?}",
                                key,
                                err
                            );

                            CacheWriteResult {
                                body: Err(Some(body_value)),
                                value: Some(value),
                            }
                        }
                    }
                } else {
                    debug!("key: {} not cacheable, ignoring", key);

                    // Not cacheable, ignore
                    CacheWriteResult {
                        body: Err(Some(body_value)),
                        value: None,
                    }
                }
            }
            _ => {
                error!("failed unwrapping body value for key: {}, ignoring", key);

                CacheWriteResult {
                    body: Err(None),
                    value: None,
                }
            }
        }
    }

    fn is_cacheable(method: &Method, status: &StatusCode, headers: &Headers) -> bool {
        Self::is_cacheable_method(method) == true && Self::is_cacheable_status(status) == true &&
            Self::is_cacheable_response(headers) == true
    }

    fn is_cacheable_method(method: &Method) -> bool {
        match *method {
            Method::Get | Method::Head => true,
            _ => false,
        }
    }

    fn is_cacheable_status(status: &StatusCode) -> bool {
        match *status {
            StatusCode::Ok |
            StatusCode::NonAuthoritativeInformation |
            StatusCode::NoContent |
            StatusCode::ResetContent |
            StatusCode::PartialContent |
            StatusCode::MultiStatus |
            StatusCode::AlreadyReported |
            StatusCode::MultipleChoices |
            StatusCode::MovedPermanently |
            StatusCode::Found |
            StatusCode::SeeOther |
            StatusCode::PermanentRedirect |
            StatusCode::Unauthorized |
            StatusCode::PaymentRequired |
            StatusCode::Forbidden |
            StatusCode::NotFound |
            StatusCode::MethodNotAllowed |
            StatusCode::Gone |
            StatusCode::UriTooLong |
            StatusCode::Locked |
            StatusCode::FailedDependency |
            StatusCode::NotImplemented => true,
            _ => false,
        }
    }

    fn is_cacheable_response(headers: &Headers) -> bool {
        // Ignore responses with 'Bloom-Response-Ignore'
        headers.has::<HeaderResponseBloomResponseIgnore>() == false
    }

    fn generate_chain_banner(version: &HttpVersion, status: &StatusCode) -> String {
        format!("{} {}", version, status)
    }

    fn generate_chain_headers(headers: &Headers) -> String {
        headers
            .iter()
            .filter(|header_view| {
                HeaderJanitor::is_contextual(&header_view) == false
            })
            .map(|header_view| {
                format!("{}: {}\n", header_view.name(), header_view.value_string())
            })
            .collect()
    }
}

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

    #[test]
    #[should_panic]
    fn it_fails_saving_cache() {
        assert!(
            CacheWrite::save(
                "bloom:0:90d52bc6:f773d6f1",
                &Method::Get,
                &HttpVersion::Http11,
                &StatusCode::Ok,
                &Headers::new(),
                Body::empty(),
            ).body
                .is_err()
        );
    }

    #[test]
    fn it_asserts_valid_cacheable_method() {
        assert_eq!(CacheWrite::is_cacheable_method(&Method::Get), true, "GET");
        assert_eq!(CacheWrite::is_cacheable_method(&Method::Head), true, "HEAD");
        assert_eq!(
            CacheWrite::is_cacheable_method(&Method::Options),
            false,
            "OPTIONS"
        );
        assert_eq!(
            CacheWrite::is_cacheable_method(&Method::Post),
            false,
            "POST"
        );
    }

    #[test]
    fn it_asserts_valid_cacheable_status() {
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::Ok),
            true,
            "200 OK"
        );
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::Unauthorized),
            true,
            "401 OK"
        );
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::BadRequest),
            false,
            "400 Bad Request"
        );
        assert_eq!(
            CacheWrite::is_cacheable_status(&StatusCode::InternalServerError),
            false,
            "500 Internal Server Error"
        );
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that an `&mut self` method, when invoked on an lvalue whose
// type is `&mut [u8]`, passes in a pointer to the lvalue and not a
// temporary. Issue #19147.

#![feature(core)]

use std::slice;

pub type IoResult<T> = Result<T, ()>;

trait MyWriter {
    fn my_write(&mut self, buf: &[u8]) -> IoResult<()>;
}

impl<'a> MyWriter for &'a mut [u8] {
    fn my_write(&mut self, buf: &[u8]) -> IoResult<()> {
        slice::bytes::copy_memory(buf, *self);

        let write_len = buf.len();
        unsafe {
            *self = slice::from_raw_parts_mut(
                self.as_mut_ptr().offset(write_len as isize),
                self.len() - write_len
            );
        }

        Ok(())
    }
}

fn main() {
    let mut buf = [0; 6];

    {
        let mut writer: &mut [_] = &mut buf;
        writer.my_write(&[0, 1, 2]).unwrap();
        writer.my_write(&[3, 4, 5]).unwrap();
    }

    // If `my_write` is not modifying `buf` in place, then we will
    // wind up with `[3, 4, 5, 0, 0, 0]` because the first call to
    // `my_write()` doesn't update the starting point for the write.

    assert_eq!(buf, [0, 1, 2, 3, 4, 5]);
}
<commit_msg>Rollup merge of #25876 - tshepang:patch-3, r=steveklabnik<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that an `&mut self` method, when invoked on an lvalue whose
// type is `&mut [u8]`, passes in a pointer to the lvalue and not a
// temporary. Issue #19147.

#![feature(core)]

use std::slice;

trait MyWriter {
    fn my_write(&mut self, buf: &[u8]) -> Result<(), ()>;
}

impl<'a> MyWriter for &'a mut [u8] {
    fn my_write(&mut self, buf: &[u8]) -> Result<(), ()> {
        slice::bytes::copy_memory(buf, *self);

        let write_len = buf.len();
        unsafe {
            *self = slice::from_raw_parts_mut(
                self.as_mut_ptr().offset(write_len as isize),
                self.len() - write_len
            );
        }

        Ok(())
    }
}

fn main() {
    let mut buf = [0; 6];

    {
        let mut writer: &mut [_] = &mut buf;
        writer.my_write(&[0, 1, 2]).unwrap();
        writer.my_write(&[3, 4, 5]).unwrap();
    }

    // If `my_write` is not modifying `buf` in place, then we will
    // wind up with `[3, 4, 5, 0, 0, 0]` because the first call to
    // `my_write()` doesn't update the starting point for the write.

    assert_eq!(buf, [0, 1, 2, 3, 4, 5]);
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;

use progress::CountMap;
use dataflow::channels::Content;
use Push;

pub struct Counter<T, D, P: Push<(T, Content<D>)>> {
    pushee: P,
    counts: Rc<RefCell<CountMap<T>>>,
    phantom: ::std::marker::PhantomData<D>,
}

impl<T, D, P: Push<(T, Content<D>)>> Push<(T, Content<D>)> for Counter<T, D, P> where T : Eq+Clone+'static {
    #[inline] fn push(&mut self, message: &mut Option<(T, Content<D>)>) {
        if let Some((ref time, ref data)) = *message {
            self.counts.borrow_mut().update(time, data.len() as i64);
        }
        self.pushee.push(message);
    }
}

impl<T, D, P: Push<(T, Content<D>)>> Counter<T, D, P> where T : Eq+Clone+'static {
    pub fn new(pushee: P, counts: Rc<RefCell<CountMap<T>>>) -> Counter<T, D, P> {
        Counter {
            pushee: pushee,
            counts: counts,
            phantom: ::std::marker::PhantomData,
        }
    }

    #[inline] pub fn pull_progress(&mut self, updates: &mut CountMap<T>) {
        while let Some((ref time, delta)) = self.counts.borrow_mut().pop() {
            updates.update(time, delta);
        }
    }
}
<commit_msg>suppress None propagation (flush) if nothing sent<commit_after>use std::rc::Rc;
use std::cell::RefCell;

use progress::CountMap;
use dataflow::channels::Content;
use Push;

pub struct Counter<T, D, P: Push<(T, Content<D>)>> {
    pushee: P,
    counts: Rc<RefCell<CountMap<T>>>,
    phantom: ::std::marker::PhantomData<D>,
}

impl<T, D, P: Push<(T, Content<D>)>> Push<(T, Content<D>)> for Counter<T, D, P> where T : Eq+Clone+'static {
    #[inline]
    fn push(&mut self, message: &mut Option<(T, Content<D>)>) {
        if let Some((ref time, ref data)) = *message {
            self.counts.borrow_mut().update(time, data.len() as i64);
        }

        // only propagate `None` if dirty (indicates flush)
        if message.is_some() || self.counts.borrow().len() > 0 {
            self.pushee.push(message);
        }
    }
}

impl<T, D, P: Push<(T, Content<D>)>> Counter<T, D, P> where T : Eq+Clone+'static {
    pub fn new(pushee: P, counts: Rc<RefCell<CountMap<T>>>) -> Counter<T, D, P> {
        Counter {
            pushee: pushee,
            counts: counts,
            phantom: ::std::marker::PhantomData,
        }
    }

    #[inline] pub fn pull_progress(&mut self, updates: &mut CountMap<T>) {
        while let Some((ref time, delta)) = self.counts.borrow_mut().pop() {
            updates.update(time, delta);
        }
    }
}
<|endoftext|>