<commit_before>#![no_std]

#[macro_use]
extern crate enum_map;

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
}
<commit_msg>Test if keys are correctly serialized for Option<T><commit_after>#[macro_use]
extern crate enum_map;

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    assert_eq!(
        map.into_iter().collect::<Vec<_>>(),
        [(None, 4), (Some(false), 5), (Some(true), 6)]
    );
}
<|endoftext|>


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

//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Path, PathBuf, Component};
use std::process::Command;

use dist::{self, pkgname, sanitize_sh, tmpdir};

use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;
use config::Config;

pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "docs", "rust-docs", stage, Some(host));
}

pub fn install_std(builder: &Builder, stage: u32, target: Interned<String>) {
    install_sh(builder, "std", "rust-std", stage, Some(target));
}

pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "cargo", "cargo", stage, Some(host));
}

pub fn install_rls(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rls", "rls", stage, Some(host));
}

pub fn install_rustfmt(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rustfmt", "rustfmt", stage, Some(host));
}

pub fn install_analysis(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "analysis", "rust-analysis", stage, Some(host));
}

pub fn install_src(builder: &Builder, stage: u32) {
    install_sh(builder, "src", "rust-src", stage, None);
}
pub fn install_rustc(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rustc", "rustc", stage, Some(host));
}

fn install_sh(
    builder: &Builder,
    package: &str,
    name: &str,
    stage: u32,
    host: Option<Interned<String>>
) {
    let build = builder.build;
    build.info(&format!("Install {} stage{} ({:?})", package, stage, host));

    let prefix_default = PathBuf::from("/usr/local");
    let sysconfdir_default = PathBuf::from("/etc");
    let datadir_default = PathBuf::from("share");
    let docdir_default = datadir_default.join("doc/rust");
    let bindir_default = PathBuf::from("bin");
    let libdir_default = PathBuf::from("lib");
    let mandir_default = datadir_default.join("man");
    let prefix = build.config.prefix.as_ref().unwrap_or(&prefix_default);
    let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
    let datadir = build.config.datadir.as_ref().unwrap_or(&datadir_default);
    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
    let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);

    let sysconfdir = prefix.join(sysconfdir);
    let datadir = prefix.join(datadir);
    let docdir = prefix.join(docdir);
    let bindir = prefix.join(bindir);
    let libdir = prefix.join(libdir);
    let mandir = prefix.join(mandir);

    let destdir = env::var_os("DESTDIR").map(PathBuf::from);

    let prefix = add_destdir(&prefix, &destdir);
    let sysconfdir = add_destdir(&sysconfdir, &destdir);
    let datadir = add_destdir(&datadir, &destdir);
    let docdir = add_destdir(&docdir, &destdir);
    let bindir = add_destdir(&bindir, &destdir);
    let libdir = add_destdir(&libdir, &destdir);
    let mandir = add_destdir(&mandir, &destdir);

    let empty_dir = build.out.join("tmp/empty_dir");

    t!(fs::create_dir_all(&empty_dir));
    let package_name = if let Some(host) = host {
        format!("{}-{}", pkgname(build, name), host)
    } else {
        pkgname(build, name)
    };

    let mut cmd = Command::new("sh");
    cmd.current_dir(&empty_dir)
        .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
        .arg(format!("--prefix={}", sanitize_sh(&prefix)))
        .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
        .arg(format!("--datadir={}", sanitize_sh(&datadir)))
        .arg(format!("--docdir={}", sanitize_sh(&docdir)))
        .arg(format!("--bindir={}", sanitize_sh(&bindir)))
        .arg(format!("--libdir={}", sanitize_sh(&libdir)))
        .arg(format!("--mandir={}", sanitize_sh(&mandir)))
        .arg("--disable-ldconfig");
    build.run(&mut cmd);
    t!(fs::remove_dir_all(&empty_dir));
}

fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
    let mut ret = match *destdir {
        Some(ref dest) => dest.clone(),
        None => return path.to_path_buf(),
    };
    for part in path.components() {
        match part {
            Component::Normal(s) => ret.push(s),
            _ => {}
        }
    }
    ret
}

macro_rules! install {
    (($sel:ident, $builder:ident, $_config:ident),
       $($name:ident,
       $path:expr,
       $default_cond:expr,
       only_hosts: $only_hosts:expr,
       $run_item:block $(, $c:ident)*;)+) => {
        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub stage: u32,
            pub target: Interned<String>,
            pub host: Interned<String>,
        }

        impl $name {
            #[allow(dead_code)]
            fn should_build(config: &Config) -> bool {
                config.extended && config.tools.as_ref()
                    .map_or(true, |t| t.contains($path))
            }

            #[allow(dead_code)]
            fn should_install(builder: &Builder) -> bool {
                builder.config.tools.as_ref().map_or(false, |t| t.contains($path))
            }
        }

        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = true;
            const ONLY_HOSTS: bool = $only_hosts;
            $(const $c: bool = true;)*

            fn should_run(run: ShouldRun) -> ShouldRun {
                let $_config = &run.builder.config;
                run.path($path).default_condition($default_cond)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    stage: run.builder.top_stage,
                    target: run.target,
                    host: run.builder.build.build,
                });
            }

            fn run($sel, $builder: &Builder) {
                $run_item
            }
        })+
    }
}

install!((self, builder, _config),
    Docs, "src/doc", _config.docs, only_hosts: false, {
        builder.ensure(dist::Docs { stage: self.stage, host: self.target });
        install_docs(builder, self.stage, self.target);
    };
    Std, "src/libstd", true, only_hosts: true, {
        for target in &builder.build.targets {
            builder.ensure(dist::Std {
                compiler: builder.compiler(self.stage, self.host),
                target: *target
            });
            install_std(builder, self.stage, *target);
        }
    };
    Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
        builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
        install_cargo(builder, self.stage, self.target);
    };
    Rls, "rls", Self::should_build(_config), only_hosts: true, {
        if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() ||
            Self::should_install(builder) {
            install_rls(builder, self.stage, self.target);
        } else {
            builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target));
        }
    };
    Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
        if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() ||
            Self::should_install(builder) {
            install_rustfmt(builder, self.stage, self.target);
        } else {
            builder.info(
                &format!("skipping Install Rustfmt stage{} ({})", self.stage, self.target));
        }
    };
    Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
        builder.ensure(dist::Analysis {
            compiler: builder.compiler(self.stage, self.host),
            target: self.target
        });
        install_analysis(builder, self.stage, self.target);
    };
    Rustc, "src/librustc", true, only_hosts: true, {
        builder.ensure(dist::Rustc {
            compiler: builder.compiler(self.stage, self.target),
        });
        install_rustc(builder, self.stage, self.target);
    };
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src {
    pub stage: u32,
}

impl Step for Src {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let config = &run.builder.config;
        let cond = config.extended &&
            config.tools.as_ref().map_or(true, |t| t.contains("src"));
        run.path("src").default_condition(cond)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Src {
            stage: run.builder.top_stage,
        });
    }

    fn run(self, builder: &Builder) {
        builder.ensure(dist::Src);
        install_src(builder, self.stage);
    }
}
<commit_msg>rustbuild: canonicalize prefix `install_sh`<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of the install aspects of the compiler.
//!
//! This module is responsible for installing the standard library,
//! compiler, and documentation.

use std::env;
use std::fs;
use std::path::{Path, PathBuf, Component};
use std::process::Command;

use dist::{self, pkgname, sanitize_sh, tmpdir};

use builder::{Builder, RunConfig, ShouldRun, Step};
use cache::Interned;
use config::Config;

pub fn install_docs(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "docs", "rust-docs", stage, Some(host));
}

pub fn install_std(builder: &Builder, stage: u32, target: Interned<String>) {
    install_sh(builder, "std", "rust-std", stage, Some(target));
}

pub fn install_cargo(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "cargo", "cargo", stage, Some(host));
}

pub fn install_rls(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rls", "rls", stage, Some(host));
}

pub fn install_rustfmt(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rustfmt", "rustfmt", stage, Some(host));
}

pub fn install_analysis(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "analysis", "rust-analysis", stage, Some(host));
}

pub fn install_src(builder: &Builder, stage: u32) {
    install_sh(builder, "src", "rust-src", stage, None);
}
pub fn install_rustc(builder: &Builder, stage: u32, host: Interned<String>) {
    install_sh(builder, "rustc", "rustc", stage, Some(host));
}

fn install_sh(
    builder: &Builder,
    package: &str,
    name: &str,
    stage: u32,
    host: Option<Interned<String>>
) {
    let build = builder.build;
    build.info(&format!("Install {} stage{} ({:?})", package, stage, host));

    let prefix_default = PathBuf::from("/usr/local");
    let sysconfdir_default = PathBuf::from("/etc");
    let datadir_default = PathBuf::from("share");
    let docdir_default = datadir_default.join("doc/rust");
    let bindir_default = PathBuf::from("bin");
    let libdir_default = PathBuf::from("lib");
    let mandir_default = datadir_default.join("man");
    let prefix = build.config.prefix.as_ref().map_or(prefix_default, |p| {
        fs::canonicalize(p).expect(&format!("could not canonicalize {}", p.display()))
    });
    let sysconfdir = build.config.sysconfdir.as_ref().unwrap_or(&sysconfdir_default);
    let datadir = build.config.datadir.as_ref().unwrap_or(&datadir_default);
    let docdir = build.config.docdir.as_ref().unwrap_or(&docdir_default);
    let bindir = build.config.bindir.as_ref().unwrap_or(&bindir_default);
    let libdir = build.config.libdir.as_ref().unwrap_or(&libdir_default);
    let mandir = build.config.mandir.as_ref().unwrap_or(&mandir_default);

    let sysconfdir = prefix.join(sysconfdir);
    let datadir = prefix.join(datadir);
    let docdir = prefix.join(docdir);
    let bindir = prefix.join(bindir);
    let libdir = prefix.join(libdir);
    let mandir = prefix.join(mandir);

    let destdir = env::var_os("DESTDIR").map(PathBuf::from);

    let prefix = add_destdir(&prefix, &destdir);
    let sysconfdir = add_destdir(&sysconfdir, &destdir);
    let datadir = add_destdir(&datadir, &destdir);
    let docdir = add_destdir(&docdir, &destdir);
    let bindir = add_destdir(&bindir, &destdir);
    let libdir = add_destdir(&libdir, &destdir);
    let mandir = add_destdir(&mandir, &destdir);

    let empty_dir = build.out.join("tmp/empty_dir");

    t!(fs::create_dir_all(&empty_dir));
    let package_name = if let Some(host) = host {
        format!("{}-{}", pkgname(build, name), host)
    } else {
        pkgname(build, name)
    };

    let mut cmd = Command::new("sh");
    cmd.current_dir(&empty_dir)
        .arg(sanitize_sh(&tmpdir(build).join(&package_name).join("install.sh")))
        .arg(format!("--prefix={}", sanitize_sh(&prefix)))
        .arg(format!("--sysconfdir={}", sanitize_sh(&sysconfdir)))
        .arg(format!("--datadir={}", sanitize_sh(&datadir)))
        .arg(format!("--docdir={}", sanitize_sh(&docdir)))
        .arg(format!("--bindir={}", sanitize_sh(&bindir)))
        .arg(format!("--libdir={}", sanitize_sh(&libdir)))
        .arg(format!("--mandir={}", sanitize_sh(&mandir)))
        .arg("--disable-ldconfig");
    build.run(&mut cmd);
    t!(fs::remove_dir_all(&empty_dir));
}

