<commit_before>use rustc::hir::*;
use rustc::hir::map::Node::NodeItem;
use rustc::lint::*;
use rustc::ty::TypeVariants;
use syntax::ast::LitKind;
use utils::paths;
use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty};

/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
///
/// **Why is this bad?** There is no point of doing that. `format!("too")` can
/// be replaced by `"foo".to_owned()` if you really need a `String`. The even
/// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
/// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
/// is `foo: &str`.
///
/// **Known problems:** None.
///
/// **Examples:**
/// ```rust
/// format!("foo")
/// format!("{}", foo)
/// ```
declare_lint! {
    pub USELESS_FORMAT,
    Warn,
    "useless use of `format!`"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array![USELESS_FORMAT]
    }
}

impl LateLintPass for Pass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if let Some(span) = is_expn_of(cx, expr.span, "format") {
            match expr.node {
                // `format!("{}", foo)` expansion
                ExprCall(ref fun, ref args) => {
                    if_let_chain!{[
                        let ExprPath(_, ref path) = fun.node,
                        args.len() == 2,
                        match_path(path, &paths::FMT_ARGUMENTS_NEWV1),
                        // ensure the format string is `"{..}"` with only one argument and no text
                        check_static_str(cx, &args[0]),
                        // ensure the format argument is `{}` ie. Display with no fancy option
                        check_arg_is_display(cx, &args[1])
                    ], {
                        span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                    }}
                }
                // `format!("foo")` expansion contains `match () { () => [], }`
                ExprMatch(ref matchee, _, _) => {
                    if let ExprTup(ref tup) = matchee.node {
                        if tup.is_empty() {
                            span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                        }
                    }
                }
                _ => (),
            }
        }
    }
}

/// Returns the slice of format string parts in an `Arguments::new_v1` call.
/// Public because it's shared with a lint in print.rs.
pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Expr)
                                         -> Option<Vec<&'a str>> {
    if_let_chain! {[
        let ExprBlock(ref block) = expr.node,
        block.stmts.len() == 1,
        let StmtDecl(ref decl, _) = block.stmts[0].node,
        let DeclItem(ref decl) = decl.node,
        let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id),
        decl.name.as_str() == "__STATIC_FMTSTR",
        let ItemStatic(_, _, ref expr) = decl.node,
        let ExprAddrOf(_, ref expr) = expr.node, // &[""]
        let ExprVec(ref exprs) = expr.node,
    ], {
        let mut result = Vec::new();
        for expr in exprs {
            if let ExprLit(ref lit) = expr.node {
                if let LitKind::Str(ref lit, _) = lit.node {
                    result.push(&**lit);
                }
            }
        }
        return Some(result);
    }}
    None
}

/// Checks if the expressions matches
/// ```rust
/// { static __STATIC_FMTSTR: &[""] = _; __STATIC_FMTSTR }
/// ```
fn check_static_str(cx: &LateContext, expr: &Expr) -> bool {
    if let Some(expr) = get_argument_fmtstr_parts(cx, expr) {
        expr.len() == 1 && expr[0].is_empty()
    } else {
        false
    }
}

/// Checks if the expressions matches
/// ```rust
/// &match (&42,) {
///     (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)],
/// })
/// ```
fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
    if_let_chain! {[
        let ExprAddrOf(_, ref expr) = expr.node,
        let ExprMatch(_, ref arms, _) = expr.node,
        arms.len() == 1,
        arms[0].pats.len() == 1,
        let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node,
        pat.len() == 1,
        let ExprVec(ref exprs) = arms[0].body.node,
        exprs.len() == 1,
        let ExprCall(_, ref args) = exprs[0].node,
        args.len() == 2,
        let ExprPath(None, ref path) = args[1].node,
        match_path(path, &paths::DISPLAY_FMT_METHOD)
    ], {
        let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0]));

        return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
    }}

    false
}
<commit_msg>Fix slightly wrong comment<commit_after>use rustc::hir::*;
use rustc::hir::map::Node::NodeItem;
use rustc::lint::*;
use rustc::ty::TypeVariants;
use syntax::ast::LitKind;
use utils::paths;
use utils::{is_expn_of, match_path, match_type, span_lint, walk_ptrs_ty};

/// **What it does:** Checks for the use of `format!("string literal with no
/// argument")` and `format!("{}", foo)` where `foo` is a string.
///
/// **Why is this bad?** There is no point of doing that. `format!("too")` can
/// be replaced by `"foo".to_owned()` if you really need a `String`. The even
/// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
/// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
/// is `foo: &str`.
///
/// **Known problems:** None.
///
/// **Examples:**
/// ```rust
/// format!("foo")
/// format!("{}", foo)
/// ```
declare_lint! {
    pub USELESS_FORMAT,
    Warn,
    "useless use of `format!`"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array![USELESS_FORMAT]
    }
}

impl LateLintPass for Pass {
    fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
        if let Some(span) = is_expn_of(cx, expr.span, "format") {
            match expr.node {
                // `format!("{}", foo)` expansion
                ExprCall(ref fun, ref args) => {
                    if_let_chain!{[
                        let ExprPath(_, ref path) = fun.node,
                        args.len() == 2,
                        match_path(path, &paths::FMT_ARGUMENTS_NEWV1),
                        // ensure the format string is `"{..}"` with only one argument and no text
                        check_static_str(cx, &args[0]),
                        // ensure the format argument is `{}` ie. Display with no fancy option
                        check_arg_is_display(cx, &args[1])
                    ], {
                        span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                    }}
                }
                // `format!("foo")` expansion contains `match () { () => [], }`
                ExprMatch(ref matchee, _, _) => {
                    if let ExprTup(ref tup) = matchee.node {
                        if tup.is_empty() {
                            span_lint(cx, USELESS_FORMAT, span, "useless use of `format!`");
                        }
                    }
                }
                _ => (),
            }
        }
    }
}

/// Returns the slice of format string parts in an `Arguments::new_v1` call.
/// Public because it's shared with a lint in print.rs.
pub fn get_argument_fmtstr_parts<'a, 'b>(cx: &LateContext<'a, 'b>, expr: &'a Expr)
                                         -> Option<Vec<&'a str>> {
    if_let_chain! {[
        let ExprBlock(ref block) = expr.node,
        block.stmts.len() == 1,
        let StmtDecl(ref decl, _) = block.stmts[0].node,
        let DeclItem(ref decl) = decl.node,
        let Some(NodeItem(decl)) = cx.tcx.map.find(decl.id),
        decl.name.as_str() == "__STATIC_FMTSTR",
        let ItemStatic(_, _, ref expr) = decl.node,
        let ExprAddrOf(_, ref expr) = expr.node, // &["…", "…", …]
        let ExprVec(ref exprs) = expr.node,
    ], {
        let mut result = Vec::new();
        for expr in exprs {
            if let ExprLit(ref lit) = expr.node {
                if let LitKind::Str(ref lit, _) = lit.node {
                    result.push(&**lit);
                }
            }
        }
        return Some(result);
    }}
    None
}

/// Checks if the expressions matches
/// ```rust
/// { static __STATIC_FMTSTR: … = &["…", "…", …]; __STATIC_FMTSTR }
/// ```
fn check_static_str(cx: &LateContext, expr: &Expr) -> bool {
    if let Some(expr) = get_argument_fmtstr_parts(cx, expr) {
        expr.len() == 1 && expr[0].is_empty()
    } else {
        false
    }
}

/// Checks if the expressions matches
/// ```rust
/// &match (&42,) {
///     (__arg0,) => [::std::fmt::ArgumentV1::new(__arg0, ::std::fmt::Display::fmt)],
/// })
/// ```
fn check_arg_is_display(cx: &LateContext, expr: &Expr) -> bool {
    if_let_chain! {[
        let ExprAddrOf(_, ref expr) = expr.node,
        let ExprMatch(_, ref arms, _) = expr.node,
        arms.len() == 1,
        arms[0].pats.len() == 1,
        let PatKind::Tuple(ref pat, None) = arms[0].pats[0].node,
        pat.len() == 1,
        let ExprVec(ref exprs) = arms[0].body.node,
        exprs.len() == 1,
        let ExprCall(_, ref args) = exprs[0].node,
        args.len() == 2,
        let ExprPath(None, ref path) = args[1].node,
        match_path(path, &paths::DISPLAY_FMT_METHOD)
    ], {
        let ty = walk_ptrs_ty(cx.tcx.pat_ty(&pat[0]));

        return ty.sty == TypeVariants::TyStr || match_type(cx, ty, &paths::STRING);
    }}

    false
}
<|endoftext|>


<commit_before>use std::vec::Vec;
use std::collections::HashSet;
use std::hash::Hash;
use std::cmp::Eq;

