<commit_before>use std::fmt::{self, Display, Formatter, Write};
use std::str;

pub struct MarkupDisplay<E, T>
where
    E: Escaper,
    T: Display,
{
    value: DisplayValue<T>,
    escaper: E,
}

impl<E, T> MarkupDisplay<E, T>
where
    E: Escaper,
    T: Display,
{
    pub fn new_unsafe(value: T, escaper: E) -> Self {
        Self {
            value: DisplayValue::Unsafe(value),
            escaper,
        }
    }

    pub fn new_safe(value: T, escaper: E) -> Self {
        Self {
            value: DisplayValue::Safe(value),
            escaper,
        }
    }

    pub fn mark_safe(mut self) -> MarkupDisplay<E, T> {
        self.value = match self.value {
            DisplayValue::Unsafe(t) => DisplayValue::Safe(t),
            _ => self.value,
        };
        self
    }
}

impl<E, T> Display for MarkupDisplay<E, T>
where
    E: Escaper,
    T: Display,
{
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        match self.value {
            DisplayValue::Unsafe(ref t) => write!(
                EscapeWriter {
                    fmt,
                    escaper: &self.escaper
                },
                "{}",
                t
            ),
            DisplayValue::Safe(ref t) => t.fmt(fmt),
        }
    }
}

pub struct EscapeWriter<'a, E, W> {
    fmt: W,
    escaper: &'a E,
}

impl<'a, E, W> Write for EscapeWriter<'a, E, W>
where
    W: Write,
    E: Escaper,
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.escaper.write_escaped(&mut self.fmt, s)
    }
}

pub fn escape<E>(string: &str, escaper: E) -> Escaped<'_, E>
where
    E: Escaper,
{
    Escaped { string, escaper }
}

pub struct Escaped<'a, E>
where
    E: Escaper,
{
    string: &'a str,
    escaper: E,
}

impl<'a, E> ::std::fmt::Display for Escaped<'a, E>
where
    E: Escaper,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.escaper.write_escaped(fmt, self.string)
    }
}

pub struct Html;

macro_rules! escaping_body {
    ($start:ident, $i:ident, $fmt:ident, $bytes:ident, $quote:expr) => {{
        if $start < $i {
            $fmt.write_str(unsafe { str::from_utf8_unchecked(&$bytes[$start..$i]) })?;
        }
        $fmt.write_str($quote)?;
        $start = $i + 1;
    }};
}

impl Escaper for Html {
    fn write_escaped<W>(&self, mut fmt: W, string: &str) -> fmt::Result
    where
        W: Write,
    {
        let bytes = string.as_bytes();
        let mut start = 0;
        for (i, b) in bytes.iter().enumerate() {
            if b.wrapping_sub(b'"') <= FLAG {
                match *b {
                    b'<' => escaping_body!(start, i, fmt, bytes, "<"),
                    b'>' => escaping_body!(start, i, fmt, bytes, ">"),
                    b'&' => escaping_body!(start, i, fmt, bytes, "&"),
                    b'"' => escaping_body!(start, i, fmt, bytes, """),
                    b'\'' => escaping_body!(start, i, fmt, bytes, "'"),
                    b'/' => escaping_body!(start, i, fmt, bytes, "/"),
                    _ => (),
                }
            }
        }
        if start < bytes.len() {
            fmt.write_str(unsafe { str::from_utf8_unchecked(&bytes[start..]) })
        } else {
            Ok(())
        }
    }
}

pub struct Text;

impl Escaper for Text {
    fn write_escaped<W>(&self, mut fmt: W, string: &str) -> fmt::Result
    where
        W: Write,
    {
        fmt.write_str(string)
    }
}

#[derive(Debug, PartialEq)]
enum DisplayValue<T>
where
    T: Display,
{
    Safe(T),
    Unsafe(T),
}

pub trait Escaper {
    fn write_escaped<W>(&self, fmt: W, string: &str) -> fmt::Result
    where
        W: Write;
}

const FLAG: u8 = b'>' - b'"';

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_escape() {
        assert_eq!(escape("", Html).to_string(), "");
        assert_eq!(escape("<&>", Html).to_string(), "<&>");
        assert_eq!(escape("bla&", Html).to_string(), "bla&");
        assert_eq!(escape("<foo", Html).to_string(), "<foo");
        assert_eq!(escape("bla&h", Html).to_string(), "bla&h");
    }
}
<commit_msg>Add no_std support to askama_escape<commit_after>#![no_std]

#[cfg(test)]
extern crate std;

use core::fmt::{self, Display, Formatter, Write};
use core::str;

pub struct MarkupDisplay<E, T>
where
    E: Escaper,
    T: Display,
{
    value: DisplayValue<T>,
    escaper: E,
}

impl<E, T> MarkupDisplay<E, T>
where
    E: Escaper,
    T: Display,
{
    pub fn new_unsafe(value: T, escaper: E) -> Self {
        Self {
            value: DisplayValue::Unsafe(value),
            escaper,
        }
    }

    pub fn new_safe(value: T, escaper: E) -> Self {
        Self {
            value: DisplayValue::Safe(value),
            escaper,
        }
    }

    pub fn mark_safe(mut self) -> MarkupDisplay<E, T> {
        self.value = match self.value {
            DisplayValue::Unsafe(t) => DisplayValue::Safe(t),
            _ => self.value,
        };
        self
    }
}

impl<E, T> Display for MarkupDisplay<E, T>
where
    E: Escaper,
    T: Display,
{
    fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
        match self.value {
            DisplayValue::Unsafe(ref t) => write!(
                EscapeWriter {
                    fmt,
                    escaper: &self.escaper
                },
                "{}",
                t
            ),
            DisplayValue::Safe(ref t) => t.fmt(fmt),
        }
    }
}

pub struct EscapeWriter<'a, E, W> {
    fmt: W,
    escaper: &'a E,
}

impl<'a, E, W> Write for EscapeWriter<'a, E, W>
where
    W: Write,
    E: Escaper,
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.escaper.write_escaped(&mut self.fmt, s)
    }
}

pub fn escape<E>(string: &str, escaper: E) -> Escaped<'_, E>
where
    E: Escaper,
{
    Escaped { string, escaper }
}

pub struct Escaped<'a, E>
where
    E: Escaper,
{
    string: &'a str,
    escaper: E,
}

impl<'a, E> Display for Escaped<'a, E>
where
    E: Escaper,
{
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.escaper.write_escaped(fmt, self.string)
    }
}

pub struct Html;

macro_rules! escaping_body {
    ($start:ident, $i:ident, $fmt:ident, $bytes:ident, $quote:expr) => {{
        if $start < $i {
            $fmt.write_str(unsafe { str::from_utf8_unchecked(&$bytes[$start..$i]) })?;
        }
        $fmt.write_str($quote)?;
        $start = $i + 1;
    }};
}

impl Escaper for Html {
    fn write_escaped<W>(&self, mut fmt: W, string: &str) -> fmt::Result
    where
        W: Write,
    {
        let bytes = string.as_bytes();
        let mut start = 0;
        for (i, b) in bytes.iter().enumerate() {
            if b.wrapping_sub(b'"') <= FLAG {
                match *b {
                    b'<' => escaping_body!(start, i, fmt, bytes, "<"),
                    b'>' => escaping_body!(start, i, fmt, bytes, ">"),
                    b'&' => escaping_body!(start, i, fmt, bytes, "&"),
                    b'"' => escaping_body!(start, i, fmt, bytes, """),
                    b'\'' => escaping_body!(start, i, fmt, bytes, "'"),
                    b'/' => escaping_body!(start, i, fmt, bytes, "/"),
                    _ => (),
                }
            }
        }
        if start < bytes.len() {
            fmt.write_str(unsafe { str::from_utf8_unchecked(&bytes[start..]) })
        } else {
            Ok(())
        }
    }
}

pub struct Text;

impl Escaper for Text {
    fn write_escaped<W>(&self, mut fmt: W, string: &str) -> fmt::Result
    where
        W: Write,
    {
        fmt.write_str(string)
    }
}

#[derive(Debug, PartialEq)]
enum DisplayValue<T>
where
    T: Display,
{
    Safe(T),
    Unsafe(T),
}

pub trait Escaper {
    fn write_escaped<W>(&self, fmt: W, string: &str) -> fmt::Result
    where
        W: Write;
}

const FLAG: u8 = b'>' - b'"';

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

    #[test]
    fn test_escape() {
        assert_eq!(escape("", Html).to_string(), "");
        assert_eq!(escape("<&>", Html).to_string(), "<&>");
        assert_eq!(escape("bla&", Html).to_string(), "bla&");
        assert_eq!(escape("<foo", Html).to_string(), "<foo");
        assert_eq!(escape("bla&h", Html).to_string(), "bla&h");
    }
}
<|endoftext|>


<commit_before>use piston_window::UpdateArgs;
use rand::{Rng, thread_rng};

use player::{Player, Ship};
use settings::Settings;

pub struct App {
    pub settings: Settings,
    pub players: [Player; 2],
    pub state: u8,
    pub turn: u8,
    pub turn_active: bool,
    pub game_over: bool,
    pub winner: Option<u8>,
    pub turn_end_timer: f64,
    pub cpu_turn_timer: f64,
    pub grid_area: [u32; 4],
    pub window_size: [u32; 2],
    mouse_cursor: [f64; 2],
    pub ship_temp_pos: Vec<[u8; 2]>,
    ship_temp_dir: u8,
}

impl App {
    pub fn new(space_size: u32, width: u8, height: u8) -> App {
        let grid_area = [
            space_size,
            space_size * 3,
            width as u32 * space_size,
            height as u32 * space_size
        ];

        let window_size = [
            grid_area[2] + space_size * 2,
            grid_area[3] + space_size * 4
        ];

        App {
            settings: Settings {
                space_size: space_size,
                width: width,
                height: height,
            },
            players: [Player::new(false), Player::new(true)],
            state: 0,
            turn: 0,
            turn_active: true,
            game_over: false,
            winner: None,
            turn_end_timer: 0.0,
            cpu_turn_timer: 0.0,
            grid_area: grid_area,
            window_size: window_size,
            mouse_cursor: [0.0; 2],
            ship_temp_pos: vec![[0, 0], [1, 0]],
            ship_temp_dir: 0,
        }
    }

