<commit_before>use std::path::PathBuf;

use clap::{Args, Subcommand};
use xshell::pushd;

use crate::{cmd, Metadata, Result};

mod spec_links;

use spec_links::check_spec_links;

const MSRV: &str = "1.55";
const NIGHTLY: &str = "nightly";

#[derive(Args)]
pub struct CiArgs {
    #[clap(subcommand)]
    pub cmd: Option<CiCmd>,
}

#[derive(Subcommand)]
pub enum CiCmd {
    /// Check crates compile with the MSRV
    Msrv,
    /// Check all crates with all features (msrv)
    MsrvAll,
    /// Check ruma-client with default features (msrv)
    MsrvClient,
    /// Check ruma crate with default features (msrv)
    MsrvRuma,
    /// Check ruma-identifiers with `ruma_identifiers_storage="Box"`
    MsrvOwnedIdBox,
    /// Check ruma-identifiers with `ruma_identifiers_storage="Arc"`
    MsrvOwnedIdArc,
    /// Run all the tasks that use the stable version
    Stable,
    /// Check all crates with all features (stable)
    StableAll,
    /// Check ruma-client without default features (stable)
    StableClient,
    /// Check ruma-common with only the required features (stable)
    StableCommon,
    /// Run all tests with almost all features (stable)
    TestAll,
    /// Run doc tests with almost all features (stable)
    TestDoc,
    /// Test ruma-common with the compat feature (stable)
    TestCommon,
    /// Run all the tasks that use the nightly version
    Nightly,
    /// Check formatting (nightly)
    Fmt,
    /// Check ruma crate with `full` features (nightly)
    NightlyFull,
    /// Lint default features with clippy (nightly)
    ClippyDefault,
    /// Lint almost all features with clippy (nightly)
    ClippyAll,
    /// Run all lints that don't need compilation
    Lint,
    /// Check sorting of dependencies (lint)
    Dependencies,
    /// Check spec links point to a recent version (lint)
    SpecLinks,
    /// Check typos
    Typos,
}

/// Task to run CI tests.
pub struct CiTask {
    /// Which command to run.
    cmd: Option<CiCmd>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(cmd: Option<CiCmd>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { cmd, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.cmd {
            Some(CiCmd::Msrv) => self.msrv()?,
            Some(CiCmd::MsrvAll) => self.msrv_all()?,
            Some(CiCmd::MsrvClient) => self.msrv_client()?,
            Some(CiCmd::MsrvRuma) => self.msrv_ruma()?,
            Some(CiCmd::MsrvOwnedIdBox) => self.msrv_owned_id_box()?,
            Some(CiCmd::MsrvOwnedIdArc) => self.msrv_owned_id_arc()?,
            Some(CiCmd::Stable) => self.stable()?,
            Some(CiCmd::StableAll) => self.stable_all()?,
            Some(CiCmd::StableClient) => self.stable_client()?,
            Some(CiCmd::StableCommon) => self.stable_common()?,
            Some(CiCmd::TestAll) => self.test_all()?,
            Some(CiCmd::TestDoc) => self.test_doc()?,
            Some(CiCmd::TestCommon) => self.test_common()?,
            Some(CiCmd::Nightly) => self.nightly()?,
            Some(CiCmd::Fmt) => self.fmt()?,
            Some(CiCmd::NightlyFull) => self.nightly_full()?,
            Some(CiCmd::ClippyDefault) => self.clippy_default()?,
            Some(CiCmd::ClippyAll) => self.clippy_all()?,
            Some(CiCmd::Lint) => self.lint()?,
            Some(CiCmd::Dependencies) => self.dependencies()?,
            Some(CiCmd::SpecLinks) => check_spec_links(&self.project_root.join("crates"))?,
            Some(CiCmd::Typos) => self.typos()?,
            None => {
                self.msrv()
                    .and(self.stable())
                    .and(self.nightly())
                    .and(self.lint())
                    .and(self.typos())?;
            }
        }

        Ok(())
    }

    /// Check that the crates compile with the MSRV.
    fn msrv(&self) -> Result<()> {
        self.msrv_all()?;
        self.msrv_client()?;
        self.msrv_ruma()
    }

    /// Check all crates with all features with the MSRV, except:
    /// * ruma (would pull in ruma-signatures)
    /// * ruma-client (tested only with client-api feature due to most / all optional HTTP client
    ///   deps having less strict MSRV)
    /// * ruma-signatures (MSRV exception)
    /// * xtask (no real reason to enforce an MSRV for it)
    fn msrv_all(&self) -> Result<()> {
        cmd!(
            "rustup run {MSRV} cargo check --workspace --all-features
                --exclude ruma
                --exclude ruma-client
                --exclude ruma-signatures
                --exclude xtask"
        )
        .run()
        .map_err(Into::into)
    }

    /// Check ruma-client with default features with the MSRV.
    fn msrv_client(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma-client --features client-api")
            .run()
            .map_err(Into::into)
    }

    /// Check ruma crate with default features with the MSRV.
    fn msrv_ruma(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma").run().map_err(Into::into)
    }

    /// Run all the tasks that use the stable version.
    fn stable(&self) -> Result<()> {
        self.stable_all()?;
        self.stable_client()?;
        self.stable_common()?;
        self.test_all()?;
        self.test_doc()?;
        self.test_common()
    }

    /// Check all crates with all features with the stable version.
    fn stable_all(&self) -> Result<()> {
        cmd!("rustup run stable cargo check --workspace --all-features").run().map_err(Into::into)
    }

    /// Check ruma-client without default features with the stable version.
    fn stable_client(&self) -> Result<()> {
        cmd!("rustup run stable cargo check -p ruma-client --no-default-features")
            .run()
            .map_err(Into::into)
    }

    /// Check ruma-common with onjy the required features with the stable version.
    fn stable_common(&self) -> Result<()> {
        cmd!("rustup run stable cargo check -p ruma-common --no-default-features --features client,server").run().map_err(Into::into)
    }

    /// Run tests on all crates with almost all features with the stable version.
    fn test_all(&self) -> Result<()> {
        cmd!("rustup run stable cargo test --tests --features __ci").run().map_err(Into::into)
    }

    /// Run doctests on all crates with almost all features with the stable version.
    fn test_doc(&self) -> Result<()> {
        cmd!("rustup run stable cargo test --doc --features __ci").run().map_err(Into::into)
    }

    /// Test ruma-common with the compat feature with the stable version.
    fn test_common(&self) -> Result<()> {
        cmd!("rustup run stable cargo test -p ruma-common --features events --features compat compat").run().map_err(Into::into)
    }

    /// Run all the tasks that use the nightly version.
    fn nightly(&self) -> Result<()> {
        self.fmt()?;
        self.nightly_full()?;
        self.clippy_default()?;
        self.clippy_all()
    }

    /// Check the formatting with the nightly version.
    fn fmt(&self) -> Result<()> {
        cmd!("rustup run {NIGHTLY} cargo fmt -- --check").run().map_err(Into::into)
    }

    /// Check ruma crate with full feature with the nightly version.
    fn nightly_full(&self) -> Result<()> {
        cmd!("rustup run {NIGHTLY} cargo check -p ruma --features full").run().map_err(Into::into)
    }

    /// Check ruma-common with `ruma_identifiers_storage="Box"`
    fn msrv_owned_id_box(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma-common")
            .env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Box\"")
            .run()
            .map_err(Into::into)
    }

    /// Check ruma-common with `ruma_identifiers_storage="Arc"`
    fn msrv_owned_id_arc(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma-common")
            .env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Arc\"")
            .run()
            .map_err(Into::into)
    }

    /// Lint default features with clippy with the nightly version.
    fn clippy_default(&self) -> Result<()> {
        cmd!(
            "
            rustup run {NIGHTLY} cargo clippy
                --workspace --all-targets --features=full -- -D warnings
            "
        )
        .run()
        .map_err(Into::into)
    }

    /// Lint almost all features with clippy with the nightly version.
    fn clippy_all(&self) -> Result<()> {
        cmd!(
            "
            rustup run {NIGHTLY} cargo clippy
                --workspace --all-targets --features=__ci,compat -- -D warnings
            "
        )
        .run()
        .map_err(Into::into)
    }

    /// Run all lints that don't need compilation.
    fn lint(&self) -> Result<()> {
        // Check dependencies being sorted
        let dependencies_res = self.dependencies();
        // Check that all links point to the same version of the spec
        let spec_links_res = check_spec_links(&self.project_root.join("crates"));

        dependencies_res.and(spec_links_res)
    }

    /// Check the sorting of dependencies with the nightly version.
    fn dependencies(&self) -> Result<()> {
        if cmd!("cargo sort --version").run().is_err() {
            return Err(
                "Could not find cargo-sort. Install it by running `cargo install cargo-sort`"
                    .into(),
            );
        }
        cmd!(
            "
            rustup run {NIGHTLY} cargo sort
                --workspace --grouped --check
                --order package,lib,features,dependencies,dev-dependencies,build-dependencies
            "
        )
        .run()
        .map_err(Into::into)
    }

    /// Check the typos.
    fn typos(&self) -> Result<()> {
        if cmd!("typos --version").run().is_err() {
            return Err(
                "Could not find typos. Install it by running `cargo install typos-cli`".into()
            );
        }
        cmd!("typos").run().map_err(Into::into)
    }
}
<commit_msg>Update cargo sort table order<commit_after>use std::path::PathBuf;

use clap::{Args, Subcommand};
use xshell::pushd;

use crate::{cmd, Metadata, Result};

mod spec_links;

use spec_links::check_spec_links;

const MSRV: &str = "1.55";
const NIGHTLY: &str = "nightly";

#[derive(Args)]
pub struct CiArgs {
    #[clap(subcommand)]
    pub cmd: Option<CiCmd>,
}

#[derive(Subcommand)]
pub enum CiCmd {
    /// Check crates compile with the MSRV
    Msrv,
    /// Check all crates with all features (msrv)
    MsrvAll,
    /// Check ruma-client with default features (msrv)
    MsrvClient,
    /// Check ruma crate with default features (msrv)
    MsrvRuma,
    /// Check ruma-identifiers with `ruma_identifiers_storage="Box"`
    MsrvOwnedIdBox,
    /// Check ruma-identifiers with `ruma_identifiers_storage="Arc"`
    MsrvOwnedIdArc,
    /// Run all the tasks that use the stable version
    Stable,
    /// Check all crates with all features (stable)
    StableAll,
    /// Check ruma-client without default features (stable)
    StableClient,
    /// Check ruma-common with only the required features (stable)
    StableCommon,
    /// Run all tests with almost all features (stable)
    TestAll,
    /// Run doc tests with almost all features (stable)
    TestDoc,
    /// Test ruma-common with the compat feature (stable)
    TestCommon,
    /// Run all the tasks that use the nightly version
    Nightly,
    /// Check formatting (nightly)
    Fmt,
    /// Check ruma crate with `full` features (nightly)
    NightlyFull,
    /// Lint default features with clippy (nightly)
    ClippyDefault,
    /// Lint almost all features with clippy (nightly)
    ClippyAll,
    /// Run all lints that don't need compilation
    Lint,
    /// Check sorting of dependencies (lint)
    Dependencies,
    /// Check spec links point to a recent version (lint)
    SpecLinks,
    /// Check typos
    Typos,
}

