<commit_before>use crate::{Location, World};
use serde_derive::{Deserialize, Serialize};
use std::slice;
use vitral::SRgba;

impl World {
    /// Return whether location is contained in the current play area.
    pub fn is_valid_location(&self, _loc: Location) -> bool {
        //Location::origin().v2_at(loc).map_or(false, ::on_screen)
        true
    }

    /// Return terrain at location.
    pub fn terrain(&self, loc: Location) -> Terrain {
        let mut t = self.world_cache.get_terrain(loc);

        if t == Terrain::Door && self.has_mobs(loc) {
            // Standing in the doorway opens the door.
            t = Terrain::OpenDoor;
        }

        t
    }

    /// If location contains a portal, return the destination of the portal.
    pub fn portal(&self, loc: Location) -> Option<Location> {
        self.world_cache.get_portal(loc)
    }

    /// Return whether location has a border portals.
    ///
    /// Portals are divided into border and hole portals. A hole portal is usually surrounded by
    /// local scenery at all sides, while border portals are assumed to be at the edges of a convex
    /// patch of local terrain with nothing local past them.
    ///
    /// The difference between the two is important in how map memory works, map memory display
    /// goes through border portals normally, but ignores hole portals.
    pub fn is_border_portal(&self, _loc: Location) -> bool {
        // TODO: Implement internal data for border portals
        // Turn type Portal in the internal portal data into enum { Border(Portal), Edge(Portal) }
        false
    }

    /// Return a portal if it can be seen through.
    pub fn visible_portal(&self, loc: Location) -> Option<Location> {
        // Only void-form is transparent to portals.
        if self.terrain(loc).form() == Form::Void {
            self.portal(loc)
        } else {
            None
        }
    }
}

/// Movement effect of a terrain tile.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Kind {
    /// Regular flat solid ground, can walk across easily.
    Ground,
    /// An obstacle that fills the entire cell, blocks field of view.
    Block,
    /// An obstacle that can be seen through.
    ///
    /// Not necessarily a literal window, thinner blocks like pillars and statues might also be
    /// see-through.
    Window,
    /// A tile that blocks sight but can be walked through.
    Door,
    /// Bodies of water, regular units can't walk into them.
    ///
    /// Flying units (if we have any) can cross. Falling into water is going to involve tricky
    /// logic since our maps aren't 3D.
    Water,
    /// Like water, but much more fun.
    Magma,
}

/// Visual form of a terrain tile.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Form {
    /// Nothingness, lets sight pass through portals
    Void,
    /// Marker pointing at adjacent nothingness
    Gate,
    /// Single frame on floor layer
    Floor,
    /// Single frame on object layer
    Prop,
    /// Blobbing form on object layer
    Blob,
    /// Wall-form on object layer
    Wall,
}

struct TerrainData {
    name: &'static str,
    kind: Kind,
    form: Form,
    map_chars: &'static str,
    /// For variants that should not show up in main terrain sets.
    is_regular: bool,
    /// 4-bit components, R << 8 + G << 4 + B.
    color: u16,
}

macro_rules! count_tts {
    () => {0usize};
    ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)};
}

macro_rules! terrain_enum {
    {
        $($sym:ident: $data:expr,)+
    } => {
        #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
        pub enum Terrain {
            $($sym,)+
        }

        const N_ENUM: usize = count_tts!($($sym)+);

        static TERRAIN_DATA: [TerrainData; N_ENUM] = [
            $($data,)+
        ];

        static TERRAIN_ENUM: [Terrain; N_ENUM] = [
            $(Terrain::$sym,)+
        ];
    }
}

terrain_enum! {
    Empty:       TerrainData { name: "n/a",       kind: Kind::Block,  form: Form::Void,  map_chars: "",    is_regular: true,  color: 0xF0F },
    Void:        TerrainData { name: "void",      kind: Kind::Block,  form: Form::Void,  map_chars: "",    is_regular: true,  color: 0x011 },
    Downstairs:  TerrainData { name: "exit down", kind: Kind::Ground, form: Form::Gate,  map_chars: ">",   is_regular: true,  color: 0x0EE },
    Upstairs:    TerrainData { name: "exit up",   kind: Kind::Ground, form: Form::Gate,  map_chars: "<",   is_regular: true,  color: 0x0FF },
    Ground:      TerrainData { name: "ground",    kind: Kind::Ground, form: Form::Floor, map_chars: ".,_", is_regular: true,  color: 0x111 },
    Grass:       TerrainData { name: "grass",     kind: Kind::Ground, form: Form::Floor, map_chars: ",._", is_regular: true,  color: 0x231 },
    Sand:        TerrainData { name: "sand",      kind: Kind::Ground, form: Form::Floor, map_chars: ",._", is_regular: true,  color: 0x650 },
    Snow:        TerrainData { name: "snow",      kind: Kind::Ground, form: Form::Floor, map_chars: ",._", is_regular: true,  color: 0x788 },
    Water:       TerrainData { name: "water",     kind: Kind::Water,  form: Form::Floor, map_chars: "~=",  is_regular: true,  color: 0x058 },
    Shallows:    TerrainData { name: "shallows",  kind: Kind::Ground, form: Form::Floor, map_chars: "~=",  is_regular: true,  color: 0x08B },
    Magma:       TerrainData { name: "magma",     kind: Kind::Magma,  form: Form::Floor, map_chars: "=~",  is_regular: true,  color: 0xF22 },
    Tree:        TerrainData { name: "tree",      kind: Kind::Block,  form: Form::Prop,  map_chars: "",    is_regular: true,  color: 0x8B1 },
    Wall:        TerrainData { name: "wall",      kind: Kind::Block,  form: Form::Wall,  map_chars: "#*",  is_regular: true,  color: 0xBBB },
    Rock:        TerrainData { name: "rock",      kind: Kind::Block,  form: Form::Blob,  map_chars: "*#",  is_regular: true,  color: 0xB84 },
    Door:        TerrainData { name: "door",      kind: Kind::Door,   form: Form::Wall,  map_chars: "|",   is_regular: true,  color: 0x842 },
    OpenDoor:    TerrainData { name: "open door", kind: Kind::Ground, form: Form::Wall,  map_chars: "",    is_regular: false, color: 0xFAF },
    Window:      TerrainData { name: "window",    kind: Kind::Window, form: Form::Wall,  map_chars: "+",   is_regular: true,  color: 0xBFF },
    Pillar:      TerrainData { name: "pillar",    kind: Kind::Block,  form: Form::Prop,  map_chars: "I",   is_regular: true,  color: 0xCCD },
    // TODO: Get rid of grass2, give render a coherent noise source for tiles and make it do the
    // variation locally.
    Grass2:      TerrainData { name: "grass",     kind: Kind::Ground, form: Form::Floor, map_chars: "",    is_regular: false, color: 0x230 },
}

impl Terrain {
    pub fn iter() -> slice::Iter<'static, Terrain> { TERRAIN_ENUM.iter() }

    pub fn from_color(color: SRgba) -> Option<Terrain> {
        let key = (((color.r >> 4) as u16) << 8)
            + (((color.g >> 4) as u16) << 4)
            + (color.b >> 4) as u16;
        Self::iter()
            .filter(|t| t.is_regular())
            .find(|t| TERRAIN_DATA[**t as usize].color == key)
            .cloned()
    }

    #[inline(always)]
    pub fn kind(self) -> Kind { TERRAIN_DATA[self as usize].kind }

    #[inline(always)]
    pub fn form(self) -> Form { TERRAIN_DATA[self as usize].form }

    pub fn blocks_sight(self) -> bool {
        match self.kind() {
            Kind::Block | Kind::Door => true,
            _ => false,
        }
    }

    pub fn blocks_shot(self) -> bool {
        match self.kind() {
            Kind::Block | Kind::Window | Kind::Door => true,
            _ => false,
        }
    }

    pub fn blocks_walk(self) -> bool {
        match self.kind() {
            Kind::Ground | Kind::Door => false,
            _ => true,
        }
    }

    pub fn name(self) -> &'static str { TERRAIN_DATA[self as usize].name }

    pub fn is_open(self) -> bool { self.kind() == Kind::Ground }

    pub fn is_door(self) -> bool { self.kind() == Kind::Door }

    pub fn is_luminous(self) -> bool { self.kind() == Kind::Magma }

    pub fn is_wall(self) -> bool { self.form() == Form::Wall }

    pub fn is_hull(self) -> bool {
        self.form() == Form::Wall || self.form() == Form::Blob
    }

    pub fn is_blob(self) -> bool { self.form() == Form::Blob }

    pub fn is_block(self) -> bool {
        self.is_hull() || self.form() == Form::Prop
    }

    pub fn is_regular(self) -> bool { TERRAIN_DATA[self as usize].is_regular }

