<commit_before>extern crate iron;
extern crate iron_sessionstorage;
extern crate urlencoded;
extern crate handlebars;
extern crate handlebars_iron as hbs;

use self::iron::{Request, IronResult, Response, status};
use presentation::helper::templating::*;
use business::crud::*;
use self::iron::modifiers::Redirect;
use presentation::helper::session;
use presentation::model::category::Category;
use presentation::model::question::Question;
use presentation::model::answer::Answer;
use self::handlebars::to_json;
use presentation::helper::util::{get_formdata, to_ironresult, redirect};

pub fn get_question(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    let categories = to_ironresult(get_categories())?
        .into_iter()
        .map(|x| {
                 Category {
                     id: x.id,
                     text: x.text,
                 }
             })
        .collect::<Vec<Category>>();
    let questions = to_ironresult(get_questions())?
        .into_iter()
        .map(|x| {
            let category = get_category(x.category_id).unwrap();
            Question {
                id: x.id,
                text: x.text,
                category: Category {
                    id: category.id,
                    text: category.text,
                },
                categories: &categories,
                answers: get_presentation_answers(x.id).unwrap(),
            }
        })
        .collect::<Vec<Question>>();
    let json = btreemap! {
        "questions".to_string() => to_json(&questions),
        "categories".to_string() => to_json(&categories),
    };
    let template = generate_site(req, "quiz/admin/question", json, None);
    Ok(Response::with((template, status::Ok)))
}

fn get_presentation_answers(question_id: i32) -> IronResult<Vec<Answer>> {
    let data_answers = to_ironresult(get_answers(question_id))?;
    let converted_answers = data_answers
        .into_iter()
        .map(|x| {
                 Answer {
                     id: x.id,
                     text: x.text,
                     is_confirmed_wrong: !x.is_correct,
                 }
             })
        .collect::<Vec<Answer>>();
    Ok(converted_answers)
}

pub fn post_question_add(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    if !validate_new_answers(req, 4)? {
        return Ok(Response::with((status::Found,
                                  Redirect(url_for!(req, "get_quiz_admin_question")))));
    }

    let category = get_formdata(req, "category_to_add")?;
    let category_as_int = to_ironresult(category.parse::<i32>())?;
    let question = get_formdata(req, "new_question")?;
    let new_question = create_question(category_as_int, &question);
    let new_question_id = to_ironresult(new_question)?.id;
    create_answer_from_form(req, 0, new_question_id)?;
    create_answer_from_form(req, 1, new_question_id)?;
    create_answer_from_form(req, 2, new_question_id)?;
    create_answer_from_form(req, 3, new_question_id)?;

    Ok(Response::with((status::Found, Redirect(url_for!(req, "get_quiz_admin_question")))))
}

fn validate_new_answers(req: &mut Request, question_count: i32) -> IronResult<bool> {
    validate_answers_on_forms(req, question_count, "new_correct_answer", "new_answer")
}

fn validate_edited_answers(req: &mut Request, question_count: i32) -> IronResult<bool> {
    validate_answers_on_forms(req, question_count, "correct_answer", "answer")
}

fn validate_answers_on_forms(req: &mut Request,
                             question_count: i32,
                             correct_answer: &str,
                             answer: &str)
                             -> IronResult<bool> {
    let correct_index = get_formdata(req, correct_answer)?;
    let correct_nr = to_ironresult(correct_index.parse::<i32>())?;
    if correct_nr >= question_count {
        return Ok(false);
    }
    let mut answers = Vec::new();
    let form_name = answer.to_owned();
    for i in 0..question_count {
        let mut this_name = form_name.clone();
        this_name.push_str(&i.to_string());
        answers.push(get_formdata(req, &this_name)?);
    }
    let orig_len = answers.len();
    answers.sort();
    answers.dedup();
    return Ok(answers.len() == orig_len);
}

fn create_answer_from_form(req: &mut Request, nr: i32, question_id: i32) -> IronResult<()> {
    let mut form_name = "new_answer".to_owned();
    form_name.push_str(&nr.to_string());
    let ans_text = &get_formdata(req, &form_name)?;
    let correct_answer = get_formdata(req, "new_correct_answer")?;
    let correct_nr = to_ironresult(correct_answer.parse::<i32>())?;
    let ans = create_answer(question_id, &ans_text, correct_nr == nr);
    to_ironresult(ans)?;
    Ok(())
}

pub fn post_question_edit(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    if !validate_edited_answers(req, 4)? {
        return Ok(Response::with((status::Found,
                                  Redirect(url_for!(req, "get_quiz_admin_question")))));
    }

    let question = get_formdata(req, "question_id")?;
    let question_id = to_ironresult(question.parse::<i32>())?;
    let text = get_formdata(req, "question_text")?;
    let edited_question = rename_question(question_id, &text);
    to_ironresult(edited_question)?;

    let cat = get_formdata(req, "category")?;
    let cat_id = to_ironresult(cat.parse::<i32>())?;
    let edited_question = change_question_category(question_id, cat_id);
    to_ironresult(edited_question)?;

    edit_answer_from_form(req, 0)?;
    edit_answer_from_form(req, 1)?;
    edit_answer_from_form(req, 2)?;
    edit_answer_from_form(req, 3)?;

    Ok(Response::with((status::Found, Redirect(url_for!(req, "get_quiz_admin_question")))))
}

fn edit_answer_from_form(req: &mut Request, nr: i32) -> IronResult<()> {
    let mut form_name = "answer".to_owned();
    let mut form_id_name = "answer_id".to_owned();
    form_name.push_str(&nr.to_string());
    form_id_name.push_str(&nr.to_string());

    let answer = &get_formdata(req, &form_id_name)?;
    let answer_id = to_ironresult(answer.parse::<i32>())?;
    let ans_text = &get_formdata(req, &form_name)?;

    let correct_answer = get_formdata(req, "correct_answer")?;
    let correct_nr = to_ironresult(correct_answer.parse::<i32>())?;

    let ans = rename_answer(answer_id, &ans_text);
    to_ironresult(ans)?;

    let ans = change_answer_correct(answer_id, correct_nr == nr);
    to_ironresult(ans)?;
    Ok(())
}

pub fn post_question_remove(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    let id = get_formdata(req, "question_id")?;
    let id_as_int = to_ironresult(id.parse::<i32>())?;
    let deactivated_category = deactivate_question(id_as_int);
    to_ironresult(deactivated_category)?;
    Ok(Response::with((status::Found, Redirect(url_for!(req, "get_quiz_admin_question")))))
}
<commit_msg>Run Rustfmt<commit_after>extern crate iron;
extern crate iron_sessionstorage;
extern crate urlencoded;
extern crate handlebars;
extern crate handlebars_iron as hbs;

use self::iron::{Request, IronResult, Response, status};
use presentation::helper::templating::*;
use business::crud::*;
use self::iron::modifiers::Redirect;
use presentation::helper::session;
use presentation::model::category::Category;
use presentation::model::question::Question;
use presentation::model::answer::Answer;
use self::handlebars::to_json;
use presentation::helper::util::{get_formdata, to_ironresult, redirect};

pub fn get_question(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    let categories = to_ironresult(get_categories())
        ?
        .into_iter()
        .map(|x| {
                 Category {
                     id: x.id,
                     text: x.text,
                 }
             })
        .collect::<Vec<Category>>();
    let questions = to_ironresult(get_questions())
        ?
        .into_iter()
        .map(|x| {
            let category = get_category(x.category_id).unwrap();
            Question {
                id: x.id,
                text: x.text,
                category: Category {
                    id: category.id,
                    text: category.text,
                },
                categories: &categories,
                answers: get_presentation_answers(x.id).unwrap(),
            }
        })
        .collect::<Vec<Question>>();
    let json = btreemap! {
        "questions".to_string() => to_json(&questions),
        "categories".to_string() => to_json(&categories),
    };
    let template = generate_site(req, "quiz/admin/question", json, None);
    Ok(Response::with((template, status::Ok)))
}

fn get_presentation_answers(question_id: i32) -> IronResult<Vec<Answer>> {
    let data_answers = to_ironresult(get_answers(question_id))?;
    let converted_answers = data_answers
        .into_iter()
        .map(|x| {
                 Answer {
                     id: x.id,
                     text: x.text,
                     is_confirmed_wrong: !x.is_correct,
                 }
             })
        .collect::<Vec<Answer>>();
    Ok(converted_answers)
}

pub fn post_question_add(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    if !validate_new_answers(req, 4)? {
        return Ok(Response::with((status::Found,
                                  Redirect(url_for!(req, "get_quiz_admin_question")))));
    }

    let category = get_formdata(req, "category_to_add")?;
    let category_as_int = to_ironresult(category.parse::<i32>())?;
    let question = get_formdata(req, "new_question")?;
    let new_question = create_question(category_as_int, &question);
    let new_question_id = to_ironresult(new_question)?.id;
    create_answer_from_form(req, 0, new_question_id)?;
    create_answer_from_form(req, 1, new_question_id)?;
    create_answer_from_form(req, 2, new_question_id)?;
    create_answer_from_form(req, 3, new_question_id)?;

    Ok(Response::with((status::Found, Redirect(url_for!(req, "get_quiz_admin_question")))))
}

fn validate_new_answers(req: &mut Request, question_count: i32) -> IronResult<bool> {
    validate_answers_on_forms(req, question_count, "new_correct_answer", "new_answer")
}

fn validate_edited_answers(req: &mut Request, question_count: i32) -> IronResult<bool> {
    validate_answers_on_forms(req, question_count, "correct_answer", "answer")
}

fn validate_answers_on_forms(req: &mut Request,
                             question_count: i32,
                             correct_answer: &str,
                             answer: &str)
                             -> IronResult<bool> {
    let correct_index = get_formdata(req, correct_answer)?;
    let correct_nr = to_ironresult(correct_index.parse::<i32>())?;
    if correct_nr >= question_count {
        return Ok(false);
    }
    let mut answers = Vec::new();
    let form_name = answer.to_owned();
    for i in 0..question_count {
        let mut this_name = form_name.clone();
        this_name.push_str(&i.to_string());
        answers.push(get_formdata(req, &this_name)?);
    }
    let orig_len = answers.len();
    answers.sort();
    answers.dedup();
    return Ok(answers.len() == orig_len);
}

fn create_answer_from_form(req: &mut Request, nr: i32, question_id: i32) -> IronResult<()> {
    let mut form_name = "new_answer".to_owned();
    form_name.push_str(&nr.to_string());
    let ans_text = &get_formdata(req, &form_name)?;
    let correct_answer = get_formdata(req, "new_correct_answer")?;
    let correct_nr = to_ironresult(correct_answer.parse::<i32>())?;
    let ans = create_answer(question_id, &ans_text, correct_nr == nr);
    to_ironresult(ans)?;
    Ok(())
}