/// Task to run CI tests.
pub struct CiTask {
    /// Which command to run.
    cmd: Option<CiCmd>,

    /// The root of the workspace.
    project_root: PathBuf,
}

impl CiTask {
    pub(crate) fn new(cmd: Option<CiCmd>) -> Result<Self> {
        let project_root = Metadata::load()?.workspace_root;
        Ok(Self { cmd, project_root })
    }

    pub(crate) fn run(self) -> Result<()> {
        let _p = pushd(&self.project_root)?;

        match self.cmd {
            Some(CiCmd::Msrv) => self.msrv()?,
            Some(CiCmd::MsrvAll) => self.msrv_all()?,
            Some(CiCmd::MsrvClient) => self.msrv_client()?,
            Some(CiCmd::MsrvRuma) => self.msrv_ruma()?,
            Some(CiCmd::MsrvOwnedIdBox) => self.msrv_owned_id_box()?,
            Some(CiCmd::MsrvOwnedIdArc) => self.msrv_owned_id_arc()?,
            Some(CiCmd::Stable) => self.stable()?,
            Some(CiCmd::StableAll) => self.stable_all()?,
            Some(CiCmd::StableClient) => self.stable_client()?,
            Some(CiCmd::StableCommon) => self.stable_common()?,
            Some(CiCmd::TestAll) => self.test_all()?,
            Some(CiCmd::TestDoc) => self.test_doc()?,
            Some(CiCmd::TestCommon) => self.test_common()?,
            Some(CiCmd::Nightly) => self.nightly()?,
            Some(CiCmd::Fmt) => self.fmt()?,
            Some(CiCmd::NightlyFull) => self.nightly_full()?,
            Some(CiCmd::ClippyDefault) => self.clippy_default()?,
            Some(CiCmd::ClippyAll) => self.clippy_all()?,
            Some(CiCmd::Lint) => self.lint()?,
            Some(CiCmd::Dependencies) => self.dependencies()?,
            Some(CiCmd::SpecLinks) => check_spec_links(&self.project_root.join("crates"))?,
            Some(CiCmd::Typos) => self.typos()?,
            None => {
                self.msrv()
                    .and(self.stable())
                    .and(self.nightly())
                    .and(self.lint())
                    .and(self.typos())?;
            }
        }

        Ok(())
    }

    /// Check that the crates compile with the MSRV.
    fn msrv(&self) -> Result<()> {
        self.msrv_all()?;
        self.msrv_client()?;
        self.msrv_ruma()
    }

    /// Check all crates with all features with the MSRV, except:
    /// * ruma (would pull in ruma-signatures)
    /// * ruma-client (tested only with client-api feature due to most / all optional HTTP client
    ///   deps having less strict MSRV)
    /// * ruma-signatures (MSRV exception)
    /// * xtask (no real reason to enforce an MSRV for it)
    fn msrv_all(&self) -> Result<()> {
        cmd!(
            "rustup run {MSRV} cargo check --workspace --all-features
                --exclude ruma
                --exclude ruma-client
                --exclude ruma-signatures
                --exclude xtask"
        )
        .run()
        .map_err(Into::into)
    }

    /// Check ruma-client with default features with the MSRV.
    fn msrv_client(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma-client --features client-api")
            .run()
            .map_err(Into::into)
    }

    /// Check ruma crate with default features with the MSRV.
    fn msrv_ruma(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma").run().map_err(Into::into)
    }

    /// Run all the tasks that use the stable version.
    fn stable(&self) -> Result<()> {
        self.stable_all()?;
        self.stable_client()?;
        self.stable_common()?;
        self.test_all()?;
        self.test_doc()?;
        self.test_common()
    }

    /// Check all crates with all features with the stable version.
    fn stable_all(&self) -> Result<()> {
        cmd!("rustup run stable cargo check --workspace --all-features").run().map_err(Into::into)
    }

    /// Check ruma-client without default features with the stable version.
    fn stable_client(&self) -> Result<()> {
        cmd!("rustup run stable cargo check -p ruma-client --no-default-features")
            .run()
            .map_err(Into::into)
    }

    /// Check ruma-common with onjy the required features with the stable version.
    fn stable_common(&self) -> Result<()> {
        cmd!("rustup run stable cargo check -p ruma-common --no-default-features --features client,server").run().map_err(Into::into)
    }

    /// Run tests on all crates with almost all features with the stable version.
    fn test_all(&self) -> Result<()> {
        cmd!("rustup run stable cargo test --tests --features __ci").run().map_err(Into::into)
    }

    /// Run doctests on all crates with almost all features with the stable version.
    fn test_doc(&self) -> Result<()> {
        cmd!("rustup run stable cargo test --doc --features __ci").run().map_err(Into::into)
    }

    /// Test ruma-common with the compat feature with the stable version.
    fn test_common(&self) -> Result<()> {
        cmd!("rustup run stable cargo test -p ruma-common --features events --features compat compat").run().map_err(Into::into)
    }

    /// Run all the tasks that use the nightly version.
    fn nightly(&self) -> Result<()> {
        self.fmt()?;
        self.nightly_full()?;
        self.clippy_default()?;
        self.clippy_all()
    }

    /// Check the formatting with the nightly version.
    fn fmt(&self) -> Result<()> {
        cmd!("rustup run {NIGHTLY} cargo fmt -- --check").run().map_err(Into::into)
    }

    /// Check ruma crate with full feature with the nightly version.
    fn nightly_full(&self) -> Result<()> {
        cmd!("rustup run {NIGHTLY} cargo check -p ruma --features full").run().map_err(Into::into)
    }

    /// Check ruma-common with `ruma_identifiers_storage="Box"`
    fn msrv_owned_id_box(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma-common")
            .env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Box\"")
            .run()
            .map_err(Into::into)
    }

    /// Check ruma-common with `ruma_identifiers_storage="Arc"`
    fn msrv_owned_id_arc(&self) -> Result<()> {
        cmd!("rustup run {MSRV} cargo check -p ruma-common")
            .env("RUSTFLAGS", "--cfg=ruma_identifiers_storage=\"Arc\"")
            .run()
            .map_err(Into::into)
    }

    /// Lint default features with clippy with the nightly version.
    fn clippy_default(&self) -> Result<()> {
        cmd!(
            "
            rustup run {NIGHTLY} cargo clippy
                --workspace --all-targets --features=full -- -D warnings
            "
        )
        .run()
        .map_err(Into::into)
    }

    /// Lint almost all features with clippy with the nightly version.
    fn clippy_all(&self) -> Result<()> {
        cmd!(
            "
            rustup run {NIGHTLY} cargo clippy
                --workspace --all-targets --features=__ci,compat -- -D warnings
            "
        )
        .run()
        .map_err(Into::into)
    }

    /// Run all lints that don't need compilation.
    fn lint(&self) -> Result<()> {
        // Check dependencies being sorted
        let dependencies_res = self.dependencies();
        // Check that all links point to the same version of the spec
        let spec_links_res = check_spec_links(&self.project_root.join("crates"));

        dependencies_res.and(spec_links_res)
    }

    /// Check the sorting of dependencies with the nightly version.
    fn dependencies(&self) -> Result<()> {
        if cmd!("cargo sort --version").run().is_err() {
            return Err(
                "Could not find cargo-sort. Install it by running `cargo install cargo-sort`"
                    .into(),
            );
        }
        cmd!(
            "
            rustup run {NIGHTLY} cargo sort
                --workspace --grouped --check
                --order package,lib,features,dependencies,target,dev-dependencies,build-dependencies
            "
        )
        .run()
        .map_err(Into::into)
    }

    /// Check the typos.
    fn typos(&self) -> Result<()> {
        if cmd!("typos --version").run().is_err() {
            return Err(
                "Could not find typos. Install it by running `cargo install typos-cli`".into()
            );
        }
        cmd!("typos").run().map_err(Into::into)
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::fmt;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::result::Result;
use std::convert::From;
use rand;
use rand::Rng;
use grid::Grid;
use item::{Item};
use point::{Point};
use tile::{Tile};

// A dungeon level.
pub struct Level {
    depth: u8,
    tiles: Grid<Tile>,
    items: HashMap<Point, Item>,
    visible: HashSet<Point>,
}

pub type Dungeon = [Level; 256];

pub enum MapError {
    ShapeError(usize),    // funny map shape at given line
    TileError(usize, u8), // bad tile (u8) on given map (usize)
    StairError(usize),    // not enough stairs on given map
    IoError(io::Error)
}

impl fmt::Display for MapError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MapError::ShapeError(line) =>
                write!(f, "map error: misshapen map at line {}", line),
            MapError::TileError(whichmap, tile) =>
                write!(f, "map error: unknown tile '{}' on map {}",
                    tile as char, whichmap),
            MapError::StairError(whichmap) =>
                write!(f, "map error: not enough stairs on map {}", whichmap),
            MapError::IoError(ref e) => e.fmt(f)
        }
    }
}

impl From<io::Error> for MapError {
    fn from(e: io::Error) -> Self {
        MapError::IoError(e)
    }
}

// TODO: make early levels easy, handle special case for level 255
pub fn build() -> Result<Vec<Grid<Tile>>, MapError> {
    let mut schemes = read_maps()?;

    // until we have 255 distinct levels, make do with duplicates
    let distinct_schemes = schemes.len();
    while schemes.len() < 255 {
        let which = rand::thread_rng().gen_range(0, distinct_schemes);
        let duplicate = schemes[which].clone();
        schemes.push(duplicate)
    }

    let mut maps: Vec<Grid<Tile>> = Vec::with_capacity(255);
    for (whichmap, scheme) in schemes.iter().enumerate() {
        maps.push(build_map(whichmap, scheme)?)
    }

    rand::thread_rng().shuffle(&mut maps[..]);

    Ok(maps)
}

type Lines<'a> = &'a mut Iterator<Item=io::Result<String>>;

fn read_maps() -> Result<Vec<Grid<u8>>, MapError> {
    let file = File::open("data/maps.txt")?;
    let reader = BufReader::new(file);
    let mut lines = reader.lines();
    let mut maps: Vec<Grid<u8>> = Vec::with_capacity(255);

    let mut linecount: usize = 1;
    loop {
        if lines.next().is_none() {
            return Ok(maps)
        }
        linecount += 1;
        maps.push(read_map(&mut linecount, &mut lines)?);
    }
}

fn read_map(linecount: &mut usize, lines: Lines) -> Result<Grid<u8>, MapError> {
    let mut grid = Grid::empty();
    for _ in 0..13 {
        match lines.next() {
            Some(Ok(ref row)) if row.len() == 19 =>
                grid.grid.extend(row.bytes()),
            Some(Err(e)) => return Err(MapError::IoError(e)),
            _ => return Err(MapError::ShapeError(*linecount))
        }
        *linecount = *linecount + 1
    }

    Ok(grid)
}