    pub fn update(&mut self, u: &UpdateArgs) {
        if self.state == 0 {
            if self.players[self.turn as usize].is_cpu {
                self.players[self.turn as usize].cpu_place_ships();
            }

            if self.players[self.turn as usize].ships.len() == 4 {
                self.switch_turn();
            }

            // All ships have been placed; start the game.
            if self.players[0].ships.len() == 4 && self.players[1].ships.len() == 4 {
                self.state = 1;
            }
        } else if self.state == 1 || self.state == 2 {
            if !self.turn_active && !self.game_over {

                // Continue/end the end-of-turn delay.
                if self.turn_end_timer < 1.5 {
                    self.turn_end_timer += u.dt;
                } else {
                    if self.state != 2 {
                        self.switch_turn();
                    } else {
                        self.game_over = true;
                        self.winner = Some(self.turn);
                    }
                }
            }

            // Continue/end the delay when CPU players take their turn.
            if self.turn_active && self.players[self.turn as usize].is_cpu {
                self.cpu_turn_timer += u.dt;
                if self.cpu_turn_timer >= 1.0 {
                    self.cpu_turn_timer = 0.0;
                    self.cpu_select_space();
                }
            }
        }
    }

    /// Selects a space, and performs related checks on the status of ships if
    /// there's a hit.
    fn select_space(&mut self, x: u8, y: u8) {
        let ref mut opponent = self.players[self.not_turn()];
        let mut space_state = 1;
        let mut hit_ship = None;
        for (i, ship) in opponent.ships.iter().enumerate() {
            if ship.position.contains(&[x, y]) {
                space_state = 2;
                hit_ship = Some(i);
            }
        }

        let space = opponent.spaces.iter().position(|space| space.position == [x, y]).unwrap();
        opponent.spaces[space].state = space_state;

        if space_state == 2 {
            // Check if this ship has sunk.
            let hit_ship = hit_ship.unwrap();
            let mut ship_state = false;
            for ship_pos in &opponent.ships[hit_ship].position {
                if let Some(space) = opponent.spaces.iter().position(|space| &space.position == ship_pos) {
                    if opponent.spaces[space].state == 0 {
                        ship_state = true;
                    }
                }
            }

            if !ship_state {
                opponent.ships[hit_ship].state = ship_state;
            }

            // Check if any ships are left.
            let mut all_sunk = true;
            for ship in &opponent.ships {
                if ship.state {
                    all_sunk = false;
                    break;
                }
            }

            if all_sunk {
                self.state = 2;
            }
        }

        self.turn_active = false;
    }