fn main() {
    let mut sample_elements = vec![0u8, 0, 1, 1, 2, 3, 2];
    println!("Before removal of duplicates : {:?}", sample_elements);
    remove_duplicate_elements(&mut sample_elements);
    println!("After removal of duplicates : {:?}", sample_elements);
}

fn remove_duplicate_elements<T: Hash + Eq>(elements: &mut Vec<T>) {
    let set: HashSet<_> = elements.drain(..).collect();
    elements.extend(set.into_iter());
}

#[test]
fn test_remove_duplicate_elements() {
    let mut sample_elements = vec![0u8, 0, 1, 1, 2, 3, 2];
    remove_duplicate_elements(&mut sample_elements);
    sample_elements.sort();
    assert_eq!(sample_elements, vec![0, 1, 2, 3])
}
<commit_msg>cleanup & add sorting method<commit_after>use std::collections::HashSet;
use std::hash::Hash;

fn remove_duplicate_elements_hashing<T: Hash + Eq>(elements: &mut Vec<T>) {
    let set: HashSet<_> = elements.drain(..).collect();
    elements.extend(set.into_iter());
}

fn remove_duplicate_elements_sorting<T: Ord>(elements: &mut Vec<T>) {
    elements.sort_unstable();
    elements.dedup();
}

fn main() {
    let mut sample_elements = vec![0, 0, 1, 1, 2, 3, 2];
    println!("Before removal of duplicates : {:?}", sample_elements);
    remove_duplicate_elements_sorting(&mut sample_elements);
    println!("After removal of duplicates : {:?}", sample_elements);
}

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

    #[test]
    fn test_remove_duplicate_elements_hashing() {
        let mut sample_elements = vec![0, 0, 1, 1, 2, 3, 2];
        remove_duplicate_elements_hashing(&mut sample_elements);
        sample_elements.sort_unstable();
        assert_eq!(sample_elements, [0, 1, 2, 3])
    }

    #[test]
    fn test_remove_duplicate_elements_sorting() {
        let mut sample_elements = vec![0, 0, 1, 1, 2, 3, 2];
        remove_duplicate_elements_sorting(&mut sample_elements);
        assert_eq!(sample_elements, [0, 1, 2, 3])
    }
}
<|endoftext|>


<commit_before><commit_msg>Fix formatting/clippy warnings<commit_after><|endoftext|>


<commit_before>use crate::file::File;
use crate::rank::Rank;
use crate::square::*;
use std::fmt;
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Mul, Not};

/// A good old-fashioned bitboard
/// You *do* have access to the actual value, but you are probably better off
/// using the implemented operators to work with this object.
///
/// ```
/// use chess::{BitBoard, Square};
///
/// let bb = BitBoard(7); // lower-left 3 squares
///
/// let mut count = 0;
///
/// // Iterate over each square in the bitboard
/// for _ in bb {
///     count += 1;
/// }
///
/// assert_eq!(count, 3);
/// ```
///
#[derive(PartialEq, PartialOrd, Clone, Copy, Debug, Default)]
pub struct BitBoard(pub u64);

/// An empty bitboard.  It is sometimes useful to use !EMPTY to get the universe of squares.
///
/// ```
///     use chess::EMPTY;
///
///     assert_eq!(EMPTY.count(), 0);
///
///     assert_eq!((!EMPTY).count(), 64);
/// ```
pub const EMPTY: BitBoard = BitBoard(0);

// Impl BitAnd
impl BitAnd for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

impl BitAnd for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

impl BitAnd<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

impl BitAnd<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

// Impl BitOr
impl BitOr for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

impl BitOr for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

impl BitOr<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

impl BitOr<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

// Impl BitXor

impl BitXor for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

impl BitXor for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

impl BitXor<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

impl BitXor<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

// Impl BitAndAssign

impl BitAndAssign for BitBoard {
    #[inline]
    fn bitand_assign(&mut self, other: BitBoard) {
        self.0 &= other.0;
    }
}

impl BitAndAssign<&BitBoard> for BitBoard {
    #[inline]
    fn bitand_assign(&mut self, other: &BitBoard) {
        self.0 &= other.0;
    }
}

// Impl BitOrAssign
impl BitOrAssign for BitBoard {
    #[inline]
    fn bitor_assign(&mut self, other: BitBoard) {
        self.0 |= other.0;
    }
}

impl BitOrAssign<&BitBoard> for BitBoard {
    #[inline]
    fn bitor_assign(&mut self, other: &BitBoard) {
        self.0 |= other.0;
    }
}

// Impl BitXor Assign
impl BitXorAssign for BitBoard {
    #[inline]
    fn bitxor_assign(&mut self, other: BitBoard) {
        self.0 ^= other.0;
    }
}

impl BitXorAssign<&BitBoard> for BitBoard {
    #[inline]
    fn bitxor_assign(&mut self, other: &BitBoard) {
        self.0 ^= other.0;
    }
}

// Impl Mul
impl Mul for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

impl Mul for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

impl Mul<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

impl Mul<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

// Impl Not
impl Not for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn not(self) -> BitBoard {
        BitBoard(!self.0)
    }
}

impl Not for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn not(self) -> BitBoard {
        BitBoard(!self.0)
    }
}

impl fmt::Display for BitBoard {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s: String = "".to_owned();
        for x in 0..64 {
            if self.0 & (1u64 << x) == (1u64 << x) {
                s.push_str("X ");
            } else {
                s.push_str(". ");
            }
            if x % 8 == 7 {
                s.push_str("\n");
            }
        }
        write!(f, "{}", s)
    }
}

impl BitBoard {
    /// Construct a new bitboard from a u64
    #[inline]
    pub fn new(b: u64) -> BitBoard {
        BitBoard(b)
    }

    /// Construct a new `BitBoard` with a particular `Square` set
    #[inline]
    pub fn set(rank: Rank, file: File) -> BitBoard {
        BitBoard::from_square(Square::make_square(rank, file))
    }

    /// Construct a new `BitBoard` with a particular `Square` set
    #[inline]
    pub fn from_square(sq: Square) -> BitBoard {
        BitBoard(1u64 << sq.to_int())
    }

    /// Convert an `Option<Square>` to an `Option<BitBoard>`
    #[inline]
    pub fn from_maybe_square(sq: Option<Square>) -> Option<BitBoard> {
        sq.map(|s| BitBoard::from_square(s))
    }

    /// Convert a `BitBoard` to a `Square`.  This grabs the least-significant `Square`
    #[inline]
    pub fn to_square(&self) -> Square {
        unsafe { Square::new(self.0.trailing_zeros() as u8) }
    }

    /// Count the number of `Squares` set in this `BitBoard`
    #[inline]
    pub fn popcnt(&self) -> u32 {
        self.0.count_ones()
    }

    /// Reverse this `BitBoard`.  Look at it from the opponents perspective.
    #[inline]
    pub fn reverse_colors(&self) -> BitBoard {
        BitBoard(self.0.swap_bytes())
    }

    /// Convert this `BitBoard` to a `usize` (for table lookups)
    #[inline]
    pub fn to_size(&self, rightshift: u8) -> usize {
        (self.0 >> rightshift) as usize
    }
}

/// For the `BitBoard`, iterate over every `Square` set.
impl Iterator for BitBoard {
    type Item = Square;

    #[inline]
    fn next(&mut self) -> Option<Square> {
        if self.0 == 0 {
            None
        } else {
            let result = self.to_square();
            *self ^= BitBoard::from_square(result);
            Some(result)
        }
    }
}
<commit_msg>Derived Eq and Hash for Bitboard<commit_after>use crate::file::File;
use crate::rank::Rank;
use crate::square::*;
use std::fmt;
use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Mul, Not};

/// A good old-fashioned bitboard
/// You *do* have access to the actual value, but you are probably better off
/// using the implemented operators to work with this object.
///
/// ```
/// use chess::{BitBoard, Square};
///
/// let bb = BitBoard(7); // lower-left 3 squares
///
/// let mut count = 0;
///
/// // Iterate over each square in the bitboard
/// for _ in bb {
///     count += 1;
/// }
///
/// assert_eq!(count, 3);
/// ```
///
#[derive(PartialEq, Eq, PartialOrd, Clone, Copy, Debug, Default, Hash)]
pub struct BitBoard(pub u64);

/// An empty bitboard.  It is sometimes useful to use !EMPTY to get the universe of squares.
///
/// ```
///     use chess::EMPTY;
///
///     assert_eq!(EMPTY.count(), 0);
///
///     assert_eq!((!EMPTY).count(), 64);
/// ```
pub const EMPTY: BitBoard = BitBoard(0);

// Impl BitAnd
impl BitAnd for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

impl BitAnd for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

impl BitAnd<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

impl BitAnd<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitand(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 & other.0)
    }
}

// Impl BitOr
impl BitOr for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

impl BitOr for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

impl BitOr<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

impl BitOr<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 | other.0)
    }
}

// Impl BitXor