fn build_map(whichmap: usize, scheme: &Grid<u8>) -> Result<Grid<Tile>, MapError> {
    let mut map = Grid::empty();

    // preliminary pass: figure out where to place stairs
    let stairtotal = scheme.grid.iter().filter(|&&t| t == b'<').count();
    if stairtotal < 2 {
        return Err(MapError::StairError(whichmap))
    }
    let upstairs = rand::thread_rng().gen_range(0, stairtotal);
    let mut downstairs = upstairs;
    while downstairs == upstairs {
        downstairs = rand::thread_rng().gen_range(0, stairtotal)
    }

    // a HashMap to keep track of which tile (floor or wall) to use for
    // each letter A-Z in the map scheme
    let mut tilechoices: HashMap<u8, Tile> = HashMap::new();

    let mut staircount = 0;

    for &srctile in scheme.grid.iter() {
        map.grid.push(match srctile {
            b'.' => Tile::Floor,
            b'#' => Tile::Wall,
            b'+' => Tile::Door,
            b'<' => {
                let tile = if staircount == upstairs {
                    Tile::StairsUp
                } else if staircount == downstairs {
                    Tile::StairsDown
                } else {
                    Tile::Floor
                };
                staircount += 1;
                tile
            }
            b'A' ... b'Z' =>
                *tilechoices.entry(srctile).or_insert_with(||
                    if rand::thread_rng().gen() {
                        Tile::Wall
                    } else {
                        Tile::Floor
                    }
                ),
            _ => return Err(MapError::TileError(whichmap, srctile))
        })
    }

    Ok(map)
}
<commit_msg>add lowercase letter features to maps<commit_after>use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::fmt;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::result::Result;
use std::convert::From;
use std::ascii::AsciiExt;
use rand;
use rand::Rng;
use grid::Grid;
use item::{Item};
use point::{Point};
use tile::{Tile};

// A dungeon level.
pub struct Level {
    depth: u8,
    tiles: Grid<Tile>,
    items: HashMap<Point, Item>,
    visible: HashSet<Point>,
}

pub type Dungeon = [Level; 256];

pub enum MapError {
    ShapeError(usize),    // funny map shape at given line
    TileError(usize, u8), // bad tile (u8) on given map (usize)
    StairError(usize),    // not enough stairs on given map
    IoError(io::Error)
}

impl fmt::Display for MapError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MapError::ShapeError(line) =>
                write!(f, "map error: misshapen map at line {}", line),
            MapError::TileError(whichmap, tile) =>
                write!(f, "map error: unknown tile '{}' on map {}",
                    tile as char, whichmap),
            MapError::StairError(whichmap) =>
                write!(f, "map error: not enough stairs on map {}", whichmap),
            MapError::IoError(ref e) => e.fmt(f)
        }
    }
}

impl From<io::Error> for MapError {
    fn from(e: io::Error) -> Self {
        MapError::IoError(e)
    }
}

// TODO: make early levels easy, handle special case for level 255
pub fn build() -> Result<Vec<Grid<Tile>>, MapError> {
    let mut schemes = read_maps()?;

    // until we have 255 distinct levels, make do with duplicates
    let distinct_schemes = schemes.len();
    while schemes.len() < 255 {
        let which = rand::thread_rng().gen_range(0, distinct_schemes);
        let duplicate = schemes[which].clone();
        schemes.push(duplicate)
    }

    let mut maps: Vec<Grid<Tile>> = Vec::with_capacity(255);
    for (whichmap, scheme) in schemes.iter().enumerate() {
        maps.push(build_map(whichmap, scheme)?)
    }

    rand::thread_rng().shuffle(&mut maps[..]);

    Ok(maps)
}

type Lines<'a> = &'a mut Iterator<Item=io::Result<String>>;

fn read_maps() -> Result<Vec<Grid<u8>>, MapError> {
    let file = File::open("data/maps.txt")?;
    let reader = BufReader::new(file);
    let mut lines = reader.lines();
    let mut maps: Vec<Grid<u8>> = Vec::with_capacity(255);

    let mut linecount: usize = 1;
    loop {
        if lines.next().is_none() {
            return Ok(maps)
        }
        linecount += 1;
        maps.push(read_map(&mut linecount, &mut lines)?);
    }
}

fn read_map(linecount: &mut usize, lines: Lines) -> Result<Grid<u8>, MapError> {
    let mut grid = Grid::empty();
    for _ in 0..13 {
        match lines.next() {
            Some(Ok(ref row)) if row.len() == 19 =>
                grid.grid.extend(row.bytes()),
            Some(Err(e)) => return Err(MapError::IoError(e)),
            _ => return Err(MapError::ShapeError(*linecount))
        }
        *linecount = *linecount + 1
    }

    Ok(grid)
}

fn build_map(whichmap: usize, scheme: &Grid<u8>) -> Result<Grid<Tile>, MapError> {
    let mut map = Grid::empty();

    // preliminary pass: figure out where to place stairs
    let stairtotal = scheme.grid.iter().filter(|&&t| t == b'<').count();
    if stairtotal < 2 {
        return Err(MapError::StairError(whichmap))
    }
    let upstairs = rand::thread_rng().gen_range(0, stairtotal);
    let mut downstairs = upstairs;
    while downstairs == upstairs {
        downstairs = rand::thread_rng().gen_range(0, stairtotal)
    }

    // a HashMap to keep track of which tile (floor or wall) to use for
    // each letter A-Z in the map scheme (and the inverse for a-z)
    let mut tilechoices: HashMap<u8, bool> = HashMap::new();

    let mut staircount = 0;

    for &srctile in scheme.grid.iter() {
        map.grid.push(match srctile {
            b'.' => Tile::Floor,
            b'#' => Tile::Wall,
            b'+' => Tile::Door,
            b'<' => {
                let tile = if staircount == upstairs {
                    Tile::StairsUp
                } else if staircount == downstairs {
                    Tile::StairsDown
                } else {
                    Tile::Floor
                };
                staircount += 1;
                tile
            }
            b'A' ... b'Z' | b'a' ... b'z' => {
                let normalized = srctile.to_ascii_uppercase();
                let selection = *tilechoices.entry(normalized).or_insert_with(||
                    rand::thread_rng().gen() );
                // flip selection for lowercase letters
                // TODO: use srctile.is_ascii_uppercase()
                // once ascii_ctype is stable
                if selection == (srctile == normalized) {
                    Tile::Wall
                } else {
                    Tile::Floor
                }
            }
            _ => return Err(MapError::TileError(whichmap, srctile))
        })
    }

    Ok(map)
}
<|endoftext|>


<commit_before>// TODO: Move some of this stuff to a parser module

use super::*;
use redox::*;
use core::marker::Sized;

pub struct InstructionIterator<'a, I: 'a> {
    pub mode: &'a Mode,
    pub iter: &'a mut I,
}

impl<'a, I: Iterator<Item = EventOption>> Iterator for InstructionIterator<'a, I> {
    type Item = Inst;

    fn next(&mut self) -> Option<Inst> {
        let mut n = 0;

        let mut last = '\0';
        for e in self.iter {
            match e {
                EventOption::Key(k) if k.pressed => {
                    let c = k.character;
                    match *self.mode {
                        Mode::Primitive(_) => {
                            Inst(0, c);
                        },
                        Mode::Command(_) => {
                            n = match c {
                                '0' if n != 0 => n * 10,
                                '1'           => n * 10 + 1,
                                '2'           => n * 10 + 2,
                                '3'           => n * 10 + 3,
                                '4'           => n * 10 + 4,
                                '5'           => n * 10 + 5,
                                '6'           => n * 10 + 6,
                                '7'           => n * 10 + 7,
                                '8'           => n * 10 + 8,
                                '9'           => n * 10 + 9,
                                _             => {
                                    last = c;
                                    break;
                                },
                            }

                        }
                    }
                },
                _ => {},
            }
        }

        Some(Inst(if n == 0 { 1 } else { n }, last))
    }
}

pub trait ToInstructionIterator
          where Self: Sized {
    fn inst_iter<'a>(&'a mut self, mode: &'a Mode) -> InstructionIterator<'a, Self>;
}

impl<I> ToInstructionIterator for I
        where I: Iterator<Item = EventOption> + Sized {
    fn inst_iter<'a>(&'a mut self, mode: &'a Mode) -> InstructionIterator<'a, Self> {
        InstructionIterator {
            mode: mode,
            iter: self,
        }
    }
}
impl Editor {
    /// Execute a instruction
    pub fn exec<'a, I>(&mut self, inst: Inst, inp: &mut InstructionIterator<'a, I>) {

    }

}
<commit_msg>Fixed error for filesystem/apps/sodium/exec.rs<commit_after>// TODO: Move some of this stuff to a parser module

use super::*;
use redox::*;
use core::marker::Sized;

pub struct InstructionIterator<'a, I: 'a> {
    pub mode: &'a Mode,
    pub iter: &'a mut I,
}

impl<'a, I: Iterator<Item = EventOption>> Iterator for InstructionIterator<'a, I> {
    type Item = Inst;

    fn next(&mut self) -> Option<Inst> {
        let mut n = 0;

        let mut last = '\0';
        while let Some(EventOption::Key(k)) = self.iter.next() {
            if k.pressed {
                let c = k.character;
                match *self.mode {
                    Mode::Primitive(_) => {
                        Inst(0, c);
                    },
                    Mode::Command(_) => {
                        n = match c {
                            '0' if n != 0 => n * 10,
                            '1'           => n * 10 + 1,
                            '2'           => n * 10 + 2,
                            '3'           => n * 10 + 3,
                            '4'           => n * 10 + 4,
                            '5'           => n * 10 + 5,
                            '6'           => n * 10 + 6,
                            '7'           => n * 10 + 7,
                            '8'           => n * 10 + 8,
                            '9'           => n * 10 + 9,
                            _             => {
                                last = c;
                                break;
                            }
                        }
                    }
                }
            }
        }
        Some(Inst(if n == 0 { 1 } else { n }, last))
    }
}

pub trait ToInstructionIterator
          where Self: Sized {
    fn inst_iter<'a>(&'a mut self, mode: &'a Mode) -> InstructionIterator<'a, Self>;
}

impl<I> ToInstructionIterator for I
        where I: Iterator<Item = EventOption> + Sized {
    fn inst_iter<'a>(&'a mut self, mode: &'a Mode) -> InstructionIterator<'a, Self> {
        InstructionIterator {
            mode: mode,
            iter: self,
        }
    }
}
impl Editor {
    /// Execute a instruction
    pub fn exec<'a, I>(&mut self, inst: Inst, inp: &mut InstructionIterator<'a, I>) {

    }

}
<|endoftext|>


<commit_before>use std::io;
use std::ops::Sub;
use std::str::FromStr;
use std::cmp::Ordering;
use std::io::prelude::*;
use std::collections::HashMap;

pub fn main() {
    println!("Pipe the puzzle input to stdin");
    let mut p1_win = 0;
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let (h1, h2) = line.split_at(14);
        let h1: Hand = h1.parse().unwrap();
        let h2: Hand = h2.parse().unwrap();
        if h1 > h2 {
            p1_win += 1;
        }
    }
    println!("{}", p1_win);
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
enum Suit {
    Spades,
    Hearts,
    Diamonds,
    Clubs,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Copy, Hash)]