fn add_destdir(path: &Path, destdir: &Option<PathBuf>) -> PathBuf {
    let mut ret = match *destdir {
        Some(ref dest) => dest.clone(),
        None => return path.to_path_buf(),
    };
    for part in path.components() {
        match part {
            Component::Normal(s) => ret.push(s),
            _ => {}
        }
    }
    ret
}

macro_rules! install {
    (($sel:ident, $builder:ident, $_config:ident),
       $($name:ident,
       $path:expr,
       $default_cond:expr,
       only_hosts: $only_hosts:expr,
       $run_item:block $(, $c:ident)*;)+) => {
        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub stage: u32,
            pub target: Interned<String>,
            pub host: Interned<String>,
        }

        impl $name {
            #[allow(dead_code)]
            fn should_build(config: &Config) -> bool {
                config.extended && config.tools.as_ref()
                    .map_or(true, |t| t.contains($path))
            }

            #[allow(dead_code)]
            fn should_install(builder: &Builder) -> bool {
                builder.config.tools.as_ref().map_or(false, |t| t.contains($path))
            }
        }

        impl Step for $name {
            type Output = ();
            const DEFAULT: bool = true;
            const ONLY_HOSTS: bool = $only_hosts;
            $(const $c: bool = true;)*

            fn should_run(run: ShouldRun) -> ShouldRun {
                let $_config = &run.builder.config;
                run.path($path).default_condition($default_cond)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    stage: run.builder.top_stage,
                    target: run.target,
                    host: run.builder.build.build,
                });
            }

            fn run($sel, $builder: &Builder) {
                $run_item
            }
        })+
    }
}

install!((self, builder, _config),
    Docs, "src/doc", _config.docs, only_hosts: false, {
        builder.ensure(dist::Docs { stage: self.stage, host: self.target });
        install_docs(builder, self.stage, self.target);
    };
    Std, "src/libstd", true, only_hosts: true, {
        for target in &builder.build.targets {
            builder.ensure(dist::Std {
                compiler: builder.compiler(self.stage, self.host),
                target: *target
            });
            install_std(builder, self.stage, *target);
        }
    };
    Cargo, "cargo", Self::should_build(_config), only_hosts: true, {
        builder.ensure(dist::Cargo { stage: self.stage, target: self.target });
        install_cargo(builder, self.stage, self.target);
    };
    Rls, "rls", Self::should_build(_config), only_hosts: true, {
        if builder.ensure(dist::Rls { stage: self.stage, target: self.target }).is_some() ||
            Self::should_install(builder) {
            install_rls(builder, self.stage, self.target);
        } else {
            builder.info(&format!("skipping Install RLS stage{} ({})", self.stage, self.target));
        }
    };
    Rustfmt, "rustfmt", Self::should_build(_config), only_hosts: true, {
        if builder.ensure(dist::Rustfmt { stage: self.stage, target: self.target }).is_some() ||
            Self::should_install(builder) {
            install_rustfmt(builder, self.stage, self.target);
        } else {
            builder.info(
                &format!("skipping Install Rustfmt stage{} ({})", self.stage, self.target));
        }
    };
    Analysis, "analysis", Self::should_build(_config), only_hosts: false, {
        builder.ensure(dist::Analysis {
            compiler: builder.compiler(self.stage, self.host),
            target: self.target
        });
        install_analysis(builder, self.stage, self.target);
    };
    Rustc, "src/librustc", true, only_hosts: true, {
        builder.ensure(dist::Rustc {
            compiler: builder.compiler(self.stage, self.target),
        });
        install_rustc(builder, self.stage, self.target);
    };
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Src {
    pub stage: u32,
}

impl Step for Src {
    type Output = ();
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let config = &run.builder.config;
        let cond = config.extended &&
            config.tools.as_ref().map_or(true, |t| t.contains("src"));
        run.path("src").default_condition(cond)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Src {
            stage: run.builder.top_stage,
        });
    }

    fn run(self, builder: &Builder) {
        builder.ensure(dist::Src);
        install_src(builder, self.stage);
    }
}
<|endoftext|>


<commit_before>const BOARD_WIDTH : usize = 3;
const BOARD_HEIGHT : usize = 3;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct GameState{
    board : [[Color; BOARD_WIDTH]; BOARD_HEIGHT],
    pub player : Color
}

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

#[derive(Debug, Copy, Clone)]
pub struct Move {
    pub color : Color,
    pub x: usize,
    pub y: usize
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum End{
    Ongoing,
    Victory(Color),
    Tie
}

impl Move{
    pub fn new(nx : usize, ny : usize, ncolor : Color) -> Self{
        Move{
            color : ncolor,
            x: nx,
            y: ny
        }
    }

    pub fn white_new(nx : usize, ny : usize) -> Self{
        Move::new(nx, ny, Color::White)
    }

    pub fn black_new(nx : usize, ny : usize) -> Self{
        Move::new(nx, ny, Color::Black)
    }

    pub fn from_int(nx : i32, ny : i32, ncolor : Color) -> Self{
        Move{
            color : Color::White,
            x : nx as usize,
            y : ny as usize
        }
    }

    fn in_bounds(&self) -> bool{
        (self.x <= BOARD_WIDTH && self.x  >= 0 && self.y <= BOARD_HEIGHT && self.y >= 0)
    }
}

impl GameState{
    pub fn new() -> Self{
        GameState{
            board: [[Color::Empty, Color::Empty, Color::Empty],
                    [Color::Empty, Color::Empty, Color::Empty],
                    [Color::Empty, Color::Empty, Color::Empty]],
            player : Color::White
        }
    }

    pub fn place(&self, game_move : &Move) -> Self{
        let mut copy = self.clone();
        copy.board[game_move.y][game_move.x] = game_move.color;
        let next_player =
        match game_move.color{
            Color::White => Color::Black,
            Color::Black => Color::White,
            _ => Color::White
        };

        copy.player = next_player;
        return copy;
    }

    pub fn legal(&self, game_move: Move) -> bool{
        if !game_move.in_bounds(){
            return false;
        }

        let tile = self.board[game_move.y][game_move.x];
        if tile != Color::Empty{
            return false;
        }
        else{
            return true;
        }
    }

    pub fn legal_moves(&self, color : Color) -> Vec<Move>{
        let mut moves = Vec::new();
        for y in 0..BOARD_HEIGHT{
            for x in 0..BOARD_WIDTH{
                let potential_move = Move::new(x, y, color);
                if self.legal(potential_move){
                    moves.push(potential_move);
                }
            }
        }
        return moves;
    }

    pub fn linear_match(&self, start_x : i32, start_y : i32, stepX : i32, stepY : i32, color : Color) -> bool{
        for i in 0..3{
            let x = (start_x + i * stepX) as usize;
            let y = (start_y + i * stepY) as usize;
            let value = self.board[y][x];
            if value != color{
                return false;
            }
        }
        return true;
    }

    fn color_win(&self, color : Color) -> bool{

        if self.linear_match(0, 0, 1, 1, Color::White) || self.linear_match(2, 0, -1, 1, color){
            return true;
        }

        for i in 0..3{
            //rows
            if self.linear_match(0, i, 1, 0, color){
                return true;
            }

            //column
            if self.linear_match(i, 0, 0, 1, color){
                return true;
            }
        }

        return false;

    }

    pub fn win(&self) -> End{
        if(self.color_win(Color::White)){
            return End::Victory(Color::White);
        }
        if(self.color_win(Color::Black)){
            return End::Victory(Color::Black);
        }
        let mut no_empty = true;
        for column in self.board.iter(){
            for &tile in column{
                if tile == Color::Empty{
                    no_empty = false;
                }
            }
        }
        if no_empty {
            return End::Tie;
        }
        return End::Ongoing;
    }

    pub fn print(&self) -> String{
        let mut string = String::from("\n");
        for column in self.board.iter(){
            for tile in column{
                string.push_str("|");
                let tile_str =
                    match tile {
                        &Color::Empty => " ",
                        &Color::White => "O",
                        &Color::Black => "X"
                    };
                string.push_str(tile_str);
                string.push_str("|")
            }
            string.push_str("\n");
        }
        return string;
    }
}

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

    #[test]
    fn legality(){
        let board = GameState::new();
        assert_eq!(board.legal(Move::black_new(4, 4)), false);
        assert_eq!(board.legal(Move::white_new(0, 0)), true);

        let new_board = board.place(Move::white_new(0, 0));
        assert_eq!(new_board.legal(Move::black_new(0, 0)), false);
    }

    fn white_victory(end : End) -> bool{
        match end{
            End::Victory(Color::White) => true,
            _ => false
        }
    }

    #[test]
    fn white_win(){
        let mut board = GameState::new();

        board = board.place(Move::white_new(0, 0));
        board = board.place(Move::white_new(1, 0));
        board = board.place(Move::white_new(2, 0));

        assert!(white_victory(board.win()));

        board = GameState::new();

        board = board.place(Move::white_new(0, 0));
        board = board.place(Move::white_new(0, 1));
        board = board.place(Move::white_new(0, 2));

        assert!(white_victory(board.win()));

        board = GameState::new();

        board = board.place(Move::white_new(0, 2));
        board = board.place(Move::white_new(1, 2));
        board = board.place(Move::white_new(2, 2));

        assert!(white_victory(board.win()));

        board = GameState::new();

        board = board.place(Move::white_new(2,0));
        board = board.place(Move::white_new(1,1));
        board = board.place(Move::white_new(0,2));

        assert!(white_victory(board.win()));
    }