impl BitXor for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

impl BitXor for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

impl BitXor<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

impl BitXor<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn bitxor(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0 ^ other.0)
    }
}

// Impl BitAndAssign

impl BitAndAssign for BitBoard {
    #[inline]
    fn bitand_assign(&mut self, other: BitBoard) {
        self.0 &= other.0;
    }
}

impl BitAndAssign<&BitBoard> for BitBoard {
    #[inline]
    fn bitand_assign(&mut self, other: &BitBoard) {
        self.0 &= other.0;
    }
}

// Impl BitOrAssign
impl BitOrAssign for BitBoard {
    #[inline]
    fn bitor_assign(&mut self, other: BitBoard) {
        self.0 |= other.0;
    }
}

impl BitOrAssign<&BitBoard> for BitBoard {
    #[inline]
    fn bitor_assign(&mut self, other: &BitBoard) {
        self.0 |= other.0;
    }
}

// Impl BitXor Assign
impl BitXorAssign for BitBoard {
    #[inline]
    fn bitxor_assign(&mut self, other: BitBoard) {
        self.0 ^= other.0;
    }
}

impl BitXorAssign<&BitBoard> for BitBoard {
    #[inline]
    fn bitxor_assign(&mut self, other: &BitBoard) {
        self.0 ^= other.0;
    }
}

// Impl Mul
impl Mul for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

impl Mul for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

impl Mul<&BitBoard> for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: &BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

impl Mul<BitBoard> for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn mul(self, other: BitBoard) -> BitBoard {
        BitBoard(self.0.wrapping_mul(other.0))
    }
}

// Impl Not
impl Not for BitBoard {
    type Output = BitBoard;

    #[inline]
    fn not(self) -> BitBoard {
        BitBoard(!self.0)
    }
}

impl Not for &BitBoard {
    type Output = BitBoard;

    #[inline]
    fn not(self) -> BitBoard {
        BitBoard(!self.0)
    }
}

impl fmt::Display for BitBoard {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s: String = "".to_owned();
        for x in 0..64 {
            if self.0 & (1u64 << x) == (1u64 << x) {
                s.push_str("X ");
            } else {
                s.push_str(". ");
            }
            if x % 8 == 7 {
                s.push_str("\n");
            }
        }
        write!(f, "{}", s)
    }
}

impl BitBoard {
    /// Construct a new bitboard from a u64
    #[inline]
    pub fn new(b: u64) -> BitBoard {
        BitBoard(b)
    }

    /// Construct a new `BitBoard` with a particular `Square` set
    #[inline]
    pub fn set(rank: Rank, file: File) -> BitBoard {
        BitBoard::from_square(Square::make_square(rank, file))
    }

    /// Construct a new `BitBoard` with a particular `Square` set
    #[inline]
    pub fn from_square(sq: Square) -> BitBoard {
        BitBoard(1u64 << sq.to_int())
    }

    /// Convert an `Option<Square>` to an `Option<BitBoard>`
    #[inline]
    pub fn from_maybe_square(sq: Option<Square>) -> Option<BitBoard> {
        sq.map(|s| BitBoard::from_square(s))
    }

    /// Convert a `BitBoard` to a `Square`.  This grabs the least-significant `Square`
    #[inline]
    pub fn to_square(&self) -> Square {
        unsafe { Square::new(self.0.trailing_zeros() as u8) }
    }

    /// Count the number of `Squares` set in this `BitBoard`
    #[inline]
    pub fn popcnt(&self) -> u32 {
        self.0.count_ones()
    }

    /// Reverse this `BitBoard`.  Look at it from the opponents perspective.
    #[inline]
    pub fn reverse_colors(&self) -> BitBoard {
        BitBoard(self.0.swap_bytes())
    }

    /// Convert this `BitBoard` to a `usize` (for table lookups)
    #[inline]
    pub fn to_size(&self, rightshift: u8) -> usize {
        (self.0 >> rightshift) as usize
    }
}

/// For the `BitBoard`, iterate over every `Square` set.
impl Iterator for BitBoard {
    type Item = Square;

    #[inline]
    fn next(&mut self) -> Option<Square> {
        if self.0 == 0 {
            None
        } else {
            let result = self.to_square();
            *self ^= BitBoard::from_square(result);
            Some(result)
        }
    }
}
<|endoftext|>


<commit_before>//! Generated messages reflection support.

use std::collections::HashMap;
use std::fmt;
use std::marker;

use crate::descriptor::FileDescriptorProto;
use crate::message_dyn::MessageDyn;
use crate::message_full::MessageFull;
use crate::reflect::acc::FieldAccessor;
use crate::reflect::file::index::FileIndex;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;

/// Sized to dynamic reflection operations.
pub(crate) trait MessageFactory: Send + Sync + 'static {
    fn new_instance(&self) -> Box<dyn MessageDyn>;
    fn default_instance(&self) -> &dyn MessageDyn;
    fn clone(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn>;
    fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool;
}

impl<'a> fmt::Debug for &'a dyn MessageFactory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageFactory").finish()
    }
}

/// The only message factory implementation.
pub(crate) struct MessageFactoryImpl<M>(pub marker::PhantomData<M>);

impl<M> MessageFactory for MessageFactoryImpl<M>
where
    M: 'static + MessageFull + Default + Clone + PartialEq,
{
    fn new_instance(&self) -> Box<dyn MessageDyn> {
        let m: M = Default::default();
        Box::new(m)
    }

    fn default_instance(&self) -> &dyn MessageDyn {
        M::default_instance() as &dyn MessageDyn
    }

    fn clone(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        let m: &M = message.downcast_ref().expect("wrong message type");
        Box::new(m.clone())
    }

    fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        let a: &M = a.downcast_ref().expect("wrong message type");
        let b: &M = b.downcast_ref().expect("wrong message type");
        a == b
    }
}

#[doc(hidden)]
pub struct GeneratedMessageDescriptorData {
    pub(crate) protobuf_name_to_package: &'static str,
    pub(crate) fields: Vec<FieldAccessor>,
    pub(crate) factory: &'static dyn MessageFactory,
}

impl GeneratedMessageDescriptorData {
    /// Construct a new message descriptor.
    ///
    /// This operation is called from generated code and rarely
    /// need to be called directly.
    ///
    /// This function is not a part of public API.
    #[doc(hidden)]
    pub fn new_2<M: MessageFull>(
        protobuf_name_to_package: &'static str,
        _index: u32,
        fields: Vec<FieldAccessor>,
    ) -> GeneratedMessageDescriptorData {
        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
        GeneratedMessageDescriptorData {
            protobuf_name_to_package,
            fields,
            factory,
        }
    }
}

#[derive(Debug)]
pub(crate) struct NonMapMessageDescriptor {
    pub(crate) factory: &'static dyn MessageFactory,

    pub(crate) fields: Vec<FieldAccessor>,
}

#[derive(Debug)]
pub(crate) struct GeneratedMessageDescriptor {
    pub non_map: Option<NonMapMessageDescriptor>,
}

impl GeneratedMessageDescriptor {
    pub fn new_map_entry() -> GeneratedMessageDescriptor {
        GeneratedMessageDescriptor { non_map: None }
    }

    pub(crate) fn new(
        data: GeneratedMessageDescriptorData,
        file_descriptor_proto: &'static FileDescriptorProto,
        _file_index: &FileIndex,
    ) -> crate::Result<GeneratedMessageDescriptor> {
        let GeneratedMessageDescriptorData {
            protobuf_name_to_package,
            fields,
            factory,
        } = data;

        let (_path_to_package, proto) =
            match find_message_or_enum(file_descriptor_proto, protobuf_name_to_package) {
                Some((path_to_package, MessageOrEnum::Message(m))) => (path_to_package, m),
                Some((_, MessageOrEnum::Enum(_))) => panic!("not a message"),
                None => panic!("not found"),
            };

        let mut field_proto_by_name = HashMap::new();
        for field_proto in &proto.field {
            field_proto_by_name.insert(field_proto.name(), field_proto);
        }

        Ok(GeneratedMessageDescriptor {
            non_map: Some(NonMapMessageDescriptor { factory, fields }),
        })
    }

    pub fn non_map(&self) -> &NonMapMessageDescriptor {
        match &self.non_map {
            Some(non_map) => non_map,
            None => panic!("map message"),
        }
    }
}
<commit_msg>Code cleanup<commit_after>//! Generated messages reflection support.

use std::collections::HashMap;
use std::fmt;
use std::marker;

use crate::descriptor::FileDescriptorProto;
use crate::message_dyn::MessageDyn;
use crate::message_full::MessageFull;
use crate::reflect::acc::FieldAccessor;
use crate::reflect::file::index::FileIndex;
use crate::reflect::find_message_or_enum::find_message_or_enum;
use crate::reflect::find_message_or_enum::MessageOrEnum;

