<commit_before>//! The `Language` struct and its various methods.

/// Languages used in formatting. Follows [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
///
/// Additional languages may be added at any time. Contributions will be
/// accepted by native and highly fluent speakers of any living language.
///
/// All languages must have the following:
/// - Month names
/// - Short month names
/// - Weekday names
/// - Short weekday names
#[non_exhaustive]
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Language {
    /// English
    en,
    /// Spanish
    es,
}

#[allow(clippy::non_ascii_literal)]
impl Language {
    /// Get the month names for the given language.
    #[inline(always)]
    pub fn month_names(self) -> [&'static str; 12] {
        use Language::*;
        match self {
            en => [
                "January",
                "February",
                "March",
                "April",
                "May",
                "June",
                "July",
                "August",
                "September",
                "October",
                "November",
                "December",
            ],
            es => [
                "enero",
                "febrero",
                "marzo",
                "abril",
                "mayo",
                "junio",
                "julio",
                "agosto",
                "septiembre",
                "octubre",
                "noviembre",
                "diciembre",
            ],
        }
    }

    /// Get the abbreviated month names for the given language.
    ///
    /// References on localization:
    /// [\[1\]](https://web.library.yale.edu/cataloging/months)
    /// [\[2\]](https://library.princeton.edu/departments/tsd/katmandu/reference/months.html)
    #[inline(always)]
    pub fn short_month_names(self) -> [&'static str; 12] {
        use Language::*;
        match self {
            en => [
                "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov",
                "Dec",
            ],
            es => [
                "enero", "feb", "marzo", "abr", "mayo", "jun", "jul", "agosto", "set", "oct",
                "nov", "dic",
            ],
        }
    }

    /// Get the names of days of the week for the given language. Starts with
    /// Monday.
    #[inline(always)]
    pub fn week_days(self) -> [&'static str; 7] {
        use Language::*;
        match self {
            en => [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday",
            ],
            es => [
                "lunes",
                "martes",
                "miércoles",
                "jueves",
                "viernes",
                "sábado",
                "domingo",
            ],
        }
    }

    /// Get the abbreviated names of days of the week for the given language.
    /// Starts with Monday.
    #[inline(always)]
    pub fn short_week_days(self) -> [&'static str; 7] {
        use Language::*;
        match self {
            en => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
            es => ["Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"],
        }
    }
}
<commit_msg>Localization: Add French (#187)<commit_after>//! The `Language` struct and its various methods.

/// Languages used in formatting. Follows [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes).
///
/// Additional languages may be added at any time. Contributions will be
/// accepted by native and highly fluent speakers of any living language.
///
/// All languages must have the following:
/// - Month names
/// - Short month names
/// - Weekday names
/// - Short weekday names
#[non_exhaustive]
#[allow(non_camel_case_types)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Language {
    /// English
    en,
    /// Spanish
    es,
    /// French
    fr,
}

#[allow(clippy::non_ascii_literal)]
impl Language {
    /// Get the month names for the given language.
    #[inline(always)]
    pub fn month_names(self) -> [&'static str; 12] {
        use Language::*;
        match self {
            en => [
                "January",
                "February",
                "March",
                "April",
                "May",
                "June",
                "July",
                "August",
                "September",
                "October",
                "November",
                "December",
            ],
            es => [
                "enero",
                "febrero",
                "marzo",
                "abril",
                "mayo",
                "junio",
                "julio",
                "agosto",
                "septiembre",
                "octubre",
                "noviembre",
                "diciembre",
            ],
            fr => [
                "janvier",
                "février",
                "mars",
                "avril",
                "mai",
                "juin",
                "juillet",
                "août",
                "septembre",
                "octobre",
                "novembre",
                "décembre",
            ],
        }
    }

    /// Get the abbreviated month names for the given language.
    ///
    /// References on localization:
    /// [\[1\]](https://web.library.yale.edu/cataloging/months)
    /// [\[2\]](https://library.princeton.edu/departments/tsd/katmandu/reference/months.html)
    #[inline(always)]
    pub fn short_month_names(self) -> [&'static str; 12] {
        use Language::*;
        match self {
            en => [
                "Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov",
                "Dec",
            ],
            es => [
                "enero", "feb", "marzo", "abr", "mayo", "jun", "jul", "agosto", "set", "oct",
                "nov", "dic",
            ],
            fr => [
                "janv", "févr", "mars", "avril", "mai", "juin", "juil", "août", "sept", "oct",
                "nov", "déc",
            ],
        }
    }

    /// Get the names of days of the week for the given language. Starts with
    /// Monday.
    #[inline(always)]
    pub fn week_days(self) -> [&'static str; 7] {
        use Language::*;
        match self {
            en => [
                "Monday",
                "Tuesday",
                "Wednesday",
                "Thursday",
                "Friday",
                "Saturday",
                "Sunday",
            ],
            es => [
                "lunes",
                "martes",
                "miércoles",
                "jueves",
                "viernes",
                "sábado",
                "domingo",
            ],
            fr => [
                "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi", "dimanche",
            ],
        }
    }

    /// Get the abbreviated names of days of the week for the given language.
    /// Starts with Monday.
    #[inline(always)]
    pub fn short_week_days(self) -> [&'static str; 7] {
        use Language::*;
        match self {
            en => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
            es => ["Lu", "Ma", "Mi", "Ju", "Vi", "Sa", "Do"],
            fr => ["lun", "mar", "mer", "jeu", "ven", "sam", "dim"],
        }
    }
}
<|endoftext|>


<commit_before>use std::io::Read;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::mac::MacResult;
use crypto::sha1::Sha1;
use hex::FromHex;
use iron;
use serde_json;

use DB_POOL;
use builds;
use config::CONFIG;
use error::DashResult;
use github::models::{CommentFromJson, IssueFromJson, PullRequestFromJson};
use github::{handle_comment, handle_issue, handle_pr};

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

pub fn handler(req: &mut iron::Request) -> iron::IronResult<iron::Response> {
    match inner_handler(req) {
        Ok(()) => (),
        Err(why) => error!("Error processing webhook: {:?}", why),
    }

    Ok(iron::Response::with((iron::status::Ok, "ok")))
}

fn inner_handler(req: &mut iron::Request) -> DashResult<()> {
    if let (Some(&XGithubEvent(ref event_name)),
            Some(&XGithubDelivery(ref delivery_id)),
            Some(&XHubSignature(ref signature))) =
        (req.headers.get::<XGithubEvent>(),
         req.headers.get::<XGithubDelivery>(),
         req.headers.get::<XHubSignature>()) {

        // unfortunately we need to read untrusted input before authenticating
        // b/c we need to sha the request payload
        let mut body = String::new();
        req.body.read_to_string(&mut body)?;

        let mut authenticated = false;

        for secret in &CONFIG.github_webhook_secrets {
            if authenticate(secret, &body, signature) {
                // once we know it's from github, we'll parse it

                authenticated = true;

                let payload = parse_event(event_name, &body)?;

                let full_event = Event {
                    delivery_id: delivery_id.to_owned(),
                    event_name: event_name.to_owned(),
                    payload: payload,
                };

                info!("Received valid webhook ({} id {})",
                      full_event.event_name,
                      full_event.delivery_id);

                authenticated_handler(full_event)?;
                break;
            }
        }

        if !authenticated {
            warn!("Received invalid webhook: {:?}", req);
        }
    }

    Ok(())
}

fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
    // https://developer.github.com/webhooks/securing/#validating-payloads-from-github
    let sans_prefix = signature[5..].as_bytes();
    match Vec::from_hex(sans_prefix) {
        Ok(sigbytes) => {
            let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
            mac.input(payload.as_bytes());
            // constant time comparison
            mac.result() == MacResult::new(&sigbytes)
        }
        Err(_) => false,
    }
}

fn parse_event(event_name: &str, body: &str) -> DashResult<Payload> {
    match event_name {
        "issue_comment" => Ok(Payload::IssueComment(serde_json::from_str(body)?)),
        "issues" => Ok(Payload::Issues(serde_json::from_str(body)?)),
        "pull_request" => Ok(Payload::PullRequest(serde_json::from_str(body)?)),
        "status" => Ok(Payload::Status(serde_json::from_str(body)?)),

        "commit_comment" |
        "create" |
        "delete" |
        "deployment" |
        "deployment_status" |
        "fork" |
        "gollum" |
        "label" |
        "member" |
        "membership" |
        "milestone" |
        "organization" |
        "page_build" |
        "public" |
        "pull_request_review_comment" |
        "pull_request_review" |
        "push" |
        "repository" |
        "release" |
        "team" |
        "team_add" |
        "watch" => {
            info!("Received {} event, ignoring...", event_name);
            Ok(Payload::Unsupported)
        }

        _ => {
            warn!("Received unrecognized event {}, check GitHub's API to see what's updated.",
                  event_name);
            Ok(Payload::Unsupported)
        }
    }
}

fn authenticated_handler(event: Event) -> DashResult<()> {
    let conn = &*DB_POOL.get()?;

    match event.payload {
        Payload::Issues(issue_event) => {
            handle_issue(conn, issue_event.issue, &issue_event.repository.full_name)?;
        }

        Payload::PullRequest(pr_event) => {
            handle_pr(conn, pr_event.pull_request, &pr_event.repository.full_name)?;
        }

        Payload::IssueComment(comment_event) => {
            // possible race conditions if we get a comment hook before the issue one (or we
            // missed the issue one), so make sure the issue exists first

            if comment_event.action != "deleted" {
                // TODO handle deleted comments properly
                handle_issue(conn, comment_event.issue, &comment_event.repository.full_name)?;
                handle_comment(conn, comment_event.comment, &comment_event.repository.full_name)?;
            }
        }

        Payload::Status(status_event) => {
            if status_event.state != "pending" &&
                status_event.branches.iter().any(|branch| {
                    branch.name == "auto" &&
                    branch.commit.sha == status_event.sha
                })
            {
                if let Some(url) = status_event.target_url {
                    builds::ingest_status_event(url)?
                }
            }
        },

        Payload::Unsupported => (),
    }

    Ok(())
}

#[derive(Debug)]
pub struct Event {
    delivery_id: String,
    event_name: String,
    payload: Payload,
}

#[derive(Debug)]
pub enum Payload {
    Issues(IssuesEvent),
    IssueComment(IssueCommentEvent),
    PullRequest(PullRequestEvent),
    Status(StatusEvent),

    Unsupported,
}

#[derive(Debug, Deserialize)]
pub struct IssuesEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
}

#[derive(Debug, Deserialize)]
pub struct IssueCommentEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
    comment: CommentFromJson,
}