enum Rank {
    Value(isize),
    Jack,
    Queen,
    King,
    Ace,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
enum HandRank {
    HighCard(Rank),
    OnePair(Rank),
    TwoPairs(Rank, Rank),
    ThreeOfAKind(Rank),
    Straight(Rank),
    Flush(Rank),
    FullHouse(Rank),
    FourOfAKind(Rank),
    StraightFlush(Rank),
    RoyalFlush,
}

#[derive(Debug, Clone, PartialEq, Copy)]
struct Card {
    suit: Suit,
    rank: Rank,
}

#[derive(Debug, PartialEq)]
struct Hand {
    cards: Vec<Card>,
    rank: HandRank,
}

impl FromStr for Suit {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Suit, Self::Err> {
        match input {
            "S" => Ok(Suit::Spades),
            "H" => Ok(Suit::Hearts),
            "D" => Ok(Suit::Diamonds),
            "C" => Ok(Suit::Clubs),
            _ => Err("invalid suit"),
        }
    }
}

impl FromStr for Rank {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Rank, Self::Err> {
        match input {
            "A" => Ok(Rank::Ace),
            "K" => Ok(Rank::King),
            "Q" => Ok(Rank::Queen),
            "J" => Ok(Rank::Jack),
            "T" => Ok(Rank::Value(10)),
            "9" => Ok(Rank::Value(9)),
            "8" => Ok(Rank::Value(8)),
            "7" => Ok(Rank::Value(7)),
            "6" => Ok(Rank::Value(6)),
            "5" => Ok(Rank::Value(5)),
            "4" => Ok(Rank::Value(4)),
            "3" => Ok(Rank::Value(3)),
            "2" => Ok(Rank::Value(2)),
            _ => Err("invalid rank"),
        }
    }
}

impl FromStr for Card {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Card, Self::Err> {
        let input = input.trim();
        if input.len() != 2 {
            return Err("invalid card string length");
        }
        let (r, s) = input.split_at(1);
        let r = try!(r.parse::<Rank>());
        let s = try!(s.parse::<Suit>());
        Ok(Card { rank: r, suit: s })
    }
}

impl FromStr for Hand {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Hand, Self::Err> {
        let cards = input.split_whitespace()
                         .map(|c| c.parse::<Card>().unwrap())
                         .collect::<Vec<_>>();
        Hand::from(cards).ok_or("invalid hand")
    }
}

impl PartialOrd for Card {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.rank.partial_cmp(&other.rank)
    }
}

impl PartialOrd for Hand {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.rank == other.rank {
            for (c1, c2) in self.cards.iter().zip(other.cards.iter()).rev() {
                if c1.rank != c2.rank {
                    return c1.rank.partial_cmp(&c2.rank);
                }
            }
            return Some(Ordering::Equal)
        } else {
            self.rank.partial_cmp(&other.rank)
        }
    }
}

impl Hand {
    fn from(cards: Vec<Card>) -> Option<Hand> {
        if cards.len() != 5 {
            None
        } else {
            let mut cards = cards;
            cards.sort_by_key(|card| card.rank);
            let r = Hand::rank(&cards);
            Some(Hand {
                cards: cards,
                rank: r,
            })
        }
    }

    fn rank(cards: &Vec<Card>) -> HandRank {
        let first_suit = cards[0].suit;
        let highest_rank = cards[4].rank;
        let is_flush = cards.iter().all(|card| card.suit == first_suit);
        let is_straight = cards.windows(2).all(|pair| (pair[0] - pair[1]).abs() == 1);
        let mut multiples = HashMap::<Rank, u32>::new();
        for &card in cards.iter() {
            *multiples.entry(card.rank).or_insert(0) += 1;
        }
        let multiples = multiples;
        let has_n = |n| multiples.values().any(|&i| i == n);

        if highest_rank == Rank::Ace && is_flush && is_straight {
            HandRank::RoyalFlush
        } else if is_flush && is_straight {
            HandRank::StraightFlush(highest_rank)
        } else if is_flush {
            HandRank::Flush(highest_rank)
        } else if has_n(4) {
            let r = *multiples.iter().find(|&(_, &n)| n == 4).unwrap().0;
            HandRank::FourOfAKind(r)
        } else if has_n(3) && has_n(2) {
            HandRank::FullHouse(highest_rank)
        } else if is_flush {
            HandRank::Flush(highest_rank)
        } else if is_straight {
            HandRank::Straight(highest_rank)
        } else if has_n(3) {
            let r = *multiples.iter().find(|&(_, &n)| n == 3).unwrap().0;
            HandRank::ThreeOfAKind(r)
        } else if has_n(2) && multiples.len() == 3 {
            let ranks = multiples.iter()
                                 .filter(|&(_, &n)| n == 2)
                                 .map(|(&r, _)| r)
                                 .collect::<Vec<_>>();
            HandRank::TwoPairs(ranks[0], ranks[1])
        } else if has_n(2) {
            let r = *multiples.iter().find(|&(_, &n)| n == 2).unwrap().0;
            HandRank::OnePair(r)
        } else {
            HandRank::HighCard(highest_rank)
        }
    }
}

impl Sub for Card {
    type Output = isize;

    fn sub(self, _rhs: Card) -> isize {
        let value = |rank| match rank {
            Rank::Ace => 14,
            Rank::King => 13,
            Rank::Queen => 12,
            Rank::Jack => 11,
            Rank::Value(n) => n,
        };
        value(self.rank) - value(_rhs.rank)
    }
}
<commit_msg>remove unnecessary return<commit_after>use std::io;
use std::ops::Sub;
use std::str::FromStr;
use std::cmp::Ordering;
use std::io::prelude::*;
use std::collections::HashMap;

pub fn main() {
    println!("Pipe the puzzle input to stdin");
    let mut p1_win = 0;
    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let line = line.unwrap();
        let (h1, h2) = line.split_at(14);
        let h1: Hand = h1.parse().unwrap();
        let h2: Hand = h2.parse().unwrap();
        if h1 > h2 {
            p1_win += 1;
        }
    }
    println!("{}", p1_win);
}

#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
enum Suit {
    Spades,
    Hearts,
    Diamonds,
    Clubs,
}

#[derive(Debug, Clone, PartialEq, PartialOrd, Ord, Eq, Copy, Hash)]
enum Rank {
    Value(isize),
    Jack,
    Queen,
    King,
    Ace,
}

#[derive(Debug, Clone, PartialEq, PartialOrd)]
enum HandRank {
    HighCard(Rank),
    OnePair(Rank),
    TwoPairs(Rank, Rank),
    ThreeOfAKind(Rank),
    Straight(Rank),
    Flush(Rank),
    FullHouse(Rank),
    FourOfAKind(Rank),
    StraightFlush(Rank),
    RoyalFlush,
}

#[derive(Debug, Clone, PartialEq, Copy)]
struct Card {
    suit: Suit,
    rank: Rank,
}

#[derive(Debug, PartialEq)]
struct Hand {
    cards: Vec<Card>,
    rank: HandRank,
}

impl FromStr for Suit {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Suit, Self::Err> {
        match input {
            "S" => Ok(Suit::Spades),
            "H" => Ok(Suit::Hearts),
            "D" => Ok(Suit::Diamonds),
            "C" => Ok(Suit::Clubs),
            _ => Err("invalid suit"),
        }
    }
}

impl FromStr for Rank {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Rank, Self::Err> {
        match input {
            "A" => Ok(Rank::Ace),
            "K" => Ok(Rank::King),
            "Q" => Ok(Rank::Queen),
            "J" => Ok(Rank::Jack),
            "T" => Ok(Rank::Value(10)),
            "9" => Ok(Rank::Value(9)),
            "8" => Ok(Rank::Value(8)),
            "7" => Ok(Rank::Value(7)),
            "6" => Ok(Rank::Value(6)),
            "5" => Ok(Rank::Value(5)),
            "4" => Ok(Rank::Value(4)),
            "3" => Ok(Rank::Value(3)),
            "2" => Ok(Rank::Value(2)),
            _ => Err("invalid rank"),
        }
    }
}

impl FromStr for Card {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Card, Self::Err> {
        let input = input.trim();
        if input.len() != 2 {
            return Err("invalid card string length");
        }
        let (r, s) = input.split_at(1);
        let r = try!(r.parse::<Rank>());
        let s = try!(s.parse::<Suit>());
        Ok(Card { rank: r, suit: s })
    }
}

impl FromStr for Hand {
    type Err = &'static str;
    fn from_str(input: &str) -> Result<Hand, Self::Err> {
        let cards = input.split_whitespace()
                         .map(|c| c.parse::<Card>().unwrap())
                         .collect::<Vec<_>>();
        Hand::from(cards).ok_or("invalid hand")
    }
}

impl PartialOrd for Card {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.rank.partial_cmp(&other.rank)
    }
}

impl PartialOrd for Hand {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        if self.rank == other.rank {
            for (c1, c2) in self.cards.iter().zip(other.cards.iter()).rev() {
                if c1.rank != c2.rank {
                    return c1.rank.partial_cmp(&c2.rank);
                }
            }
            Some(Ordering::Equal)
        } else {
            self.rank.partial_cmp(&other.rank)
        }
    }
}

impl Hand {
    fn from(cards: Vec<Card>) -> Option<Hand> {
        if cards.len() != 5 {
            None
        } else {
            let mut cards = cards;
            cards.sort_by_key(|card| card.rank);
            let r = Hand::rank(&cards);
            Some(Hand {
                cards: cards,
                rank: r,
            })
        }
    }

    fn rank(cards: &Vec<Card>) -> HandRank {
        let first_suit = cards[0].suit;
        let highest_rank = cards[4].rank;
        let is_flush = cards.iter().all(|card| card.suit == first_suit);
        let is_straight = cards.windows(2).all(|pair| (pair[0] - pair[1]).abs() == 1);
        let mut multiples = HashMap::<Rank, u32>::new();
        for &card in cards.iter() {
            *multiples.entry(card.rank).or_insert(0) += 1;
        }
        let multiples = multiples;
        let has_n = |n| multiples.values().any(|&i| i == n);

        if highest_rank == Rank::Ace && is_flush && is_straight {
            HandRank::RoyalFlush
        } else if is_flush && is_straight {
            HandRank::StraightFlush(highest_rank)
        } else if is_flush {
            HandRank::Flush(highest_rank)
        } else if has_n(4) {
            let r = *multiples.iter().find(|&(_, &n)| n == 4).unwrap().0;
            HandRank::FourOfAKind(r)
        } else if has_n(3) && has_n(2) {
            HandRank::FullHouse(highest_rank)
        } else if is_flush {
            HandRank::Flush(highest_rank)
        } else if is_straight {
            HandRank::Straight(highest_rank)
        } else if has_n(3) {
            let r = *multiples.iter().find(|&(_, &n)| n == 3).unwrap().0;
            HandRank::ThreeOfAKind(r)
        } else if has_n(2) && multiples.len() == 3 {
            let ranks = multiples.iter()
                                 .filter(|&(_, &n)| n == 2)
                                 .map(|(&r, _)| r)
                                 .collect::<Vec<_>>();
            HandRank::TwoPairs(ranks[0], ranks[1])
        } else if has_n(2) {
            let r = *multiples.iter().find(|&(_, &n)| n == 2).unwrap().0;
            HandRank::OnePair(r)
        } else {
            HandRank::HighCard(highest_rank)
        }
    }
}

impl Sub for Card {
    type Output = isize;

    fn sub(self, _rhs: Card) -> isize {
        let value = |rank| match rank {
            Rank::Ace => 14,
            Rank::King => 13,
            Rank::Queen => 12,
            Rank::Jack => 11,
            Rank::Value(n) => n,
        };
        value(self.rank) - value(_rhs.rank)
    }
}
<|endoftext|>


<commit_before>use std::boxed::FnBox;
use std::sync::{Arc, Mutex};
use std::thread::{JoinHandle, spawn};
use std::any::{Any};

use world_state;