pub fn post_question_edit(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    if !validate_edited_answers(req, 4)? {
        return Ok(Response::with((status::Found,
                                  Redirect(url_for!(req, "get_quiz_admin_question")))));
    }

    let question = get_formdata(req, "question_id")?;
    let question_id = to_ironresult(question.parse::<i32>())?;
    let text = get_formdata(req, "question_text")?;
    let edited_question = rename_question(question_id, &text);
    to_ironresult(edited_question)?;

    let cat = get_formdata(req, "category")?;
    let cat_id = to_ironresult(cat.parse::<i32>())?;
    let edited_question = change_question_category(question_id, cat_id);
    to_ironresult(edited_question)?;

    edit_answer_from_form(req, 0)?;
    edit_answer_from_form(req, 1)?;
    edit_answer_from_form(req, 2)?;
    edit_answer_from_form(req, 3)?;

    Ok(Response::with((status::Found, Redirect(url_for!(req, "get_quiz_admin_question")))))
}

fn edit_answer_from_form(req: &mut Request, nr: i32) -> IronResult<()> {
    let mut form_name = "answer".to_owned();
    let mut form_id_name = "answer_id".to_owned();
    form_name.push_str(&nr.to_string());
    form_id_name.push_str(&nr.to_string());

    let answer = &get_formdata(req, &form_id_name)?;
    let answer_id = to_ironresult(answer.parse::<i32>())?;
    let ans_text = &get_formdata(req, &form_name)?;

    let correct_answer = get_formdata(req, "correct_answer")?;
    let correct_nr = to_ironresult(correct_answer.parse::<i32>())?;

    let ans = rename_answer(answer_id, &ans_text);
    to_ironresult(ans)?;

    let ans = change_answer_correct(answer_id, correct_nr == nr);
    to_ironresult(ans)?;
    Ok(())
}

pub fn post_question_remove(req: &mut Request) -> IronResult<Response> {
    if session::get_admin(req)?.is_none() {
        return redirect(req, "get_root");
    }
    let id = get_formdata(req, "question_id")?;
    let id_as_int = to_ironresult(id.parse::<i32>())?;
    let deactivated_category = deactivate_question(id_as_int);
    to_ironresult(deactivated_category)?;
    Ok(Response::with((status::Found, Redirect(url_for!(req, "get_quiz_admin_question")))))
}
<|endoftext|>


<commit_before>use context::{GlVersion, ExtensionsList};
use version::Api;
use gl;

/// Represents the capabilities of the context.
pub struct Capabilities {
    /// Whether the context has a shader compiler.
    pub shader_compiler: bool,

    /// Whether the context supports left and right buffers.
    pub stereo: bool,

    /// Number of bits in the default framebuffer's depth buffer
    pub depth_bits: Option<u16>,

    /// Number of bits in the default framebuffer's stencil buffer
    pub stencil_bits: Option<u16>,

    /// Maximum number of textures that can be bound to a program.
    ///
    /// `glActiveTexture` must be between `GL_TEXTURE0` and `GL_TEXTURE0` + this value - 1.
    pub max_combined_texture_image_units: gl::types::GLint,

    /// Maximum value for `GL_TEXTURE_MAX_ANISOTROPY_EXT`.
    ///
    /// `None` if the extension is not supported by the hardware.
    pub max_texture_max_anisotropy: Option<gl::types::GLfloat>,

    /// Maximum width and height of `glViewport`.
    pub max_viewport_dims: (gl::types::GLint, gl::types::GLint),

    /// Maximum number of elements that can be passed with `glDrawBuffers`.
    pub max_draw_buffers: gl::types::GLint,

    /// Maximum number of vertices per patch. `None` if tessellation is not supported.
    pub max_patch_vertices: Option<gl::types::GLint>,
}

/// Loads the capabilities.
pub fn get_capabilities(gl: &gl::Gl, version: &GlVersion, extensions: &ExtensionsList)
                        -> Capabilities
{
    use std::mem;

    Capabilities {
        shader_compiler: if version >= &GlVersion(Api::Gl, 1, 0) {
            true
        } else {
            unsafe {
                let mut val = mem::uninitialized();
                gl.GetBooleanv(gl::SHADER_COMPILER, &mut val);
                val != 0
            }
        },

        stereo: unsafe {
            if version >= &GlVersion(Api::Gl, 1, 0) {
                let mut val: gl::types::GLboolean = mem::uninitialized();
                gl.GetBooleanv(gl::STEREO, &mut val);
                val != 0
            } else {
                false
            }
        },

        depth_bits: unsafe {
            let mut value = mem::uninitialized();

            if version >= &GlVersion(Api::Gl, 3, 0) {
                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::DEPTH,
                                                       gl::FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
                                                       &mut value);
            } else {
                gl.GetIntegerv(gl::DEPTH_BITS, &mut value);
            };

            match value {
                0 => None,
                v => Some(v as u16),
            }
        },

        stencil_bits: unsafe {
            let mut value = mem::uninitialized();

            if version >= &GlVersion(Api::Gl, 3, 0) {
                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::STENCIL,
                                                       gl::FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
                                                       &mut value);
            } else {
                gl.GetIntegerv(gl::STENCIL_BITS, &mut value);
            };

            match value {
                0 => None,
                v => Some(v as u16),
            }
        },

        max_combined_texture_image_units: unsafe {
            let mut val = 2;
            gl.GetIntegerv(gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mut val);
            val
        },

        max_texture_max_anisotropy: if !extensions.gl_ext_texture_filter_anisotropic {
            None

        } else {
            Some(unsafe {
                let mut val = mem::uninitialized();
                gl.GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mut val);
                val
            })
        },

        max_viewport_dims: unsafe {
            let mut val: [gl::types::GLint; 2] = [ 0, 0 ];
            gl.GetIntegerv(gl::MAX_VIEWPORT_DIMS, val.as_mut_ptr());
            (val[0], val[1])
        },

        max_draw_buffers: unsafe {
            let mut val = 1;
            gl.GetIntegerv(gl::MAX_DRAW_BUFFERS, &mut val);
            val
        },

        max_patch_vertices: if version < &GlVersion(Api::Gl, 4, 0) && !extensions.gl_arb_tessellation_shader {
            None

        } else {
            Some(unsafe {
                let mut val = mem::uninitialized();
                gl.GetIntegerv(gl::MAX_PATCH_VERTICES, &mut val);
                val
            })
        },

    }
}
<commit_msg>Fix context/capabilities for OpenGL ES 2<commit_after>use context::{GlVersion, ExtensionsList};
use version::Api;
use gl;

/// Represents the capabilities of the context.
pub struct Capabilities {
    /// Whether the context has a shader compiler.
    pub shader_compiler: bool,

    /// Whether the context supports left and right buffers.
    pub stereo: bool,

    /// Number of bits in the default framebuffer's depth buffer
    pub depth_bits: Option<u16>,

    /// Number of bits in the default framebuffer's stencil buffer
    pub stencil_bits: Option<u16>,

    /// Maximum number of textures that can be bound to a program.
    ///
    /// `glActiveTexture` must be between `GL_TEXTURE0` and `GL_TEXTURE0` + this value - 1.
    pub max_combined_texture_image_units: gl::types::GLint,

    /// Maximum value for `GL_TEXTURE_MAX_ANISOTROPY_EXT`.
    ///
    /// `None` if the extension is not supported by the hardware.
    pub max_texture_max_anisotropy: Option<gl::types::GLfloat>,

    /// Maximum width and height of `glViewport`.
    pub max_viewport_dims: (gl::types::GLint, gl::types::GLint),

    /// Maximum number of elements that can be passed with `glDrawBuffers`.
    pub max_draw_buffers: gl::types::GLint,

    /// Maximum number of vertices per patch. `None` if tessellation is not supported.
    pub max_patch_vertices: Option<gl::types::GLint>,
}

/// Loads the capabilities.
pub fn get_capabilities(gl: &gl::Gl, version: &GlVersion, extensions: &ExtensionsList)
                        -> Capabilities
{
    use std::mem;

    Capabilities {
        shader_compiler: if version >= &GlVersion(Api::Gl, 1, 0) {
            true
        } else {
            unsafe {
                let mut val = mem::uninitialized();
                gl.GetBooleanv(gl::SHADER_COMPILER, &mut val);
                val != 0
            }
        },

        stereo: unsafe {
            if version >= &GlVersion(Api::Gl, 1, 0) {
                let mut val: gl::types::GLboolean = mem::uninitialized();
                gl.GetBooleanv(gl::STEREO, &mut val);
                val != 0
            } else {
                false
            }
        },

        depth_bits: unsafe {
            let mut value = mem::uninitialized();

            if version >= &GlVersion(Api::Gl, 3, 0) {
                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::DEPTH,
                                                       gl::FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE,
                                                       &mut value);
            } else {
                gl.GetIntegerv(gl::DEPTH_BITS, &mut value);
            };

            match value {
                0 => None,
                v => Some(v as u16),
            }
        },

        stencil_bits: unsafe {
            let mut value = mem::uninitialized();

            if version >= &GlVersion(Api::Gl, 3, 0) {
                gl.GetFramebufferAttachmentParameteriv(gl::FRAMEBUFFER, gl::STENCIL,
                                                       gl::FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE,
                                                       &mut value);
            } else {
                gl.GetIntegerv(gl::STENCIL_BITS, &mut value);
            };

            match value {
                0 => None,
                v => Some(v as u16),
            }
        },

        max_combined_texture_image_units: unsafe {
            let mut val = 2;
            gl.GetIntegerv(gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mut val);
            val
        },

        max_texture_max_anisotropy: if !extensions.gl_ext_texture_filter_anisotropic {
            None

        } else {
            Some(unsafe {
                let mut val = mem::uninitialized();
                gl.GetFloatv(gl::MAX_TEXTURE_MAX_ANISOTROPY_EXT, &mut val);
                val
            })
        },

        max_viewport_dims: unsafe {
            let mut val: [gl::types::GLint; 2] = [ 0, 0 ];
            gl.GetIntegerv(gl::MAX_VIEWPORT_DIMS, val.as_mut_ptr());
            (val[0], val[1])
        },

        max_draw_buffers: unsafe {
            if gl.version >= &GlVersion(Api::Gl, 2, 0) ||
                gl.version >= &GlVersion(Api::GlEs, 3, 0)
            {
                let mut val = 1;
                gl.GetIntegerv(gl::MAX_DRAW_BUFFERS, &mut val);
                val
            } else {
                1
            }
        },

        max_patch_vertices: if version >= &GlVersion(Api::Gl, 4, 0) ||
            extensions.gl_arb_tessellation_shader
        {
            Some(unsafe {
                let mut val = mem::uninitialized();
                gl.GetIntegerv(gl::MAX_PATCH_VERTICES, &mut val);
                val
            })

        } else {
            None
        },
    }
}
<|endoftext|>


<commit_before>use std::error::FromError;

#[macro_export]
macro_rules! try {
    ($expression: expr) => {
        match ::triable::Triable::try($expression) {
            ::triable::TriableResult::Expression(value) => value,
            ::triable::TriableResult::EarlyReturn(value) => return value,
        }
    };
}

// Work around Servo’s Rust version not having $crate yet.
mod triable {
    pub use super::{Triable, TriableResult};
}

pub enum TriableResult<Expr, Return> {
    Expression(Expr),
    EarlyReturn(Return),
}

pub trait Triable<Expr, Return> {
    fn try(self) -> TriableResult<Expr, Return>;
}

impl<T1, T2, Err1, Err2> Triable<T1, Result<T2, Err2>> for Result<T1, Err1>
where Err2: FromError<Err1> {
    fn try(self) -> TriableResult<T1, Result<T2, Err2>> {
        match self {
            Ok(value) => TriableResult::Expression(value),
            Err(error) => TriableResult::EarlyReturn(Err(FromError::from_error(error)))
        }
    }
}