    /// Uses RNG to select a space for CPU players.
    pub fn cpu_select_space(&mut self) {
        let mut rng = thread_rng();
        let mut first_hit = None;
        let mut select = vec![];

        // Determines the order of priority of directions to check if there are
        // any hit spaces found.
        let mut directions: [[i32; 2]; 4] = [
            [-1, 0],
            [1, 0],
            [0, -1],
            [0, 1]
        ];
        rng.shuffle(&mut directions);

        {
            let ref opponent = self.players[self.not_turn()];
            for space in &opponent.spaces {
                if space.state == 2 {
                    for ship in &opponent.ships {

                        // Make sure this hit space belongs to an unsunk ship.
                        if ship.state && ship.position.contains(&space.position) {
                            if first_hit.is_none() {
                                first_hit = Some(space.position);
                            }

                            // Check if this space forms part of a line of hit
                            // spaces.  If it does, and the space at the end of
                            // the line hasn't been selected yet, it's a
                            // candidate for selection this turn.
                            for check in &directions {
                                let mut xc = space.position[0];
                                let mut yc = space.position[1];

                                while opponent.get_space_state((xc as i32 + check[0]) as u8, (yc as i32 + check[1]) as u8) == Some(2) {
                                    xc = (xc as i32 + check[0]) as u8;
                                    yc = (yc as i32 + check[1]) as u8;
                                }

                                if opponent.get_space_state((xc as i32 + check[0]) as u8, (yc as i32 + check[1]) as u8) == Some(0) && (xc != space.position[0] || yc != space.position[1]) {
                                    select.push([
                                        (xc as i32 + check[0]) as u8,
                                        (yc as i32 + check[1]) as u8
                                    ]);
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            // If a hit space was found, but no hit spaces next to it, select
            // a non-selected space next to it.
            if first_hit.is_some() && select.len() == 0 {
                let first_hit = first_hit.unwrap();
                for check in &directions {
                    if opponent.get_space_state((first_hit[0] as i32 + check[0]) as u8, (first_hit[1] as i32 + check[1]) as u8) == Some(0) {
                        select.push([
                            (first_hit[0] as i32 + check[0]) as u8,
                            (first_hit[1] as i32 + check[1]) as u8
                        ]);
                        break;
                    }
                }
            }

            // If no spaces were selected to check, just check any available space.
            if select.len() == 0 {
                let mut x: u8 = rng.gen_range(0, self.settings.width);
                let mut y: u8 = rng.gen_range(0, self.settings.height);
                let mut space_state = opponent.get_space_state(x, y);

                while space_state.is_some() && space_state != Some(0) {
                    x = rng.gen_range(0, self.settings.width);
                    y = rng.gen_range(0, self.settings.height);
                    space_state = opponent.get_space_state(x, y);
                }

                select.push([x, y]);
            }
        }

        // The way the potential selections are chosen, empty spaces to the
        // right or bottom of a line of hit spaces will always be chosen first,
        // so the list of selections should be shuffled.
        if select.len() > 1 {
            select.dedup();
            rng.shuffle(&mut select);
        }

        self.select_space(select[0][0], select[0][1]);
    }

    /// Returns the player who is not currently taking their turn.
    pub fn not_turn(&self) -> usize {
        (self.turn + 1) as usize % 2
    }

    /// When a player's turn is finished, this sets the other player as active.
    fn switch_turn(&mut self) {
        self.turn = self.not_turn() as u8;
        self.turn_active = true;
        self.turn_end_timer = 0.0;
    }

    /// Processes all left mouse clicks according to the current program state.
    pub fn mouse_left_click(&mut self) {
        if let Some(grid_pos) = self.mouse_cursor_grid_position() {
            if self.state == 0 && self.turn_active && !self.players[self.turn as usize].is_cpu {

                // State 0: place ships.
                let mut ship = vec![];
                for pos in &self.ship_temp_pos {
                    ship.push(*pos);
                }

                if self.players[self.turn as usize].valid_ship_position(&ship) {
                    self.players[self.turn as usize].ships.push(Ship {
                        position: ship,
                        state: true,
                    });
                }
            } else if self.state == 1 && self.turn_active && !self.players[self.turn as usize].is_cpu {

                // State 1: select spaces on opponent's grid.
                if let Some(space) = self.players[self.not_turn()].spaces.iter().position(|space| space.position == grid_pos) {
                    if self.players[self.not_turn()].spaces[space].state == 0 {
                        self.select_space(grid_pos[0], grid_pos[1]);
                    }
                }
            }
        }
    }

    /// Processes all right mouse clicks according to the current program state.
    pub fn mouse_right_click(&mut self) {
        if self.state == 0 {

            // State 0: rotate ships.
            let mut new_ship_pos = vec![self.ship_temp_pos[0]];
            match self.ship_temp_dir {
                0 => {
                    self.ship_temp_dir = 1;
                    let length = self.players[self.turn as usize].ships.len() + 2;
                    for pos in 1..length {
                        new_ship_pos.push([self.ship_temp_pos[0][0], self.ship_temp_pos[0][1] + pos as u8]);
                    }
                },
                1 => {
                    self.ship_temp_dir = 0;
                    let length = self.players[self.turn as usize].ships.len() + 2;
                    for pos in 1..length {
                        new_ship_pos.push([self.ship_temp_pos[0][0] + pos as u8, self.ship_temp_pos[0][1]]);
                    }
                },
                _ => {}
            }

            self.ship_temp_pos = new_ship_pos;
        }
    }

    /// Records the last known mouse cursor position.
    pub fn mouse_cursor_movement(&mut self, c: &[f64; 2]) {
        self.mouse_cursor = *c;

        if let Some(grid_pos) = self.mouse_cursor_grid_position() {
            let ref mut player = self.players[self.turn as usize];

            // During ship placement, set the temporary ship position so it can
            // be drawn by the window renderer.
            if self.state == 0 {
                self.ship_temp_pos = player.get_ship_position(
                    grid_pos,
                    self.ship_temp_dir,
                    player.ships.len() as u8 + 2
                );
            }

            // State 1: set the player's grid cursor.
            if self.state == 1 {
                if self.turn_end_timer == 0.0 && !player.is_cpu {
                    player.grid_cursor = grid_pos;
                }
            }
        }
    }

    /// Returns the grid coordinates of the mouse cursor position.
    fn mouse_cursor_grid_position(&self) -> Option<[u8; 2]> {
        let position: Option<[u8; 2]>;
        if self.mouse_cursor[0] >= self.grid_area[0] as f64
            && self.mouse_cursor[1] >= self.grid_area[1] as f64
            && self.mouse_cursor[0] < (self.grid_area[0] + self.grid_area[2]) as f64
            && self.mouse_cursor[1] < (self.grid_area[1] + self.grid_area[3]) as f64
        {
            position = Some([
                ((self.mouse_cursor[0] - self.grid_area[0] as f64) / self.settings.space_size as f64) as u8,
                ((self.mouse_cursor[1] - self.grid_area[1] as f64) / self.settings.space_size as f64) as u8,
            ]);
        } else {
            position = None;
        }

        position
    }
}

<commit_msg>Partial cleanup of cpu_select_space function<commit_after>use piston_window::UpdateArgs;
use rand::{Rng, thread_rng};

use player::{Player, Ship};
use settings::Settings;

pub struct App {
    pub settings: Settings,
    pub players: [Player; 2],
    pub state: u8,
    pub turn: u8,
    pub turn_active: bool,
    pub game_over: bool,
    pub winner: Option<u8>,
    pub turn_end_timer: f64,
    pub cpu_turn_timer: f64,
    pub grid_area: [u32; 4],
    pub window_size: [u32; 2],
    mouse_cursor: [f64; 2],
    pub ship_temp_pos: Vec<[u8; 2]>,
    ship_temp_dir: u8,
}

impl App {
    pub fn new(space_size: u32, width: u8, height: u8) -> App {
        let grid_area = [
            space_size,
            space_size * 3,
            width as u32 * space_size,
            height as u32 * space_size
        ];

        let window_size = [
            grid_area[2] + space_size * 2,
            grid_area[3] + space_size * 4
        ];

        App {
            settings: Settings {
                space_size: space_size,
                width: width,
                height: height,
            },
            players: [Player::new(false), Player::new(true)],
            state: 0,
            turn: 0,
            turn_active: true,
            game_over: false,
            winner: None,
            turn_end_timer: 0.0,
            cpu_turn_timer: 0.0,
            grid_area: grid_area,
            window_size: window_size,
            mouse_cursor: [0.0; 2],
            ship_temp_pos: vec![[0, 0], [1, 0]],
            ship_temp_dir: 0,
        }
    }

    pub fn update(&mut self, u: &UpdateArgs) {
        if self.state == 0 {
            if self.players[self.turn as usize].is_cpu {
                self.players[self.turn as usize].cpu_place_ships();
            }

            if self.players[self.turn as usize].ships.len() == 4 {
                self.switch_turn();
            }

            // All ships have been placed; start the game.
            if self.players[0].ships.len() == 4 && self.players[1].ships.len() == 4 {
                self.state = 1;
            }
        } else if self.state == 1 || self.state == 2 {
            if !self.turn_active && !self.game_over {

                // Continue/end the end-of-turn delay.
                if self.turn_end_timer < 1.5 {
                    self.turn_end_timer += u.dt;
                } else {
                    if self.state != 2 {
                        self.switch_turn();
                    } else {
                        self.game_over = true;
                        self.winner = Some(self.turn);
                    }
                }
            }

            // Continue/end the delay when CPU players take their turn.
            if self.turn_active && self.players[self.turn as usize].is_cpu {
                self.cpu_turn_timer += u.dt;
                if self.cpu_turn_timer >= 1.0 {
                    self.cpu_turn_timer = 0.0;
                    let cpu_space = self.cpu_select_space();
                    self.select_space(cpu_space[0], cpu_space[1]);
                }
            }
        }
    }

    /// Selects a space, and performs related checks on the status of ships if
    /// there's a hit.
    fn select_space(&mut self, x: u8, y: u8) {
        let ref mut opponent = self.players[self.not_turn()];
        let mut space_state = 1;
        let mut hit_ship = None;
        for (i, ship) in opponent.ships.iter().enumerate() {
            if ship.position.contains(&[x, y]) {
                space_state = 2;
                hit_ship = Some(i);
            }
        }

        let space = opponent.spaces.iter().position(|space| space.position == [x, y]).unwrap();
        opponent.spaces[space].state = space_state;

        if space_state == 2 {
            // Check if this ship has sunk.
            let hit_ship = hit_ship.unwrap();
            let mut ship_state = false;
            for ship_pos in &opponent.ships[hit_ship].position {
                if let Some(space) = opponent.spaces.iter().position(|space| &space.position == ship_pos) {
                    if opponent.spaces[space].state == 0 {
                        ship_state = true;
                    }
                }
            }

            if !ship_state {
                opponent.ships[hit_ship].state = ship_state;
            }

            // Check if any ships are left.
            let mut all_sunk = true;
            for ship in &opponent.ships {
                if ship.state {
                    all_sunk = false;
                    break;
                }
            }

            if all_sunk {
                self.state = 2;
            }
        }

        self.turn_active = false;
    }

    /// Uses RNG to select a space for CPU players.
    fn cpu_select_space(&mut self) -> [u8; 2] {
        let mut rng = thread_rng();
        let mut first_hit = None;
        let mut select = vec![];

        // Determines the order of priority of directions to check if there are
        // any hit spaces found.
        let mut directions: [[i32; 2]; 4] = [
            [-1, 0],
            [1, 0],
            [0, -1],
            [0, 1]
        ];
        rng.shuffle(&mut directions);

        let ref opponent = self.players[self.not_turn()];

        for space in &opponent.spaces {
            if space.state == 2 {

                // Get the hit ship.
                let mut ship: Option<&Ship> = None;
                for s in &opponent.ships {
                    if s.position.contains(&space.position) {
                        ship = Some(s);
                        break;
                    }
                }

                // Make sure the hit ship hasn't been sunk.
                if ship.unwrap().state {
                    if first_hit.is_none() {
                        first_hit = Some(space.position);
                    }

                    // Check if this space forms part of a line of hit spaces.
                    // If it does, and the space at the end hasn't been
                    // selected yet, it's a candidate for selection this turn.
                    for check in &directions {
                        let mut xc = space.position[0];
                        let mut yc = space.position[1];

                        while opponent.get_space_state((xc as i32 + check[0]) as u8, (yc as i32 + check[1]) as u8) == Some(2) {
                            xc = (xc as i32 + check[0]) as u8;
                            yc = (yc as i32 + check[1]) as u8;
                        }

                        if opponent.get_space_state((xc as i32 + check[0]) as u8, (yc as i32 + check[1]) as u8) == Some(0) && (xc != space.position[0] || yc != space.position[1]) {
                            select.push([
                                (xc as i32 + check[0]) as u8,
                                (yc as i32 + check[1]) as u8
                            ]);
                            break;
                        }
                    }
                }
            }
        }

        // If a hit space was found, but no hit spaces next to it, select a
        // non-selected space next to it.
        if first_hit.is_some() && select.len() == 0 {
            let first_hit = first_hit.unwrap();
            for check in &directions {
                if opponent.get_space_state((first_hit[0] as i32 + check[0]) as u8, (first_hit[1] as i32 + check[1]) as u8) == Some(0) {
                    select.push([
                        (first_hit[0] as i32 + check[0]) as u8,
                        (first_hit[1] as i32 + check[1]) as u8
                    ]);
                    break;
                }
            }
        }

        // If no spaces were selected to check, just check any available space.
        if select.len() == 0 {
            let mut x: u8 = rng.gen_range(0, self.settings.width);
            let mut y: u8 = rng.gen_range(0, self.settings.height);
            let mut space_state = opponent.get_space_state(x, y);

            while space_state != Some(0) {
                x = rng.gen_range(0, self.settings.width);
                y = rng.gen_range(0, self.settings.height);
                space_state = opponent.get_space_state(x, y);
            }

            select.push([x, y]);
        }

        // The way the potential selections are chosen, empty spaces to the
        // right or bottom of a line of hit spaces will always be chosen first,
        // so the list of selections should be shuffled.
        if select.len() > 1 {
            select.dedup();
            rng.shuffle(&mut select);
        }

        select[0]
    }

    /// Returns the player who is not currently taking their turn.
    pub fn not_turn(&self) -> usize {
        (self.turn + 1) as usize % 2
    }

    /// When a player's turn is finished, this sets the other player as active.
    fn switch_turn(&mut self) {
        self.turn = self.not_turn() as u8;
        self.turn_active = true;
        self.turn_end_timer = 0.0;
    }

    /// Processes all left mouse clicks according to the current program state.
    pub fn mouse_left_click(&mut self) {
        if let Some(grid_pos) = self.mouse_cursor_grid_position() {
            if self.state == 0 && self.turn_active && !self.players[self.turn as usize].is_cpu {

                // State 0: place ships.
                let mut ship = vec![];
                for pos in &self.ship_temp_pos {
                    ship.push(*pos);
                }

                if self.players[self.turn as usize].valid_ship_position(&ship) {
                    self.players[self.turn as usize].ships.push(Ship {
                        position: ship,
                        state: true,
                    });
                }
            } else if self.state == 1 && self.turn_active && !self.players[self.turn as usize].is_cpu {

                // State 1: select spaces on opponent's grid.
                if let Some(space) = self.players[self.not_turn()].spaces.iter().position(|space| space.position == grid_pos) {
                    if self.players[self.not_turn()].spaces[space].state == 0 {
                        self.select_space(grid_pos[0], grid_pos[1]);
                    }
                }
            }
        }
    }

    /// Processes all right mouse clicks according to the current program state.
    pub fn mouse_right_click(&mut self) {
        if self.state == 0 {

            // State 0: rotate ships.
            let mut new_ship_pos = vec![self.ship_temp_pos[0]];
            match self.ship_temp_dir {
                0 => {
                    self.ship_temp_dir = 1;
                    let length = self.players[self.turn as usize].ships.len() + 2;
                    for pos in 1..length {
                        new_ship_pos.push([self.ship_temp_pos[0][0], self.ship_temp_pos[0][1] + pos as u8]);
                    }
                },
                1 => {
                    self.ship_temp_dir = 0;
                    let length = self.players[self.turn as usize].ships.len() + 2;
                    for pos in 1..length {
                        new_ship_pos.push([self.ship_temp_pos[0][0] + pos as u8, self.ship_temp_pos[0][1]]);
                    }
                },
                _ => {}
            }

            self.ship_temp_pos = new_ship_pos;
        }
    }

    /// Records the last known mouse cursor position.
    pub fn mouse_cursor_movement(&mut self, c: &[f64; 2]) {
        self.mouse_cursor = *c;

        if let Some(grid_pos) = self.mouse_cursor_grid_position() {
            let ref mut player = self.players[self.turn as usize];

            // During ship placement, set the temporary ship position so it can
            // be drawn by the window renderer.
            if self.state == 0 {
                self.ship_temp_pos = player.get_ship_position(
                    grid_pos,
                    self.ship_temp_dir,
                    player.ships.len() as u8 + 2
                );
            }

            // State 1: set the player's grid cursor.
            if self.state == 1 {
                if self.turn_end_timer == 0.0 && !player.is_cpu {
                    player.grid_cursor = grid_pos;
                }
            }
        }
    }

    /// Returns the grid coordinates of the mouse cursor position.
    fn mouse_cursor_grid_position(&self) -> Option<[u8; 2]> {
        let position: Option<[u8; 2]>;
        if self.mouse_cursor[0] >= self.grid_area[0] as f64
            && self.mouse_cursor[1] >= self.grid_area[1] as f64
            && self.mouse_cursor[0] < (self.grid_area[0] + self.grid_area[2]) as f64
            && self.mouse_cursor[1] < (self.grid_area[1] + self.grid_area[3]) as f64
        {
            position = Some([
                ((self.mouse_cursor[0] - self.grid_area[0] as f64) / self.settings.space_size as f64) as u8,
                ((self.mouse_cursor[1] - self.grid_area[1] as f64) / self.settings.space_size as f64) as u8,
            ]);
        } else {
            position = None;
        }

        position
    }
}

<|endoftext|>


<commit_before>extern crate libc;

use std::env;

use ArgMatches;
use Arg;
use args::OptArg;
use args::FlagArg;
use args::PosArg;

pub struct App {
	pub name: &'static str,
	pub author: Option<&'static str>,
	pub version: Option<&'static str>,
	pub about: Option<&'static str>,
	// raw_args: Vec<Arg>,
	flags: Vec<FlagArg>,
	opts: Vec<OptArg>,
	positionals: Vec<PosArg>,
	needs_long_help: bool,
	needs_long_version: bool,
	needs_short_help: bool,
	needs_short_version: bool
}

impl App {
	pub fn new(n: &'static str) -> App {
		App {
			name: n,
			author: None,
			about: None,
			version: None,
			// raw_args: vec![],
			flags: vec![],
			opts: vec![],
			needs_long_version: true,
			needs_long_help: true,
			positionals: vec![],
			needs_short_help: true,
			needs_short_version: true
		}
	}

	pub fn author(&mut self, a: &'static str) -> &mut App {
		self.author = Some(a);
		self
	}

	pub fn about(&mut self, a: &'static str) -> &mut App {
		self.about = Some(a);
		self
	}

	pub fn version(&mut self, v: &'static str)-> &mut App  {
		self.version = Some(v);
		self
	}

	pub fn arg(&mut self, a: &Arg) -> &mut App {
		if let Some(i) = a.index {
			self.positionals.push(PosArg {
				name: a.name,
				index: i,
				required: a.required,
				help: a.help,
				value: None

			});
		} else if a.takes_value {
			self.opts.push(OptArg {
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
				required: a.required,
				value: None
			});
		} else {
			if let Some(l) = a.long {
				if l == "help" {
					self.needs_long_help = false;
				} else if l == "version" {
					self.needs_long_version = false;
				}
			}
			if let Some(s) = a.short {
				if s == 'h' {
					self.needs_short_help = false;
				} else if s == 'v' {
					self.needs_short_version = false;
				}
			}
			self.flags.push(FlagArg{
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
			});
		}
		self
	}

	pub fn print_help(&self) {
		println!("Help info!");
		unsafe { libc::exit(0); }
	}

	pub fn print_version(&self) {
		println!("Version Info!");
		unsafe { libc::exit(0); }
	}

	pub fn get_matches(&mut self) -> ArgMatches {

		let mut matches = ArgMatches::new(self);

		let mut needs_val = false;
		let mut needs_val_of = String::new();
		let mut pos_counter = 1;
		for arg in env::args().collect::<Vec<String>>().tail() {
			let arg_slice = arg.as_slice();
			if needs_val {
				for o in self.opts.iter() {
					if needs_val_of == o.name.to_string() {
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(arg.clone())
						});
						needs_val = false;
						needs_val_of.clear();
						break;
					}
				}
				continue;
			}
			if arg_slice.starts_with("--") {
				// Single flag, or option
				let mut p_arg = arg_slice.trim_left_matches(|c| c == '-');
				let mut found = false;
				if p_arg == "help" && self.needs_long_help {
					self.print_help();
				} else if p_arg == "version" && self.needs_long_version {
					self.print_version();
				}
				for f in self.flags.iter() {
					if let Some(l) = f.long {
						if l == p_arg {
							matches.flags.push(f.clone());
							found = true;
							break;
						}
					}
				}
				if found { continue; }
				if p_arg.as_slice().contains("=") {
					let p_argv: Vec<&str> = p_arg.split_str("=").collect();
					p_arg = p_argv[0];
					for o in self.opts.iter() {
						if let Some(l) = o.long {
							if l == p_arg {
								// found = true;
								matches.opts.push(OptArg{
									name: o.name,
								    short: o.short,
								    long: o.long,
								    help: o.help,
								    required: o.required,
								    value: Some(p_argv[1].to_string())
								});
								break;
							}
						}
					}
				} else {
					for o in self.opts.iter() {
						if let Some(l) = o.long {
							if l == p_arg {
								found = true;
								needs_val = true;
								needs_val_of = o.name.to_string();
								break;
							}
						}
					}
					// Fails if argument supplied to binary isn't valid
					assert!(found == false);
					continue;
				}
			} else if arg_slice.starts_with("-") {
				if arg_slice.len() > 2 {
					// Multiple flags using short i.e. -bgHlS
					let p_arg = arg_slice.trim_left_matches(|c| c == '-');
					let mut found = false;
					for c in p_arg.chars() {
						if c == 'h' && self.needs_short_help {
							self.print_help();
						} else if c == 'v' && self.needs_short_version {
							self.print_version();
						}
						for f in self.flags.iter() {
							if let Some(s) = f.short {
								if c == s {
									found = true;
									matches.flags.push(f.clone());
								}
							}
						}
						// Fails if argument supplied to binary isn't valid
						assert!(found == false);
						continue;
					}
				} else {
					// Short flag or opt
					let mut found = false;
					let p_arg = arg_slice.char_at(1);
					if p_arg == 'h' && self.needs_short_help {
						self.print_help();
					} else if p_arg == 'v' && self.needs_short_version {
						self.print_version();
					}
					for f in self.flags.iter() {
						if let Some(s) = f.short {
							if p_arg == s {
								found = true;
								matches.flags.push(f.clone());
							}
						}
					}
					for o in self.opts.iter() {
						if let Some(s) = o.short {
							if s == p_arg {
								found = true;
								needs_val = true;
								needs_val_of = o.name.to_string();
								break;
							}
						}
					}
					// Fails if argument supplied to binary isn't valid
					assert!(found == false);
					continue;
				}
			} else {
				// Positional

				// Fails if no positionals are expected/possible
				assert!(self.positionals.is_empty() == false);
				for p in self.positionals.iter() {
					matches.positionals.push(PosArg{
						name: p.name,
						help: p.help,
						required: p.required,
						value: Some(arg.clone()),
						index: pos_counter
					});
					pos_counter += 1;
				}
			}

		}

		// Fails if we reached the end of args() but were still
		// expecting a value, such as ./fake -c
		// where -c takes a value
		assert!(needs_val == false);

		matches
	}
}<commit_msg>v0.0.3.7<commit_after>extern crate libc;

use std::env;

use ArgMatches;
use Arg;
use args::OptArg;
use args::FlagArg;
use args::PosArg;

pub struct App {
	pub name: &'static str,
	pub author: Option<&'static str>,
	pub version: Option<&'static str>,
	pub about: Option<&'static str>,
	// raw_args: Vec<Arg>,
	flags: Vec<FlagArg>,
	opts: Vec<OptArg>,
	positionals: Vec<PosArg>,
	needs_long_help: bool,
	needs_long_version: bool,
	needs_short_help: bool,
	needs_short_version: bool
}

impl App {
	pub fn new(n: &'static str) -> App {
		App {
			name: n,
			author: None,
			about: None,
			version: None,
			// raw_args: vec![],
			flags: vec![],
			opts: vec![],
			needs_long_version: true,
			needs_long_help: true,
			positionals: vec![],
			needs_short_help: true,
			needs_short_version: true
		}
	}

	pub fn author(&mut self, a: &'static str) -> &mut App {
		self.author = Some(a);
		self
	}

	pub fn about(&mut self, a: &'static str) -> &mut App {
		self.about = Some(a);
		self
	}

	pub fn version(&mut self, v: &'static str)-> &mut App  {
		self.version = Some(v);
		self
	}

	pub fn arg(&mut self, a: &Arg) -> &mut App {
		if let Some(i) = a.index {
			self.positionals.push(PosArg {
				name: a.name,
				index: i,
				required: a.required,
				help: a.help,
				value: None

			});
		} else if a.takes_value {
			self.opts.push(OptArg {
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
				required: a.required,
				value: None
			});
		} else {
			if let Some(l) = a.long {
				if l == "help" {
					self.needs_long_help = false;
				} else if l == "version" {
					self.needs_long_version = false;
				}
			}
			if let Some(s) = a.short {
				if s == 'h' {
					self.needs_short_help = false;
				} else if s == 'v' {
					self.needs_short_version = false;
				}
			}
			self.flags.push(FlagArg{
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
			});
		}
		self
	}

	pub fn print_help(&self) {
		println!("Help info!");
		unsafe { libc::exit(0); }
	}

	pub fn print_version(&self) {
		println!("Version Info!");
		unsafe { libc::exit(0); }
	}

	fn parse_long_arg(&self, matches: &mut ArgMatches, arg: &str) -> &'static str {
		let mut p_arg = arg.trim_left_matches(|c| c == '-');
		let mut found = false;
		let mut needs_val = false;

		if p_arg == "help" && self.needs_long_help {
			self.print_help();
		} else if p_arg == "version" && self.needs_long_version {
			self.print_version();
		}
		for f in self.flags.iter() {
			if let Some(l) = f.long {
				if l == p_arg {
					found = true;
					matches.flags.push(f.clone());
					return "";
				}
			}
		}
		if p_arg.contains("=") {
			let p_argv: Vec<&str> = p_arg.split_str("=").collect();
			p_arg = p_argv[0];
			for o in self.opts.iter() {
				if let Some(l) = o.long {
					if l == p_arg {
						found = true;
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(p_argv[1].to_string())
						});
						break;
					}
				}
			}
		} else {
			for o in self.opts.iter() {
				if let Some(l) = o.long {
					if l == p_arg {
						return o.name;
					}
				}
			}
		}

		// Fails if argument supplied to binary isn't valid
		assert!(found == false);

		""
	}

	fn parse_short_arg(&self, matches: &mut ArgMatches, arg: &str) -> &'static str {
		let mut found = false;
		if arg.len() > 2 {
			// Multiple flags using short i.e. -bgHlS
			let p_arg = arg.trim_left_matches(|c| c == '-');
			for c in p_arg.chars() {
				if c == 'h' && self.needs_short_help {
					self.print_help();
				} else if c == 'v' && self.needs_short_version {
					self.print_version();
				}
				for f in self.flags.iter() {
					if let Some(s) = f.short {
						if c == s {
							found = true;
							matches.flags.push(f.clone());
						}
					}
				}
				// Fails if argument supplied to binary isn't valid
				assert!(found == false);
				return "";
			}
		} else {
			// Short flag or opt
			let p_arg = arg.char_at(1);
			if p_arg == 'h' && self.needs_short_help {
				self.print_help();
			} else if p_arg == 'v' && self.needs_short_version {
				self.print_version();
			}
			for f in self.flags.iter() {
				if let Some(s) = f.short {
					if p_arg == s {
						found = true;
						matches.flags.push(f.clone());
					}
				}
			}
			for o in self.opts.iter() {
				if let Some(s) = o.short {
					if s == p_arg {
						return o.name;
					}
				}
			}
		}
		// Fails if argument supplied to binary isn't valid
		assert!(found == false);

		""
	}