/// Sized to dynamic reflection operations.
pub(crate) trait MessageFactory: Send + Sync + 'static {
    fn new_instance(&self) -> Box<dyn MessageDyn>;
    fn default_instance(&self) -> &dyn MessageDyn;
    fn clone(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn>;
    fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool;
}

impl<'a> fmt::Debug for &'a dyn MessageFactory {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageFactory").finish()
    }
}

/// The only message factory implementation.
pub(crate) struct MessageFactoryImpl<M>(pub marker::PhantomData<M>);

impl<M> MessageFactory for MessageFactoryImpl<M>
where
    M: 'static + MessageFull + Default + Clone + PartialEq,
{
    fn new_instance(&self) -> Box<dyn MessageDyn> {
        let m: M = Default::default();
        Box::new(m)
    }

    fn default_instance(&self) -> &dyn MessageDyn {
        M::default_instance() as &dyn MessageDyn
    }

    fn clone(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        let m: &M = message.downcast_ref().expect("wrong message type");
        Box::new(m.clone())
    }

    fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        let a: &M = a.downcast_ref().expect("wrong message type");
        let b: &M = b.downcast_ref().expect("wrong message type");
        a == b
    }
}

#[doc(hidden)]
pub struct GeneratedMessageDescriptorData {
    pub(crate) protobuf_name_to_package: &'static str,
    pub(crate) fields: Vec<FieldAccessor>,
    pub(crate) factory: &'static dyn MessageFactory,
}

impl GeneratedMessageDescriptorData {
    /// Construct a new message descriptor.
    ///
    /// This operation is called from generated code and rarely
    /// need to be called directly.
    ///
    /// This function is not a part of public API.
    #[doc(hidden)]
    pub fn new_2<M: MessageFull>(
        protobuf_name_to_package: &'static str,
        _index: u32,
        fields: Vec<FieldAccessor>,
    ) -> GeneratedMessageDescriptorData {
        let factory = &MessageFactoryImpl(marker::PhantomData::<M>);
        GeneratedMessageDescriptorData {
            protobuf_name_to_package,
            fields,
            factory,
        }
    }
}

#[derive(Debug)]
pub(crate) struct NonMapMessageDescriptor {
    pub(crate) factory: &'static dyn MessageFactory,

    pub(crate) fields: Vec<FieldAccessor>,
}

#[derive(Debug)]
pub(crate) struct GeneratedMessageDescriptor {
    pub(crate) non_map: Option<NonMapMessageDescriptor>,
}

impl GeneratedMessageDescriptor {
    pub(crate) fn new_map_entry() -> GeneratedMessageDescriptor {
        GeneratedMessageDescriptor { non_map: None }
    }

    pub(crate) fn new(
        data: GeneratedMessageDescriptorData,
        file_descriptor_proto: &'static FileDescriptorProto,
        _file_index: &FileIndex,
    ) -> crate::Result<GeneratedMessageDescriptor> {
        let GeneratedMessageDescriptorData {
            protobuf_name_to_package,
            fields,
            factory,
        } = data;

        let (_path_to_package, proto) =
            match find_message_or_enum(file_descriptor_proto, protobuf_name_to_package) {
                Some((path_to_package, MessageOrEnum::Message(m))) => (path_to_package, m),
                Some((_, MessageOrEnum::Enum(_))) => panic!("not a message"),
                None => panic!("not found"),
            };

        let mut field_proto_by_name = HashMap::new();
        for field_proto in &proto.field {
            field_proto_by_name.insert(field_proto.name(), field_proto);
        }

        Ok(GeneratedMessageDescriptor {
            non_map: Some(NonMapMessageDescriptor { factory, fields }),
        })
    }

    pub(crate) fn non_map(&self) -> &NonMapMessageDescriptor {
        match &self.non_map {
            Some(non_map) => non_map,
            None => panic!("map message"),
        }
    }
}
<|endoftext|>


<commit_before>use std::iter::repeat;

/// An I/O buffer with various convenience functions.  This is an internal
/// class, and the API is subject to change.
pub struct Buffer {
    /// Our data.
    buffer: Vec<u8>,
    /// The start of the unread data in the buffer.
    begin: usize,
    /// The end of the unread data in the buffer.
    end: usize
}

/// Regular Buffer interface.
impl Buffer {
    pub fn new(sz: usize) -> Buffer {
        Buffer{buffer: vec![0; sz], begin: 0, end: 0}
    }

    pub fn capacity(&self) -> usize { self.buffer.len() }
    pub fn buffered(&self) -> usize { self.end - self.begin }
    pub fn empty(&self) -> bool { self.buffered() == 0 }

    pub fn move_data_to_start(&mut self) {
        if self.begin > 0 {
            // TODO: Replace with a fast memmove routine.
            for i in 0..self.buffered() {
                self.buffer[i] = self.buffer[self.begin+i];
            }
            self.end = self.buffered();
            self.begin = 0;
        }
    }

    pub fn space_to_fill(&mut self) -> &mut [u8] {
        &mut self.buffer[self.end..]
    }

    pub fn set_data(&mut self, data: &[u8]) {
        // TODO: Replace with a memory copy routine.
        for i in 0..data.len() {
            self.buffer[i] = data[i];
        }
        self.begin = 0;
        self.end = data.len();
    }

    pub fn added(&mut self, bytes: usize) {
        self.end += bytes;
    }

    pub fn consume(&mut self, bytes: usize) -> &[u8] {
        let result = &self.buffer[self.begin..self.begin+bytes];
        self.begin += bytes;
        result
    }

    pub fn copy_out_and_consume(&mut self, bytes: usize, dest: &mut [u8]) {
        // TODO: Replace with a fast memcopy routine.
        for i in 0..bytes {
            dest[i] = self.buffer[self.begin+i];
        }
        self.begin += bytes;
    }

    pub fn add_capacity(&mut self, bytes: usize) {
        self.buffer.extend(repeat(0).take(bytes));
    }
}
<commit_msg>Use unsafe ptr::copy code for a major speedup<commit_after>use std::iter::repeat;
use std::ptr::{copy, copy_nonoverlapping};

/// An I/O buffer with various convenience functions.  This is an internal
/// class, and the API is subject to change.
pub struct Buffer {
    /// Our data.
    buffer: Vec<u8>,
    /// The start of the unread data in the buffer.
    begin: usize,
    /// The end of the unread data in the buffer.
    end: usize
}

/// Regular Buffer interface.
impl Buffer {
    pub fn new(sz: usize) -> Buffer {
        Buffer{buffer: vec![0; sz], begin: 0, end: 0}
    }

    pub fn capacity(&self) -> usize { self.buffer.len() }
    pub fn buffered(&self) -> usize { self.end - self.begin }
    pub fn empty(&self) -> bool { self.buffered() == 0 }

    pub fn move_data_to_start(&mut self) {
        if self.begin > 0 {
            unsafe {
                copy(self.buffer.as_ptr().offset(self.begin as isize),
                     self.buffer.as_mut_ptr(),
                     self.buffered());
            }
            self.end = self.buffered();
            self.begin = 0;
        }
    }

    pub fn space_to_fill(&mut self) -> &mut [u8] {
        &mut self.buffer[self.end..]
    }

    pub fn set_data(&mut self, data: &[u8]) {
        assert!(data.len() <= self.buffer.len());
        unsafe {
            // HOTSPOT: Slow copies here have a drastic impact on performance.
            copy_nonoverlapping(data.as_ptr(),
                                self.buffer.as_mut_ptr(),
                                data.len());
        }
        self.begin = 0;
        self.end = data.len();
    }

    pub fn added(&mut self, bytes: usize) {
        self.end += bytes;
    }

    pub fn consume(&mut self, bytes: usize) -> &[u8] {
        let result = &self.buffer[self.begin..self.begin+bytes];
        self.begin += bytes;
        result
    }

    pub fn copy_out_and_consume(&mut self, bytes: usize, dest: &mut [u8]) {
        assert!(bytes <= dest.len());
        unsafe {
            // HOTSPOT: Slow copies here have a drastic impact on performance.
            copy_nonoverlapping(self.buffer.as_ptr().offset(self.begin as isize),
                                dest.as_mut_ptr(),
                                bytes);
        }
        self.begin += bytes;
    }

    pub fn add_capacity(&mut self, bytes: usize) {
        self.buffer.extend(repeat(0).take(bytes));
    }
}
<|endoftext|>


<commit_before>use std::{fmt, cmp};

mod tests;

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

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.rank, self.suit)
    }
}

impl cmp::Ord for Card {
    fn cmp(&self, other: &Card) -> cmp::Ordering {
        self.rank.cmp(&other.rank)
    }
}

impl cmp::Eq for Card { }

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

impl Card {
    pub fn new(rank: Rank, suit: Suit) -> Card {
        Card {
            rank: rank,
            suit: suit
        }
    }

