<commit_before>//! MC Server List Ping protocol.
//!
//! Reference: http://wiki.vg/Server_List_Ping

use std::fs::File;
use std::io::ErrorKind::InvalidInput;
use std::io::prelude::*;
use std::io;
use std::net::TcpStream;
use std::ops::Sub; // Sub for Timespec
use std::path::Path;

use packet::{PacketRead, PacketWrite, Protocol};

use rustc_serialize::base64::{ToBase64, STANDARD};
use rustc_serialize::json;
use time;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Description {
    pub text: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Players {
    pub max: i32,
    pub online: i32,
    pub sample: Option<Vec<Sample>>,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Sample {
    pub name: String,
    pub id: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub name: String,
    pub protocol: i32,
}

/// Response sent to clients as JSON.
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Response {
    // FIXME(toqueteos): This is ChatJson
    pub description: String,
    pub favicon: Option<String>,
    pub players: Players,
    pub version: Version,
}

impl Protocol for Response {
    type Clean = Response;

    fn proto_len(value: &Response) -> usize {
        <String as Protocol>::proto_len(&json::encode(&value).unwrap())
    }
    fn proto_encode(value: &Response, dst: &mut Write) -> io::Result<()> {
        try!(<String as Protocol>::proto_encode(&json::encode(&value).unwrap(), dst));
        Ok(())
    }
    fn proto_decode(src: &mut Read) -> io::Result<Response> {
        let s = try!(<String as Protocol>::proto_decode(src));
        println!("Response proto_decode {}", s);
        json::decode(&s).map_err(|_| io::Error::new(InvalidInput, "found invalid JSON"))
    }
}

// FIXME(toqueteos): This is yelling to be a method of a Server struct or
// something more useful. We need the Handshake's `next_state` field in order
// to perform login for a player.
/// Server-side Server List response
pub fn response(mut stream: &mut TcpStream) -> io::Result<()> {
    use packet::status::serverbound::Packet::{self, StatusRequest};
    use packet::status::clientbound::StatusResponse;

    // C->S: Status Request packet
    match try!(Packet::read(stream)) {
        StatusRequest(_) => {
            // S->C: Status Response packet
            let mut file = try!(File::open(&Path::new("assets/favicon.png")));
            let mut contents = Vec::new();
            try!(file.read_to_end(&mut contents));
            let favicon = contents.to_base64(STANDARD);
            // FIXME(toqueteos): Micro-optimization? We could totally drop JSON
            // encoding and just replace player values (online & max) with format! all
            // other values are static.
            let resp = Response{
                version: Version{
                    name: "1.8.3".to_string(),
                    protocol: 47,
                },
                players: Players{
                    // FIXME(toqueteos): This is value should be a internal counter of server
                    online: 0,
                    // FIXME(toqueteos): This is value read from server.properties file
                    max: 20,
                    sample: None
                },
                description: "With custom favicons! Woot :D".to_string(),
                favicon: Some(format!("data:image/png;base64,{:}", favicon)),
            };
            try!(StatusResponse { response: resp }.write(stream));
            Ok(())
        }
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting C->S StatusRequest packet, got {:?}", wrong_packet)[..]))
    }
}

/// Server-side pong response, optional
pub fn pong(mut stream: &mut TcpStream) -> io::Result<()> {
    use packet::status::clientbound::Pong;
    use packet::status::serverbound::Packet::{self, Ping};

    // C->S: Ping packet
    match try!(Packet::read(stream)) {
        Ping(ping) => {
            // S->C: Pong packet
            try!(Pong { time: ping.time }.write(stream));
            Ok(())
        }
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting C->S Ping packet, got {:?}", wrong_packet)[..]))
    }
}

/// Client-side Server List request
pub fn request(mut stream: &mut TcpStream) -> io::Result<Response> {
    use packet::status::serverbound::StatusRequest;
    use packet::status::clientbound::Packet::{self, StatusResponse};

    // C->S: Status Request packet
    try!(StatusRequest.write(stream));

    // S->C: Status Response packet
    match try!(Packet::read(stream)) {
        StatusResponse(resp) => Ok(resp.response),
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting S->C StatusResponse packet, got {:?}", wrong_packet)[..]))
    }
}

/// Client-side ping request, optional
pub fn ping(mut stream: &mut TcpStream) -> io::Result<i64> {
    use packet::status::clientbound::Packet::{self, Pong};
    use packet::status::serverbound::Ping;

    // C->S: Ping packet
    let start = time::get_time();
    try!(Ping { time: start.sec }.write(stream));

    // S->C: Pong packet
    match try!(Packet::read(stream)) {
        Pong(_) => {
            let end = time::get_time();
            let elapsed = end.sub(start).num_milliseconds();
            Ok(elapsed)
        }
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting S->C Pong packet, got {:?}", wrong_packet)[..]))
    }
}

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

    use std::io::prelude::*;
    use std::net::TcpStream;

    use packet::handshake::Handshake;
    use packet::{PacketWrite, NextState};

    #[test]
    #[cfg(vanilla_server_required)]
    fn client_server_list_ping() {
        let mut stream = TcpStream::connect("127.0.0.1:25565").unwrap();
        Handshake {
            proto_version: 47,
            server_address: "127.0.0.1".to_string(),
            server_port: 25565,
            next_state: NextState::Status
        }.write(&mut stream).unwrap();
        let response = request(&mut stream).unwrap();
        println!("request {:?}", response);
        let elapsed = ping(&mut stream).unwrap();
        println!("ping {}", elapsed);
    }

    #[test]
    #[should_panic]
    #[cfg(vanilla_server_required)]
    fn client_slp_reversed() {
        let mut stream = TcpStream::connect("127.0.0.1:25565").unwrap();
        let elapsed = ping(&mut stream).unwrap();
        println!("ping {}", elapsed);
        Handshake {
            proto_version: 47,
            server_address: "127.0.0.1".to_string(),
            server_port: 25565,
            next_state: NextState::Status
        }.write(&mut stream).unwrap();
        let response = request(&mut stream).unwrap();
        println!("request {:?}", response);
    }
}
<commit_msg>Fix proto/slp unused imports.<commit_after>//! MC Server List Ping protocol.
//!
//! Reference: http://wiki.vg/Server_List_Ping

use std::fs::File;
use std::io::ErrorKind::InvalidInput;
use std::io::prelude::*;
use std::io;
use std::net::TcpStream;
use std::ops::Sub; // Sub for Timespec
use std::path::Path;

use packet::{PacketRead, PacketWrite, Protocol};

use rustc_serialize::base64::{ToBase64, STANDARD};
use rustc_serialize::json;
use time;

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Description {
    pub text: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Players {
    pub max: i32,
    pub online: i32,
    pub sample: Option<Vec<Sample>>,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Sample {
    pub name: String,
    pub id: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Version {
    pub name: String,
    pub protocol: i32,
}

/// Response sent to clients as JSON.
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct Response {
    // FIXME(toqueteos): This is ChatJson
    pub description: String,
    pub favicon: Option<String>,
    pub players: Players,
    pub version: Version,
}

impl Protocol for Response {
    type Clean = Response;

    fn proto_len(value: &Response) -> usize {
        <String as Protocol>::proto_len(&json::encode(&value).unwrap())
    }
    fn proto_encode(value: &Response, dst: &mut Write) -> io::Result<()> {
        try!(<String as Protocol>::proto_encode(&json::encode(&value).unwrap(), dst));
        Ok(())
    }
    fn proto_decode(src: &mut Read) -> io::Result<Response> {
        let s = try!(<String as Protocol>::proto_decode(src));
        println!("Response proto_decode {}", s);
        json::decode(&s).map_err(|_| io::Error::new(InvalidInput, "found invalid JSON"))
    }
}

// FIXME(toqueteos): This is yelling to be a method of a Server struct or
// something more useful. We need the Handshake's `next_state` field in order
// to perform login for a player.
/// Server-side Server List response
pub fn response(mut stream: &mut TcpStream) -> io::Result<()> {
    use packet::status::serverbound::Packet::{self, StatusRequest};
    use packet::status::clientbound::StatusResponse;

    // C->S: Status Request packet
    match try!(Packet::read(stream)) {
        StatusRequest(_) => {
            // S->C: Status Response packet
            let mut file = try!(File::open(&Path::new("assets/favicon.png")));
            let mut contents = Vec::new();
            try!(file.read_to_end(&mut contents));
            let favicon = contents.to_base64(STANDARD);
            // FIXME(toqueteos): Micro-optimization? We could totally drop JSON
            // encoding and just replace player values (online & max) with format! all
            // other values are static.
            let resp = Response{
                version: Version{
                    name: "1.8.3".to_string(),
                    protocol: 47,
                },
                players: Players{
                    // FIXME(toqueteos): This is value should be a internal counter of server
                    online: 0,
                    // FIXME(toqueteos): This is value read from server.properties file
                    max: 20,
                    sample: None
                },
                description: "With custom favicons! Woot :D".to_string(),
                favicon: Some(format!("data:image/png;base64,{:}", favicon)),
            };
            try!(StatusResponse { response: resp }.write(stream));
            Ok(())
        }
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting C->S StatusRequest packet, got {:?}", wrong_packet)[..]))
    }
}

/// Server-side pong response, optional
pub fn pong(mut stream: &mut TcpStream) -> io::Result<()> {
    use packet::status::clientbound::Pong;
    use packet::status::serverbound::Packet::{self, Ping};

    // C->S: Ping packet
    match try!(Packet::read(stream)) {
        Ping(ping) => {
            // S->C: Pong packet
            try!(Pong { time: ping.time }.write(stream));
            Ok(())
        }
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting C->S Ping packet, got {:?}", wrong_packet)[..]))
    }
}

/// Client-side Server List request
pub fn request(mut stream: &mut TcpStream) -> io::Result<Response> {
    use packet::status::serverbound::StatusRequest;
    use packet::status::clientbound::Packet::{self, StatusResponse};

    // C->S: Status Request packet
    try!(StatusRequest.write(stream));

    // S->C: Status Response packet
    match try!(Packet::read(stream)) {
        StatusResponse(resp) => Ok(resp.response),
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting S->C StatusResponse packet, got {:?}", wrong_packet)[..]))
    }
}

/// Client-side ping request, optional
pub fn ping(mut stream: &mut TcpStream) -> io::Result<i64> {
    use packet::status::clientbound::Packet::{self, Pong};
    use packet::status::serverbound::Ping;

    // C->S: Ping packet
    let start = time::get_time();
    try!(Ping { time: start.sec }.write(stream));

    // S->C: Pong packet
    match try!(Packet::read(stream)) {
        Pong(_) => {
            let end = time::get_time();
            let elapsed = end.sub(start).num_milliseconds();
            Ok(elapsed)
        }
        wrong_packet => Err(io::Error::new(InvalidInput, &format!("Invalid packet read, expecting S->C Pong packet, got {:?}", wrong_packet)[..]))
    }
}

#[allow(unused_imports)]
#[cfg(test)]
mod tests {
    // This module is special, compiler sees imports as they were unused
    // because there's no `vanilla_server_required` cfg set.
    //
    // Unless we tell Travis to run a vanilla server, these tests will
    // only get run if the cfg attr is removed manually.

    use super::*;

    use std::io::prelude::*;
    use std::net::TcpStream;

    use packet::handshake::Handshake;
    use packet::{PacketWrite, NextState};

    #[test]
    #[cfg(vanilla_server_required)]
    fn client_server_list_ping() {
        let mut stream = TcpStream::connect("127.0.0.1:25565").unwrap();
        Handshake {
            proto_version: 47,
            server_address: "127.0.0.1".to_string(),
            server_port: 25565,
            next_state: NextState::Status
        }.write(&mut stream).unwrap();
        let response = request(&mut stream).unwrap();
        println!("request {:?}", response);
        let elapsed = ping(&mut stream).unwrap();
        println!("ping {}", elapsed);
    }

    #[test]
    #[should_panic]
    #[cfg(vanilla_server_required)]
    fn client_slp_reversed() {
        let mut stream = TcpStream::connect("127.0.0.1:25565").unwrap();
        let elapsed = ping(&mut stream).unwrap();
        println!("ping {}", elapsed);
        Handshake {
            proto_version: 47,
            server_address: "127.0.0.1".to_string(),
            server_port: 25565,
            next_state: NextState::Status
        }.write(&mut stream).unwrap();
        let response = request(&mut stream).unwrap();
        println!("request {:?}", response);
    }
}
<|endoftext|>


<commit_before>//! Draw rectangle

use current::{ Get, Modifier, Set };
use internal;
use triangulation;
use Context;
use BackEnd;
use ImageSize;
use Color;

/// Use x, y, half-width, half-height
pub fn centered(rect: internal::Rectangle) -> internal::Rectangle {
    let [cx, cy, rw, rh] = rect;
    [cx - rw, cy - rh, 2.0 * rw, 2.0 * rh]
}

/// Use centered square
pub fn centered_square(
    x: internal::Scalar,
    y: internal::Scalar,
    radius: internal::Scalar
) -> internal::Rectangle {
    [x - radius, y - radius, 2.0 * radius, 2.0 * radius]
}

/// Use square with x, y in upper left corner
pub fn square(
    x: internal::Scalar,
    y: internal::Scalar,
    size: internal::Scalar
) -> internal::Rectangle {
    [x, y, size, size]
}

/// The shape of the rectangle
pub enum Shape {
    /// Square corners
    Square,
    /// Round corners
    Round(internal::Radius),
    /// Bevel corners
    Bevel(internal::Radius),
}

/// Wrapper trait for `Get<Shape>`
pub trait GetShape: Get<Shape> {
    /// Get shape
    #[inline(always)]
    fn get_shape(&self) -> Shape {
        self.get()
    }
}

impl<T: Get<Shape>> GetShape for T {}

/// Wrapper trait for `Set<Shape>`
pub trait SetShape: Set<Shape> {
    /// Set shape
    #[inline(always)]
    fn set_shape(&mut self, val: Shape) {
        self.set_mut(val);
    }
}

impl<T: Set<Shape>> SetShape for T {}

/// The border of the rectangle
pub struct Border {
    /// The color of the border
    pub color: internal::Color,
    /// The radius of the border
    pub radius: internal::Radius,
}

/// Wrapper trait for `Get<Border>`
pub trait GetBorder: Get<Border> {
    /// Get border
    #[inline(always)]
    fn get_border(&self) -> Border {
        self.get()
    }
}

impl<T: Get<Border>> GetBorder for T {}

/// Wrapper trait for `Set<Border>`
pub trait SetBorder: Set<Border> {
    /// Set border
    #[inline(always)]
    fn set_border(&mut self, val: Border) {
        self.set_mut(val);
    }
}

impl<T: Set<Border>> SetBorder for T {}

/// A filled rectangle
#[deriving(Copy)]
pub struct Rectangle {
    /// The rectangle color
    pub color: internal::Color,
    /// The roundness of the rectangle
    pub shape: Shape,
    /// The border
    pub border: Option<Border>,
}

impl Rectangle {
    /// Creates a new rectangle.
    pub fn new(color: internal::Color) -> Rectangle {
        Rectangle {
            color: color,
            shape: Shape::Square,
            border: None,
        }
    }

    /// Draws the rectangle
    pub fn draw<B: BackEnd<I>, I: ImageSize>(
        &self,
        rectangle: internal::Rectangle,
        c: &Context,
        back_end: &mut B
    ) {
        if self.color[3] != 0.0 {
            back_end.color(self.color);
            match self.shape {
                Shape::Square => {
                    back_end.tri_list(
                        &triangulation::rect_tri_list_xy(c.transform, rectangle),
                    );
                }
                Shape::Round(round_radius) => {
                    triangulation::with_round_rectangle_tri_list(
                        32,
                        c.transform,
                        rectangle,
                        round_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
                Shape::Bevel(bevel_radius) => {
                    triangulation::with_round_rectangle_tri_list(
                        2,
                        c.transform,
                        rectangle,
                        bevel_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
            }
        }

        if let Some(Border { color, radius: border_radius }) = self.border {
            if color[3] == 0.0 { return; }
            back_end.color(color);
            match self.shape {
                Shape::Square => {
                    back_end.tri_list(
                        &triangulation::rect_border_tri_list_xy(
                            c.transform, rectangle, border_radius),
                    );
                }
                Shape::Round(round_radius) => {
                    triangulation::with_round_rectangle_border_tri_list(
                        128,
                        c.transform,
                        rectangle,
                        round_radius,
                        border_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
                Shape::Bevel(bevel_radius) => {
                    triangulation::with_round_rectangle_border_tri_list(
                        2,
                        c.transform,
                        rectangle,
                        bevel_radius,
                        border_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
            }
        }
    }
}

impl Modifier<Rectangle> for Color {
    fn modify(self, r: &mut Rectangle) {
        let Color(val) = self;
        r.color = val;
    }
}

impl Modifier<Rectangle> for Shape {
    fn modify(self, r: &mut Rectangle) {
        r.shape = self;
    }
}

impl Modifier<Rectangle> for Border {
    fn modify(self, r: &mut Rectangle) {
        r.border = Some(self);
    }
}

#[cfg(test)]
mod test {
    use super::Rectangle;
    use super::Shape;
    use super::Border;
    use Color;
    use current::Set;

    #[test]
    fn test_rectangle() {
        let _rectangle = Rectangle::new([1.0, ..4])
            .set(Color([0.0, ..4]))
            .set(Shape::Round(10.0))
            .set(Border { color: [0.0, ..4], radius: 4.0 });
    }
}

<commit_msg>Added MaybeBorder property to Rectangle<commit_after>//! Draw rectangle

use current::{ Get, Modifier, Set };
use internal;
use triangulation;
use Context;
use BackEnd;
use ImageSize;
use Color;

/// Use x, y, half-width, half-height
pub fn centered(rect: internal::Rectangle) -> internal::Rectangle {
    let [cx, cy, rw, rh] = rect;
    [cx - rw, cy - rh, 2.0 * rw, 2.0 * rh]
}

/// Use centered square
pub fn centered_square(
    x: internal::Scalar,
    y: internal::Scalar,
    radius: internal::Scalar
) -> internal::Rectangle {
    [x - radius, y - radius, 2.0 * radius, 2.0 * radius]
}

/// Use square with x, y in upper left corner
pub fn square(
    x: internal::Scalar,
    y: internal::Scalar,
    size: internal::Scalar
) -> internal::Rectangle {
    [x, y, size, size]
}

/// The shape of the rectangle
pub enum Shape {
    /// Square corners
    Square,
    /// Round corners
    Round(internal::Radius),
    /// Bevel corners
    Bevel(internal::Radius),
}

/// Wrapper trait for `Get<Shape>`
pub trait GetShape: Get<Shape> {
    /// Get shape
    #[inline(always)]
    fn get_shape(&self) -> Shape {
        self.get()
    }
}

impl<T: Get<Shape>> GetShape for T {}

/// Wrapper trait for `Set<Shape>`
pub trait SetShape: Set<Shape> {
    /// Set shape
    #[inline(always)]
    fn set_shape(&mut self, val: Shape) {
        self.set_mut(val);
    }
}

impl<T: Set<Shape>> SetShape for T {}

/// The border of the rectangle
pub struct Border {
    /// The color of the border
    pub color: internal::Color,
    /// The radius of the border
    pub radius: internal::Radius,
}

/// Wrapper trait for `Get<Border>`
pub trait GetBorder: Get<Border> {
    /// Get border
    #[inline(always)]
    fn get_border(&self) -> Border {
        self.get()
    }
}

impl<T: Get<Border>> GetBorder for T {}

/// Wrapper trait for `Set<Border>`
pub trait SetBorder: Set<Border> {
    /// Set border
    #[inline(always)]
    fn set_border(&mut self, val: Border) {
        self.set_mut(val);
    }
}

impl<T: Set<Border>> SetBorder for T {}

/// Maybe border property
pub struct MaybeBorder(pub Option<Border>);

/// Wrapper trait for `Get<MaybeBorder>`
pub trait GetMaybeBorder: Get<MaybeBorder> {
    /// Get maybe border
    #[inline(always)]
    fn get_maybe_border(&self) -> MaybeBorder {
        self.get()
    }
}

impl<T: Get<MaybeBorder>> GetMaybeBorder for T {}

/// Wrapper trait for `Set<MaybeBorder>`
pub trait SetMaybeBorder: Set<MaybeBorder> {
    /// Set maybe border
    #[inline(always)]
    fn set_maybe_border(&mut self, val: MaybeBorder) {
        self.set_mut(val);
    }
}

impl<T: Set<MaybeBorder>> SetMaybeBorder for T {}

/// A filled rectangle
#[deriving(Copy)]
pub struct Rectangle {
    /// The rectangle color
    pub color: internal::Color,
    /// The roundness of the rectangle
    pub shape: Shape,
    /// The border
    pub border: Option<Border>,
}

impl Rectangle {
    /// Creates a new rectangle.
    pub fn new(color: internal::Color) -> Rectangle {
        Rectangle {
            color: color,
            shape: Shape::Square,
            border: None,
        }
    }

    /// Draws the rectangle
    pub fn draw<B: BackEnd<I>, I: ImageSize>(
        &self,
        rectangle: internal::Rectangle,
        c: &Context,
        back_end: &mut B
    ) {
        if self.color[3] != 0.0 {
            back_end.color(self.color);
            match self.shape {
                Shape::Square => {
                    back_end.tri_list(
                        &triangulation::rect_tri_list_xy(c.transform, rectangle),
                    );
                }
                Shape::Round(round_radius) => {
                    triangulation::with_round_rectangle_tri_list(
                        32,
                        c.transform,
                        rectangle,
                        round_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
                Shape::Bevel(bevel_radius) => {
                    triangulation::with_round_rectangle_tri_list(
                        2,
                        c.transform,
                        rectangle,
                        bevel_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
            }
        }

        if let Some(Border { color, radius: border_radius }) = self.border {
            if color[3] == 0.0 { return; }
            back_end.color(color);
            match self.shape {
                Shape::Square => {
                    back_end.tri_list(
                        &triangulation::rect_border_tri_list_xy(
                            c.transform, rectangle, border_radius),
                    );
                }
                Shape::Round(round_radius) => {
                    triangulation::with_round_rectangle_border_tri_list(
                        128,
                        c.transform,
                        rectangle,
                        round_radius,
                        border_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
                Shape::Bevel(bevel_radius) => {
                    triangulation::with_round_rectangle_border_tri_list(
                        2,
                        c.transform,
                        rectangle,
                        bevel_radius,
                        border_radius,
                        |vertices| back_end.tri_list(vertices)
                    );
                }
            }
        }
    }
}

impl Modifier<Rectangle> for Color {
    #[inline(always)]
    fn modify(self, r: &mut Rectangle) {
        let Color(val) = self;
        r.color = val;
    }
}

impl Get<Color> for Rectangle {
    #[inline(always)]
    fn get(&self) -> Color {
        Color(self.color)
    }
}

impl Modifier<Rectangle> for Shape {
    #[inline(always)]
    fn modify(self, r: &mut Rectangle) {
        r.shape = self;
    }
}

impl Get<Shape> for Rectangle {
    #[inline(always)]
    fn get(&self) -> Shape {
        self.shape
    }
}

impl Modifier<Rectangle> for Border {
    #[inline(always)]
    fn modify(self, r: &mut Rectangle) {
        r.border = Some(self);
    }
}

impl Modifier<Rectangle> for MaybeBorder {
    #[inline(always)]
    fn modify(self, r: &mut Rectangle) {
        let MaybeBorder(val) = self;
        r.border = val;
    }
}

impl Get<MaybeBorder> for Rectangle {
    #[inline(always)]
    fn get(&self) -> MaybeBorder {
        MaybeBorder(self.border)
    }
}

#[cfg(test)]
mod test {
    use super::Rectangle;
    use super::Shape;
    use super::Border;
    use Color;
    use current::Set;

    #[test]
    fn test_rectangle() {
        let _rectangle = Rectangle::new([1.0, ..4])
            .set(Color([0.0, ..4]))
            .set(Shape::Round(10.0))
            .set(Border { color: [0.0, ..4], radius: 4.0 });
    }
}

<|endoftext|>


<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.

#![allow(non_snake_case)]

register_long_diagnostics! {

E0010: r##"
The value of statics and constants must be known at compile time, and they live
for the entire lifetime of a program. Creating a boxed value allocates memory on
the heap at runtime, and therefore cannot be done at compile time. Erroneous
code example:

```compile_fail
#![feature(box_syntax)]

const CON : Box<i32> = box 0;
```
"##,

E0013: r##"
Static and const variables can refer to other const variables. But a const
variable cannot refer to a static variable. For example, `Y` cannot refer to
`X` here:

```compile_fail
static X: i32 = 42;
const Y: i32 = X;
```

To fix this, the value can be extracted as a const and then used:

```
const A: i32 = 42;
static X: i32 = A;
const Y: i32 = A;
```
"##,

// FIXME(#24111) Change the language here when const fn stabilizes
E0015: r##"
The only functions that can be called in static or constant expressions are
`const` functions, and struct/enum constructors. `const` functions are only
available on a nightly compiler. Rust currently does not support more general
compile-time function execution.

```
const FOO: Option<u8> = Some(1); // enum constructor
struct Bar {x: u8}
const BAR: Bar = Bar {x: 1}; // struct constructor
```

See [RFC 911] for more details on the design of `const fn`s.

[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
"##,

E0016: r##"
Blocks in constants may only contain items (such as constant, function
definition, etc...) and a tail expression. Erroneous code example:

```compile_fail
const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
```

To avoid it, you have to replace the non-item object:

```
const FOO: i32 = { const X : i32 = 0; X };
```
"##,

E0017: r##"
References in statics and constants may only refer to immutable values.
Erroneous code example:

```compile_fail
static X: i32 = 1;
const C: i32 = 2;

// these three are not allowed:
const CR: &'static mut i32 = &mut C;
static STATIC_REF: &'static mut i32 = &mut X;
static CONST_REF: &'static mut i32 = &mut C;
```

Statics are shared everywhere, and if they refer to mutable data one might
violate memory safety since holding multiple mutable references to shared data
is not allowed.

If you really want global mutable state, try using `static mut` or a global
`UnsafeCell`.
"##,

E0018: r##"

The value of static and constant integers must be known at compile time. You
can't cast a pointer to an integer because the address of a pointer can
vary.

For example, if you write:

```compile_fail
static MY_STATIC: u32 = 42;
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
```

Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
the address can change when the program is linked, as well as change
between different executions due to ASLR, and many linkers would
not be able to calculate the value of `WHAT`.

On the other hand, static and constant pointers can point either to
a known numeric address or to the address of a symbol.

```
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
// ... and also
static MY_STATIC_ADDR2: *const u32 = &MY_STATIC;

const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
```

This does not pose a problem by itself because they can't be
accessed directly.
"##,

E0019: r##"
A function call isn't allowed in the const's initialization expression
because the expression's value must be known at compile-time. Erroneous code
example:

```compile_fail
enum Test {
    V1
}

impl Test {
    fn test(&self) -> i32 {
        12
    }
}

fn main() {
    const FOO: Test = Test::V1;

    const A: i32 = FOO.test(); // You can't call Test::func() here !
}
```

Remember: you can't use a function call inside a const's initialization
expression! However, you can totally use it anywhere else:

```
fn main() {
    const FOO: Test = Test::V1;

    FOO.func(); // here is good
    let x = FOO.func(); // or even here!
}
```
"##,

E0022: r##"
Constant functions are not allowed to mutate anything. Thus, binding to an
argument with a mutable pattern is not allowed. For example,

```compile_fail
const fn foo(mut x: u8) {
    // do stuff
}
```

Is incorrect because the function body may not mutate `x`.

Remove any mutable bindings from the argument list to fix this error. In case
you need to mutate the argument, try lazily initializing a global variable
instead of using a `const fn`, or refactoring the code to a functional style to
avoid mutation if possible.
"##,

E0394: r##"
From [RFC 246]:

 > It is invalid for a static to reference another static by value. It is
 > required that all references be borrowed.

[RFC 246]: https://github.com/rust-lang/rfcs/pull/246
"##,

E0395: r##"
The value assigned to a constant scalar must be known at compile time,
which is not the case when comparing raw pointers.

Erroneous code example:

```compile_fail
static FOO: i32 = 42;
static BAR: i32 = 42;

static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
// error: raw pointers cannot be compared in statics!
```

The address assigned by the linker to `FOO` and `BAR` may or may not
be identical, so the value of `BAZ` can't be determined.

If you want to do the comparison, please do it at run-time.

For example:

```
static FOO: i32 = 42;
static BAR: i32 = 42;

let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
// baz isn't a constant expression so it's ok
```
"##,

E0396: r##"
The value behind a raw pointer can't be determined at compile-time
(or even link-time), which means it can't be used in a constant
expression. Erroneous code example:

```compile_fail
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;

const VALUE: u8 = unsafe { *REG_ADDR };
// error: raw pointers cannot be dereferenced in constants
```

A possible fix is to dereference your pointer at some point in run-time.

For example:

```
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;

let reg_value = unsafe { *REG_ADDR };
```
"##,

E0492: r##"
A borrow of a constant containing interior mutability was attempted. Erroneous
code example:

```compile_fail
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};

const A: AtomicUsize = ATOMIC_USIZE_INIT;
static B: &'static AtomicUsize = &A;
// error: cannot borrow a constant which contains interior mutability, create a
//        static instead
```

A `const` represents a constant value that should never change. If one takes
a `&` reference to the constant, then one is taking a pointer to some memory
location containing the value. Normally this is perfectly fine: most values
can't be changed via a shared `&` pointer, but interior mutability would allow
it. That is, a constant value could be mutated. On the other hand, a `static` is
explicitly a single memory location, which can be mutated at will.

So, in order to solve this error, either use statics which are `Sync`:

```
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};

static A: AtomicUsize = ATOMIC_USIZE_INIT;
static B: &'static AtomicUsize = &A; // ok!
```

You can also have this error while using a cell type:

```compile_fail
#![feature(const_fn)]

use std::cell::Cell;

const A: Cell<usize> = Cell::new(1);
const B: &'static Cell<usize> = &A;
// error: cannot borrow a constant which contains interior mutability, create
//        a static instead

// or:
struct C { a: Cell<usize> }

const D: C = C { a: Cell::new(1) };
const E: &'static Cell<usize> = &D.a; // error

// or:
const F: &'static C = &D; // error
```

This is because cell types do operations that are not thread-safe. Due to this,
they don't implement Sync and thus can't be placed in statics. In this
case, `StaticMutex` would work just fine, but it isn't stable yet:
https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html

However, if you still wish to use these types, you can achieve this by an unsafe
wrapper:

```
#![feature(const_fn)]

use std::cell::Cell;
use std::marker::Sync;

struct NotThreadSafe<T> {
    value: Cell<T>,
}

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

static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
static B: &'static NotThreadSafe<usize> = &A; // ok!
```

Remember this solution is unsafe! You will have to ensure that accesses to the
cell are synchronized.
"##,

E0493: r##"
A type with a destructor was assigned to an invalid type of variable. Erroneous
code example:

```compile_fail
struct Foo {
    a: u32
}

impl Drop for Foo {
    fn drop(&mut self) {}
}

const F : Foo = Foo { a : 0 };
// error: constants are not allowed to have destructors
static S : Foo = Foo { a : 0 };
// error: destructors in statics are an unstable feature
```

To solve this issue, please use a type which does allow the usage of type with
destructors.
"##,

E0494: r##"
A reference of an interior static was assigned to another const/static.
Erroneous code example:

```compile_fail
struct Foo {
    a: u32
}

static S : Foo = Foo { a : 0 };
static A : &'static u32 = &S.a;
// error: cannot refer to the interior of another static, use a
//        constant instead
```

The "base" variable has to be a const if you want another static/const variable
to refer to one of its fields. Example:

```
struct Foo {
    a: u32
}

const S : Foo = Foo { a : 0 };
static A : &'static u32 = &S.a; // ok!
```
"##,

}

register_diagnostics! {
    E0526, // shuffle indices are not constant
}
<commit_msg>Add E0394 error explanation<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.

#![allow(non_snake_case)]

register_long_diagnostics! {

E0010: r##"
The value of statics and constants must be known at compile time, and they live
for the entire lifetime of a program. Creating a boxed value allocates memory on
the heap at runtime, and therefore cannot be done at compile time. Erroneous
code example:

```compile_fail
#![feature(box_syntax)]

const CON : Box<i32> = box 0;
```
"##,

E0013: r##"
Static and const variables can refer to other const variables. But a const
variable cannot refer to a static variable. For example, `Y` cannot refer to
`X` here:

```compile_fail
static X: i32 = 42;
const Y: i32 = X;
```

To fix this, the value can be extracted as a const and then used:

```
const A: i32 = 42;
static X: i32 = A;
const Y: i32 = A;
```
"##,

// FIXME(#24111) Change the language here when const fn stabilizes
E0015: r##"
The only functions that can be called in static or constant expressions are
`const` functions, and struct/enum constructors. `const` functions are only
available on a nightly compiler. Rust currently does not support more general
compile-time function execution.

```
const FOO: Option<u8> = Some(1); // enum constructor
struct Bar {x: u8}
const BAR: Bar = Bar {x: 1}; // struct constructor
```

See [RFC 911] for more details on the design of `const fn`s.

[RFC 911]: https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md
"##,

E0016: r##"
Blocks in constants may only contain items (such as constant, function
definition, etc...) and a tail expression. Erroneous code example:

```compile_fail
const FOO: i32 = { let x = 0; x }; // 'x' isn't an item!
```

To avoid it, you have to replace the non-item object:

```
const FOO: i32 = { const X : i32 = 0; X };
```
"##,

E0017: r##"
References in statics and constants may only refer to immutable values.
Erroneous code example:

```compile_fail
static X: i32 = 1;
const C: i32 = 2;

// these three are not allowed:
const CR: &'static mut i32 = &mut C;
static STATIC_REF: &'static mut i32 = &mut X;
static CONST_REF: &'static mut i32 = &mut C;
```

Statics are shared everywhere, and if they refer to mutable data one might
violate memory safety since holding multiple mutable references to shared data
is not allowed.

If you really want global mutable state, try using `static mut` or a global
`UnsafeCell`.
"##,

E0018: r##"

The value of static and constant integers must be known at compile time. You
can't cast a pointer to an integer because the address of a pointer can
vary.

For example, if you write:

```compile_fail
static MY_STATIC: u32 = 42;
static MY_STATIC_ADDR: usize = &MY_STATIC as *const _ as usize;
static WHAT: usize = (MY_STATIC_ADDR^17) + MY_STATIC_ADDR;
```

Then `MY_STATIC_ADDR` would contain the address of `MY_STATIC`. However,
the address can change when the program is linked, as well as change
between different executions due to ASLR, and many linkers would
not be able to calculate the value of `WHAT`.

On the other hand, static and constant pointers can point either to
a known numeric address or to the address of a symbol.

```
static MY_STATIC_ADDR: &'static u32 = &MY_STATIC;
// ... and also
static MY_STATIC_ADDR2: *const u32 = &MY_STATIC;

const CONST_ADDR: *const u8 = 0x5f3759df as *const u8;
```

This does not pose a problem by itself because they can't be
accessed directly.
"##,

E0019: r##"
A function call isn't allowed in the const's initialization expression
because the expression's value must be known at compile-time. Erroneous code
example:

```compile_fail
enum Test {
    V1
}

impl Test {
    fn test(&self) -> i32 {
        12
    }
}

fn main() {
    const FOO: Test = Test::V1;

    const A: i32 = FOO.test(); // You can't call Test::func() here !
}
```

Remember: you can't use a function call inside a const's initialization
expression! However, you can totally use it anywhere else:

```
fn main() {
    const FOO: Test = Test::V1;

    FOO.func(); // here is good
    let x = FOO.func(); // or even here!
}
```
"##,

E0022: r##"
Constant functions are not allowed to mutate anything. Thus, binding to an
argument with a mutable pattern is not allowed. For example,

```compile_fail
const fn foo(mut x: u8) {
    // do stuff
}
```

Is incorrect because the function body may not mutate `x`.

Remove any mutable bindings from the argument list to fix this error. In case
you need to mutate the argument, try lazily initializing a global variable
instead of using a `const fn`, or refactoring the code to a functional style to
avoid mutation if possible.
"##,

E0394: r##"
A static was referred to by value by another static.

Erroneous code examples:

```compile_fail,E0394
static A: u32 = 0;
static B: u32 = A; // error: cannot refer to other statics by value, use the
                   //        address-of operator or a constant instead
```

A static cannot be referred by value. To fix this issue, either use a
constant:

```
const A: u32 = 0; // `A` is now a constant
static B: u32 = A; // ok!
```

Or refer to `A` by reference:

```
static A: u32 = 0;
static B: &'static u32 = &A; // ok!
```
"##,

E0395: r##"
The value assigned to a constant scalar must be known at compile time,
which is not the case when comparing raw pointers.

Erroneous code example:

```compile_fail
static FOO: i32 = 42;
static BAR: i32 = 42;

static BAZ: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
// error: raw pointers cannot be compared in statics!
```

The address assigned by the linker to `FOO` and `BAR` may or may not
be identical, so the value of `BAZ` can't be determined.

If you want to do the comparison, please do it at run-time.

For example:

```
static FOO: i32 = 42;
static BAR: i32 = 42;

let baz: bool = { (&FOO as *const i32) == (&BAR as *const i32) };
// baz isn't a constant expression so it's ok
```
"##,

E0396: r##"
The value behind a raw pointer can't be determined at compile-time
(or even link-time), which means it can't be used in a constant
expression. Erroneous code example:

```compile_fail
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;

const VALUE: u8 = unsafe { *REG_ADDR };
// error: raw pointers cannot be dereferenced in constants
```

A possible fix is to dereference your pointer at some point in run-time.

For example:

```
const REG_ADDR: *const u8 = 0x5f3759df as *const u8;

let reg_value = unsafe { *REG_ADDR };
```
"##,

E0492: r##"
A borrow of a constant containing interior mutability was attempted. Erroneous
code example:

```compile_fail
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};

const A: AtomicUsize = ATOMIC_USIZE_INIT;
static B: &'static AtomicUsize = &A;
// error: cannot borrow a constant which contains interior mutability, create a
//        static instead
```

A `const` represents a constant value that should never change. If one takes
a `&` reference to the constant, then one is taking a pointer to some memory
location containing the value. Normally this is perfectly fine: most values
can't be changed via a shared `&` pointer, but interior mutability would allow
it. That is, a constant value could be mutated. On the other hand, a `static` is
explicitly a single memory location, which can be mutated at will.

So, in order to solve this error, either use statics which are `Sync`:

```
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};

static A: AtomicUsize = ATOMIC_USIZE_INIT;
static B: &'static AtomicUsize = &A; // ok!
```

You can also have this error while using a cell type:

```compile_fail
#![feature(const_fn)]

use std::cell::Cell;

const A: Cell<usize> = Cell::new(1);
const B: &'static Cell<usize> = &A;
// error: cannot borrow a constant which contains interior mutability, create
//        a static instead

// or:
struct C { a: Cell<usize> }

const D: C = C { a: Cell::new(1) };
const E: &'static Cell<usize> = &D.a; // error

// or:
const F: &'static C = &D; // error
```

This is because cell types do operations that are not thread-safe. Due to this,
they don't implement Sync and thus can't be placed in statics. In this
case, `StaticMutex` would work just fine, but it isn't stable yet:
https://doc.rust-lang.org/nightly/std/sync/struct.StaticMutex.html

However, if you still wish to use these types, you can achieve this by an unsafe
wrapper:

```
#![feature(const_fn)]

use std::cell::Cell;
use std::marker::Sync;

struct NotThreadSafe<T> {
    value: Cell<T>,
}

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

static A: NotThreadSafe<usize> = NotThreadSafe { value : Cell::new(1) };
static B: &'static NotThreadSafe<usize> = &A; // ok!
```

Remember this solution is unsafe! You will have to ensure that accesses to the
cell are synchronized.
"##,

E0493: r##"
A type with a destructor was assigned to an invalid type of variable. Erroneous
code example:

```compile_fail
struct Foo {
    a: u32
}

impl Drop for Foo {
    fn drop(&mut self) {}
}

const F : Foo = Foo { a : 0 };
// error: constants are not allowed to have destructors
static S : Foo = Foo { a : 0 };
// error: destructors in statics are an unstable feature
```

To solve this issue, please use a type which does allow the usage of type with
destructors.
"##,

E0494: r##"
A reference of an interior static was assigned to another const/static.
Erroneous code example:

```compile_fail
struct Foo {
    a: u32
}

static S : Foo = Foo { a : 0 };
static A : &'static u32 = &S.a;
// error: cannot refer to the interior of another static, use a
//        constant instead
```

The "base" variable has to be a const if you want another static/const variable
to refer to one of its fields. Example:

```
struct Foo {
    a: u32
}

const S : Foo = Foo { a : 0 };
static A : &'static u32 = &S.a; // ok!
```
"##,

}

register_diagnostics! {
    E0526, // shuffle indices are not constant
}
<|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.

#![allow(non_camel_case_types)]

use core::prelude::*;
use libc;
use local::Local;
use task::Task;

pub unsafe fn init() {
    imp::init();
}

pub unsafe fn cleanup() {
    imp::cleanup();
}

pub struct Handler {
    _data: *mut libc::c_void
}

impl Handler {
    pub unsafe fn new() -> Handler {
        imp::make_handler()
    }
}

impl Drop for Handler {
    fn drop(&mut self) {
        unsafe {
            imp::drop_handler(self);
        }
    }
}

pub unsafe fn report() {
    // See the message below for why this is not emitted to the
    // ^ Where did the message below go?
    // task's logger. This has the additional conundrum of the
    // logger may not be initialized just yet, meaning that an FFI
    // call would happen to initialized it (calling out to libuv),
    // and the FFI call needs 2MB of stack when we just ran out.

    let task: Option<*mut Task> = Local::try_unsafe_borrow();

    let name = task.and_then(|task| {
        (*task).name.as_ref().map(|n| n.as_slice())
    });

    rterrln!("\ntask '{}' has overflowed its stack", name.unwrap_or("<unknown>"));
}

// get_task_info is called from an exception / signal handler.
// It returns the guard page of the current task or 0 if that
// guard page doesn't exist. None is returned if there's currently
// no local task.
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
unsafe fn get_task_guard_page() -> Option<uint> {
    let task: Option<*mut Task> = Local::try_unsafe_borrow();

    task.map(|task| {
        let runtime = (*task).take_runtime();
        let guard = runtime.stack_guard();
        (*task).put_runtime(runtime);

        guard.unwrap_or(0)
    })
}

#[cfg(windows)]
#[allow(non_snake_case)]
mod imp {
    use core::ptr;
    use core::mem;
    use libc;
    use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
    use stack;
    use super::{Handler, get_task_guard_page, report};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
        unsafe {
            let rec = &(*(*ExceptionInfo).ExceptionRecord);
            let code = rec.ExceptionCode;

            if code != EXCEPTION_STACK_OVERFLOW {
                return EXCEPTION_CONTINUE_SEARCH;
            }

            // We're calling into functions with stack checks,
            // however stack checks by limit should be disabled on Windows
            stack::record_sp_limit(0);

            if get_task_guard_page().is_some() {
               report();
            }

            EXCEPTION_CONTINUE_SEARCH
        }
    }

    pub unsafe fn init() {
        let mut info = mem::zeroed();
        libc::GetSystemInfo(&mut info);
        PAGE_SIZE = info.dwPageSize as uint;

        if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
            panic!("failed to install exception handler");
        }

        mem::forget(make_handler());
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> Handler {
        if SetThreadStackGuarantee(&mut 0x5000) == 0 {
            panic!("failed to reserve stack space for exception handling");
        }

        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut Handler) {
    }

    pub struct EXCEPTION_RECORD {
        pub ExceptionCode: DWORD,
        pub ExceptionFlags: DWORD,
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ExceptionAddress: LPVOID,
        pub NumberParameters: DWORD,
        pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
    }

    pub struct EXCEPTION_POINTERS {
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ContextRecord: LPVOID
    }

    pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
            fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;

    pub type ULONG = libc::c_ulong;

    const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
    const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15;
    const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;

    extern "system" {
        fn AddVectoredExceptionHandler(FirstHandler: ULONG,
                                       VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
                                      -> LPVOID;
        fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod imp {
    use core::prelude::*;
    use stack;

    use super::{Handler, get_task_guard_page, report};
    use core::mem;
    use core::ptr;
    use core::intrinsics;
    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
                       SIGSTKSZ};
    use libc;
    use libc::funcs::posix88::mman::{mmap, munmap};
    use libc::consts::os::posix88::{SIGSEGV,
                                    PROT_READ,
                                    PROT_WRITE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    unsafe extern fn signal_handler(signum: libc::c_int,
                                     info: *mut siginfo,
                                     _data: *mut libc::c_void) {

        // We can not return from a SIGSEGV or SIGBUS signal.
        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html

        unsafe fn term(signum: libc::c_int) -> ! {
            use core::mem::transmute;

            signal(signum, transmute(SIG_DFL));
            raise(signum);
            intrinsics::abort();
        }

        // We're calling into functions with stack checks
        stack::record_sp_limit(0);

        match get_task_guard_page() {
            Some(guard) => {
                let addr = (*info).si_addr as uint;

                if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
                    term(signum);
                }

                report();

                intrinsics::abort()
            }
            None => term(signum)
        }
    }

    static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;

    pub unsafe fn init() {
        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
        if psize == -1 {
            panic!("failed to get page size");
        }

        PAGE_SIZE = psize as uint;

        let mut action: sigaction = mem::zeroed();
        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
        action.sa_sigaction = signal_handler as sighandler_t;
        sigaction(SIGSEGV, &action, ptr::null_mut());
        sigaction(SIGBUS, &action, ptr::null_mut());

        let handler = make_handler();
        MAIN_ALTSTACK = handler._data;
        mem::forget(handler);
    }

    pub unsafe fn cleanup() {
        Handler { _data: MAIN_ALTSTACK };
    }

    pub unsafe fn make_handler() -> Handler {
        let alt_stack = mmap(ptr::null_mut(),
                             signal::SIGSTKSZ,
                             PROT_READ | PROT_WRITE,
                             MAP_PRIVATE | MAP_ANON,
                             -1,
                             0);
        if alt_stack == MAP_FAILED {
            panic!("failed to allocate an alternative stack");
        }

        let mut stack: sigaltstack = mem::zeroed();

        stack.ss_sp = alt_stack;
        stack.ss_flags = 0;
        stack.ss_size = SIGSTKSZ;

        sigaltstack(&stack, ptr::null_mut());

        Handler { _data: alt_stack }
    }

    pub unsafe fn drop_handler(handler: &mut Handler) {
        munmap(handler._data, SIGSTKSZ);
    }

    type sighandler_t = *mut libc::c_void;

    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
              all(target_os = "linux", target_arch = "x86_64"),
              all(target_os = "linux", target_arch = "arm"), // may not match
              target_os = "android"))] // may not match
    mod signal {
        use libc;
        use super::sighandler_t;

        pub static SA_ONSTACK: libc::c_int = 0x08000000;
        pub static SA_SIGINFO: libc::c_int = 0x00000004;
        pub static SIGBUS: libc::c_int = 7;

        pub static SIGSTKSZ: libc::size_t = 8192;

        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;

        // This definition is not as accurate as it could be, {si_addr} is
        // actually a giant union. Currently we're only interested in that field,
        // however.
        #[repr(C)]
        pub struct siginfo {
            si_signo: libc::c_int,
            si_errno: libc::c_int,
            si_code: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
            sa_restorer: *mut libc::c_void,
        }

        #[cfg(target_word_size = "32")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..32],
        }
        #[cfg(target_word_size = "64")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..16],
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_flags: libc::c_int,
            pub ss_size: libc::size_t
        }

    }

    #[cfg(target_os = "macos")]
    mod signal {
        use libc;
        use super::sighandler_t;

        pub const SA_ONSTACK: libc::c_int = 0x0001;
        pub const SA_SIGINFO: libc::c_int = 0x0040;
        pub const SIGBUS: libc::c_int = 10;

        pub const SIGSTKSZ: libc::size_t = 131072;

        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;

        pub type sigset_t = u32;

        // This structure has more fields, but we're not all that interested in
        // them.
        #[repr(C)]
        pub struct siginfo {
            pub si_signo: libc::c_int,
            pub si_errno: libc::c_int,
            pub si_code: libc::c_int,
            pub pid: libc::pid_t,
            pub uid: libc::uid_t,
            pub status: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_size: libc::size_t,
            pub ss_flags: libc::c_int
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
        }
    }

    extern {
        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
        pub fn raise(signum: libc::c_int) -> libc::c_int;

        pub fn sigaction(signum: libc::c_int,
                         act: *const sigaction,
                         oldact: *mut sigaction) -> libc::c_int;

        pub fn sigaltstack(ss: *const sigaltstack,
                           oss: *mut sigaltstack) -> libc::c_int;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "macos",
              windows)))]
mod imp {
    use libc;

    pub unsafe fn init() {
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> super::Handler {
        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
    }
}
<commit_msg>rollup merge of #19076: jxv/master<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.

#![allow(non_camel_case_types)]

use core::prelude::*;
use libc;
use local::Local;
use task::Task;

pub unsafe fn init() {
    imp::init();
}

pub unsafe fn cleanup() {
    imp::cleanup();
}

pub struct Handler {
    _data: *mut libc::c_void
}

impl Handler {
    pub unsafe fn new() -> Handler {
        imp::make_handler()
    }
}

impl Drop for Handler {
    fn drop(&mut self) {
        unsafe {
            imp::drop_handler(self);
        }
    }
}

pub unsafe fn report() {
    // See the message below for why this is not emitted to the
    // ^ Where did the message below go?
    // task's logger. This has the additional conundrum of the
    // logger may not be initialized just yet, meaning that an FFI
    // call would happen to initialized it (calling out to libuv),
    // and the FFI call needs 2MB of stack when we just ran out.

    let task: Option<*mut Task> = Local::try_unsafe_borrow();

    let name = task.and_then(|task| {
        (*task).name.as_ref().map(|n| n.as_slice())
    });

    rterrln!("\ntask '{}' has overflowed its stack", name.unwrap_or("<unknown>"));
}

// get_task_info is called from an exception / signal handler.
// It returns the guard page of the current task or 0 if that
// guard page doesn't exist. None is returned if there's currently
// no local task.
#[cfg(any(windows, target_os = "linux", target_os = "macos"))]
unsafe fn get_task_guard_page() -> Option<uint> {
    let task: Option<*mut Task> = Local::try_unsafe_borrow();

    task.map(|task| {
        let runtime = (*task).take_runtime();
        let guard = runtime.stack_guard();
        (*task).put_runtime(runtime);

        guard.unwrap_or(0)
    })
}

#[cfg(windows)]
#[allow(non_snake_case)]
mod imp {
    use core::ptr;
    use core::mem;
    use libc;
    use libc::types::os::arch::extra::{LPVOID, DWORD, LONG, BOOL};
    use stack;
    use super::{Handler, get_task_guard_page, report};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    extern "system" fn vectored_handler(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG {
        unsafe {
            let rec = &(*(*ExceptionInfo).ExceptionRecord);
            let code = rec.ExceptionCode;

            if code != EXCEPTION_STACK_OVERFLOW {
                return EXCEPTION_CONTINUE_SEARCH;
            }

            // We're calling into functions with stack checks,
            // however stack checks by limit should be disabled on Windows
            stack::record_sp_limit(0);

            if get_task_guard_page().is_some() {
               report();
            }

            EXCEPTION_CONTINUE_SEARCH
        }
    }

    pub unsafe fn init() {
        let mut info = mem::zeroed();
        libc::GetSystemInfo(&mut info);
        PAGE_SIZE = info.dwPageSize as uint;

        if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
            panic!("failed to install exception handler");
        }

        mem::forget(make_handler());
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> Handler {
        if SetThreadStackGuarantee(&mut 0x5000) == 0 {
            panic!("failed to reserve stack space for exception handling");
        }

        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut Handler) {
    }

    pub struct EXCEPTION_RECORD {
        pub ExceptionCode: DWORD,
        pub ExceptionFlags: DWORD,
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ExceptionAddress: LPVOID,
        pub NumberParameters: DWORD,
        pub ExceptionInformation: [LPVOID, ..EXCEPTION_MAXIMUM_PARAMETERS]
    }

    pub struct EXCEPTION_POINTERS {
        pub ExceptionRecord: *mut EXCEPTION_RECORD,
        pub ContextRecord: LPVOID
    }

    pub type PVECTORED_EXCEPTION_HANDLER = extern "system"
            fn(ExceptionInfo: *mut EXCEPTION_POINTERS) -> LONG;

    pub type ULONG = libc::c_ulong;

    const EXCEPTION_CONTINUE_SEARCH: LONG = 0;
    const EXCEPTION_MAXIMUM_PARAMETERS: uint = 15;
    const EXCEPTION_STACK_OVERFLOW: DWORD = 0xc00000fd;

    extern "system" {
        fn AddVectoredExceptionHandler(FirstHandler: ULONG,
                                       VectoredHandler: PVECTORED_EXCEPTION_HANDLER)
                                      -> LPVOID;
        fn SetThreadStackGuarantee(StackSizeInBytes: *mut ULONG) -> BOOL;
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod imp {
    use core::prelude::*;
    use stack;

    use super::{Handler, get_task_guard_page, report};
    use core::mem;
    use core::ptr;
    use core::intrinsics;
    use self::signal::{siginfo, sigaction, SIGBUS, SIG_DFL,
                       SA_SIGINFO, SA_ONSTACK, sigaltstack,
                       SIGSTKSZ};
    use libc;
    use libc::funcs::posix88::mman::{mmap, munmap};
    use libc::consts::os::posix88::{SIGSEGV,
                                    PROT_READ,
                                    PROT_WRITE,
                                    MAP_PRIVATE,
                                    MAP_ANON,
                                    MAP_FAILED};

    // This is initialized in init() and only read from after
    static mut PAGE_SIZE: uint = 0;

    #[no_stack_check]
    unsafe extern fn signal_handler(signum: libc::c_int,
                                     info: *mut siginfo,
                                     _data: *mut libc::c_void) {

        // We can not return from a SIGSEGV or SIGBUS signal.
        // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html

        unsafe fn term(signum: libc::c_int) -> ! {
            use core::mem::transmute;

            signal(signum, transmute(SIG_DFL));
            raise(signum);
            intrinsics::abort();
        }

        // We're calling into functions with stack checks
        stack::record_sp_limit(0);

        match get_task_guard_page() {
            Some(guard) => {
                let addr = (*info).si_addr as uint;

                if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
                    term(signum);
                }

                report();

                intrinsics::abort()
            }
            None => term(signum)
        }
    }

    static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;

    pub unsafe fn init() {
        let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
        if psize == -1 {
            panic!("failed to get page size");
        }

        PAGE_SIZE = psize as uint;

        let mut action: sigaction = mem::zeroed();
        action.sa_flags = SA_SIGINFO | SA_ONSTACK;
        action.sa_sigaction = signal_handler as sighandler_t;
        sigaction(SIGSEGV, &action, ptr::null_mut());
        sigaction(SIGBUS, &action, ptr::null_mut());

        let handler = make_handler();
        MAIN_ALTSTACK = handler._data;
        mem::forget(handler);
    }

    pub unsafe fn cleanup() {
        Handler { _data: MAIN_ALTSTACK };
    }

    pub unsafe fn make_handler() -> Handler {
        let alt_stack = mmap(ptr::null_mut(),
                             signal::SIGSTKSZ,
                             PROT_READ | PROT_WRITE,
                             MAP_PRIVATE | MAP_ANON,
                             -1,
                             0);
        if alt_stack == MAP_FAILED {
            panic!("failed to allocate an alternative stack");
        }

        let mut stack: sigaltstack = mem::zeroed();

        stack.ss_sp = alt_stack;
        stack.ss_flags = 0;
        stack.ss_size = SIGSTKSZ;

        sigaltstack(&stack, ptr::null_mut());

        Handler { _data: alt_stack }
    }

    pub unsafe fn drop_handler(handler: &mut Handler) {
        munmap(handler._data, SIGSTKSZ);
    }

    type sighandler_t = *mut libc::c_void;

    #[cfg(any(all(target_os = "linux", target_arch = "x86"), // may not match
              all(target_os = "linux", target_arch = "x86_64"),
              all(target_os = "linux", target_arch = "arm"), // may not match
              all(target_os = "linux", target_arch = "mips"), // may not match
              target_os = "android"))] // may not match
    mod signal {
        use libc;
        use super::sighandler_t;

        pub static SA_ONSTACK: libc::c_int = 0x08000000;
        pub static SA_SIGINFO: libc::c_int = 0x00000004;
        pub static SIGBUS: libc::c_int = 7;

        pub static SIGSTKSZ: libc::size_t = 8192;

        pub static SIG_DFL: sighandler_t = 0i as sighandler_t;

        // This definition is not as accurate as it could be, {si_addr} is
        // actually a giant union. Currently we're only interested in that field,
        // however.
        #[repr(C)]
        pub struct siginfo {
            si_signo: libc::c_int,
            si_errno: libc::c_int,
            si_code: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
            sa_restorer: *mut libc::c_void,
        }

        #[cfg(target_word_size = "32")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..32],
        }
        #[cfg(target_word_size = "64")]
        #[repr(C)]
        pub struct sigset_t {
            __val: [libc::c_ulong, ..16],
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_flags: libc::c_int,
            pub ss_size: libc::size_t
        }

    }

    #[cfg(target_os = "macos")]
    mod signal {
        use libc;
        use super::sighandler_t;

        pub const SA_ONSTACK: libc::c_int = 0x0001;
        pub const SA_SIGINFO: libc::c_int = 0x0040;
        pub const SIGBUS: libc::c_int = 10;

        pub const SIGSTKSZ: libc::size_t = 131072;

        pub const SIG_DFL: sighandler_t = 0i as sighandler_t;

        pub type sigset_t = u32;

        // This structure has more fields, but we're not all that interested in
        // them.
        #[repr(C)]
        pub struct siginfo {
            pub si_signo: libc::c_int,
            pub si_errno: libc::c_int,
            pub si_code: libc::c_int,
            pub pid: libc::pid_t,
            pub uid: libc::uid_t,
            pub status: libc::c_int,
            pub si_addr: *mut libc::c_void
        }

        #[repr(C)]
        pub struct sigaltstack {
            pub ss_sp: *mut libc::c_void,
            pub ss_size: libc::size_t,
            pub ss_flags: libc::c_int
        }

        #[repr(C)]
        pub struct sigaction {
            pub sa_sigaction: sighandler_t,
            pub sa_mask: sigset_t,
            pub sa_flags: libc::c_int,
        }
    }

    extern {
        pub fn signal(signum: libc::c_int, handler: sighandler_t) -> sighandler_t;
        pub fn raise(signum: libc::c_int) -> libc::c_int;

        pub fn sigaction(signum: libc::c_int,
                         act: *const sigaction,
                         oldact: *mut sigaction) -> libc::c_int;

        pub fn sigaltstack(ss: *const sigaltstack,
                           oss: *mut sigaltstack) -> libc::c_int;
    }
}

#[cfg(not(any(target_os = "linux",
              target_os = "macos",
              windows)))]
mod imp {
    use libc;

    pub unsafe fn init() {
    }

    pub unsafe fn cleanup() {
    }

    pub unsafe fn make_handler() -> super::Handler {
        super::Handler { _data: 0i as *mut libc::c_void }
    }

    pub unsafe fn drop_handler(_handler: &mut super::Handler) {
    }
}
<|endoftext|>


<commit_before><commit_msg>Add zst tests and some other parsing tests<commit_after><|endoftext|>


<commit_before><commit_msg>use slicing syntax<commit_after><|endoftext|>


<commit_before><commit_msg>Fix documentation in lib.rs.<commit_after><|endoftext|>


<commit_before><commit_msg>PgResult Iterator.<commit_after><|endoftext|>


<commit_before><commit_msg>Update<commit_after><|endoftext|>


<commit_before><commit_msg>Fix trailing whitespace bug and add tests<commit_after><|endoftext|>


<commit_before><commit_msg>refac: Restructre algorithm to hash mapping<commit_after><|endoftext|>


<commit_before><commit_msg>Implement for usize and isize<commit_after><|endoftext|>


<commit_before><commit_msg>Replace multirows mutable slices in LRF<commit_after><|endoftext|>


<commit_before><commit_msg>Fix desync on sub8x8 partitions caused by fine dir intrapred<commit_after><|endoftext|>


<commit_before>mod draw_field;
mod console_player;

use ::game::*;

pub fn run() {
    let mut game: Game = Game::new(console_player::player_controller, console_player::player_controller);
    match game.play() {
        Player::Nobody => println!("Well, that's a draw. ¯\\_(ツ)_/¯"),
        winner @ _ => println!("Player {0} wins! (ツ)_/\\_({0})", player_to_str(winner)),
    }
    print_game_field(&game.field());
}

fn print_game_field(field: &Field) {
    println!("{}", draw_field::draw(&field));
}

fn player_to_str(player: Player) -> String {
    match player {
        Player::X => "X",
        Player::O => "O",
        Player::Nobody => "Nobody",
    }.into()
}
<commit_msg>Make choosing players in console engine possible<commit_after>mod draw_field;
mod console_player;

use ::game::*;

use std::io;
use std::error::Error;

pub fn run() {
    loop {
        println!("{}" ,instructions());

        match (first_player(), second_player()) {
            (Some(first_player), Some(second_player)) => play(first_player, second_player),
            _ => break,
        }
    }
}

fn play(first_player: PlayerController, second_player: PlayerController) {
    let mut game: Game = Game::new(first_player, second_player);
    match game.play() {
        Player::Nobody => println!("Well, that's a draw. ¯\\_(ツ)_/¯"),
        winner @ _ => println!("Player {0} wins! (ツ)_/\\_({0})", player_to_str(winner)),
    }
    print_game_field(&game.field());
}

fn player_to_str(player: Player) -> String {
    match player {
        Player::X => "X",
        Player::O => "O",
        Player::Nobody => "Nobody",
    }.into()
}

fn print_game_field(field: &Field) {
    println!("{}", draw_field::draw(&field));
}

fn instructions() -> String {
    r#"
    Hey! That's a new game.

    You can use the following keys:
    - 1 - Human
    - 2 - Perfect AI
    - 3 - Ultimate AI
    "#.into()
}

fn first_player() -> Option<PlayerController> {
    print!("Choose the first player (or print 'q' to quit): ");
    choose_player()
}

fn second_player() -> Option<PlayerController> {
    print!("Choose the second player (or print 'q' to quit): ");
    choose_player()
}

fn choose_player() -> Option<PlayerController> {
    loop {
        io::Write::flush(&mut io::stdout()).unwrap();
        let mut text: String = String::new();
        io::stdin().read_line(&mut text).unwrap();
        let text = text.trim_right();

        if text == String::from("q") {
            return None;
        }

        match parse_key(text) {
            Ok(1) => return Some(console_player::player_controller),
            Ok(2) => return Some(::ai::perfect::player_controller),
            Ok(3) => return Some(::ai::ultimate::player_controller),
            Err(error) => print!("Error: {}\nRepeat: ", error),
            _ => panic!("unexpected key {}", text),
        }
    }
}

fn parse_key(key: &str) -> Result<usize, String> {
    let key: usize = key.parse().map_err(show_error)?;
    match key {
        1 ... 3 => Ok(key),
        _ => Err(parse_error())
    }
}

fn parse_error() -> String {
    "possible keys are 1, 2 or 3".into()
}

fn show_error<T: Error>(err: T) -> String {
    err.description().to_string()
}
<|endoftext|>


<commit_before>use crate::dist::dist::TargetTriple;
use crate::dist::manifest::Component;
use crate::dist::temp;
use crate::errors::*;
use crate::utils::notify::NotificationLevel;
use std::fmt::{self, Display};
use std::path::Path;

#[derive(Debug)]
pub enum Notification<'a> {
    Utils(crate::utils::Notification<'a>),
    Temp(temp::Notification<'a>),

    Extracting(&'a Path, &'a Path),
    ComponentAlreadyInstalled(&'a str),
    CantReadUpdateHash(&'a Path),
    NoUpdateHash(&'a Path),
    ChecksumValid(&'a str),
    SignatureValid(&'a str),
    FileAlreadyDownloaded,
    CachedFileChecksumFailed,
    RollingBack,
    ExtensionNotInstalled(&'a str),
    NonFatalError(&'a Error),
    MissingInstalledComponent(&'a str),
    DownloadingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    InstallingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    RemovingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    RemovingOldComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    DownloadingManifest(&'a str),
    DownloadedManifest(&'a str, Option<&'a str>),
    DownloadingLegacyManifest,
    SkippingNightlyMissingComponent(&'a [Component]),
    ManifestChecksumFailedHack,
    ComponentUnavailable(&'a str, Option<&'a TargetTriple>),
    StrayHash(&'a Path),
}

impl<'a> From<crate::utils::Notification<'a>> for Notification<'a> {
    fn from(n: crate::utils::Notification<'a>) -> Self {
        Notification::Utils(n)
    }
}

impl<'a> From<temp::Notification<'a>> for Notification<'a> {
    fn from(n: temp::Notification<'a>) -> Self {
        Notification::Temp(n)
    }
}

impl<'a> Notification<'a> {
    pub fn level(&self) -> NotificationLevel {
        use self::Notification::*;
        match self {
            Temp(n) => n.level(),
            Utils(n) => n.level(),
            ChecksumValid(_)
            | NoUpdateHash(_)
            | FileAlreadyDownloaded
            | DownloadingLegacyManifest => NotificationLevel::Verbose,
            Extracting(_, _)
            | SignatureValid(_)
            | DownloadingComponent(_, _, _)
            | InstallingComponent(_, _, _)
            | RemovingComponent(_, _, _)
            | RemovingOldComponent(_, _, _)
            | ComponentAlreadyInstalled(_)
            | ManifestChecksumFailedHack
            | RollingBack
            | DownloadingManifest(_)
            | SkippingNightlyMissingComponent(_)
            | DownloadedManifest(_, _) => NotificationLevel::Info,
            CantReadUpdateHash(_)
            | ExtensionNotInstalled(_)
            | MissingInstalledComponent(_)
            | CachedFileChecksumFailed
            | ComponentUnavailable(_, _)
            | StrayHash(_) => NotificationLevel::Warn,
            NonFatalError(_) => NotificationLevel::Error,
        }
    }
}

impl<'a> Display for Notification<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
        use self::Notification::*;
        match self {
            Temp(n) => n.fmt(f),
            Utils(n) => n.fmt(f),
            Extracting(_, _) => write!(f, "extracting..."),
            ComponentAlreadyInstalled(c) => write!(f, "component {} is up to date", c),
            CantReadUpdateHash(path) => write!(
                f,
                "can't read update hash file: '{}', can't skip update...",
                path.display()
            ),
            NoUpdateHash(path) => write!(f, "no update hash at: '{}'", path.display()),
            ChecksumValid(_) => write!(f, "checksum passed"),
            SignatureValid(_) => write!(f, "signature valid"),
            FileAlreadyDownloaded => write!(f, "reusing previously downloaded file"),
            CachedFileChecksumFailed => write!(f, "bad checksum for cached download"),
            RollingBack => write!(f, "rolling back changes"),
            ExtensionNotInstalled(c) => write!(f, "extension '{}' was not installed", c),
            NonFatalError(e) => write!(f, "{}", e),
            MissingInstalledComponent(c) => {
                write!(f, "during uninstall component {} was not found", c)
            }
            DownloadingComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "downloading component '{}'", c)
                } else {
                    write!(f, "downloading component '{}' for '{}'", c, t.unwrap())
                }
            }
            InstallingComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "installing component '{}'", c)
                } else {
                    write!(f, "installing component '{}' for '{}'", c, t.unwrap())
                }
            }
            RemovingComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "removing component '{}'", c)
                } else {
                    write!(f, "removing component '{}' for '{}'", c, t.unwrap())
                }
            }
            RemovingOldComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "removing previous version of component '{}'", c)
                } else {
                    write!(
                        f,
                        "removing previous version of component '{}' for '{}'",
                        c,
                        t.unwrap()
                    )
                }
            }
            DownloadingManifest(t) => write!(f, "syncing channel updates for '{}'", t),
            DownloadedManifest(date, Some(version)) => {
                write!(f, "latest update on {}, rust version {}", date, version)
            }
            DownloadedManifest(date, None) => {
                write!(f, "latest update on {}, no rust version", date)
            }
            DownloadingLegacyManifest => write!(f, "manifest not found. trying legacy manifest"),
            ManifestChecksumFailedHack => {
                write!(f, "update not yet available, sorry! try again later")
            }
            ComponentUnavailable(pkg, toolchain) => {
                if let Some(tc) = toolchain {
                    write!(f, "component '{}' is not available on target '{}'", pkg, tc)
                } else {
                    write!(f, "component '{}' is not available", pkg)
                }
            }
            StrayHash(path) => write!(
                f,
                "removing stray hash found at '{}' in order to continue",
                path.display()
            ),
            SkippingNightlyMissingComponent(components) => write!(
                f,
                "skipping nightly which is missing installed component '{}'",
                components[0].short_name_in_manifest()
            ),
        }
    }
}
<commit_msg>Notifications: Add 'forcing unavailable component' notification<commit_after>use crate::dist::dist::TargetTriple;
use crate::dist::manifest::Component;
use crate::dist::temp;
use crate::errors::*;
use crate::utils::notify::NotificationLevel;
use std::fmt::{self, Display};
use std::path::Path;

#[derive(Debug)]
pub enum Notification<'a> {
    Utils(crate::utils::Notification<'a>),
    Temp(temp::Notification<'a>),

    Extracting(&'a Path, &'a Path),
    ComponentAlreadyInstalled(&'a str),
    CantReadUpdateHash(&'a Path),
    NoUpdateHash(&'a Path),
    ChecksumValid(&'a str),
    SignatureValid(&'a str),
    FileAlreadyDownloaded,
    CachedFileChecksumFailed,
    RollingBack,
    ExtensionNotInstalled(&'a str),
    NonFatalError(&'a Error),
    MissingInstalledComponent(&'a str),
    DownloadingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    InstallingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    RemovingComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    RemovingOldComponent(&'a str, &'a TargetTriple, Option<&'a TargetTriple>),
    DownloadingManifest(&'a str),
    DownloadedManifest(&'a str, Option<&'a str>),
    DownloadingLegacyManifest,
    SkippingNightlyMissingComponent(&'a [Component]),
    ForcingUnavailableComponent(&'a str),
    ManifestChecksumFailedHack,
    ComponentUnavailable(&'a str, Option<&'a TargetTriple>),
    StrayHash(&'a Path),
}

impl<'a> From<crate::utils::Notification<'a>> for Notification<'a> {
    fn from(n: crate::utils::Notification<'a>) -> Self {
        Notification::Utils(n)
    }
}

impl<'a> From<temp::Notification<'a>> for Notification<'a> {
    fn from(n: temp::Notification<'a>) -> Self {
        Notification::Temp(n)
    }
}

impl<'a> Notification<'a> {
    pub fn level(&self) -> NotificationLevel {
        use self::Notification::*;
        match self {
            Temp(n) => n.level(),
            Utils(n) => n.level(),
            ChecksumValid(_)
            | NoUpdateHash(_)
            | FileAlreadyDownloaded
            | DownloadingLegacyManifest => NotificationLevel::Verbose,
            Extracting(_, _)
            | SignatureValid(_)
            | DownloadingComponent(_, _, _)
            | InstallingComponent(_, _, _)
            | RemovingComponent(_, _, _)
            | RemovingOldComponent(_, _, _)
            | ComponentAlreadyInstalled(_)
            | ManifestChecksumFailedHack
            | RollingBack
            | DownloadingManifest(_)
            | SkippingNightlyMissingComponent(_)
            | DownloadedManifest(_, _) => NotificationLevel::Info,
            CantReadUpdateHash(_)
            | ExtensionNotInstalled(_)
            | MissingInstalledComponent(_)
            | CachedFileChecksumFailed
            | ComponentUnavailable(_, _)
            | ForcingUnavailableComponent(_)
            | StrayHash(_) => NotificationLevel::Warn,
            NonFatalError(_) => NotificationLevel::Error,
        }
    }
}

impl<'a> Display for Notification<'a> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::result::Result<(), fmt::Error> {
        use self::Notification::*;
        match self {
            Temp(n) => n.fmt(f),
            Utils(n) => n.fmt(f),
            Extracting(_, _) => write!(f, "extracting..."),
            ComponentAlreadyInstalled(c) => write!(f, "component {} is up to date", c),
            CantReadUpdateHash(path) => write!(
                f,
                "can't read update hash file: '{}', can't skip update...",
                path.display()
            ),
            NoUpdateHash(path) => write!(f, "no update hash at: '{}'", path.display()),
            ChecksumValid(_) => write!(f, "checksum passed"),
            SignatureValid(_) => write!(f, "signature valid"),
            FileAlreadyDownloaded => write!(f, "reusing previously downloaded file"),
            CachedFileChecksumFailed => write!(f, "bad checksum for cached download"),
            RollingBack => write!(f, "rolling back changes"),
            ExtensionNotInstalled(c) => write!(f, "extension '{}' was not installed", c),
            NonFatalError(e) => write!(f, "{}", e),
            MissingInstalledComponent(c) => {
                write!(f, "during uninstall component {} was not found", c)
            }
            DownloadingComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "downloading component '{}'", c)
                } else {
                    write!(f, "downloading component '{}' for '{}'", c, t.unwrap())
                }
            }
            InstallingComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "installing component '{}'", c)
                } else {
                    write!(f, "installing component '{}' for '{}'", c, t.unwrap())
                }
            }
            RemovingComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "removing component '{}'", c)
                } else {
                    write!(f, "removing component '{}' for '{}'", c, t.unwrap())
                }
            }
            RemovingOldComponent(c, h, t) => {
                if Some(h) == t.as_ref() || t.is_none() {
                    write!(f, "removing previous version of component '{}'", c)
                } else {
                    write!(
                        f,
                        "removing previous version of component '{}' for '{}'",
                        c,
                        t.unwrap()
                    )
                }
            }
            DownloadingManifest(t) => write!(f, "syncing channel updates for '{}'", t),
            DownloadedManifest(date, Some(version)) => {
                write!(f, "latest update on {}, rust version {}", date, version)
            }
            DownloadedManifest(date, None) => {
                write!(f, "latest update on {}, no rust version", date)
            }
            DownloadingLegacyManifest => write!(f, "manifest not found. trying legacy manifest"),
            ManifestChecksumFailedHack => {
                write!(f, "update not yet available, sorry! try again later")
            }
            ComponentUnavailable(pkg, toolchain) => {
                if let Some(tc) = toolchain {
                    write!(f, "component '{}' is not available on target '{}'", pkg, tc)
                } else {
                    write!(f, "component '{}' is not available", pkg)
                }
            }
            StrayHash(path) => write!(
                f,
                "removing stray hash found at '{}' in order to continue",
                path.display()
            ),
            SkippingNightlyMissingComponent(components) => write!(
                f,
                "skipping nightly which is missing installed component '{}'",
                components[0].short_name_in_manifest()
            ),
            ForcingUnavailableComponent(component) => {
                write!(f, "Force-skipping unavailable component '{}'", component)
            }
        }
    }
}
<|endoftext|>


<commit_before>use regex::Regex;

use std::convert::Into;
use std::convert::From;

use std::option::Option;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct KeyValue<K, V> {
    k: K,
    v: V,
}

impl<K, V> KeyValue<K, V> {

    pub fn new(k: K, v: V) -> KeyValue<K, V> {
        KeyValue { k: k, v: v }
    }

}

impl<K, V> Into<(K, V)> for KeyValue<K, V> {

    fn into(self) -> (K, V) {
        (self.k, self.v)
    }

}

pub trait IntoKeyValue<K, V> {
    fn into_kv(self) -> Option<KeyValue<K, V>>;
}

impl IntoKeyValue<String, String> for String {

    fn into_kv(self) -> Option<KeyValue<String, String>> {
        let r = "^(?P<KEY>(.*))=((\"(?P<DOUBLE_QVAL>(.*))\")|(\'(?P<SINGLE_QVAL>(.*)))\'|(?P<VAL>[^\'\"](.*)[^\'\"]))$";
        let regex = Regex::new(r).unwrap();
        regex.captures(&self[..]).and_then(|cap| {
            cap.name("KEY")
                .map(|name| {
                    cap.name("SINGLE_QVAL")
                        .or(cap.name("DOUBLE_QVAL"))
                        .or(cap.name("VAL"))
                        .map(|value| KeyValue::new(String::from(name), String::from(value)))
                }).unwrap_or(None)
        })
    }

}

#[cfg(test)]
mod test {
    use super::{KeyValue, IntoKeyValue};

    #[test]
    fn test_single_quoted() {
        let s = String::from("foo='bar'").into_kv().unwrap();
        assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
    }

    #[test]
    fn test_double_quoted() {
        let s = String::from("foo=\"bar\"").into_kv().unwrap();
        assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
    }

    #[test]
    fn test_double_and_single_quoted() {
        assert!(String::from("foo=\"bar\'").into_kv().is_none());
    }

    #[test]
    fn test_single_and_double_quoted() {
        assert!(String::from("foo=\'bar\"").into_kv().is_none());
    }

    #[test]
    fn test_not_quoted() {
        let s = String::from("foo=bar").into_kv().unwrap();
        assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
    }

}

<commit_msg>Add getter for key/value<commit_after>use regex::Regex;

use std::convert::Into;
use std::convert::From;

use std::option::Option;

#[derive(Clone, Copy, Debug, PartialEq)]
pub struct KeyValue<K, V> {
    k: K,
    v: V,
}

impl<K, V> KeyValue<K, V> {

    pub fn new(k: K, v: V) -> KeyValue<K, V> {
        KeyValue { k: k, v: v }
    }

    pub fn key(&self) -> &K {
        &self.k
    }

    pub fn value(&self) -> &V {
        &self.v
    }

}

impl<K, V> Into<(K, V)> for KeyValue<K, V> {

    fn into(self) -> (K, V) {
        (self.k, self.v)
    }

}

pub trait IntoKeyValue<K, V> {
    fn into_kv(self) -> Option<KeyValue<K, V>>;
}

impl IntoKeyValue<String, String> for String {

    fn into_kv(self) -> Option<KeyValue<String, String>> {
        let r = "^(?P<KEY>(.*))=((\"(?P<DOUBLE_QVAL>(.*))\")|(\'(?P<SINGLE_QVAL>(.*)))\'|(?P<VAL>[^\'\"](.*)[^\'\"]))$";
        let regex = Regex::new(r).unwrap();
        regex.captures(&self[..]).and_then(|cap| {
            cap.name("KEY")
                .map(|name| {
                    cap.name("SINGLE_QVAL")
                        .or(cap.name("DOUBLE_QVAL"))
                        .or(cap.name("VAL"))
                        .map(|value| KeyValue::new(String::from(name), String::from(value)))
                }).unwrap_or(None)
        })
    }

}

#[cfg(test)]
mod test {
    use super::{KeyValue, IntoKeyValue};

    #[test]
    fn test_single_quoted() {
        let s = String::from("foo='bar'").into_kv().unwrap();
        assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
    }

    #[test]
    fn test_double_quoted() {
        let s = String::from("foo=\"bar\"").into_kv().unwrap();
        assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
    }

    #[test]
    fn test_double_and_single_quoted() {
        assert!(String::from("foo=\"bar\'").into_kv().is_none());
    }

    #[test]
    fn test_single_and_double_quoted() {
        assert!(String::from("foo=\'bar\"").into_kv().is_none());
    }

    #[test]
    fn test_not_quoted() {
        let s = String::from("foo=bar").into_kv().unwrap();
        assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
    }

}

<|endoftext|>