	pub fn get_matches(&mut self) -> ArgMatches {

		let mut matches = ArgMatches::new(self);

		// let mut needs_val = false;
		let mut needs_val_of = String::new();
		let mut pos_counter = 1;
		for arg in env::args().collect::<Vec<String>>().tail() {
			let arg_slice = arg.as_slice();
			if needs_val_of.is_empty() {
				for o in self.opts.iter() {
					if needs_val_of == o.name.to_string() {
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(arg.clone())
						});
						needs_val_of.clear();
						break;
					}
				}
				continue;
			}
			if arg_slice.starts_with("--") {
				// Single flag, or option
				needs_val_of = self.parse_long_arg(&mut matches, arg_slice).to_string();

			} else if arg_slice.starts_with("-") {
				needs_val_of = self.parse_short_arg(&mut matches, arg_slice).to_string();
			} else {
				// Positional

				// Fails if no positionals are expected/possible
				assert!(self.positionals.is_empty() == false);

				for p in self.positionals.iter() {
					matches.positionals.push(PosArg{
						name: p.name,
						help: p.help,
						required: p.required,
						value: Some(arg.clone()),
						index: pos_counter
					});
					pos_counter += 1;
				}
			}

		}

		// Fails if we reached the end of args() but were still
		// expecting a value, such as ./fake -c
		// where -c takes a value
		assert!(needs_val_of.is_empty());

		matches
	}
}<|endoftext|>