    /// For constructing text maps.
    pub fn preferred_map_chars(self) -> &'static str {
        TERRAIN_DATA[self as usize].map_chars
    }

    /// Terrain is a narrow object that blocks movement.
    ///
    /// Prop obstacles might not be distinguishable from floors if you only see a corner of the
    /// terrain tile. Use this if there's need to highlight partially visible terrain as obstacles.
    pub fn is_narrow_obstacle(self) -> bool {
        self.blocks_walk() && self.form() == Form::Prop
    }

    pub fn color(self) -> SRgba {
        let col = TERRAIN_DATA[self as usize].color;
        let r = ((col >> 8) & 0xf) as u8;
        let g = ((col >> 4) & 0xf) as u8;
        let b = (col & 0xf) as u8;

        SRgba::new(r << 4, g << 4, b << 4, 0xff)
    }

    /// Vertical delta (up a level / down a level / flat) for this terrain.
    pub fn dz(self) -> i32 {
        use Terrain::*;
        match self {
            Upstairs => -1,
            Downstairs => 1,
            _ => 0,
        }
    }
}

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

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

    #[test]
    fn test_colors_are_unique() {
        use std::collections::HashSet;

        let terrains: HashSet<Terrain> = Terrain::iter()
            .filter(|t| t.is_regular())
            .cloned()
            .collect();
        let colors: HashSet<SRgba> =
            terrains.iter().map(|t| t.color()).collect();

        assert_eq!(colors.len(), terrains.len());
    }

    #[test]
    fn test_from_color() {
        assert_eq!(
            Terrain::from_color(SRgba::new(0xff, 0x88, 0xff, 0xff)),
            None
        );
        assert_eq!(
            Terrain::from_color(SRgba::new(0x22, 0x30, 0x1f, 0xff)),
            Some(Terrain::Grass)
        );
    }
}
<commit_msg>Pillars don't block FOV<commit_after>use crate::{Location, World};
use serde_derive::{Deserialize, Serialize};
use std::slice;
use vitral::SRgba;

impl World {
    /// Return whether location is contained in the current play area.
    pub fn is_valid_location(&self, _loc: Location) -> bool {
        //Location::origin().v2_at(loc).map_or(false, ::on_screen)
        true
    }

    /// Return terrain at location.
    pub fn terrain(&self, loc: Location) -> Terrain {
        let mut t = self.world_cache.get_terrain(loc);

        if t == Terrain::Door && self.has_mobs(loc) {
            // Standing in the doorway opens the door.
            t = Terrain::OpenDoor;
        }

        t
    }

    /// If location contains a portal, return the destination of the portal.
    pub fn portal(&self, loc: Location) -> Option<Location> {
        self.world_cache.get_portal(loc)
    }

    /// Return whether location has a border portals.
    ///
    /// Portals are divided into border and hole portals. A hole portal is usually surrounded by
    /// local scenery at all sides, while border portals are assumed to be at the edges of a convex
    /// patch of local terrain with nothing local past them.
    ///
    /// The difference between the two is important in how map memory works, map memory display
    /// goes through border portals normally, but ignores hole portals.
    pub fn is_border_portal(&self, _loc: Location) -> bool {
        // TODO: Implement internal data for border portals
        // Turn type Portal in the internal portal data into enum { Border(Portal), Edge(Portal) }
        false
    }

    /// Return a portal if it can be seen through.
    pub fn visible_portal(&self, loc: Location) -> Option<Location> {
        // Only void-form is transparent to portals.
        if self.terrain(loc).form() == Form::Void {
            self.portal(loc)
        } else {
            None
        }
    }
}

/// Movement effect of a terrain tile.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Kind {
    /// Regular flat solid ground, can walk across easily.
    Ground,
    /// An obstacle that fills the entire cell, blocks field of view.
    Block,
    /// An obstacle that can be seen through.
    ///
    /// Not necessarily a literal window, thinner blocks like pillars and statues might also be
    /// see-through.
    Window,
    /// A tile that blocks sight but can be walked through.
    Door,
    /// Bodies of water, regular units can't walk into them.
    ///
    /// Flying units (if we have any) can cross. Falling into water is going to involve tricky
    /// logic since our maps aren't 3D.
    Water,
    /// Like water, but much more fun.
    Magma,
}

/// Visual form of a terrain tile.
#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub enum Form {
    /// Nothingness, lets sight pass through portals
    Void,
    /// Marker pointing at adjacent nothingness
    Gate,
    /// Single frame on floor layer
    Floor,
    /// Single frame on object layer
    Prop,
    /// Blobbing form on object layer
    Blob,
    /// Wall-form on object layer
    Wall,
}

struct TerrainData {
    name: &'static str,
    kind: Kind,
    form: Form,
    map_chars: &'static str,
    /// For variants that should not show up in main terrain sets.
    is_regular: bool,
    /// 4-bit components, R << 8 + G << 4 + B.
    color: u16,
}

macro_rules! count_tts {
    () => {0usize};
    ($_head:tt $($tail:tt)*) => {1usize + count_tts!($($tail)*)};
}

macro_rules! terrain_enum {
    {
        $($sym:ident: $data:expr,)+
    } => {
        #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Serialize, Deserialize)]
        pub enum Terrain {
            $($sym,)+
        }

        const N_ENUM: usize = count_tts!($($sym)+);

        static TERRAIN_DATA: [TerrainData; N_ENUM] = [
            $($data,)+
        ];

        static TERRAIN_ENUM: [Terrain; N_ENUM] = [
            $(Terrain::$sym,)+
        ];
    }
}

terrain_enum! {
    Empty:       TerrainData { name: "n/a",       kind: Kind::Block,  form: Form::Void,  map_chars: "",    is_regular: true,  color: 0xF0F },
    Void:        TerrainData { name: "void",      kind: Kind::Block,  form: Form::Void,  map_chars: "",    is_regular: true,  color: 0x011 },
    Downstairs:  TerrainData { name: "exit down", kind: Kind::Ground, form: Form::Gate,  map_chars: ">",   is_regular: true,  color: 0x0EE },
    Upstairs:    TerrainData { name: "exit up",   kind: Kind::Ground, form: Form::Gate,  map_chars: "<",   is_regular: true,  color: 0x0FF },
    Ground:      TerrainData { name: "ground",    kind: Kind::Ground, form: Form::Floor, map_chars: ".,_", is_regular: true,  color: 0x111 },
    Grass:       TerrainData { name: "grass",     kind: Kind::Ground, form: Form::Floor, map_chars: ",._", is_regular: true,  color: 0x231 },
    Sand:        TerrainData { name: "sand",      kind: Kind::Ground, form: Form::Floor, map_chars: ",._", is_regular: true,  color: 0x650 },
    Snow:        TerrainData { name: "snow",      kind: Kind::Ground, form: Form::Floor, map_chars: ",._", is_regular: true,  color: 0x788 },
    Water:       TerrainData { name: "water",     kind: Kind::Water,  form: Form::Floor, map_chars: "~=",  is_regular: true,  color: 0x058 },
    Shallows:    TerrainData { name: "shallows",  kind: Kind::Ground, form: Form::Floor, map_chars: "~=",  is_regular: true,  color: 0x08B },
    Magma:       TerrainData { name: "magma",     kind: Kind::Magma,  form: Form::Floor, map_chars: "=~",  is_regular: true,  color: 0xF22 },
    Tree:        TerrainData { name: "tree",      kind: Kind::Block,  form: Form::Prop,  map_chars: "",    is_regular: true,  color: 0x8B1 },
    Wall:        TerrainData { name: "wall",      kind: Kind::Block,  form: Form::Wall,  map_chars: "#*",  is_regular: true,  color: 0xBBB },
    Rock:        TerrainData { name: "rock",      kind: Kind::Block,  form: Form::Blob,  map_chars: "*#",  is_regular: true,  color: 0xB84 },
    Door:        TerrainData { name: "door",      kind: Kind::Door,   form: Form::Wall,  map_chars: "|",   is_regular: true,  color: 0x842 },
    OpenDoor:    TerrainData { name: "open door", kind: Kind::Ground, form: Form::Wall,  map_chars: "",    is_regular: false, color: 0xFAF },
    Window:      TerrainData { name: "window",    kind: Kind::Window, form: Form::Wall,  map_chars: "+",   is_regular: true,  color: 0xBFF },
    Pillar:      TerrainData { name: "pillar",    kind: Kind::Window, form: Form::Prop,  map_chars: "I",   is_regular: true,  color: 0xCCD },
    // TODO: Get rid of grass2, give render a coherent noise source for tiles and make it do the
    // variation locally.
    Grass2:      TerrainData { name: "grass",     kind: Kind::Ground, form: Form::Floor, map_chars: "",    is_regular: false, color: 0x230 },
}

impl Terrain {
    pub fn iter() -> slice::Iter<'static, Terrain> { TERRAIN_ENUM.iter() }

    pub fn from_color(color: SRgba) -> Option<Terrain> {
        let key = (((color.r >> 4) as u16) << 8)
            + (((color.g >> 4) as u16) << 4)
            + (color.b >> 4) as u16;
        Self::iter()
            .filter(|t| t.is_regular())
            .find(|t| TERRAIN_DATA[**t as usize].color == key)
            .cloned()
    }

    #[inline(always)]
    pub fn kind(self) -> Kind { TERRAIN_DATA[self as usize].kind }

    #[inline(always)]
    pub fn form(self) -> Form { TERRAIN_DATA[self as usize].form }

    pub fn blocks_sight(self) -> bool {
        match self.kind() {
            Kind::Block | Kind::Door => true,
            _ => false,
        }
    }

    pub fn blocks_shot(self) -> bool {
        match self.kind() {
            Kind::Block | Kind::Window | Kind::Door => true,
            _ => false,
        }
    }

    pub fn blocks_walk(self) -> bool {
        match self.kind() {
            Kind::Ground | Kind::Door => false,
            _ => true,
        }
    }

    pub fn name(self) -> &'static str { TERRAIN_DATA[self as usize].name }

    pub fn is_open(self) -> bool { self.kind() == Kind::Ground }

    pub fn is_door(self) -> bool { self.kind() == Kind::Door }

    pub fn is_luminous(self) -> bool { self.kind() == Kind::Magma }

    pub fn is_wall(self) -> bool { self.form() == Form::Wall }

    pub fn is_hull(self) -> bool {
        self.form() == Form::Wall || self.form() == Form::Blob
    }

    pub fn is_blob(self) -> bool { self.form() == Form::Blob }

    pub fn is_block(self) -> bool {
        self.is_hull() || self.form() == Form::Prop
    }