pub type ExampleResult = Result<(), Box<Any + Send>>;
pub type ExampleRecoveryBlock = Box<FnBox() -> Result<(),  Box<Any + Send + 'static>> + Send + 'static>;

pub struct Example {
    _description: String,
    block: ExampleRecoveryBlock,
}

impl Example {
    pub fn new(description: String, block: ExampleRecoveryBlock) -> Example {
        Example {
            _description: description,
            block: block,
        }
    }

    pub fn spawn(self, state: Arc<Mutex<world_state::WorldState>>) -> JoinHandle<ExampleResult> {
        spawn(move || self.run(state))
    }

    fn run(self, state: Arc<Mutex<world_state::WorldState>>) -> ExampleResult {
        let result = (self.block)();

        Example::report_result(&result, state);

        return result;
    }

    fn report_result(result: &Result<(), Box<Any + Send + 'static>>, state: Arc<Mutex<world_state::WorldState>>) {
        let ref reporter = state.lock().unwrap().reporter;

        let reporting_result = if result.is_err() {
            reporter.example_failed()
        } else {
            reporter.example_passed()
        };

        if reporting_result.is_err() {
            panic!("work out what to do here");
        }
    }
}
<commit_msg>More small refactorings<commit_after>use std::boxed::FnBox;
use std::sync::{Arc, Mutex};
use std::thread::{JoinHandle, spawn};
use std::any::{Any};

use world_state;

pub type ExampleResult = Result<(), Box<Any + Send + 'static>>;
pub type ExampleRecoveryBlock = Box<FnBox() -> Result<(),  Box<Any + Send + 'static>> + Send + 'static>;

pub struct Example {
    _description: String,
    block: ExampleRecoveryBlock,
}

impl Example {
    pub fn new(description: String, block: ExampleRecoveryBlock) -> Example {
        Example {
            _description: description,
            block: block,
        }
    }

    pub fn spawn(self, state: Arc<Mutex<world_state::WorldState>>) -> JoinHandle<ExampleResult> {
        spawn(move || self.run(state))
    }

    fn run(self, state: Arc<Mutex<world_state::WorldState>>) -> ExampleResult {
        let result = (self.block)();

        Example::report_result(&result, state);

        result
    }

    fn report_result(result: &ExampleResult, state: Arc<Mutex<world_state::WorldState>>) {
        let ref reporter = state.lock().unwrap().reporter;

        let reporting_result = if result.is_err() {
            reporter.example_failed()
        } else {
            reporter.example_passed()
        };

        if reporting_result.is_err() {
            panic!("work out what to do here");
        }
    }
}
<|endoftext|>


<commit_before>use chrono::UTC;
use chrono::datetime::DateTime;

use company::Company;

use postgres::Connection;

use rs_es::query::Filter;
use rs_es::units::JsonVal;

pub fn visibility_filters(conn: &Connection, company_id: &Option<i32>) -> Vec<Filter> {
  let now = DateTime::timestamp(&UTC::now());

  let visibility_rules = Filter::build_bool()
                                .with_must(
                                  vec![
                                    Filter::build_term("accepted", true)
                                           .build(),
                                    Filter::build_range("batch_starts_at")
                                           .with_lt(JsonVal::from(now))
                                           .with_format("epoch_second")
                                           .build(),
                                    Filter::build_range("batch_ends_at")
                                           .with_gte(JsonVal::from(now))
                                           .with_format("epoch_second")
                                           .build()
                                  ])
                                .build();

  let company = match *company_id {
    Some(company_id) => Company::find(conn, &company_id),
    None             => None,
  };

  match company {
    Some(company) => {
      let presented_talents = Filter::build_bool()
                                     .with_must(
                                       vec![
                                         <Filter as VectorOfTerms<i32>>::build_terms(
                                           "ids", &company.presented_talents)
                                       ].into_iter()
                                        .flat_map(|x| x)
                                        .collect::<Vec<Filter>>())
                                     .build();
      vec![
        Filter::build_bool()
               .with_should(vec![visibility_rules, presented_talents])
               .build()
      ]
    },
    None => vec![visibility_rules]
  }
}

pub trait VectorOfTerms<T> {
  fn build_terms(key: &str, values: &Vec<T>) -> Vec<Filter>;
}

macro_rules! build_vector_of_terms_impl {
  ($t:ty) => {
    impl VectorOfTerms<$t> for Filter {
      /// Extract all given items into multiple filters (if present)
      /// i.e. build_terms("field", vec![1, 2]) => vec![Filter(1), Filter(2)]
      /// This enable us to operate on these values with boolean values
      fn build_terms(key: &str, values: &Vec<$t>) -> Vec<Filter> {
        if values.is_empty() {
          return vec![];
        }

        vec![
          Filter::build_terms(key, values.iter()
                                         .map(|v| JsonVal::from(v.clone()))
                                         .collect::<Vec<JsonVal>>()).build()
        ]
      }
    }
  }
}

build_vector_of_terms_impl!(i32);
build_vector_of_terms_impl!(String);
<commit_msg>filters: let visibility_filters() take the ownership of company_id<commit_after>use chrono::UTC;
use chrono::datetime::DateTime;

use company::Company;

use postgres::Connection;

use rs_es::query::Filter;
use rs_es::units::JsonVal;

pub fn visibility_filters(conn: &Connection, company_id: Option<i32>) -> Vec<Filter> {
  let now = DateTime::timestamp(&UTC::now());

  let visibility_rules = Filter::build_bool()
                                .with_must(
                                  vec![
                                    Filter::build_term("accepted", true)
                                           .build(),
                                    Filter::build_range("batch_starts_at")
                                           .with_lt(JsonVal::from(now))
                                           .with_format("epoch_second")
                                           .build(),
                                    Filter::build_range("batch_ends_at")
                                           .with_gte(JsonVal::from(now))
                                           .with_format("epoch_second")
                                           .build()
                                  ])
                                .build();

  let company = match company_id {
    Some(company_id) => Company::find(conn, &company_id),
    None             => None,
  };

  match company {
    Some(company) => {
      let presented_talents = Filter::build_bool()
                                     .with_must(
                                       vec![
                                         <Filter as VectorOfTerms<i32>>::build_terms(
                                           "ids", &company.presented_talents)
                                       ].into_iter()
                                        .flat_map(|x| x)
                                        .collect::<Vec<Filter>>())
                                     .build();
      vec![
        Filter::build_bool()
               .with_should(vec![visibility_rules, presented_talents])
               .build()
      ]
    },
    None => vec![visibility_rules]
  }
}

pub trait VectorOfTerms<T> {
  fn build_terms(key: &str, values: &Vec<T>) -> Vec<Filter>;
}

macro_rules! build_vector_of_terms_impl {
  ($t:ty) => {
    impl VectorOfTerms<$t> for Filter {
      /// Extract all given items into multiple filters (if present)
      /// i.e. build_terms("field", vec![1, 2]) => vec![Filter(1), Filter(2)]
      /// This enable us to operate on these values with boolean values
      fn build_terms(key: &str, values: &Vec<$t>) -> Vec<Filter> {
        if values.is_empty() {
          return vec![];
        }

        vec![
          Filter::build_terms(key, values.iter()
                                         .map(|v| JsonVal::from(v.clone()))
                                         .collect::<Vec<JsonVal>>()).build()
        ]
      }
    }
  }
}

build_vector_of_terms_impl!(i32);
build_vector_of_terms_impl!(String);
<|endoftext|>


<commit_before>use std::num::Int;
use std::mem;

fn fmix32(mut h: u32) -> u32 {
    h ^= h >> 16;
    h *= 0x85ebca6b;
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    h ^= h >> 16;

    return h;
}

fn get_32_block(bytes: &[u8], index: usize) -> u32 {
    let b32: &[u32] = unsafe { mem::transmute(bytes) };

    return b32[index];
}