<commit_before>//! This exposes the command line interface that the binary uses
use std::fs;
use std::env;
use std::process;

use clap::{App, Arg, SubCommand};
use log;

use super::Result;
use super::sdk::{Sdk, SdkInfo, DumpOptions};
use super::config::Config;
use super::memdbstash::MemDbStash;
use super::api::server::ApiServer;

struct SimpleLogger;

impl log::Log for SimpleLogger {

    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= log::LogLevel::Info
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            println!("[{}] {}: {}", record.level(),
                record.target(), record.args());
        }
    }
}

fn setup_logging() {
    log::set_logger(|max_log_level| {
        max_log_level.set(log::LogLevelFilter::Warn);
        Box::new(SimpleLogger)
    }).unwrap();
}

/// Main entry point that starts the CLI
pub fn main() {
    setup_logging();
    match execute() {
        Ok(()) => {},
        Err(err) => {
            use std::error::Error;
            println!("error: {}", err);
            let mut cause = err.cause();
            while let Some(the_cause) = cause {
                println!("  caused by: {}", the_cause);
                cause = the_cause.cause();
            }
            process::exit(1);
        }
    }
}

fn execute() -> Result<()> {
    let app = App::new("SymbolServer")
        .author("Sentry")
        .about("Serves up apple system symbols")
        .arg(Arg::with_name("config")
             .long("config")
             .value_name("FILE")
             .help("The path to the config file"))
        .subcommand(
            SubCommand::with_name("sync-symbols"))
        .subcommand(
            SubCommand::with_name("run"))
        .subcommand(
            SubCommand::with_name("convert-sdk")
                .about("Converts an SDK into a memdb file")
                .arg(Arg::with_name("path")
                     .index(1)
                     .value_name("PATH")
                     .required(true)
                     .multiple(true)
                     .help("Path to the support folder"))
                .arg(Arg::with_name("compress")
                     .short("c")
                     .long("compress")
                     .help("Write compressed files instead."))
                .arg(Arg::with_name("output-path")
                     .short("o")
                     .long("output")
                     .help("Where the result should be stored")));
    let matches = app.get_matches();

    let cfg = if let Some(config_path) = matches.value_of("config") {
        Config::load_file(config_path)?
    } else {
        Config::load_default()?
    };

    if let Some(matches) = matches.subcommand_matches("convert-sdk") {
        convert_sdk_action(matches.values_of("path").unwrap().collect(),
                           matches.value_of("output-path").unwrap_or("."),
                           matches.is_present("compress"))?;
    } else if let Some(_matches) = matches.subcommand_matches("run") {
        run_action(&cfg)?;
    } else if let Some(_matches) = matches.subcommand_matches("sync-symbols") {
        sync_symbols_action(&cfg)?;
    }

    Ok(())
}

fn convert_sdk_action(paths: Vec<&str>, output_path: &str, compress: bool)
    -> Result<()>
{
    let dst_base = env::current_dir().unwrap().join(output_path);

    for (idx, path) in paths.iter().enumerate() {
        if idx > 0 {
            println!("");
        }
        let sdk = Sdk::new(&path)?;
        let mut dst = dst_base.join(&sdk.info().memdb_filename());
        if compress {
            dst.set_extension("memdbz");
        }

        println!("SDK {} ({} {}):", sdk.info().name(),
                 sdk.info().version(), sdk.info().build());

        // make sure we close the file at the end, in case we want to
        // re-open it for compressing.
        let f = fs::File::create(&dst)?;
        let options = DumpOptions {
            show_progress_bar: true,
            compress: compress,
            ..Default::default()
        };
        sdk.dump_memdb(f, options)?;
    }

    Ok(())
}

fn sync_symbols_action(config: &Config) -> Result<()> {
    let stash = MemDbStash::new(config)?;
    let status = stash.get_sync_status()?;
    println!("Sync healthy: {:?} (lag: {})", status.is_healthy(), status.lag());

    stash.sync()?;

    let info = SdkInfo::new("iOS", 10, 2, 1, "14D27");
    let memdb = stash.get_memdb(&info)?;
    println!("MemDB: {:?}", memdb.info());

    Ok(())
}

fn run_action(config: &Config) -> Result<()> {
    let api_server = ApiServer::new(config)?;
    api_server.run()?;
    Ok(())
}
<commit_msg>Added missing about strings<commit_after>//! This exposes the command line interface that the binary uses
use std::fs;
use std::env;
use std::process;

use clap::{App, Arg, SubCommand};
use log;

use super::Result;
use super::sdk::{Sdk, SdkInfo, DumpOptions};
use super::config::Config;
use super::memdbstash::MemDbStash;
use super::api::server::ApiServer;

struct SimpleLogger;

impl log::Log for SimpleLogger {

    fn enabled(&self, metadata: &log::LogMetadata) -> bool {
        metadata.level() <= log::LogLevel::Info
    }

    fn log(&self, record: &log::LogRecord) {
        if self.enabled(record.metadata()) {
            println!("[{}] {}: {}", record.level(),
                record.target(), record.args());
        }
    }
}

fn setup_logging() {
    log::set_logger(|max_log_level| {
        max_log_level.set(log::LogLevelFilter::Warn);
        Box::new(SimpleLogger)
    }).unwrap();
}

/// Main entry point that starts the CLI
pub fn main() {
    setup_logging();
    match execute() {
        Ok(()) => {},
        Err(err) => {
            use std::error::Error;
            println!("error: {}", err);
            let mut cause = err.cause();
            while let Some(the_cause) = cause {
                println!("  caused by: {}", the_cause);
                cause = the_cause.cause();
            }
            process::exit(1);
        }
    }
}

