<commit_before>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use rusqlite::{Row,Connection};

use content::Content;
use fromdb::FromDb;
use lrobject::LrObject;

pub struct Folder {
    id: i64,
    uuid: String,
    pub path_from_root: String,
    pub root_folder: i64,
    pub content: Option<Content>,
}

impl LrObject for Folder {
    fn id(&self) -> i64 {
        self.id
    }
    fn uuid(&self) -> &str {
        &self.uuid
    }
}

impl FromDb for Folder {
    fn read_from(row: &Row) -> Option<Self> {
        Some(Folder {
            id: row.get(0),
            uuid: row.get(1),
            path_from_root: row.get(2),
            root_folder: row.get(3),
            content: None,
        })
    }
    fn read_db_tables() -> &'static str {
        "AgLibraryFolder"
    }
    fn read_db_columns() -> &'static str {
        "id_local,id_global,pathFromRoot,rootFolder"
    }
}

impl Folder {
    pub fn read_content(&self, conn: &Connection) -> Content {
        Content::from_db(conn, "AgFolderContent", "containingFolder", self.id)
    }
}

pub struct RootFolder {
    id: i64,
    uuid: String,
    pub absolute_path: String,
    pub name: String,
    pub relative_path_from_catalog: Option<String>,
}

impl LrObject for RootFolder {
    fn id(&self) -> i64 {
        self.id
    }
    fn uuid(&self) -> &str {
        &self.uuid
    }
}

impl FromDb for RootFolder {
    fn read_from(row: &Row) -> Option<Self> {
        Some(RootFolder {
            id: row.get(0),
            uuid: row.get(1),
            absolute_path: row.get(2),
            name: row.get(3),
            relative_path_from_catalog: row.get_checked(4).ok(),
        })
    }

    fn read_db_tables() -> &'static str {
        "AgLibraryRootFolder"
    }

    fn read_db_columns() -> &'static str {
        "id_local,id_global,absolutePath,name,relativePathFromCatalog"
    }

}

pub struct Folders {
    pub roots: Vec<RootFolder>,
    pub folders: Vec<Folder>,
}

impl Folders {

    pub fn new() -> Folders {
        Folders { roots: vec!(),
                  folders: vec!() }
    }

    pub fn is_empty(&self) -> bool {
        self.roots.is_empty() && self.folders.is_empty()
    }

    pub fn add_folder(&mut self, folder: Folder) {
        self.folders.push(folder);
    }

    pub fn add_root_folder(&mut self, root_folder: RootFolder) {
        self.roots.push(root_folder);
    }

    pub fn append_folders(&mut self, mut folders: Vec<Folder>) {
        self.folders.append(&mut folders);
    }