pub fn murmurhash3_x86_32(bytes: &[u8], seed: u32) -> u32 {
    let c1 = 0xcc9e2d51u32;
    let c2 = 0x1b873593u32;
    let read_size = 4;
    let len = bytes.len() as u32;
    let block_count = len / read_size;

    let mut h1 = seed;

    for i in range(0, block_count as usize) {
        let mut k1 = get_32_block(bytes, i);

        k1 *= c1;
        k1 = k1.rotate_left(15);
        k1 *= c2;

        h1 ^= k1;
        h1 = h1.rotate_left(13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    let mut k1 = 0u32;

    if len & 3 == 3 { k1 ^= (bytes[(block_count * read_size) as usize + 2] as u32) << 16; }
    if len & 3 >= 2 { k1 ^= (bytes[(block_count * read_size) as usize + 1] as u32) << 8; }
    if len & 3 >= 1 { k1 ^=  bytes[(block_count * read_size) as usize + 0] as u32;
        k1 *= c1;
        k1 = k1.rotate_left(15);
        k1 *= c2;
        h1 ^= k1;
    }

    h1 ^= bytes.len() as u32;
    h1 = fmix32(h1);

    return h1;
}

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

    #[test]
    fn test_empty_string() {
        assert!(murmurhash3_x86_32("".as_bytes(), 0) == 0);
    }

    #[test]
    fn test_tail_lengths() {
        assert!(murmurhash3_x86_32("1".as_bytes(), 0)
            == 2484513939);
        assert!(murmurhash3_x86_32("12".as_bytes(), 0)
            == 4191350549);
        assert!(murmurhash3_x86_32("123".as_bytes(), 0)
            == 2662625771);
        assert!(murmurhash3_x86_32("1234".as_bytes(), 0)
            == 1914461635);
    }

    #[test]
    fn test_large_data() {
        assert!(murmurhash3_x86_32("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam at consequat massa. Cras eleifend pellentesque ex, at dignissim libero maximus ut. Sed eget nulla felis".as_bytes(), 0)
            == 1004899618);
    }
}
<commit_msg>Add benchmark for 32 bit hasher<commit_after>use std::num::Int;
use std::mem;

fn fmix32(mut h: u32) -> u32 {
    h ^= h >> 16;
    h *= 0x85ebca6b;
    h ^= h >> 13;
    h *= 0xc2b2ae35;
    h ^= h >> 16;

    return h;
}

fn get_32_block(bytes: &[u8], index: usize) -> u32 {
    let b32: &[u32] = unsafe { mem::transmute(bytes) };

    return b32[index];
}

pub fn murmurhash3_x86_32(bytes: &[u8], seed: u32) -> u32 {
    let c1 = 0xcc9e2d51u32;
    let c2 = 0x1b873593u32;
    let read_size = 4;
    let len = bytes.len() as u32;
    let block_count = len / read_size;

    let mut h1 = seed;

    for i in range(0, block_count as usize) {
        let mut k1 = get_32_block(bytes, i);

        k1 *= c1;
        k1 = k1.rotate_left(15);
        k1 *= c2;

        h1 ^= k1;
        h1 = h1.rotate_left(13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    let mut k1 = 0u32;

    if len & 3 == 3 { k1 ^= (bytes[(block_count * read_size) as usize + 2] as u32) << 16; }
    if len & 3 >= 2 { k1 ^= (bytes[(block_count * read_size) as usize + 1] as u32) << 8; }
    if len & 3 >= 1 { k1 ^=  bytes[(block_count * read_size) as usize + 0] as u32;
        k1 *= c1;
        k1 = k1.rotate_left(15);
        k1 *= c2;
        h1 ^= k1;
    }

    h1 ^= bytes.len() as u32;
    h1 = fmix32(h1);

    return h1;
}

#[cfg(test)]
mod test {
    extern crate rand;
    extern crate test;

    use std::iter::FromIterator;

    use super::murmurhash3_x86_32;

    use self::rand::Rng;
    use self::test::{Bencher, black_box};

    #[test]
    fn test_empty_string() {
        assert!(murmurhash3_x86_32("".as_bytes(), 0) == 0);
    }

    #[test]
    fn test_tail_lengths() {
        assert!(murmurhash3_x86_32("1".as_bytes(), 0)
            == 2484513939);
        assert!(murmurhash3_x86_32("12".as_bytes(), 0)
            == 4191350549);
        assert!(murmurhash3_x86_32("123".as_bytes(), 0)
            == 2662625771);
        assert!(murmurhash3_x86_32("1234".as_bytes(), 0)
            == 1914461635);
    }

    #[test]
    fn test_large_data() {
        assert!(murmurhash3_x86_32("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam at consequat massa. Cras eleifend pellentesque ex, at dignissim libero maximus ut. Sed eget nulla felis".as_bytes(), 0)
            == 1004899618);
    }

    fn run_bench(b: &mut Bencher, size: u64) {
        let mut data: Vec<u8> = FromIterator::from_iter(range(0, size).map(|_| 0u8));
        rand::thread_rng().fill_bytes(data.as_mut_slice());

        b.bytes = size;
        b.iter(|| {
            black_box(murmurhash3_x86_32(data.as_slice(), 0));
        });
    }

    #[bench]
    fn bench_random_256k(b: &mut Bencher) {
        run_bench(b, 256 * 1024);
    }

    #[bench]
    fn bench_random_16b(b: &mut Bencher) {
        run_bench(b, 16);
    }
}
<|endoftext|>


<commit_before>//! The net module is resonsible for the network related parts,
//! the mDNS registering, mDNS search, communication server and client.
//! It also let's us startup and perform everything in yet one step.
mod connect_from;
mod connect_to;
mod data;
pub mod key_keeper;

use super::ctrl::{self, ForwardNetMessage};

use async_std::sync::{Arc, Mutex};
use libp2p::{
    mdns::{
        service::{self, MdnsPacket, MdnsPeer},
        MdnsService,
    },
    PeerId,
};
use std::{self, sync::mpsc::Sender, time::Duration};

/// The Net component keeps control about everything from net.
///
/// # Arguments
/// * 'peer_id' - the own peer id (to not talk to much with itself ;-))
/// * 'clients_connected' - All clients that are connected
/// * 'has_ui' - if there is an ui present, that would need update messages///
/// * 'ui_sender' - to send out update ui messages
pub struct Net {
    own_peer_id: PeerId,
    clients_connected: Arc<Mutex<Vec<PeerId>>>,
    has_ui: bool,
    ui_sender: Sender<ctrl::UiUpdateMsg>,
}

impl Net {
    pub fn new(own_peer_id: PeerId, has_ui: bool, ui_sender: Sender<ctrl::UiUpdateMsg>) -> Self {
        Net {
            own_peer_id,
            clients_connected: Arc::new(Mutex::new(Vec::new())),
            has_ui,
            ui_sender,
        }
    }

    /// Lookup yet is the start of the networking.
    /// It looks for possible mDNS clients and spawns eventually
    pub async fn lookup(&mut self) {
        let has_ui = self.has_ui.clone();

        // to controller messages (mostly tui now)
        let ui_update_sender = self.ui_sender.clone();

        // collection of addresses
        let borrow_arc_connected_clients = self.clients_connected.clone();

        // statistics
        let mut count_valid = 0;

        // prepare everything for mdns thread
        let my_peer_id = &self.own_peer_id;
        Self::async_mdns_discover(
            my_peer_id,
            &ui_update_sender,
            has_ui,
            borrow_arc_connected_clients,
            &mut count_valid,
        )
        .await
        .and_then(|count_response| {
            if !has_ui {
                let output_string = format!(
                    "no response from : \n\
                     ----------------- {no_resp:>width$}\n",
                    no_resp = count_response,
                    width = 3
                );
                info!("{}", output_string);
            }
            Ok(())
        })
        .unwrap();
    }

    /// Discovers mdns on the net and should have a whole
    /// process with discovered clients to share data.
    async fn async_mdns_discover(
        my_peer_id: &PeerId,
        ctrl_sender: &std::sync::mpsc::Sender<ctrl::UiUpdateMsg>,
        has_ui: bool,
        borrow_arc_connected_clients: Arc<Mutex<Vec<PeerId>>>,
        count_valid: &mut u32,
    ) -> Result<u32, std::io::Error> {
        let mut count_no_response: u32 = 0;

        let mut service = MdnsService::new()?;
        info!("Started Mdns Service!");

        // finally stop animation
        if has_ui {
            info!("Start animation!");
            ctrl_sender
                .send(ctrl::UiUpdateMsg::CollectionUpdate(
                    ctrl::CollectionPathAlive::HostSearch,
                    ctrl::Status::ON,
                ))
                .unwrap();
        }

        info!("Starting Mdns Looping!");
        loop {
            trace!("taking package ...");
            let (mut srv, packet) = service.next().await;
            match packet {
                MdnsPacket::Query(query) => {
                    // We detected a libp2p mDNS query on the network. In a real application, you
                    // probably want to answer this query by doing `query.respond(...)`.
                    trace!("Detected query from {:?}", query.remote_addr());
                    let response = service::build_query_response(
                        query.query_id(),
                        my_peer_id.clone(),
                        vec![].into_iter(), // something or leave it empty??
                        Duration::from_secs(120),
                    )
                    .unwrap();
                    srv.enqueue_response(response);
                }
                MdnsPacket::Response(response) => {
                    // We detected a libp2p mDNS response on the network. Responses are for
                    // everyone and not just for the requester, which makes it possible to
                    // passively listen.
                    for new_peer in response.discovered_peers() {
                        info!("Discovered peer {:?}", new_peer.id());
                        // These are the self-reported addresses of the peer we just discovered.
                        for addr in new_peer.addresses() {
                            println!(" Address = {:?}", addr);
                        }
                        // todo: filter own address already here
                        *count_valid += 1;
                        Self::connect_new_clients(
                            new_peer,
                            borrow_arc_connected_clients.clone(),
                            ctrl_sender,
                            has_ui,
                        )
                        .await;
                        count_no_response += 1;
                    }
                }
                MdnsPacket::ServiceDiscovery(query) => {
                    // The last possibility is a service detection query from DNS-SD.
                    // Just like `Query`, in a real application you probably want to call
                    // `query.respond`.
                    info!("Detected service query from {:?}", query.remote_addr());
                }
            }
            service = srv
        }
        Ok(count_no_response)
    }

    async fn connect_new_clients(
        new_peer: &MdnsPeer,
        peers_connected: Arc<Mutex<Vec<PeerId>>>,
        ctrl_sender: &std::sync::mpsc::Sender<ctrl::UiUpdateMsg>,
        has_ui: bool,
    ) {
        // wait for message
        //
        // input address
        //
        //let to_push_into_arc_clone = incoming_id.clone();
        if let Some(mut guard) = peers_connected.try_lock() {
            let ip_addresses = &mut *guard;
            // search if ip address is already collected
            if ip_addresses
                .iter()
                .all(|stored_peer_ids| stored_peer_ids != new_peer.id())
            {
                // put into collection to not find again
                // todo: what this
                // let id_for_processing = to_push_into_arc_clone.clone();
                // ip_addresses.push(to_push_into_arc_clone);

                let count = ip_addresses.len();
                if has_ui {
                    ctrl_sender
                        .send(ctrl::UiUpdateMsg::NetUpdate(ForwardNetMessage::new(
                            ctrl::NetMessages::ShowNewHost,
                            new_peer.id().to_string(),
                        )))
                        .unwrap();
                    ctrl_sender
                        .send(ctrl::UiUpdateMsg::NetUpdate(ForwardNetMessage::new(
                            ctrl::NetMessages::ShowStats {
                                show: ctrl::NetStats {
                                    line: count,
                                    max: 0, //index,
                                },
                            },
                            String::from(""),
                        )))
                        .unwrap();
                }
                // create ssh client in new thread
                // let _connect_ip_client_thread = task::spawn(async move {
                //     let connector = ConnectToOther::new(&id_for_processing);
                //     connector.run();
                // });
            }
        }
        ()
    }
}

impl Drop for Net {
    fn drop(&mut self) {
        if !self.has_ui {
            println!("Dropping/destroying net");
        }
    }
}
<commit_msg>[net] fixed to not list yourself, and no multiple entries, added more logging<commit_after>//! The net module is resonsible for the network related parts,
//! the mDNS registering, mDNS search, communication server and client.
//! It also let's us startup and perform everything in yet one step.
mod connect_from;
mod connect_to;
mod data;
pub mod key_keeper;

use super::ctrl::{self, ForwardNetMessage};

use async_std::sync::{Arc, Mutex};
use libp2p::{
    mdns::{
        service::{self, MdnsPacket, MdnsPeer},
        MdnsService,
    },
    PeerId,
};
use std::{self, sync::mpsc::Sender, time::Duration};

/// The Net component keeps control about everything from net.
///
/// # Arguments
/// * 'peer_id' - the own peer id (to not talk to much with itself ;-))
/// * 'clients_connected' - All clients that are connected
/// * 'has_ui' - if there is an ui present, that would need update messages///
/// * 'ui_sender' - to send out update ui messages
pub struct Net {
    own_peer_id: PeerId,
    clients_connected: Arc<Mutex<Vec<PeerId>>>,
    has_ui: bool,
    ui_sender: Sender<ctrl::UiUpdateMsg>,
}

impl Net {
    pub fn new(own_peer_id: PeerId, has_ui: bool, ui_sender: Sender<ctrl::UiUpdateMsg>) -> Self {
        Net {
            own_peer_id,
            clients_connected: Arc::new(Mutex::new(Vec::new())),
            has_ui,
            ui_sender,
        }
    }

    /// Lookup yet is the start of the networking.
    /// It looks for possible mDNS clients and spawns eventually
    pub async fn lookup(&mut self) {
        let has_ui = self.has_ui.clone();

        // to controller messages (mostly tui now)
        let ui_update_sender = self.ui_sender.clone();

        // collection of addresses
        let borrow_arc_connected_clients = self.clients_connected.clone();

        // statistics
        let mut count_valid = 0;

        // prepare everything for mdns thread
        let my_peer_id = &self.own_peer_id;
        Self::async_mdns_discover(
            my_peer_id,
            &ui_update_sender,
            has_ui,
            borrow_arc_connected_clients,
            &mut count_valid,
        )
        .await
        .and_then(|count_response| {
            if !has_ui {
                let output_string = format!(
                    "no response from : \n\
                     ----------------- {no_resp:>width$}\n",
                    no_resp = count_response,
                    width = 3
                );
                info!("{}", output_string);
            }
            Ok(())
        })
        .unwrap();
    }

    /// Discovers mdns on the net and should have a whole
    /// process with discovered clients to share data.
    async fn async_mdns_discover(
        own_peer_id: &PeerId,
        ctrl_sender: &std::sync::mpsc::Sender<ctrl::UiUpdateMsg>,
        has_ui: bool,
        borrow_arc_connected_clients: Arc<Mutex<Vec<PeerId>>>,
        count_valid: &mut u32,
    ) -> Result<u32, std::io::Error> {
        let mut count_no_response: u32 = 0;

        let mut service = MdnsService::new()?;
        info!("Started Mdns Service!");

        // start animation
        if has_ui {
            info!("Start netsearch animation!");
            ctrl_sender
                .send(ctrl::UiUpdateMsg::CollectionUpdate(
                    ctrl::CollectionPathAlive::HostSearch,
                    ctrl::Status::ON,
                ))
                .unwrap();
        }
        info!("Starting Mdns Looping!");
        // todo: to gracefully stop here, inside the loop could be a receive, which in an
        //       async select! block or just by try_select waits for a terminate message
        //       through a channel.
        loop {
            trace!("taking new package ...");
            let (mut srv, packet) = service.next().await;
            match packet {
                MdnsPacket::Query(query) => {
                    // We detected a libp2p mDNS query on the network. In a real application, you
                    // probably want to answer this query by doing `query.respond(...)`.
                    trace!("Query came in from {:?}", query.remote_addr());
                    if !has_ui {
                        println!("Query came in from: {:?}", query.remote_addr());
                    }

                    // send back own peer ?? todo: a bit more maybe? addresses?
                    let response = service::build_query_response(
                        query.query_id(),
                        own_peer_id.clone(),
                        vec![].into_iter(), // something or leave it empty??
                        Duration::from_secs(120),
                    )
                    .unwrap();
                    srv.enqueue_response(response);
                }
                MdnsPacket::Response(response) => {
                    // We detected a libp2p mDNS response on the network. Responses are for
                    // everyone and not just for the requester, which makes it possible to
                    // passively listen.
                    for new_peer in response.discovered_peers() {
                        // if found myself then don't connect
                        if own_peer_id != new_peer.id() {
                            info!("Discovered: {:?}", new_peer.id());
                            if !has_ui {
                                println!("Discovered: {:?}", new_peer.id());
                            }
                            // These are the self-reported addresses of the peer we just discovered.
                            for addr in new_peer.addresses() {
                                trace!(" Address = {:?}", addr);
                            }

                            *count_valid += 1;
                            Self::connect_new_clients(
                                new_peer,
                                borrow_arc_connected_clients.clone(),
                                ctrl_sender,
                                has_ui,
                            )
                            .await;
                            count_no_response += 1;
                        } else {
                            trace!("Found myself: {:?}", new_peer.id());
                            // to terminal
                            if !has_ui {
                                println!("Found myself: {:?}", new_peer.id());
                            }
                        }
                    }
                }
                MdnsPacket::ServiceDiscovery(query) => {
                    // The last possibility is a service detection query from DNS-SD.
                    // Just like `Query`, in a real application you probably want to call
                    // `query.respond`.
                    info!("Detected service query from {:?}", query.remote_addr());
                }
            }
            // todo: really necessary???
            service = srv
        }
        Ok(count_no_response)
    }

    async fn connect_new_clients(
        new_peer: &MdnsPeer,
        peers_connected: Arc<Mutex<Vec<PeerId>>>,
        ctrl_sender: &std::sync::mpsc::Sender<ctrl::UiUpdateMsg>,
        has_ui: bool,
    ) {
        if let Some(mut guard) = peers_connected.try_lock() {
            let all_stored_peers = &mut *guard;
            // search if ip address is already collected
            if all_stored_peers
                .iter()
                .all(|stored_peer| stored_peer != new_peer.id())
            {
                let count = all_stored_peers.len();
                if has_ui {
                    ctrl_sender
                        .send(ctrl::UiUpdateMsg::NetUpdate(ForwardNetMessage::new(
                            ctrl::NetMessages::ShowNewHost,
                            new_peer.id().to_string(),
                        )))
                        .unwrap();
                    ctrl_sender
                        .send(ctrl::UiUpdateMsg::NetUpdate(ForwardNetMessage::new(
                            ctrl::NetMessages::ShowStats {
                                show: ctrl::NetStats {
                                    line: count,
                                    max: 0, //index,
                                },
                            },
                            String::from(""),
                        )))
                        .unwrap();
                }
                // put into collection to not find again
                all_stored_peers.push(new_peer.id().clone());

                // todo: here!!!!!!!!!!!!!!!!!!!!!!!
                // create ssh client in new thread
                // let _connect_ip_client_thread = task::spawn(async move {
                //     let connector = ConnectToOther::new(&id_for_processing);
                //     connector.run();
                // });
            }
        }
        ()
    }
}

impl Drop for Net {
    fn drop(&mut self) {
        if !self.has_ui {
            println!("Dropping/destroying net");
        }
    }
}
<|endoftext|>


<commit_before>//! The [`uuid`] prelude.
//!
//! This module contains the most important items of the [`uuid`] crate.
//!
//! To use the prelude, include the following in your crate root:
//!
//! ```rust
//! extern crate uuid;
//! ```
//!
//! and the following in every module:
//!
//! ```rust
//! use uuid::prelude::*;
//! ```
//!
//! # Prelude Contents
//!
//! Currently the prelude reexports the following:
//!
//! ## The core types
//!
//! [`uuid`]`::{`[`ParseError`], [`Uuid`], [`UuidVariant`]`}`: The fundamental
//! types used in [`uuid`] crate.
//!
//! [`uuid`]: ../index.html
//! [`ParseError`]: ../enum.ParseError.html
//! [`Uuid`]: ../struct.Uuid.html
//! [`UuidVariant`]: enum.UuidVariant.html

#[doc(inline)]
pub use super::{ParseError, Uuid, UuidVariant};
<commit_msg>remove ParseError from the prelude<commit_after>//! The [`uuid`] prelude.
//!
//! This module contains the most important items of the [`uuid`] crate.
//!
//! To use the prelude, include the following in your crate root:
//!
//! ```rust
//! extern crate uuid;
//! ```
//!
//! and the following in every module:
//!
//! ```rust
//! use uuid::prelude::*;
//! ```
//!
//! # Prelude Contents
//!
//! Currently the prelude reexports the following:
//!
//! ## The core types
//!
//! [`uuid`]`::{`[`Uuid`], [`UuidVariant`]`}`: The fundamental
//! types used in [`uuid`] crate.
//!
//! [`uuid`]: ../index.html
//! [`Uuid`]: ../struct.Uuid.html
//! [`UuidVariant`]: enum.UuidVariant.html

#[doc(inline)]
pub use super::{Uuid, UuidVariant};
<|endoftext|>


<commit_before>// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Evil private APIs.
//!
//! These are liable to change at any time. Use with caution!

use geometry::CGRect;
use std::ptr;

pub struct CGSRegion {
    region: ffi::CGSRegionRef,
}

impl Drop for CGSRegion {
    fn drop(&mut self) {
        unsafe {
            ffi::CGSRegionRelease(self.region)
        }
    }
}

impl CGSRegion {
    #[inline]
    pub fn from_rect(rect: &CGRect) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRect(rect, &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }

    #[inline]
    pub fn from_rects(rects: &[CGRect]) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRectList(rects.as_ptr(),
                                                  rects.len() as c_uint,
                                                  &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }
}

mod ffi {
    use geometry::CGRect;
    use libc::c_uint;

    // This is an enum so that we can't easily make instances of this opaque type.
    enum CGSRegionObject {}

    pub type CGError = OSStatus;
    pub type CGSRegionRef = *mut CGSRegionObject;
    pub type OSStatus = i32;

    #[link(name = "ApplicationServices", kind = "framework")]
    extern {
        pub fn CGSRegionRelease(region: CGSRegionRef);
        pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError;
        pub fn CGSNewRegionWithRectList(rects: *const CGRect,
                                        rectCount: c_uint,
                                        outRegion: *mut CGSRegionRef)
                                        -> CGError;
    }
}

<commit_msg>private: Add a binding to `CGSSetSurfaceShape`.<commit_after>// Copyright 2016 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// 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.

//! Evil private APIs.
//!
//! These are liable to change at any time. Use with caution!

use geometry::CGRect;
use libc::{c_int, c_uint};
use std::ptr;

pub struct CGSRegion {
    region: ffi::CGSRegionRef,
}

impl Drop for CGSRegion {
    fn drop(&mut self) {
        unsafe {
            ffi::CGSRegionRelease(self.region)
        }
    }
}

impl CGSRegion {
    #[inline]
    pub fn from_rect(rect: &CGRect) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRect(rect, &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }

    #[inline]
    pub fn from_rects(rects: &[CGRect]) -> CGSRegion {
        unsafe {
            let mut region = ptr::null_mut();
            assert!(ffi::CGSNewRegionWithRectList(rects.as_ptr(),
                                                  rects.len() as c_uint,
                                                  &mut region) == 0);
            CGSRegion {
                region: region,
            }
        }
    }
}

/// This should always be memory-safe; the window server rejects any invalid surface IDs.
pub struct CGSSurface {
    context_id: c_uint,
    window_number: c_int,
    surface_id: c_uint,
}

impl CGSSurface {
    #[inline]
    pub fn from_ids(context_id: c_uint, window_number: c_int, surface_id: c_uint) -> CGSSurface {
        CGSSurface {
            context_id: context_id,
            window_number: window_number,
            surface_id: surface_id,
        }
    }

    #[inline]
    pub fn id(&self) -> c_uint {
        self.surface_id
    }

    #[inline]
    pub fn set_shape(&self, region: &CGSRegion) {
        unsafe {
            assert!(ffi::CGSSetSurfaceShape(self.context_id,
                                            self.window_number,
                                            self.surface_id,
                                            region.region) == 0)
        }
    }
}

mod ffi {
    use geometry::CGRect;
    use libc::{c_int, c_uint};

    // This is an enum so that we can't easily make instances of this opaque type.
    enum CGSRegionObject {}

    pub type CGError = OSStatus;
    pub type CGSRegionRef = *mut CGSRegionObject;
    pub type OSStatus = i32;

    #[link(name = "ApplicationServices", kind = "framework")]
    extern {
        pub fn CGSRegionRelease(region: CGSRegionRef);
        pub fn CGSNewRegionWithRect(rect: *const CGRect, outRegion: *mut CGSRegionRef) -> CGError;
        pub fn CGSNewRegionWithRectList(rects: *const CGRect,
                                        rectCount: c_uint,
                                        outRegion: *mut CGSRegionRef)
                                        -> CGError;

        pub fn CGSSetSurfaceShape(contextID: c_uint,
                                  windowNumber: c_int,
                                  surfaceID: c_uint,
                                  region: CGSRegionRef)
                                  -> CGError;
    }
}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::fmt;
use std::path::{Path, PathBuf};
use std::result::Result as StdResult;
use std::str;

use java_properties;
use toml;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};

use super::errors::*;
use super::format::Style;
use super::fsutils;
use super::template::Template;

type Context = HashMap<String, String>;

#[derive(Debug)]
pub struct Project {
    pub root_path: Option<String>,
    pub config_format: ConfigFormat,
    pub style: Style,
    pub force_packaged: bool,
}

#[derive(Copy, Clone, Debug)]
pub enum ConfigFormat {
    JavaProps,
    Toml,
}

impl fmt::Display for ConfigFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        let name = match *self {
            ConfigFormat::JavaProps => "properties",
            ConfigFormat::Toml => "toml",
        };
        write!(f, "default.{}", &name)
    }
}