    pub fn is_regular(self) -> bool { TERRAIN_DATA[self as usize].is_regular }

    /// For constructing text maps.
    pub fn preferred_map_chars(self) -> &'static str {
        TERRAIN_DATA[self as usize].map_chars
    }

    /// Terrain is a narrow object that blocks movement.
    ///
    /// Prop obstacles might not be distinguishable from floors if you only see a corner of the
    /// terrain tile. Use this if there's need to highlight partially visible terrain as obstacles.
    pub fn is_narrow_obstacle(self) -> bool {
        self.blocks_walk() && self.form() == Form::Prop
    }

    pub fn color(self) -> SRgba {
        let col = TERRAIN_DATA[self as usize].color;
        let r = ((col >> 8) & 0xf) as u8;
        let g = ((col >> 4) & 0xf) as u8;
        let b = (col & 0xf) as u8;

        SRgba::new(r << 4, g << 4, b << 4, 0xff)
    }

    /// Vertical delta (up a level / down a level / flat) for this terrain.
    pub fn dz(self) -> i32 {
        use Terrain::*;
        match self {
            Upstairs => -1,
            Downstairs => 1,
            _ => 0,
        }
    }
}

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

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

    #[test]
    fn test_colors_are_unique() {
        use std::collections::HashSet;

        let terrains: HashSet<Terrain> = Terrain::iter()
            .filter(|t| t.is_regular())
            .cloned()
            .collect();
        let colors: HashSet<SRgba> =
            terrains.iter().map(|t| t.color()).collect();

        assert_eq!(colors.len(), terrains.len());
    }

    #[test]
    fn test_from_color() {
        assert_eq!(
            Terrain::from_color(SRgba::new(0xff, 0x88, 0xff, 0xff)),
            None
        );
        assert_eq!(
            Terrain::from_color(SRgba::new(0x22, 0x30, 0x1f, 0xff)),
            Some(Terrain::Grass)
        );
    }
}
<|endoftext|>


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

use std::fmt;
use std::str::FromStr;

/// The edition of the compiler (RFC 2052)
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
#[non_exhaustive]
pub enum Edition {
    // editions must be kept in order, newest to oldest

    /// The 2015 edition
    Edition2015,
    /// The 2018 edition
    Edition2018,

    // when adding new editions, be sure to update:
    //
    // - Update the `ALL_EDITIONS` const
    // - Update the EDITION_NAME_LIST const
    // - add a `rust_####()` function to the session
    // - update the enum in Cargo's sources as well
}

// must be in order from oldest to newest
pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];

pub const EDITION_NAME_LIST: &'static str = "2015|2018";

pub const DEFAULT_EDITION: Edition = Edition::Edition2015;

impl fmt::Display for Edition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            Edition::Edition2015 => "2015",
            Edition::Edition2018 => "2018",
        };
        write!(f, "{}", s)
    }
}

impl Edition {
    pub fn lint_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_compatibility",
            Edition::Edition2018 => "rust_2018_compatibility",
        }
    }

    pub fn feature_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_preview",
            Edition::Edition2018 => "rust_2018_preview",
        }
    }

    pub fn is_stable(&self) -> bool {
        match *self {
            Edition::Edition2015 => true,
            Edition::Edition2018 => false,
        }
    }
}

impl FromStr for Edition {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "2015" => Ok(Edition::Edition2015),
            "2018" => Ok(Edition::Edition2018),
            _ => Err(())
        }
    }
}
<commit_msg>Auto merge of #51558 - Manishearth:manish-is-stupid, r=oli-obk<commit_after>// Copyright 2018 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.

use std::fmt;
use std::str::FromStr;

/// The edition of the compiler (RFC 2052)
#[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug, RustcEncodable, RustcDecodable)]
#[non_exhaustive]
pub enum Edition {
    // editions must be kept in order, oldest to newest

    /// The 2015 edition
    Edition2015,
    /// The 2018 edition
    Edition2018,

    // when adding new editions, be sure to update:
    //
    // - Update the `ALL_EDITIONS` const
    // - Update the EDITION_NAME_LIST const
    // - add a `rust_####()` function to the session
    // - update the enum in Cargo's sources as well
}

// must be in order from oldest to newest
pub const ALL_EDITIONS: &[Edition] = &[Edition::Edition2015, Edition::Edition2018];

pub const EDITION_NAME_LIST: &'static str = "2015|2018";

pub const DEFAULT_EDITION: Edition = Edition::Edition2015;

impl fmt::Display for Edition {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = match *self {
            Edition::Edition2015 => "2015",
            Edition::Edition2018 => "2018",
        };
        write!(f, "{}", s)
    }
}

impl Edition {
    pub fn lint_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_compatibility",
            Edition::Edition2018 => "rust_2018_compatibility",
        }
    }

    pub fn feature_name(&self) -> &'static str {
        match *self {
            Edition::Edition2015 => "rust_2015_preview",
            Edition::Edition2018 => "rust_2018_preview",
        }
    }

    pub fn is_stable(&self) -> bool {
        match *self {
            Edition::Edition2015 => true,
            Edition::Edition2018 => false,
        }
    }
}

impl FromStr for Edition {
    type Err = ();
    fn from_str(s: &str) -> Result<Self, ()> {
        match s {
            "2015" => Ok(Edition::Edition2015),
            "2018" => Ok(Edition::Edition2018),
            _ => Err(())
        }
    }
}
<|endoftext|>


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

//! The fixed-size array type (`[T; n]`).

#![doc(primitive = "array")]
<commit_msg>doc: add some array usage examples<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! The fixed-size array type (`[T; n]`).
//!
//! Some usage examples:
//!
//! ```
//! let array: [i32; 3] = [0, 1, 2];
//!
//! assert_eq!(0, array[0]);
//! assert_eq!([0, 1], &array[..2]);
//!
//! for x in &array {
//!     println!("{}", x);
//! }
//! ```

#![doc(primitive = "array")]
<|endoftext|>


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

#![deny(warnings)]

extern crate build_helper;
extern crate cc;

use build_helper::native_lib_boilerplate;
use std::env;
use std::fs::File;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    if cfg!(feature = "backtrace") &&
        !target.contains("cloudabi") &&
        !target.contains("emscripten") &&
        !target.contains("fuchsia") &&
        !target.contains("msvc") &&
        !target.contains("wasm32")
    {
        let _ = build_libbacktrace(&target);
    }

    if target.contains("linux") {
        if target.contains("android") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=log");
            println!("cargo:rustc-link-lib=gcc");
        } else if !target.contains("musl") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=rt");
            println!("cargo:rustc-link-lib=pthread");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=execinfo");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("dragonfly") || target.contains("bitrig") ||
              target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=socket");
        println!("cargo:rustc-link-lib=posix4");
        println!("cargo:rustc-link-lib=pthread");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-darwin") {
        println!("cargo:rustc-link-lib=System");

        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-ios") {
        println!("cargo:rustc-link-lib=System");
        println!("cargo:rustc-link-lib=objc");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=Foundation");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=userenv");
        println!("cargo:rustc-link-lib=shell32");
    } else if target.contains("fuchsia") {
        // use system-provided libbacktrace
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=backtrace");
        }
        println!("cargo:rustc-link-lib=zircon");
        println!("cargo:rustc-link-lib=fdio");
    } else if target.contains("cloudabi") {
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=unwind");
        }
        println!("cargo:rustc-link-lib=c");
        println!("cargo:rustc-link-lib=compiler_rt");
    }
}

fn build_libbacktrace(target: &str) -> Result<(), ()> {
    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", "")?;

    let mut build = cc::Build::new();
    build
        .flag("-fvisibility=hidden")
        .include("../libbacktrace")
        .include(&native.out_dir)
        .out_dir(&native.out_dir)
        .warnings(false)
        .file("../libbacktrace/alloc.c")
        .file("../libbacktrace/backtrace.c")
        .file("../libbacktrace/dwarf.c")
        .file("../libbacktrace/fileline.c")
        .file("../libbacktrace/posix.c")
        .file("../libbacktrace/read.c")
        .file("../libbacktrace/sort.c")
        .file("../libbacktrace/state.c");

    if target.contains("darwin") {
        build.file("../libbacktrace/macho.c");
    } else if target.contains("windows") {
        build.file("../libbacktrace/pecoff.c");
    } else {
        build.file("../libbacktrace/elf.c");

        if target.contains("64") {
            build.define("BACKTRACE_ELF_SIZE", "64");
        } else {
            build.define("BACKTRACE_ELF_SIZE", "32");
        }
    }

    File::create(native.out_dir.join("backtrace-supported.h")).unwrap();
    build.define("BACKTRACE_SUPPORTED", "1");
    build.define("BACKTRACE_USES_MALLOC", "1");
    build.define("BACKTRACE_SUPPORTS_THREADS", "0");
    build.define("BACKTRACE_SUPPORTS_DATA", "0");

    File::create(native.out_dir.join("config.h")).unwrap();
    if !target.contains("apple-ios") &&
       !target.contains("solaris") &&
       !target.contains("redox") &&
       !target.contains("android") {
        build.define("HAVE_DL_ITERATE_PHDR", "1");
    }
    build.define("_GNU_SOURCE", "1");
    build.define("_LARGE_FILES", "1");

    build.compile("backtrace");
    Ok(())
}
<commit_msg>Haiku: fix build of libbacktrace<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![deny(warnings)]

extern crate build_helper;
extern crate cc;

use build_helper::native_lib_boilerplate;
use std::env;
use std::fs::File;