    #[test]
    #[should_panic]
    fn white_not_win(){

        let mut board = GameState::new();
        board = board.place(Move::white_new(0, 0));
        board = board.place(Move::white_new(1, 0));
        println!("{}", board.print());
        assert!(white_victory(board.win()));
    }

    #[test]
    fn tie(){
        let mut board = GameState::new();
        board = board.place(Move::black_new(0, 0));
        board = board.place(Move::white_new(1, 0));
        board = board.place(Move::black_new(2, 0));

        board = board.place(Move::white_new(0, 1));
        board = board.place(Move::white_new(1, 1));
        board = board.place(Move::black_new(2, 1));

        board = board.place(Move::white_new(0, 2));
        board = board.place(Move::black_new(1, 2));
        board = board.place(Move::white_new(2, 2));

        let bwin = board.win();
        let win =
        match bwin{
            End::Tie => true,
            _ => false
        };

        assert!(win);
    }
}
<commit_msg>quick fix<commit_after>const BOARD_WIDTH : usize = 3;
const BOARD_HEIGHT : usize = 3;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct GameState{
    board : [[Color; BOARD_WIDTH]; BOARD_HEIGHT],
    pub player : Color
}

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

#[derive(Debug, Copy, Clone)]
pub struct Move {
    pub color : Color,
    pub x: usize,
    pub y: usize
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub enum End{
    Ongoing,
    Victory(Color),
    Tie
}

impl Move{
    pub fn new(nx : usize, ny : usize, ncolor : Color) -> Self{
        Move{
            color : ncolor,
            x: nx,
            y: ny
        }
    }

    pub fn white_new(nx : usize, ny : usize) -> Self{
        Move::new(nx, ny, Color::White)
    }

    pub fn black_new(nx : usize, ny : usize) -> Self{
        Move::new(nx, ny, Color::Black)
    }

    pub fn from_int(nx : i32, ny : i32, ncolor : Color) -> Self{
        Move{
            color : Color::White,
            x : nx as usize,
            y : ny as usize
        }
    }

    fn in_bounds(&self) -> bool{
        (self.x <= BOARD_WIDTH && self.x  >= 0 && self.y <= BOARD_HEIGHT && self.y >= 0)
    }
}

impl GameState{
    pub fn new() -> Self{
        GameState{
            board: [[Color::Empty, Color::Empty, Color::Empty],
                    [Color::Empty, Color::Empty, Color::Empty],
                    [Color::Empty, Color::Empty, Color::Empty]],
            player : Color::White
        }
    }

    pub fn place(&self, game_move : &Move) -> Self{
        let mut copy = self.clone();
        copy.board[game_move.y][game_move.x] = game_move.color;
        let next_player =
        match game_move.color{
            Color::White => Color::Black,
            Color::Black => Color::White,
            _ => Color::White
        };

        copy.player = next_player;
        return copy;
    }

    pub fn legal(&self, game_move: Move) -> bool{
        if !game_move.in_bounds(){
            return false;
        }

        let tile = self.board[game_move.y][game_move.x];
        if tile != Color::Empty{
            return false;
        }
        else{
            return true;
        }
    }

    pub fn legal_moves(&self, color : Color) -> Vec<Move>{
        let mut moves = Vec::new();
        for y in 0..BOARD_HEIGHT{
            for x in 0..BOARD_WIDTH{
                let potential_move = Move::new(x, y, color);
                if self.legal(potential_move){
                    moves.push(potential_move);
                }
            }
        }
        return moves;
    }

    pub fn linear_match(&self, start_x : i32, start_y : i32, stepX : i32, stepY : i32, color : Color) -> bool{
        for i in 0..3{
            let x = (start_x + i * stepX) as usize;
            let y = (start_y + i * stepY) as usize;
            let value = self.board[y][x];
            if value != color{
                return false;
            }
        }
        return true;
    }

    fn color_win(&self, color : Color) -> bool{

        if self.linear_match(0, 0, 1, 1, color) || self.linear_match(2, 0, -1, 1, color){
            return true;
        }

        for i in 0..3{
            //rows
            if self.linear_match(0, i, 1, 0, color){
                return true;
            }

            //column
            if self.linear_match(i, 0, 0, 1, color){
                return true;
            }
        }

        return false;

    }

    pub fn win(&self) -> End{
        if(self.color_win(Color::White)){
            return End::Victory(Color::White);
        }
        if(self.color_win(Color::Black)){
            return End::Victory(Color::Black);
        }
        let mut no_empty = true;
        for column in self.board.iter(){
            for &tile in column{
                if tile == Color::Empty{
                    no_empty = false;
                }
            }
        }
        if no_empty {
            return End::Tie;
        }
        return End::Ongoing;
    }

    pub fn print(&self) -> String{
        let mut string = String::from("\n");
        for column in self.board.iter(){
            for tile in column{
                string.push_str("|");
                let tile_str =
                    match tile {
                        &Color::Empty => " ",
                        &Color::White => "O",
                        &Color::Black => "X"
                    };
                string.push_str(tile_str);
                string.push_str("|")
            }
            string.push_str("\n");
        }
        return string;
    }
}

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

    #[test]
    fn legality(){
        let board = GameState::new();
        assert_eq!(board.legal(Move::black_new(4, 4)), false);
        assert_eq!(board.legal(Move::white_new(0, 0)), true);

        let new_board = board.place(Move::white_new(0, 0));
        assert_eq!(new_board.legal(Move::black_new(0, 0)), false);
    }

    fn white_victory(end : End) -> bool{
        match end{
            End::Victory(Color::White) => true,
            _ => false
        }
    }

    #[test]
    fn white_win(){
        let mut board = GameState::new();

        board = board.place(Move::white_new(0, 0));
        board = board.place(Move::white_new(1, 0));
        board = board.place(Move::white_new(2, 0));

        assert!(white_victory(board.win()));

        board = GameState::new();

        board = board.place(Move::white_new(0, 0));
        board = board.place(Move::white_new(0, 1));
        board = board.place(Move::white_new(0, 2));

        assert!(white_victory(board.win()));

        board = GameState::new();

        board = board.place(Move::white_new(0, 2));
        board = board.place(Move::white_new(1, 2));
        board = board.place(Move::white_new(2, 2));

        assert!(white_victory(board.win()));

        board = GameState::new();

        board = board.place(Move::white_new(2,0));
        board = board.place(Move::white_new(1,1));
        board = board.place(Move::white_new(0,2));

        assert!(white_victory(board.win()));
    }

    #[test]
    #[should_panic]
    fn white_not_win(){

        let mut board = GameState::new();
        board = board.place(Move::white_new(0, 0));
        board = board.place(Move::white_new(1, 0));
        println!("{}", board.print());
        assert!(white_victory(board.win()));
    }

    #[test]
    fn tie(){
        let mut board = GameState::new();
        board = board.place(Move::black_new(0, 0));
        board = board.place(Move::white_new(1, 0));
        board = board.place(Move::black_new(2, 0));

        board = board.place(Move::white_new(0, 1));
        board = board.place(Move::white_new(1, 1));
        board = board.place(Move::black_new(2, 1));

        board = board.place(Move::white_new(0, 2));
        board = board.place(Move::black_new(1, 2));
        board = board.place(Move::white_new(2, 2));

        let bwin = board.win();
        let win =
        match bwin{
            End::Tie => true,
            _ => false
        };

        assert!(win);
    }
}
<|endoftext|>


<commit_before>use super::Blob;
use failure::Error;
use futures::Future;
use log::{error, warn};
use rusoto_core::region::Region;
use rusoto_credential::DefaultCredentialsProvider;
use rusoto_s3::{GetObjectRequest, PutObjectRequest, S3Client, S3};
use std::convert::TryInto;
use std::io::Read;
use time::Timespec;
use tokio::runtime::Runtime;

pub(crate) struct S3Backend<'a> {
    client: S3Client,
    bucket: &'a str,
    runtime: Runtime,
}

impl<'a> S3Backend<'a> {
    pub(crate) fn new(client: S3Client, bucket: &'a str) -> Self {
        Self {
            client,
            bucket,
            runtime: Runtime::new().unwrap(),
        }
    }

    pub(super) fn get(&self, path: &str) -> Result<Blob, Error> {
        let res = self
            .client
            .get_object(GetObjectRequest {
                bucket: self.bucket.to_string(),
                key: path.into(),
                ..Default::default()
            })
            .sync()?;

        let mut b = res.body.unwrap().into_blocking_read();
        let mut content = Vec::with_capacity(
            res.content_length
                .and_then(|l| l.try_into().ok())
                .unwrap_or(0),
        );
        b.read_to_end(&mut content).unwrap();

        let date_updated = parse_timespec(&res.last_modified.unwrap())?;

        Ok(Blob {
            path: path.into(),
            mime: res.content_type.unwrap(),
            date_updated,
            content,
        })
    }

    pub(super) fn store_batch(&mut self, batch: &[Blob]) -> Result<(), Error> {
        use futures::stream::FuturesUnordered;
        use futures::stream::Stream;
        let mut attempts = 0;

        loop {
            let mut futures = FuturesUnordered::new();
            for blob in batch {
                futures.push(
                    self.client
                        .put_object(PutObjectRequest {
                            bucket: self.bucket.to_string(),
                            key: blob.path.clone(),
                            body: Some(blob.content.clone().into()),
                            content_type: Some(blob.mime.clone()),
                            ..Default::default()
                        })
                        .inspect(|_| {
                            crate::web::metrics::UPLOADED_FILES_TOTAL.inc_by(1);
                        }),
                );
            }
            attempts += 1;

            match self.runtime.block_on(futures.collect()) {
                // this batch was successful, start another batch if there are still more files
                Ok(_) => break,
                Err(err) => {
                    error!("failed to upload to s3: {:?}", err);
                    // if a futures error occurs, retry the batch
                    if attempts > 2 {
                        panic!("failed to upload 3 times, exiting");
                    }
                }
            }
        }
        Ok(())
    }
}

// public for testing
pub(crate) const TIME_FMT: &str = "%a, %d %b %Y %H:%M:%S %Z";