impl Default for Project {
    fn default() -> Project {
        Project {
            root_path: None,
            config_format: ConfigFormat::Toml,
            style: Style::Simple,
            force_packaged: false,
        }
    }
}

impl Project {

    pub fn new<S>(root: Option<S>,
                  config_format: ConfigFormat,
                  packaged: bool)
                  -> Project
        where S: AsRef<str>
    {
        Project {
            root_path: root.map(|v| v.as_ref().to_owned()),
            config_format: config_format,
            style: Style::Simple,
            force_packaged: packaged,
        }
    }

    pub fn new_g8(root: Option<&str>) -> Project {
        Project {
            root_path: root.map(|v| v.to_string()),
            config_format: ConfigFormat::JavaProps,
            style: Style::Giter8,
            force_packaged: true,
        }
    }

    pub fn set_root_dir(&mut self, root: &str) -> &mut Project {
        self.root_path = Some(root.into());
        self
    }

    pub fn resolve_root_dir(&self, clone_root: &Path) -> PathBuf {
        let mut buf = clone_root.to_path_buf();

        if let Some(ref inner) = self.root_path {
            if fsutils::exists(clone_root.join(inner)) {
                buf.push(inner);
            }
        }
        buf
    }

    pub fn default_context(&self, clone_root: &Path) -> Result<Context> {
        let root = self.resolve_root_dir(clone_root);
        get_default_context(self, &root)
    }