fn main() {
    let target = env::var("TARGET").expect("TARGET was not set");
    if cfg!(feature = "backtrace") &&
        !target.contains("cloudabi") &&
        !target.contains("emscripten") &&
        !target.contains("fuchsia") &&
        !target.contains("msvc") &&
        !target.contains("wasm32")
    {
        let _ = build_libbacktrace(&target);
    }

    if target.contains("linux") {
        if target.contains("android") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=log");
            println!("cargo:rustc-link-lib=gcc");
        } else if !target.contains("musl") {
            println!("cargo:rustc-link-lib=dl");
            println!("cargo:rustc-link-lib=rt");
            println!("cargo:rustc-link-lib=pthread");
        }
    } else if target.contains("freebsd") {
        println!("cargo:rustc-link-lib=execinfo");
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("dragonfly") || target.contains("bitrig") ||
              target.contains("netbsd") || target.contains("openbsd") {
        println!("cargo:rustc-link-lib=pthread");
    } else if target.contains("solaris") {
        println!("cargo:rustc-link-lib=socket");
        println!("cargo:rustc-link-lib=posix4");
        println!("cargo:rustc-link-lib=pthread");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-darwin") {
        println!("cargo:rustc-link-lib=System");

        // res_init and friends require -lresolv on macOS/iOS.
        // See #41582 and http://blog.achernya.com/2013/03/os-x-has-silly-libsystem.html
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("apple-ios") {
        println!("cargo:rustc-link-lib=System");
        println!("cargo:rustc-link-lib=objc");
        println!("cargo:rustc-link-lib=framework=Security");
        println!("cargo:rustc-link-lib=framework=Foundation");
        println!("cargo:rustc-link-lib=resolv");
    } else if target.contains("windows") {
        println!("cargo:rustc-link-lib=advapi32");
        println!("cargo:rustc-link-lib=ws2_32");
        println!("cargo:rustc-link-lib=userenv");
        println!("cargo:rustc-link-lib=shell32");
    } else if target.contains("fuchsia") {
        // use system-provided libbacktrace
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=backtrace");
        }
        println!("cargo:rustc-link-lib=zircon");
        println!("cargo:rustc-link-lib=fdio");
    } else if target.contains("cloudabi") {
        if cfg!(feature = "backtrace") {
            println!("cargo:rustc-link-lib=unwind");
        }
        println!("cargo:rustc-link-lib=c");
        println!("cargo:rustc-link-lib=compiler_rt");
    }
}

fn build_libbacktrace(target: &str) -> Result<(), ()> {
    let native = native_lib_boilerplate("libbacktrace", "libbacktrace", "backtrace", "")?;

    let mut build = cc::Build::new();
    build
        .flag("-fvisibility=hidden")
        .include("../libbacktrace")
        .include(&native.out_dir)
        .out_dir(&native.out_dir)
        .warnings(false)
        .file("../libbacktrace/alloc.c")
        .file("../libbacktrace/backtrace.c")
        .file("../libbacktrace/dwarf.c")
        .file("../libbacktrace/fileline.c")
        .file("../libbacktrace/posix.c")
        .file("../libbacktrace/read.c")
        .file("../libbacktrace/sort.c")
        .file("../libbacktrace/state.c");

    if target.contains("darwin") {
        build.file("../libbacktrace/macho.c");
    } else if target.contains("windows") {
        build.file("../libbacktrace/pecoff.c");
    } else {
        build.file("../libbacktrace/elf.c");

        if target.contains("64") {
            build.define("BACKTRACE_ELF_SIZE", "64");
        } else {
            build.define("BACKTRACE_ELF_SIZE", "32");
        }
    }

    File::create(native.out_dir.join("backtrace-supported.h")).unwrap();
    build.define("BACKTRACE_SUPPORTED", "1");
    build.define("BACKTRACE_USES_MALLOC", "1");
    build.define("BACKTRACE_SUPPORTS_THREADS", "0");
    build.define("BACKTRACE_SUPPORTS_DATA", "0");

    File::create(native.out_dir.join("config.h")).unwrap();
    if !target.contains("apple-ios") &&
       !target.contains("solaris") &&
       !target.contains("redox") &&
       !target.contains("android") &&
       !target.contains("haiku") {
        build.define("HAVE_DL_ITERATE_PHDR", "1");
    }
    build.define("_GNU_SOURCE", "1");
    build.define("_LARGE_FILES", "1");

    build.compile("backtrace");
    Ok(())
}
<|endoftext|>


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

//! Panic support in the standard library

#![unstable(feature = "std_panic", reason = "awaiting feedback",
            issue = "27719")]

use any::Any;
use boxed::Box;
use cell::UnsafeCell;
use ops::{Deref, DerefMut};
use ptr::{Unique, Shared};
use rc::Rc;
use sync::{Arc, Mutex, RwLock};
use sys_common::unwind;
use thread::Result;

pub use panicking::{take_handler, set_handler, PanicInfo, Location};

/// A marker trait which represents "panic safe" types in Rust.
///
/// This trait is implemented by default for many types and behaves similarly in
/// terms of inference of implementation to the `Send` and `Sync` traits. The
/// purpose of this trait is to encode what types are safe to cross a `recover`
/// boundary with no fear of panic safety.
///
/// ## What is panic safety?
///
/// In Rust a function can "return" early if it either panics or calls a
/// function which transitively panics. This sort of control flow is not always
/// anticipated, and has the possibility of causing subtle bugs through a
/// combination of two cricial components:
///
/// 1. A data structure is in a temporarily invalid state when the thread
///    panics.
/// 2. This broken invariant is then later observed.
///
/// Typically in Rust, it is difficult to perform step (2) because catching a
/// panic involves either spawning a thread (which in turns makes it difficult
/// to later witness broken invariants) or using the `recover` function in this
/// module. Additionally, even if an invariant is witnessed, it typically isn't a
/// problem in Rust because there's no uninitialized values (like in C or C++).
///
/// It is possible, however, for **logical** invariants to be broken in Rust,
/// which can end up causing behavioral bugs. Another key aspect of panic safety
/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to
/// memory unsafety.
///
/// That was a bit of a whirlwind tour of panic safety, but for more information
/// about panic safety and how it applies to Rust, see an [associated RFC][rfc].
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// ## What is `RecoverSafe`?
///
/// Now that we've got an idea of what panic safety is in Rust, it's also
/// important to understand what this trait represents. As mentioned above, one
/// way to witness broken invariants is through the `recover` function in this
/// module as it allows catching a panic and then re-using the environment of
/// the closure.
///
/// Simply put, a type `T` implements `RecoverSafe` if it cannot easily allow
/// witnessing a broken invariant through the use of `recover` (catching a
/// panic). This trait is a marker trait, so it is automatically implemented for
/// many types, and it is also structurally composed (e.g. a struct is recover
/// safe if all of its components are recover safe).
///
/// Note, however, that this is not an unsafe trait, so there is not a succinct
/// contract that this trait is providing. Instead it is intended as more of a
/// "speed bump" to alert users of `recover` that broken invariants may be
/// witnessed and may need to be accounted for.
///
/// ## Who implements `RecoverSafe`?
///
/// Types such as `&mut T` and `&RefCell<T>` are examples which are **not**
/// recover safe. The general idea is that any mutable state which can be shared
/// across `recover` is not recover safe by default. This is because it is very
/// easy to witness a broken invariant outside of `recover` as the data is
/// simply accessed as usual.
///
/// Types like `&Mutex<T>`, however, are recover safe because they implement
/// poisoning by default. They still allow witnessing a broken invariant, but
/// they already provide their own "speed bumps" to do so.
///
/// ## When should `RecoverSafe` be used?
///
/// Is not intended that most types or functions need to worry about this trait.
/// It is only used as a bound on the `recover` function and as mentioned above,
/// the lack of `unsafe` means it is mostly an advisory. The `AssertRecoverSafe`
/// wrapper struct in this module can be used to force this trait to be
/// implemented for any closed over variables passed to the `recover` function
/// (more on this below).
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                            across a recover boundary"]
pub trait RecoverSafe {}

/// A marker trait representing types where a shared reference is considered
/// recover safe.
///
/// This trait is namely not implemented by `UnsafeCell`, the root of all
/// interior mutability.
///
/// This is a "helper marker trait" used to provide impl blocks for the
/// `RecoverSafe` trait, for more information see that documentation.
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                            and a reference may not be safely transferrable \
                            across a recover boundary"]
pub trait RefRecoverSafe {}

/// A simple wrapper around a type to assert that it is panic safe.
///
/// When using `recover` it may be the case that some of the closed over
/// variables are not panic safe. For example if `&mut T` is captured the
/// compiler will generate a warning indicating that it is not panic safe. It
/// may not be the case, however, that this is actually a problem due to the
/// specific usage of `recover` if panic safety is specifically taken into
/// account. This wrapper struct is useful for a quick and lightweight
/// annotation that a variable is indeed panic safe.
///
/// # Examples
///
/// One way to use `AssertRecoverSafe` is to assert that the entire closure
/// itself is recover safe, bypassing all checks for all variables:
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic::{self, AssertRecoverSafe};
///
/// let mut variable = 4;
///
/// // This code will not compile because the closure captures `&mut variable`
/// // which is not considered panic safe by default.
///
/// // panic::recover(|| {
/// //     variable += 3;
/// // });
///
/// // This, however, will compile due to the `AssertRecoverSafe` wrapper
/// let result = panic::recover(AssertRecoverSafe(|| {
///     variable += 3;
/// }));
/// // ...
/// ```
///
/// Wrapping the entire closure amounts to a blanket assertion that all captured
/// variables are recover safe. This has the downside that if new captures are
/// added in the future, they will also be considered recover safe. Therefore,
/// you may prefer to just wrap individual captures, as shown below. This is
/// more annotation, but it ensures that if a new capture is added which is not
/// recover safe, you will get a compilation error at that time, which will
/// allow you to consider whether that new capture in fact represent a bug or
/// not.
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic::{self, AssertRecoverSafe};
///
/// let mut variable = 4;
/// let other_capture = 3;
///
/// let result = {
///     let mut wrapper = AssertRecoverSafe(&mut variable);
///     panic::recover(move || {
///         **wrapper += other_capture;
///     })
/// };
/// // ...
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub struct AssertRecoverSafe<T>(pub T);