    pub fn get_id(&self) -> i64 {
        ((1 as i64) << ((self.suit as i64) * 13 + (self.rank as i64))) as i64
    }
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace
}

impl fmt::Display for Rank {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let value = match *self {
            Rank::Two      =>  "2",
            Rank::Three    =>  "3",
            Rank::Four     =>  "4",
            Rank::Five     =>  "5",
            Rank::Six      =>  "6",
            Rank::Seven    =>  "7",
            Rank::Eight    =>  "8",
            Rank::Nine     =>  "9",
            Rank::Ten      =>  "T",
            Rank::Jack     =>  "J",
            Rank::Queen    =>  "Q",
            Rank::King     =>  "K",
            Rank::Ace      =>  "A"
        };
        write!(f, "{}", value)
    }
}

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

impl fmt::Display for Suit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let suit = match *self {
            Suit::Diamonds  =>  "♢",
            Suit::Clubs     =>  "♣",
            Suit::Hearts    =>  "♡",
            Suit::Spades    =>  "♠"
        };
        write!(f, "{}", suit)
    }
}

impl Suit {
    pub fn get_suit_mask(suit: Suit) -> i64 {
        (0b1111111111111 << (suit as u32)) as i64
    }
}
<commit_msg>Now using Suit as i64<commit_after>use std::{fmt, cmp};

mod tests;

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

impl fmt::Display for Card {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}{}", self.rank, self.suit)
    }
}

impl cmp::Ord for Card {
    fn cmp(&self, other: &Card) -> cmp::Ordering {
        self.rank.cmp(&other.rank)
    }
}

impl cmp::Eq for Card { }

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

impl Card {
    pub fn new(rank: Rank, suit: Suit) -> Card {
        Card {
            rank: rank,
            suit: suit
        }
    }

    pub fn get_id(&self) -> i64 {
        ((1 as i64) << ((self.suit as i64) * 13 + (self.rank as i64))) as i64
    }
}

#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
pub enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace
}

impl fmt::Display for Rank {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let value = match *self {
            Rank::Two      =>  "2",
            Rank::Three    =>  "3",
            Rank::Four     =>  "4",
            Rank::Five     =>  "5",
            Rank::Six      =>  "6",
            Rank::Seven    =>  "7",
            Rank::Eight    =>  "8",
            Rank::Nine     =>  "9",
            Rank::Ten      =>  "T",
            Rank::Jack     =>  "J",
            Rank::Queen    =>  "Q",
            Rank::King     =>  "K",
            Rank::Ace      =>  "A"
        };
        write!(f, "{}", value)
    }
}

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

impl fmt::Display for Suit {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let suit = match *self {
            Suit::Diamonds  =>  "♢",
            Suit::Clubs     =>  "♣",
            Suit::Hearts    =>  "♡",
            Suit::Spades    =>  "♠"
        };
        write!(f, "{}", suit)
    }
}

impl Suit {
    pub fn get_suit_mask(suit: Suit) -> i64 {
        (0b1111111111111 << (suit as i64)) as i64
    }
}
<|endoftext|>


<commit_before>    //   Copyright 2014 Colin Sherratt
//
//   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.

#![crate_name = "snowmew-render-gfx"]
#![crate_type = "lib"]

#![feature(phase)]
#![allow(dead_code)]

//extern crate debug;

extern crate sync;
extern crate time;
extern crate libc;

extern crate opencl;
extern crate cow;
extern crate glfw;

#[phase(plugin)]
extern crate gfx_macros;
extern crate gfx;
extern crate device;
extern crate render;
extern crate genmesh;

extern crate snowmew  = "snowmew-core";
extern crate position = "snowmew-position";
extern crate graphics = "snowmew-graphics";
extern crate render_data = "snowmew-render-data";

use std::collections::hashmap::HashMap;

use opencl::hl;
use sync::Arc;

use position::Positions;
use graphics::Graphics;
use snowmew::common::ObjectKey;
use snowmew::io::Window;

use graphics::geometry::{Geo, GeoTex, GeoNorm, GeoTexNorm, GeoTexNormTan};
use graphics::geometry::{VertexGeoTex, VertexGeoTexNorm};
use graphics::Drawable;

use cow::join::{join_set_to_map, join_maps};
use render_data::RenderData;

use gfx::{Device, DeviceHelper};

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform mat4 proj_mat;
    uniform mat4 view_mat;
    uniform mat4 model_mat;

    in vec3 position;
    in vec2 texture;

    out vec2 o_texture;

    void main() {
        gl_Position = proj_mat * view_mat * model_mat * vec4(position, 1.0);
        o_texture = texture;
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform vec4 ka_color;
    uniform int ka_use_texture;
    uniform sampler2D ka_texture;

    in vec2 o_texture;

    out vec4 o_Color;

    void main() {
        if (1 == ka_use_texture) {
            o_Color = texture(ka_texture, o_texture);
        } else {
            o_Color = ka_color;
        }
    }
"
};

#[shader_param(MyProgram)]
struct Params {
    proj_mat: [[f32, ..4], ..4],
    view_mat: [[f32, ..4], ..4],
    model_mat: [[f32, ..4], ..4],
    ka_color: [f32, ..4],
    ka_use_texture: i32,
    ka_texture: gfx::shade::TextureParam,
}

struct Mesh {
    mesh: render::mesh::Mesh,
    index: device::BufferHandle<u32>
}

pub struct RenderManager {
    data: Params,
    graphics: gfx::Graphics<device::gl_device::GlDevice,
                            device::gl_device::GlCommandBuffer>,
    frame: render::target::Frame,
    state: render::state::DrawState,
    prog: device::Handle<u32,device::shade::ProgramInfo>,
    meshes: HashMap<ObjectKey, Mesh>,
    textures: HashMap<ObjectKey, device::TextureHandle>,
    sampler: device::SamplerHandle,
    window: Window
}

impl RenderManager {

    fn _new(mut device: gfx::GlDevice,
            window: Window,
            size: (i32, i32),
            _: Option<Arc<hl::Device>>) -> RenderManager {

        let (width, height) = size;
        let frame = gfx::Frame::new(width as u16, height as u16);
        let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

        let sampler = device.create_sampler(
            gfx::tex::SamplerInfo::new(
                    gfx::tex::Bilinear, gfx::tex::Tile
            )
        );

        let (prog, data) = {
            let tinfo = gfx::tex::TextureInfo {
                width: 1,
                height: 1,
                depth: 1,
                levels: 1,
                kind: gfx::tex::Texture2D,
                format: gfx::tex::RGBA8,
            };

            let img_info = tinfo.to_image_info();
            let dummy_texture = device.create_texture(tinfo)
                                      .ok().expect("Failed to create texture");
            device.update_texture(&dummy_texture,
                                  &img_info,
                                  &vec![0u8, 0, 0, 0].as_slice());

            let data = Params {
                proj_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                view_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                model_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                ka_use_texture: 0,
                ka_color: [1., 1., 1., 1.],
                ka_texture: (dummy_texture, Some(sampler))
            };
            (device.link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
                  .ok().expect("Failed to link program"),
             data)
        };

        RenderManager {
            data: data,
            graphics: gfx::Graphics::new(device),
            frame: frame,
            state: state,
            prog: prog,
            meshes: HashMap::new(),
            textures: HashMap::new(),
            sampler: sampler,
            window: window
        }
    }