impl<T1, T2> Triable<T1, Option<T2>> for Option<T1> {
    fn try(self) -> TriableResult<T1, Option<T2>> {
        match self {
            Some(value) => TriableResult::Expression(value),
            None => TriableResult::EarlyReturn(None)
        }
    }
}

impl<T1, T2> Triable<T1, Result<T2, ()>> for Option<T1> {
    fn try(self) -> TriableResult<T1, Result<T2, ()>> {
        match self {
            Some(value) => TriableResult::Expression(value),
            None => TriableResult::EarlyReturn(Err(()))
        }
    }
}

impl<T1, T2> Triable<T1, Option<T2>> for Result<T1, ()> {
    fn try(self) -> TriableResult<T1, Option<T2>> {
        match self {
            Ok(value) => TriableResult::Expression(value),
            Err(()) => TriableResult::EarlyReturn(None)
        }
    }
}

#[test]
fn result() {
    fn ok() -> Result<i32, ()> {
        Ok(try!(Ok(4)))
    }
    assert_eq!(ok(), Ok(4));

    fn err() -> Result<i32, ()> {
        Ok(try!(Err(())))
    }
    assert_eq!(err(), Err(()));
}

#[test]
fn option() {
    fn some() -> Option<i32> {
        Some(try!(Some(5)))
    }
    assert_eq!(some(), Some(5));

    fn none() -> Option<i32> {
        Some(try!(None))
    }
    assert_eq!(none(), None);
}

#[test]
fn option_to_result() {
    fn ok() -> Result<i32, ()> {
        Ok(try!(Some(4)))
    }
    assert_eq!(ok(), Ok(4));

    fn err() -> Result<i32, ()> {
        Ok(try!(None))
    }
    assert_eq!(err(), Err(()));
}

#[test]
fn result_to_option() {
    fn some() -> Option<i32> {
        Some(try!(Ok(5)))
    }
    assert_eq!(some(), Some(5));

    fn none() -> Option<i32> {
        Some(try!(Err(())))
    }
    assert_eq!(none(), None);
}

<commit_msg>Triable: add bool, with conversions to and from Option<()> and Result<(), ()><commit_after>use std::error::FromError;

#[macro_export]
macro_rules! try {
    ($expression: expr) => {
        match ::triable::Triable::try($expression) {
            ::triable::TriableResult::Expression(value) => value,
            ::triable::TriableResult::EarlyReturn(value) => return value,
        }
    };
}

// Work around Servo’s Rust version not having $crate yet.
mod triable {
    pub use super::{Triable, TriableResult};
}

pub enum TriableResult<Expr, Return> {
    Expression(Expr),
    EarlyReturn(Return),
}

pub trait Triable<Expr, Return> {
    fn try(self) -> TriableResult<Expr, Return>;
}

impl<T1, T2, Err1, Err2> Triable<T1, Result<T2, Err2>> for Result<T1, Err1>
where Err2: FromError<Err1> {
    fn try(self) -> TriableResult<T1, Result<T2, Err2>> {
        match self {
            Ok(value) => TriableResult::Expression(value),
            Err(error) => TriableResult::EarlyReturn(Err(FromError::from_error(error)))
        }
    }
}

impl<T1, T2> Triable<T1, Option<T2>> for Option<T1> {
    fn try(self) -> TriableResult<T1, Option<T2>> {
        match self {
            Some(value) => TriableResult::Expression(value),
            None => TriableResult::EarlyReturn(None)
        }
    }
}

impl<T1, T2> Triable<T1, Result<T2, ()>> for Option<T1> {
    fn try(self) -> TriableResult<T1, Result<T2, ()>> {
        match self {
            Some(value) => TriableResult::Expression(value),
            None => TriableResult::EarlyReturn(Err(()))
        }
    }
}

impl<T1, T2> Triable<T1, Option<T2>> for Result<T1, ()> {
    fn try(self) -> TriableResult<T1, Option<T2>> {
        match self {
            Ok(value) => TriableResult::Expression(value),
            Err(()) => TriableResult::EarlyReturn(None)
        }
    }
}

impl Triable<(), bool> for bool {
    fn try(self) -> TriableResult<(), bool> {
        if self {
            TriableResult::Expression(())
        } else {
            TriableResult::EarlyReturn(false)
        }
    }
}

impl<T> Triable<T, bool> for Result<T, ()> {
    fn try(self) -> TriableResult<T, bool> {
        match self {
            Ok(value) => TriableResult::Expression(value),
            Err(()) => TriableResult::EarlyReturn(false)
        }
    }
}

impl<T> Triable<T, bool> for Option<T> {
    fn try(self) -> TriableResult<T, bool> {
        match self {
            Some(value) => TriableResult::Expression(value),
            None => TriableResult::EarlyReturn(false)
        }
    }
}

impl<T> Triable<(), Result<T, ()>> for bool {
    fn try(self) -> TriableResult<(), Result<T, ()>> {
        if self {
            TriableResult::Expression(())
        } else {
            TriableResult::EarlyReturn(Err(()))
        }
    }
}

impl<T> Triable<(), Option<T>> for bool {
    fn try(self) -> TriableResult<(), Option<T>> {
        if self {
            TriableResult::Expression(())
        } else {
            TriableResult::EarlyReturn(None)
        }
    }
}

#[test]
fn result() {
    fn ok() -> Result<i32, ()> {
        Ok(try!(Ok(4)))
    }
    assert_eq!(ok(), Ok(4));

    fn err() -> Result<i32, ()> {
        Ok(try!(Err(())))
    }
    assert_eq!(err(), Err(()));
}

#[test]
fn option() {
    fn some() -> Option<i32> {
        Some(try!(Some(5)))
    }
    assert_eq!(some(), Some(5));

    fn none() -> Option<i32> {
        Some(try!(None))
    }
    assert_eq!(none(), None);
}

#[test]
fn option_to_result() {
    fn ok() -> Result<i32, ()> {
        Ok(try!(Some(4)))
    }
    assert_eq!(ok(), Ok(4));

    fn err() -> Result<i32, ()> {
        Ok(try!(None))
    }
    assert_eq!(err(), Err(()));
}

#[test]
fn result_to_option() {
    fn some() -> Option<i32> {
        Some(try!(Ok(5)))
    }
    assert_eq!(some(), Some(5));

    fn none() -> Option<i32> {
        Some(try!(Err(())))
    }
    assert_eq!(none(), None);
}

#[test]
fn bool() {
    fn true_() -> bool {
        try!(true);
        true
    }
    assert_eq!(true_(), true);

    fn false_() -> bool {
        try!(false);
        true
    }
    assert_eq!(false_(), false);
}

#[test]
fn option_to_bool() {
    fn true_() -> bool {
        try!(Some(5));
        true
    }
    assert_eq!(true_(), true);

    fn false_() -> bool {
        try!(None);
        true
    }
    assert_eq!(false_(), false);
}

#[test]
fn result_to_bool() {
    fn true_() -> bool {
        try!(Ok(5));
        true
    }
    assert_eq!(true_(), true);

    fn false_() -> bool {
        try!(Err(()));
        true
    }
    assert_eq!(false_(), false);
}

#[test]
fn bool_to_result() {
    fn ok() -> Result<(), ()> {
        Ok(try!(true))
    }
    assert_eq!(ok(), Ok(()));

    fn err() -> Result<(), ()> {
        Ok(try!(false))
    }
    assert_eq!(err(), Err(()));
}

#[test]
fn bool_to_option() {
    fn some() -> Option<()> {
        Some(try!(true))
    }
    assert_eq!(some(), Some(()));

    fn none() -> Option<()> {
        Some(try!(false))
    }
    assert_eq!(none(), None);
}
<|endoftext|>


<commit_before>use hubcaps::{
    self,
    gists::{self, Content, GistOptions},
    Credentials, Github,
};
use hyper;
use hyper_tls;
use std::collections::HashMap;
use tokio::{prelude::Future, runtime::current_thread::Runtime};

const FILENAME: &str = "playground.rs";
const DESCRIPTION: &str = "Code shared from the Rust Playground";

pub struct Gist {
    pub id: String,
    pub url: String,
    pub code: String,
}

impl From<gists::Gist> for Gist {
    fn from(other: gists::Gist) -> Self {
        let mut files: Vec<_> = other.files
            .into_iter()
            .map(|(name, file)| (name, file.content.unwrap_or_default()))
            .collect();

        files.sort_by(|&(ref name1, _), &(ref name2, _)| name1.cmp(name2));

        let code = match files.len() {
            0 | 1 => files.into_iter().map(|(_, content)| content).collect(),
            _ => {
                files
                    .into_iter()
                    .map(|(name, content)| format!("// {}\n\n{}\n\n", name, content))
                    .collect()
            }
        };

        Gist {
            id: other.id,
            url: other.html_url,
            code: code,
        }
    }
}

pub fn create(token: String, code: String) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(create_future(token, code))
        .expect("Unable to create gist")
    // TODO: Better reporting of failures
}

pub fn create_future(token: String, code: String) -> impl Future<Item = Gist, Error = hubcaps::Error> {
    let github = github(token);

    let file = Content {
        filename: None,
        content: code,
    };

    let mut files = HashMap::new();
    files.insert(FILENAME.into(), file);

    let options = GistOptions {
        description: Some(DESCRIPTION.into()),
        public: Some(true),
        files,
    };

    github
        .gists()
        .create(&options)
        .map(Into::into)
}

pub fn load(token: String, id: &str) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(load_future(token, id))
        .expect("Unable to load gist")
    // TODO: Better reporting of a 404
}

pub fn load_future(token: String, id: &str) -> impl Future<Item = Gist, Error = ::hubcaps::Error> {
    let github = github(token);

    github
        .gists()
        .get(id)
        .map(Into::into)
}

type HubcapConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;

fn github(token: String) -> Github<HubcapConnector> {
    Github::new(
        String::from("The Rust Playground"),
        Some(Credentials::Token(token)),
    )
}
<commit_msg>Remove unneeded explicit `ref`<commit_after>use hubcaps::{
    self,
    gists::{self, Content, GistOptions},
    Credentials, Github,
};
use hyper;
use hyper_tls;
use std::collections::HashMap;
use tokio::{prelude::Future, runtime::current_thread::Runtime};

const FILENAME: &str = "playground.rs";
const DESCRIPTION: &str = "Code shared from the Rust Playground";

pub struct Gist {
    pub id: String,
    pub url: String,
    pub code: String,
}

impl From<gists::Gist> for Gist {
    fn from(other: gists::Gist) -> Self {
        let mut files: Vec<_> = other.files
            .into_iter()
            .map(|(name, file)| (name, file.content.unwrap_or_default()))
            .collect();

        files.sort_by(|(name1, _), (name2, _)| name1.cmp(name2));

        let code = match files.len() {
            0 | 1 => files.into_iter().map(|(_, content)| content).collect(),
            _ => {
                files
                    .into_iter()
                    .map(|(name, content)| format!("// {}\n\n{}\n\n", name, content))
                    .collect()
            }
        };

        Gist {
            id: other.id,
            url: other.html_url,
            code: code,
        }
    }
}