// Implementations of the `RecoverSafe` trait:
//
// * By default everything is recover safe
// * pointers T contains mutability of some form are not recover safe
// * Unique, an owning pointer, lifts an implementation
// * Types like Mutex/RwLock which are explicilty poisoned are recover safe
// * Our custom AssertRecoverSafe wrapper is indeed recover safe
impl RecoverSafe for .. {}
impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
impl<T: ?Sized> RecoverSafe for Mutex<T> {}
impl<T: ?Sized> RecoverSafe for RwLock<T> {}
impl<T> RecoverSafe for AssertRecoverSafe<T> {}

// not covered via the Shared impl above b/c the inner contents use
// Cell/AtomicUsize, but the usage here is recover safe so we can lift the
// impl up one level to Arc/Rc itself
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}

// Pretty simple implementations for the `RefRecoverSafe` marker trait,
// basically just saying that this is a marker trait and `UnsafeCell` is the
// only thing which doesn't implement it (which then transitively applies to
// everything else).
impl RefRecoverSafe for .. {}
impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}

impl<T> AssertRecoverSafe<T> {
    /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    #[rustc_deprecated(reason = "the type's field is now public, construct it directly", since = "1.9.0")]
    pub fn new(t: T) -> AssertRecoverSafe<T> {
        AssertRecoverSafe(t)
    }

    /// Consumes the `AssertRecoverSafe`, returning the wrapped value.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    #[rustc_deprecated(reason = "the type's field is now public, access it directly", since = "1.9.0)]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> Deref for AssertRecoverSafe<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for AssertRecoverSafe<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
    type Output = R;

    extern "rust-call" fn call_once(self, _args: ()) -> R {
        (self.0)()
    }
}

/// Invokes a closure, capturing the cause of panic if one occurs.
///
/// This function will return `Ok` with the closure's result if the closure
/// does not panic, and will return `Err(cause)` if the closure panics. The
/// `cause` returned is the object with which panic was originally invoked.
///
/// It is currently undefined behavior to unwind from Rust code into foreign
/// code, so this function is particularly useful when Rust is called from
/// another language (normally C). This can run arbitrary Rust code, capturing a
/// panic and allowing a graceful handling of the error.
///
/// It is **not** recommended to use this function for a general try/catch
/// mechanism. The `Result` type is more appropriate to use for functions that
/// can fail on a regular basis.
///
/// The closure provided is required to adhere to the `RecoverSafe` to ensure
/// that all captured variables are safe to cross this recover boundary. The
/// purpose of this bound is to encode the concept of [exception safety][rfc] in
/// the type system. Most usage of this function should not need to worry about
/// this bound as programs are naturally panic safe without `unsafe` code. If it
/// becomes a problem the associated `AssertRecoverSafe` wrapper type in this
/// module can be used to quickly assert that the usage here is indeed exception
/// safe.
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// # Examples
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     println!("hello!");
/// });
/// assert!(result.is_ok());
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
/// assert!(result.is_err());
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
    let mut result = None;
    unsafe {
        let result = &mut result;
        try!(unwind::try(move || *result = Some(f())))
    }
    Ok(result.unwrap())
}

/// Triggers a panic without invoking the panic handler.
///
/// This is designed to be used in conjunction with `recover` to, for example,
/// carry a panic across a layer of C code.
///
/// # Examples
///
/// ```should_panic
/// #![feature(std_panic, recover, panic_propagate)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
///
/// if let Err(err) = result {
///     panic::propagate(err);
/// }
/// ```
#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
pub fn propagate(payload: Box<Any + Send>) -> ! {
    unwind::rust_panic(payload)
}
<commit_msg>Fix tidy<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Panic support in the standard library

#![unstable(feature = "std_panic", reason = "awaiting feedback",
            issue = "27719")]

use any::Any;
use boxed::Box;
use cell::UnsafeCell;
use ops::{Deref, DerefMut};
use ptr::{Unique, Shared};
use rc::Rc;
use sync::{Arc, Mutex, RwLock};
use sys_common::unwind;
use thread::Result;

pub use panicking::{take_handler, set_handler, PanicInfo, Location};

/// A marker trait which represents "panic safe" types in Rust.
///
/// This trait is implemented by default for many types and behaves similarly in
/// terms of inference of implementation to the `Send` and `Sync` traits. The
/// purpose of this trait is to encode what types are safe to cross a `recover`
/// boundary with no fear of panic safety.
///
/// ## What is panic safety?
///
/// In Rust a function can "return" early if it either panics or calls a
/// function which transitively panics. This sort of control flow is not always
/// anticipated, and has the possibility of causing subtle bugs through a
/// combination of two cricial components:
///
/// 1. A data structure is in a temporarily invalid state when the thread
///    panics.
/// 2. This broken invariant is then later observed.
///
/// Typically in Rust, it is difficult to perform step (2) because catching a
/// panic involves either spawning a thread (which in turns makes it difficult
/// to later witness broken invariants) or using the `recover` function in this
/// module. Additionally, even if an invariant is witnessed, it typically isn't a
/// problem in Rust because there's no uninitialized values (like in C or C++).
///
/// It is possible, however, for **logical** invariants to be broken in Rust,
/// which can end up causing behavioral bugs. Another key aspect of panic safety
/// in Rust is that, in the absence of `unsafe` code, a panic cannot lead to
/// memory unsafety.
///
/// That was a bit of a whirlwind tour of panic safety, but for more information
/// about panic safety and how it applies to Rust, see an [associated RFC][rfc].
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// ## What is `RecoverSafe`?
///
/// Now that we've got an idea of what panic safety is in Rust, it's also
/// important to understand what this trait represents. As mentioned above, one
/// way to witness broken invariants is through the `recover` function in this
/// module as it allows catching a panic and then re-using the environment of
/// the closure.
///
/// Simply put, a type `T` implements `RecoverSafe` if it cannot easily allow
/// witnessing a broken invariant through the use of `recover` (catching a
/// panic). This trait is a marker trait, so it is automatically implemented for
/// many types, and it is also structurally composed (e.g. a struct is recover
/// safe if all of its components are recover safe).
///
/// Note, however, that this is not an unsafe trait, so there is not a succinct
/// contract that this trait is providing. Instead it is intended as more of a
/// "speed bump" to alert users of `recover` that broken invariants may be
/// witnessed and may need to be accounted for.
///
/// ## Who implements `RecoverSafe`?
///
/// Types such as `&mut T` and `&RefCell<T>` are examples which are **not**
/// recover safe. The general idea is that any mutable state which can be shared
/// across `recover` is not recover safe by default. This is because it is very
/// easy to witness a broken invariant outside of `recover` as the data is
/// simply accessed as usual.
///
/// Types like `&Mutex<T>`, however, are recover safe because they implement
/// poisoning by default. They still allow witnessing a broken invariant, but
/// they already provide their own "speed bumps" to do so.
///
/// ## When should `RecoverSafe` be used?
///
/// Is not intended that most types or functions need to worry about this trait.
/// It is only used as a bound on the `recover` function and as mentioned above,
/// the lack of `unsafe` means it is mostly an advisory. The `AssertRecoverSafe`
/// wrapper struct in this module can be used to force this trait to be
/// implemented for any closed over variables passed to the `recover` function
/// (more on this below).
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} may not be safely transferred \
                            across a recover boundary"]
pub trait RecoverSafe {}

/// A marker trait representing types where a shared reference is considered
/// recover safe.
///
/// This trait is namely not implemented by `UnsafeCell`, the root of all
/// interior mutability.
///
/// This is a "helper marker trait" used to provide impl blocks for the
/// `RecoverSafe` trait, for more information see that documentation.
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
#[rustc_on_unimplemented = "the type {Self} contains interior mutability \
                            and a reference may not be safely transferrable \
                            across a recover boundary"]
pub trait RefRecoverSafe {}

/// A simple wrapper around a type to assert that it is panic safe.
///
/// When using `recover` it may be the case that some of the closed over
/// variables are not panic safe. For example if `&mut T` is captured the
/// compiler will generate a warning indicating that it is not panic safe. It
/// may not be the case, however, that this is actually a problem due to the
/// specific usage of `recover` if panic safety is specifically taken into
/// account. This wrapper struct is useful for a quick and lightweight
/// annotation that a variable is indeed panic safe.
///
/// # Examples
///
/// One way to use `AssertRecoverSafe` is to assert that the entire closure
/// itself is recover safe, bypassing all checks for all variables:
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic::{self, AssertRecoverSafe};
///
/// let mut variable = 4;
///
/// // This code will not compile because the closure captures `&mut variable`
/// // which is not considered panic safe by default.
///
/// // panic::recover(|| {
/// //     variable += 3;
/// // });
///
/// // This, however, will compile due to the `AssertRecoverSafe` wrapper
/// let result = panic::recover(AssertRecoverSafe(|| {
///     variable += 3;
/// }));
/// // ...
/// ```
///
/// Wrapping the entire closure amounts to a blanket assertion that all captured
/// variables are recover safe. This has the downside that if new captures are
/// added in the future, they will also be considered recover safe. Therefore,
/// you may prefer to just wrap individual captures, as shown below. This is
/// more annotation, but it ensures that if a new capture is added which is not
/// recover safe, you will get a compilation error at that time, which will
/// allow you to consider whether that new capture in fact represent a bug or
/// not.
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic::{self, AssertRecoverSafe};
///
/// let mut variable = 4;
/// let other_capture = 3;
///
/// let result = {
///     let mut wrapper = AssertRecoverSafe(&mut variable);
///     panic::recover(move || {
///         **wrapper += other_capture;
///     })
/// };
/// // ...
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub struct AssertRecoverSafe<T>(pub T);