#[derive(Debug, Deserialize)]
pub struct PullRequestEvent {
    action: String,
    repository: Repository,
    number: i32,
    pull_request: PullRequestFromJson,
}

#[derive(Debug, Deserialize)]
pub struct StatusEvent {
    sha: String,
    state: String,
    target_url: Option<String>,
    branches: Vec<Branch>,
}

#[derive(Debug, Deserialize)]
pub struct Repository {
    full_name: String,
}

#[derive(Debug, Deserialize)]
pub struct Branch {
    name: String,
    commit: Commit,
}

#[derive(Debug, Deserialize)]
pub struct Commit {
    sha: String
}
<commit_msg>Get build info for all of bors's commits<commit_after>use std::io::Read;

use crypto::hmac::Hmac;
use crypto::mac::Mac;
use crypto::mac::MacResult;
use crypto::sha1::Sha1;
use hex::FromHex;
use iron;
use serde_json;

use DB_POOL;
use builds;
use config::CONFIG;
use error::DashResult;
use github::models::{CommentFromJson, IssueFromJson, PullRequestFromJson};
use github::{handle_comment, handle_issue, handle_pr};

/// signature for request
/// see [this document](https://developer.github.com/webhooks/securing/) for more information
header! {(XHubSignature, "X-Hub-Signature") => [String]}

/// name of Github event
/// see [this document](https://developer.github.com/webhooks/#events) for available types
header! {(XGithubEvent, "X-Github-Event") => [String]}

/// unique id for each delivery
header! {(XGithubDelivery, "X-Github-Delivery") => [String]}

pub fn handler(req: &mut iron::Request) -> iron::IronResult<iron::Response> {
    match inner_handler(req) {
        Ok(()) => (),
        Err(why) => error!("Error processing webhook: {:?}", why),
    }

    Ok(iron::Response::with((iron::status::Ok, "ok")))
}

fn inner_handler(req: &mut iron::Request) -> DashResult<()> {
    if let (Some(&XGithubEvent(ref event_name)),
            Some(&XGithubDelivery(ref delivery_id)),
            Some(&XHubSignature(ref signature))) =
        (req.headers.get::<XGithubEvent>(),
         req.headers.get::<XGithubDelivery>(),
         req.headers.get::<XHubSignature>()) {

        // unfortunately we need to read untrusted input before authenticating
        // b/c we need to sha the request payload
        let mut body = String::new();
        req.body.read_to_string(&mut body)?;

        let mut authenticated = false;

        for secret in &CONFIG.github_webhook_secrets {
            if authenticate(secret, &body, signature) {
                // once we know it's from github, we'll parse it

                authenticated = true;

                let payload = parse_event(event_name, &body)?;

                let full_event = Event {
                    delivery_id: delivery_id.to_owned(),
                    event_name: event_name.to_owned(),
                    payload: payload,
                };

                info!("Received valid webhook ({} id {})",
                      full_event.event_name,
                      full_event.delivery_id);

                authenticated_handler(full_event)?;
                break;
            }
        }

        if !authenticated {
            warn!("Received invalid webhook: {:?}", req);
        }
    }

    Ok(())
}

fn authenticate(secret: &str, payload: &str, signature: &str) -> bool {
    // https://developer.github.com/webhooks/securing/#validating-payloads-from-github
    let sans_prefix = signature[5..].as_bytes();
    match Vec::from_hex(sans_prefix) {
        Ok(sigbytes) => {
            let mut mac = Hmac::new(Sha1::new(), secret.as_bytes());
            mac.input(payload.as_bytes());
            // constant time comparison
            mac.result() == MacResult::new(&sigbytes)
        }
        Err(_) => false,
    }
}

fn parse_event(event_name: &str, body: &str) -> DashResult<Payload> {
    match event_name {
        "issue_comment" => Ok(Payload::IssueComment(serde_json::from_str(body)?)),
        "issues" => Ok(Payload::Issues(serde_json::from_str(body)?)),
        "pull_request" => Ok(Payload::PullRequest(serde_json::from_str(body)?)),
        "status" => Ok(Payload::Status(serde_json::from_str(body)?)),

        "commit_comment" |
        "create" |
        "delete" |
        "deployment" |
        "deployment_status" |
        "fork" |
        "gollum" |
        "label" |
        "member" |
        "membership" |
        "milestone" |
        "organization" |
        "page_build" |
        "public" |
        "pull_request_review_comment" |
        "pull_request_review" |
        "push" |
        "repository" |
        "release" |
        "team" |
        "team_add" |
        "watch" => {
            info!("Received {} event, ignoring...", event_name);
            Ok(Payload::Unsupported)
        }

        _ => {
            warn!("Received unrecognized event {}, check GitHub's API to see what's updated.",
                  event_name);
            Ok(Payload::Unsupported)
        }
    }
}

fn authenticated_handler(event: Event) -> DashResult<()> {
    let conn = &*DB_POOL.get()?;

    match event.payload {
        Payload::Issues(issue_event) => {
            handle_issue(conn, issue_event.issue, &issue_event.repository.full_name)?;
        }

        Payload::PullRequest(pr_event) => {
            handle_pr(conn, pr_event.pull_request, &pr_event.repository.full_name)?;
        }

        Payload::IssueComment(comment_event) => {
            // possible race conditions if we get a comment hook before the issue one (or we
            // missed the issue one), so make sure the issue exists first

            if comment_event.action != "deleted" {
                // TODO handle deleted comments properly
                handle_issue(conn, comment_event.issue, &comment_event.repository.full_name)?;
                handle_comment(conn, comment_event.comment, &comment_event.repository.full_name)?;
            }
        }

        Payload::Status(status_event) => {
            if status_event.state != "pending" &&
                status_event.commit.committer.login == "bors"
            {
                if let Some(url) = status_event.target_url {
                    builds::ingest_status_event(url)?
                }
            }
        },

        Payload::Unsupported => (),
    }

    Ok(())
}

#[derive(Debug)]
pub struct Event {
    delivery_id: String,
    event_name: String,
    payload: Payload,
}

#[derive(Debug)]
pub enum Payload {
    Issues(IssuesEvent),
    IssueComment(IssueCommentEvent),
    PullRequest(PullRequestEvent),
    Status(StatusEvent),

    Unsupported,
}

#[derive(Debug, Deserialize)]
pub struct IssuesEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
}

#[derive(Debug, Deserialize)]
pub struct IssueCommentEvent {
    action: String,
    issue: IssueFromJson,
    repository: Repository,
    comment: CommentFromJson,
}

#[derive(Debug, Deserialize)]
pub struct PullRequestEvent {
    action: String,
    repository: Repository,
    number: i32,
    pull_request: PullRequestFromJson,
}

#[derive(Debug, Deserialize)]
pub struct Repository {
    full_name: String,
}

#[derive(Debug, Deserialize)]
pub struct StatusEvent {
    commit: Commit,
    state: String,
    target_url: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct Commit {
    committer: Committer,
}

#[derive(Debug, Deserialize)]
pub struct Committer {
    login: String,
}
<|endoftext|>


<commit_before>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use ffi;
use glib::translate::*;

#[allow(raw_pointer_derive)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Atom(ffi::GdkAtom);

pub const NONE: Atom = Atom(0 as *mut _);

impl Atom {
    pub fn intern(atom_name: &str) -> Atom {
        unsafe { Atom(ffi::gdk_atom_intern(atom_name.to_glib_none().0, false.to_glib())) }
    }

    pub fn name(&self) -> String {
        unsafe { from_glib_full(ffi::gdk_atom_name(self.0)) }
    }
}

impl<'a> ToGlibPtr<'a, ffi::GdkAtom> for Atom {
    type Storage = ();

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, ffi::GdkAtom, Atom> {
        Stash(self.0, ())
    }
}

impl FromGlibPtr<ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_none(ptr: ffi::GdkAtom) -> Atom { Atom(ptr) }
    #[inline]
    unsafe fn from_glib_full(_: ffi::GdkAtom) -> Atom { unimplemented!() }
}
<commit_msg>Add Atom documentation<commit_after>// Copyright 2013-2015, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Atoms — Functions to manipulate properties on windows

use ffi;
use glib::translate::*;

#[allow(raw_pointer_derive)]
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Atom(ffi::GdkAtom);

pub const NONE: Atom = Atom(0 as *mut _);

impl Atom {
    /// Finds or creates an atom corresponding to a given string.
    pub fn intern(atom_name: &str) -> Atom {
        unsafe { Atom(ffi::gdk_atom_intern(atom_name.to_glib_none().0, false.to_glib())) }
    }

    /// Determines the string corresponding to an atom.
    pub fn name(&self) -> String {
        unsafe { from_glib_full(ffi::gdk_atom_name(self.0)) }
    }
}

impl<'a> ToGlibPtr<'a, ffi::GdkAtom> for Atom {
    type Storage = ();

    #[inline]
    fn to_glib_none(&self) -> Stash<'a, ffi::GdkAtom, Atom> {
        Stash(self.0, ())
    }
}

impl FromGlibPtr<ffi::GdkAtom> for Atom {
    #[inline]
    unsafe fn from_glib_none(ptr: ffi::GdkAtom) -> Atom { Atom(ptr) }
    #[inline]
    unsafe fn from_glib_full(_: ffi::GdkAtom) -> Atom { unimplemented!() }
}
<|endoftext|>


<commit_before>mod iter;
mod coord;
mod test;

use traits::Grid;
use traits::Cell;
use traits::Nhood;
use traits::Coord;

use self::iter::Iter;
pub use self::coord::GridCoord;

pub struct TwodimGrid<C, N>
    where C: Cell,
          N: Nhood<Coord = GridCoord>
{
    cells: Vec<C>,
    old_cells: Vec<C>,
    nhood: N,
    neighbors: Vec<Vec<Option<usize>>>,
    dimensions: GridCoord,
    rows: i32,
    cols: i32,
}