    pub fn append_root_folders(&mut self, mut root_folders: Vec<RootFolder>) {
        self.roots.append(&mut root_folders);
    }

}
<commit_msg>folder: resolve path<commit_after>/*
  This Source Code Form is subject to the terms of the Mozilla Public
  License, v. 2.0. If a copy of the MPL was not distributed with this
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

use rusqlite::{Row,Connection};

use content::Content;
use fromdb::FromDb;
use lrobject::LrObject;

pub struct Folder {
    id: i64,
    uuid: String,
    pub path_from_root: String,
    pub root_folder: i64,
    pub content: Option<Content>,
}

impl LrObject for Folder {
    fn id(&self) -> i64 {
        self.id
    }
    fn uuid(&self) -> &str {
        &self.uuid
    }
}

impl FromDb for Folder {
    fn read_from(row: &Row) -> Option<Self> {
        Some(Folder {
            id: row.get(0),
            uuid: row.get(1),
            path_from_root: row.get(2),
            root_folder: row.get(3),
            content: None,
        })
    }
    fn read_db_tables() -> &'static str {
        "AgLibraryFolder"
    }
    fn read_db_columns() -> &'static str {
        "id_local,id_global,pathFromRoot,rootFolder"
    }
}

impl Folder {
    pub fn new(id: i64, uuid: &str) -> Folder {
        Folder { id, uuid: String::from(uuid), path_from_root: String::from(""),
                 root_folder: 0, content: None }
    }
    pub fn read_content(&self, conn: &Connection) -> Content {
        Content::from_db(conn, "AgFolderContent", "containingFolder", self.id)
    }
}

pub struct RootFolder {
    id: i64,
    uuid: String,
    pub absolute_path: String,
    pub name: String,
    pub relative_path_from_catalog: Option<String>,
}

impl LrObject for RootFolder {
    fn id(&self) -> i64 {
        self.id
    }
    fn uuid(&self) -> &str {
        &self.uuid
    }
}

impl RootFolder {
    pub fn new(id: i64, uuid: &str) -> RootFolder {
        RootFolder { id, uuid: String::from(uuid),
                     absolute_path: String::from(""),
                     name: String::from(""), relative_path_from_catalog: None }
    }
}

impl FromDb for RootFolder {
    fn read_from(row: &Row) -> Option<Self> {
        Some(RootFolder {
            id: row.get(0),
            uuid: row.get(1),
            absolute_path: row.get(2),
            name: row.get(3),
            relative_path_from_catalog: row.get_checked(4).ok(),
        })
    }

    fn read_db_tables() -> &'static str {
        "AgLibraryRootFolder"
    }

    fn read_db_columns() -> &'static str {
        "id_local,id_global,absolutePath,name,relativePathFromCatalog"
    }

}

pub struct Folders {
    pub roots: Vec<RootFolder>,
    pub folders: Vec<Folder>,
}

impl Folders {

    pub fn new() -> Folders {
        Folders { roots: vec!(),
                  folders: vec!() }
    }

    pub fn is_empty(&self) -> bool {
        self.roots.is_empty() && self.folders.is_empty()
    }

    pub fn add_folder(&mut self, folder: Folder) {
        self.folders.push(folder);
    }

    pub fn add_root_folder(&mut self, root_folder: RootFolder) {
        self.roots.push(root_folder);
    }

    pub fn append_folders(&mut self, mut folders: Vec<Folder>) {
        self.folders.append(&mut folders);
    }

    pub fn append_root_folders(&mut self, mut root_folders: Vec<RootFolder>) {
        self.roots.append(&mut root_folders);
    }

    fn find_root_folder(&self, id: i64) -> Option<&RootFolder> {
        for root in &self.roots {
            if root.id() == id {
                return Some(root);
            }
        }
        None
    }

    pub fn resolve_folder_path(&self, folder: &Folder) -> Option<String> {
        if let Some(root_folder) = self.find_root_folder(folder.root_folder) {
            let mut root_path = root_folder.absolute_path.clone();
            root_path += &folder.path_from_root;
            return Some(root_path);
        }
        None
    }
}

#[cfg(test)]
#[test]
fn test_resolve_folder_path() {
    let mut folders = Folders::new();

    let mut rfolder = RootFolder::new(24, "toplevel");
    rfolder.absolute_path = String::from("/home/hub/Pictures");
    rfolder.name = String::from("Pictures");
    folders.add_root_folder(rfolder);

    let mut folder = Folder::new(42, "foobar");
    folder.root_folder = 24;
    folder.path_from_root = String::from("/2017/10");
    folders.add_folder(folder);

    let resolved = folders.resolve_folder_path(&folders.folders[0]);
    assert!(resolved.is_some());
    let resolved = resolved.unwrap();
    assert_eq!(resolved, "/home/hub/Pictures/2017/10");
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! View frustum for visibility determination

use Plane;
use bound::*;
use cgmath::{Matrix, Matrix4};
use cgmath::BaseFloat;
use cgmath::Point3;
use cgmath::{PerspectiveFov, Ortho, Perspective};

#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
pub struct Frustum<S: BaseFloat> {
    pub left:   Plane<S>,
    pub right:  Plane<S>,
    pub bottom: Plane<S>,
    pub top:    Plane<S>,
    pub near:   Plane<S>,
    pub far:    Plane<S>,
}

impl<S: BaseFloat + 'static> Frustum<S> {
    /// Construct a frustum.
    pub fn new(left:   Plane<S>, right:  Plane<S>,
               bottom: Plane<S>, top:    Plane<S>,
               near:   Plane<S>, far:    Plane<S>) -> Frustum<S> {
        Frustum {
            left:   left,
            right:  right,
            bottom: bottom,
            top:    top,
            near:   near,
            far:    far,
        }
    }

    /// Extract frustum planes from a projection matrix.
    pub fn from_matrix4(mat: Matrix4<S>) -> Option<Frustum<S>> {
        Some(Frustum::new(
            match Plane::from_vector4_alt(mat.row(3) + mat.row(0)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) - mat.row(0)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) + mat.row(1)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) - mat.row(1)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) + mat.row(2)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) - mat.row(2)).normalize()
                { Some(p) => p, None => return None }
        ))
    }

    /// Find the spatial relation of a bound inside this frustum.
    pub fn contains<B: Bound<S>+Copy>(&self, bound: B) -> Relation {
        [self.left, self.right, self.top, self.bottom, self.near, self.far]
            .iter().fold(Relation::In, |cur, p| {
            use std::cmp::max;
            let r = bound.relate_plane(*p);
            // If any of the planes are `Out`, the bound is outside.
            // Otherwise, if any are `Cross`, the bound is crossing.
            // Otherwise, the bound is fully inside.
            max(cur, r)
        })
    }
}

#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
pub struct FrustumPoints<S> {
    pub near_top_left:     Point3<S>,
    pub near_top_right:    Point3<S>,
    pub near_bottom_left:  Point3<S>,
    pub near_bottom_right: Point3<S>,
    pub far_top_left:      Point3<S>,
    pub far_top_right:     Point3<S>,
    pub far_bottom_left:   Point3<S>,
    pub far_bottom_right:  Point3<S>,
}

pub trait Projection<S: BaseFloat>: Into<Matrix4<S>> {
    fn to_frustum(&self) -> Frustum<S>;
}

impl<S: BaseFloat + 'static> Projection<S> for PerspectiveFov<S> {
    fn to_frustum(&self) -> Frustum<S> {
        // TODO: Could this be faster?
        Frustum::from_matrix4(self.clone().into()).unwrap()
    }
}

impl<S: BaseFloat + 'static> Projection<S> for Perspective<S> {
    fn to_frustum(&self) -> Frustum<S> {
        // TODO: Could this be faster?
        Frustum::from_matrix4(self.clone().into()).unwrap()
    }
}

impl<S: BaseFloat> Projection<S> for Ortho<S> {
    fn to_frustum(&self) -> Frustum<S> {
        Frustum {
            left:   Plane::from_abcd(S::one(), S::zero(), S::zero(), self.left.clone()),
            right:  Plane::from_abcd(-S::one(), S::zero(), S::zero(), self.right.clone()),
            bottom: Plane::from_abcd(S::zero(), S::one(), S::zero(), self.bottom.clone()),
            top:    Plane::from_abcd(S::zero(), -S::one(), S::zero(), self.top.clone()),
            near:   Plane::from_abcd(S::zero(), S::zero(), -S::one(), self.near.clone()),
            far:    Plane::from_abcd(S::zero(), S::zero(), S::one(), self.far.clone()),
        }
    }
}
<commit_msg>Remove: unneeded clone()<commit_after>// Copyright 2013-2014 The CGMath Developers. For a full listing of the authors,
// refer to the Cargo.toml file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! View frustum for visibility determination

use Plane;
use bound::*;
use cgmath::{Matrix, Matrix4};
use cgmath::BaseFloat;
use cgmath::Point3;
use cgmath::{PerspectiveFov, Ortho, Perspective};

#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
pub struct Frustum<S: BaseFloat> {
    pub left:   Plane<S>,
    pub right:  Plane<S>,
    pub bottom: Plane<S>,
    pub top:    Plane<S>,
    pub near:   Plane<S>,
    pub far:    Plane<S>,
}

impl<S: BaseFloat + 'static> Frustum<S> {
    /// Construct a frustum.
    pub fn new(left:   Plane<S>, right:  Plane<S>,
               bottom: Plane<S>, top:    Plane<S>,
               near:   Plane<S>, far:    Plane<S>) -> Frustum<S> {
        Frustum {
            left:   left,
            right:  right,
            bottom: bottom,
            top:    top,
            near:   near,
            far:    far,
        }
    }

    /// Extract frustum planes from a projection matrix.
    pub fn from_matrix4(mat: Matrix4<S>) -> Option<Frustum<S>> {
        Some(Frustum::new(
            match Plane::from_vector4_alt(mat.row(3) + mat.row(0)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) - mat.row(0)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) + mat.row(1)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) - mat.row(1)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) + mat.row(2)).normalize()
                { Some(p) => p, None => return None },
            match Plane::from_vector4_alt(mat.row(3) - mat.row(2)).normalize()
                { Some(p) => p, None => return None }
        ))
    }

    /// Find the spatial relation of a bound inside this frustum.
    pub fn contains<B: Bound<S>+Copy>(&self, bound: B) -> Relation {
        [self.left, self.right, self.top, self.bottom, self.near, self.far]
            .iter().fold(Relation::In, |cur, p| {
            use std::cmp::max;
            let r = bound.relate_plane(*p);
            // If any of the planes are `Out`, the bound is outside.
            // Otherwise, if any are `Cross`, the bound is crossing.
            // Otherwise, the bound is fully inside.
            max(cur, r)
        })
    }
}

#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(feature = "rustc-serialize", derive(RustcEncodable, RustcDecodable))]
pub struct FrustumPoints<S> {
    pub near_top_left:     Point3<S>,
    pub near_top_right:    Point3<S>,
    pub near_bottom_left:  Point3<S>,
    pub near_bottom_right: Point3<S>,
    pub far_top_left:      Point3<S>,
    pub far_top_right:     Point3<S>,
    pub far_bottom_left:   Point3<S>,
    pub far_bottom_right:  Point3<S>,
}

pub trait Projection<S: BaseFloat>: Into<Matrix4<S>> {
    fn to_frustum(&self) -> Frustum<S>;
}

impl<S: BaseFloat + 'static> Projection<S> for PerspectiveFov<S> {
    fn to_frustum(&self) -> Frustum<S> {
        // TODO: Could this be faster?
        Frustum::from_matrix4(self.clone().into()).unwrap()
    }
}

impl<S: BaseFloat + 'static> Projection<S> for Perspective<S> {
    fn to_frustum(&self) -> Frustum<S> {
        // TODO: Could this be faster?
        Frustum::from_matrix4(self.clone().into()).unwrap()
    }
}

impl<S: BaseFloat> Projection<S> for Ortho<S> {
    fn to_frustum(&self) -> Frustum<S> {
        Frustum {
            left:   Plane::from_abcd(S::one(), S::zero(), S::zero(), self.left),
            right:  Plane::from_abcd(-S::one(), S::zero(), S::zero(), self.right),
            bottom: Plane::from_abcd(S::zero(), S::one(), S::zero(), self.bottom),
            top:    Plane::from_abcd(S::zero(), -S::one(), S::zero(), self.top),
            near:   Plane::from_abcd(S::zero(), S::zero(), -S::one(), self.near),
            far:    Plane::from_abcd(S::zero(), S::zero(), S::one(), self.far),
        }
    }
}
<|endoftext|>


<commit_before>use crate::error::{ParseError, ParseErrorKind, ParseErrorKind::*};
use std::fmt;
use std::iter;
use std::str::{self, FromStr};

/// A cfg expression.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum CfgExpr {
    Not(Box<CfgExpr>),
    All(Vec<CfgExpr>),
    Any(Vec<CfgExpr>),
    Value(Cfg),
}

/// A cfg value.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum Cfg {
    /// A named cfg value, like `unix`.
    Name(String),
    /// A key/value cfg pair, like `target_os = "linux"`.
    KeyPair(String, String),
}

#[derive(PartialEq)]
enum Token<'a> {
    LeftParen,
    RightParen,
    Ident(&'a str),
    Comma,
    Equals,
    String(&'a str),
}

#[derive(Clone)]
struct Tokenizer<'a> {
    s: iter::Peekable<str::CharIndices<'a>>,
    orig: &'a str,
}

struct Parser<'a> {
    t: Tokenizer<'a>,
}

impl Cfg {
    pub(crate) fn validate_as_target(&self) -> Result<(), ParseErrorKind> {
        match self {
            Cfg::Name(name) => match name.as_str() {
                "unix" | "windows" => Ok(()),
                _ => Err(InvalidCfgName(name.to_string())),
            },
            Cfg::KeyPair(name, _) => match name.as_str() {
                "target_arch"
                | "target_feature"
                | "target_os"
                | "target_family"
                | "target_env"
                | "target_endian"
                | "target_pointer_width"
                | "target_vendor" => Ok(()),
                _ => Err(InvalidCfgKey(name.to_string())),
            },
        }
    }
}

impl FromStr for Cfg {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Cfg, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.cfg()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for Cfg {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Cfg::Name(ref s) => s.fmt(f),
            Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v),
        }
    }
}

impl CfgExpr {
    /// Utility function to check if the key, "cfg(..)" matches the `target_cfg`
    pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool {
        if key.starts_with("cfg(") && key.ends_with(')') {
            let cfg = &key[4..key.len() - 1];

            CfgExpr::from_str(cfg)
                .ok()
                .map(|ce| ce.matches(target_cfg))
                .unwrap_or(false)
        } else {
            false
        }
    }

    pub fn matches(&self, cfg: &[Cfg]) -> bool {
        match *self {
            CfgExpr::Not(ref e) => !e.matches(cfg),
            CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),
            CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),
            CfgExpr::Value(ref e) => cfg.contains(e),
        }
    }

    pub(crate) fn validate_as_target(&self) -> Result<(), ParseErrorKind> {
        match *self {
            CfgExpr::Not(ref e) => e.validate_as_target()?,
            CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {
                for e in e {
                    e.validate_as_target()?;
                }
            }
            CfgExpr::Value(ref e) => e.validate_as_target()?,
        }
        Ok(())
    }
}

impl FromStr for CfgExpr {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<CfgExpr, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.expr()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for CfgExpr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            CfgExpr::Not(ref e) => write!(f, "not({})", e),
            CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)),
            CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)),
            CfgExpr::Value(ref e) => write!(f, "{}", e),
        }
    }
}

struct CommaSep<'a, T>(&'a [T]);

impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for (i, v) in self.0.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }
            write!(f, "{}", v)?;
        }
        Ok(())
    }
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            t: Tokenizer {
                s: s.char_indices().peekable(),
                orig: s,
            },
        }
    }

    fn expr(&mut self) -> Result<CfgExpr, ParseError> {
        match self.peek() {
            Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => {
                self.t.next();
                let mut e = Vec::new();
                self.eat(&Token::LeftParen)?;
                while !self.r#try(&Token::RightParen) {
                    e.push(self.expr()?);
                    if !self.r#try(&Token::Comma) {
                        self.eat(&Token::RightParen)?;
                        break;
                    }
                }
                if op == "all" {
                    Ok(CfgExpr::All(e))
                } else {
                    Ok(CfgExpr::Any(e))
                }
            }
            Some(Ok(Token::Ident("not"))) => {
                self.t.next();
                self.eat(&Token::LeftParen)?;
                let e = self.expr()?;
                self.eat(&Token::RightParen)?;
                Ok(CfgExpr::Not(Box::new(e)))
            }
            Some(Ok(..)) => self.cfg().map(CfgExpr::Value),
            Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr("start of a cfg expression"),
            )),
        }
    }

    fn cfg(&mut self) -> Result<Cfg, ParseError> {
        match self.t.next() {
            Some(Ok(Token::Ident(name))) => {
                let e = if self.r#try(&Token::Equals) {
                    let val = match self.t.next() {
                        Some(Ok(Token::String(s))) => s,
                        Some(Ok(t)) => {
                            return Err(ParseError::new(
                                self.t.orig,
                                UnexpectedToken {
                                    expected: "a string",
                                    found: t.classify(),
                                },
                            ))
                        }
                        Some(Err(e)) => return Err(e),
                        None => {
                            return Err(ParseError::new(self.t.orig, IncompleteExpr("a string")))
                        }
                    };
                    Cfg::KeyPair(name.to_string(), val.to_string())
                } else {
                    Cfg::Name(name.to_string())
                };
                Ok(e)
            }
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: "identifier",
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))),
        }
    }

    fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        self.t.clone().next()
    }

    fn r#try(&mut self, token: &Token<'a>) -> bool {
        match self.peek() {
            Some(Ok(ref t)) if token == t => {}
            _ => return false,
        }
        self.t.next();
        true
    }

    fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> {
        match self.t.next() {
            Some(Ok(ref t)) if token == t => Ok(()),
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: token.classify(),
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr(token.classify()),
            )),
        }
    }

    /// Returns the rest of the input from the current location.
    fn rest(&self) -> Option<&str> {
        let mut s = self.t.s.clone();
        loop {
            match s.next() {
                Some((_, ' ')) => {}
                Some((start, _ch)) => return Some(&self.t.orig[start..]),
                None => return None,
            }
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Result<Token<'a>, ParseError>;

    fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        loop {
            match self.s.next() {
                Some((_, ' ')) => {}
                Some((_, '(')) => return Some(Ok(Token::LeftParen)),
                Some((_, ')')) => return Some(Ok(Token::RightParen)),
                Some((_, ',')) => return Some(Ok(Token::Comma)),
                Some((_, '=')) => return Some(Ok(Token::Equals)),
                Some((start, '"')) => {
                    while let Some((end, ch)) = self.s.next() {
                        if ch == '"' {
                            return Some(Ok(Token::String(&self.orig[start + 1..end])));
                        }
                    }
                    return Some(Err(ParseError::new(self.orig, UnterminatedString)));
                }
                Some((start, ch)) if is_ident_start(ch) => {
                    while let Some(&(end, ch)) = self.s.peek() {
                        if !is_ident_rest(ch) {
                            return Some(Ok(Token::Ident(&self.orig[start..end])));
                        } else {
                            self.s.next();
                        }
                    }
                    return Some(Ok(Token::Ident(&self.orig[start..])));
                }
                Some((_, ch)) => {
                    return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch))));
                }
                None => return None,
            }
        }
    }
}

fn is_ident_start(ch: char) -> bool {
    ch == '_' || ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')
}

fn is_ident_rest(ch: char) -> bool {
    is_ident_start(ch) || ('0' <= ch && ch <= '9')
}

impl<'a> Token<'a> {
    fn classify(&self) -> &'static str {
        match *self {
            Token::LeftParen => "`(`",
            Token::RightParen => "`)`",
            Token::Ident(..) => "an identifier",
            Token::Comma => "`,`",
            Token::Equals => "`=`",
            Token::String(..) => "a string",
        }
    }
}

#[test]
fn cfg_validate_as_target() {
    fn p(s: &str) -> CfgExpr {
        s.parse().unwrap()
    }

    assert!(p("unix").validate_as_target().is_ok());
    assert!(p("windows").validate_as_target().is_ok());
    assert!(p("any(not(unix), windows)").validate_as_target().is_ok());

    assert!(p("target_arch = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_feature = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_os = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_family = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_env = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_endian = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_pointer_width = \"abc\"")
        .validate_as_target()
        .is_ok());
    assert!(p("target_vendor = \"abc\"").validate_as_target().is_ok());

    assert!(p("debug_assertions").validate_as_target().is_err());
    assert!(p("foo").validate_as_target().is_err());
    assert!(p("any(not(debug_assertions), windows)")
        .validate_as_target()
        .is_err());

    assert!(p("feature = \"abc\"").validate_as_target().is_err());
    assert!(p("bar = \"def\"").validate_as_target().is_err());
    assert!(p("any(not(feature = \"def\"))")
        .validate_as_target()
        .is_err());
}
<commit_msg>Use blacklist instead of whitelist<commit_after>use crate::error::{ParseError, ParseErrorKind, ParseErrorKind::*};
use std::fmt;
use std::iter;
use std::str::{self, FromStr};

/// A cfg expression.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum CfgExpr {
    Not(Box<CfgExpr>),
    All(Vec<CfgExpr>),
    Any(Vec<CfgExpr>),
    Value(Cfg),
}

/// A cfg value.
#[derive(Eq, PartialEq, Hash, Ord, PartialOrd, Clone, Debug)]
pub enum Cfg {
    /// A named cfg value, like `unix`.
    Name(String),
    /// A key/value cfg pair, like `target_os = "linux"`.
    KeyPair(String, String),
}

#[derive(PartialEq)]
enum Token<'a> {
    LeftParen,
    RightParen,
    Ident(&'a str),
    Comma,
    Equals,
    String(&'a str),
}

#[derive(Clone)]
struct Tokenizer<'a> {
    s: iter::Peekable<str::CharIndices<'a>>,
    orig: &'a str,
}

struct Parser<'a> {
    t: Tokenizer<'a>,
}

impl Cfg {
    pub(crate) fn validate_as_target(&self) -> Result<(), ParseErrorKind> {
        match self {
            Cfg::Name(name) => match name.as_str() {
                "test" | "debug_assertions" | "proc_macro" => Err(InvalidCfgName(name.to_string())),
                _ => Ok(()),
            },
            Cfg::KeyPair(name, _) => match name.as_str() {
                "feature" => Err(InvalidCfgKey(name.to_string())),
                _ => Ok(()),
            },
        }
    }
}

impl FromStr for Cfg {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Cfg, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.cfg()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for Cfg {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Cfg::Name(ref s) => s.fmt(f),
            Cfg::KeyPair(ref k, ref v) => write!(f, "{} = \"{}\"", k, v),
        }
    }
}

impl CfgExpr {
    /// Utility function to check if the key, "cfg(..)" matches the `target_cfg`
    pub fn matches_key(key: &str, target_cfg: &[Cfg]) -> bool {
        if key.starts_with("cfg(") && key.ends_with(')') {
            let cfg = &key[4..key.len() - 1];

            CfgExpr::from_str(cfg)
                .ok()
                .map(|ce| ce.matches(target_cfg))
                .unwrap_or(false)
        } else {
            false
        }
    }

    pub fn matches(&self, cfg: &[Cfg]) -> bool {
        match *self {
            CfgExpr::Not(ref e) => !e.matches(cfg),
            CfgExpr::All(ref e) => e.iter().all(|e| e.matches(cfg)),
            CfgExpr::Any(ref e) => e.iter().any(|e| e.matches(cfg)),
            CfgExpr::Value(ref e) => cfg.contains(e),
        }
    }

    pub(crate) fn validate_as_target(&self) -> Result<(), ParseErrorKind> {
        match *self {
            CfgExpr::Not(ref e) => e.validate_as_target()?,
            CfgExpr::All(ref e) | CfgExpr::Any(ref e) => {
                for e in e {
                    e.validate_as_target()?;
                }
            }
            CfgExpr::Value(ref e) => e.validate_as_target()?,
        }
        Ok(())
    }
}

impl FromStr for CfgExpr {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<CfgExpr, Self::Err> {
        let mut p = Parser::new(s);
        let e = p.expr()?;
        if let Some(rest) = p.rest() {
            return Err(ParseError::new(
                p.t.orig,
                UnterminatedExpression(rest.to_string()),
            ));
        }
        Ok(e)
    }
}

impl fmt::Display for CfgExpr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            CfgExpr::Not(ref e) => write!(f, "not({})", e),
            CfgExpr::All(ref e) => write!(f, "all({})", CommaSep(e)),
            CfgExpr::Any(ref e) => write!(f, "any({})", CommaSep(e)),
            CfgExpr::Value(ref e) => write!(f, "{}", e),
        }
    }
}

struct CommaSep<'a, T>(&'a [T]);

impl<'a, T: fmt::Display> fmt::Display for CommaSep<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for (i, v) in self.0.iter().enumerate() {
            if i > 0 {
                write!(f, ", ")?;
            }
            write!(f, "{}", v)?;
        }
        Ok(())
    }
}

impl<'a> Parser<'a> {
    fn new(s: &'a str) -> Parser<'a> {
        Parser {
            t: Tokenizer {
                s: s.char_indices().peekable(),
                orig: s,
            },
        }
    }

    fn expr(&mut self) -> Result<CfgExpr, ParseError> {
        match self.peek() {
            Some(Ok(Token::Ident(op @ "all"))) | Some(Ok(Token::Ident(op @ "any"))) => {
                self.t.next();
                let mut e = Vec::new();
                self.eat(&Token::LeftParen)?;
                while !self.r#try(&Token::RightParen) {
                    e.push(self.expr()?);
                    if !self.r#try(&Token::Comma) {
                        self.eat(&Token::RightParen)?;
                        break;
                    }
                }
                if op == "all" {
                    Ok(CfgExpr::All(e))
                } else {
                    Ok(CfgExpr::Any(e))
                }
            }
            Some(Ok(Token::Ident("not"))) => {
                self.t.next();
                self.eat(&Token::LeftParen)?;
                let e = self.expr()?;
                self.eat(&Token::RightParen)?;
                Ok(CfgExpr::Not(Box::new(e)))
            }
            Some(Ok(..)) => self.cfg().map(CfgExpr::Value),
            Some(Err(..)) => Err(self.t.next().unwrap().err().unwrap()),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr("start of a cfg expression"),
            )),
        }
    }

    fn cfg(&mut self) -> Result<Cfg, ParseError> {
        match self.t.next() {
            Some(Ok(Token::Ident(name))) => {
                let e = if self.r#try(&Token::Equals) {
                    let val = match self.t.next() {
                        Some(Ok(Token::String(s))) => s,
                        Some(Ok(t)) => {
                            return Err(ParseError::new(
                                self.t.orig,
                                UnexpectedToken {
                                    expected: "a string",
                                    found: t.classify(),
                                },
                            ))
                        }
                        Some(Err(e)) => return Err(e),
                        None => {
                            return Err(ParseError::new(self.t.orig, IncompleteExpr("a string")))
                        }
                    };
                    Cfg::KeyPair(name.to_string(), val.to_string())
                } else {
                    Cfg::Name(name.to_string())
                };
                Ok(e)
            }
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: "identifier",
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(self.t.orig, IncompleteExpr("identifier"))),
        }
    }

    fn peek(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        self.t.clone().next()
    }

    fn r#try(&mut self, token: &Token<'a>) -> bool {
        match self.peek() {
            Some(Ok(ref t)) if token == t => {}
            _ => return false,
        }
        self.t.next();
        true
    }

    fn eat(&mut self, token: &Token<'a>) -> Result<(), ParseError> {
        match self.t.next() {
            Some(Ok(ref t)) if token == t => Ok(()),
            Some(Ok(t)) => Err(ParseError::new(
                self.t.orig,
                UnexpectedToken {
                    expected: token.classify(),
                    found: t.classify(),
                },
            )),
            Some(Err(e)) => Err(e),
            None => Err(ParseError::new(
                self.t.orig,
                IncompleteExpr(token.classify()),
            )),
        }
    }

    /// Returns the rest of the input from the current location.
    fn rest(&self) -> Option<&str> {
        let mut s = self.t.s.clone();
        loop {
            match s.next() {
                Some((_, ' ')) => {}
                Some((start, _ch)) => return Some(&self.t.orig[start..]),
                None => return None,
            }
        }
    }
}

impl<'a> Iterator for Tokenizer<'a> {
    type Item = Result<Token<'a>, ParseError>;

    fn next(&mut self) -> Option<Result<Token<'a>, ParseError>> {
        loop {
            match self.s.next() {
                Some((_, ' ')) => {}
                Some((_, '(')) => return Some(Ok(Token::LeftParen)),
                Some((_, ')')) => return Some(Ok(Token::RightParen)),
                Some((_, ',')) => return Some(Ok(Token::Comma)),
                Some((_, '=')) => return Some(Ok(Token::Equals)),
                Some((start, '"')) => {
                    while let Some((end, ch)) = self.s.next() {
                        if ch == '"' {
                            return Some(Ok(Token::String(&self.orig[start + 1..end])));
                        }
                    }
                    return Some(Err(ParseError::new(self.orig, UnterminatedString)));
                }
                Some((start, ch)) if is_ident_start(ch) => {
                    while let Some(&(end, ch)) = self.s.peek() {
                        if !is_ident_rest(ch) {
                            return Some(Ok(Token::Ident(&self.orig[start..end])));
                        } else {
                            self.s.next();
                        }
                    }
                    return Some(Ok(Token::Ident(&self.orig[start..])));
                }
                Some((_, ch)) => {
                    return Some(Err(ParseError::new(self.orig, UnexpectedChar(ch))));
                }
                None => return None,
            }
        }
    }
}

fn is_ident_start(ch: char) -> bool {
    ch == '_' || ('a' <= ch && ch <= 'z') || ('A' <= ch && ch <= 'Z')
}

fn is_ident_rest(ch: char) -> bool {
    is_ident_start(ch) || ('0' <= ch && ch <= '9')
}

impl<'a> Token<'a> {
    fn classify(&self) -> &'static str {
        match *self {
            Token::LeftParen => "`(`",
            Token::RightParen => "`)`",
            Token::Ident(..) => "an identifier",
            Token::Comma => "`,`",
            Token::Equals => "`=`",
            Token::String(..) => "a string",
        }
    }
}

#[test]
fn cfg_validate_as_target() {
    fn p(s: &str) -> CfgExpr {
        s.parse().unwrap()
    }

    assert!(p("unix").validate_as_target().is_ok());
    assert!(p("windows").validate_as_target().is_ok());
    assert!(p("any(not(unix), windows)").validate_as_target().is_ok());
    assert!(p("foo").validate_as_target().is_ok());

    assert!(p("target_arch = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_feature = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_os = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_family = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_env = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_endian = \"abc\"").validate_as_target().is_ok());
    assert!(p("target_pointer_width = \"abc\"")
        .validate_as_target()
        .is_ok());
    assert!(p("target_vendor = \"abc\"").validate_as_target().is_ok());
    assert!(p("bar = \"def\"").validate_as_target().is_ok());

    assert!(p("test").validate_as_target().is_err());
    assert!(p("debug_assertions").validate_as_target().is_err());
    assert!(p("proc_macro").validate_as_target().is_err());
    assert!(p("any(not(debug_assertions), windows)")
        .validate_as_target()
        .is_err());

    assert!(p("feature = \"abc\"").validate_as_target().is_err());
    assert!(p("any(not(feature = \"def\"), target_arch = \"abc\")")
        .validate_as_target()
        .is_err());
}
<|endoftext|>


<commit_before>use {Action, InputTranslator, InputRebind, MouseTranslationData, to_act_bt_hashmap};
use input::Button;
use window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap.
pub struct RebindBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> RebindBuilder<A> {
    /// Creates a new `RebindBuilder` with the specified viewport size.
    pub fn new<S: Into<Size> + Sized>(size: S) -> Self {
        RebindBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new(size)
        }
    }

    /// Set whether the x scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    /// Returns true if the x scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    /// Set whether the y scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    /// Returns true if the y scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    /// Set whether the x axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    /// Returns true if the x axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    /// Set whether the y axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    /// Returns true if the y axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    /// Set the mouse sensitivity
    pub fn mouse_sensitivity(mut self, sensitivity: f64) -> Self {
        self.mouse_data.sensitivity = sensitivity;
        self
    }

    /// Returns the mouse sensitivity
    pub fn get_mouse_sensitivity(&self) -> &f64 {
        &self.mouse_data.sensitivity
    }

    /// Sets the viewport size used for mouse position calculations.
    pub fn viewport_size(mut self, size: Size) -> Self {
        self.mouse_data.viewport_size = size;
        self
    }

    /// Returns the currently set viewport size.
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    /// Add an association between the Button and Action in the built object.
    pub fn with_action_mapping(mut self, button: Button, action: A) -> Self {
        self.input_remappings.push((button, action));
        self
    }

    /// Creates an `InputTranslator` from this builder object. Consumes self.
    pub fn build_translator(self) -> InputTranslator<A> { self.into() }

    /// Creates an `InputRebind` from this builder object. Consumes self.
    pub fn build_rebind(self) -> InputRebind<A> { self.into() }
}

/// Creates a new `RebindBuilder`. The viewport size is set to (800, 600).
impl<A: Action> Default for RebindBuilder<A> {
    fn default() -> Self {
        Self::new((800, 600))
    }
}

impl<A: Action> Into<InputTranslator<A>> for RebindBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data = self.mouse_data;
        input_map.keymap = self.input_remappings.iter().cloned().collect();

        input_map
    }
}

impl<A: Action> Into<InputRebind<A>> for RebindBuilder<A> {
    fn into(self) -> InputRebind<A> {
        let mut input_rebind = InputRebind::new(self.mouse_data.viewport_size);

        input_rebind.mouse_data = self.mouse_data;
        input_rebind.keymap = to_act_bt_hashmap(self.input_remappings.iter().cloned());

        input_rebind
    }
}<commit_msg>Remove unnecessary documentation<commit_after>use {Action, InputTranslator, InputRebind, MouseTranslationData, to_act_bt_hashmap};
use input::Button;
use window::Size;
use std::convert::Into;
use std::default::Default;

/// Convenience object for constructing an InputMap.
pub struct RebindBuilder<A: Action> {
    input_remappings: Vec<(Button, A)>,
    mouse_data: MouseTranslationData
}

impl<A: Action> RebindBuilder<A> {
    /// Creates a new `RebindBuilder` with the specified viewport size.
    pub fn new<S: Into<Size> + Sized>(size: S) -> Self {
        RebindBuilder {
            input_remappings: vec![],
            mouse_data: MouseTranslationData::new(size)
        }
    }

    /// Set whether the x scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn x_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_scroll_inverted = invert;
        self
    }

    /// Returns true if the x scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn get_x_scroll_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_scroll_inverted
    }

    /// Set whether the y scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn y_scroll_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_scroll_inverted = invert;
        self
    }

    /// Returns true if the y scroll is inverted on the builder (and thus
    /// on the built object).
    pub fn get_y_scroll_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_scroll_inverted
    }

    /// Set whether the x axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn x_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.x_axis_motion_inverted = invert;
        self
    }

    /// Returns true if the x axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn get_x_motion_inverted(&self) -> &bool {
        &self.mouse_data.x_axis_motion_inverted
    }

    /// Set whether the y axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn y_motion_inverted(mut self, invert: bool) -> Self {
        self.mouse_data.y_axis_motion_inverted = invert;
        self
    }

    /// Returns true if the y axis motion is inverted on the builder (and thus
    /// on the built object).
    pub fn get_y_motion_inverted(&self) -> &bool {
        &self.mouse_data.y_axis_motion_inverted
    }

    /// Set the mouse sensitivity
    pub fn mouse_sensitivity(mut self, sensitivity: f64) -> Self {
        self.mouse_data.sensitivity = sensitivity;
        self
    }

    /// Returns the mouse sensitivity
    pub fn get_mouse_sensitivity(&self) -> &f64 {
        &self.mouse_data.sensitivity
    }

    /// Sets the viewport size used for mouse position calculations.
    pub fn viewport_size(mut self, size: Size) -> Self {
        self.mouse_data.viewport_size = size;
        self
    }

    /// Returns the currently set viewport size.
    pub fn get_viewport_size(&self) -> &Size {
        &self.mouse_data.viewport_size
    }

    /// Add an association between the Button and Action in the built object.
    pub fn with_action_mapping(mut self, button: Button, action: A) -> Self {
        self.input_remappings.push((button, action));
        self
    }

    /// Creates an `InputTranslator` from this builder object.
    pub fn build_translator(self) -> InputTranslator<A> { self.into() }

    /// Creates an `InputRebind` from this builder object.
    pub fn build_rebind(self) -> InputRebind<A> { self.into() }
}

/// Creates a new `RebindBuilder`. The viewport size is set to (800, 600).
impl<A: Action> Default for RebindBuilder<A> {
    fn default() -> Self {
        Self::new((800, 600))
    }
}

impl<A: Action> Into<InputTranslator<A>> for RebindBuilder<A> {
    fn into(self) -> InputTranslator<A> {
        let mut input_map = InputTranslator::new(self.mouse_data.viewport_size);

        input_map.mouse_translator.data = self.mouse_data;
        input_map.keymap = self.input_remappings.iter().cloned().collect();

        input_map
    }
}

impl<A: Action> Into<InputRebind<A>> for RebindBuilder<A> {
    fn into(self) -> InputRebind<A> {
        let mut input_rebind = InputRebind::new(self.mouse_data.viewport_size);

        input_rebind.mouse_data = self.mouse_data;
        input_rebind.keymap = to_act_bt_hashmap(self.input_remappings.iter().cloned());

        input_rebind
    }
}<|endoftext|>


<commit_before>use std::collections::BTreeSet;
use cgmath::InnerSpace;
use event::{SiteEvent, CircleEvent};
use beach_line::{BeachLine, Arc};
use generator::Generator;
use ::Position;

#[derive(Default)]
struct Builder<G: Generator> {
    site_index: usize,
    site_events: Vec<SiteEvent>,
    circle_events: BTreeSet<CircleEvent>,
    beach: BeachLine,
    generator: G,
}

impl<G: Generator> Builder<G> {
    fn build<I: IntoIterator<Item = Position>>(mut self, positions: I) -> G::Result {
        self.site_events.extend(positions.into_iter().map(SiteEvent::from));
        self.site_events.sort();
        loop {
            let has_sites = self.site_index < self.site_events.len();
            if let Some(circle) = self.circle_events.iter().next().cloned() {
                if has_sites && self.site_events[self.site_index].theta.value < circle.theta {
                    self.site_event();
                } else {
                    self.circle_event(&circle);
                }
            } else if has_sites {
                self.site_event()
            } else {
                break;
            }
        }
        self.generator.result()
    }

    fn site_event(&mut self) {
        let cell = self.generator.cell();
        let theta = self.site_events[self.site_index].theta.value;
        self.site_index += 1;
        let arc = self.beach.insert(cell, &self.site_events);
        let (prev, next) = self.beach.neighbors(arc);
        self.generator.temporary(self.beach.index(arc), self.beach.index(prev));
        if prev != next {
            self.detach_circle(prev);
            self.detach_circle(next);
            self.attach_circle(prev, theta);
            self.attach_circle(next, theta);
        }
    }

    fn circle_event(&mut self, circle: &CircleEvent) {
        self.circle_events.remove(circle);
        let arc = circle.arc;
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            let (prev, next) = self.beach.neighbors(arc);
            self.beach.detach_circle(arc);
            self.detach_circle(prev);
            self.detach_circle(next);
            let vertex = self.generator.vertex(self.beach.circle_center(arc),
                                               self.beach.cell(prev),
                                               self.beach.cell(arc),
                                               self.beach.cell(next));
            self.generator.edge(self.beach.index(prev), vertex);
            self.generator.edge(self.beach.index(arc), vertex);
            self.beach.remove(arc);
            if self.beach.prev(prev) == next {
                self.generator.edge(self.beach.index(next), vertex);
                self.beach.remove(prev);
                self.beach.remove(next);
            } else {
                if self.attach_circle(prev, theta) {
                    self.generator.start(self.beach.index(prev), vertex);
                }
                self.attach_circle(next, theta);
            }
        }
    }

    fn attach_circle(&mut self, arc: Arc, min: f64) -> bool {
        let (prev, next) = self.beach.neighbors(arc);
        let position = self.arc_position(arc);
        let from_prev = self.arc_position(prev) - position;
        let from_next = self.arc_position(next) - position;
        let center = from_prev.cross(from_next).normalize();
        let theta = center.z.acos() + center.dot(position).acos();
        if theta >= min {
            self.beach.attach_circle(arc, theta, center);
            self.circle_events.insert(CircleEvent {
                theta: theta,
                arc: arc,
            });
            true
        } else {
            false
        }
    }

    fn detach_circle(&mut self, arc: Arc) {
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            self.circle_events.remove(&CircleEvent {
                arc: arc,
                theta: theta,
            });
            self.beach.detach_circle(arc);
        }
    }

    fn arc_position(&self, arc: Arc) -> Position {
        self.site_events[self.beach.cell(arc).index()].position
    }
}

pub fn build<G: Generator, I: IntoIterator<Item = Position>>(positions: I) -> G::Result {
    Builder::<G>::default().build(positions)
}
<commit_msg>Remove one if<commit_after>use std::collections::BTreeSet;
use cgmath::InnerSpace;
use event::{SiteEvent, CircleEvent};
use beach_line::{BeachLine, Arc};
use generator::Generator;
use ::Position;

#[derive(Default)]
struct Builder<G: Generator> {
    site_index: usize,
    site_events: Vec<SiteEvent>,
    circle_events: BTreeSet<CircleEvent>,
    beach: BeachLine,
    generator: G,
}

impl<G: Generator> Builder<G> {
    fn build<I: IntoIterator<Item = Position>>(mut self, positions: I) -> G::Result {
        self.site_events.extend(positions.into_iter().map(SiteEvent::from));
        self.site_events.sort();
        loop {
            let has_sites = self.site_index < self.site_events.len();
            if let Some(circle) = self.circle_events.iter().next().cloned() {
                if has_sites && self.site_events[self.site_index].theta.value < circle.theta {
                    self.site_event();
                } else {
                    self.circle_event(&circle);
                }
            } else if has_sites {
                self.site_event()
            } else {
                break;
            }
        }
        self.generator.result()
    }

    fn site_event(&mut self) {
        let cell = self.generator.cell();
        let theta = self.site_events[self.site_index].theta.value;
        self.site_index += 1;
        let arc = self.beach.insert(cell, &self.site_events);
        let (prev, next) = self.beach.neighbors(arc);
        self.generator.temporary(self.beach.index(arc), self.beach.index(prev));
        if prev != next {
            self.detach_circle(prev);
            self.detach_circle(next);
            self.attach_circle(prev, theta);
            self.attach_circle(next, theta);
        }
    }

    fn circle_event(&mut self, circle: &CircleEvent) {
        self.circle_events.remove(circle);
        let arc = circle.arc;
        let theta = circle.theta;
        let (prev, next) = self.beach.neighbors(arc);
        self.beach.detach_circle(arc);
        self.detach_circle(prev);
        self.detach_circle(next);
        let vertex = self.generator.vertex(self.beach.circle_center(arc),
                                            self.beach.cell(prev),
                                            self.beach.cell(arc),
                                            self.beach.cell(next));
        self.generator.edge(self.beach.index(prev), vertex);
        self.generator.edge(self.beach.index(arc), vertex);
        self.beach.remove(arc);
        if self.beach.prev(prev) == next {
            self.generator.edge(self.beach.index(next), vertex);
            self.beach.remove(prev);
            self.beach.remove(next);
        } else {
            if self.attach_circle(prev, theta) {
                self.generator.start(self.beach.index(prev), vertex);
            }
            self.attach_circle(next, theta);
        }
    }

    fn attach_circle(&mut self, arc: Arc, min: f64) -> bool {
        let (prev, next) = self.beach.neighbors(arc);
        let position = self.arc_position(arc);
        let from_prev = self.arc_position(prev) - position;
        let from_next = self.arc_position(next) - position;
        let center = from_prev.cross(from_next).normalize();
        let theta = center.z.acos() + center.dot(position).acos();
        if theta >= min {
            self.beach.attach_circle(arc, theta, center);
            self.circle_events.insert(CircleEvent {
                theta: theta,
                arc: arc,
            });
            true
        } else {
            false
        }
    }

    fn detach_circle(&mut self, arc: Arc) {
        let theta = self.beach.circle_theta(arc);
        if theta >= 0.0 {
            self.circle_events.remove(&CircleEvent {
                arc: arc,
                theta: theta,
            });
            self.beach.detach_circle(arc);
        }
    }

    fn arc_position(&self, arc: Arc) -> Position {
        self.site_events[self.beach.cell(arc).index()].position
    }
}

pub fn build<G: Generator, I: IntoIterator<Item = Position>>(positions: I) -> G::Result {
    Builder::<G>::default().build(positions)
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

pub use self::lua::lua_Alloc;
pub use self::lua::lua_CFunction;
pub use self::lua::lua_Ctx;
pub use self::lua::lua_Debug;
pub use self::lua::lua_Hook;
pub use self::lua::lua_Integer;
pub use self::lua::lua_KFunction;
pub use self::lua::lua_Number;
pub use self::lua::lua_Reader;
pub use self::lua::lua_State;
pub use self::lua::lua_Unsigned;
pub use self::lua::lua_Writer;

pub use self::lua::lua_absindex;
pub use self::lua::lua_arith;
pub use self::lua::lua_atpanic;
pub use self::lua::lua_call;
pub use self::lua::lua_callk;
pub use self::lua::lua_checkstack;
pub use self::lua::lua_close;
pub use self::lua::lua_compare;
pub use self::lua::lua_concat;
pub use self::lua::lua_copy;
pub use self::lua::lua_createtable;
pub use self::lua::lua_dump;
pub use self::lua::lua_error;
pub use self::lua::lua_gc;
pub use self::lua::lua_getallocf;
pub use self::lua::lua_getextraspace;
pub use self::lua::lua_getfield;
pub use self::lua::lua_getglobal;
pub use self::lua::lua_gethook;
pub use self::lua::lua_gethookcount;
pub use self::lua::lua_gethookmask;
pub use self::lua::lua_getinfo;
pub use self::lua::lua_getlocal;
pub use self::lua::lua_getmetatable;
pub use self::lua::lua_getstack;
pub use self::lua::lua_gettable;
pub use self::lua::lua_gettop;
pub use self::lua::lua_getupvalue;
pub use self::lua::lua_getuservalue;
pub use self::lua::lua_insert;
pub use self::lua::lua_isboolean;
pub use self::lua::lua_iscfunction;
pub use self::lua::lua_isfunction;
pub use self::lua::lua_isinteger;
pub use self::lua::lua_islightuserdata;
pub use self::lua::lua_isnil;
pub use self::lua::lua_isnone;
pub use self::lua::lua_isnoneornil;
pub use self::lua::lua_isnumber;
pub use self::lua::lua_isstring;
pub use self::lua::lua_istable;
pub use self::lua::lua_isthread;
pub use self::lua::lua_isuserdata;
pub use self::lua::lua_isyieldable;
pub use self::lua::lua_len;
pub use self::lua::lua_load;
pub use self::lua::lua_newstate;
pub use self::lua::lua_newtable;
pub use self::lua::lua_newthread;
pub use self::lua::lua_newuserdata;
pub use self::lua::lua_next;
pub use self::luaconf::lua_numtointeger;
pub use self::lua::lua_pcall;
pub use self::lua::lua_pcallk;
pub use self::lua::lua_pop;
pub use self::lua::lua_pushboolean;
pub use self::lua::lua_pushcclosure;
pub use self::lua::lua_pushcfunction;
pub use self::lua::lua_pushfstring;
pub use self::lua::lua_pushglobaltable;
pub use self::lua::lua_pushinteger;
pub use self::lua::lua_pushlightuserdata;
pub use self::lua::lua_pushliteral;
pub use self::lua::lua_pushlstring;
pub use self::lua::lua_pushnil;
pub use self::lua::lua_pushnumber;
pub use self::lua::lua_pushstring;
pub use self::lua::lua_pushthread;
pub use self::lua::lua_pushvalue;
//pub use self::lua::lua_pushvfstring; -- not implemented
pub use self::lua::lua_rawequal;
pub use self::lua::lua_rawget;
pub use self::lua::lua_rawgeti;
pub use self::lua::lua_rawgetp;
pub use self::lua::lua_rawlen;
pub use self::lua::lua_rawset;
pub use self::lua::lua_rawseti;
pub use self::lua::lua_rawsetp;
pub use self::lua::lua_register;
pub use self::lua::lua_remove;
pub use self::lua::lua_replace;
pub use self::lua::lua_resume;
pub use self::lua::lua_rotate;
pub use self::lua::lua_setallocf;
pub use self::lua::lua_setfield;
pub use self::lua::lua_setglobal;
pub use self::lua::lua_sethook;
pub use self::lua::lua_setlocal;
pub use self::lua::lua_setmetatable;
pub use self::lua::lua_settable;
pub use self::lua::lua_settop;
pub use self::lua::lua_setupvalue;
pub use self::lua::lua_setuservalue;
pub use self::lua::lua_status;
pub use self::lua::lua_strtonum;
pub use self::lua::lua_toboolean;
pub use self::lua::lua_tocfunction;
pub use self::lua::lua_tointeger;
pub use self::lua::lua_tointegerx;
pub use self::lua::lua_tolstring;
pub use self::lua::lua_tonumber;
pub use self::lua::lua_tonumberx;
pub use self::lua::lua_topointer;
pub use self::lua::lua_tostring;
pub use self::lua::lua_tothread;
pub use self::lua::lua_touserdata;
pub use self::lua::lua_type;
pub use self::lua::lua_typename;
pub use self::lua::lua_upvalueid;
pub use self::lua::lua_upvalueindex;
pub use self::lua::lua_upvaluejoin;
pub use self::lua::lua_version;
pub use self::lua::lua_xmove;
pub use self::lua::lua_yield;
pub use self::lua::lua_yieldk;

pub use self::lauxlib::luaL_Buffer;
pub use self::lauxlib::luaL_Reg;
pub use self::lauxlib::luaL_Stream;

pub use self::lauxlib::luaL_addchar;
pub use self::lauxlib::luaL_addlstring;
pub use self::lauxlib::luaL_addsize;
pub use self::lauxlib::luaL_addstring;
pub use self::lauxlib::luaL_addvalue;
pub use self::lauxlib::luaL_argcheck;
pub use self::lauxlib::luaL_argerror;
pub use self::lauxlib::luaL_buffinit;
pub use self::lauxlib::luaL_buffinitsize;
pub use self::lauxlib::luaL_callmeta;
pub use self::lauxlib::luaL_checkany;
pub use self::lauxlib::luaL_checkint;
pub use self::lauxlib::luaL_checkinteger;
pub use self::lauxlib::luaL_checklong;
pub use self::lauxlib::luaL_checklstring;
pub use self::lauxlib::luaL_checknumber;
pub use self::lauxlib::luaL_checkoption;
pub use self::lauxlib::luaL_checkstack;
pub use self::lauxlib::luaL_checkstring;
pub use self::lauxlib::luaL_checktype;
pub use self::lauxlib::luaL_checkudata;
pub use self::lauxlib::luaL_checkversion;
pub use self::lauxlib::luaL_dofile;
pub use self::lauxlib::luaL_dostring;
pub use self::lauxlib::luaL_error;
pub use self::lauxlib::luaL_execresult;
pub use self::lauxlib::luaL_fileresult;
pub use self::lauxlib::luaL_getmetafield;
pub use self::lauxlib::luaL_getmetatable;
pub use self::lauxlib::luaL_getsubtable;
pub use self::lauxlib::luaL_gsub;
pub use self::lauxlib::luaL_len;
pub use self::lauxlib::luaL_loadbuffer;
pub use self::lauxlib::luaL_loadbufferx;
pub use self::lauxlib::luaL_loadfile;
pub use self::lauxlib::luaL_loadfilex;
pub use self::lauxlib::luaL_loadstring;
pub use self::lauxlib::luaL_newlib;
pub use self::lauxlib::luaL_newlibtable;
pub use self::lauxlib::luaL_newmetatable;
pub use self::lauxlib::luaL_newstate;
pub use self::lualib::luaL_openlibs;
pub use self::lauxlib::luaL_optint;
pub use self::lauxlib::luaL_optinteger;
pub use self::lauxlib::luaL_optlong;
pub use self::lauxlib::luaL_optlstring;
pub use self::lauxlib::luaL_optnumber;
pub use self::lauxlib::luaL_optstring;
pub use self::lauxlib::luaL_prepbuffer;
pub use self::lauxlib::luaL_prepbuffsize;
pub use self::lauxlib::luaL_pushresult;
pub use self::lauxlib::luaL_pushresultsize;
pub use self::lauxlib::luaL_ref;
pub use self::lauxlib::luaL_requiref;
pub use self::lauxlib::luaL_setfuncs;
pub use self::lauxlib::luaL_setmetatable;
pub use self::lauxlib::luaL_testudata;
pub use self::lauxlib::luaL_tolstring;
pub use self::lauxlib::luaL_traceback;
pub use self::lauxlib::luaL_typename;
pub use self::lauxlib::luaL_unref;
pub use self::lauxlib::luaL_where;

// commonly used constants from lua.h
pub use self::lua::LUA_MULTRET;
pub use self::lua::LUA_REGISTRYINDEX;

pub use self::lua::{LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS};

pub use self::lua::{LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV};
pub use self::lua::{LUA_OPMOD, LUA_OPPOW, LUA_OPUNM};
pub use self::lua::{LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR};
pub use self::lua::{LUA_OPEQ, LUA_OPLT, LUA_OPLE};

pub use self::lua::{LUA_OK, LUA_ERRRUN, LUA_ERRMEM, LUA_ERRERR, LUA_ERRGCMM};

pub use self::lua::{LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE};
pub use self::lua::{LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA};

pub use self::lua::{LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT};

// constants from lauxlib.h
pub use self::lauxlib::{LUA_REFNIL, LUA_NOREF};

mod glue;
pub mod luaconf;
pub mod lua;
pub mod lauxlib;
pub mod lualib;

<commit_msg>Re-export GC options<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

#![allow(non_camel_case_types)]
#![allow(non_snake_case)]

pub use self::lua::lua_Alloc;
pub use self::lua::lua_CFunction;
pub use self::lua::lua_Ctx;
pub use self::lua::lua_Debug;
pub use self::lua::lua_Hook;
pub use self::lua::lua_Integer;
pub use self::lua::lua_KFunction;
pub use self::lua::lua_Number;
pub use self::lua::lua_Reader;
pub use self::lua::lua_State;
pub use self::lua::lua_Unsigned;
pub use self::lua::lua_Writer;

pub use self::lua::lua_absindex;
pub use self::lua::lua_arith;
pub use self::lua::lua_atpanic;
pub use self::lua::lua_call;
pub use self::lua::lua_callk;
pub use self::lua::lua_checkstack;
pub use self::lua::lua_close;
pub use self::lua::lua_compare;
pub use self::lua::lua_concat;
pub use self::lua::lua_copy;
pub use self::lua::lua_createtable;
pub use self::lua::lua_dump;
pub use self::lua::lua_error;
pub use self::lua::lua_gc;
pub use self::lua::lua_getallocf;
pub use self::lua::lua_getextraspace;
pub use self::lua::lua_getfield;
pub use self::lua::lua_getglobal;
pub use self::lua::lua_gethook;
pub use self::lua::lua_gethookcount;
pub use self::lua::lua_gethookmask;
pub use self::lua::lua_getinfo;
pub use self::lua::lua_getlocal;
pub use self::lua::lua_getmetatable;
pub use self::lua::lua_getstack;
pub use self::lua::lua_gettable;
pub use self::lua::lua_gettop;
pub use self::lua::lua_getupvalue;
pub use self::lua::lua_getuservalue;
pub use self::lua::lua_insert;
pub use self::lua::lua_isboolean;
pub use self::lua::lua_iscfunction;
pub use self::lua::lua_isfunction;
pub use self::lua::lua_isinteger;
pub use self::lua::lua_islightuserdata;
pub use self::lua::lua_isnil;
pub use self::lua::lua_isnone;
pub use self::lua::lua_isnoneornil;
pub use self::lua::lua_isnumber;
pub use self::lua::lua_isstring;
pub use self::lua::lua_istable;
pub use self::lua::lua_isthread;
pub use self::lua::lua_isuserdata;
pub use self::lua::lua_isyieldable;
pub use self::lua::lua_len;
pub use self::lua::lua_load;
pub use self::lua::lua_newstate;
pub use self::lua::lua_newtable;
pub use self::lua::lua_newthread;
pub use self::lua::lua_newuserdata;
pub use self::lua::lua_next;
pub use self::luaconf::lua_numtointeger;
pub use self::lua::lua_pcall;
pub use self::lua::lua_pcallk;
pub use self::lua::lua_pop;
pub use self::lua::lua_pushboolean;
pub use self::lua::lua_pushcclosure;
pub use self::lua::lua_pushcfunction;
pub use self::lua::lua_pushfstring;
pub use self::lua::lua_pushglobaltable;
pub use self::lua::lua_pushinteger;
pub use self::lua::lua_pushlightuserdata;
pub use self::lua::lua_pushliteral;
pub use self::lua::lua_pushlstring;
pub use self::lua::lua_pushnil;
pub use self::lua::lua_pushnumber;
pub use self::lua::lua_pushstring;
pub use self::lua::lua_pushthread;
pub use self::lua::lua_pushvalue;
//pub use self::lua::lua_pushvfstring; -- not implemented
pub use self::lua::lua_rawequal;
pub use self::lua::lua_rawget;
pub use self::lua::lua_rawgeti;
pub use self::lua::lua_rawgetp;
pub use self::lua::lua_rawlen;
pub use self::lua::lua_rawset;
pub use self::lua::lua_rawseti;
pub use self::lua::lua_rawsetp;
pub use self::lua::lua_register;
pub use self::lua::lua_remove;
pub use self::lua::lua_replace;
pub use self::lua::lua_resume;
pub use self::lua::lua_rotate;
pub use self::lua::lua_setallocf;
pub use self::lua::lua_setfield;
pub use self::lua::lua_setglobal;
pub use self::lua::lua_sethook;
pub use self::lua::lua_setlocal;
pub use self::lua::lua_setmetatable;
pub use self::lua::lua_settable;
pub use self::lua::lua_settop;
pub use self::lua::lua_setupvalue;
pub use self::lua::lua_setuservalue;
pub use self::lua::lua_status;
pub use self::lua::lua_strtonum;
pub use self::lua::lua_toboolean;
pub use self::lua::lua_tocfunction;
pub use self::lua::lua_tointeger;
pub use self::lua::lua_tointegerx;
pub use self::lua::lua_tolstring;
pub use self::lua::lua_tonumber;
pub use self::lua::lua_tonumberx;
pub use self::lua::lua_topointer;
pub use self::lua::lua_tostring;
pub use self::lua::lua_tothread;
pub use self::lua::lua_touserdata;
pub use self::lua::lua_type;
pub use self::lua::lua_typename;
pub use self::lua::lua_upvalueid;
pub use self::lua::lua_upvalueindex;
pub use self::lua::lua_upvaluejoin;
pub use self::lua::lua_version;
pub use self::lua::lua_xmove;
pub use self::lua::lua_yield;
pub use self::lua::lua_yieldk;

pub use self::lauxlib::luaL_Buffer;
pub use self::lauxlib::luaL_Reg;
pub use self::lauxlib::luaL_Stream;

pub use self::lauxlib::luaL_addchar;
pub use self::lauxlib::luaL_addlstring;
pub use self::lauxlib::luaL_addsize;
pub use self::lauxlib::luaL_addstring;
pub use self::lauxlib::luaL_addvalue;
pub use self::lauxlib::luaL_argcheck;
pub use self::lauxlib::luaL_argerror;
pub use self::lauxlib::luaL_buffinit;
pub use self::lauxlib::luaL_buffinitsize;
pub use self::lauxlib::luaL_callmeta;
pub use self::lauxlib::luaL_checkany;
pub use self::lauxlib::luaL_checkint;
pub use self::lauxlib::luaL_checkinteger;
pub use self::lauxlib::luaL_checklong;
pub use self::lauxlib::luaL_checklstring;
pub use self::lauxlib::luaL_checknumber;
pub use self::lauxlib::luaL_checkoption;
pub use self::lauxlib::luaL_checkstack;
pub use self::lauxlib::luaL_checkstring;
pub use self::lauxlib::luaL_checktype;
pub use self::lauxlib::luaL_checkudata;
pub use self::lauxlib::luaL_checkversion;
pub use self::lauxlib::luaL_dofile;
pub use self::lauxlib::luaL_dostring;
pub use self::lauxlib::luaL_error;
pub use self::lauxlib::luaL_execresult;
pub use self::lauxlib::luaL_fileresult;
pub use self::lauxlib::luaL_getmetafield;
pub use self::lauxlib::luaL_getmetatable;
pub use self::lauxlib::luaL_getsubtable;
pub use self::lauxlib::luaL_gsub;
pub use self::lauxlib::luaL_len;
pub use self::lauxlib::luaL_loadbuffer;
pub use self::lauxlib::luaL_loadbufferx;
pub use self::lauxlib::luaL_loadfile;
pub use self::lauxlib::luaL_loadfilex;
pub use self::lauxlib::luaL_loadstring;
pub use self::lauxlib::luaL_newlib;
pub use self::lauxlib::luaL_newlibtable;
pub use self::lauxlib::luaL_newmetatable;
pub use self::lauxlib::luaL_newstate;
pub use self::lualib::luaL_openlibs;
pub use self::lauxlib::luaL_optint;
pub use self::lauxlib::luaL_optinteger;
pub use self::lauxlib::luaL_optlong;
pub use self::lauxlib::luaL_optlstring;
pub use self::lauxlib::luaL_optnumber;
pub use self::lauxlib::luaL_optstring;
pub use self::lauxlib::luaL_prepbuffer;
pub use self::lauxlib::luaL_prepbuffsize;
pub use self::lauxlib::luaL_pushresult;
pub use self::lauxlib::luaL_pushresultsize;
pub use self::lauxlib::luaL_ref;
pub use self::lauxlib::luaL_requiref;
pub use self::lauxlib::luaL_setfuncs;
pub use self::lauxlib::luaL_setmetatable;
pub use self::lauxlib::luaL_testudata;
pub use self::lauxlib::luaL_tolstring;
pub use self::lauxlib::luaL_traceback;
pub use self::lauxlib::luaL_typename;
pub use self::lauxlib::luaL_unref;
pub use self::lauxlib::luaL_where;

// commonly used constants from lua.h
pub use self::lua::LUA_MULTRET;
pub use self::lua::LUA_REGISTRYINDEX;

pub use self::lua::{LUA_RIDX_MAINTHREAD, LUA_RIDX_GLOBALS};

pub use self::lua::{LUA_OPADD, LUA_OPSUB, LUA_OPMUL, LUA_OPDIV, LUA_OPIDIV};
pub use self::lua::{LUA_OPMOD, LUA_OPPOW, LUA_OPUNM};
pub use self::lua::{LUA_OPBNOT, LUA_OPBAND, LUA_OPBOR, LUA_OPBXOR, LUA_OPSHL, LUA_OPSHR};
pub use self::lua::{LUA_OPEQ, LUA_OPLT, LUA_OPLE};

pub use self::lua::{LUA_OK, LUA_ERRRUN, LUA_ERRMEM, LUA_ERRERR, LUA_ERRGCMM};

pub use self::lua::{LUA_TNIL, LUA_TNUMBER, LUA_TBOOLEAN, LUA_TSTRING, LUA_TTABLE};
pub use self::lua::{LUA_TFUNCTION, LUA_TUSERDATA, LUA_TTHREAD, LUA_TLIGHTUSERDATA};

pub use self::lua::{LUA_HOOKCALL, LUA_HOOKRET, LUA_HOOKTAILCALL, LUA_HOOKLINE, LUA_HOOKCOUNT};

pub use self::lua::{LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, LUA_GCCOUNT, LUA_GCCOUNTB};
pub use self::lua::{LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, LUA_GCISRUNNING};

// constants from lauxlib.h
pub use self::lauxlib::{LUA_REFNIL, LUA_NOREF};

mod glue;
pub mod luaconf;
pub mod lua;
pub mod lauxlib;
pub mod lualib;

<|endoftext|>


<commit_before>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread;

use bincode::rustc_serialize::decode;

static LIB_NAME: &'static str = "ws-p2p";

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client
    pub demo_client: Option<String>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                let message: PeerMessage = decode(encoded_msg).unwrap();

                debug!(target: LIB_NAME, "I am {:?}.", self.ws.token());

                if let Some(demo_client) = self.demo_client.clone() {
                    if message.sender.as_str() == demo_client.as_str() {
                        info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                        thread::sleep(Duration::from_millis(4000))
                    }
                }

				self.message_handler(message);
                self.buffer_check();
                Ok(())
            },
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to the client list", string);
                let mut clocks = self.clocks.lock().unwrap();
                clocks.insert(string, 0u32);
                Ok(())
            }
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        //TODO: Remove disconnected client's clock from our vclock copy.
        if reason.is_empty() {
            //This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} disconnected with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        debug!("trying to get lock");
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            debug!("Are we getting here?");
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if let Some(lval) = vclocks.get(&key.clone()) {
                    debug!(target: LIB_NAME, "key: {} incoming val: {} and lval: {}", key, val, lval);
                    if val <= lval {
                        debug!(target: LIB_NAME, "val <= lval");
                        continue;
                    } else { // There's a clock that is greater than what we have
                        debug!(target: LIB_NAME, "discrepency still exists");
                        ()
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                let lval = vclocks.get(&key.clone()).unwrap().clone();
                let max_val = cmp::max(val, &lval);
                vclocks.insert(key.clone(), *max_val);
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        let mut vclocks = self.clocks.lock().unwrap();
        for (key, val) in message.clocks.iter() {
            if key.as_str() == message.sender.as_str() {
                if let Some(lval) = vclocks.get(&key.clone()) {
                    if *val != *lval + 1 {
                        let mut buffer = self.buffer.lock().unwrap();
                        buffer.push_back(message.clone());
                        debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                        ()
                    }
                }
            } else {
                if let Some(lval) = vclocks.get(&key.clone()) {
                    debug!(target: LIB_NAME, "key: {} incoming val: {} and lval: {}", key, val, lval);
                    if val <= lval {
                        debug!(target: LIB_NAME, "val <= lval");
                        continue;
                    } else { // There's a clock that is greater than what we have
                        // Push to local buffer
                        let mut buffer = self.buffer.lock().unwrap();
                        buffer.push_back(message.clone());
                        debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                        ()
                    }
                }
            }
        }

        // Update clocks
        debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
        info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                message.sender, message.clocks, message.message);
        for (key, val) in message.clocks.iter() {
            let lval = vclocks.get(&key.clone()).unwrap().clone();
            let max_val = cmp::max(val, &lval);
            vclocks.insert(key.clone(), *max_val);
        }
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
        }
    }
}

<commit_msg>A better delay for demoing using timeout<commit_after>extern crate ws;

use message::PeerMessage;

use std::cmp;
use std::collections::hash_map::HashMap;
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::thread;

use bincode::rustc_serialize::decode;

use ws::util::Token;

static LIB_NAME: &'static str = "ws-p2p";

const DELAYED_MESSAGE: Token = Token(1);

/// Connection handler for incoming messages.
pub struct MessageHandler {
    /// Sender that is used to communicate for the handler.
    pub ws: ws::Sender,
    /// An arc clone of my local vector clocks.
    pub clocks: Arc<Mutex<HashMap<String, u32>>>,
    /// My address/name.
    pub me: String,
    /// Buffer of messages that caused conflicts when initially received.
    pub buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    /// Delays messages received from client.
    pub demo_client: Option<String>,
    /// Holder for delayed messages.
    message_queue: VecDeque<PeerMessage>,
}

impl ws::Handler for MessageHandler {
    fn on_message(&mut self, msg: ws::Message) -> ws::Result<()> {
        match msg {
            ws::Message::Binary(vector) => {
                let encoded_msg = &*vector.into_boxed_slice();
                let message: PeerMessage = decode(encoded_msg).unwrap();

                debug!(target: LIB_NAME, "I am {:?}.", self.ws.token());

                if let Some(demo_client) = self.demo_client.clone() {
                    if message.sender.as_str() == demo_client.as_str() {
                        info!(target: LIB_NAME, "Faking delay for messages from {}!", demo_client);
                        self.message_queue.push_back(message);
                        return self.ws.timeout(4000, DELAYED_MESSAGE);
                    }
                }

				self.message_handler(message);
                self.buffer_check();
                Ok(())
            },
            ws::Message::Text(string) => {
                info!(target: LIB_NAME, "Received peer's name. Adding {} to the client list", string);
                let mut clocks = self.clocks.lock().unwrap();
                clocks.insert(string, 0u32);
                Ok(())
            }
        }
    }
    fn on_timeout(&mut self, event: Token) -> ws::Result<()> {
        match event {
            DELAYED_MESSAGE => {
                let msg = self.message_queue.pop_front().unwrap();
                self.message_handler(msg);
                self.buffer_check();
                Ok(())
            },
            _ => Err(ws::Error::new(ws::ErrorKind::Internal, "Invalid timeout token encountered!")),
        }
    }
    fn on_close(&mut self, code: ws::CloseCode, reason: &str) {
        //TODO: Remove disconnected client's clock from our vclock copy.
        if reason.is_empty() {
            //This works: CloseCode::Abnormal
            info!(target: LIB_NAME, "Client disconnected with code: {:?}", code);
        } else {
            info!(target: LIB_NAME, "{} disconnected with code: {:?} and reason: {}", self.me, code, reason);
        }
    }
    fn on_error(&mut self, err: ws::Error) {
        warn!(target: LIB_NAME, "Error family robinson! {:?}", err.kind);
    }
    fn on_shutdown(&mut self) {
        warn!(target: LIB_NAME, "Socket shutdown from {}", self.me);
    }
}

impl MessageHandler {
    fn buffer_check(&self) {
        debug!("trying to get lock");
        let mut buffer = self.buffer.lock().unwrap();
        let buffer_clone = buffer.clone();
        for message in buffer_clone.iter() {
            debug!("Are we getting here?");
            let mut vclocks = self.clocks.lock().unwrap();
            for (key, val) in message.clocks.iter() {
                if let Some(lval) = vclocks.get(&key.clone()) {
                    debug!(target: LIB_NAME, "key: {} incoming val: {} and lval: {}", key, val, lval);
                    if val <= lval {
                        debug!(target: LIB_NAME, "val <= lval");
                        continue;
                    } else { // There's a clock that is greater than what we have
                        debug!(target: LIB_NAME, "discrepency still exists");
                        ()
                    }
                }
            }

            // Update clocks
            for (key, val) in message.clocks.iter() {
                let lval = vclocks.get(&key.clone()).unwrap().clone();
                let max_val = cmp::max(val, &lval);
                vclocks.insert(key.clone(), *max_val);
            }
            info!(target: LIB_NAME, "buf_check: Peer {} with clocks: {:?} got message: {}",
                    message.sender, message.clocks, message.message);
            buffer.pop_front();
        }
    }
    fn message_handler(&self, message: PeerMessage) {
        let mut vclocks = self.clocks.lock().unwrap();
        for (key, val) in message.clocks.iter() {
            if key.as_str() == message.sender.as_str() {
                if let Some(lval) = vclocks.get(&key.clone()) {
                    if *val != *lval + 1 {
                        let mut buffer = self.buffer.lock().unwrap();
                        buffer.push_back(message.clone());
                        debug!(target: LIB_NAME, "clock discrepency with from incoming peer");
                        ()
                    }
                }
            } else {
                if let Some(lval) = vclocks.get(&key.clone()) {
                    debug!(target: LIB_NAME, "key: {} incoming val: {} and lval: {}", key, val, lval);
                    if val <= lval {
                        debug!(target: LIB_NAME, "val <= lval");
                        continue;
                    } else { // There's a clock that is greater than what we have
                        // Push to local buffer
                        let mut buffer = self.buffer.lock().unwrap();
                        buffer.push_back(message.clone());
                        debug!(target: LIB_NAME, "clock discrepency from other peer clocks");
                        ()
                    }
                }
            }
        }

        // Update clocks
        debug!(target: LIB_NAME, "Updating clocks now because no discrepency");
        info!(target: LIB_NAME, "msg_handler: Peer {} with clocks: {:?} got message: {}",
                message.sender, message.clocks, message.message);
        for (key, val) in message.clocks.iter() {
            let lval = vclocks.get(&key.clone()).unwrap().clone();
            let max_val = cmp::max(val, &lval);
            vclocks.insert(key.clone(), *max_val);
        }
    }
}

#[derive(Clone)]
pub struct MessageFactory {
    vclocks: Arc<Mutex<HashMap<String, u32>>>,
    me: String,
    buffer: Arc<Mutex<VecDeque<PeerMessage>>>,
    demo_client: Option<String>,
}

impl MessageFactory {
    pub fn build(vclocks: Arc<Mutex<HashMap<String, u32>>>) -> MessageFactory {
        MessageFactory {
            vclocks: vclocks.clone(),
            me: String::from("undefined"),
            buffer: Arc::new(Mutex::new(VecDeque::new())),
            demo_client: None,
        }
    }
    pub fn me(&self, me: &str) -> MessageFactory {
        MessageFactory {
            vclocks: self.vclocks.clone(),
            me: String::from(me),
            buffer: self.buffer.clone(),
            demo_client: match self.demo_client.clone() {
                Some(peer) => Some(peer),
                None => None,
            },
        }
    }
    pub fn demo(&mut self, peer: &str) {
        self.demo_client = Some(String::from(peer));
    }
}

impl ws::Factory for MessageFactory {
    type Handler = MessageHandler;

    fn connection_made(&mut self, ws: ws::Sender) -> Self::Handler {
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn server_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }

    fn client_connected(&mut self, ws: ws::Sender) -> Self::Handler {
        ws.send(self.me.clone()).unwrap();
        MessageHandler {
            ws: ws,
            clocks: self.vclocks.clone(),
            me: self.me.clone(),
            buffer: self.buffer.clone(),
            demo_client: self.demo_client.clone(),
            message_queue: VecDeque::new(),
        }
    }
}

<|endoftext|>