// Implementations of the `RecoverSafe` trait:
//
// * By default everything is recover safe
// * pointers T contains mutability of some form are not recover safe
// * Unique, an owning pointer, lifts an implementation
// * Types like Mutex/RwLock which are explicilty poisoned are recover safe
// * Our custom AssertRecoverSafe wrapper is indeed recover safe
impl RecoverSafe for .. {}
impl<'a, T: ?Sized> !RecoverSafe for &'a mut T {}
impl<'a, T: RefRecoverSafe + ?Sized> RecoverSafe for &'a T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *const T {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for *mut T {}
impl<T: RecoverSafe> RecoverSafe for Unique<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Shared<T> {}
impl<T: ?Sized> RecoverSafe for Mutex<T> {}
impl<T: ?Sized> RecoverSafe for RwLock<T> {}
impl<T> RecoverSafe for AssertRecoverSafe<T> {}

// not covered via the Shared impl above b/c the inner contents use
// Cell/AtomicUsize, but the usage here is recover safe so we can lift the
// impl up one level to Arc/Rc itself
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Rc<T> {}
impl<T: RefRecoverSafe + ?Sized> RecoverSafe for Arc<T> {}

// Pretty simple implementations for the `RefRecoverSafe` marker trait,
// basically just saying that this is a marker trait and `UnsafeCell` is the
// only thing which doesn't implement it (which then transitively applies to
// everything else).
impl RefRecoverSafe for .. {}
impl<T: ?Sized> !RefRecoverSafe for UnsafeCell<T> {}
impl<T> RefRecoverSafe for AssertRecoverSafe<T> {}

impl<T> AssertRecoverSafe<T> {
    /// Creates a new `AssertRecoverSafe` wrapper around the provided type.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    #[rustc_deprecated(reason = "the type's field is now public, construct it directly",
                       since = "1.9.0")]
    pub fn new(t: T) -> AssertRecoverSafe<T> {
        AssertRecoverSafe(t)
    }

    /// Consumes the `AssertRecoverSafe`, returning the wrapped value.
    #[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
    #[rustc_deprecated(reason = "the type's field is now public, access it directly",
                       since = "1.9.0")]
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> Deref for AssertRecoverSafe<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> DerefMut for AssertRecoverSafe<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<R, F: FnOnce() -> R> FnOnce<()> for AssertRecoverSafe<F> {
    type Output = R;

    extern "rust-call" fn call_once(self, _args: ()) -> R {
        (self.0)()
    }
}

/// Invokes a closure, capturing the cause of panic if one occurs.
///
/// This function will return `Ok` with the closure's result if the closure
/// does not panic, and will return `Err(cause)` if the closure panics. The
/// `cause` returned is the object with which panic was originally invoked.
///
/// It is currently undefined behavior to unwind from Rust code into foreign
/// code, so this function is particularly useful when Rust is called from
/// another language (normally C). This can run arbitrary Rust code, capturing a
/// panic and allowing a graceful handling of the error.
///
/// It is **not** recommended to use this function for a general try/catch
/// mechanism. The `Result` type is more appropriate to use for functions that
/// can fail on a regular basis.
///
/// The closure provided is required to adhere to the `RecoverSafe` to ensure
/// that all captured variables are safe to cross this recover boundary. The
/// purpose of this bound is to encode the concept of [exception safety][rfc] in
/// the type system. Most usage of this function should not need to worry about
/// this bound as programs are naturally panic safe without `unsafe` code. If it
/// becomes a problem the associated `AssertRecoverSafe` wrapper type in this
/// module can be used to quickly assert that the usage here is indeed exception
/// safe.
///
/// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md
///
/// # Examples
///
/// ```
/// #![feature(recover, std_panic)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     println!("hello!");
/// });
/// assert!(result.is_ok());
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
/// assert!(result.is_err());
/// ```
#[unstable(feature = "recover", reason = "awaiting feedback", issue = "27719")]
pub fn recover<F: FnOnce() -> R + RecoverSafe, R>(f: F) -> Result<R> {
    let mut result = None;
    unsafe {
        let result = &mut result;
        try!(unwind::try(move || *result = Some(f())))
    }
    Ok(result.unwrap())
}

/// Triggers a panic without invoking the panic handler.
///
/// This is designed to be used in conjunction with `recover` to, for example,
/// carry a panic across a layer of C code.
///
/// # Examples
///
/// ```should_panic
/// #![feature(std_panic, recover, panic_propagate)]
///
/// use std::panic;
///
/// let result = panic::recover(|| {
///     panic!("oh no!");
/// });
///
/// if let Err(err) = result {
///     panic::propagate(err);
/// }
/// ```
#[unstable(feature = "panic_propagate", reason = "awaiting feedback", issue = "30752")]
pub fn propagate(payload: Box<Any + Send>) -> ! {
    unwind::rust_panic(payload)
}
<|endoftext|>


<commit_before>use bit_twiddles;
use board::*;
use templates::*;

struct MagicHelper {
    square_BB: [u64; 64], // Maps index to square
    magic_bishop_table: [[u64; 4096]; 64],
    magic_rook_table: [[u64; 1024]; 64],
    knight_table: [u64; 64],
    king_table: [u64; 64]
}

//impl MagicHelper {
//    pub fn new() -> MagicHelper {
//        MagicHelper {
//            magic_bishop_moves: MagicHelper::gen_magic_bishop(),
//            magic_rook_moves: MagicHelper::gen_magic_rook()
//        }
//    }
//
//    pub fn default() -> MagicHelper { MagicHelper::new() }
//
//    fn gen_magic_bishop() -> [[u64; 4096]; 64] {
//        let mut arr: [[u64; 4096]; 64] = [[0; 4096]; 64];
//        let mut mask: u64 = 0;
//        for bitRef in 0..64 {
//            mask = BISHOP_MASK[bitRef];
//
//        }
//
//    }
//
//    fn gen_magic_rook() -> [[u64; 1024]; 64] {
//        let mut arr: [[u64; 1024]; 64] = [[0; 1024]; 64];
//
//    }
//}

fn gen_king_moves() -> [u64; 64] {
    let mut moves: [u64;64] = [0; 64];

    for index in 0..64 {
        let mut mask: u64 = 0;
        let file = index % 8;
        // LEFT
        if file != 0 {
            mask |= 1 << (index - 1);
        }
        // RIGHT
        if file != 7 {
            mask |= 1 << (index + 1);
        }
        // UP
        if index < 56  {
            mask |= 1 << (index + 8);
        }
        // DOWN
        if index > 7  {
            mask |= 1 << (index - 8);
        }
        // LEFT UP
        if file != 0 && index < 56 {
            mask |= 1 << (index + 7);
        }
        // LEFT DOWN
        if file != 0 && index > 7 {
            mask |= 1 << (index - 9);
        }
        // RIGHT DOWN
        if file!= 7 && index > 7 {
            mask |= 1 << (index - 7);
        }
        // RIGHT UP
        if file != 7 && index < 56 {
            mask |= 1 << (index + 0);
        }
        moves[index] = mask;
    }
    moves
}

fn gen_knight_moves() -> [u64; 64] {
    let mut moves: [u64;64] = [0; 64];
    for index in 0..64 {
        let mut mask: u64 = 0;
        let file = index % 8;

        // 1 UP   + 2 LEFT
        if file > 1 && index < 56 {
            mask |= 1 << (index + 6);
        }
        // 2 UP   + 1 LEFT
        if file != 0 && index < 48 {
            mask |= 1 << (index + 15);
        }
        // 2 UP   + 1 RIGHT
        if file != 7 && index < 48 {
            mask |= 1 << (index + 17);
        }
        // 1 UP   + 2 RIGHT
        if file < 6 && index < 56 {
            mask |= 1 << (index + 10);
        }
        // 1 DOWN   + 2 RIGHT
        if file < 6 && index > 7 {
            mask |= 1 << (index - 6);
        }
        // 2 DOWN   + 1 RIGHT
        if file != 7 && index > 15 {
            mask |= 1 << (index - 15 );
        }
        // 2 DOWN   + 1 LEFT
        if file != 0 && index > 15 {
            mask |= 1 << (index - 17 );
        }
        // 1 DOWN   + 2 LEFT
        if file > 1 && index > 7 {
            mask |= 1 << (index - 10 );
        }
        moves[index] = mask;
    }
    moves
}

//Bitboard  RookMasks  [SQUARE_NB];
//Bitboard  RookMagics [SQUARE_NB];
//Bitboard* RookAttacks[SQUARE_NB];
//unsigned  RookShifts [SQUARE_NB];
//
//Bitboard  BishopMasks  [SQUARE_NB];
//Bitboard  BishopMagics [SQUARE_NB];
//Bitboard* BishopAttacks[SQUARE_NB];
//unsigned  BishopShifts [SQUARE_NB];
//Bitboard RookTable[0x19000];  // To store rook attacks
//Bitboard BishopTable[0x1480]; // To store bishop attacks