impl<C, N> TwodimGrid<C, N>
    where C: Cell,
          N: Nhood<Coord = GridCoord>
{
    pub fn new(rows: i32, cols: i32, nhood: N) -> Self {

        let len = (rows * cols) as usize;

        let cells = Vec::with_capacity(len);
        let old_cells = Vec::with_capacity(len);
        let neighbors = Vec::with_capacity(len);

        let mut grid = TwodimGrid {
            cells: cells,
            old_cells: old_cells,
            nhood: nhood,
            neighbors: neighbors,
            rows: rows,
            cols: cols,
            dimensions: GridCoord::from_2d(cols, rows),
        };

        grid.init();

        grid
    }

    fn init(&mut self) {

        for offset in 0..self.rows * self.cols {

            let coord = GridCoord::from_offset(offset as i32, self.rows, self.cols);

            // init neighbors
            let neighbors = self.get_neighbors(&coord);
            self.neighbors.push(neighbors);

            // init cells
            self.cells.push(C::with_coord(coord));

        }
    }

    fn get_neighbors(&self, coord: &GridCoord) -> Vec<Option<usize>> {

        let neighbors_count = self.nhood.neighbors_count();
        let mut neighbors = Vec::with_capacity(neighbors_count);

        for coord in self.nhood.neighbors(coord).iter() {

            if coord.x() >= 0 && coord.x() < self.cols && coord.y() >= 0 && coord.y() < self.rows {

                neighbors.push(Some(self.offset(coord)));
            } else {
                neighbors.push(None);
            }
        }

        neighbors
    }

    fn neighbors_iter<'b>(&self,
                          cells: &'b Vec<C>,
                          neighbors: &'b Vec<Option<usize>>)
                          -> Iter<'b, C> {

        Iter::new(cells, neighbors, self.nhood.neighbors_count())
    }

    #[inline]
    pub fn offset<Crd: Coord>(&self, coord: &Crd) -> usize {
        (coord.y() * self.cols + coord.x()) as usize
    }
}

impl<C, N> Grid for TwodimGrid<C, N>
    where C: Cell,
          N: Nhood<Coord = GridCoord>
{
    type Cell = C;
    type Coord = GridCoord;

    fn step(&mut self) {
        self.old_cells = self.cells.clone();

        for (cell_no, cell) in self.old_cells.iter().enumerate() {

            let ref neighbors = self.neighbors[cell_no];
            let neighbors_iter = self.neighbors_iter(&self.old_cells, &neighbors);

            let mut new_cell = cell.step(neighbors_iter);
            new_cell.set_coord(cell.coord());

            self.cells[cell_no] = new_cell;
        }
    }

    fn set_cells(&mut self, new_cells: Vec<Self::Cell>) {

        for cell in new_cells.into_iter() {

            let index;

            {
                index = self.offset(cell.coord());
            }

            self.cells[index] = cell;
        }
    }

    fn cells(&self) -> &Vec<Self::Cell> {
        &self.cells
    }

    fn dimensions(&self) -> Self::Coord {
        self.dimensions.clone()
    }
}
<commit_msg>Swap instead of clone.<commit_after>mod iter;
mod coord;
mod test;

use std::mem;

use traits::Grid;
use traits::Cell;
use traits::Nhood;
use traits::Coord;

use self::iter::Iter;
pub use self::coord::GridCoord;

pub struct TwodimGrid<C, N>
    where C: Cell,
          N: Nhood<Coord = GridCoord>
{
    cells: Vec<C>,
    old_cells: Vec<C>,
    nhood: N,
    neighbors: Vec<Vec<Option<usize>>>,
    dimensions: GridCoord,
    rows: i32,
    cols: i32,
}

impl<C, N> TwodimGrid<C, N>
    where C: Cell,
          N: Nhood<Coord = GridCoord>
{
    pub fn new(rows: i32, cols: i32, nhood: N) -> Self {

        let len = (rows * cols) as usize;

        let cells = Vec::with_capacity(len);
        let old_cells = Vec::with_capacity(len);
        let neighbors = Vec::with_capacity(len);

        let mut grid = TwodimGrid {
            cells: cells,
            old_cells: old_cells,
            nhood: nhood,
            neighbors: neighbors,
            rows: rows,
            cols: cols,
            dimensions: GridCoord::from_2d(cols, rows),
        };

        grid.init();

        grid
    }

    fn init(&mut self) {

        for offset in 0..self.rows * self.cols {

            let coord = GridCoord::from_offset(offset as i32, self.rows, self.cols);

            // init neighbors
            let neighbors = self.get_neighbors(&coord);
            self.neighbors.push(neighbors);

            // init cells
            let cell = C::with_coord(coord);
            self.cells.push(cell.clone());
            self.old_cells.push(cell.clone());
        }
    }

    fn get_neighbors(&self, coord: &GridCoord) -> Vec<Option<usize>> {

        let neighbors_count = self.nhood.neighbors_count();
        let mut neighbors = Vec::with_capacity(neighbors_count);

        for coord in self.nhood.neighbors(coord).iter() {

            if coord.x() >= 0 && coord.x() < self.cols && coord.y() >= 0 && coord.y() < self.rows {

                neighbors.push(Some(self.offset(coord)));
            } else {
                neighbors.push(None);
            }
        }

        neighbors
    }

    fn neighbors_iter<'b>(&self,
                          cells: &'b Vec<C>,
                          neighbors: &'b Vec<Option<usize>>)
                          -> Iter<'b, C> {

        Iter::new(cells, neighbors, self.nhood.neighbors_count())
    }

    #[inline]
    pub fn offset<Crd: Coord>(&self, coord: &Crd) -> usize {
        (coord.y() * self.cols + coord.x()) as usize
    }
}

impl<C, N> Grid for TwodimGrid<C, N>
    where C: Cell,
          N: Nhood<Coord = GridCoord>
{
    type Cell = C;
    type Coord = GridCoord;

    fn step(&mut self) {
        mem::swap(&mut self.cells, &mut self.old_cells);

        for (cell_no, cell) in self.old_cells.iter().enumerate() {

            let ref neighbors = self.neighbors[cell_no];
            let neighbors_iter = self.neighbors_iter(&self.old_cells, &neighbors);

            let mut new_cell = cell.step(neighbors_iter);
            new_cell.set_coord(cell.coord());

            self.cells[cell_no] = new_cell;
        }
    }

    fn set_cells(&mut self, new_cells: Vec<Self::Cell>) {

        for cell in new_cells.into_iter() {

            let index;

            {
                index = self.offset(cell.coord());
            }

            self.cells[index] = cell;
        }
    }

    fn cells(&self) -> &Vec<Self::Cell> {
        &self.cells
    }

    fn dimensions(&self) -> Self::Coord {
        self.dimensions.clone()
    }
}
<|endoftext|>


<commit_before>use std::slice;
use cose::decoder::decode_signature;
use cose::CoseSignatureType;

unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
    slice::from_raw_parts(ptr, len).to_vec()
}

type VerifyCallback = extern "C" fn(*const u8, /* payload */
                                    usize, /* payload len */
                                    *const u8, /* cert_chain */
                                    usize, /* cert_chain len */
                                    *const u8, /* signer cert */
                                    usize, /* signer cert len */
                                    *const u8, /* signature bytes */
                                    usize, /* signature len */
                                    u8 /* signature algorithm */)
                                    -> bool;

#[no_mangle]
pub unsafe extern "C" fn verify_signature_with_cpp(
    payload: *const u8,
    payload_len: usize,
    cose_signature: *const u8,
    cose_signature_len: usize,
    verify_callback: VerifyCallback,
) -> bool {
    if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
        cose_signature_len == 0
    {
        return false;
    }

    // Build Rust variables from C parameters.
    let payload = from_raw(payload, payload_len);
    let cose_signature = from_raw(cose_signature, cose_signature_len);

    // Parse the incoming signature.
    let cose_signatures = decode_signature(cose_signature, &payload);
    let cose_signatures = match cose_signatures {
        Ok(signature) => signature,
        Err(_) => Vec::new(),
    };
    if cose_signatures.len() < 1 {
        return false;
    }
    let signature_type = &cose_signatures[0].signature_type;
    // ES256 = 0, ES384 = 1, ES521 = 2, PS256 = 3
    let signature_type = match *signature_type {
        CoseSignatureType::ES256 => 0,
        _ => return false,
    };
    let signature_bytes = &cose_signatures[0].signature;
    let real_payload = &cose_signatures[0].to_verify;

    // Call callback to verify the parsed signatures.
    let result = verify_callback(
        real_payload.as_ptr(),
        real_payload.len(),
        cose_signatures[0].certs.as_ptr(),
        cose_signatures[0].certs.len(),
        cose_signatures[0].signer_cert.as_ptr(),
        cose_signatures[0].signer_cert.len(),
        signature_bytes.as_ptr(),
        signature_bytes.len(),
        signature_type
    );

    result
}
<commit_msg>rustfmt<commit_after>use std::slice;
use cose::decoder::decode_signature;
use cose::CoseSignatureType;

unsafe fn from_raw(ptr: *const u8, len: usize) -> Vec<u8> {
    slice::from_raw_parts(ptr, len).to_vec()
}

type VerifyCallback = extern "C" fn(*const u8, /* payload */
                                    usize, /* payload len */
                                    *const u8, /* cert_chain */
                                    usize, /* cert_chain len */
                                    *const u8, /* signer cert */
                                    usize, /* signer cert len */
                                    *const u8, /* signature bytes */
                                    usize, /* signature len */
                                    u8 /* signature algorithm */)
                                    -> bool;

#[no_mangle]
pub unsafe extern "C" fn verify_signature_with_cpp(
    payload: *const u8,
    payload_len: usize,
    cose_signature: *const u8,
    cose_signature_len: usize,
    verify_callback: VerifyCallback,
) -> bool {
    if payload.is_null() || cose_signature.is_null() || payload_len == 0 ||
        cose_signature_len == 0
    {
        return false;
    }

    // Build Rust variables from C parameters.
    let payload = from_raw(payload, payload_len);
    let cose_signature = from_raw(cose_signature, cose_signature_len);

    // Parse the incoming signature.
    let cose_signatures = decode_signature(cose_signature, &payload);
    let cose_signatures = match cose_signatures {
        Ok(signature) => signature,
        Err(_) => Vec::new(),
    };
    if cose_signatures.len() < 1 {
        return false;
    }
    let signature_type = &cose_signatures[0].signature_type;
    // ES256 = 0, ES384 = 1, ES521 = 2, PS256 = 3
    let signature_type = match *signature_type {
        CoseSignatureType::ES256 => 0,
        _ => return false,
    };
    let signature_bytes = &cose_signatures[0].signature;
    let real_payload = &cose_signatures[0].to_verify;

    // Call callback to verify the parsed signatures.
    let result = verify_callback(
        real_payload.as_ptr(),
        real_payload.len(),
        cose_signatures[0].certs.as_ptr(),
        cose_signatures[0].certs.len(),
        cose_signatures[0].signer_cert.as_ptr(),
        cose_signatures[0].signer_cert.len(),
        signature_bytes.as_ptr(),
        signature_bytes.len(),
        signature_type,
    );

    result
}
<|endoftext|>


<commit_before>//! Functions for performing affine transformations.

use buffer::{ImageBuffer, Pixel};
use image::GenericImage;