pub fn create(token: String, code: String) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(create_future(token, code))
        .expect("Unable to create gist")
    // TODO: Better reporting of failures
}

pub fn create_future(token: String, code: String) -> impl Future<Item = Gist, Error = hubcaps::Error> {
    let github = github(token);

    let file = Content {
        filename: None,
        content: code,
    };

    let mut files = HashMap::new();
    files.insert(FILENAME.into(), file);

    let options = GistOptions {
        description: Some(DESCRIPTION.into()),
        public: Some(true),
        files,
    };

    github
        .gists()
        .create(&options)
        .map(Into::into)
}

pub fn load(token: String, id: &str) -> Gist {
    Runtime::new()
        .expect("unable to create runtime")
        .block_on(load_future(token, id))
        .expect("Unable to load gist")
    // TODO: Better reporting of a 404
}

pub fn load_future(token: String, id: &str) -> impl Future<Item = Gist, Error = ::hubcaps::Error> {
    let github = github(token);

    github
        .gists()
        .get(id)
        .map(Into::into)
}

type HubcapConnector = hyper_tls::HttpsConnector<hyper::client::HttpConnector>;

fn github(token: String) -> Github<HubcapConnector> {
    Github::new(
        String::from("The Rust Playground"),
        Some(Credentials::Token(token)),
    )
}
<|endoftext|>


<commit_before>use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use palette::convert::FromColorUnclamped;
use palette::encoding;
use palette::{Hsl, Hsv, Hwb, LinSrgb, Srgb};

#[path = "../tests/convert/data_color_mine.rs"]
#[allow(dead_code)]
mod data_color_mine;
use data_color_mine::{load_data, ColorMine};

/* Benches the following conversions:
    - rgb to linear
    - rgb to hsl
    - hsv to hsl
    - rgb to hsv
    - hsl to hsv
    - hwb to hsv
    - hsv to hwb
    - xyz to rgb
    - hsl to rgb
    - hsv to rgb
    - linsrgb to rgb
    - rgb_u8 to linsrgb_f32
    - linsrgb_f32 to rgb_u8
*/

fn rgb_conversion(c: &mut Criterion) {
    let mut group = c.benchmark_group("Rgb family");
    let colormine: Vec<ColorMine> = load_data();
    let rgb: Vec<Srgb> = colormine.iter().map(|x| Srgb::from(x.linear_rgb)).collect();
    let rgb_u8: Vec<Srgb<u8>> = rgb.iter().map(|x| x.into_format().into()).collect();

    group.throughput(Throughput::Elements(colormine.len() as u64));

    group.bench_with_input("rgb to linsrgb", &rgb, |b, rgb| {
        b.iter(|| {
            for c in rgb {
                black_box(c.into_linear());
            }
        })
    });
    group.bench_with_input("rgb to hsl", &rgb, |b, rgb| {
        b.iter(|| {
            for c in rgb {
                black_box(Hsl::from_color_unclamped(*c));
            }
        })
    });
    group.bench_with_input("hsv to hsl", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsl::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("rgb to hsv", &rgb, |b, rgb| {
        b.iter(|| {
            for c in rgb {
                black_box(Hsv::from_color_unclamped(*c));
            }
        })
    });
    group.bench_with_input("hsl to hsv", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsv::from_color_unclamped(c.hsl));
            }
        })
    });
    group.bench_with_input("hwb to hsv", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsv::<encoding::Srgb, _>::from_color_unclamped(c.hwb));
            }
        })
    });
    group.bench_with_input("hsv to hwb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hwb::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("xyz to linsrgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(LinSrgb::from_color_unclamped(c.xyz));
            }
        })
    });
    group.bench_with_input("hsl to rgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_color_unclamped(c.hsl));
            }
        })
    });
    group.bench_with_input("hsv to rgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("linsrgb to rgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_linear(c.linear_rgb));
            }
        })
    });
    group.bench_with_input("rgb_u8 to linsrgb_f32", &rgb_u8, |b, rgb_u8| {
        b.iter(|| {
            for c in rgb_u8 {
                black_box(c.into_format::<f32>().into_linear());
            }
        })
    });
    group.bench_with_input("linsrgb_f32 to rgb_u8", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_linear(c.linear_rgb).into_format::<u8>());
            }
        })
    });

    group.finish();
}

criterion_group!(benches, rgb_conversion);
criterion_main!(benches);
<commit_msg>Add benchmarks for converting between linear and nonlinear HSV, HSL and HWB<commit_after>use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput};
use palette::convert::FromColorUnclamped;
use palette::encoding;
use palette::{Hsl, Hsv, Hwb, IntoColor, LinSrgb, Srgb};

type SrgbHsv = Hsv<encoding::Srgb>;
type SrgbHsl = Hsl<encoding::Srgb>;
type SrgbHwb = Hwb<encoding::Srgb>;
type LinHsv = Hsv<encoding::Linear<encoding::Srgb>>;
type LinHsl = Hsl<encoding::Linear<encoding::Srgb>>;
type LinHwb = Hwb<encoding::Linear<encoding::Srgb>>;

#[path = "../tests/convert/data_color_mine.rs"]
#[allow(dead_code)]
mod data_color_mine;
use data_color_mine::{load_data, ColorMine};

/* Benches the following conversions:
    - rgb to linear
    - rgb to hsl
    - hsv to hsl
    - rgb to hsv
    - hsl to hsv
    - hwb to hsv
    - hsv to hwb
    - xyz to rgb
    - hsl to rgb
    - hsv to rgb
    - hsv to linear hsv
    - linear hsv to hsv
    - hsl to linear hsl
    - linear hsl to hsl
    - hwb to linear hwb
    - linear hwb to hwb
    - linsrgb to rgb
    - rgb_u8 to linsrgb_f32
    - linsrgb_f32 to rgb_u8
*/

fn rgb_conversion(c: &mut Criterion) {
    let mut group = c.benchmark_group("Rgb family");
    let colormine: Vec<ColorMine> = load_data();
    let rgb_u8: Vec<Srgb<u8>> = colormine.iter().map(|x| x.rgb.into_format()).collect();

    let linear_hsv: Vec<LinHsv> = colormine.iter().map(|x| x.hsv.into_color()).collect();
    let linear_hsl: Vec<LinHsl> = colormine.iter().map(|x| x.hsl.into_color()).collect();
    let linear_hwb: Vec<LinHwb> = colormine.iter().map(|x| x.hwb.into_color()).collect();

    group.throughput(Throughput::Elements(colormine.len() as u64));

    group.bench_with_input("rgb to linsrgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(c.rgb.into_linear());
            }
        })
    });
    group.bench_with_input("rgb to hsl", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsl::from_color_unclamped(c.rgb));
            }
        })
    });
    group.bench_with_input("hsv to hsl", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsl::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("rgb to hsv", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsv::from_color_unclamped(c.rgb));
            }
        })
    });
    group.bench_with_input("hsl to hsv", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsv::from_color_unclamped(c.hsl));
            }
        })
    });
    group.bench_with_input("hwb to hsv", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hsv::<encoding::Srgb, _>::from_color_unclamped(c.hwb));
            }
        })
    });
    group.bench_with_input("hsv to hwb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Hwb::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("xyz to linsrgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(LinSrgb::from_color_unclamped(c.xyz));
            }
        })
    });
    group.bench_with_input("hsl to rgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_color_unclamped(c.hsl));
            }
        })
    });
    group.bench_with_input("hsv to rgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("hsv to linear hsv", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(LinHsv::from_color_unclamped(c.hsv));
            }
        })
    });
    group.bench_with_input("linear hsv to hsv", &linear_hsv, |b, linear_hsv| {
        b.iter(|| {
            for &c in linear_hsv {
                black_box(SrgbHsv::from_color_unclamped(c));
            }
        })
    });
    group.bench_with_input("hsl to linear hsl", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(LinHsl::from_color_unclamped(c.hsl));
            }
        })
    });
    group.bench_with_input("linear hsl to hsl", &linear_hsl, |b, linear_hsl| {
        b.iter(|| {
            for &c in linear_hsl {
                black_box(SrgbHsl::from_color_unclamped(c));
            }
        })
    });
    group.bench_with_input("hwb to linear hwb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(LinHwb::from_color_unclamped(c.hwb));
            }
        })
    });
    group.bench_with_input("linear hwb to hwb", &linear_hwb, |b, linear_hwb| {
        b.iter(|| {
            for &c in linear_hwb {
                black_box(SrgbHwb::from_color_unclamped(c));
            }
        })
    });
    group.bench_with_input("linsrgb to rgb", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_linear(c.linear_rgb));
            }
        })
    });
    group.bench_with_input("rgb_u8 to linsrgb_f32", &rgb_u8, |b, rgb_u8| {
        b.iter(|| {
            for c in rgb_u8 {
                black_box(c.into_format::<f32>().into_linear());
            }
        })
    });
    group.bench_with_input("linsrgb_f32 to rgb_u8", &colormine, |b, colormine| {
        b.iter(|| {
            for c in colormine {
                black_box(Srgb::from_linear(c.linear_rgb).into_format::<u8>());
            }
        })
    });

    group.finish();
}

criterion_group!(benches, rgb_conversion);
criterion_main!(benches);
<|endoftext|>


<commit_before>use std::iter;
use std::ops::{Index, IndexMut};

#[derive(Clone, PartialEq, Eq)]
pub struct CellBuffer {
    cols: usize,
    rows: usize,
    cells: Vec<Vec<Cell>>,
}

impl CellBuffer {
    pub fn new(cols: usize, rows: usize) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::default())
    }

    pub fn with_char(cols: usize, rows: usize, ch: char) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_char(ch))
    }

    pub fn with_styles(cols: usize, rows: usize, fg: Style, bg: Style) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_styles(fg, bg))
    }

    pub fn with_cell(cols: usize, rows: usize, cell: Cell) -> CellBuffer {
        CellBuffer {
            cols: cols,
            rows: rows,
            cells: vec![vec![cell; rows]; cols],
        }
    }

    pub fn cols(&self) -> usize {
        self.cols
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn size(&self) -> (usize, usize) {
        (self.cols, self.rows)
    }

    pub fn clear(&mut self) {
        self.clear_with_cell(Cell::default());
    }

    pub fn clear_with_char(&mut self, ch: char) {
        self.clear_with_cell(Cell::with_char(ch));
    }

    pub fn clear_with_styles(&mut self, fg: Style, bg: Style) {
        self.clear_with_cell(Cell::with_styles(fg, bg));
    }

    pub fn clear_with_cell(&mut self, blank: Cell) {
        for col in &mut self.cells {
            for cell in col.iter_mut() {
                cell.ch = blank.ch;
                cell.fg = blank.fg;
                cell.bg = blank.bg;
            }
        }
    }

    pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Cell) {
        if self.cols == newcols && self.rows == newrows {
            return;
        }

        if newcols > self.cols {
            if newrows > self.rows {
                for col in &mut self.cells {
                    col.extend(iter::repeat(blank).take(newrows - self.rows));
                }
            } else {
                for col in &mut self.cells {
                    col.truncate(newrows);
                }
            }
            self.cells.extend(iter::repeat(vec![blank; newrows]).take(newcols - self.cols));
        } else {
            if newrows > self.rows {
                for col in &mut self.cells {
                    col.extend(iter::repeat(blank).take(newrows - self.rows));
                }
            } else {
                for col in &mut self.cells {
                    col.truncate(newrows);
                }
            }
            self.cells.truncate(newcols);
        }

        self.cols = newcols;
        self.rows = newrows;
    }
}