fn parse_timespec(raw: &str) -> Result<Timespec, Error> {
    Ok(time::strptime(raw, TIME_FMT)?.to_timespec())
}

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

    fn assert_s3_404(env: &TestEnvironment, path: &'static str) {
        use rusoto_core::RusotoError;
        use rusoto_s3::GetObjectError;

        let s3 = env.s3().not_found(path);
        let backend = S3Backend::new(s3.client, s3.bucket);
        let err = backend.get(path).unwrap_err();
        let status = match err
            .downcast_ref::<RusotoError<GetObjectError>>()
            .expect("wanted GetObject")
        {
            RusotoError::Unknown(http) => http.status,
            _ => panic!("wrong error"),
        };
        assert_eq!(status, 404);
    }

    #[test]
    fn test_parse_timespec() {
        crate::test::wrapper(|_| {
            // Test valid conversions
            assert_eq!(
                parse_timespec("Thu, 1 Jan 1970 00:00:00 GMT")?,
                Timespec::new(0, 0)
            );
            assert_eq!(
                parse_timespec("Mon, 16 Apr 2018 04:33:50 GMT")?,
                Timespec::new(1523853230, 0)
            );

            // Test invalid conversion
            assert!(parse_timespec("foo").is_err());

            Ok(())
        })
    }

    #[test]
    fn test_path_get() {
        crate::test::wrapper(|env| {
            let blob = Blob {
                path: "dir/foo.txt".into(),
                mime: "text/plain".into(),
                date_updated: Timespec::new(42, 0),
                content: "Hello world!".into(),
            };

            // Add a test file to the database
            let s3 = env.s3().upload(blob.clone());

            let backend = S3Backend::new(s3.client, &s3.bucket);

            // Test that the proper file was returned
            assert_eq!(blob, backend.get("dir/foo.txt")?);

            // Test that other files are not returned
            assert_s3_404(&env, "dir/bar.txt");
            assert_s3_404(&env, "foo.txt");

            Ok(())
        });
    }
}

pub(crate) static S3_BUCKET_NAME: &str = "rust-docs-rs";

pub(crate) fn s3_client() -> Option<S3Client> {
    // If AWS keys aren't configured, then presume we should use the DB exclusively
    // for file storage.
    if std::env::var_os("AWS_ACCESS_KEY_ID").is_none() && std::env::var_os("FORCE_S3").is_none() {
        return None;
    }
    let creds = match DefaultCredentialsProvider::new() {
        Ok(creds) => creds,
        Err(err) => {
            warn!("failed to retrieve AWS credentials: {}", err);
            return None;
        }
    };
    Some(S3Client::new_with(
        rusoto_core::request::HttpClient::new().unwrap(),
        creds,
        std::env::var("S3_ENDPOINT")
            .ok()
            .map(|e| Region::Custom {
                name: std::env::var("S3_REGION").unwrap_or_else(|_| "us-west-1".to_owned()),
                endpoint: e,
            })
            .unwrap_or(Region::UsWest1),
    ))
}
<commit_msg>Don't hold all PutObjectOutputs in memory<commit_after>use super::Blob;
use failure::Error;
use futures::Future;
use log::{error, warn};
use rusoto_core::region::Region;
use rusoto_credential::DefaultCredentialsProvider;
use rusoto_s3::{GetObjectRequest, PutObjectRequest, S3Client, S3};
use std::convert::TryInto;
use std::io::Read;
use time::Timespec;
use tokio::runtime::Runtime;

pub(crate) struct S3Backend<'a> {
    client: S3Client,
    bucket: &'a str,
    runtime: Runtime,
}

impl<'a> S3Backend<'a> {
    pub(crate) fn new(client: S3Client, bucket: &'a str) -> Self {
        Self {
            client,
            bucket,
            runtime: Runtime::new().unwrap(),
        }
    }

    pub(super) fn get(&self, path: &str) -> Result<Blob, Error> {
        let res = self
            .client
            .get_object(GetObjectRequest {
                bucket: self.bucket.to_string(),
                key: path.into(),
                ..Default::default()
            })
            .sync()?;

        let mut b = res.body.unwrap().into_blocking_read();
        let mut content = Vec::with_capacity(
            res.content_length
                .and_then(|l| l.try_into().ok())
                .unwrap_or(0),
        );
        b.read_to_end(&mut content).unwrap();

        let date_updated = parse_timespec(&res.last_modified.unwrap())?;

        Ok(Blob {
            path: path.into(),
            mime: res.content_type.unwrap(),
            date_updated,
            content,
        })
    }

    pub(super) fn store_batch(&mut self, batch: &[Blob]) -> Result<(), Error> {
        use futures::stream::FuturesUnordered;
        use futures::stream::Stream;
        let mut attempts = 0;

        loop {
            let mut futures = FuturesUnordered::new();
            for blob in batch {
                futures.push(
                    self.client
                        .put_object(PutObjectRequest {
                            bucket: self.bucket.to_string(),
                            key: blob.path.clone(),
                            body: Some(blob.content.clone().into()),
                            content_type: Some(blob.mime.clone()),
                            ..Default::default()
                        })
                        .inspect(|_| {
                            crate::web::metrics::UPLOADED_FILES_TOTAL.inc_by(1);
                        }),
                );
            }
            attempts += 1;

            match self.runtime.block_on(futures.map(drop).collect()) {
                // this batch was successful, start another batch if there are still more files
                Ok(_) => break,
                Err(err) => {
                    error!("failed to upload to s3: {:?}", err);
                    // if a futures error occurs, retry the batch
                    if attempts > 2 {
                        panic!("failed to upload 3 times, exiting");
                    }
                }
            }
        }
        Ok(())
    }
}

// public for testing
pub(crate) const TIME_FMT: &str = "%a, %d %b %Y %H:%M:%S %Z";

fn parse_timespec(raw: &str) -> Result<Timespec, Error> {
    Ok(time::strptime(raw, TIME_FMT)?.to_timespec())
}

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

    fn assert_s3_404(env: &TestEnvironment, path: &'static str) {
        use rusoto_core::RusotoError;
        use rusoto_s3::GetObjectError;

        let s3 = env.s3().not_found(path);
        let backend = S3Backend::new(s3.client, s3.bucket);
        let err = backend.get(path).unwrap_err();
        let status = match err
            .downcast_ref::<RusotoError<GetObjectError>>()
            .expect("wanted GetObject")
        {
            RusotoError::Unknown(http) => http.status,
            _ => panic!("wrong error"),
        };
        assert_eq!(status, 404);
    }

    #[test]
    fn test_parse_timespec() {
        crate::test::wrapper(|_| {
            // Test valid conversions
            assert_eq!(
                parse_timespec("Thu, 1 Jan 1970 00:00:00 GMT")?,
                Timespec::new(0, 0)
            );
            assert_eq!(
                parse_timespec("Mon, 16 Apr 2018 04:33:50 GMT")?,
                Timespec::new(1523853230, 0)
            );

            // Test invalid conversion
            assert!(parse_timespec("foo").is_err());

            Ok(())
        })
    }

    #[test]
    fn test_path_get() {
        crate::test::wrapper(|env| {
            let blob = Blob {
                path: "dir/foo.txt".into(),
                mime: "text/plain".into(),
                date_updated: Timespec::new(42, 0),
                content: "Hello world!".into(),
            };

            // Add a test file to the database
            let s3 = env.s3().upload(blob.clone());

            let backend = S3Backend::new(s3.client, &s3.bucket);

            // Test that the proper file was returned
            assert_eq!(blob, backend.get("dir/foo.txt")?);

            // Test that other files are not returned
            assert_s3_404(&env, "dir/bar.txt");
            assert_s3_404(&env, "foo.txt");

            Ok(())
        });
    }
}

pub(crate) static S3_BUCKET_NAME: &str = "rust-docs-rs";

pub(crate) fn s3_client() -> Option<S3Client> {
    // If AWS keys aren't configured, then presume we should use the DB exclusively
    // for file storage.
    if std::env::var_os("AWS_ACCESS_KEY_ID").is_none() && std::env::var_os("FORCE_S3").is_none() {
        return None;
    }
    let creds = match DefaultCredentialsProvider::new() {
        Ok(creds) => creds,
        Err(err) => {
            warn!("failed to retrieve AWS credentials: {}", err);
            return None;
        }
    };
    Some(S3Client::new_with(
        rusoto_core::request::HttpClient::new().unwrap(),
        creds,
        std::env::var("S3_ENDPOINT")
            .ok()
            .map(|e| Region::Custom {
                name: std::env::var("S3_REGION").unwrap_or_else(|_| "us-west-1".to_owned()),
                endpoint: e,
            })
            .unwrap_or(Region::UsWest1),
    ))
}
<|endoftext|>


<commit_before>pub mod ffi;

use std::ptr;

use super::DynLibrary;
use super::utils::fn_ptr::FnPtrLibrary;

pub struct FreeType {
   pub dyn_lib: DynLibrary,
   pub ft_lib: ffi::FT_Library,
}

impl FreeType {
   pub fn new() -> Self {
      let dyn_lib = FreeType::load_library();

      unsafe {
         ffi::load_functions(&dyn_lib);

         let mut ft_lib: ffi::FT_Library = ptr::null_mut();

         ffi::FT_Init_FreeType(&mut ft_lib);

         FreeType {
            ft_lib: ft_lib,
            dyn_lib: dyn_lib,
         }
      }
   }

   #[inline]
   #[cfg(target_os = "linux")]
   pub fn load_library() -> DynLibrary {
      DynLibrary::open("libfreetype.so.6").unwrap()
   }

   #[inline]
   #[cfg(target_os = "windows")]
   pub fn load_library() -> DynLibrary {
      DynLibrary::open("freetype.dll").unwrap()
   }
}

impl Drop for FreeType {
   fn drop (&mut self) {
      unsafe {
         ffi::FT_Done_FreeType(self.ft_lib);
      }
   }
}
<commit_msg>Character outlines as polygons<commit_after>pub mod ffi;

use std::os::raw::{c_void, c_int};

use std::ptr;
use std::ffi::CString;

use data::FloatPoint;
use geom::point::Point;

use super::DynLibrary;
use super::utils::fn_ptr::FnPtrLibrary;

pub struct FreeType {
   pub dyn_lib: DynLibrary,
   pub ft_lib: ffi::FT_Library,
}

impl FreeType {
   pub fn new() -> Self {
      let dyn_lib = FreeType::load_library();

      unsafe {
         ffi::load_functions(&dyn_lib);

         let mut ft_lib: ffi::FT_Library = ptr::null_mut();

         ffi::FT_Init_FreeType(&mut ft_lib);

         FreeType {
            ft_lib: ft_lib,
            dyn_lib: dyn_lib,
         }
      }
   }