/// Rotate an image 90 degrees clockwise.
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn rotate90<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(height, width);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(height - 1 - y, x, p);
        }
    }

    out
}

/// Rotate an image 180 degrees clockwise.
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn rotate180<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(width - 1 - x, height - 1 - y, p);
        }
    }

    out
}

/// Rotate an image 270 degrees clockwise.
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn rotate270<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(height, width);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(y, width - 1 - x, p);
        }
    }

    out
}

/// Flip an image horizontally
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn flip_horizontal<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(height, width);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(width - 1 - x, y, p);
        }
    }

    out
}

/// Flip an image vertically
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn flip_vertical<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(x, height - 1 - y, p);
        }
    }

    out
}
<commit_msg>Fix flip_horizontal output dimensions. Add tests for all affine.rs functions<commit_after>//! Functions for performing affine transformations.

use buffer::{ImageBuffer, Pixel};
use image::GenericImage;

/// Rotate an image 90 degrees clockwise.
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn rotate90<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(height, width);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(height - 1 - y, x, p);
        }
    }

    out
}

/// Rotate an image 180 degrees clockwise.
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn rotate180<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(width - 1 - x, height - 1 - y, p);
        }
    }

    out
}

/// Rotate an image 270 degrees clockwise.
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn rotate270<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(height, width);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(y, width - 1 - x, p);
        }
    }

    out
}

/// Flip an image horizontally
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn flip_horizontal<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(width - 1 - x, y, p);
        }
    }

    out
}

/// Flip an image vertically
// TODO: Is the 'static bound on `I` really required? Can we avoid it?
pub fn flip_vertical<I: GenericImage + 'static>(image:  &I)
    -> ImageBuffer<I::Pixel, Vec<<I::Pixel as Pixel>::Subpixel>>
    where I::Pixel: 'static,
          <I::Pixel as Pixel>::Subpixel: 'static {
    let (width, height) = image.dimensions();
    let mut out = ImageBuffer::new(width, height);

    for y in (0..height) {
        for x in (0..width) {
            let p = image.get_pixel(x, y);
            out.put_pixel(x, height - 1 - y, p);
        }
    }

    out
}

#[cfg(test)]
mod test {
    use super::{rotate90,rotate180,rotate270,flip_horizontal,flip_vertical};
    use buffer::{ImageBuffer,Pixel,GrayImage};
    use image::{GenericImage};

    macro_rules! assert_pixels_eq {
        ($actual:expr, $expected:expr) => ({
            let actual_dim = $actual.dimensions();
            let expected_dim = $expected.dimensions();

            if actual_dim != expected_dim {
                panic!("dimensions do not match. \
                    actual: {:?}, expected: {:?}", actual_dim, expected_dim)
            }

            let diffs = pixel_diffs($actual, $expected);

            if !diffs.is_empty() {
                let mut err = "pixels do not match. ".to_string();

                let diff_messages = diffs
                    .iter()
                    .take(5)
                    .map(|d| format!("\nactual: {:?}, expected {:?} ", d.0, d.1))
                    .collect::<Vec<_>>()
                    .join("");

                err.push_str(&diff_messages);
                panic!(err)
            }
         })
     }

    #[test]
    fn test_rotate90() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00u8, 01u8, 02u8,
            10u8, 11u8, 12u8]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(2, 3, vec![
            10u8, 00u8,
            11u8, 01u8,
            12u8, 02u8]).unwrap();

        assert_pixels_eq!(&rotate90(&image), &expected);
    }

    #[test]
    fn test_rotate180() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00u8, 01u8, 02u8,
            10u8, 11u8, 12u8]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            12u8, 11u8, 10u8,
            02u8, 01u8, 00u8]).unwrap();

        assert_pixels_eq!(&rotate180(&image), &expected);
    }

    #[test]
    fn test_rotate270() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00u8, 01u8, 02u8,
            10u8, 11u8, 12u8]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(2, 3, vec![
            02u8, 12u8,
            01u8, 11u8,
            00u8, 10u8]).unwrap();

        assert_pixels_eq!(&rotate270(&image), &expected);
    }

    #[test]
    fn test_flip_horizontal() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00u8, 01u8, 02u8,
            10u8, 11u8, 12u8]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            02u8, 01u8, 00u8,
            12u8, 11u8, 10u8]).unwrap();

        assert_pixels_eq!(&flip_horizontal(&image), &expected);
    }

    #[test]
    fn test_flip_vertical() {
        let image: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            00u8, 01u8, 02u8,
            10u8, 11u8, 12u8]).unwrap();

        let expected: GrayImage = ImageBuffer::from_raw(3, 2, vec![
            10u8, 11u8, 12u8,
            00u8, 01u8, 02u8]).unwrap();

        assert_pixels_eq!(&flip_vertical(&image), &expected);
    }

    fn pixel_diffs<I, J, P>(left: &I, right: &J) -> Vec<((u32, u32, P), (u32, u32, P))>
        where I: GenericImage<Pixel=P>,
              J: GenericImage<Pixel=P>,
              P: Pixel + Eq {
        left.pixels()
            .zip(right.pixels())
            .filter(|&(p, q)| p != q)
            .collect::<Vec<_>>()
    }
}
<|endoftext|>


<commit_before>//! The `conf` module contains functions for loading and saving game
//! configurations.
//!
//! A `Conf` struct is used to specify hardware setup stuff used to create
//! the window and other context information.
//!
//! By default a ggez game will search its resource paths for a `/conf.toml`
//! file and load values from it when the `Context` is created.  This file
//! must be complete (ie you cannot just fill in some fields and have the
//! rest be default) and provides a nice way to specify settings that
//! can be tweaked such as window resolution, multisampling options, etc.

use std::io;
use toml;

use GameResult;

/// Possible fullscreen modes.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum FullscreenType {
    /// Windowed mode
    Off,
    /// Real fullscreen
    True(MonitorId),
    /// Windowed fullscreen, generally preferred over real fullscreen
    /// these days 'cause it plays nicer with multiple monitors.
    Desktop(MonitorId),
}

/// Identifies a monitor connected to the system.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum MonitorId {
    /// Monitor the window is currently in.
    Current,
    /// Monitor retrieved by it's index in the system.
    Index(usize),
}

/// A builder structure containing window settings
/// that can be set at runtime and changed with `graphics::set_mode()`
///
/// Defaults:
///
/// ```rust,ignore
/// WindowMode {
///     width: 800,
///     height: 600,
///     borderless: false,
///     fullscreen_type: FullscreenType::Off,
///     vsync: true,
///     min_width: 0,
///     max_width: 0,
///     min_height: 0,
///     max_height: 0,
/// }
/// ```
#[derive(Debug, Copy, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowMode {
    /// Window's inner dimensions (drawable area).
    #[default = r#"(800, 600)"#]
    pub dimensions: (u32, u32),
    /// Window's minimum dimensions; `None` is no limit.
    #[default = r#"None"#]
    pub min_dimensions: Option<(u32, u32)>,
    /// Window's maximum dimensions; `None` is no limit.
    #[default = r#"None"#]
    pub max_dimensions: Option<(u32, u32)>,
    /// Fullscreen type.
    #[default = r#"FullscreenType::Off"#]
    pub fullscreen_type: FullscreenType,
    /// Whether or not to maximize the window.
    #[default = r#"false"#]
    pub maximized: bool,
    /// Whether or not the window is hidden.
    #[default = r#"false"#]
    pub hidden: bool,
    /// Whether or not to show window decorations.
    #[default = r#"false"#]
    pub borderless: bool,
    /// Whether or not the window is pinned to always be on top of other windows.
    #[default = r#"false"#]
    pub always_on_top: bool,
}

impl WindowMode {
    /// Set default window size, or screen resolution in true fullscreen mode.
    pub fn dimensions(mut self, width: u32, height: u32) -> Self {
        self.dimensions = (width, height);
        self
    }

    /// Set minimum window dimensions for windowed mode.
    pub fn min_dimensions(mut self, width: u32, height: u32) -> Self {
        self.min_dimensions = Some((width, height));
        self
    }

    /// Set maximum window dimensions for windowed mode.
    pub fn max_dimensions(mut self, width: u32, height: u32) -> Self {
        self.max_dimensions = Some((width, height));
        self
    }

    /// Set the fullscreen type.
    pub fn fullscreen_type(mut self, fullscreen_type: FullscreenType) -> Self {
        self.fullscreen_type = fullscreen_type;
        self
    }

    /// Set if window should be maximized.
    pub fn maximized(mut self, maximized: bool) -> Self {
        self.maximized = maximized;
        self
    }

    /// Set if window should be hidden.
    pub fn hidden(mut self, hidden: bool) -> Self {
        self.hidden = hidden;
        self
    }

    /// Set whether or not to show window decorations.
    pub fn borderless(mut self, borderless: bool) -> Self {
        self.borderless = borderless;
        self
    }

    /// Set if window should pinned to always be on top of other windows.
    pub fn always_on_top(mut self, always_on_top: bool) -> Self {
        self.always_on_top = always_on_top;
        self
    }
}

/// A builder structure containing window settings
/// that must be set at init time and cannot be changed afterwards.
///
/// Defaults:
///
/// ```rust,ignore
/// WindowSetup {
///     title: "An easy, good game".to_owned(),
///     icon: "".to_owned(),
///     resizable: false,
///     allow_highdpi: true,
///     samples: NumSamples::One,
/// }
/// ```
#[derive(Debug, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowSetup {
    /// The window title.
    #[default = r#""An easy, good game".to_owned()"#]
    pub title: String,
    /// A file path to the window's icon.
    /// It is rooted in the `resources` directory (see the `filesystem` module for details),
    /// and an empty string results in a blank/default icon.
    #[default = r#""".to_owned()"#]
    pub icon: String,
    /// Whether or not the window is resizable.
    #[default = r#"false"#]
    pub resizable: bool,
    /// Whether or not should the window's background be transparent.
    #[default = r#"false"#]
    pub transparent: bool,
    /// Whether or not to enable vsync (vertical synchronization).
    #[default = r#"true"#]
    pub vsync: bool,
    /// Number of samples for multisample anti-aliasing.
    #[default = r#"NumSamples::One"#]
    pub samples: NumSamples,
}

impl WindowSetup {
    /// Set window's title.
    pub fn title(mut self, title: &str) -> Self {
        self.title = title.to_owned();
        self
    }

    /// Set the window's icon.
    pub fn icon(mut self, icon: &str) -> Self {
        self.icon = icon.to_owned();
        self
    }