fn execute() -> Result<()> {
    let app = App::new("SymbolServer")
        .author("Sentry")
        .about("Serves up apple system symbols")
        .arg(Arg::with_name("config")
             .long("config")
             .value_name("FILE")
             .help("The path to the config file"))
        .subcommand(
            SubCommand::with_name("sync-symbols")
                .about("Updates symbols from S3"))
        .subcommand(
            SubCommand::with_name("run")
                .about("Runs the symbol server"))
        .subcommand(
            SubCommand::with_name("convert-sdk")
                .about("Converts an SDK into a memdb file")
                .arg(Arg::with_name("path")
                     .index(1)
                     .value_name("PATH")
                     .required(true)
                     .multiple(true)
                     .help("Path to the support folder"))
                .arg(Arg::with_name("compress")
                     .short("c")
                     .long("compress")
                     .help("Write compressed files instead."))
                .arg(Arg::with_name("output-path")
                     .short("o")
                     .long("output")
                     .help("Where the result should be stored")));
    let matches = app.get_matches();

    let cfg = if let Some(config_path) = matches.value_of("config") {
        Config::load_file(config_path)?
    } else {
        Config::load_default()?
    };

    if let Some(matches) = matches.subcommand_matches("convert-sdk") {
        convert_sdk_action(matches.values_of("path").unwrap().collect(),
                           matches.value_of("output-path").unwrap_or("."),
                           matches.is_present("compress"))?;
    } else if let Some(_matches) = matches.subcommand_matches("run") {
        run_action(&cfg)?;
    } else if let Some(_matches) = matches.subcommand_matches("sync-symbols") {
        sync_symbols_action(&cfg)?;
    }

    Ok(())
}

fn convert_sdk_action(paths: Vec<&str>, output_path: &str, compress: bool)
    -> Result<()>
{
    let dst_base = env::current_dir().unwrap().join(output_path);

    for (idx, path) in paths.iter().enumerate() {
        if idx > 0 {
            println!("");
        }
        let sdk = Sdk::new(&path)?;
        let mut dst = dst_base.join(&sdk.info().memdb_filename());
        if compress {
            dst.set_extension("memdbz");
        }

        println!("SDK {} ({} {}):", sdk.info().name(),
                 sdk.info().version(), sdk.info().build());

        // make sure we close the file at the end, in case we want to
        // re-open it for compressing.
        let f = fs::File::create(&dst)?;
        let options = DumpOptions {
            show_progress_bar: true,
            compress: compress,
            ..Default::default()
        };
        sdk.dump_memdb(f, options)?;
    }

    Ok(())
}

fn sync_symbols_action(config: &Config) -> Result<()> {
    let stash = MemDbStash::new(config)?;
    let status = stash.get_sync_status()?;
    println!("Sync healthy: {:?} (lag: {})", status.is_healthy(), status.lag());

    stash.sync()?;

    let info = SdkInfo::new("iOS", 10, 2, 1, "14D27");
    let memdb = stash.get_memdb(&info)?;
    println!("MemDB: {:?}", memdb.info());

    Ok(())
}

fn run_action(config: &Config) -> Result<()> {
    let api_server = ApiServer::new(config)?;
    api_server.run()?;
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2012-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.

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! Boxes are useful in two situations: recursive data structures, and
//! occasionally when returning data. [The Pointer chapter of the
//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
//! detail.
//!
//! # Examples
//!
//! Creating a box:
//!
//! ```
//! let x = Box::new(5);
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//!     Cons(T, Box<List<T>>),
//!     Nil,
//! }
//!
//! fn main() {
//!     let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//!     println!("{:?}", list);
//! }
//! ```
//!
//! This will print `Cons(1i32, Box(Cons(2i32, Box(Nil))))`.

#![stable(feature = "rust1", since = "1.0.0")]

use core::prelude::*;

use core::any::Any;
use core::cmp::Ordering;
use core::default::Default;
use core::error::{Error, FromError};
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use core::raw::TraitObject;

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```rust
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
///     let foo = box(HEAP) 5;
///     let foo = box 5;
/// }
/// ```
#[lang = "exchange_heap"]
#[unstable(feature = "alloc",
           reason = "may be renamed; uncertain about custom allocator design")]
pub static HEAP: () = ();

/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Box<T>(Unique<T>);

impl<T> Box<T> {
    /// Allocates memory on the heap and then moves `x` into it.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new(x: T) -> Box<T> {
        box x
    }
}

impl<T : ?Sized> Box<T> {
    /// Constructs a box from the raw pointer.
    ///
    /// After this function call, pointer is owned by resulting box.
    /// In particular, it means that `Box` destructor calls destructor
    /// of `T` and releases memory. Since the way `Box` allocates and
    /// releases memory is unspecified, so the only valid pointer to
    /// pass to this function is the one taken from another `Box` with
    /// `box::into_raw` function.
    ///
    /// Function is unsafe, because improper use of this function may
    /// lead to memory problems like double-free, for example if the
    /// function is called twice on the same raw pointer.
    #[unstable(feature = "alloc",
               reason = "may be renamed or moved out of Box scope")]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        mem::transmute(raw)
    }
}

/// Consumes the `Box`, returning the wrapped raw pointer.
///
/// After call to this function, caller is responsible for the memory
/// previously managed by `Box`, in particular caller should properly
/// destroy `T` and release memory. The proper way to do it is to
/// convert pointer back to `Box` with `Box::from_raw` function, because
/// `Box` does not specify, how memory is allocated.
///
/// Function is unsafe, because result of this function is no longer
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Example
/// ```
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = unsafe { boxed::into_raw(seventeen) };
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "alloc",
           reason = "may be renamed")]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
    mem::transmute(b)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<T> { box Default::default() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<[T]> { box [] }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Box<T> {
    /// Returns a new box with a `clone()` of this box's contents.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let y = x.clone();
    /// ```
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Copies `source`'s contents into `self` without creating a new allocation.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let mut y = Box::new(10);
    ///
    /// y.clone_from(&x);
    ///
    /// assert_eq!(*y, 5);
    /// ```
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

/// Extension methods for an owning `Any` trait object.
#[unstable(feature = "alloc",
           reason = "this trait will likely disappear once compiler bugs blocking \
                     a direct impl on `Box<Any>` have been fixed ")]
// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
//                removing this please make sure that you can downcase on
//                `Box<Any + Send>` as well as `Box<Any>`
pub trait BoxAny {
    /// Returns the boxed value if it is of type `T`, or
    /// `Err(Self)` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl BoxAny for Box<Any> {
    #[inline]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject =
                    mem::transmute::<Box<Any>, TraitObject>(self);

                // Extract the data pointer
                Ok(mem::transmute(to.data))
            }
        } else {
            Err(self)
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Box<Any> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Box<Any>")
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> FromError<E> for Box<Error + 'a> {
    fn from_error(err: E) -> Box<Error + 'a> {
        Box::new(err)
    }
}
<commit_msg>boxed: fix typo in doc<commit_after>// Copyright 2012-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.

//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! Boxes are useful in two situations: recursive data structures, and
//! occasionally when returning data. [The Pointer chapter of the
//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
//! detail.
//!
//! # Examples
//!
//! Creating a box:
//!
//! ```
//! let x = Box::new(5);
//! ```
//!
//! Creating a recursive data structure:
//!
//! ```
//! #[derive(Debug)]
//! enum List<T> {
//!     Cons(T, Box<List<T>>),
//!     Nil,
//! }
//!
//! fn main() {
//!     let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
//!     println!("{:?}", list);
//! }
//! ```
//!
//! This will print `Cons(1i32, Box(Cons(2i32, Box(Nil))))`.

#![stable(feature = "rust1", since = "1.0.0")]

use core::prelude::*;

use core::any::Any;
use core::cmp::Ordering;
use core::default::Default;
use core::error::{Error, FromError};
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
use core::ops::{Deref, DerefMut};
use core::ptr::Unique;
use core::raw::TraitObject;

/// A value that represents the heap. This is the default place that the `box`
/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
/// ```rust
/// #![feature(box_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
///     let foo = box(HEAP) 5;
///     let foo = box 5;
/// }
/// ```
#[lang = "exchange_heap"]
#[unstable(feature = "alloc",
           reason = "may be renamed; uncertain about custom allocator design")]
pub static HEAP: () = ();

/// A pointer type for heap allocation.
///
/// See the [module-level documentation](../../std/boxed/index.html) for more.
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Box<T>(Unique<T>);

impl<T> Box<T> {
    /// Allocates memory on the heap and then moves `x` into it.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// ```
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new(x: T) -> Box<T> {
        box x
    }
}

impl<T : ?Sized> Box<T> {
    /// Constructs a box from the raw pointer.
    ///
    /// After this function call, pointer is owned by resulting box.
    /// In particular, it means that `Box` destructor calls destructor
    /// of `T` and releases memory. Since the way `Box` allocates and
    /// releases memory is unspecified, the only valid pointer to pass
    /// to this function is the one taken from another `Box` with
    /// `boxed::into_raw` function.
    ///
    /// Function is unsafe, because improper use of this function may
    /// lead to memory problems like double-free, for example if the
    /// function is called twice on the same raw pointer.
    #[unstable(feature = "alloc",
               reason = "may be renamed or moved out of Box scope")]
    pub unsafe fn from_raw(raw: *mut T) -> Self {
        mem::transmute(raw)
    }
}

/// Consumes the `Box`, returning the wrapped raw pointer.
///
/// After call to this function, caller is responsible for the memory
/// previously managed by `Box`, in particular caller should properly
/// destroy `T` and release memory. The proper way to do it is to
/// convert pointer back to `Box` with `Box::from_raw` function, because
/// `Box` does not specify, how memory is allocated.
///
/// Function is unsafe, because result of this function is no longer
/// automatically managed that may lead to memory or other resource
/// leak.
///
/// # Example
/// ```
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = unsafe { boxed::into_raw(seventeen) };
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "alloc",
           reason = "may be renamed")]