impl Default for CellBuffer {
    fn default() -> CellBuffer {
        CellBuffer::with_cell(0, 0, Cell::default())
    }
}

impl Index<usize> for CellBuffer {
    type Output = Vec<Cell>;

    fn index(&self, index: usize) -> &Vec<Cell> {
        &self.cells[index]
    }
}

impl IndexMut<usize> for CellBuffer {
    fn index_mut(&mut self, index: usize) -> &mut Vec<Cell> {
        &mut self.cells[index]
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Cell {
    ch: char,
    fg: Style,
    bg: Style,
}

impl Cell {
    pub fn new(ch: char, fg: Style, bg: Style) -> Cell {
        Cell {
            ch: ch,
            fg: fg,
            bg: bg,
        }
    }

    pub fn with_char(ch: char) -> Cell {
        Cell::new(ch, Style::default(), Style::default())
    }

    pub fn with_styles(fg: Style, bg: Style) -> Cell {
        Cell::new(' ', fg, bg)
    }

    pub fn ch(&self) -> char {
        self.ch
    }

    pub fn set_ch(&mut self, newch: char) {
        self.ch = newch;
    }

    pub fn fg(&self) -> Style {
        self.fg
    }

    pub fn set_fg(&mut self, newfg: Style) {
        self.fg = newfg;
    }

    pub fn bg(&self) -> Style {
        self.bg
    }

    pub fn set_bg(&mut self, newbg: Style) {
        self.bg = newbg;
    }
}

impl Default for Cell {
    fn default() -> Cell {
        Cell::new(' ', Style::default(), Style::default())
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Style(Color, Attr);

impl Style {
    pub fn new(color: Color, attr: Attr) -> Style {
        Style(color, attr)
    }

    pub fn with_color(c: Color) -> Style {
        Style::new(c, Attr::Default)
    }

    pub fn with_attr(a: Attr) -> Style {
        Style::new(Color::Default, a)
    }

    pub fn color(&self) -> Color {
        self.0
    }

    pub fn set_color(&mut self, newcolor: Color) {
        self.0 = newcolor;
    }

    pub fn attr(&self) -> Attr {
        self.1
    }

    pub fn set_attr(&mut self, newattr: Attr) {
        self.1 = newattr;
    }
}

impl Default for Style {
    fn default() -> Style {
        Style::new(Color::Default, Attr::Default)
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Color {
    Black = 0x0000,
    Red = 0x0001,
    Green = 0x0002,
    Yellow = 0x0003,
    Blue = 0x0004,
    Magenta = 0x0005,
    Cyan = 0x0006,
    White = 0x0007,
    Default,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Attr {
    Default,
    Bold,
    Underline,
    Reverse,
}

<commit_msg>return &mut references on set methods to facilitate chaining<commit_after>use std::iter;
use std::ops::{Index, IndexMut};

#[derive(Clone, PartialEq, Eq)]
pub struct CellBuffer {
    cols: usize,
    rows: usize,
    cells: Vec<Vec<Cell>>,
}

impl CellBuffer {
    pub fn new(cols: usize, rows: usize) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::default())
    }

    pub fn with_char(cols: usize, rows: usize, ch: char) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_char(ch))
    }

    pub fn with_styles(cols: usize, rows: usize, fg: Style, bg: Style) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_styles(fg, bg))
    }

    pub fn with_cell(cols: usize, rows: usize, cell: Cell) -> CellBuffer {
        CellBuffer {
            cols: cols,
            rows: rows,
            cells: vec![vec![cell; rows]; cols],
        }
    }

    pub fn cols(&self) -> usize {
        self.cols
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn size(&self) -> (usize, usize) {
        (self.cols, self.rows)
    }

    pub fn clear(&mut self) {
        self.clear_with_cell(Cell::default());
    }

    pub fn clear_with_char(&mut self, ch: char) {
        self.clear_with_cell(Cell::with_char(ch));
    }

    pub fn clear_with_styles(&mut self, fg: Style, bg: Style) {
        self.clear_with_cell(Cell::with_styles(fg, bg));
    }

    pub fn clear_with_cell(&mut self, blank: Cell) {
        for col in &mut self.cells {
            for cell in col.iter_mut() {
                cell.ch = blank.ch;
                cell.fg = blank.fg;
                cell.bg = blank.bg;
            }
        }
    }

    pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Cell) {
        if self.cols == newcols && self.rows == newrows {
            return;
        }

        if newcols > self.cols {
            if newrows > self.rows {
                for col in &mut self.cells {
                    col.extend(iter::repeat(blank).take(newrows - self.rows));
                }
            } else {
                for col in &mut self.cells {
                    col.truncate(newrows);
                }
            }
            self.cells.extend(iter::repeat(vec![blank; newrows]).take(newcols - self.cols));
        } else {
            if newrows > self.rows {
                for col in &mut self.cells {
                    col.extend(iter::repeat(blank).take(newrows - self.rows));
                }
            } else {
                for col in &mut self.cells {
                    col.truncate(newrows);
                }
            }
            self.cells.truncate(newcols);
        }

        self.cols = newcols;
        self.rows = newrows;
    }
}

impl Default for CellBuffer {
    fn default() -> CellBuffer {
        CellBuffer::with_cell(0, 0, Cell::default())
    }
}

impl Index<usize> for CellBuffer {
    type Output = Vec<Cell>;