// RookTable
fn get_magics() {
    let rook_table: [u64; 0x19000] = [0; 0x19000];
    let bishop_table: [u64; 0x1480] = [0; 0x1480];

    let rook_masks: [u64; 64] = [0; 64];
    let rook_magics: [u64; 64] = [0; 64];
    let rook_attacks: [u64; 64] = [0; 64];
    let rook_shifts: [u64; 64] = [0; 64];

    let bishop_masks: [u64; 64] = [0; 64];
    let bishop_magics: [u64; 64] = [0; 64];
    let bishop_attacks: [u64; 64] = [0; 64];
    let bishop_shifts: [u64; 64] = [0; 64];

}

fn init_rook_magics(mut table: [u64; 0x19000], mut attacks: [u64; 64], magics: [u64; 64],
                    mut masks: [u64; 64], shifts: [u64; 64], deltas: [u64; 64], index: [u64; 64]) {

    let seeds: [[i32;8]; 2] = [ [ 8977, 44560, 54343, 38998,  5731, 95205, 104912, 17020 ],
                                [  728, 10316, 55013, 32803, 12281, 15100,  16645,   255 ] ];

    let bishop_deltas: [i8; 4] = [7,9,9,7];
    let rook_deltas: [i8; 4] = [8,1,-8,1];

    let mut occupancy: [u64; 4096] = [0; 4096];
    let mut reference: [u64; 4096] = [0; 4096];
    let mut edges: u64 = 0;
    let mut age: [i32; 4096] =  [0; 4096];
    let mut current: i32 = 0;
    let mut size: usize = 0;

    for s in 0..64 {
        // ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
        edges = ((RANK_1 | RANK_8) & !rank_bb(s)) | ((FILE_A | FILE_B) & !file_bb(s));

        masks[s] = sliding_attack(deltas, s, 0) & !edges;
        shifts[s] = 64 - popcount(masks[s as usize]);
        d = size = 0;

        loop {
            occupancy[size] = b;
            reference[size] = sliding_attack(deltas, s, b);
            size += 1;
            b = (b - masks[s as usize]) * masks[s as usize];
            if b == 0 {
                break;
            }
        }

        if s < 63 {
            attacks[s + 1] = attacks[s as usize] + size;
        }

        let mut rng = PRNG::init(seeds[1][rank_of(s)]);

        'outer: loop {
            'first_in: loop {
                magics[s] = rng.sparse_rand();
                if popcount((magics[s as usize] * masks[s as usize]) >> 56) < 6 {
                    break 'first_in;
                }
            }
            // magic_index return unsigned(((occupied & Masks[s]) * Magics[s]) >> Shifts[s]);
            current += 1;
            let mut i: usize = 0;
            'secon_in: while i < size {
                let index: usize = (((occupied[i as usize] & masks[s as usize]) * magics[s as usize]) >> Shifts[s as usize]) as usize;
                if age[index] < current {
                    age[index] = current;
                    attacks[s as usize][index] = reference[i];
                } else if attacks[s as usize][index as usize] != reference[i] {
                    break 'secon_in;
                }
            }
            if i < size {
                break 'outer;
            }
        }
    }

}

struct PRNG {
    seed: u64
}

impl PRNG {
    pub fn init(s: seed) -> PRNG {
        assert!(s);
        PRNG {seed: s}
    }

    pub fn rand(&mut self) -> u64 {
        self.rand_change()
    }

    pub fn sparse_rand(&mut self) -> u64 {
        let mut s = self.rand_change();
        s ^= self.rand_change();
        s ^= self.rand_change();
        s
    }

    fn rand_change(&mut self) -> u64 {
        self.seed ^= self.seed >> 12;
        self.seed ^= self.seed << 25;
        self.seed ^= self.seed >> 27;

        self.seed * 2685821657736338717
    }
}

fn sliding_attack(deltas: [u64; 4], square: u64, u64: occupied) -> u64 {
    let mut attack: u64 = 0;

    for i in 0..4 {
        let mut s: u64 = square + deltas[i];
        while is_ok(s) &&  distance(s, s - deltas[i]) == 1 {

            if occupied & s { break;}
            s += deltas[i];
        }
    }
    attack
}

pub fn gen_rook_masks() {
    let mut arr_masks: [u64; 64] = [0; 64];
    let mut shifts: [u8; 64] = [0; 64];

    let mut bit_ref: usize = 0;
    while bit_ref < 64 {
        let mut mask: u64 = 0;
        let mut i = bit_ref + 8;
        while i < 56 {
            mask |= (1 as u64) << (i as u8);
            i += 8;
        }
        if bit_ref > 7 {
            let mut i = bit_ref - 8;
            while i > 7 {
                mask |= (1 as u64) << (i as u8);
                i -= 8;
            }
        }
        let mut i = bit_ref + 1;
        while i % 8 != 0 && i <= 63 {
            mask |= (1 as u64) << (i as u8);
            i += 1;
        }
        if bit_ref > 0  {
            let mut i = bit_ref - 1;
            while i % 8 != 0 && i >= 0 {
                mask |= (1 as u64) << (i as u8);
                i -= 1;
            }
        }
        arr_masks[bit_ref] = mask;
        format_bits(format!("{:b}",mask));
        bit_ref += 1;
    }
}

pub fn gen_bishop_masks() {
    let mut arr_masks: [u64; 64] = [0; 64];
    let mut shifts: [u8; 64] = [0; 64];

    let mut bitRef: i32 = 0;
    while bitRef < 64 {
        let mut mask: u64 = 0;

        let mut i = bitRef + 9;
        while i < 56 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i += 9;
        }
        let mut i = bitRef - 9;
        while i > 7 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i -= 9;
        }
        let mut i = bitRef + 7;
        while i < 56 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i += 7;
        }

        let mut i = bitRef - 7;
        while i > 7 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i -= 7;
        }
        format_bits(format!("{:b}",mask));
        arr_masks[bitRef as usize] = mask;
        bitRef += 1;
    }
}

pub fn format_bits(bits: String) {
    let x = 64 - bits.len();
    let mut i = 0;
    while i < x {
        print!("0");
        i += 1;
    }
    println!("{}",bits);
}

#[test]
fn test_king_mask_gen() {
    let arr = gen_king_moves().to_vec();
    let sum = arr.iter().fold(0 as  u64,|a, &b| a + (bit_twiddles::popcount64(b) as u64));
    assert_eq!(sum, (3*4) + (5 * 6 * 4) + (8 * 6 * 6));
}

#[test]
fn test_knight_mask_gen() {
    let arr = gen_knight_moves().to_vec();
    let sum = arr.iter().fold(0 as  u64,|a, &b| a + (bit_twiddles::popcount64(b) as u64));
    assert_eq!(sum, (2 * 4) + (4 * 4) + (3 * 2 * 4) + (4 * 4 * 4) + (6 * 4 * 4) + (8 * 4 * 4));
}
<commit_msg>Further Magic work<commit_after>use bit_twiddles::*;
use board::*;
use templates::*;
use std::ptr;

struct MagicHelper {
    square_BB: [u64; 64], // Maps index to square
    magic_bishop_table: [[u64; 4096]; 64],
    magic_rook_table: [[u64; 1024]; 64],
    knight_table: [u64; 64],
    king_table: [u64; 64]
}

//impl MagicHelper {
//    pub fn new() -> MagicHelper {
//        MagicHelper {
//            magic_bishop_moves: MagicHelper::gen_magic_bishop(),
//            magic_rook_moves: MagicHelper::gen_magic_rook()
//        }
//    }
//
//    pub fn default() -> MagicHelper { MagicHelper::new() }
//
//    fn gen_magic_bishop() -> [[u64; 4096]; 64] {
//        let mut arr: [[u64; 4096]; 64] = [[0; 4096]; 64];
//        let mut mask: u64 = 0;
//        for bitRef in 0..64 {
//            mask = BISHOP_MASK[bitRef];
//
//        }
//
//    }
//
//    fn gen_magic_rook() -> [[u64; 1024]; 64] {
//        let mut arr: [[u64; 1024]; 64] = [[0; 1024]; 64];
//
//    }
//}

fn gen_king_moves() -> [u64; 64] {
    let mut moves: [u64;64] = [0; 64];

    for index in 0..64 {
        let mut mask: u64 = 0;
        let file = index % 8;
        // LEFT
        if file != 0 {
            mask |= 1 << (index - 1);
        }
        // RIGHT
        if file != 7 {
            mask |= 1 << (index + 1);
        }
        // UP
        if index < 56  {
            mask |= 1 << (index + 8);
        }
        // DOWN
        if index > 7  {
            mask |= 1 << (index - 8);
        }
        // LEFT UP
        if file != 0 && index < 56 {
            mask |= 1 << (index + 7);
        }
        // LEFT DOWN
        if file != 0 && index > 7 {
            mask |= 1 << (index - 9);
        }
        // RIGHT DOWN
        if file!= 7 && index > 7 {
            mask |= 1 << (index - 7);
        }
        // RIGHT UP
        if file != 7 && index < 56 {
            mask |= 1 << (index + 0);
        }
        moves[index] = mask;
    }
    moves
}

fn gen_knight_moves() -> [u64; 64] {
    let mut moves: [u64;64] = [0; 64];
    for index in 0..64 {
        let mut mask: u64 = 0;
        let file = index % 8;

        // 1 UP   + 2 LEFT
        if file > 1 && index < 56 {
            mask |= 1 << (index + 6);
        }
        // 2 UP   + 1 LEFT
        if file != 0 && index < 48 {
            mask |= 1 << (index + 15);
        }
        // 2 UP   + 1 RIGHT
        if file != 7 && index < 48 {
            mask |= 1 << (index + 17);
        }
        // 1 UP   + 2 RIGHT
        if file < 6 && index < 56 {
            mask |= 1 << (index + 10);
        }
        // 1 DOWN   + 2 RIGHT
        if file < 6 && index > 7 {
            mask |= 1 << (index - 6);
        }
        // 2 DOWN   + 1 RIGHT
        if file != 7 && index > 15 {
            mask |= 1 << (index - 15 );
        }
        // 2 DOWN   + 1 LEFT
        if file != 0 && index > 15 {
            mask |= 1 << (index - 17 );
        }
        // 1 DOWN   + 2 LEFT
        if file > 1 && index > 7 {
            mask |= 1 << (index - 10 );
        }
        moves[index] = mask;
    }
    moves
}