    /// Set whether or not the window is resizable.
    pub fn resizable(mut self, resizable: bool) -> Self {
        self.resizable = resizable;
        self
    }

    /// Set if window's background should be transparent.
    pub fn transparent(mut self, transparent: bool) -> Self {
        self.transparent = transparent;
        self
    }

    /// Set if vsync is enabled.
    pub fn vsync(mut self, vsync: bool) -> Self {
        self.vsync = vsync;
        self
    }

    /// Set number of samples for multisample anti-aliasing.
    pub fn samples(mut self, samples: NumSamples) -> Self {
        self.samples = samples;
        self
    }
}

/// Possible backends.
/// Currently, only OpenGL Core spec is supported,
/// but this lets you specify the version numbers.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(tag = "type")]
pub enum Backend {
    /// Defaults to OpenGL 3.2, which is supported by basically
    /// every machine since 2009 or so (apart from the ones that don't)
    #[default]
    OpenGL {
        /// OpenGL major version
        #[default = r#"3"#]
        major: u8,
        /// OpenGL minor version
        #[default = r#"2"#]
        minor: u8,
    },
}

/// The possible number of samples for multisample anti-aliasing
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NumSamples {
    /// One sample
    One = 1,
    /// Two samples
    Two = 2,
    /// Four samples
    Four = 4,
    /// Eight samples
    Eight = 8,
    /// Sixteen samples
    Sixteen = 16,
}

impl NumSamples {
    /// Create a NumSamples from a number.
    /// Returns None if i is invalid.
    pub fn from_u32(i: u32) -> Option<NumSamples> {
        match i {
            1 => Some(NumSamples::One),
            2 => Some(NumSamples::Two),
            4 => Some(NumSamples::Four),
            8 => Some(NumSamples::Eight),
            16 => Some(NumSamples::Sixteen),
            _ => None,
        }
    }
}

/// A structure containing configuration data
/// for the game engine.
///
/// Defaults:
///
/// ```rust,ignore
/// Conf {
///     window_mode: WindowMode::default(),
///     window_setup: WindowSetup::default(),
///     backend: Backend::OpenGL(3, 2),
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, PartialEq, SmartDefault)]
pub struct Conf {
    /// Window setting information that can be set at runtime
    pub window_mode: WindowMode,
    /// Window setting information that must be set at init-time
    pub window_setup: WindowSetup,
    /// Backend configuration
    pub backend: Backend,
}

impl Conf {
    /// Same as Conf::default()
    pub fn new() -> Self {
        Self::default()
    }

    /// Load a TOML file from the given `Read` and attempts to parse
    /// a `Conf` from it.
    pub fn from_toml_file<R: io::Read>(file: &mut R) -> GameResult<Conf> {
        let mut s = String::new();
        file.read_to_string(&mut s)?;
        let decoded = toml::from_str(&s)?;
        Ok(decoded)
    }

    /// Saves the `Conf` to the given `Write` object,
    /// formatted as TOML.
    pub fn to_toml_file<W: io::Write>(&self, file: &mut W) -> GameResult {
        let s = toml::to_vec(self)?;
        file.write_all(&s)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use conf;

    /// Tries to encode and decode a `Conf` object
    /// and makes sure it gets the same result it had.
    #[test]
    fn encode_round_trip() {
        let c1 = conf::Conf::new();
        let mut writer = Vec::new();
        let _c = c1.to_toml_file(&mut writer).unwrap();
        let mut reader = writer.as_slice();
        let c2 = conf::Conf::from_toml_file(&mut reader).unwrap();
        assert_eq!(c1, c2);
    }
}
<commit_msg>Fixed docs for `WindowMode`, `WindowSetup`.<commit_after>//! The `conf` module contains functions for loading and saving game
//! configurations.
//!
//! A `Conf` struct is used to specify hardware setup stuff used to create
//! the window and other context information.
//!
//! By default a ggez game will search its resource paths for a `/conf.toml`
//! file and load values from it when the `Context` is created.  This file
//! must be complete (ie you cannot just fill in some fields and have the
//! rest be default) and provides a nice way to specify settings that
//! can be tweaked such as window resolution, multisampling options, etc.

use std::io;
use toml;

use GameResult;

/// Possible fullscreen modes.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum FullscreenType {
    /// Windowed mode
    Off,
    /// Real fullscreen
    True(MonitorId),
    /// Windowed fullscreen, generally preferred over real fullscreen
    /// these days 'cause it plays nicer with multiple monitors.
    Desktop(MonitorId),
}

/// Identifies a monitor connected to the system.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum MonitorId {
    /// Monitor the window is currently in.
    Current,
    /// Monitor retrieved by it's index in the system.
    Index(usize),
}

/// A builder structure containing window settings
/// that can be set at runtime and changed with `graphics::set_mode()`.
///
/// Defaults:
///
/// ```rust
///use ggez::conf::{FullscreenType, WindowMode};
///assert_eq!(
///    WindowMode::default(),
///    WindowMode {
///        dimensions: (800, 600),
///        min_dimensions: None,
///        max_dimensions: None,
///        fullscreen_type: FullscreenType::Off,
///        maximized: false,
///        hidden: false,
///        borderless: false,
///        always_on_top: false,
///    },
///);
/// ```
#[derive(Debug, Copy, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowMode {
    /// Window's inner dimensions (drawable area).
    #[default = r#"(800, 600)"#]
    pub dimensions: (u32, u32),
    /// Window's minimum dimensions; `None` is no limit.
    #[default = r#"None"#]
    pub min_dimensions: Option<(u32, u32)>,
    /// Window's maximum dimensions; `None` is no limit.
    #[default = r#"None"#]
    pub max_dimensions: Option<(u32, u32)>,
    /// Fullscreen type.
    #[default = r#"FullscreenType::Off"#]
    pub fullscreen_type: FullscreenType,
    /// Whether or not to maximize the window.
    #[default = r#"false"#]
    pub maximized: bool,
    /// Whether or not the window is hidden.
    #[default = r#"false"#]
    pub hidden: bool,
    /// Whether or not to show window decorations.
    #[default = r#"false"#]
    pub borderless: bool,
    /// Whether or not the window is pinned to always be on top of other windows.
    #[default = r#"false"#]
    pub always_on_top: bool,
}

impl WindowMode {
    /// Set default window size, or screen resolution in true fullscreen mode.
    pub fn dimensions(mut self, width: u32, height: u32) -> Self {
        self.dimensions = (width, height);
        self
    }

    /// Set minimum window dimensions for windowed mode.
    pub fn min_dimensions(mut self, width: u32, height: u32) -> Self {
        self.min_dimensions = Some((width, height));
        self
    }

    /// Set maximum window dimensions for windowed mode.
    pub fn max_dimensions(mut self, width: u32, height: u32) -> Self {
        self.max_dimensions = Some((width, height));
        self
    }

    /// Set the fullscreen type.
    pub fn fullscreen_type(mut self, fullscreen_type: FullscreenType) -> Self {
        self.fullscreen_type = fullscreen_type;
        self
    }

    /// Set if window should be maximized.
    pub fn maximized(mut self, maximized: bool) -> Self {
        self.maximized = maximized;
        self
    }

    /// Set if window should be hidden.
    pub fn hidden(mut self, hidden: bool) -> Self {
        self.hidden = hidden;
        self
    }

    /// Set whether or not to show window decorations.
    pub fn borderless(mut self, borderless: bool) -> Self {
        self.borderless = borderless;
        self
    }

    /// Set if window should pinned to always be on top of other windows.
    pub fn always_on_top(mut self, always_on_top: bool) -> Self {
        self.always_on_top = always_on_top;
        self
    }
}

/// A builder structure containing window settings
/// that must be set at init time and (mostly) cannot be changed afterwards.
///
/// Defaults:
///
/// ```rust
///use ggez::conf::{NumSamples, WindowSetup};
///assert_eq!(
///    WindowSetup::default(),
///    WindowSetup {
///        title: "An easy, good game".to_owned(),
///        icon: "".to_owned(),
///        resizable: false,
///        transparent: false,
///        vsync: true,
///        samples: NumSamples::One,
///    },
///);
/// ```
#[derive(Debug, Clone, SmartDefault, Serialize, Deserialize, PartialEq, Eq)]
pub struct WindowSetup {
    /// The window title.
    #[default = r#""An easy, good game".to_owned()"#]
    pub title: String,
    /// A file path to the window's icon.
    /// It is rooted in the `resources` directory (see the `filesystem` module for details),
    /// and an empty string results in a blank/default icon.
    #[default = r#""".to_owned()"#]
    pub icon: String,
    /// Whether or not the window is resizable.
    #[default = r#"false"#]
    pub resizable: bool,
    /// Whether or not should the window's background be transparent.
    #[default = r#"false"#]
    pub transparent: bool,
    /// Whether or not to enable vsync (vertical synchronization).
    #[default = r#"true"#]
    pub vsync: bool,
    /// Number of samples for multisample anti-aliasing.
    #[default = r#"NumSamples::One"#]
    pub samples: NumSamples,
}

impl WindowSetup {
    /// Set window's title.
    pub fn title(mut self, title: &str) -> Self {
        self.title = title.to_owned();
        self
    }

    /// Set the window's icon.
    pub fn icon(mut self, icon: &str) -> Self {
        self.icon = icon.to_owned();
        self
    }

    /// Set whether or not the window is resizable.
    pub fn resizable(mut self, resizable: bool) -> Self {
        self.resizable = resizable;
        self
    }

    /// Set if window's background should be transparent.
    pub fn transparent(mut self, transparent: bool) -> Self {
        self.transparent = transparent;
        self
    }

    /// Set if vsync is enabled.
    pub fn vsync(mut self, vsync: bool) -> Self {
        self.vsync = vsync;
        self
    }

    /// Set number of samples for multisample anti-aliasing.
    pub fn samples(mut self, samples: NumSamples) -> Self {
        self.samples = samples;
        self
    }
}

/// Possible backends.
/// Currently, only OpenGL Core spec is supported,
/// but this lets you specify the version numbers.
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq, SmartDefault)]
#[serde(tag = "type")]
pub enum Backend {
    /// Defaults to OpenGL 3.2, which is supported by basically
    /// every machine since 2009 or so (apart from the ones that don't)
    #[default]
    OpenGL {
        /// OpenGL major version
        #[default = r#"3"#]
        major: u8,
        /// OpenGL minor version
        #[default = r#"2"#]
        minor: u8,
    },
}

/// The possible number of samples for multisample anti-aliasing
#[derive(Debug, Copy, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum NumSamples {
    /// One sample
    One = 1,
    /// Two samples
    Two = 2,
    /// Four samples
    Four = 4,
    /// Eight samples
    Eight = 8,
    /// Sixteen samples
    Sixteen = 16,
}