   #[inline]
   #[cfg(target_os = "linux")]
   pub fn load_library() -> DynLibrary {
      DynLibrary::open("libfreetype.so.6").unwrap()
   }

   #[inline]
   #[cfg(target_os = "windows")]
   pub fn load_library() -> DynLibrary {
      DynLibrary::open("freetype.dll").unwrap()
   }

   pub fn load_face(&self, name: &str) -> Face {
      let cname = CString::new(name).unwrap();

      let mut ft_face: ffi::FT_Face = ptr::null_mut();

      unsafe {
         ffi::FT_New_Face(self.ft_lib, cname.as_ptr() as *const _, 0, &mut ft_face);
      }

      Face::new(ft_face)
   }
}

impl Drop for FreeType {
   fn drop (&mut self) {
      unsafe {
         ffi::FT_Done_FreeType(self.ft_lib);
      }
   }
}

unsafe extern "C" fn move_to(
   to: *const ffi::FT_Vector,
   user: *mut c_void
) -> c_int {
   let points: &mut CharPoints = &mut *(user as *mut CharPoints);

   points.move_to(pt(to));

   0
}

unsafe extern "C" fn line_to(
   to: *const ffi::FT_Vector,
   user: *mut c_void
) -> c_int {
   let points: &mut CharPoints = &mut *(user as *mut CharPoints);

   points.line_to(pt(to));

   0
}

unsafe extern "C" fn conic_to(
   ctrl: *const ffi::FT_Vector,
   to: *const ffi::FT_Vector,
   user: *mut c_void
) -> c_int {
   let points: &mut CharPoints = &mut *(user as *mut CharPoints);

   points.conic_to(pt(ctrl), pt(to));

   0
}

unsafe extern "C" fn cubic_to(
   ctrl1: *const ffi::FT_Vector,
   ctrl2: *const ffi::FT_Vector,
   to: *const ffi::FT_Vector,
   user: *mut c_void
) -> c_int {
   let points: &mut CharPoints = &mut *(user as *mut CharPoints);

   points.cubic_to(pt(ctrl1), pt(ctrl2), pt(to));

   0
}

unsafe fn pt(ft_vec: *const ffi::FT_Vector) -> FloatPoint {
   FloatPoint::new((*ft_vec).x as f64, (*ft_vec).y as f64)
}

#[derive(Debug)]
struct CharPoints {
   points: Vec<Vec<FloatPoint>>,
   steps: usize,
}

impl CharPoints {
   pub fn new(steps: usize) -> Self {
      CharPoints {
         points: Vec::new(),
         steps: steps,
      }
   }

   #[inline]
   pub fn move_to(&mut self, to: FloatPoint) {
      self.points.push(Vec::new());

      self.push(to);
   }

   #[inline]
   pub fn line_to(&mut self, to: FloatPoint) {
      self.push(to);
   }

   #[inline]
   pub fn conic_to(&mut self, ctrl: FloatPoint, to: FloatPoint) {
      let from = self.last();

      for i in 1..self.steps {
         let t2 = i as f64 / self.steps as f64;
         let t1 = 1. - t2;

         let u = on_segment(from, ctrl, t1, t2);
         let v = on_segment(ctrl, to, t1, t2);

         let f = on_segment(u, v, t1, t2);

         self.push(f);
      }

      self.push(to);
   }

   #[inline]
   pub fn cubic_to(&mut self, ctrl1: FloatPoint, ctrl2: FloatPoint, to: FloatPoint) {
      let from = self.last();

      for i in 1..self.steps {
         let t2 = i as f64 / self.steps as f64;
         let t1 = 1. - t2;

         let u = on_segment(from, ctrl1, t1, t2);
         let v = on_segment(ctrl1, ctrl2, t1, t2);
         let w = on_segment(ctrl2, to, t1, t2);

         let m = on_segment(u, v, t1, t2);
         let n = on_segment(v, w, t1, t2);

         let f = on_segment(m, n, t1, t2);

         self.push(f);
      }

      self.push(to);
   }

   #[inline]
   fn push(&mut self, point: FloatPoint) {
      if let Some(last) = self.points.last_mut() {
         last.push(point);
      }
   }

   #[inline]
   fn last(&mut self) -> FloatPoint {
      if let Some(list) = self.points.last() {
         if let Some(last) = list.last() {
            return *last;
         }
      }

      panic!("No points");
   }

   #[inline]
   fn as_int_points(&self) -> Vec<Vec<Point>> {
      let mut outer = Vec::new();

      for contour in &self.points {
         let mut inner = Vec::new();

         for point in contour {
            let x = point.x.round() as i64;
            let y = -(point.y.round() as i64);

            inner.push(Point::new(x, y));
         }

         outer.push(inner);
      }

      outer
   }
}

#[inline]
fn on_segment(pt1: FloatPoint, pt2: FloatPoint, t1: f64, t2: f64) -> FloatPoint {
   let x = t1 * pt1.x + t2 * pt2.x;
   let y = t1 * pt1.y + t2 * pt2.y;

   FloatPoint::new(x, y)
}

pub struct Face {
   pub ft_face: ffi::FT_Face
}

impl Face {
   pub fn new(ft_face: ffi::FT_Face) -> Self {
      Face {
         ft_face: ft_face,
      }
   }

   pub fn set_size(&self, height: i64) {
      unsafe {
         ffi::FT_Set_Pixel_Sizes(self.ft_face, 0, height as ffi::FT_UInt);
      }
   }

   pub fn char_points(&self, ch: char, steps: usize) -> Vec<Vec<Point>> {
      let funcs = ffi::FT_Outline_Funcs {
         move_to: Some(move_to),
         line_to: Some(line_to),
         conic_to: Some(conic_to),
         cubic_to: Some(cubic_to),
         shift: 0,
         delta: 0,
      };

      let mut points: Box<CharPoints> = Box::new(CharPoints::new(steps));

      unsafe {
         ffi::FT_Load_Char(self.ft_face, ch as u32, ffi::FT_LOAD_DEFAULT);

         let slot: ffi::FT_GlyphSlot = (*self.ft_face).glyph as ffi::FT_GlyphSlot;

         ffi::FT_Outline_Decompose(
            &mut (*slot).outline,
            &funcs,
            &mut *points as *mut _ as *mut c_void
         );
      }

      points.as_int_points()
   }
}

<|endoftext|>


<commit_before>//! Render input types and related functions.

use glsl::syntax::{
  ExternalDeclaration, StructFieldSpecifier, TypeName, TypeSpecifier, TypeSpecifierNonArray
};
use serde_derive::{Deserialize, Serialize};

use crate::render::type_channel::TypeChan;

/// Input type.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan),
}

/// Role of an input. It can either be a functional input, like a vertex’s attribute, or a constant
/// parameter.
///
/// This is not really important when writing a shader code but becomes important when writing the
/// render pipeline.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Role {
  Pipeline,
  Parameter,
  #[serde(rename = "built-in")]
  BuiltIn(BuiltIn)
}

/// Associate an input type to a given type.
pub trait InputType {
  const INPUT: Type;
}

/// Render inputs.
pub trait InputTypes {
  /// Get the types of the input.
  fn ty() -> &'static [Type];
}

impl<A> InputTypes for A where A: InputType {
  fn ty() -> &'static [Type] {
    &[A::INPUT]
  }
}

macro_rules! multi_input_type_impl {
  ($($t:tt),*) => {
    impl<$($t),*> InputTypes for ($($t),*) where $($t: InputType),* {
      fn ty() -> &'static [Type] {
        &[$($t::INPUT),*]
      }
    }
  }
}

multi_input_type_impl!(A, B);
multi_input_type_impl!(A, B, C);
multi_input_type_impl!(A, B, C, D);
multi_input_type_impl!(A, B, C, D, E);
multi_input_type_impl!(A, B, C, D, E, F);
multi_input_type_impl!(A, B, C, D, E, F, G);
multi_input_type_impl!(A, B, C, D, E, F, G, H);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// Built-ins.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BuiltIn {
  Time,
  FramebufferResolution
}

/// An input.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Input {
  /// Name of the input.
  name: String,
  /// Type of the input.
  #[serde(rename = "type")]
  ty: Type,
}

impl Input {
  /// Create a new input.
  pub fn new<T, N>(name: N) -> Self
  where T: InputType,
        N: Into<String> {
    Input {
      name: name.into(),
      ty: T::INPUT,
    }
  }
}

/// Generate a GLSL structure given a list of inputs.
pub(crate) fn inputs_to_struct_decl<'a, N, I>(
  name: N,
  inputs: I
) -> Option<ExternalDeclaration>
where N: Into<TypeName>,
      I: IntoIterator<Item = &'a Input> {
  ExternalDeclaration::new_struct(name, inputs.into_iter().map(input_to_struct_field))
}

/// Generate a struct field from an input.
fn input_to_struct_field(input: &Input) -> StructFieldSpecifier {
  StructFieldSpecifier::new(input.name.as_str(), glsl_type_from_input_type(&input.ty))
}

/// Generate a GLSL type from a given input type.
fn glsl_type_from_input_type(ty: &Type) -> TypeSpecifier {
  let ty_nonarray = match *ty {
    Type::Int(TypeChan::One) => TypeSpecifierNonArray::Int,
    Type::Int(TypeChan::Two) => TypeSpecifierNonArray::IVec2,
    Type::Int(TypeChan::Three) => TypeSpecifierNonArray::IVec3,
    Type::Int(TypeChan::Four) => TypeSpecifierNonArray::IVec4,
    Type::UInt(TypeChan::One) => TypeSpecifierNonArray::UInt,
    Type::UInt(TypeChan::Two) => TypeSpecifierNonArray::UVec2,
    Type::UInt(TypeChan::Three) => TypeSpecifierNonArray::UVec3,
    Type::UInt(TypeChan::Four) => TypeSpecifierNonArray::UVec4,
    Type::Float(TypeChan::One) => TypeSpecifierNonArray::Float,
    Type::Float(TypeChan::Two) => TypeSpecifierNonArray::Vec2,
    Type::Float(TypeChan::Three) => TypeSpecifierNonArray::Vec3,
    Type::Float(TypeChan::Four) => TypeSpecifierNonArray::Vec4,
    Type::Bool(TypeChan::One) => TypeSpecifierNonArray::Bool,
    Type::Bool(TypeChan::Two) => TypeSpecifierNonArray::BVec2,
    Type::Bool(TypeChan::Three) => TypeSpecifierNonArray::BVec3,
    Type::Bool(TypeChan::Four) => TypeSpecifierNonArray::BVec4,
  };

  TypeSpecifier::new(ty_nonarray)
}