//Bitboard  RookMasks  [SQUARE_NB];
//Bitboard  RookMagics [SQUARE_NB];
//Bitboard* RookAttacks[SQUARE_NB];
//unsigned  RookShifts [SQUARE_NB];
//
//Bitboard  BishopMasks  [SQUARE_NB];
//Bitboard  BishopMagics [SQUARE_NB];
//Bitboard* BishopAttacks[SQUARE_NB];
//unsigned  BishopShifts [SQUARE_NB];
//Bitboard RookTable[0x19000];  // To store rook attacks
//Bitboard BishopTable[0x1480]; // To store bishop attacks

// RookTable
fn get_magics() {
    let rook_table: [u64; 0x19000] = [0; 0x19000];
    let bishop_table: [u64; 0x1480] = [0; 0x1480];

    let rook_masks: [u64; 64] = [0; 64];
    let rook_magics: [u64; 64] = [0; 64];
    let rook_attacks: [u64; 64] = [0; 64];
    let rook_shifts: [u64; 64] = [0; 64];

    let bishop_masks: [u64; 64] = [0; 64];
    let bishop_magics: [u64; 64] = [0; 64];
    let bishop_attacks: [u64; 64] = [0; 64];
    let bishop_shifts: [u64; 64] = [0; 64];

}

// std::mem::transmute::<f32, u32>(1.0)
fn init_rook_magics(mut table: [u64; 0x19000], mut attacks: [*mut u64; 64], magics: [u64; 64],
                    mut masks: [u64; 64], shifts: [u64; 64], deltas: [u64; 4], index: [u64; 64]) {

    let seeds: [[u64;8]; 2] = [ [ 8977, 44560, 54343, 38998,  5731, 95205, 104912, 17020 ],
                                [  728, 10316, 55013, 32803, 12281, 15100,  16645,   255 ] ];

    let bishop_deltas: [i8; 4] = [7,9,9,7];
    let rook_deltas: [i8; 4] = [8,1,-8,1];

    let mut occupancy: [u64; 4096] = [0; 4096];
    let mut reference: [u64; 4096] = [0; 4096];
    let mut edges: u64 = 0;
    let mut age: [i32; 4096] =  [0; 4096];
    let mut current: i32 = 0;
    let mut size: usize = 0;

    for s in 0..64 {
        // ((Rank1BB | Rank8BB) & ~rank_bb(s)) | ((FileABB | FileHBB) & ~file_bb(s));
        edges = ((RANK_1 | RANK_8) & !rank_bb(s)) | ((FILE_A | FILE_B) & !file_bb(s));

        masks[s as usize] = sliding_attack(deltas, s, 0) & !edges;
        shifts[s as usize] = (64 - popcount64(masks[s as usize])) as u64;
        let mut b = 0;
        size = 0;

        loop {
            occupancy[size] = b;
            reference[size] = sliding_attack(deltas, s, b);
            size += 1;
            b = (b - masks[s as usize]) * masks[s as usize];
            if b == 0 {
                break;
            }
        }

        if s < 63 {
            unsafe {
                attacks[s as usize + 1] = std::mem::transmute::<*u64, u64>(1.0);
                    attacks[s as usize] + size as u64;

            }
//            attacks[s as usize + 1] = attacks[s as usize] + size as u64;

        }

        let mut rng = PRNG::init(seeds[1][rank_of(s) as usize]);

        'outer: loop {
            'first_in: loop {
                magics[s as usize] = rng.sparse_rand();
                if popcount64((magics[s as usize] * masks[s as usize]) >> 56) < 6 {
                    break 'first_in;
                }
            }
            // magic_index return unsigned(((occupied & Masks[s]) * Magics[s]) >> Shifts[s]);
            current += 1;
            let mut i: usize = 0;
            'secon_in: while i < size {
                let index: usize = (((occupancy[i as usize] & masks[s as usize]) * magics[s as usize]) >> shifts[s as usize]) as usize;
                if age[index] < current {
                    age[index] = current;
                    attacks[s as usize][index] = reference[i];
                } else if attacks[s as usize][index as usize] != reference[i] {
                    break 'secon_in;
                }
            }
            if i < size {
                break 'outer;
            }
        }
    }
}

// https://bluss.github.io/rust-ndarray/master/ndarray/struct.ArrayBase.html

struct PRNG {
    seed: u64
}

impl PRNG {
    pub fn init(s: u64) -> PRNG {
        assert_ne!(s,0);
        PRNG {seed: s}
    }

    pub fn rand(&mut self) -> u64 {
        self.rand_change()
    }

    pub fn sparse_rand(&mut self) -> u64 {
        let mut s = self.rand_change();
        s ^= self.rand_change();
        s ^= self.rand_change();
        s
    }

    fn rand_change(&mut self) -> u64 {
        self.seed ^= self.seed >> 12;
        self.seed ^= self.seed << 25;
        self.seed ^= self.seed >> 27;

        self.seed * 2685821657736338717
    }
}

fn sliding_attack(deltas: [u64; 4], square: u64, occupied: u64) -> u64 {
    let mut attack: u64 = 0;

    for i in 0..4 {
        let mut s: u64 = square + deltas[i];
        while is_ok(s) &&  distance(s, s - deltas[i]) == 1 {

            if occupied & s == 0 { break;}
            s += deltas[i];
        }
    }
    attack
}

pub fn gen_rook_masks() {
    let mut arr_masks: [u64; 64] = [0; 64];
    let mut shifts: [u8; 64] = [0; 64];

    let mut bit_ref: usize = 0;
    while bit_ref < 64 {
        let mut mask: u64 = 0;
        let mut i = bit_ref + 8;
        while i < 56 {
            mask |= (1 as u64) << (i as u8);
            i += 8;
        }
        if bit_ref > 7 {
            let mut i = bit_ref - 8;
            while i > 7 {
                mask |= (1 as u64) << (i as u8);
                i -= 8;
            }
        }
        let mut i = bit_ref + 1;
        while i % 8 != 0 && i <= 63 {
            mask |= (1 as u64) << (i as u8);
            i += 1;
        }
        if bit_ref > 0  {
            let mut i = bit_ref - 1;
            while i % 8 != 0 && i >= 0 {
                mask |= (1 as u64) << (i as u8);
                i -= 1;
            }
        }
        arr_masks[bit_ref] = mask;
        format_bits(format!("{:b}",mask));
        bit_ref += 1;
    }
}

pub fn gen_bishop_masks() {
    let mut arr_masks: [u64; 64] = [0; 64];
    let mut shifts: [u8; 64] = [0; 64];

    let mut bitRef: i32 = 0;
    while bitRef < 64 {
        let mut mask: u64 = 0;

        let mut i = bitRef + 9;
        while i < 56 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i += 9;
        }
        let mut i = bitRef - 9;
        while i > 7 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i -= 9;
        }
        let mut i = bitRef + 7;
        while i < 56 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i += 7;
        }

        let mut i = bitRef - 7;
        while i > 7 && i % 8 != 0 && i % 8 != 7 {
            mask |= (1 as u64) << (i as u8);
            i -= 7;
        }
        format_bits(format!("{:b}",mask));
        arr_masks[bitRef as usize] = mask;
        bitRef += 1;
    }
}

pub fn format_bits(bits: String) {
    let x = 64 - bits.len();
    let mut i = 0;
    while i < x {
        print!("0");
        i += 1;
    }
    println!("{}",bits);
}

#[test]
fn test_king_mask_gen() {
    let arr = gen_king_moves().to_vec();
    let sum = arr.iter().fold(0 as  u64,|a, &b| a + (bit_twiddles::popcount64(b) as u64));
    assert_eq!(sum, (3*4) + (5 * 6 * 4) + (8 * 6 * 6));
}

#[test]
fn test_knight_mask_gen() {
    let arr = gen_knight_moves().to_vec();
    let sum = arr.iter().fold(0 as  u64,|a, &b| a + (bit_twiddles::popcount64(b) as u64));
    assert_eq!(sum, (2 * 4) + (4 * 4) + (3 * 2 * 4) + (4 * 4 * 4) + (6 * 4 * 4) + (8 * 4 * 4));
}
<|endoftext|>


<commit_before>extern crate cc;

mod build_linux;
mod build_windows;
mod build_macos;

use std::env;

fn main() {
    if env::var("TARGET").unwrap().contains("windows") {
        build_windows::build_windows();
    } else if env::var("TARGET").unwrap().contains("linux") {
        build_linux::build_linux();
    } else if env::var("TARGET").unwrap().contains("mac") {
        build_macos::build_macos();
    } else {
        panic!("Unsupported platform!");
    }

}
<commit_msg>WIP macos build<commit_after>extern crate cc;

mod build_linux;
mod build_windows;
mod build_macos;

use std::env;

fn main() {
    if env::var("TARGET").unwrap().contains("windows") {
        build_windows::build_windows();
    } else if env::var("TARGET").unwrap().contains("linux") {
        build_linux::build_linux();
    } else if env::var("TARGET").unwrap().contains("apple") {
        build_macos::build_macos();
    } else {
        panic!("Unsupported platform!");
    }

}
<|endoftext|>