impl NumSamples {
    /// Create a NumSamples from a number.
    /// Returns None if i is invalid.
    pub fn from_u32(i: u32) -> Option<NumSamples> {
        match i {
            1 => Some(NumSamples::One),
            2 => Some(NumSamples::Two),
            4 => Some(NumSamples::Four),
            8 => Some(NumSamples::Eight),
            16 => Some(NumSamples::Sixteen),
            _ => None,
        }
    }
}

/// A structure containing configuration data
/// for the game engine.
///
/// Defaults:
///
/// ```rust,ignore
/// Conf {
///     window_mode: WindowMode::default(),
///     window_setup: WindowSetup::default(),
///     backend: Backend::OpenGL(3, 2),
/// }
/// ```
#[derive(Serialize, Deserialize, Debug, PartialEq, SmartDefault)]
pub struct Conf {
    /// Window setting information that can be set at runtime
    pub window_mode: WindowMode,
    /// Window setting information that must be set at init-time
    pub window_setup: WindowSetup,
    /// Backend configuration
    pub backend: Backend,
}

impl Conf {
    /// Same as Conf::default()
    pub fn new() -> Self {
        Self::default()
    }

    /// Load a TOML file from the given `Read` and attempts to parse
    /// a `Conf` from it.
    pub fn from_toml_file<R: io::Read>(file: &mut R) -> GameResult<Conf> {
        let mut s = String::new();
        file.read_to_string(&mut s)?;
        let decoded = toml::from_str(&s)?;
        Ok(decoded)
    }

    /// Saves the `Conf` to the given `Write` object,
    /// formatted as TOML.
    pub fn to_toml_file<W: io::Write>(&self, file: &mut W) -> GameResult {
        let s = toml::to_vec(self)?;
        file.write_all(&s)?;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use conf;

    /// Tries to encode and decode a `Conf` object
    /// and makes sure it gets the same result it had.
    #[test]
    fn encode_round_trip() {
        let c1 = conf::Conf::new();
        let mut writer = Vec::new();
        let _c = c1.to_toml_file(&mut writer).unwrap();
        let mut reader = writer.as_slice();
        let c2 = conf::Conf::from_toml_file(&mut reader).unwrap();
        assert_eq!(c1, c2);
    }
}
<|endoftext|>


<commit_before>use Cost;

/// Pass an instance of this type to a training algorithm to optimize for C=Error^2
///
/// Optimizing a `model::Constant` for `LeastSquares` should yield the mean value
pub struct LeastSquares;

impl Cost<f64> for LeastSquares {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64 {
        let error = prediction - truth;
        2.0 * error * gradient_error_by_coefficent
    }
}

/// Pass an instance of this type to a training algorithm to optimize for C=|Error|
///
/// Optimizing a `model::Constant` for `LeastAbsoluteDeviation` should yield the median.
/// Gradient for error == 0 is set to 0
pub struct LeastAbsoluteDeviation;

impl Cost<f64> for LeastAbsoluteDeviation {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64 {
        let error = prediction - truth;
        if error > 0.0 {
            gradient_error_by_coefficent
        } else if error < 0.0 {
            -gradient_error_by_coefficent
        } else {
            0.0
        }
    }
}

/// Maximizes the likelihood function `L` by defining `C=-ln(L)`
///
/// You can use this function if your truth is a probability
/// (i.e., a value betwenn 0 and 1). Maximizing the likelihood
/// function is equivalent to minimizing the least square error,
/// yet this cost function has shown itself to converge quicker
/// for some problems.
///
/// #Examples
///
/// ```
/// use vikos::{learn_history, Model};
/// use vikos::model::{Logistic, Linear};
///
/// let history = [([2.7, 2.5], false),
///                ([1.4, 2.3], false),
///                ([3.3, 4.4], false),
///                ([1.3, 1.8], false),
///                ([3.0, 3.0], false),
///                ([7.6, 2.7], true),
///                ([5.3, 2.0], true),
///                ([6.9, 1.7], true),
///                ([8.6, -0.2], true),
///                ([7.6, 3.5], true)];
///
/// let mut model = Logistic {
///     linear: Linear {
///         m: [0.0, 0.0],
///         c: 0.0,
///     },
/// };
/// let teacher = teacher::GradientDescent { learning_rate: 0.3 };
/// let cost = cost::MaxLikelihood {};
///
/// learn_history(&teacher,
///               &cost,
///               &mut model,
///               history.iter().cycle().take(20).cloned());
/// ```
pub struct MaxLikelihood;

impl Cost<f64> for MaxLikelihood {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64 {
        gradient_error_by_coefficent * ((1.0 - truth) / (1.0 - prediction) - truth / prediction)
    }
}

impl Cost<bool> for MaxLikelihood {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: bool, gradient_error_by_coefficent: f64) -> f64 {
        gradient_error_by_coefficent / if truth { -prediction } else { 1.0 - prediction }
    }
}
<commit_msg>example for max likelihood<commit_after>use Cost;

/// Pass an instance of this type to a training algorithm to optimize for C=Error^2
///
/// Optimizing a `model::Constant` for `LeastSquares` should yield the mean value
pub struct LeastSquares;

impl Cost<f64> for LeastSquares {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64 {
        let error = prediction - truth;
        2.0 * error * gradient_error_by_coefficent
    }
}

/// Pass an instance of this type to a training algorithm to optimize for C=|Error|
///
/// Optimizing a `model::Constant` for `LeastAbsoluteDeviation` should yield the median.
/// Gradient for error == 0 is set to 0
pub struct LeastAbsoluteDeviation;

impl Cost<f64> for LeastAbsoluteDeviation {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64 {
        let error = prediction - truth;
        if error > 0.0 {
            gradient_error_by_coefficent
        } else if error < 0.0 {
            -gradient_error_by_coefficent
        } else {
            0.0
        }
    }
}

/// Maximizes the likelihood function `L` by defining `C=-ln(L)`
///
/// You can use this function if your truth is a probability
/// (i.e., a value betwenn 0 and 1). Maximizing the likelihood
/// function is equivalent to minimizing the least square error,
/// yet this cost function has shown itself to converge quicker
/// for some problems.
///
/// #Examples
///
/// ```
/// use vikos::{learn_history, Model, teacher, cost};
/// use vikos::model::{Logistic, Linear};
///
/// let history = [([2.7, 2.5], false),
///                ([1.4, 2.3], false),
///                ([3.3, 4.4], false),
///                ([1.3, 1.8], false),
///                ([3.0, 3.0], false),
///                ([7.6, 2.7], true),
///                ([5.3, 2.0], true),
///                ([6.9, 1.7], true),
///                ([8.6, -0.2], true),
///                ([7.6, 3.5], true)];
///
/// let mut model = Logistic {
///     linear: Linear {
///         m: [0.0, 0.0],
///         c: 0.0,
///     },
/// };
/// let teacher = teacher::GradientDescent { learning_rate: 0.3 };
/// let cost = cost::MaxLikelihood {};
///
/// learn_history(&teacher,
///               &cost,
///               &mut model,
///               history.iter().cycle().take(20).cloned());
/// ```
pub struct MaxLikelihood;

impl Cost<f64> for MaxLikelihood {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: f64, gradient_error_by_coefficent: f64) -> f64 {
        gradient_error_by_coefficent * ((1.0 - truth) / (1.0 - prediction) - truth / prediction)
    }
}

impl Cost<bool> for MaxLikelihood {
    type Error = f64;

    fn gradient(&self, prediction: f64, truth: bool, gradient_error_by_coefficent: f64) -> f64 {
        gradient_error_by_coefficent / if truth { -prediction } else { 1.0 - prediction }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::io::prelude::*;
use std::io::Cursor;
use std::result::Result::{Err, Ok};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use errors::{Error, Result};
use util::{XxHash32, xxhash32};

const ENTRY_STATIC_SIZE: usize = 18; // checksum(4) + sequence(8) + key_size(2) + value_size(4)
const ENTRY_TOMBSTONE: u32 = !0;
pub const MAX_VALUE_SIZE: u32 = !0 - 1;
pub const MAX_KEY_SIZE: u16 = !0;

pub type SequenceNumber = u64;

#[derive(Debug, Eq, PartialEq)]
pub struct Entry<'a> {
    pub key: Cow<'a, [u8]>,
    pub value: Cow<'a, [u8]>,
    pub sequence: SequenceNumber,
    pub deleted: bool,
}

impl<'a> Entry<'a> {
    pub fn new<K, V>(sequence: SequenceNumber, key: K, value: V) -> Result<Entry<'a>>
        where Cow<'a, [u8]>: From<K>,
              Cow<'a, [u8]>: From<V>
    {
        let v = Cow::from(value);
        let k = Cow::from(key);

        if k.len() > MAX_KEY_SIZE as usize {
            return Err(Error::InvalidKeySize(k.len()));
        }

        if v.len() > MAX_VALUE_SIZE as usize {
            return Err(Error::InvalidValueSize(v.len()));
        }

        Ok(Entry {
               key: k,
               value: v,
               sequence: sequence,
               deleted: false,
           })
    }

    pub fn deleted<K>(sequence: SequenceNumber, key: K) -> Entry<'a>
        where Cow<'a, [u8]>: From<K>
    {
        Entry {
            key: Cow::from(key),
            value: Cow::Borrowed(&[]),
            sequence: sequence,
            deleted: true,
        }
    }

    pub fn size(&self) -> u64 {
        ENTRY_STATIC_SIZE as u64 + self.key.len() as u64 + self.value.len() as u64
    }

    #[allow(dead_code)]
    pub fn to_bytes(&self) -> Result<Vec<u8>> {
        let mut cursor = Cursor::new(Vec::with_capacity(self.size() as usize));
        cursor.set_position(4);
        cursor.write_u64::<LittleEndian>(self.sequence)?;
        cursor.write_u16::<LittleEndian>(self.key.len() as u16)?;

        if self.deleted {
            cursor.write_u32::<LittleEndian>(ENTRY_TOMBSTONE)?;
            cursor.write_all(&self.key)?;
        } else {
            cursor.write_u32::<LittleEndian>(self.value.len() as u32)?;
            cursor.write_all(&self.key)?;
            cursor.write_all(&self.value)?;
        }

        let checksum = xxhash32(&cursor.get_ref()[4..]);
        cursor.set_position(0);
        cursor.write_u32::<LittleEndian>(checksum)?;

        Ok(cursor.into_inner())
    }