    // TODO: give clear `Err` type
    // TODO: make it run async
    pub fn generate(&self,
                    context: &Context,
                    clone_root: &Path,
                    dest: &Path,
                    dry_run: bool)
                    -> Result<()> {

        let root = self.resolve_root_dir(clone_root);
        let walker = WalkDir::new(&root).into_iter();

        let mut file_map: HashMap<OsString, String> = HashMap::new();
        let default_ctx = root.join(format!("{}", &self.config_format));

        if !dry_run {
            fs::create_dir_all(dest).unwrap();
        }

        for entry in walker.filter_entry(|e| !is_git_metadata(e)) {
            let entry = entry.unwrap();

            if entry.path() == &root || entry.path() == &default_ctx {
                debug!("skipping {:?}", entry.file_name());
                continue;
            }

            let mut segment: Vec<&OsStr> = Vec::new();
            let mut rel_path_up = entry.path().parent();
            let mut upwards = 1;
            while let Some(parent) = rel_path_up {
                if upwards >= entry.depth() {
                    break;
                } else {
                    segment.push(parent.file_name().unwrap_or("".as_ref()));
                }
                upwards += 1;
                rel_path_up = parent.parent();
            }

            let base = entry.file_name();
            let mut dest = dest.to_path_buf();
            if !segment.is_empty() {
                segment.reverse();
                for part in segment {
                    if let Some(rep) = file_map.get(part) {
                        debug!("File tree altered: {:?} => {:?}", part, rep);
                        dest.push(rep);
                    } else {
                        dest.push(part);
                    }
                }
            }

            let mut buf = Vec::new();
            // FIXME: we need to re-design `Template` so we can manipulate its elements
            if "$package$" == base.to_string_lossy().as_ref() && self.force_packaged {
                Template::compile_inline(&mut buf,
                                         Style::Pathname,
                                         "$package__packaged$",
                                         context)
                                         .unwrap();
            } else {
                Template::compile_inline(&mut buf, Style::Pathname, &base.to_string_lossy(), context)
                    .unwrap();
            }

            let name = String::from_utf8(buf).unwrap();
            if &name != base.to_string_lossy().as_ref() {
                file_map.insert(base.to_os_string(), name.clone());
            }
            dest.push(&name);
            debug!("Destination entry: {:?}", dest);

            // TODO:
            if !dry_run {
                if entry.file_type().is_file() {
                    let mut tpl = Template::read_file(self.style.clone(), &entry.path()).unwrap();
                    let mut f = fs::OpenOptions::new()
                        .write(true)
                        .truncate(true)
                        .create(true)
                        .open(dest.as_path())
                        .unwrap();

                    tpl.write(&mut f, context).unwrap();
                    f.sync_data().unwrap();
                } else if entry.file_type().is_dir() {
                    fs::create_dir_all(dest.as_path()).expect("Failed to copy directory");
                }
            }
        }
        debug!("{:?}", &file_map);

        Ok(())
    }
}

fn is_git_metadata(entry: &DirEntry) -> bool {
    let is_git = entry.file_name().to_str().map(|s| s == ".git").unwrap_or(false);
    fsutils::is_directory(entry.path()) && is_git
}

fn get_default_context(project: &Project, root_dir: &Path) -> Result<Context> {
    let default_ctx = root_dir.join(format!("{}", project.config_format));

    match project.config_format {
        ConfigFormat::JavaProps => {
            fs::File::open(&default_ctx)
                .map(|f| java_properties::read(f).unwrap())
                .map_err(|e| ErrorKind::Io(e).into())
        }
        ConfigFormat::Toml => {
            fsutils::read_file(&default_ctx)
                .map(|s| toml::decode_str::<HashMap<String, String>>(&s).unwrap())
                .chain_err(|| ErrorKind::TomlDecodeFailure)
        }
    }
}
<commit_msg>changed default config file name in simple style<commit_after>use std::collections::HashMap;
use std::ffi::{OsStr, OsString};
use std::fs;
use std::fmt;
use std::path::{Path, PathBuf};
use std::result::Result as StdResult;
use std::str;

use java_properties;
use toml;
use walkdir::{DirEntry, WalkDir, WalkDirIterator};

use super::errors::*;
use super::format::Style;
use super::fsutils;
use super::template::Template;

type Context = HashMap<String, String>;

#[derive(Debug)]
pub struct Project {
    pub root_path: Option<String>,
    pub config_format: ConfigFormat,
    pub style: Style,
    pub force_packaged: bool,
}

#[derive(Copy, Clone, Debug)]
pub enum ConfigFormat {
    JavaProps,
    Toml,
}

impl fmt::Display for ConfigFormat {
    fn fmt(&self, f: &mut fmt::Formatter) -> StdResult<(), fmt::Error> {
        let name = match *self {
            ConfigFormat::JavaProps => "default.properties",
            ConfigFormat::Toml => "_rig.toml",
        };
        write!(f, "{}", &name)
    }
}

impl Default for Project {
    fn default() -> Project {
        Project {
            root_path: None,
            config_format: ConfigFormat::Toml,
            style: Style::Simple,
            force_packaged: false,
        }
    }
}

impl Project {

    pub fn new<S>(root: Option<S>,
                  config_format: ConfigFormat,
                  packaged: bool)
                  -> Project
        where S: AsRef<str>
    {
        Project {
            root_path: root.map(|v| v.as_ref().to_owned()),
            config_format: config_format,
            style: Style::Simple,
            force_packaged: packaged,
        }
    }

    pub fn new_g8(root: Option<&str>) -> Project {
        Project {
            root_path: root.map(|v| v.to_string()),
            config_format: ConfigFormat::JavaProps,
            style: Style::Giter8,
            force_packaged: true,
        }
    }

    pub fn set_root_dir(&mut self, root: &str) -> &mut Project {
        self.root_path = Some(root.into());
        self
    }

    pub fn resolve_root_dir(&self, clone_root: &Path) -> PathBuf {
        let mut buf = clone_root.to_path_buf();

        if let Some(ref inner) = self.root_path {
            if fsutils::exists(clone_root.join(inner)) {
                buf.push(inner);
            }
        }
        buf
    }

    pub fn default_context(&self, clone_root: &Path) -> Result<Context> {
        let root = self.resolve_root_dir(clone_root);
        get_default_context(self, &root)
    }

    // TODO: give clear `Err` type
    // TODO: make it run async
    pub fn generate(&self,
                    context: &Context,
                    clone_root: &Path,
                    dest: &Path,
                    dry_run: bool)
                    -> Result<()> {

        let root = self.resolve_root_dir(clone_root);
        let walker = WalkDir::new(&root).into_iter();

        let mut file_map: HashMap<OsString, String> = HashMap::new();
        let default_ctx = root.join(format!("{}", &self.config_format));

        if !dry_run {
            fs::create_dir_all(dest).unwrap();
        }

        for entry in walker.filter_entry(|e| !is_git_metadata(e)) {
            let entry = entry.unwrap();

            if entry.path() == &root || entry.path() == &default_ctx {
                debug!("skipping {:?}", entry.file_name());
                continue;
            }

            let mut segment: Vec<&OsStr> = Vec::new();
            let mut rel_path_up = entry.path().parent();
            let mut upwards = 1;
            while let Some(parent) = rel_path_up {
                if upwards >= entry.depth() {
                    break;
                } else {
                    segment.push(parent.file_name().unwrap_or("".as_ref()));
                }
                upwards += 1;
                rel_path_up = parent.parent();
            }

            let base = entry.file_name();
            let mut dest = dest.to_path_buf();
            if !segment.is_empty() {
                segment.reverse();
                for part in segment {
                    if let Some(rep) = file_map.get(part) {
                        debug!("File tree altered: {:?} => {:?}", part, rep);
                        dest.push(rep);
                    } else {
                        dest.push(part);
                    }
                }
            }

            let mut buf = Vec::new();
            // FIXME: we need to re-design `Template` so we can manipulate its elements
            if "$package$" == base.to_string_lossy().as_ref() && self.force_packaged {
                Template::compile_inline(&mut buf,
                                         Style::Pathname,
                                         "$package__packaged$",
                                         context)
                                         .unwrap();
            } else {
                Template::compile_inline(&mut buf, Style::Pathname, &base.to_string_lossy(), context)
                    .unwrap();
            }

            let name = String::from_utf8(buf).unwrap();
            if &name != base.to_string_lossy().as_ref() {
                file_map.insert(base.to_os_string(), name.clone());
            }
            dest.push(&name);
            debug!("Destination entry: {:?}", dest);

            // TODO:
            if !dry_run {
                if entry.file_type().is_file() {
                    let mut tpl = Template::read_file(self.style.clone(), &entry.path()).unwrap();
                    let mut f = fs::OpenOptions::new()
                        .write(true)
                        .truncate(true)
                        .create(true)
                        .open(dest.as_path())
                        .unwrap();

                    tpl.write(&mut f, context).unwrap();
                    f.sync_data().unwrap();
                } else if entry.file_type().is_dir() {
                    fs::create_dir_all(dest.as_path()).expect("Failed to copy directory");
                }
            }
        }
        debug!("{:?}", &file_map);

        Ok(())
    }
}

fn is_git_metadata(entry: &DirEntry) -> bool {
    let is_git = entry.file_name().to_str().map(|s| s == ".git").unwrap_or(false);
    fsutils::is_directory(entry.path()) && is_git
}

fn get_default_context(project: &Project, root_dir: &Path) -> Result<Context> {
    let default_ctx = root_dir.join(format!("{}", project.config_format));

    match project.config_format {
        ConfigFormat::JavaProps => {
            fs::File::open(&default_ctx)
                .map(|f| java_properties::read(f).unwrap())
                .map_err(|e| ErrorKind::Io(e).into())
        }
        ConfigFormat::Toml => {
            fsutils::read_file(&default_ctx)
                .map(|s| toml::decode_str::<HashMap<String, String>>(&s).unwrap())
                .chain_err(|| ErrorKind::TomlDecodeFailure)
        }
    }
}
<|endoftext|>