    fn load_meshes<RD: RenderData>(&mut self, db: &RD) {
        for (oid, vb) in db.vertex_buffer_iter() {
            if self.meshes.find(oid).is_none() {
                let mesh = match vb.vertex {
                    Geo(ref d) => {
                        println!("Geo");
                        let data: Vec<VertexGeoTex> = d.iter()
                            .map(|v| {
                                VertexGeoTex {
                                    position: v.position,
                                    texture: [0., 0.]
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTex(ref d) => {
                        println!("GeoTex");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoNorm(ref d) => {
                        let data: Vec<VertexGeoTexNorm> = d.iter()
                            .map(|v| {
                                VertexGeoTexNorm {
                                    position: v.position,
                                    texture: [0., 0.],
                                    normal: v.normal
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTexNorm(ref d) => {
                        println!("GeoTexNorm");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoTexNormTan(ref d) => {
                        println!("GeoTexNormTan");
                        self.graphics.device.create_mesh(d.clone())
                    }
                };

                let vb: Vec<u32> = vb.index.iter().map(|&x| x as u32).collect();

                let index = self.graphics.device.create_buffer_static(&vb);

                self.meshes.insert(*oid, Mesh {
                    index: index,
                    mesh: mesh
                });
            }
        }
    }

    fn load_textures<RD: RenderData>(&mut self, db: &RD) {
        for (oid, text) in db.texture_iter() {
            if self.textures.find(oid).is_none() {
                let tinfo = gfx::tex::TextureInfo {
                    width: text.width() as u16,
                    height: text.height() as u16,
                    depth: 1 as u16,
                    levels: 1,
                    kind: gfx::tex::Texture2D,
                    format: match text.depth() {
                        4 => gfx::tex::Unsigned(gfx::tex::RGBA, 8, gfx::attrib::IntNormalized),
                        3 => gfx::tex::Unsigned(gfx::tex::RGB, 8, gfx::attrib::IntNormalized),
                        _ => fail!("Unsupported color depth")
                    }
                };

                let img_info = tinfo.to_image_info();
                let texture = self.graphics.device.create_texture(tinfo)
                                         .ok().expect("Failed to create texture");
                self.graphics.device.update_texture(&texture, &img_info, &text.data().to_vec());
                self.textures.insert(*oid, texture);
            }
        }
    }

    fn create_geometry_batches<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey) -> HashMap<u32, MyProgram> {
        let mut batches: HashMap<u32, MyProgram> = HashMap::new();

        for (_, draw) in join_set_to_map(db.scene_iter(scene), db.drawable_iter()) {
            if batches.contains_key(&draw.geometry) {
                continue;
            }

            let geo = db.geometry(draw.geometry).expect("failed to find geometry");
            let vb = self.meshes.find(&geo.vb).expect("Could not get vertex buffer");

            let batch: MyProgram = self.graphics.make_batch(
                &self.prog,
                &vb.mesh,
                gfx::IndexSlice32(gfx::TriangleList,
                                  vb.index,
                                  geo.offset as u32,
                                  geo.count as u32),
                &self.state
            ).unwrap();

            batches.insert(draw.geometry, batch);
        }

        return batches;
    }

    fn draw<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey, camera: ObjectKey) {
        let cdata = gfx::ClearData {
            color: Some([0.3, 0.3, 0.3, 1.0]),
            depth: Some(1.0),
            stencil: None,
        };
        let start = time::precise_time_s();
        self.graphics.clear(cdata, &self.frame);

        let camera_trans = db.position(camera);
        let camera = snowmew::camera::Camera::new(camera_trans);

        let proj = camera.projection_matrix(16. / 9.);
        self.data.proj_mat =
            [[proj.x.x, proj.x.y, proj.x.z, proj.x.w],
             [proj.y.x, proj.y.y, proj.y.z, proj.y.w],
             [proj.z.x, proj.z.y, proj.z.z, proj.z.w],
             [proj.w.x, proj.w.y, proj.w.z, proj.w.w]];

        let view = camera.view_matrix();
        self.data.view_mat =
            [[view.x.x, view.x.y, view.x.z, view.x.w],
             [view.y.x, view.y.y, view.y.z, view.y.w],
             [view.z.x, view.z.y, view.z.z, view.z.w],
             [view.w.x, view.w.y, view.w.z, view.w.w]];

        let batches = self.create_geometry_batches(db, scene);

        for (id, (draw, _)) in join_set_to_map(db.scene_iter(scene),
                                               join_maps(db.drawable_iter(),
                                                         db.location_iter())) {

            let mat = db.material(draw.material).expect("Could not find material");
            let model = db.position(*id);

            self.data.model_mat =
                [[model.x.x, model.x.y, model.x.z, model.x.w],
                 [model.y.x, model.y.y, model.y.z, model.y.w],
                 [model.z.x, model.z.y, model.z.z, model.z.w],
                 [model.w.x, model.w.y, model.w.z, model.w.w]];

            self.data.ka_use_texture = match mat.map_ka() {
                Some(tid) => {
                    let &texture = self.textures.find(&tid).expect("Texture not loaded");
                    self.data.ka_texture = (texture, Some(self.sampler));
                    1
                }
                None => {
                    let [r, g, b] = mat.ka();
                    self.data.ka_color = [r, g, b, 1.];
                    0
                }
            };

            self.graphics.draw(
                batches.find(&draw.geometry).expect("Missing draw"),
                &self.data,
                &self.frame
            );
        }

        self.graphics.end_frame();
        self.window.swap_buffers();
        let end = time::precise_time_s();
        println!("{0:4.3}ms", (end - start) * 1000.);
    }
}

impl<RD: RenderData+Send> snowmew::Render<RD> for RenderManager {
    fn update(&mut self, db: RD, scene: ObjectKey, camera: ObjectKey) {
        self.load_meshes(&db);
        self.load_textures(&db);
        self.draw(&db, scene, camera);
    }
}

impl<RD: RenderData+Send> snowmew::RenderFactory<RD, RenderManager> for RenderFactory {
    fn init(self: Box<RenderFactory>,
            io: &snowmew::IOManager,
            window: Window,
            size: (i32, i32),
            cl: Option<Arc<hl::Device>>) -> RenderManager {

        window.make_context_current();

        let mut device = gfx::GlDevice::new(|s| io.get_proc_address(s));
        RenderManager::_new(device, window, size, cl)
    }
}

pub struct RenderFactory;

impl RenderFactory {
    pub fn new() -> RenderFactory { RenderFactory }
}<commit_msg>Update render-gfx<commit_after>    //   Copyright 2014 Colin Sherratt
//
//   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.

#![crate_name = "snowmew-render-gfx"]
#![crate_type = "lib"]

#![feature(phase)]
#![allow(dead_code)]

//extern crate debug;

extern crate sync;
extern crate time;
extern crate libc;

extern crate opencl;
extern crate cow;
extern crate glfw;

#[phase(plugin)]
extern crate gfx_macros;
extern crate gfx;
extern crate device;
extern crate render;
extern crate genmesh;

extern crate snowmew  = "snowmew-core";
extern crate position = "snowmew-position";
extern crate graphics = "snowmew-graphics";
extern crate render_data = "snowmew-render-data";

use std::collections::hashmap::HashMap;

use opencl::hl;
use sync::Arc;

use position::Positions;
use graphics::Graphics;
use snowmew::common::ObjectKey;
use snowmew::io::Window;

use graphics::geometry::{Geo, GeoTex, GeoNorm, GeoTexNorm, GeoTexNormTan};
use graphics::geometry::{VertexGeoTex, VertexGeoTexNorm};
use graphics::Drawable;

use cow::join::{join_set_to_map, join_maps};
use render_data::RenderData;

use gfx::{Device, DeviceHelper};

static VERTEX_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform mat4 proj_mat;
    uniform mat4 view_mat;
    uniform mat4 model_mat;

    in vec3 position;
    in vec2 texture;

    out vec2 o_texture;

    void main() {
        gl_Position = proj_mat * view_mat * model_mat * vec4(position, 1.0);
        o_texture = texture;
    }
"
};

static FRAGMENT_SRC: gfx::ShaderSource = shaders! {
GLSL_150: b"
    #version 150 core
    uniform vec4 ka_color;
    uniform int ka_use_texture;
    uniform sampler2D ka_texture;

    in vec2 o_texture;

    out vec4 o_Color;

    void main() {
        if (1 == ka_use_texture) {
            o_Color = texture(ka_texture, o_texture);
        } else {
            o_Color = ka_color;
        }
    }
"
};

#[shader_param(MyProgram)]
struct Params {
    proj_mat: [[f32, ..4], ..4],
    view_mat: [[f32, ..4], ..4],
    model_mat: [[f32, ..4], ..4],
    ka_color: [f32, ..4],
    ka_use_texture: i32,
    ka_texture: gfx::shade::TextureParam,
}

struct Mesh {
    mesh: render::mesh::Mesh,
    index: device::BufferHandle<u32>
}

pub struct RenderManager {
    data: Params,
    graphics: gfx::Graphics<device::gl_device::GlDevice,
                            device::gl_device::GlCommandBuffer>,
    frame: render::target::Frame,
    state: render::state::DrawState,
    prog: device::Handle<u32,device::shade::ProgramInfo>,
    meshes: HashMap<ObjectKey, Mesh>,
    textures: HashMap<ObjectKey, device::TextureHandle>,
    sampler: device::SamplerHandle,
    window: Window
}

impl RenderManager {

    fn _new(mut device: gfx::GlDevice,
            window: Window,
            size: (i32, i32),
            _: Option<Arc<hl::Device>>) -> RenderManager {

        let (width, height) = size;
        let frame = gfx::Frame::new(width as u16, height as u16);
        let state = gfx::DrawState::new().depth(gfx::state::LessEqual, true);

        let sampler = device.create_sampler(
            gfx::tex::SamplerInfo::new(
                    gfx::tex::Bilinear, gfx::tex::Tile
            )
        );

        let (prog, data) = {
            let tinfo = gfx::tex::TextureInfo {
                width: 1,
                height: 1,
                depth: 1,
                levels: 1,
                kind: gfx::tex::Texture2D,
                format: gfx::tex::RGBA8,
            };

            let img_info = tinfo.to_image_info();
            let dummy_texture = device.create_texture(tinfo)
                                      .ok().expect("Failed to create texture");
            device.update_texture(&dummy_texture,
                                  &img_info,
                                  &vec![0u8, 0, 0, 0].as_slice());

            let data = Params {
                proj_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                view_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                model_mat: [
                    [1.0, 0.0, 0.0, 0.0],
                    [0.0, 1.0, 0.0, 0.0],
                    [0.0, 0.0, 1.0, 0.0],
                    [0.0, 0.0, 0.0, 1.0],
                ],
                ka_use_texture: 0,
                ka_color: [1., 1., 1., 1.],
                ka_texture: (dummy_texture, Some(sampler))
            };
            (device.link_program(VERTEX_SRC.clone(), FRAGMENT_SRC.clone())
                  .ok().expect("Failed to link program"),
             data)
        };

        RenderManager {
            data: data,
            graphics: gfx::Graphics::new(device),
            frame: frame,
            state: state,
            prog: prog,
            meshes: HashMap::new(),
            textures: HashMap::new(),
            sampler: sampler,
            window: window
        }
    }

    fn load_meshes<RD: RenderData>(&mut self, db: &RD) {
        for (oid, vb) in db.vertex_buffer_iter() {
            if self.meshes.find(oid).is_none() {
                let mesh = match vb.vertex {
                    Geo(ref d) => {
                        println!("Geo");
                        let data: Vec<VertexGeoTex> = d.iter()
                            .map(|v| {
                                VertexGeoTex {
                                    position: v.position,
                                    texture: [0., 0.]
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTex(ref d) => {
                        println!("GeoTex");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoNorm(ref d) => {
                        let data: Vec<VertexGeoTexNorm> = d.iter()
                            .map(|v| {
                                VertexGeoTexNorm {
                                    position: v.position,
                                    texture: [0., 0.],
                                    normal: v.normal
                                }
                            })
                            .collect();
                        self.graphics.device.create_mesh(data)
                    },
                    GeoTexNorm(ref d) => {
                        println!("GeoTexNorm");
                        self.graphics.device.create_mesh(d.clone())
                    },
                    GeoTexNormTan(ref d) => {
                        println!("GeoTexNormTan");
                        self.graphics.device.create_mesh(d.clone())
                    }
                };

                let vb: Vec<u32> = vb.index.iter().map(|&x| x as u32).collect();

                let index = self.graphics.device.create_buffer_static(&vb);

                self.meshes.insert(*oid, Mesh {
                    index: index,
                    mesh: mesh
                });
            }
        }
    }

    fn load_textures<RD: RenderData>(&mut self, db: &RD) {
        for (oid, text) in db.texture_iter() {
            if self.textures.find(oid).is_none() {
                let tinfo = gfx::tex::TextureInfo {
                    width: text.width() as u16,
                    height: text.height() as u16,
                    depth: 1 as u16,
                    levels: 1,
                    kind: gfx::tex::Texture2D,
                    format: match text.depth() {
                        4 => gfx::tex::Unsigned(gfx::tex::RGBA, 8, gfx::attrib::IntNormalized),
                        3 => gfx::tex::Unsigned(gfx::tex::RGB, 8, gfx::attrib::IntNormalized),
                        _ => fail!("Unsupported color depth")
                    }
                };

                let img_info = tinfo.to_image_info();
                let texture = self.graphics.device.create_texture(tinfo)
                                         .ok().expect("Failed to create texture");
                self.graphics.device.update_texture(&texture, &img_info, &text.data().to_vec());
                self.textures.insert(*oid, texture);
            }
        }
    }

    fn create_geometry_batches<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey) -> HashMap<u32, MyProgram> {
        let mut batches: HashMap<u32, MyProgram> = HashMap::new();

        for (_, draw) in join_set_to_map(db.scene_iter(scene), db.drawable_iter()) {
            if batches.contains_key(&draw.geometry) {
                continue;
            }

            let geo = db.geometry(draw.geometry).expect("failed to find geometry");
            let vb = self.meshes.find(&geo.vb).expect("Could not get vertex buffer");

            let batch: MyProgram = self.graphics.make_batch(
                &self.prog,
                &vb.mesh,
                gfx::IndexSlice32(gfx::TriangleList,
                                  vb.index,
                                  geo.offset as u32,
                                  geo.count as u32),
                &self.state
            ).unwrap();

            batches.insert(draw.geometry, batch);
        }

        return batches;
    }

    fn draw<RD: RenderData>(&mut self, db: &RD, scene: ObjectKey, camera: ObjectKey) {
        let cdata = gfx::ClearData {
            color: [0.3, 0.3, 0.3, 1.0],
            depth: 1.0,
            stencil: 0,
        };
        let start = time::precise_time_s();
        self.graphics.clear(cdata, gfx::Color | gfx::Depth, &self.frame);

        let camera_trans = db.position(camera);
        let camera = snowmew::camera::Camera::new(camera_trans);

        let proj = camera.projection_matrix(16. / 9.);
        self.data.proj_mat =
            [[proj.x.x, proj.x.y, proj.x.z, proj.x.w],
             [proj.y.x, proj.y.y, proj.y.z, proj.y.w],
             [proj.z.x, proj.z.y, proj.z.z, proj.z.w],
             [proj.w.x, proj.w.y, proj.w.z, proj.w.w]];

        let view = camera.view_matrix();
        self.data.view_mat =
            [[view.x.x, view.x.y, view.x.z, view.x.w],
             [view.y.x, view.y.y, view.y.z, view.y.w],
             [view.z.x, view.z.y, view.z.z, view.z.w],
             [view.w.x, view.w.y, view.w.z, view.w.w]];

        let batches = self.create_geometry_batches(db, scene);

        for (id, (draw, _)) in join_set_to_map(db.scene_iter(scene),
                                               join_maps(db.drawable_iter(),
                                                         db.location_iter())) {

            let mat = db.material(draw.material).expect("Could not find material");
            let model = db.position(*id);

            self.data.model_mat =
                [[model.x.x, model.x.y, model.x.z, model.x.w],
                 [model.y.x, model.y.y, model.y.z, model.y.w],
                 [model.z.x, model.z.y, model.z.z, model.z.w],
                 [model.w.x, model.w.y, model.w.z, model.w.w]];

            self.data.ka_use_texture = match mat.map_ka() {
                Some(tid) => {
                    let &texture = self.textures.find(&tid).expect("Texture not loaded");
                    self.data.ka_texture = (texture, Some(self.sampler));
                    1
                }
                None => {
                    let [r, g, b] = mat.ka();
                    self.data.ka_color = [r, g, b, 1.];
                    0
                }
            };

            self.graphics.draw(
                batches.find(&draw.geometry).expect("Missing draw"),
                &self.data,
                &self.frame
            );
        }

        self.graphics.end_frame();
        self.window.swap_buffers();
        let end = time::precise_time_s();
        println!("{0:4.3}ms", (end - start) * 1000.);
    }
}

impl<RD: RenderData+Send> snowmew::Render<RD> for RenderManager {
    fn update(&mut self, db: RD, scene: ObjectKey, camera: ObjectKey) {
        self.load_meshes(&db);
        self.load_textures(&db);
        self.draw(&db, scene, camera);
    }
}

impl<RD: RenderData+Send> snowmew::RenderFactory<RD, RenderManager> for RenderFactory {
    fn init(self: Box<RenderFactory>,
            io: &snowmew::IOManager,
            window: Window,
            size: (i32, i32),
            cl: Option<Arc<hl::Device>>) -> RenderManager {

        window.make_context_current();

        let mut device = gfx::GlDevice::new(|s| io.get_proc_address(s));
        RenderManager::_new(device, window, size, cl)
    }
}

pub struct RenderFactory;

impl RenderFactory {
    pub fn new() -> RenderFactory { RenderFactory }
}<|endoftext|>


<commit_before>use std::io::process::Command;
use std::thread::Thread;
use config::Config;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;

pub enum Cmd {
  Exec(String),
  SwitchWorkspace(uint),
  SwitchScreen(uint),
  MoveToWorkspace(uint),
  MoveToScreen(uint),
  KillClient,
  FocusUp,
  FocusDown,
  FocusMaster,
  SwapUp,
  SwapDown,
  SwapMaster,
}

impl Cmd {
  pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config) {
    match *self {
      Cmd::Exec(ref cmd) => {
        debug!("Cmd::Exec: {}", cmd);
        exec(cmd.clone());
      },
      Cmd::SwitchWorkspace(index) => {
        debug!("Cmd::SwitchWorkspace: {}", index);
        workspaces.switch_to(ws, config, index - 1);
      },
      Cmd::SwitchScreen(screen) => {
        debug!("Cmd::SwitchScreen: {}", screen);
        workspaces.switch_to_screen(ws, config, screen - 1);
      },
      Cmd::MoveToWorkspace(index) => {
        debug!("Cmd::MoveToWorkspace: {}", index);
        workspaces.move_window_to(ws, config, index - 1);
      },
      Cmd::MoveToScreen(screen) => {
        debug!("Cmd::MoveToScreen: {}", screen);
        workspaces.move_window_to_screen(ws, config, screen - 1);
      }
      Cmd::KillClient => {
        let focused_window = workspaces.current_mut().focused_window();
        debug!("Cmd::KillClient: {}", focused_window);
        ws.kill_window(focused_window);
      },
      Cmd::FocusUp => {
        debug!("Cmd::FocusUp: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
      },
      Cmd::FocusDown => {
        debug!("Cmd::FocusDown: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
      },
      Cmd::FocusMaster => {
        debug!("Cmd::FocusMaster: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
      },
      Cmd::SwapUp => {
        debug!("Cmd::SwapUp: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Up);
      },
      Cmd::SwapDown => {
        debug!("Cmd::SwapDown: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Down);
      },
      Cmd::SwapMaster => {
        debug!("Cmd::SwapMaster: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
      }
    }
  }
}

pub struct ManageHook {
  pub class_name: String,
  pub cmd: CmdManage
}

pub enum CmdManage {
  Move(uint),
  Float,
  Fullscreen,
  Ignore
}

impl CmdManage {
  pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config, window: Window) {
    match *self {
      CmdManage::Move(index) => {
        debug!("CmdManage::Move: {}, {}", window, index - 1);
        workspaces.get_mut(index - 1).add_window(ws, config, window);
        workspaces.get_mut(index - 1).focus_window(ws, config, window);
      },
      CmdManage::Float => {
        debug!("CmdManage::Float");
        unimplemented!()
      },
      CmdManage::Fullscreen => {
        debug!("CmdManage::Fullscreen");
        unimplemented!()
      },
      CmdManage::Ignore => {
        debug!("CmdManage::Ignore");
        unimplemented!()
      }
    }
  }
}

pub enum LogInfo {
  Workspaces(Vec<String>, uint, Vec<uint>),
  Title(String),
  Layout(String)
}

pub struct LogHook<'a> {
  pub logs: Vec<CmdLogHook>,
  pub output: |Vec<LogInfo>|:'a -> String
}

impl<'a> LogHook<'a> {
  pub fn call(&mut self, ws: &XlibWindowSystem, workspaces: &Workspaces) {
    println!("{}", (self.output)(self.logs.iter().map(|x| x.call(ws, workspaces)).collect()));
  }
}

pub enum CmdLogHook {
  Workspaces,
  Title,
  Layout
}

impl CmdLogHook {
  pub fn call(&self, ws: &XlibWindowSystem, workspaces: &Workspaces) -> LogInfo {
    match *self {
      CmdLogHook::Workspaces => {
        LogInfo::Workspaces(workspaces.all().iter().map(|x| x.get_tag()).collect(), workspaces.get_index(), Vec::new())
      },
      CmdLogHook::Title => {
        LogInfo::Title(ws.get_window_title(workspaces.current().focused_window()))
      },
      CmdLogHook::Layout => {
        LogInfo::Layout(workspaces.current().get_layout().name())
      }
    }
  }
}

fn exec(cmd: String) {
  Thread::spawn(move || {
    let args : Vec<&str> = cmd.as_slice().split(' ').collect();

    if args.len() > 0 {
      let mut cmd = Command::new(args[0]);

      if args.len() > 1 {
        cmd.args(args.as_slice().slice_from(1));
      }

      match cmd.detached().spawn() {
        Ok(_) => (),
        _ => panic!("failed to start \"{}\"", cmd)
      }
    }

  }).detach();
}
<commit_msg>fixed thread lifetime problems #14<commit_after>use std::io::process::Command;
use std::thread::Thread;
use config::Config;
use xlib_window_system::XlibWindowSystem;
use workspaces::{Workspaces, MoveOp};
use xlib::Window;

pub enum Cmd {
  Exec(String),
  SwitchWorkspace(uint),
  SwitchScreen(uint),
  MoveToWorkspace(uint),
  MoveToScreen(uint),
  KillClient,
  FocusUp,
  FocusDown,
  FocusMaster,
  SwapUp,
  SwapDown,
  SwapMaster,
}

impl Cmd {
  pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config) {
    match *self {
      Cmd::Exec(ref cmd) => {
        debug!("Cmd::Exec: {}", cmd);
        exec(cmd.clone());
      },
      Cmd::SwitchWorkspace(index) => {
        debug!("Cmd::SwitchWorkspace: {}", index);
        workspaces.switch_to(ws, config, index - 1);
      },
      Cmd::SwitchScreen(screen) => {
        debug!("Cmd::SwitchScreen: {}", screen);
        workspaces.switch_to_screen(ws, config, screen - 1);
      },
      Cmd::MoveToWorkspace(index) => {
        debug!("Cmd::MoveToWorkspace: {}", index);
        workspaces.move_window_to(ws, config, index - 1);
      },
      Cmd::MoveToScreen(screen) => {
        debug!("Cmd::MoveToScreen: {}", screen);
        workspaces.move_window_to_screen(ws, config, screen - 1);
      }
      Cmd::KillClient => {
        let focused_window = workspaces.current_mut().focused_window();
        debug!("Cmd::KillClient: {}", focused_window);
        ws.kill_window(focused_window);
      },
      Cmd::FocusUp => {
        debug!("Cmd::FocusUp: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Up);
      },
      Cmd::FocusDown => {
        debug!("Cmd::FocusDown: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Down);
      },
      Cmd::FocusMaster => {
        debug!("Cmd::FocusMaster: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_focus(ws, config, MoveOp::Swap);
      },
      Cmd::SwapUp => {
        debug!("Cmd::SwapUp: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Up);
      },
      Cmd::SwapDown => {
        debug!("Cmd::SwapDown: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Down);
      },
      Cmd::SwapMaster => {
        debug!("Cmd::SwapMaster: {}", workspaces.current_mut().focused_window());
        workspaces.current_mut().move_window(ws, config, MoveOp::Swap);
      }
    }
  }
}

pub struct ManageHook {
  pub class_name: String,
  pub cmd: CmdManage
}

pub enum CmdManage {
  Move(uint),
  Float,
  Fullscreen,
  Ignore
}

impl CmdManage {
  pub fn call(&self, ws: &XlibWindowSystem, workspaces: &mut Workspaces, config: &Config, window: Window) {
    match *self {
      CmdManage::Move(index) => {
        debug!("CmdManage::Move: {}, {}", window, index - 1);
        workspaces.get_mut(index - 1).add_window(ws, config, window);
        workspaces.get_mut(index - 1).focus_window(ws, config, window);
      },
      CmdManage::Float => {
        debug!("CmdManage::Float");
        unimplemented!()
      },
      CmdManage::Fullscreen => {
        debug!("CmdManage::Fullscreen");
        unimplemented!()
      },
      CmdManage::Ignore => {
        debug!("CmdManage::Ignore");
        unimplemented!()
      }
    }
  }
}

pub enum LogInfo {
  Workspaces(Vec<String>, uint, Vec<uint>),
  Title(String),
  Layout(String)
}

pub struct LogHook<'a> {
  pub logs: Vec<CmdLogHook>,
  pub output: |Vec<LogInfo>|:'a -> String
}

impl<'a> LogHook<'a> {
  pub fn call(&mut self, ws: &XlibWindowSystem, workspaces: &Workspaces) {
    println!("{}", (self.output)(self.logs.iter().map(|x| x.call(ws, workspaces)).collect()));
  }
}

pub enum CmdLogHook {
  Workspaces,
  Title,
  Layout
}

impl CmdLogHook {
  pub fn call(&self, ws: &XlibWindowSystem, workspaces: &Workspaces) -> LogInfo {
    match *self {
      CmdLogHook::Workspaces => {
        LogInfo::Workspaces(workspaces.all().iter().map(|x| x.get_tag()).collect(), workspaces.get_index(), Vec::new())
      },
      CmdLogHook::Title => {
        LogInfo::Title(ws.get_window_title(workspaces.current().focused_window()))
      },
      CmdLogHook::Layout => {
        LogInfo::Layout(workspaces.current().get_layout().name())
      }
    }
  }
}

fn exec(cmd: String) {
  Thread::spawn(move || {
    let args : Vec<&str> = cmd.as_slice().split(' ').collect();

    if args.len() > 0 {
      let mut cmd = Command::new(args[0]);

      if args.len() > 1 {
        cmd.args(args.as_slice().slice_from(1));
      }

      match cmd.detached().output() {
        Ok(_) => (),
        _ => panic!("failed to start \"{}\"", cmd)
      }
    }
  }).detach();
}
<|endoftext|>