    pub fn write_bytes<W: Write>(&self, writer: &mut W) -> Result<()> {
        let mut cursor = Cursor::new(Vec::with_capacity(ENTRY_STATIC_SIZE));
        cursor.set_position(4);
        cursor.write_u64::<LittleEndian>(self.sequence)?;
        cursor.write_u16::<LittleEndian>(self.key.len() as u16)?;

        if self.deleted {
            cursor.write_u32::<LittleEndian>(ENTRY_TOMBSTONE)?;
        } else {
            cursor.write_u32::<LittleEndian>(self.value.len() as u32)?;
        }

        let checksum = {
            let mut hasher = XxHash32::new();
            hasher.update(&cursor.get_ref()[4..]);
            hasher.update(&self.key);
            hasher.update(&self.value);
            hasher.get()
        };

        cursor.set_position(0);
        cursor.write_u32::<LittleEndian>(checksum)?;

        writer.write_all(&cursor.into_inner())?;
        writer.write_all(&self.key)?;

        if !self.deleted {
            writer.write_all(&self.value)?;
        }

        Ok(())
    }

    #[allow(dead_code)]
    pub fn from_bytes(bytes: &'a [u8]) -> Result<Entry<'a>> {
        let mut cursor = Cursor::new(bytes);

        let checksum = cursor.read_u32::<LittleEndian>()?;
        assert_eq!(xxhash32(&bytes[4..]), checksum);

        let sequence = cursor.read_u64::<LittleEndian>()?;
        let key_size = cursor.read_u16::<LittleEndian>()?;
        let value_size = cursor.read_u32::<LittleEndian>()?;

        let deleted = value_size == ENTRY_TOMBSTONE;

        let value = if deleted {
            let empty: &[u8] = &[];
            Cow::from(empty)
        } else {
            Cow::from(&bytes[ENTRY_STATIC_SIZE + key_size as usize..])
        };

        Ok(Entry {
               key: Cow::from(&bytes[ENTRY_STATIC_SIZE..ENTRY_STATIC_SIZE + key_size as usize]),
               value: value,
               sequence: sequence,
               deleted: value_size == ENTRY_TOMBSTONE,
           })
    }

    pub fn from_read<R: Read>(reader: &mut R) -> Result<Entry<'a>> {
        let mut header = vec![0u8; ENTRY_STATIC_SIZE as usize];
        reader.read_exact(&mut header)?;

        let mut cursor = Cursor::new(header);
        let checksum = cursor.read_u32::<LittleEndian>()?;
        let sequence = cursor.read_u64::<LittleEndian>()?;
        let key_size = cursor.read_u16::<LittleEndian>()?;
        let value_size = cursor.read_u32::<LittleEndian>()?;

        let mut key = vec![0u8; key_size as usize];
        reader.read_exact(&mut key)?;

        let deleted = value_size == ENTRY_TOMBSTONE;

        let value = if deleted {
            let empty: &[u8] = &[];
            Cow::from(empty)
        } else {
            let mut value = vec![0u8; value_size as usize];
            reader.read_exact(&mut value)?;
            Cow::from(value)
        };

        let hash = {
            let mut hasher = XxHash32::new();
            hasher.update(&cursor.get_ref()[4..]);
            hasher.update(&key);
            hasher.update(&value);
            hasher.get()
        };

        assert_eq!(hash, checksum);

        Ok(Entry {
               key: Cow::from(key),
               value: value,
               sequence: sequence,
               deleted: deleted,
           })
    }
}

pub struct Hint<'a> {
    pub key: Cow<'a, [u8]>,
    pub entry_pos: u64,
    pub value_size: u32,
    pub sequence: SequenceNumber,
    pub deleted: bool,
}

impl<'a> Hint<'a> {
    pub fn new(e: &'a Entry, entry_pos: u64) -> Hint<'a> {
        Hint {
            key: Cow::from(&*e.key),
            entry_pos: entry_pos,
            value_size: e.value.len() as u32,
            sequence: e.sequence,
            deleted: e.deleted,
        }
    }

    pub fn from(e: Entry<'a>, entry_pos: u64) -> Hint<'a> {
        Hint {
            key: e.key,
            entry_pos: entry_pos,
            value_size: e.value.len() as u32,
            sequence: e.sequence,
            deleted: e.deleted,
        }
    }

    pub fn entry_size(&self) -> u64 {
        ENTRY_STATIC_SIZE as u64 + self.key.len() as u64 + self.value_size as u64
    }

    pub fn write_bytes<W: Write>(&self, writer: &mut W) -> Result<()> {
        writer.write_u64::<LittleEndian>(self.sequence)?;
        writer.write_u16::<LittleEndian>(self.key.len() as u16)?;

        if self.deleted {
            writer.write_u32::<LittleEndian>(ENTRY_TOMBSTONE)?;
        } else {
            writer.write_u32::<LittleEndian>(self.value_size)?;
        }

        writer.write_u64::<LittleEndian>(self.entry_pos)?;
        writer.write_all(&self.key)?;

        Ok(())
    }

    pub fn from_read<R: Read>(reader: &mut R) -> Result<Hint<'a>> {
        let sequence = reader.read_u64::<LittleEndian>()?;
        let key_size = reader.read_u16::<LittleEndian>()?;
        let value_size = reader.read_u32::<LittleEndian>()?;
        let entry_pos = reader.read_u64::<LittleEndian>()?;

        let mut key = vec![0u8; key_size as usize];
        reader.read_exact(&mut key)?;

        let deleted = value_size == ENTRY_TOMBSTONE;

        Ok(Hint {
               key: Cow::from(key),
               entry_pos: entry_pos,
               value_size: if deleted { 0 } else { value_size },
               sequence: sequence,
               deleted: value_size == ENTRY_TOMBSTONE,
           })
    }
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;

    use data::Entry;

    #[test]
    fn test_serialization() {
        let sequence = 0;
        let key: &[u8] = &[0, 0, 0];
        let value: &[u8] = &[0, 0, 0];
        let entry = Entry::new(sequence, key, value).unwrap();
        let deleted_entry = Entry::deleted(sequence, key);

        assert_eq!(entry.to_bytes().unwrap().len(), 24);

        assert_eq!(entry,
                   Entry::from_bytes(&entry.to_bytes().unwrap()).unwrap());
        assert_eq!(entry,
                   Entry::from_read(&mut Cursor::new(entry.to_bytes().unwrap())).unwrap());
        let mut v = Vec::new();
        entry.write_bytes(&mut v).unwrap();
        assert_eq!(entry, Entry::from_bytes(&v).unwrap());

        assert_eq!(deleted_entry,
                   Entry::from_bytes(&deleted_entry.to_bytes().unwrap()).unwrap());
        assert_eq!(deleted_entry,
                   Entry::from_read(&mut Cursor::new(deleted_entry.to_bytes().unwrap())).unwrap());
        v.clear();
        deleted_entry.write_bytes(&mut v).unwrap();
        assert_eq!(deleted_entry, Entry::from_bytes(&v).unwrap());
    }

    #[test]
    fn test_deleted() {
        let sequence = 0;
        let key: &[u8] = &[0, 0, 0];

        assert!(Entry::deleted(sequence, key).deleted);
        assert_eq!(Entry::deleted(sequence, key).value.len(), 0);
    }
}
<commit_msg>handle checksum errors<commit_after>use std::borrow::Cow;
use std::io::prelude::*;
use std::io::Cursor;
use std::result::Result::{Err, Ok};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use errors::{Error, Result};
use util::{XxHash32, xxhash32};

const ENTRY_STATIC_SIZE: usize = 18; // checksum(4) + sequence(8) + key_size(2) + value_size(4)
const ENTRY_TOMBSTONE: u32 = !0;
pub const MAX_VALUE_SIZE: u32 = !0 - 1;
pub const MAX_KEY_SIZE: u16 = !0;

pub type SequenceNumber = u64;

#[derive(Debug, Eq, PartialEq)]
pub struct Entry<'a> {
    pub key: Cow<'a, [u8]>,
    pub value: Cow<'a, [u8]>,
    pub sequence: SequenceNumber,
    pub deleted: bool,
}

impl<'a> Entry<'a> {
    pub fn new<K, V>(sequence: SequenceNumber, key: K, value: V) -> Result<Entry<'a>>
        where Cow<'a, [u8]>: From<K>,
              Cow<'a, [u8]>: From<V>
    {
        let v = Cow::from(value);
        let k = Cow::from(key);

        if k.len() > MAX_KEY_SIZE as usize {
            return Err(Error::InvalidKeySize(k.len()));
        }

        if v.len() > MAX_VALUE_SIZE as usize {
            return Err(Error::InvalidValueSize(v.len()));
        }

        Ok(Entry {
               key: k,
               value: v,
               sequence: sequence,
               deleted: false,
           })
    }

    pub fn deleted<K>(sequence: SequenceNumber, key: K) -> Entry<'a>
        where Cow<'a, [u8]>: From<K>
    {
        Entry {
            key: Cow::from(key),
            value: Cow::Borrowed(&[]),
            sequence: sequence,
            deleted: true,
        }
    }

    pub fn size(&self) -> u64 {
        ENTRY_STATIC_SIZE as u64 + self.key.len() as u64 + self.value.len() as u64
    }

    #[allow(dead_code)]
    pub fn to_bytes(&self) -> Result<Vec<u8>> {
        let mut cursor = Cursor::new(Vec::with_capacity(self.size() as usize));
        cursor.set_position(4);
        cursor.write_u64::<LittleEndian>(self.sequence)?;
        cursor.write_u16::<LittleEndian>(self.key.len() as u16)?;

        if self.deleted {
            cursor.write_u32::<LittleEndian>(ENTRY_TOMBSTONE)?;
            cursor.write_all(&self.key)?;
        } else {
            cursor.write_u32::<LittleEndian>(self.value.len() as u32)?;
            cursor.write_all(&self.key)?;
            cursor.write_all(&self.value)?;
        }

        let checksum = xxhash32(&cursor.get_ref()[4..]);
        cursor.set_position(0);
        cursor.write_u32::<LittleEndian>(checksum)?;

        Ok(cursor.into_inner())
    }