pub unsafe fn into_raw<T : ?Sized>(b: Box<T>) -> *mut T {
    mem::transmute(b)
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default> Default for Box<T> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<T> { box Default::default() }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Default for Box<[T]> {
    #[stable(feature = "rust1", since = "1.0.0")]
    fn default() -> Box<[T]> { box [] }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for Box<T> {
    /// Returns a new box with a `clone()` of this box's contents.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let y = x.clone();
    /// ```
    #[inline]
    fn clone(&self) -> Box<T> { box {(**self).clone()} }

    /// Copies `source`'s contents into `self` without creating a new allocation.
    ///
    /// # Examples
    ///
    /// ```
    /// let x = Box::new(5);
    /// let mut y = Box::new(10);
    ///
    /// y.clone_from(&x);
    ///
    /// assert_eq!(*y, 5);
    /// ```
    #[inline]
    fn clone_from(&mut self, source: &Box<T>) {
        (**self).clone_from(&(**source));
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialEq> PartialEq for Box<T> {
    #[inline]
    fn eq(&self, other: &Box<T>) -> bool { PartialEq::eq(&**self, &**other) }
    #[inline]
    fn ne(&self, other: &Box<T>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + PartialOrd> PartialOrd for Box<T> {
    #[inline]
    fn partial_cmp(&self, other: &Box<T>) -> Option<Ordering> {
        PartialOrd::partial_cmp(&**self, &**other)
    }
    #[inline]
    fn lt(&self, other: &Box<T>) -> bool { PartialOrd::lt(&**self, &**other) }
    #[inline]
    fn le(&self, other: &Box<T>) -> bool { PartialOrd::le(&**self, &**other) }
    #[inline]
    fn ge(&self, other: &Box<T>) -> bool { PartialOrd::ge(&**self, &**other) }
    #[inline]
    fn gt(&self, other: &Box<T>) -> bool { PartialOrd::gt(&**self, &**other) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Ord> Ord for Box<T> {
    #[inline]
    fn cmp(&self, other: &Box<T>) -> Ordering {
        Ord::cmp(&**self, &**other)
    }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Eq> Eq for Box<T> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + Hash> Hash for Box<T> {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        (**self).hash(state);
    }
}

/// Extension methods for an owning `Any` trait object.
#[unstable(feature = "alloc",
           reason = "this trait will likely disappear once compiler bugs blocking \
                     a direct impl on `Box<Any>` have been fixed ")]
// FIXME(#18737): this should be a direct impl on `Box<Any>`. If you're
//                removing this please make sure that you can downcase on
//                `Box<Any + Send>` as well as `Box<Any>`
pub trait BoxAny {
    /// Returns the boxed value if it is of type `T`, or
    /// `Err(Self)` if it isn't.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Self>;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl BoxAny for Box<Any> {
    #[inline]
    fn downcast<T: 'static>(self) -> Result<Box<T>, Box<Any>> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject =
                    mem::transmute::<Box<Any>, TraitObject>(self);

                // Extract the data pointer
                Ok(mem::transmute(to.data))
            }
        } else {
            Err(self)
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display + ?Sized> fmt::Display for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&**self, f)
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Box<Any> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.pad("Box<Any>")
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
    type Target = T;

    fn deref(&self) -> &T { &**self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> DerefMut for Box<T> {
    fn deref_mut(&mut self) -> &mut T { &mut **self }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<I: Iterator + ?Sized> Iterator for Box<I> {
    type Item = I::Item;
    fn next(&mut self) -> Option<I::Item> { (**self).next() }
    fn size_hint(&self) -> (usize, Option<usize>) { (**self).size_hint() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for Box<I> {
    fn next_back(&mut self) -> Option<I::Item> { (**self).next_back() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for Box<I> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, E: Error + 'a> FromError<E> for Box<Error + 'a> {
    fn from_error(err: E) -> Box<Error + 'a> {
        Box::new(err)
    }
}
<|endoftext|>


<commit_before>/*!
 * Operations on the ubiquitous `option` type.
 *
 * Type `option` represents an optional value.
 *
 * Every `Option<T>` value can either be `Some(T)` or `none`. Where in other
 * languages you might use a nullable type, in Rust you would use an option
 * type.
 */

// NB: transitionary, de-mode-ing.
#[warn(deprecated_mode)];
#[forbid(deprecated_pattern)];

use cmp::Eq;

/// The option type
pub enum Option<T> {
    None,
    Some(T),
}

pub pure fn get<T: Copy>(opt: &Option<T>) -> T {
    /*!
     * Gets the value out of an option
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */

    match *opt {
      Some(copy x) => return x,
      None => fail ~"option::get none"
    }
}

pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
    /*!
     * Gets an immutable reference to the value inside an option.
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match *opt {
        Some(ref x) => x,
        None => fail ~"option::get_ref none"
    }
}

pub pure fn expect<T: Copy>(opt: &Option<T>, reason: ~str) -> T {
    /*!
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match *opt { Some(copy x) => x, None => fail reason }
}

pub pure fn map<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
    //! Maps a `some` value by reference from one type to another

    match *opt { Some(ref x) => Some(f(x)), None => None }
}

pub pure fn map_consume<T, U>(opt: Option<T>,
                              f: fn(v: T) -> U) -> Option<U> {
    /*!
     * As `map`, but consumes the option and gives `f` ownership to avoid
     * copying.
     */
    if opt.is_some() { Some(f(option::unwrap(move opt))) } else { None }
}

pub pure fn chain<T, U>(opt: Option<T>,
                        f: fn(t: T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content through a
     * function that returns an option.
     */

    // XXX write with move match
    if opt.is_some() {
        f(unwrap(opt))
    } else {
        None
    }
}

pub pure fn chain_ref<T, U>(opt: &Option<T>,
                            f: fn(x: &T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */

    match *opt { Some(ref x) => f(x), None => None }
}

pub pure fn or<T>(opta: Option<T>, optb: Option<T>) -> Option<T> {
    /*!
     * Returns the leftmost some() value, or none if both are none.
     */
    match opta {
        Some(_) => move opta,
        _ => move optb
    }
}

#[inline(always)]
pub pure fn while_some<T>(x: Option<T>, blk: fn(v: T) -> Option<T>) {
    //! Applies a function zero or more times until the result is none.

    let mut opt <- x;
    while opt.is_some() {
        opt = blk(unwrap(move opt));
    }
}

pub pure fn is_none<T>(opt: &Option<T>) -> bool {
    //! Returns true if the option equals `none`

    match *opt { None => true, Some(_) => false }
}

pub pure fn is_some<T>(opt: &Option<T>) -> bool {
    //! Returns true if the option contains some value

    !is_none(opt)
}

pub pure fn get_default<T: Copy>(opt: &Option<T>, def: T) -> T {
    //! Returns the contained value or a default

    match *opt { Some(copy x) => x, None => def }
}

pub pure fn map_default<T, U>(opt: &Option<T>, def: U,
                              f: fn(x: &T) -> U) -> U {
    //! Applies a function to the contained value or returns a default

    match *opt { None => move def, Some(ref t) => f(t) }
}

pub pure fn iter<T>(opt: &Option<T>, f: fn(x: &T)) {
    //! Performs an operation on the contained value by reference
    match *opt { None => (), Some(ref t) => f(t) }
}

#[inline(always)]
pub pure fn unwrap<T>(opt: Option<T>) -> T {
    /*!
     * Moves a value out of an option type and returns it.
     *
     * Useful primarily for getting strings, vectors and unique pointers out
     * of option types without copying them.
     */
    match move opt {
        Some(move x) => move x,
        None => fail ~"option::unwrap none"
    }
}

/// The ubiquitous option dance.
#[inline(always)]
pub fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
    if opt.is_none() { fail ~"option::swap_unwrap none" }
    unwrap(util::replace(opt, None))
}

pub pure fn unwrap_expect<T>(opt: Option<T>, reason: &str) -> T {
    //! As unwrap, but with a specified failure message.
    if opt.is_none() { fail reason.to_unique(); }
    unwrap(move opt)
}

// Some of these should change to be &Option<T>, some should not. See below.
impl<T> Option<T> {
    /// Returns true if the option equals `none`
    pure fn is_none() -> bool { is_none(&self) }
    /// Returns true if the option contains some value
    pure fn is_some() -> bool { is_some(&self) }
}

impl<T> &Option<T> {
    /**
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */
    pure fn chain_ref<U>(f: fn(x: &T) -> Option<U>) -> Option<U> {
        chain_ref(self, f)
    }
    /// Applies a function to the contained value or returns a default
    pure fn map_default<U>(def: U, f: fn(x: &T) -> U) -> U
        { map_default(self, move def, f) }
    /// Performs an operation on the contained value by reference
    pure fn iter(f: fn(x: &T)) { iter(self, f) }
    /// Maps a `some` value from one type to another by reference
    pure fn map<U>(f: fn(x: &T) -> U) -> Option<U> { map(self, f) }
    /// Gets an immutable reference to the value inside a `some`.
    pure fn get_ref() -> &self/T { get_ref(self) }
}

impl<T: Copy> Option<T> {
    /**
     * Gets the value out of an option
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn get() -> T { get(&self) }
    pure fn get_default(def: T) -> T { get_default(&self, def) }
    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn expect(reason: ~str) -> T { expect(&self, reason) }
    /// Applies a function zero or more times until the result is none.
    pure fn while_some(blk: fn(v: T) -> Option<T>) { while_some(self, blk) }
}

impl<T: Eq> Option<T> : Eq {
    pure fn eq(other: &Option<T>) -> bool {
        match self {
            None => {
                match (*other) {
                    None => true,
                    Some(_) => false
                }
            }
            Some(ref self_contents) => {
                match (*other) {
                    None => false,
                    Some(ref other_contents) =>
                        (*self_contents).eq(other_contents)
                }
            }
        }
    }
    pure fn ne(other: &Option<T>) -> bool { !self.eq(other) }
}

#[test]
fn test_unwrap_ptr() {
    let x = ~0;
    let addr_x = ptr::p2::addr_of(&(*x));
    let opt = Some(x);
    let y = unwrap(opt);
    let addr_y = ptr::p2::addr_of(&(*y));
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| buf);
    let opt = Some(move x);
    let y = unwrap(move opt);
    let addr_y = str::as_buf(y, |buf, _len| buf);
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_resource() {
    struct R {
       i: @mut int,
       drop { *(self.i) += 1; }
    }

    fn R(i: @mut int) -> R {
        R {
            i: i
        }
    }

    let i = @mut 0;
    {
        let x = R(i);
        let opt = Some(x);
        let _y = unwrap(opt);
    }
    assert *i == 1;
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    do x.iter |_x| {
        y2 = swap_unwrap(&mut y);
    }
    assert y2 == 5;
    assert y.is_none();
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable());
    let _y2 = swap_unwrap(&mut y);
    let _y3 = swap_unwrap(&mut y);
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert i == 11;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<commit_msg>core: Improve option docs a little<commit_after>/*!

Operations on the ubiquitous `Option` type.

Type `Option` represents an optional value.

Every `Option<T>` value can either be `Some(T)` or `None`. Where in other
languages you might use a nullable type, in Rust you would use an option
type.

Options are most commonly used with pattern matching to query the presence
of a value and take action, always accounting for the `None` case.

# Example

~~~
let msg = Some(~"howdy");

// Take a reference to the contained string
match msg {
    Some(ref m) => io::println(m),
    None => ()
}

// Remove the contained string, destroying the Option
let unwrapped_msg = match move msg {
    Some(move m) => m,
    None => ~"default message"
};
~~~

*/

// NB: transitionary, de-mode-ing.
#[warn(deprecated_mode)];
#[forbid(deprecated_pattern)];

use cmp::Eq;

/// The option type
pub enum Option<T> {
    None,
    Some(T),
}

pub pure fn get<T: Copy>(opt: &Option<T>) -> T {
    /*!
    Gets the value out of an option

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
    */

    match *opt {
      Some(copy x) => return x,
      None => fail ~"option::get none"
    }
}

pub pure fn get_ref<T>(opt: &r/Option<T>) -> &r/T {
    /*!
    Gets an immutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    match *opt {
        Some(ref x) => x,
        None => fail ~"option::get_ref none"
    }
}

pub pure fn expect<T: Copy>(opt: &Option<T>, reason: ~str) -> T {
    /*!
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    match *opt { Some(copy x) => x, None => fail reason }
}

pub pure fn map<T, U>(opt: &Option<T>, f: fn(x: &T) -> U) -> Option<U> {
    //! Maps a `some` value by reference from one type to another

    match *opt { Some(ref x) => Some(f(x)), None => None }
}

pub pure fn map_consume<T, U>(opt: Option<T>,
                              f: fn(v: T) -> U) -> Option<U> {
    /*!
     * As `map`, but consumes the option and gives `f` ownership to avoid
     * copying.
     */
    if opt.is_some() { Some(f(option::unwrap(move opt))) } else { None }
}

pub pure fn chain<T, U>(opt: Option<T>,
                        f: fn(t: T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content through a
     * function that returns an option.
     */

    // XXX write with move match
    if opt.is_some() {
        f(unwrap(opt))
    } else {
        None
    }
}

pub pure fn chain_ref<T, U>(opt: &Option<T>,
                            f: fn(x: &T) -> Option<U>) -> Option<U> {
    /*!
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */

    match *opt { Some(ref x) => f(x), None => None }
}

pub pure fn or<T>(opta: Option<T>, optb: Option<T>) -> Option<T> {
    /*!
     * Returns the leftmost some() value, or none if both are none.
     */
    match opta {
        Some(_) => move opta,
        _ => move optb
    }
}

#[inline(always)]
pub pure fn while_some<T>(x: Option<T>, blk: fn(v: T) -> Option<T>) {
    //! Applies a function zero or more times until the result is none.

    let mut opt <- x;
    while opt.is_some() {
        opt = blk(unwrap(move opt));
    }
}

pub pure fn is_none<T>(opt: &Option<T>) -> bool {
    //! Returns true if the option equals `none`

    match *opt { None => true, Some(_) => false }
}

pub pure fn is_some<T>(opt: &Option<T>) -> bool {
    //! Returns true if the option contains some value

    !is_none(opt)
}

pub pure fn get_default<T: Copy>(opt: &Option<T>, def: T) -> T {
    //! Returns the contained value or a default

    match *opt { Some(copy x) => x, None => def }
}

pub pure fn map_default<T, U>(opt: &Option<T>, def: U,
                              f: fn(x: &T) -> U) -> U {
    //! Applies a function to the contained value or returns a default

    match *opt { None => move def, Some(ref t) => f(t) }
}

pub pure fn iter<T>(opt: &Option<T>, f: fn(x: &T)) {
    //! Performs an operation on the contained value by reference
    match *opt { None => (), Some(ref t) => f(t) }
}

#[inline(always)]
pub pure fn unwrap<T>(opt: Option<T>) -> T {
    /*!
    Moves a value out of an option type and returns it.

    Useful primarily for getting strings, vectors and unique pointers out
    of option types without copying them.

    # Failure

    Fails if the value equals `None`.

    # Safety note

    In general, because this function may fail, its use is discouraged.
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    match move opt {
        Some(move x) => move x,
        None => fail ~"option::unwrap none"
    }
}

#[inline(always)]
pub fn swap_unwrap<T>(opt: &mut Option<T>) -> T {
    /*!
    The option dance. Moves a value out of an option type and returns it,
    replacing the original with `None`.

    # Failure

    Fails if the value equals `None`.
     */
    if opt.is_none() { fail ~"option::swap_unwrap none" }
    unwrap(util::replace(opt, None))
}

pub pure fn unwrap_expect<T>(opt: Option<T>, reason: &str) -> T {
    //! As unwrap, but with a specified failure message.
    if opt.is_none() { fail reason.to_unique(); }
    unwrap(move opt)
}

// Some of these should change to be &Option<T>, some should not. See below.
impl<T> Option<T> {
    /// Returns true if the option equals `none`
    pure fn is_none() -> bool { is_none(&self) }
    /// Returns true if the option contains some value
    pure fn is_some() -> bool { is_some(&self) }
}

impl<T> &Option<T> {
    /**
     * Update an optional value by optionally running its content by reference
     * through a function that returns an option.
     */
    pure fn chain_ref<U>(f: fn(x: &T) -> Option<U>) -> Option<U> {
        chain_ref(self, f)
    }
    /// Applies a function to the contained value or returns a default
    pure fn map_default<U>(def: U, f: fn(x: &T) -> U) -> U
        { map_default(self, move def, f) }
    /// Performs an operation on the contained value by reference
    pure fn iter(f: fn(x: &T)) { iter(self, f) }
    /// Maps a `some` value from one type to another by reference
    pure fn map<U>(f: fn(x: &T) -> U) -> Option<U> { map(self, f) }
    /**
    Gets an immutable reference to the value inside an option.

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
     */
    pure fn get_ref() -> &self/T { get_ref(self) }
}

impl<T: Copy> Option<T> {
    /**
    Gets the value out of an option

    # Failure

    Fails if the value equals `None`

    # Safety note

    In general, because this function may fail, its use is discouraged
    (calling `get` on `None` is akin to dereferencing a null pointer).
    Instead, prefer to use pattern matching and handle the `None`
    case explicitly.
    */
    pure fn get() -> T { get(&self) }
    pure fn get_default(def: T) -> T { get_default(&self, def) }
    /**
     * Gets the value out of an option, printing a specified message on
     * failure
     *
     * # Failure
     *
     * Fails if the value equals `none`
     */
    pure fn expect(reason: ~str) -> T { expect(&self, reason) }
    /// Applies a function zero or more times until the result is none.
    pure fn while_some(blk: fn(v: T) -> Option<T>) { while_some(self, blk) }
}

impl<T: Eq> Option<T> : Eq {
    pure fn eq(other: &Option<T>) -> bool {
        match self {
            None => {
                match (*other) {
                    None => true,
                    Some(_) => false
                }
            }
            Some(ref self_contents) => {
                match (*other) {
                    None => false,
                    Some(ref other_contents) =>
                        (*self_contents).eq(other_contents)
                }
            }
        }
    }
    pure fn ne(other: &Option<T>) -> bool { !self.eq(other) }
}

#[test]
fn test_unwrap_ptr() {
    let x = ~0;
    let addr_x = ptr::p2::addr_of(&(*x));
    let opt = Some(x);
    let y = unwrap(opt);
    let addr_y = ptr::p2::addr_of(&(*y));
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_str() {
    let x = ~"test";
    let addr_x = str::as_buf(x, |buf, _len| buf);
    let opt = Some(move x);
    let y = unwrap(move opt);
    let addr_y = str::as_buf(y, |buf, _len| buf);
    assert addr_x == addr_y;
}

#[test]
fn test_unwrap_resource() {
    struct R {
       i: @mut int,
       drop { *(self.i) += 1; }
    }

    fn R(i: @mut int) -> R {
        R {
            i: i
        }
    }

    let i = @mut 0;
    {
        let x = R(i);
        let opt = Some(x);
        let _y = unwrap(opt);
    }
    assert *i == 1;
}

#[test]
fn test_option_dance() {
    let x = Some(());
    let mut y = Some(5);
    let mut y2 = 0;
    do x.iter |_x| {
        y2 = swap_unwrap(&mut y);
    }
    assert y2 == 5;
    assert y.is_none();
}
#[test] #[should_fail] #[ignore(cfg(windows))]
fn test_option_too_much_dance() {
    let mut y = Some(util::NonCopyable());
    let _y2 = swap_unwrap(&mut y);
    let _y3 = swap_unwrap(&mut y);
}

#[test]
fn test_option_while_some() {
    let mut i = 0;
    do Some(10).while_some |j| {
        i += 1;
        if (j > 0) {
            Some(j-1)
        } else {
            None
        }
    }
    assert i == 11;
}

// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
<|endoftext|>