    fn index(&self, index: usize) -> &Vec<Cell> {
        &self.cells[index]
    }
}

impl IndexMut<usize> for CellBuffer {
    fn index_mut(&mut self, index: usize) -> &mut Vec<Cell> {
        &mut self.cells[index]
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Cell {
    ch: char,
    fg: Style,
    bg: Style,
}

impl Cell {
    pub fn new(ch: char, fg: Style, bg: Style) -> Cell {
        Cell {
            ch: ch,
            fg: fg,
            bg: bg,
        }
    }

    pub fn with_char(ch: char) -> Cell {
        Cell::new(ch, Style::default(), Style::default())
    }

    pub fn with_styles(fg: Style, bg: Style) -> Cell {
        Cell::new(' ', fg, bg)
    }

    pub fn ch(&self) -> char {
        self.ch
    }

    pub fn set_ch(&mut self, newch: char) -> &mut Cell {
        self.ch = newch;
        self
    }

    pub fn fg(&self) -> Style {
        self.fg
    }

    pub fn set_fg(&mut self, newfg: Style) -> &mut Cell {
        self.fg = newfg;
        self
    }

    pub fn bg(&self) -> Style {
        self.bg
    }

    pub fn set_bg(&mut self, newbg: Style) -> &mut Cell {
        self.bg = newbg;
        self
    }
}

impl Default for Cell {
    fn default() -> Cell {
        Cell::new(' ', Style::default(), Style::default())
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Style(Color, Attr);

impl Style {
    pub fn new(color: Color, attr: Attr) -> Style {
        Style(color, attr)
    }

    pub fn with_color(c: Color) -> Style {
        Style::new(c, Attr::Default)
    }

    pub fn with_attr(a: Attr) -> Style {
        Style::new(Color::Default, a)
    }

    pub fn color(&self) -> Color {
        self.0
    }

    pub fn set_color(&mut self, newcolor: Color) -> &mut Style {
        self.0 = newcolor;
        self
    }

    pub fn attr(&self) -> Attr {
        self.1
    }

    pub fn set_attr(&mut self, newattr: Attr) -> &mut Style {
        self.1 = newattr;
        self
    }
}

impl Default for Style {
    fn default() -> Style {
        Style::new(Color::Default, Attr::Default)
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Color {
    Black = 0x0000,
    Red = 0x0001,
    Green = 0x0002,
    Yellow = 0x0003,
    Blue = 0x0004,
    Magenta = 0x0005,
    Cyan = 0x0006,
    White = 0x0007,
    Default,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Attr {
    Default,
    Bold,
    Underline,
    Reverse,
}

<|endoftext|>


<commit_before>use std::io::net::ip::{SocketAddr, IpAddr};
use std::io::{TcpListener, TcpStream, Listener, Acceptor, TimedOut, IoError};
use std::io::net::tcp::{TcpAcceptor, TcpStream};
use std::collections::hashmap::HashMap;
use std::comm::{channel, Sender, Receiver};
use std::io::timer::Timer;
use std::ops::Drop;
use std::task::TaskBuilder;
use std::clone::Clone;

use serialize::{Decodable, Encodable};
use serialize::json::{Encoder, Decoder, DecoderError};
use uuid::Uuid;

use transport::Transport;
use result::{GossipResult, io_err};
use connection::Connection;
use message::{Message, Join};
use tcp::connection::TcpConnection;
use server::Server;

/// Messages that the AcceptingManager is communicating with.
pub enum AcceptingMsg {
    Exit
}

/// Wrap the common idiom of accepting a string and port into a
/// single source that's easier to pass around. It also mitigates the
/// naming issue of port (u16) and port (Receiver).
#[deriving(Show, PartialEq, Clone)]
pub struct Addr {
    pub ip: String,
    pub port: u16
}

impl Addr {
    /// Create a new instance of the Addr record.
    pub fn new(ip: String, port: u16) -> Addr {
        Addr {
            ip: ip,
            port: port
        }
    }
}

/// Alias the type to be easier to use.
pub type AcceptingTask = Sender<AcceptingMsg>;

/// The AcceptingManager is responsible for managing incoming
/// TCP connections/streams. The manager first creates a new TcpListener
/// and TcpAcceptor in order to start listening in. All communication
/// then happens through the use of channels. A new StreamManager will
/// be created in order to handle the appropriate streams.
struct AcceptingManager {
    port: Receiver<AcceptingMsg>,
    acceptor: Option<TcpAcceptor>,
    addr: Addr
}

impl AcceptingManager {
    /// Given a Receiver (port) to read new messages from and an address
    /// create a new context. This does **not** actually create a new
    /// TcpAcceptor and doesn't bind to anything. That happens in the
    /// .start() method.
    pub fn new(port: Receiver<AcceptingMsg>, addr: Addr) -> AcceptingManager {
        AcceptingManager {
            port: port,
            acceptor: None,
            addr: addr
        }
    }

    /// Start listening on the Tcp address and start processing incoming
    /// streams. We also need to continue listening on the channel to see if
    /// we should be shutting down or not.
    ///
    /// Note: It's impossible to shutdown while the task is blocking on
    ///       acceptor.accept() and no more connections are coming through.
    ///       You'll have to physically shutdown the whole process, which is
    ///       kinda ugly, but works.
    pub fn start(&mut self) {

        let acceptor = TcpListener::bind(self.addr.ip.as_slice(), self.addr.port).listen();

        loop {
            match self.port.try_recv() {
                Ok(val) => {
                    match val {
                        Exit => {
                            drop(acceptor);
                            break
                        }
                    }
                },
                Err(err) => {}
            }
        }
    }
}

/// Create a new AcceptingTask responsible for accepting brand new
/// tcp connections and passing them on.
///
/// We initialize a new setup channel that is used to return the correct
/// Sender, which is created inside the task.
pub fn create_accepting_task(addr: Addr) -> AcceptingTask {
    let (setup_chan, setup_port) = channel();
    let builder = TaskBuilder::new().named("AcceptingManager");

    builder.spawn(proc() {
        let (chan, port) = channel();
        setup_chan.send(chan);
        AcceptingManager::new(port, addr).start();
    });

    setup_port.recv()
}

/// A tcp transport has two fundamental elements within: An acceptor (server)
/// and a set of connections. The only job of the acceptor is to, well,
/// accept new connections and store them.
///
/// Connections are how all the nodes will communicate. Each node within
/// the system has a connection to every other node in the cluster. That
/// means, if node A wants to communicate with server B, it'll look up
/// server's B connection and send a message through that medium.
pub struct TcpTransport {
    addr: Addr,
    sender: AcceptingTask
}

impl TcpTransport {

    /// Createa a new local transport. The ip and port are used for the
    /// Acceptor. Thus, having a local address of "0.0.0.0" is the common
    /// practice for the tcp server to be accessible from outside the
    /// current node.
    pub fn listen(ip: &str, port: u16) -> GossipResult<TcpTransport> {

        let addr = Addr::new(ip.to_string(), port);
        let sender = create_accepting_task(addr.clone());

        let mut transport = TcpTransport {
            addr: addr,
            sender: sender
        };

        Ok(transport)
    }
}

#[unsafe_destructor]
impl Drop for TcpTransport {
    fn drop(&mut self) {
        self.close();
    }
}

impl Transport for TcpTransport {

    /// By default, a node does **not** join a cluster automatically. Thus,
    /// one has to manually initiate the join operation.
    ///
    /// To join a cluster, one just needs to establish a connection
    /// with one that already has membership (peer node). The join operation first
    /// establishes the new connection **and** sends a "join" broadcast.
    ///
    /// The peer node is responsible for propagating the new membership details
    /// through a new broadcast.
    fn join<'a, T>(&self, ip: &str, port: u16, server: &Server<'a, T>) -> GossipResult<()> {

        // Establish a new connection with the peer node.
        let mut conn = try!(TcpConnection::connect(ip, port));
        try!(conn.send(Join::new(server)));

        Ok(())
    }

    /// Receive a message from any of the connections.
    fn receive<T: Decodable<Decoder, DecoderError>>(&self) -> GossipResult<T> {
        unimplemented!()
    }

    /// Terminate the accept, along with disconnecting all connections. However,
    /// before doing so, the node will send one last broadcast letting the
    /// cluster know it's going offline.
    fn close(&mut self) -> GossipResult<()> {
        self.sender.send(Exit);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::net::ip::{Ipv4Addr};
    use tcp::connection::TcpConnection;
    use connection::Connection;
    use transport::Transport;

    #[test]
    fn accepting_manager() {
        let addr = Addr::new("127.0.0.1".to_string(), 6553);
        let chan: AcceptingTask = create_accepting_task(addr);
        let conn = TcpConnection::connect("127.0.0.1", 6553).unwrap();
        chan.send(Exit);
    }

    #[test]
    fn new_transport() {
        let addr = "127.0.0.1";
        let port = 5499;

        let mut transport = TcpTransport::listen(addr, port).unwrap();
        let mut connection = TcpConnection::connect(addr, port).unwrap();
    }
}
<commit_msg>Accepting sockets. Now the .accept() method is polling and not blocking<commit_after>use std::io::net::ip::{SocketAddr, IpAddr};
use std::io::{TcpListener, TcpStream, Listener, Acceptor, TimedOut, IoError};
use std::io::net::tcp::{TcpAcceptor, TcpStream};
use std::collections::hashmap::HashMap;
use std::comm::{channel, Sender, Receiver};
use std::io::timer::Timer;
use std::ops::Drop;
use std::task::TaskBuilder;
use std::clone::Clone;

use serialize::{Decodable, Encodable};
use serialize::json::{Encoder, Decoder, DecoderError};
use uuid::Uuid;

use transport::Transport;
use result::{GossipResult, io_err};
use connection::Connection;
use message::{Message, Join};
use tcp::connection::TcpConnection;
use server::Server;

/// Messages that the AcceptingManager is communicating with.
pub enum AcceptingMsg {
    Exit,
    Noop
}

/// Wrap the common idiom of accepting a string and port into a
/// single source that's easier to pass around. It also mitigates the
/// naming issue of port (u16) and port (Receiver).
#[deriving(Show, PartialEq, Clone)]
pub struct Addr {
    pub ip: String,
    pub port: u16
}

impl Addr {
    /// Create a new instance of the Addr record.
    pub fn new(ip: String, port: u16) -> Addr {
        Addr {
            ip: ip,
            port: port
        }
    }
}

/// Alias the type to be easier to use.
pub type AcceptingTask = Sender<AcceptingMsg>;

/// The AcceptingManager is responsible for managing incoming
/// TCP connections/streams. The manager first creates a new TcpListener
/// and TcpAcceptor in order to start listening in. All communication
/// then happens through the use of channels. A new StreamManager will
/// be created in order to handle the appropriate streams.
struct AcceptingManager {
    port: Receiver<AcceptingMsg>,
    acceptor: Option<TcpAcceptor>,
    addr: Addr
}

impl AcceptingManager {
    /// Given a Receiver (port) to read new messages from and an address
    /// create a new context. This does **not** actually create a new
    /// TcpAcceptor and doesn't bind to anything. That happens in the
    /// .start() method.
    pub fn new(port: Receiver<AcceptingMsg>, addr: Addr) -> AcceptingManager {
        AcceptingManager {
            port: port,
            acceptor: None,
            addr: addr
        }
    }

    /// Start listening on the Tcp address and start processing incoming
    /// streams. We also need to continue listening on the channel to see if
    /// we should be shutting down or not.
    ///
    /// Note: It's impossible to shutdown while the task is blocking on
    ///       acceptor.accept() and no more connections are coming through.
    ///       You'll have to physically shutdown the whole process, which is
    ///       kinda ugly, but works.
    pub fn start(&mut self) {

        let mut acceptor = TcpListener::bind(self.addr.ip.as_slice(), self.addr.port).listen().unwrap();
        acceptor.set_timeout(Some(0));

        loop {
            match self.port.try_recv() {
                Ok(val) => {
                    match val {
                        Exit => {
                            drop(acceptor);
                            break
                        },
                        _ => {}
                    }
                },
                Err(err) => {}
            }

            match acceptor.accept() {
                Ok(socket) => {},
                Err(ref e) if e.kind == TimedOut => {},
                Err(e) => println!("err: {}", e)
            }
        }
    }
}

/// Create a new AcceptingTask responsible for accepting brand new
/// tcp connections and passing them on.
///
/// We initialize a new setup channel that is used to return the correct
/// Sender, which is created inside the task.
pub fn create_accepting_task(addr: Addr) -> AcceptingTask {
    let (setup_chan, setup_port) = channel();
    let builder = TaskBuilder::new().named("AcceptingManager");

    builder.spawn(proc() {
        let (chan, port) = channel();
        setup_chan.send(chan);
        AcceptingManager::new(port, addr).start();
    });

    setup_port.recv()
}

/// A tcp transport has two fundamental elements within: An acceptor (server)
/// and a set of connections. The only job of the acceptor is to, well,
/// accept new connections and store them.
///
/// Connections are how all the nodes will communicate. Each node within
/// the system has a connection to every other node in the cluster. That
/// means, if node A wants to communicate with server B, it'll look up
/// server's B connection and send a message through that medium.
pub struct TcpTransport {
    addr: Addr,
    sender: AcceptingTask
}

impl TcpTransport {

    /// Createa a new local transport. The ip and port are used for the
    /// Acceptor. Thus, having a local address of "0.0.0.0" is the common
    /// practice for the tcp server to be accessible from outside the
    /// current node.
    pub fn listen(ip: &str, port: u16) -> GossipResult<TcpTransport> {

        let addr = Addr::new(ip.to_string(), port);
        let sender = create_accepting_task(addr.clone());

        let mut transport = TcpTransport {
            addr: addr,
            sender: sender
        };

        Ok(transport)
    }
}

#[unsafe_destructor]
impl Drop for TcpTransport {
    fn drop(&mut self) {
        self.close();
    }
}

impl Transport for TcpTransport {

    /// By default, a node does **not** join a cluster automatically. Thus,
    /// one has to manually initiate the join operation.
    ///
    /// To join a cluster, one just needs to establish a connection
    /// with one that already has membership (peer node). The join operation first
    /// establishes the new connection **and** sends a "join" broadcast.
    ///
    /// The peer node is responsible for propagating the new membership details
    /// through a new broadcast.
    fn join<'a, T>(&self, ip: &str, port: u16, server: &Server<'a, T>) -> GossipResult<()> {

        // Establish a new connection with the peer node.
        let mut conn = try!(TcpConnection::connect(ip, port));
        try!(conn.send(Join::new(server)));

        Ok(())
    }

    /// Receive a message from any of the connections.
    fn receive<T: Decodable<Decoder, DecoderError>>(&self) -> GossipResult<T> {
        unimplemented!()
    }

    /// Terminate the accept, along with disconnecting all connections. However,
    /// before doing so, the node will send one last broadcast letting the
    /// cluster know it's going offline.
    fn close(&mut self) -> GossipResult<()> {
        self.sender.send(Exit);
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use std::io::net::ip::{Ipv4Addr};
    use std::io::Timer;
    use std::comm::channel;
    use tcp::connection::TcpConnection;
    use connection::Connection;
    use transport::Transport;

    #[test]
    fn accepting_manager() {
        let addr = Addr::new("127.0.0.1".to_string(), 6553);
        let chan: AcceptingTask = create_accepting_task(addr);
        let conn = TcpConnection::connect("127.0.0.1", 6553).unwrap();
        chan.send(Exit);
    }

    #[test]
    fn new_transport() {
        let addr = "127.0.0.1";
        let port = 5499;

        let mut transport = TcpTransport::listen(addr, port).unwrap();
        let mut connection = TcpConnection::connect(addr, port).unwrap();
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use core::types::{MInt, MapPos, Size2};
use core::core::Unit;
use core::game_state::GameState;
use core::dir::Dir;

struct Tile {
    cost: MInt,
    parent: Option<Dir>,
}

struct Map {
    size: Size2<MInt>,
    tiles: Vec<Tile>,
}

fn max_cost() -> MInt {
    30000
}

impl<'a> Map {
    fn tile_mut(&'a mut self, pos: MapPos) -> &'a mut Tile {
        self.tiles.get_mut((pos.v.x + pos.v.y * self.size.w) as uint)
    }

    fn tile(&'a self, pos: MapPos) -> &'a Tile {
        &self.tiles[(pos.v.x + pos.v.y * self.size.w) as uint]
    }

    fn is_inboard(&self, pos: MapPos) -> bool {
        let x = pos.v.x;
        let y = pos.v.y;
        x >= 0 && y >= 0 && x < self.size.w && y < self.size.h
    }
}

pub struct Pathfinder {
    queue: Vec<MapPos>,
    map: Map,
}

fn create_tiles(tiles_count: MInt) -> Vec<Tile> {
    let mut tiles = Vec::new();
    for _ in range(0, tiles_count) {
        tiles.push(Tile {
            cost: 0,
            parent: None,
        });
    }
    tiles
}

impl Pathfinder {
    pub fn new(map_size: Size2<MInt>) -> Pathfinder {
        let tiles_count = map_size.w * map_size.h;
        Pathfinder {
            queue: Vec::new(),
            map: Map {
                size: map_size,
                tiles: create_tiles(tiles_count),
            },
        }
    }

    fn process_neighbour_pos(
        &mut self,
        _: &GameState,
        _: &Unit, // TODO: use unit`s type and action points later
        original_pos: MapPos,
        neighbour_pos: MapPos
    ) {
        let old_cost = self.map.tile(original_pos).cost;
        let tile = self.map.tile_mut(neighbour_pos);
        let new_cost: MInt = old_cost + 1;
        if tile.cost > new_cost {
            self.queue.push(neighbour_pos);
            // update neighbour tile info
            tile.cost = new_cost;
            let dir = Dir::get_dir_from_to(neighbour_pos, original_pos);
            tile.parent = Some(dir);
        }
    }

    fn clean_map(&mut self) {
        for tile in self.map.tiles.mut_iter() {
            tile.cost = max_cost();
            tile.parent = None;
        }
    }

    fn try_to_push_neighbours(
        &mut self,
        state: &GameState,
        unit: &Unit,
        pos: MapPos
    ) {
        assert!(self.map.is_inboard(pos));
        for i in range(0i, 6) {
            let neighbour_pos = Dir::get_neighbour_pos(pos, Dir::from_int(i as MInt));
            if self.map.is_inboard(neighbour_pos) {
                self.process_neighbour_pos(
                    state, unit, pos, neighbour_pos);
            }
        }
    }

    fn push_start_pos_to_queue(&mut self, start_pos: MapPos) {
        self.queue.push(start_pos);
        let start_tile = self.map.tile_mut(start_pos);
        start_tile.cost = 0;
        start_tile.parent = None;
    }

    pub fn fill_map(&mut self, state: &GameState, unit: &Unit) {
        assert!(self.queue.len() == 0);
        self.clean_map();
        self.push_start_pos_to_queue(unit.pos);
        while self.queue.len() != 0 {
            let pos = self.queue.shift().unwrap();
            self.try_to_push_neighbours(state, unit, pos);
        }
    }

    pub fn get_path(&self, destination: MapPos) -> Vec<MapPos> {
        let mut path = Vec::new();
        let mut pos = destination;
        assert!(self.map.is_inboard(pos));
        path.push(destination);
        while self.map.tile(pos).cost != 0 {
            let parent_dir = self.map.tile(pos).parent.unwrap();
            pos = Dir::get_neighbour_pos(pos, parent_dir);
            assert!(self.map.is_inboard(pos));
            path.push(pos);
        }
        path.reverse();
        path
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Fixed pathfinder<commit_after>// See LICENSE file for copyright and license details.

use core::types::{MInt, MapPos, Size2};
use core::core::Unit;
use core::game_state::GameState;
use core::dir::Dir;

struct Tile {
    cost: MInt,
    parent: Option<Dir>,
}

struct Map {
    size: Size2<MInt>,
    tiles: Vec<Tile>,
}

fn max_cost() -> MInt {
    30000
}

impl<'a> Map {
    fn tile_mut(&'a mut self, pos: MapPos) -> &'a mut Tile {
        self.tiles.get_mut((pos.v.x + pos.v.y * self.size.w) as uint)
    }

    fn tile(&'a self, pos: MapPos) -> &'a Tile {
        &self.tiles[(pos.v.x + pos.v.y * self.size.w) as uint]
    }

    fn is_inboard(&self, pos: MapPos) -> bool {
        let x = pos.v.x;
        let y = pos.v.y;
        x >= 0 && y >= 0 && x < self.size.w && y < self.size.h
    }
}

pub struct Pathfinder {
    queue: Vec<MapPos>,
    map: Map,
}

fn create_tiles(tiles_count: MInt) -> Vec<Tile> {
    let mut tiles = Vec::new();
    for _ in range(0, tiles_count) {
        tiles.push(Tile {
            cost: 0,
            parent: None,
        });
    }
    tiles
}

impl Pathfinder {
    pub fn new(map_size: Size2<MInt>) -> Pathfinder {
        let tiles_count = map_size.w * map_size.h;
        Pathfinder {
            queue: Vec::new(),
            map: Map {
                size: map_size,
                tiles: create_tiles(tiles_count),
            },
        }
    }

    fn process_neighbour_pos(
        &mut self,
        state: &GameState,
        _: &Unit, // TODO: use unit`s type and action points later
        original_pos: MapPos,
        neighbour_pos: MapPos
    ) {
        let old_cost = self.map.tile(original_pos).cost;
        let tile = self.map.tile_mut(neighbour_pos);
        let new_cost: MInt = old_cost + 1;
        let units_count = state.units_at(neighbour_pos).len();
        if tile.cost > new_cost && units_count == 0 {
            self.queue.push(neighbour_pos);
            // update neighbour tile info
            tile.cost = new_cost;
            let dir = Dir::get_dir_from_to(neighbour_pos, original_pos);
            tile.parent = Some(dir);
        }
    }

    fn clean_map(&mut self) {
        for tile in self.map.tiles.mut_iter() {
            tile.cost = max_cost();
            tile.parent = None;
        }
    }

    fn try_to_push_neighbours(
        &mut self,
        state: &GameState,
        unit: &Unit,
        pos: MapPos
    ) {
        assert!(self.map.is_inboard(pos));
        for i in range(0i, 6) {
            let neighbour_pos = Dir::get_neighbour_pos(pos, Dir::from_int(i as MInt));
            if self.map.is_inboard(neighbour_pos) {
                self.process_neighbour_pos(
                    state, unit, pos, neighbour_pos);
            }
        }
    }

    fn push_start_pos_to_queue(&mut self, start_pos: MapPos) {
        self.queue.push(start_pos);
        let start_tile = self.map.tile_mut(start_pos);
        start_tile.cost = 0;
        start_tile.parent = None;
    }

    pub fn fill_map(&mut self, state: &GameState, unit: &Unit) {
        assert!(self.queue.len() == 0);
        self.clean_map();
        self.push_start_pos_to_queue(unit.pos);
        while self.queue.len() != 0 {
            let pos = self.queue.shift().unwrap();
            self.try_to_push_neighbours(state, unit, pos);
        }
    }

    pub fn get_path(&self, destination: MapPos) -> Vec<MapPos> {
        let mut path = Vec::new();
        let mut pos = destination;
        assert!(self.map.is_inboard(pos));
        path.push(destination);
        while self.map.tile(pos).cost != 0 {
            let parent_dir = self.map.tile(pos).parent.unwrap();
            pos = Dir::get_neighbour_pos(pos, parent_dir);
            assert!(self.map.is_inboard(pos));
            path.push(pos);
        }
        path.reverse();
        path
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::collections::HashMap;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use {RequestedSlice, VersionMatchStrategy};
use commands::command::Command;
use formatters;
use options_parse::Options;
use os::Os;
use slice::{List, Slice};

pub struct MakeCommand<'a> {
    slices: Vec<RequestedSlice>,
    os: Os,
    root_directory: &'a Path,
    slice_root_directory: &'a Path,
    options: Options
}

struct DependenciesSearchResult<'a> {
    found_requested_slices: Vec<&'a Slice>,
    missing_requested_slices: Vec<&'a str>,
    unresolved_dependencies: HashMap<&'a str, Vec<&'a str>>,
}

impl<'a> MakeCommand<'a> {
    /// # Panics
    /// If `slices` is empty
    pub fn new(slices: Vec<RequestedSlice>, os: Os, root_directory: &'a Path,
           slice_root_directory: &'a Path, options: Options) -> MakeCommand<'a> {
        assert_not_empty!(slices);
        assert!(!slices.is_empty(), "There is no specified layers");
        MakeCommand { slices: slices, os: os, root_directory: root_directory,
                      slice_root_directory: slice_root_directory,
                      options: options }
    }

    fn create_code_from_slices(&self, slices: Vec<&Slice>, visited_slices: &mut Vec<&str>) -> String {
        let mut code = String::new();
        for slice in slices {
            let slice_name = slice.name() as &str;
            if visited_slices.contains(&slice_name) {
                continue;
            }
            let dependencies = slice.resolved_dependencies();
            if !dependencies.is_empty() {
                let dependency_code = self.create_code_from_slices(dependencies, visited_slices);
                code.push_str(&dependency_code);
            }
            let slice_code = formatters::generate_code(&slice, &self.options.format);
            code.push_str(&slice_code);
        }
        code
    }

    fn get_output_file_path(&self) -> PathBuf {
        if self.options.outpath.is_empty() {
            let mut path = self.root_directory.to_path_buf();
            path.push("make");
            path.push(&self.slices.first().unwrap().name);
            path
        } else {
            let mut path = PathBuf::new();
            path.push(&self.options.outpath);
            path
        }
    }

    fn find_unresolved_dependencies<'b>(&'b self, list: &'b List) -> DependenciesSearchResult {
        let mut result = DependenciesSearchResult { found_requested_slices: Vec::new(),
                                                    missing_requested_slices: Vec::new(),
                                                    unresolved_dependencies: HashMap::new() };
        for slice in &self.slices {
            if let Some(slice) = list.find_slice(&slice.name, &slice.version,
                                                 slice.version_match_strategy) {
                let dependencies = slice.unresolved_dependencies_include_nested();
                if !dependencies.is_empty() {
                    for dep in dependencies {
                        let entry = result.unresolved_dependencies.entry(&slice.name());
                        entry.or_insert(Vec::new()).push(dep);
                    }
                } else {
                    result.found_requested_slices.push(slice.borrow());
                }
            } else {
                result.missing_requested_slices.push(&slice.name);
            }
        }
        result
    }

    fn generate_code(&self) -> String {
        match List::new(&self.slice_root_directory, &self.os,
                        VersionMatchStrategy::ExactOrGreater) {
            Ok(list) => {
                match self.generate_code_for_list(&list) {
                    Some(code) => code,
                    None => panic!("Code generation failed")
                }
            }
            Err(error) => panic!("{}", error)
        }
    }

    fn generate_code_for_list(&self, list: &List) -> Option<String> {
        let result = self.find_unresolved_dependencies(list);
        let has_missing_slice = !result.unresolved_dependencies.is_empty() ||
                                !result.missing_requested_slices.is_empty();
        if has_missing_slice {
            if !result.missing_requested_slices.is_empty() {
                println!("Missing requested slices:");
                for slice in &result.missing_requested_slices {
                    println!("{}", slice);
                }
            }
            if !result.unresolved_dependencies.is_empty() {
                println!("Missing dependencies:");
                for (requested_slice, missing_dependencies) in &result.unresolved_dependencies {
                    for missing_dep in missing_dependencies {
                        println!("{} depends on {}, but it is missing", requested_slice, missing_dep);
                    }
                }
            }
            return None;
        }

        let mut visited_slices = Vec::new();
        Some(self.create_code_from_slices(result.found_requested_slices, &mut visited_slices))
    }

    fn write_code(&self, code: String) {
        match File::create(self.get_output_file_path()) {
            Ok(mut file) => {
                if let Err(error) = file.write_fmt(format_args!("{}", code)) {
                    panic!("{}", error);
                }
            }
            Err(error) =>  panic!("File cannot be created at path {}\nReason = {}",
                                  self.get_output_file_path().display(), error)
        }
    }
}

impl<'a> Command for MakeCommand<'a> {
    fn run(&mut self) {
        let code = self.generate_code();
        self.write_code(code);
    }
}

#[cfg(test)]
mod tests {
    use std::env;
    use std::path::Path;
    use {MakeCommand, RequestedSlice, VersionMatchStrategy};
    use options_parse::{Format, Options};
    use os::Os;
    use version;

    fn generate_code_for_jekyll_with_format(format: Format) -> String {
        let version_match_strategy = VersionMatchStrategy::ExactOrGreater;
        let slice = RequestedSlice { name: String::from("jekyll"), version: version::zero(),
                                     version_match_strategy: version_match_strategy };
        let slices = vec![slice];

        let os = Os { name: String::from("debian"), version: version::zero() };

        let mut path = env::current_dir().expect("Current dir is not set").to_path_buf();
        path.push("test_slices");

        let options = Options { format: format, .. Options::new() };

        let command = MakeCommand::new(slices, os, Path::new("/"), &path, options);
        println!("{}", command.generate_code());
        command.generate_code()
    }

    #[test]
    fn generate_code_for_jekyll_in_docker_format() {
        let code = generate_code_for_jekyll_with_format(Format::Docker);
        assert_eq!(code, "RUN export DEBIAN_FRONTEND=noninteractive && \\
apt-get update -q -y && \\
alias apt-get='apt-get --no-install-recommends' && \\
apt-get install -q -y apt-utils
RUN apt-get install -q -y wget
RUN cd /tmp && \\
wget https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz && \\
tar xvzf ruby-2.2.3.tar.gz && \\
cd ruby-2.2.3 && \\
./configure --prefix=/usr/local && \\
make && \\
make install && \\
cd .. && \\
rm -rf ruby-2.2.3 && \\
wget https://rubygems.org/rubygems/rubygems-2.4.8.tgz && \\
tar xvzf rubygems-2.4.8.tgz && \\
cd rubygems-2.4.8 && \\
ruby setup.rb && \\
cd .. && \\
rm -rf rubygems-2.4.8
RUN gem install jekyll -v '3.0.0.pre.beta9'
");
    }

    #[test]
    fn generate_code_for_jekyll_in_shell_format() {
        let code = generate_code_for_jekyll_with_format(Format::Shell);
        assert_eq!(code, "export DEBIAN_FRONTEND=noninteractive
apt-get update -q -y
alias apt-get='apt-get --no-install-recommends'
apt-get install -q -y apt-utils
apt-get install -q -y wget
cd /tmp
wget https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz
tar xvzf ruby-2.2.3.tar.gz
cd ruby-2.2.3
./configure --prefix=/usr/local
make
make install
cd ..
rm -rf ruby-2.2.3
wget https://rubygems.org/rubygems/rubygems-2.4.8.tgz
tar xvzf rubygems-2.4.8.tgz
cd rubygems-2.4.8
ruby setup.rb
cd ..
rm -rf rubygems-2.4.8
gem install jekyll -v '3.0.0.pre.beta9'
");
    }
}<commit_msg>Changes to fix bug introduced by #25 fix<commit_after>use std::borrow::Borrow;
use std::collections::HashMap;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::path::{Path, PathBuf};
use {RequestedSlice, VersionMatchStrategy};
use commands::command::Command;
use formatters;
use options_parse::Options;
use os::Os;
use slice::{List, Slice};

pub struct MakeCommand<'a> {
    slices: Vec<RequestedSlice>,
    os: Os,
    root_directory: &'a Path,
    slice_root_directory: &'a Path,
    options: Options
}

struct DependenciesSearchResult<'a> {
    found_requested_slices: Vec<&'a Slice>,
    missing_requested_slices: Vec<&'a str>,
    unresolved_dependencies: HashMap<&'a str, Vec<&'a str>>,
}

impl<'a> MakeCommand<'a> {
    /// # Panics
    /// If `slices` is empty
    pub fn new(slices: Vec<RequestedSlice>, os: Os, root_directory: &'a Path,
           slice_root_directory: &'a Path, options: Options) -> MakeCommand<'a> {
        assert_not_empty!(slices);
        assert!(!slices.is_empty(), "There is no specified layers");
        MakeCommand { slices: slices, os: os, root_directory: root_directory,
                      slice_root_directory: slice_root_directory,
                      options: options }
    }

    fn create_code_from_slices(&self, slices: Vec<&Slice>, visited_slices: &mut Vec<&str>) -> String {
        let mut code = String::new();
        for slice in slices {
            let slice_name = slice.name() as &str;
            if visited_slices.contains(&slice_name) {
                continue;
            }
            let dependencies = slice.resolved_dependencies();
            if !dependencies.is_empty() {
                let dependency_code = self.create_code_from_slices(dependencies, visited_slices);
                code.push_str(&dependency_code);
            }
            let slice_code = formatters::generate_code(&slice, &self.options.format);
            code.push_str(&slice_code);
        }
        code
    }

    fn get_output_file_path(&self) -> PathBuf {
        if self.options.outpath.is_empty() {
            let mut path = self.root_directory.to_path_buf();
            path.push("make");
            path.push(&self.slices.first().unwrap().name);
            path
        } else {
            let mut path = PathBuf::new();
            path.push(&self.options.outpath);
            path
        }
    }

    fn find_unresolved_dependencies<'b>(&'b self, list: &'b List) -> DependenciesSearchResult {
        let mut result = DependenciesSearchResult { found_requested_slices: Vec::new(),
                                                    missing_requested_slices: Vec::new(),
                                                    unresolved_dependencies: HashMap::new() };
        for slice in &self.slices {
            if let Some(slice) = list.find_slice(&slice.name, &slice.version,
                                                 slice.version_match_strategy) {
                let dependencies = slice.unresolved_dependencies_include_nested();
                if !dependencies.is_empty() {
                    for dep in dependencies {
                        let entry = result.unresolved_dependencies.entry(&slice.name());
                        entry.or_insert(Vec::new()).push(dep);
                    }
                } else {
                    result.found_requested_slices.push(slice.borrow());
                }
            } else {
                result.missing_requested_slices.push(&slice.name);
            }
        }
        result
    }

    fn generate_code(&self) -> String {
        match List::new(&self.slice_root_directory, &self.os,
                        VersionMatchStrategy::ExactOrGreater) {
            Ok(list) => {
                match self.generate_code_for_list(&list) {
                    Some(code) => code,
                    None => panic!("Code generation failed")
                }
            }
            Err(error) => panic!("{}", error)
        }
    }

    fn generate_code_for_list(&self, list: &List) -> Option<String> {
        let result = self.find_unresolved_dependencies(list);
        let has_missing_slice = !result.unresolved_dependencies.is_empty() ||
                                !result.missing_requested_slices.is_empty();
        if has_missing_slice {
            if !result.missing_requested_slices.is_empty() {
                println!("Missing requested slices:");
                for slice in &result.missing_requested_slices {
                    println!("{}", slice);
                }
            }
            if !result.unresolved_dependencies.is_empty() {
                println!("Missing dependencies:");
                for (requested_slice, missing_dependencies) in &result.unresolved_dependencies {
                    for missing_dep in missing_dependencies {
                        println!("{} depends on {}, but it is missing", requested_slice, missing_dep);
                    }
                }
            }
            return None;
        }

        let mut visited_slices = Vec::new();
        Some(self.create_code_from_slices(result.found_requested_slices, &mut visited_slices))
    }

    fn write_code(&self, code: String) {
    	let path = self.get_output_file_path();
    	if let Err(error) = fs::create_dir_all(path.parent().unwrap()) {
    	    panic!("Directory for make file cannot be created.
Path = {}
Reason = {}",
    	           path.parent().unwrap().display(), error);
    	}
        match File::create(path) {
            Ok(mut file) => {
                if let Err(error) = file.write_fmt(format_args!("{}", code)) {
                    panic!("{}", error);
                }
            }
            Err(error) =>  panic!("File cannot be created at path {}\nReason = {}",
                                  self.get_output_file_path().display(), error)
        }
    }
}

impl<'a> Command for MakeCommand<'a> {
    fn run(&mut self) {
        let code = self.generate_code();
        self.write_code(code);
    }
}

#[cfg(test)]
mod tests {
    use std::env;
    use std::path::Path;
    use {MakeCommand, RequestedSlice, VersionMatchStrategy};
    use options_parse::{Format, Options};
    use os::Os;
    use version;

    fn generate_code_for_jekyll_with_format(format: Format) -> String {
        let version_match_strategy = VersionMatchStrategy::ExactOrGreater;
        let slice = RequestedSlice { name: String::from("jekyll"), version: version::zero(),
                                     version_match_strategy: version_match_strategy };
        let slices = vec![slice];

        let os = Os { name: String::from("debian"), version: version::zero() };

        let mut path = env::current_dir().expect("Current dir is not set").to_path_buf();
        path.push("test_slices");

        let options = Options { format: format, .. Options::new() };

        let command = MakeCommand::new(slices, os, Path::new("/"), &path, options);
        println!("{}", command.generate_code());
        command.generate_code()
    }

    #[test]
    fn generate_code_for_jekyll_in_docker_format() {
        let code = generate_code_for_jekyll_with_format(Format::Docker);
        assert_eq!(code, "RUN export DEBIAN_FRONTEND=noninteractive && \\
apt-get update -q -y && \\
alias apt-get='apt-get --no-install-recommends' && \\
apt-get install -q -y apt-utils
RUN apt-get install -q -y wget
RUN cd /tmp && \\
wget https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz && \\
tar xvzf ruby-2.2.3.tar.gz && \\
cd ruby-2.2.3 && \\
./configure --prefix=/usr/local && \\
make && \\
make install && \\
cd .. && \\
rm -rf ruby-2.2.3 && \\
wget https://rubygems.org/rubygems/rubygems-2.4.8.tgz && \\
tar xvzf rubygems-2.4.8.tgz && \\
cd rubygems-2.4.8 && \\
ruby setup.rb && \\
cd .. && \\
rm -rf rubygems-2.4.8
RUN gem install jekyll -v '3.0.0.pre.beta9'
");
    }

    #[test]
    fn generate_code_for_jekyll_in_shell_format() {
        let code = generate_code_for_jekyll_with_format(Format::Shell);
        assert_eq!(code, "export DEBIAN_FRONTEND=noninteractive
apt-get update -q -y
alias apt-get='apt-get --no-install-recommends'
apt-get install -q -y apt-utils
apt-get install -q -y wget
cd /tmp
wget https://cache.ruby-lang.org/pub/ruby/2.2/ruby-2.2.3.tar.gz
tar xvzf ruby-2.2.3.tar.gz
cd ruby-2.2.3
./configure --prefix=/usr/local
make
make install
cd ..
rm -rf ruby-2.2.3
wget https://rubygems.org/rubygems/rubygems-2.4.8.tgz
tar xvzf rubygems-2.4.8.tgz
cd rubygems-2.4.8
ruby setup.rb
cd ..
rm -rf rubygems-2.4.8
gem install jekyll -v '3.0.0.pre.beta9'
");
    }
}<|endoftext|>