    pub fn write_bytes<W: Write>(&self, writer: &mut W) -> Result<()> {
        let mut cursor = Cursor::new(Vec::with_capacity(ENTRY_STATIC_SIZE));
        cursor.set_position(4);
        cursor.write_u64::<LittleEndian>(self.sequence)?;
        cursor.write_u16::<LittleEndian>(self.key.len() as u16)?;

        if self.deleted {
            cursor.write_u32::<LittleEndian>(ENTRY_TOMBSTONE)?;
        } else {
            cursor.write_u32::<LittleEndian>(self.value.len() as u32)?;
        }

        let checksum = {
            let mut hasher = XxHash32::new();
            hasher.update(&cursor.get_ref()[4..]);
            hasher.update(&self.key);
            hasher.update(&self.value);
            hasher.get()
        };

        cursor.set_position(0);
        cursor.write_u32::<LittleEndian>(checksum)?;

        writer.write_all(&cursor.into_inner())?;
        writer.write_all(&self.key)?;

        if !self.deleted {
            writer.write_all(&self.value)?;
        }

        Ok(())
    }

    #[allow(dead_code)]
    pub fn from_bytes(bytes: &'a [u8]) -> Result<Entry<'a>> {
        let mut cursor = Cursor::new(bytes);

        let checksum = cursor.read_u32::<LittleEndian>()?;

        let hash = xxhash32(&bytes[4..]);

        if hash != checksum {
            return Err(Error::InvalidChecksum {
                           expected: checksum,
                           found: hash,
                       });
        }

        let sequence = cursor.read_u64::<LittleEndian>()?;
        let key_size = cursor.read_u16::<LittleEndian>()?;
        let value_size = cursor.read_u32::<LittleEndian>()?;

        let deleted = value_size == ENTRY_TOMBSTONE;

        let value = if deleted {
            let empty: &[u8] = &[];
            Cow::from(empty)
        } else {
            Cow::from(&bytes[ENTRY_STATIC_SIZE + key_size as usize..])
        };

        Ok(Entry {
               key: Cow::from(&bytes[ENTRY_STATIC_SIZE..ENTRY_STATIC_SIZE + key_size as usize]),
               value: value,
               sequence: sequence,
               deleted: value_size == ENTRY_TOMBSTONE,
           })
    }

    pub fn from_read<R: Read>(reader: &mut R) -> Result<Entry<'a>> {
        let mut header = vec![0u8; ENTRY_STATIC_SIZE as usize];
        reader.read_exact(&mut header)?;

        let mut cursor = Cursor::new(header);
        let checksum = cursor.read_u32::<LittleEndian>()?;
        let sequence = cursor.read_u64::<LittleEndian>()?;
        let key_size = cursor.read_u16::<LittleEndian>()?;
        let value_size = cursor.read_u32::<LittleEndian>()?;

        let mut key = vec![0u8; key_size as usize];
        reader.read_exact(&mut key)?;

        let deleted = value_size == ENTRY_TOMBSTONE;

        let value = if deleted {
            let empty: &[u8] = &[];
            Cow::from(empty)
        } else {
            let mut value = vec![0u8; value_size as usize];
            reader.read_exact(&mut value)?;
            Cow::from(value)
        };

        let hash = {
            let mut hasher = XxHash32::new();
            hasher.update(&cursor.get_ref()[4..]);
            hasher.update(&key);
            hasher.update(&value);
            hasher.get()
        };

        if hash != checksum {
            return Err(Error::InvalidChecksum {
                           expected: checksum,
                           found: hash,
                       });
        }

        Ok(Entry {
               key: Cow::from(key),
               value: value,
               sequence: sequence,
               deleted: deleted,
           })
    }
}

pub struct Hint<'a> {
    pub key: Cow<'a, [u8]>,
    pub entry_pos: u64,
    pub value_size: u32,
    pub sequence: SequenceNumber,
    pub deleted: bool,
}

impl<'a> Hint<'a> {
    pub fn new(e: &'a Entry, entry_pos: u64) -> Hint<'a> {
        Hint {
            key: Cow::from(&*e.key),
            entry_pos: entry_pos,
            value_size: e.value.len() as u32,
            sequence: e.sequence,
            deleted: e.deleted,
        }
    }

    pub fn from(e: Entry<'a>, entry_pos: u64) -> Hint<'a> {
        Hint {
            key: e.key,
            entry_pos: entry_pos,
            value_size: e.value.len() as u32,
            sequence: e.sequence,
            deleted: e.deleted,
        }
    }

    pub fn entry_size(&self) -> u64 {
        ENTRY_STATIC_SIZE as u64 + self.key.len() as u64 + self.value_size as u64
    }

    pub fn write_bytes<W: Write>(&self, writer: &mut W) -> Result<()> {
        writer.write_u64::<LittleEndian>(self.sequence)?;
        writer.write_u16::<LittleEndian>(self.key.len() as u16)?;

        if self.deleted {
            writer.write_u32::<LittleEndian>(ENTRY_TOMBSTONE)?;
        } else {
            writer.write_u32::<LittleEndian>(self.value_size)?;
        }

        writer.write_u64::<LittleEndian>(self.entry_pos)?;
        writer.write_all(&self.key)?;

        Ok(())
    }

    pub fn from_read<R: Read>(reader: &mut R) -> Result<Hint<'a>> {
        let sequence = reader.read_u64::<LittleEndian>()?;
        let key_size = reader.read_u16::<LittleEndian>()?;
        let value_size = reader.read_u32::<LittleEndian>()?;
        let entry_pos = reader.read_u64::<LittleEndian>()?;

        let mut key = vec![0u8; key_size as usize];
        reader.read_exact(&mut key)?;

        let deleted = value_size == ENTRY_TOMBSTONE;

        Ok(Hint {
               key: Cow::from(key),
               entry_pos: entry_pos,
               value_size: if deleted { 0 } else { value_size },
               sequence: sequence,
               deleted: value_size == ENTRY_TOMBSTONE,
           })
    }
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;

    use data::Entry;

    #[test]
    fn test_serialization() {
        let sequence = 0;
        let key: &[u8] = &[0, 0, 0];
        let value: &[u8] = &[0, 0, 0];
        let entry = Entry::new(sequence, key, value).unwrap();
        let deleted_entry = Entry::deleted(sequence, key);

        assert_eq!(entry.to_bytes().unwrap().len(), 24);

        assert_eq!(entry,
                   Entry::from_bytes(&entry.to_bytes().unwrap()).unwrap());
        assert_eq!(entry,
                   Entry::from_read(&mut Cursor::new(entry.to_bytes().unwrap())).unwrap());
        let mut v = Vec::new();
        entry.write_bytes(&mut v).unwrap();
        assert_eq!(entry, Entry::from_bytes(&v).unwrap());

        assert_eq!(deleted_entry,
                   Entry::from_bytes(&deleted_entry.to_bytes().unwrap()).unwrap());
        assert_eq!(deleted_entry,
                   Entry::from_read(&mut Cursor::new(deleted_entry.to_bytes().unwrap())).unwrap());
        v.clear();
        deleted_entry.write_bytes(&mut v).unwrap();
        assert_eq!(deleted_entry, Entry::from_bytes(&v).unwrap());
    }

    #[test]
    fn test_deleted() {
        let sequence = 0;
        let key: &[u8] = &[0, 0, 0];

        assert!(Entry::deleted(sequence, key).deleted);
        assert_eq!(Entry::deleted(sequence, key).value.len(), 0);
    }
}
<|endoftext|>


<commit_before>//! Evaluation of expressions

use std::fmt;

use ast::Expr;
use env::Env;

/// Evaluation errors
#[derive(Debug)]
pub enum Error {
    /// `()`
    EmptyList,
    /// `("abc" 1 2)`
    ExpectedSymbolGot(Expr),
    /// Symbol not yet defined
    UndefinedSymbol,
    /// `(+ 1)`
    UnsupportedOperation,
}

/// A value
pub enum Value {
    /// Integer: `123`
    Integer(u64),
    /// `()`
    Nil,
    /// String: `123`
    String(String),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Integer(int) => int.fmt(f),
            Value::Nil => f.write_str("nil"),
            Value::String(ref s) => write!(f, "\"{}\"", s),
        }
    }
}

/// Evaluates an expression
pub fn expr(e: &Expr, env: &Env) -> Result<Value, Error> {
    match *e {
        Expr::Integer(int) => Ok(Value::Integer(int)),
        Expr::List(ref list) => match &**list {
            [] => Err(Error::EmptyList),
            [ref sym, exprs..] => match *sym {
                Expr::Symbol(ref sym) => match env.get(sym) {
                    None => Err(Error::UndefinedSymbol),
                    Some(f) => {
                        let mut args = Vec::with_capacity(exprs.len());

                        for expr in exprs {
                            args.push(try!(::eval::expr(expr, env)));
                        }

                        f(&args)
                    },
                },
                ref e => Err(Error::ExpectedSymbolGot(e.clone())),
            },
        },
        Expr::Nil => Ok(Value::Nil),
        Expr::String(ref s) => Ok(Value::String(s.clone())),
        // XXX What to do here? Is a symbol a value? Print it as e.g. "function `+`"?
        Expr::Symbol(_) => unimplemented!(),
    }
}
<commit_msg>feat: include symbol name in `UndefinedSymbol` error<commit_after>//! Evaluation of expressions

use std::fmt;

use ast::Expr;
use env::Env;

/// Evaluation errors
#[derive(Debug)]
pub enum Error {
    /// `()`
    EmptyList,
    /// `("abc" 1 2)`
    ExpectedSymbolGot(Expr),
    /// Symbol not yet defined
    UndefinedSymbol(String),
    /// `(+ 1)`
    UnsupportedOperation,
}

/// A value
pub enum Value {
    /// Integer: `123`
    Integer(u64),
    /// `()`
    Nil,
    /// String: `123`
    String(String),
}

impl fmt::Display for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Value::Integer(int) => int.fmt(f),
            Value::Nil => f.write_str("nil"),
            Value::String(ref s) => write!(f, "\"{}\"", s),
        }
    }
}

/// Evaluates an expression
pub fn expr(e: &Expr, env: &Env) -> Result<Value, Error> {
    match *e {
        Expr::Integer(int) => Ok(Value::Integer(int)),
        Expr::List(ref list) => match &**list {
            [] => Err(Error::EmptyList),
            [ref sym, exprs..] => match *sym {
                Expr::Symbol(ref sym) => match env.get(sym) {
                    None => Err(Error::UndefinedSymbol(sym.clone())),
                    Some(f) => {
                        let mut args = Vec::with_capacity(exprs.len());

                        for expr in exprs {
                            args.push(try!(::eval::expr(expr, env)));
                        }

                        f(&args)
                    },
                },
                ref e => Err(Error::ExpectedSymbolGot(e.clone())),
            },
        },
        Expr::Nil => Ok(Value::Nil),
        Expr::String(ref s) => Ok(Value::String(s.clone())),
        // XXX What to do here? Is a symbol a value? Print it as e.g. "function `+`"?
        Expr::Symbol(_) => unimplemented!(),
    }
}
<|endoftext|>