#[cfg(test)]
mod tests {
  use glsl::syntax::TranslationUnit;
  use glsl_quasiquote::glsl;
  use serde_json::{from_str, to_string};
  use std::iter;

  use crate::render::types::*;
  use super::*;

  #[test]
  fn serialize_type() {
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RGF::INPUT).unwrap(), r#"{"float":2}"#);
    assert_eq!(to_string(&RGBF::INPUT).unwrap(), r#"{"float":3}"#);
    assert_eq!(to_string(&RGBAF::INPUT).unwrap(), r#"{"float":4}"#);
    assert_eq!(to_string(&RI::INPUT).unwrap(), r#"{"int":1}"#);
    assert_eq!(to_string(&RGI::INPUT).unwrap(), r#"{"int":2}"#);
    assert_eq!(to_string(&RGBI::INPUT).unwrap(), r#"{"int":3}"#);
    assert_eq!(to_string(&RGBAI::INPUT).unwrap(), r#"{"int":4}"#);
    assert_eq!(to_string(&RU::INPUT).unwrap(), r#"{"uint":1}"#);
    assert_eq!(to_string(&RGU::INPUT).unwrap(), r#"{"uint":2}"#);
    assert_eq!(to_string(&RGBU::INPUT).unwrap(), r#"{"uint":3}"#);
    assert_eq!(to_string(&RGBAU::INPUT).unwrap(), r#"{"uint":4}"#);
    assert_eq!(to_string(&RZ::INPUT).unwrap(), r#"{"bool":1}"#);
    assert_eq!(to_string(&RGZ::INPUT).unwrap(), r#"{"bool":2}"#);
    assert_eq!(to_string(&RGBZ::INPUT).unwrap(), r#"{"bool":3}"#);
    assert_eq!(to_string(&RGBAZ::INPUT).unwrap(), r#"{"bool":4}"#);
  }

  #[test]
  fn deserialize_type() {
    assert_eq!(from_str::<Type>(r#"{"float":1}"#).unwrap(), RF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":2}"#).unwrap(), RGF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":3}"#).unwrap(), RGBF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":4}"#).unwrap(), RGBAF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":1}"#).unwrap(), RI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":2}"#).unwrap(), RGI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":3}"#).unwrap(), RGBI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":4}"#).unwrap(), RGBAI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":1}"#).unwrap(), RU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":2}"#).unwrap(), RGU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":3}"#).unwrap(), RGBU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":4}"#).unwrap(), RGBAU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":1}"#).unwrap(), RZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":2}"#).unwrap(), RGZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":3}"#).unwrap(), RGBZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":4}"#).unwrap(), RGBAZ::INPUT);
  }

  #[test]
  fn serialize_role() {
    assert_eq!(&to_string(&Role::Pipeline).unwrap(), r#""pipeline""#);
    assert_eq!(&to_string(&Role::Parameter).unwrap(), r#""parameter""#);
  }

  #[test]
  fn deserialize_role() {
    assert_eq!(from_str::<Role>(r#""pipeline""#).unwrap(), Role::Pipeline);
    assert_eq!(from_str::<Role>(r#""parameter""#).unwrap(), Role::Parameter);
  }

  #[test]
  fn serialize_builtin() {
    assert_eq!(&to_string(&BuiltIn::Time).unwrap(), r#""time""#);
    assert_eq!(&to_string(&BuiltIn::FramebufferResolution).unwrap(), r#""framebuffer_resolution""#);
  }

  #[test]
  fn deserialize_builtin() {
    assert_eq!(from_str::<BuiltIn>(r#""time""#).unwrap(), BuiltIn::Time);
    assert_eq!(from_str::<BuiltIn>(r#""framebuffer_resolution""#).unwrap(), BuiltIn::FramebufferResolution);
  }

  #[test]
  fn input_construction() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&time.name, "t");
    assert_eq!(time.ty, RF::INPUT);
    assert_eq!(&jitter.name, "jitter");
    assert_eq!(jitter.ty, RGBF::INPUT);
  }

  #[test]
  fn serialize_input() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&to_string(&time).unwrap(), r#"{"name":"t","type":{"float":1}}"#);
    assert_eq!(&to_string(&jitter).unwrap(), r#"{"name":"jitter","type":{"float":3}}"#);
  }

  #[test]
  fn deserialize_input() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(from_str::<Input>(r#"{"name":"t","type":{"float":1}}"#).unwrap(), time);
    assert_eq!(from_str::<Input>(r#"{"name":"jitter","type":{"float":3}}"#).unwrap(), jitter);
  }

  #[test]
  fn inputs_to_glsl_struct() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");
    let inputs = &[time, jitter];

    let ed = TranslationUnit::from_iter(iter::once(inputs_to_struct_decl("Input", inputs).unwrap()));
    let expected = glsl!{
      struct Input {
        float t;
        vec3 jitter;
      };
    };

    assert_eq!(ed, Some(expected));
  }
}
<commit_msg>render::Role is now smarter to use.<commit_after>//! Render input types and related functions.

use glsl::syntax::{
  ExternalDeclaration, StructFieldSpecifier, TypeName, TypeSpecifier, TypeSpecifierNonArray
};
use serde_derive::{Deserialize, Serialize};

use crate::render::type_channel::TypeChan;

/// Input type.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Type {
  Int(TypeChan),
  #[serde(rename = "uint")]
  UInt(TypeChan),
  Float(TypeChan),
  Bool(TypeChan),
}

/// Associate an input type to a given type.
pub trait InputType {
  const INPUT: Type;
}

/// Render inputs.
pub trait InputTypes {
  /// Get the types of the input.
  fn ty() -> &'static [Type];
}

impl<A> InputTypes for A where A: InputType {
  fn ty() -> &'static [Type] {
    &[A::INPUT]
  }
}

macro_rules! multi_input_type_impl {
  ($($t:tt),*) => {
    impl<$($t),*> InputTypes for ($($t),*) where $($t: InputType),* {
      fn ty() -> &'static [Type] {
        &[$($t::INPUT),*]
      }
    }
  }
}

multi_input_type_impl!(A, B);
multi_input_type_impl!(A, B, C);
multi_input_type_impl!(A, B, C, D);
multi_input_type_impl!(A, B, C, D, E);
multi_input_type_impl!(A, B, C, D, E, F);
multi_input_type_impl!(A, B, C, D, E, F, G);
multi_input_type_impl!(A, B, C, D, E, F, G, H);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K);
multi_input_type_impl!(A, B, C, D, E, F, G, H, I, J, K, L);

/// An input.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub struct Input {
  /// Name of the input.
  name: String,
  /// Type of the input.
  #[serde(rename = "type")]
  ty: Type,
}

impl Input {
  /// Create a new input.
  pub fn new<T, N>(name: N) -> Self
  where T: InputType,
        N: Into<String> {
    Input {
      name: name.into(),
      ty: T::INPUT,
    }
  }
}

/// Generate a GLSL structure given a list of inputs.
pub(crate) fn inputs_to_struct_decl<'a, N, I>(
  name: N,
  inputs: I
) -> Option<ExternalDeclaration>
where N: Into<TypeName>,
      I: IntoIterator<Item = &'a Input> {
  ExternalDeclaration::new_struct(name, inputs.into_iter().map(input_to_struct_field))
}

/// Generate a struct field from an input.
fn input_to_struct_field(input: &Input) -> StructFieldSpecifier {
  StructFieldSpecifier::new(input.name.as_str(), glsl_type_from_input_type(&input.ty))
}

/// Generate a GLSL type from a given input type.
fn glsl_type_from_input_type(ty: &Type) -> TypeSpecifier {
  let ty_nonarray = match *ty {
    Type::Int(TypeChan::One) => TypeSpecifierNonArray::Int,
    Type::Int(TypeChan::Two) => TypeSpecifierNonArray::IVec2,
    Type::Int(TypeChan::Three) => TypeSpecifierNonArray::IVec3,
    Type::Int(TypeChan::Four) => TypeSpecifierNonArray::IVec4,
    Type::UInt(TypeChan::One) => TypeSpecifierNonArray::UInt,
    Type::UInt(TypeChan::Two) => TypeSpecifierNonArray::UVec2,
    Type::UInt(TypeChan::Three) => TypeSpecifierNonArray::UVec3,
    Type::UInt(TypeChan::Four) => TypeSpecifierNonArray::UVec4,
    Type::Float(TypeChan::One) => TypeSpecifierNonArray::Float,
    Type::Float(TypeChan::Two) => TypeSpecifierNonArray::Vec2,
    Type::Float(TypeChan::Three) => TypeSpecifierNonArray::Vec3,
    Type::Float(TypeChan::Four) => TypeSpecifierNonArray::Vec4,
    Type::Bool(TypeChan::One) => TypeSpecifierNonArray::Bool,
    Type::Bool(TypeChan::Two) => TypeSpecifierNonArray::BVec2,
    Type::Bool(TypeChan::Three) => TypeSpecifierNonArray::BVec3,
    Type::Bool(TypeChan::Four) => TypeSpecifierNonArray::BVec4,
  };

  TypeSpecifier::new(ty_nonarray)
}

/// Role of an input. It can either be a functional input, like a vertex’s attribute, or a constant
/// parameter.
///
/// This is not really important when writing a shader code but becomes important when writing the
/// render pipeline.
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Role {
  Pipeline(Input),
  Parameter(Input),
  #[serde(rename = "built-in")] BuiltIn(BuiltIn)
}

/// Built-ins.
#[derive(Clone, Copy, Debug, Deserialize, Hash, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum BuiltIn {
  Time,
  FramebufferResolution
}

#[cfg(test)]
mod tests {
  use glsl::syntax::TranslationUnit;
  use glsl_quasiquote::glsl;
  use serde_json::{from_str, to_string};
  use std::iter;

  use crate::render::types::*;
  use super::*;

  #[test]
  fn serialize_type() {
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RF::INPUT).unwrap(), r#"{"float":1}"#);
    assert_eq!(to_string(&RGF::INPUT).unwrap(), r#"{"float":2}"#);
    assert_eq!(to_string(&RGBF::INPUT).unwrap(), r#"{"float":3}"#);
    assert_eq!(to_string(&RGBAF::INPUT).unwrap(), r#"{"float":4}"#);
    assert_eq!(to_string(&RI::INPUT).unwrap(), r#"{"int":1}"#);
    assert_eq!(to_string(&RGI::INPUT).unwrap(), r#"{"int":2}"#);
    assert_eq!(to_string(&RGBI::INPUT).unwrap(), r#"{"int":3}"#);
    assert_eq!(to_string(&RGBAI::INPUT).unwrap(), r#"{"int":4}"#);
    assert_eq!(to_string(&RU::INPUT).unwrap(), r#"{"uint":1}"#);
    assert_eq!(to_string(&RGU::INPUT).unwrap(), r#"{"uint":2}"#);
    assert_eq!(to_string(&RGBU::INPUT).unwrap(), r#"{"uint":3}"#);
    assert_eq!(to_string(&RGBAU::INPUT).unwrap(), r#"{"uint":4}"#);
    assert_eq!(to_string(&RZ::INPUT).unwrap(), r#"{"bool":1}"#);
    assert_eq!(to_string(&RGZ::INPUT).unwrap(), r#"{"bool":2}"#);
    assert_eq!(to_string(&RGBZ::INPUT).unwrap(), r#"{"bool":3}"#);
    assert_eq!(to_string(&RGBAZ::INPUT).unwrap(), r#"{"bool":4}"#);
  }

  #[test]
  fn deserialize_type() {
    assert_eq!(from_str::<Type>(r#"{"float":1}"#).unwrap(), RF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":2}"#).unwrap(), RGF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":3}"#).unwrap(), RGBF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"float":4}"#).unwrap(), RGBAF::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":1}"#).unwrap(), RI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":2}"#).unwrap(), RGI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":3}"#).unwrap(), RGBI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"int":4}"#).unwrap(), RGBAI::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":1}"#).unwrap(), RU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":2}"#).unwrap(), RGU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":3}"#).unwrap(), RGBU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"uint":4}"#).unwrap(), RGBAU::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":1}"#).unwrap(), RZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":2}"#).unwrap(), RGZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":3}"#).unwrap(), RGBZ::INPUT);
    assert_eq!(from_str::<Type>(r#"{"bool":4}"#).unwrap(), RGBAZ::INPUT);
  }

  #[test]
  fn serialize_role() {
    let pipeline = Input::new::<RGBF, _>("vertex_color");
    let param = Input::new::<RZ, _>("enabled");

    assert_eq!(&to_string(&Role::Pipeline(pipeline)).unwrap(), r#"{"pipeline":{"name":"vertex_color","type":{"float":3}}}"#);
    assert_eq!(&to_string(&Role::Parameter(param)).unwrap(), r#"{"parameter":{"name":"enabled","type":{"bool":1}}}"#);
    assert_eq!(&to_string(&Role::BuiltIn(BuiltIn::Time)).unwrap(), r#"{"built-in":"time"}"#);
  }

  #[test]
  fn deserialize_role() {
    let pipeline = Input::new::<RGBF, _>("vertex_color");
    let param = Input::new::<RZ, _>("enabled");

    assert_eq!(from_str::<Role>(r#"{"pipeline":{"name":"vertex_color","type":{"float":3}}}"#).unwrap(), Role::Pipeline(pipeline));
    assert_eq!(from_str::<Role>(r#"{"parameter":{"name":"enabled","type":{"bool":1}}}"#).unwrap(), Role::Parameter(param));
    assert_eq!(from_str::<Role>(r#"{"built-in":"time"}"#).unwrap(), Role::BuiltIn(BuiltIn::Time));
  }

  #[test]
  fn serialize_builtin() {
    assert_eq!(&to_string(&BuiltIn::Time).unwrap(), r#""time""#);
    assert_eq!(&to_string(&BuiltIn::FramebufferResolution).unwrap(), r#""framebuffer_resolution""#);
  }

  #[test]
  fn deserialize_builtin() {
    assert_eq!(from_str::<BuiltIn>(r#""time""#).unwrap(), BuiltIn::Time);
    assert_eq!(from_str::<BuiltIn>(r#""framebuffer_resolution""#).unwrap(), BuiltIn::FramebufferResolution);
  }

  #[test]
  fn input_construction() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&time.name, "t");
    assert_eq!(time.ty, RF::INPUT);
    assert_eq!(&jitter.name, "jitter");
    assert_eq!(jitter.ty, RGBF::INPUT);
  }

  #[test]
  fn serialize_input() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(&to_string(&time).unwrap(), r#"{"name":"t","type":{"float":1}}"#);
    assert_eq!(&to_string(&jitter).unwrap(), r#"{"name":"jitter","type":{"float":3}}"#);
  }

  #[test]
  fn deserialize_input() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");

    assert_eq!(from_str::<Input>(r#"{"name":"t","type":{"float":1}}"#).unwrap(), time);
    assert_eq!(from_str::<Input>(r#"{"name":"jitter","type":{"float":3}}"#).unwrap(), jitter);
  }

  #[test]
  fn inputs_to_glsl_struct() {
    let time = Input::new::<RF, _>("t");
    let jitter = Input::new::<RGBF, _>("jitter");
    let inputs = &[time, jitter];

    let ed = TranslationUnit::from_iter(iter::once(inputs_to_struct_decl("Input", inputs).unwrap()));
    let expected = glsl!{
      struct Input {
        float t;
        vec3 jitter;
      };
    };

    assert_eq!(ed, Some(expected));
  }
}
<|endoftext|>


<commit_before>
<commit_msg>Remove empty / unused test_utils.rs file.<commit_after><|endoftext|>


<commit_before>use ansi_term::Colour::{Green, Yellow, Red, White, Blue};
use hyper::header::{Accept, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper;
use rustc_serialize::json;
use std::collections::HashSet;
use std::fs;
use std::io::{Read, Write};
use std::path::Path;
use std::sync::Arc;

use tfl::line::{Line, TimeTableResponse, Sequence, Stop};

pub enum DataSource {
    API,
    Cache
}

#[derive(Clone)]
pub struct Client {
    client : Arc<hyper::Client>,
    app_id : String,
    app_key : String,
    cache_dir : String,
}

impl Client {
    pub fn new() -> Client {
        let cache_path : &Path = Path::new("./cache");
        let _ = fs::create_dir(cache_path);
        return Client{
            client : Arc::new(hyper::Client::new()),
            app_id : String::new(),
            app_key : String::new(),
            cache_dir : String::from("./cache"),
        }
    }

    fn get(&self, endpoint : &str) -> String {
        match self.cache_get(endpoint) {
            Some(body) => body,
            None => self.remote_get(endpoint)
        }
    }

    fn remote_get(&self, endpoint : &str) -> String {
        let req_uri = format!("https://api.tfl.gov.uk{}?app_id={}&app_key={}", endpoint, self.app_id, self.app_key);
        let mut body = String::new();
        let mut resp = self.client.get(&req_uri)
            .header(Accept(vec![
                           qitem(Mime(TopLevel::Application,
                                      SubLevel::Ext("json".to_owned()), vec![])),
            ]))
            .send().unwrap();
        resp.read_to_string(&mut body).unwrap();
        self.cache_put(endpoint, body)
    }

    fn cache_fname(&self, endpoint : &str) -> String {
        let fname = String::from(endpoint);
        let fname0 = fname.replace("/", "_");
        self.cache_dir.clone() + "/" + &fname0
    }

    fn cache_put(&self, endpoint : &str, body : String) -> String {
        let mut f = fs::File::create(self.cache_fname(endpoint)).unwrap();
        f.write_all(body.as_bytes()).unwrap();
        body
    }

    fn cache_get(&self, endpoint : &str) -> Option<String> {
        let mut body = String::new();
        match fs::File::open(self.cache_fname(endpoint)) {
            Ok(ref mut f) => {
                f.read_to_string(&mut body).unwrap();
                Some(body)
            },
            Err(_) => None,
        }
    }

    pub fn get_cached_lines(&self) -> Vec<Line> {
        let body = self.cache_get("/line/route");
        match body {
            Some(x) => json::decode(&x).unwrap(),
            None => vec![]
        }
    }

    pub fn get_lines(&self) -> Vec<Line> {
        let body = self.get("/line/route");
        json::decode(&body).unwrap()
    }

    pub fn get_timetable(&self, line_id : &str, originator: &str, destination : &str) -> Option<TimeTableResponse> {
        let req_uri = format!("/line/{}/timetable/{}/to/{}", line_id, originator, destination);
        let body = self.get(&req_uri);
        match json::decode::<TimeTableResponse>(&body) {
            Ok(ttresp) =>  Some(ttresp.clone()),
            Err(err) => {
                println!("{}: {}", Red.bold().paint("Error decoding timetable"), err);
                None
            },
        }
    }

    pub fn get_stops(&self, line_id : &str) -> Vec<Stop> {
        let req_uri = format!("/line/{}/stoppoints", line_id);
        let body = self.get(&req_uri);
        match json::decode::<Vec<Stop>>(&body) {
            Ok(stops) => stops,
            Err(err) => {
                println!("{}: {}", Red.bold().paint("Error decoding stops"), err);
                Vec::<Stop>::new()
            }
        }
    }

    pub fn get_sequence(&self, line_id : &str, direction : &str) -> Option<Sequence> {
        let req_uri = format!("/line/{}/route/sequence/{}", line_id, direction);
        let body = self.get(&req_uri);
        match json::decode::<Sequence>(&body) {
            Ok(seq) => Some(seq),
            Err(err) => {
                println!("{}: {}", Red.bold().paint("Error decoding sequence") err);
                None
            }
        }
    }
}
<commit_msg>Fix missing comma breaking the build<commit_after>use ansi_term::Colour::{Green, Yellow, Red, White, Blue};
use hyper::header::{Accept, qitem};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper;
use rustc_serialize::json;
use std::collections::HashSet;
use std::fs;
use std::io::{Read, Write};
use std::path::Path;
use std::sync::Arc;

use tfl::line::{Line, TimeTableResponse, Sequence, Stop};

pub enum DataSource {
    API,
    Cache
}

#[derive(Clone)]
pub struct Client {
    client : Arc<hyper::Client>,
    app_id : String,
    app_key : String,
    cache_dir : String,
}

impl Client {
    pub fn new() -> Client {
        let cache_path : &Path = Path::new("./cache");
        let _ = fs::create_dir(cache_path);
        return Client{
            client : Arc::new(hyper::Client::new()),
            app_id : String::new(),
            app_key : String::new(),
            cache_dir : String::from("./cache"),
        }
    }

    fn get(&self, endpoint : &str) -> String {
        match self.cache_get(endpoint) {
            Some(body) => body,
            None => self.remote_get(endpoint)
        }
    }

    fn remote_get(&self, endpoint : &str) -> String {
        let req_uri = format!("https://api.tfl.gov.uk{}?app_id={}&app_key={}", endpoint, self.app_id, self.app_key);
        let mut body = String::new();
        let mut resp = self.client.get(&req_uri)
            .header(Accept(vec![
                           qitem(Mime(TopLevel::Application,
                                      SubLevel::Ext("json".to_owned()), vec![])),
            ]))
            .send().unwrap();
        resp.read_to_string(&mut body).unwrap();
        self.cache_put(endpoint, body)
    }

    fn cache_fname(&self, endpoint : &str) -> String {
        let fname = String::from(endpoint);
        let fname0 = fname.replace("/", "_");
        self.cache_dir.clone() + "/" + &fname0
    }

    fn cache_put(&self, endpoint : &str, body : String) -> String {
        let mut f = fs::File::create(self.cache_fname(endpoint)).unwrap();
        f.write_all(body.as_bytes()).unwrap();
        body
    }

    fn cache_get(&self, endpoint : &str) -> Option<String> {
        let mut body = String::new();
        match fs::File::open(self.cache_fname(endpoint)) {
            Ok(ref mut f) => {
                f.read_to_string(&mut body).unwrap();
                Some(body)
            },
            Err(_) => None,
        }
    }

    pub fn get_cached_lines(&self) -> Vec<Line> {
        let body = self.cache_get("/line/route");
        match body {
            Some(x) => json::decode(&x).unwrap(),
            None => vec![]
        }
    }

    pub fn get_lines(&self) -> Vec<Line> {
        let body = self.get("/line/route");
        json::decode(&body).unwrap()
    }

    pub fn get_timetable(&self, line_id : &str, originator: &str, destination : &str) -> Option<TimeTableResponse> {
        let req_uri = format!("/line/{}/timetable/{}/to/{}", line_id, originator, destination);
        let body = self.get(&req_uri);
        match json::decode::<TimeTableResponse>(&body) {
            Ok(ttresp) =>  Some(ttresp.clone()),
            Err(err) => {
                println!("{}: {}", Red.bold().paint("Error decoding timetable"), err);
                None
            },
        }
    }

    pub fn get_stops(&self, line_id : &str) -> Vec<Stop> {
        let req_uri = format!("/line/{}/stoppoints", line_id);
        let body = self.get(&req_uri);
        match json::decode::<Vec<Stop>>(&body) {
            Ok(stops) => stops,
            Err(err) => {
                println!("{}: {}", Red.bold().paint("Error decoding stops"), err);
                Vec::<Stop>::new()
            }
        }
    }

    pub fn get_sequence(&self, line_id : &str, direction : &str) -> Option<Sequence> {
        let req_uri = format!("/line/{}/route/sequence/{}", line_id, direction);
        let body = self.get(&req_uri);
        match json::decode::<Sequence>(&body) {
            Ok(seq) => Some(seq),
            Err(err) => {
                println!("{}: {}", Red.bold().paint("Error decoding sequence"), err);
                None
            }
        }
    }
}
<|endoftext|>


<commit_before>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::surface::Surface;
use std::io::Result;
use std::path::Path;
use uorustlibs::art::{ArtReader, Art};
use uorustlibs::hues::{HueReader, HueGroup, Hue};
use uorustlibs::color::Color as ColorTrait;

use std::io::{Error, };
use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct HuesScene {
    reader: Result<HueReader>,
    index: u32,
    texture: Option<Texture>
}

impl HuesScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let mut scene = Box::new(HuesScene {
            reader: HueReader::new(&Path::new("./assets/hues.mul")),
            texture: None,
            index: 0
        });
        scene.load_group(renderer, engine_data);
        scene
    }

    fn load_group(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        let mut surface = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
        let maybe_group = match self.reader {
            Ok(ref mut hue_reader) => {
                hue_reader.read_hue_group(self.index)
            },
            Err(ref x) => Err(Error::new(x.kind(), "Whoops"))
        };
        match maybe_group {
            Ok(group) => {
                let drawn_group = self.draw_hue_group(self.index, &group, renderer, engine_data);
                drawn_group.blit(None, &mut surface, Some(Rect::new(0, 0, drawn_group.width(), drawn_group.height())));
            },
            Err(_) => ()
        };
        self.texture = Some(renderer.create_texture_from_surface(&surface).unwrap());
    }

    fn draw_hue_group(&self, group_idx: u32, group: &HueGroup, renderer: &mut Renderer, engine_data: &mut EngineData) -> Surface {
        let mut surface = Surface::new(256, 64 * 9, PixelFormatEnum::RGBA8888).unwrap();
        for (idx, hue) in group.entries.iter().enumerate() {
            let drawn_hue = self.draw_hue(&hue, renderer, engine_data);
            drawn_hue.blit(None, &mut surface, Some(Rect::new(0, idx as i32 * drawn_hue.height() as i32, drawn_hue.width(), drawn_hue.height()))).unwrap();
        }
        let label = engine_data.text_renderer.create_text(&format!("Group {} - {}", group_idx, group.header), Color::RGBA(255, 255, 255, 255));
        label.blit(None, &mut surface, Some(Rect::new(0, 64 * 8 + 32, label.width(), label.height())));
        surface
    }

    fn draw_hue(&self, hue: &Hue, renderer: &mut Renderer, engine_data: &mut EngineData) -> Surface {
        let mut surface = Surface::new(256, 64, PixelFormatEnum::RGBA8888).unwrap();
        for (col_idx, &color) in hue.color_table.iter().enumerate() {
            let (r, g, b, _) = color.to_rgba();
            surface.fill_rect(Some(Rect::new((col_idx as i32 * 16), 0, 16, 64)), Color::RGB(r, g, b)).unwrap();
        };
        let label_text = format!("{}: {} - {}", if hue.name.trim().len() > 0 { &hue.name } else { "NONE" }, hue.table_start, hue.table_end);
        let label = engine_data.text_renderer.create_text(&label_text, Color::RGBA(255, 255, 255, 255));
        label.blit(None, &mut surface, Some(Rect::new(0, 48, label.width(), label.height())));
        surface
    }
}

impl<'a> Scene<SceneName, EngineData<'a>> for HuesScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        renderer.clear();
        match self.texture {
            Some(ref texture) => {
                renderer.copy(texture, None, None).unwrap();
            },
            None => ()
        };
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.load_group(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.load_group(renderer, engine_data);
                None
            },
             _ => None
        }
    }
}
<commit_msg>Provide type information for HuesScene<commit_after>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use engine::EngineData;
use text_renderer::TextRenderer;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::surface::Surface;
use std::io::Result;
use std::path::Path;
use uorustlibs::art::{ArtReader, Art};
use uorustlibs::hues::{HueReader, HueGroup, Hue};
use uorustlibs::color::Color as ColorTrait;

use std::io::{Error};
use std::fs::{File};
use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct HuesScene {
    reader: Result<HueReader<File>>,
    index: u32,
    texture: Option<Texture>
}

impl HuesScene {
    pub fn new<'a>(renderer: &mut Renderer, engine_data: &mut EngineData<'a>) -> BoxedScene<SceneName, EngineData<'a>> {
        let mut scene = Box::new(HuesScene {
            reader: HueReader::new(&Path::new("./assets/hues.mul")),
            texture: None,
            index: 0
        });
        scene.load_group(renderer, engine_data);
        scene
    }

    fn load_group(&mut self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        let mut surface = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
        let maybe_group = match self.reader {
            Ok(ref mut hue_reader) => {
                hue_reader.read_hue_group(self.index)
            },
            Err(ref x) => Err(Error::new(x.kind(), "Whoops"))
        };
        match maybe_group {
            Ok(group) => {
                let drawn_group = self.draw_hue_group(self.index, &group, renderer, engine_data);
                drawn_group.blit(None, &mut surface, Some(Rect::new(0, 0, drawn_group.width(), drawn_group.height())));
            },
            Err(_) => ()
        };
        self.texture = Some(renderer.create_texture_from_surface(&surface).unwrap());
    }

    fn draw_hue_group(&self, group_idx: u32, group: &HueGroup, renderer: &mut Renderer, engine_data: &mut EngineData) -> Surface {
        let mut surface = Surface::new(256, 64 * 9, PixelFormatEnum::RGBA8888).unwrap();
        for (idx, hue) in group.entries.iter().enumerate() {
            let drawn_hue = self.draw_hue(&hue, renderer, engine_data);
            drawn_hue.blit(None, &mut surface, Some(Rect::new(0, idx as i32 * drawn_hue.height() as i32, drawn_hue.width(), drawn_hue.height()))).unwrap();
        }
        let label = engine_data.text_renderer.create_text(&format!("Group {} - {}", group_idx, group.header), Color::RGBA(255, 255, 255, 255));
        label.blit(None, &mut surface, Some(Rect::new(0, 64 * 8 + 32, label.width(), label.height())));
        surface
    }

    fn draw_hue(&self, hue: &Hue, renderer: &mut Renderer, engine_data: &mut EngineData) -> Surface {
        let mut surface = Surface::new(256, 64, PixelFormatEnum::RGBA8888).unwrap();
        for (col_idx, &color) in hue.color_table.iter().enumerate() {
            let (r, g, b, _) = color.to_rgba();
            surface.fill_rect(Some(Rect::new((col_idx as i32 * 16), 0, 16, 64)), Color::RGB(r, g, b)).unwrap();
        };
        let label_text = format!("{}: {} - {}", if hue.name.trim().len() > 0 { &hue.name } else { "NONE" }, hue.table_start, hue.table_end);
        let label = engine_data.text_renderer.create_text(&label_text, Color::RGBA(255, 255, 255, 255));
        label.blit(None, &mut surface, Some(Rect::new(0, 48, label.width(), label.height())));
        surface
    }
}

impl<'a> Scene<SceneName, EngineData<'a>> for HuesScene {
    fn render(&self, renderer: &mut Renderer, engine_data: &mut EngineData) {
        renderer.clear();
        match self.texture {
            Some(ref texture) => {
                renderer.copy(texture, None, None).unwrap();
            },
            None => ()
        };
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, renderer: &mut Renderer, engine_data: &mut EngineData) -> Option<SceneChangeEvent<SceneName>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.load_group(renderer, engine_data);
                }
                None
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.load_group(renderer, engine_data);
                None
            },
             _ => None
        }
    }
}
<|endoftext|>