<commit_before>use std::{mem, ptr, int};
use alloc::heap;
use token::Token;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    mem: *mut Entry<T>,
    // Number of elements currently in the slab
    len: int,
    // The total number of elements that the slab can hold
    cap: int,
    // THe token offset
    off: uint,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: int,
    // The total number of slots that were initialized
    init: int,
}

const MAX: uint = int::MAX as uint;

// When Entry.nxt is set to this, the entry is in use
const IN_USE: int = -1;

impl<T> Slab<T> {
    pub fn new(cap: uint) -> Slab<T> {
        Slab::new_starting_at(Token(0), cap)
    }

    pub fn new_starting_at(offset: Token, cap: uint) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Rename to with_capacity
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than uint::MAX

        let size = cap.checked_mul(&mem::size_of::<Entry<T>>())
            .expect("capacity overflow");

        let ptr = unsafe { heap::allocate(size, mem::min_align_of::<Entry<T>>()) };

        Slab {
            mem: ptr as *mut Entry<T>,
            cap: cap as int,
            len: 0,
            off: offset.as_uint(),
            nxt: 0,
            init: 0,
        }
    }

    #[inline]
    pub fn count(&self) -> uint {
        self.len as uint
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    pub fn remaining(&self) -> uint {
        (self.cap - self.len) as uint
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    #[inline]
    pub fn contains(&self, idx: uint) -> bool {
        if idx <= MAX {
            let idx = idx as int;

            if idx < self.init {
                return self.entry(idx).in_use();
            }
        }

        false
    }

    pub fn get(&self, idx: Token) -> Option<&T> {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as int;

            if idx < self.init {
                let entry = self.entry(idx);

                if entry.in_use() {
                    return Some(&entry.val);
                }
            }
        }

        None
    }

    pub fn insert(&mut self, val: T) -> Result<Token, T> {
        let idx = self.nxt;

        if idx == self.init {
            // Using an uninitialized entry
            if idx == self.cap {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.cap);
                return Err(val);
            }

            self.mut_entry(idx).put(val, true);

            self.init += 1;
            self.len = self.init;
            self.nxt = self.init;

            debug!("inserting into new slot; idx={}", idx);
        }
        else {
            self.len += 1;
            self.nxt = self.mut_entry(idx).put(val, false);

            debug!("inserting into reused slot; idx={}", idx);
        }

        Ok(self.idx_to_token(idx))
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: Token) -> Option<T> {
        debug!("removing value; idx={}", idx);

        // Cast to uint
        let idx = self.token_to_idx(idx);

        if idx > MAX {
            return None;
        }

        let idx = idx as int;

        // Ensure index is within capacity of slab
        if idx >= self.init {
            return None;
        }

        let nxt = self.nxt;

        match self.mut_entry(idx).remove(nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    #[inline]
    fn entry(&self, idx: int) -> &Entry<T> {
        unsafe { &*self.mem.offset(idx) }
    }

    #[inline]
    fn mut_entry(&mut self, idx: int) -> &mut Entry<T> {
        unsafe { &mut *self.mem.offset(idx) }
    }

    #[inline]
    fn validate_idx(&self, idx: uint) -> int {
        if idx <= MAX {
            let idx = idx as int;

            if idx < self.init {
                return idx;
            }
        }

        panic!("invalid index {} -- greater than capacity {}", idx, self.cap);
    }

    fn token_to_idx(&self, token: Token) -> uint {
        token.as_uint() - self.off
    }

    fn idx_to_token(&self, idx: int) -> Token {
        Token(idx as uint + self.off)
    }
}

impl<T> Index<Token, T> for Slab<T> {
    fn index<'a>(&'a self, idx: &Token) -> &'a T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &e.val
    }
}

impl<T> IndexMut<Token, T> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: &Token) -> &'a mut T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.mut_entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &mut e.val
    }
}

#[unsafe_destructor]
impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        // TODO: check whether or not this is needed with intrinsics::needs_drop
        let mut i = 0;

        while i < self.init {
            self.mut_entry(i).release();
            i += 1;
        }
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: int,
    val: T
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T, init: bool) -> int {
        assert!(init || self.nxt != IN_USE);

        let ret = self.nxt;

        unsafe { ptr::write(&mut self.val as *mut T, val); }
        self.nxt = IN_USE;

        // Could be uninitialized memory, but the caller (Slab) should guard
        // not use the return value in those cases.
        ret
    }

    fn remove(&mut self, nxt: int) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            Some(unsafe { ptr::read(&self.val as *const T) })
        } else {
            None
        }
    }

    fn release(&mut self) {
        if self.in_use() {
            let _ = Some(unsafe { ptr::read(&self.val as *const T) });
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.nxt == IN_USE
    }
}

#[cfg(test)]
mod tests {
    use super::Slab;
    use {Token};

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10u).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10u);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10u);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10u);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10u).ok().expect("Failed to insert");
        slab.insert(10u).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10u).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20u).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20u);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(slab[t1].as_slice(), "foobar");
    }

    #[test]
    #[should_fail]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();
        let t1 = slab.insert(456u).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();

        assert!(slab[t0] == 123u);
        assert!(slab.remove(t0) == Some(123u));

        let t0 = slab.insert(456u).unwrap();

        assert!(slab[t0] == 456u);

        let t1 = slab.insert(789u).unwrap();

        assert!(slab[t0] == 456u);
        assert!(slab[t1] == 789u);

        assert!(slab.remove(t0).unwrap() == 456u);
        assert!(slab.remove(t1).unwrap() == 789u);

        assert!(slab.count() == 0);
    }

    #[test]
    #[should_fail]
    fn test_accessing_out_of_bounds() {
        let slab = Slab::<uint>::new(16);
        slab[Token(0)];
    }
}
<commit_msg>[fix] Slab.contains()<commit_after>use std::{mem, ptr, int};
use alloc::heap;
use token::Token;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    mem: *mut Entry<T>,
    // Number of elements currently in the slab
    len: int,
    // The total number of elements that the slab can hold
    cap: int,
    // THe token offset
    off: uint,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: int,
    // The total number of slots that were initialized
    init: int,
}

const MAX: uint = int::MAX as uint;

// When Entry.nxt is set to this, the entry is in use
const IN_USE: int = -1;

impl<T> Slab<T> {
    pub fn new(cap: uint) -> Slab<T> {
        Slab::new_starting_at(Token(0), cap)
    }

    pub fn new_starting_at(offset: Token, cap: uint) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Rename to with_capacity
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than uint::MAX

        let size = cap.checked_mul(&mem::size_of::<Entry<T>>())
            .expect("capacity overflow");

        let ptr = unsafe { heap::allocate(size, mem::min_align_of::<Entry<T>>()) };

        Slab {
            mem: ptr as *mut Entry<T>,
            cap: cap as int,
            len: 0,
            off: offset.as_uint(),
            nxt: 0,
            init: 0,
        }
    }

    #[inline]
    pub fn count(&self) -> uint {
        self.len as uint
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    #[inline]
    pub fn remaining(&self) -> uint {
        (self.cap - self.len) as uint
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    #[inline]
    pub fn contains(&self, idx: Token) -> bool {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as int;

            if idx < self.init {
                return self.entry(idx).in_use();
            }
        }

        false
    }

    pub fn get(&self, idx: Token) -> Option<&T> {
        let idx = self.token_to_idx(idx);

        if idx <= MAX {
            let idx = idx as int;

            if idx < self.init {
                let entry = self.entry(idx);

                if entry.in_use() {
                    return Some(&entry.val);
                }
            }
        }

        None
    }

    pub fn insert(&mut self, val: T) -> Result<Token, T> {
        let idx = self.nxt;

        if idx == self.init {
            // Using an uninitialized entry
            if idx == self.cap {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.cap);
                return Err(val);
            }

            self.mut_entry(idx).put(val, true);

            self.init += 1;
            self.len = self.init;
            self.nxt = self.init;

            debug!("inserting into new slot; idx={}", idx);
        }
        else {
            self.len += 1;
            self.nxt = self.mut_entry(idx).put(val, false);

            debug!("inserting into reused slot; idx={}", idx);
        }

        Ok(self.idx_to_token(idx))
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: Token) -> Option<T> {
        debug!("removing value; idx={}", idx);

        // Cast to uint
        let idx = self.token_to_idx(idx);

        if idx > MAX {
            return None;
        }

        let idx = idx as int;

        // Ensure index is within capacity of slab
        if idx >= self.init {
            return None;
        }

        let nxt = self.nxt;

        match self.mut_entry(idx).remove(nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    #[inline]
    fn entry(&self, idx: int) -> &Entry<T> {
        unsafe { &*self.mem.offset(idx) }
    }

    #[inline]
    fn mut_entry(&mut self, idx: int) -> &mut Entry<T> {
        unsafe { &mut *self.mem.offset(idx) }
    }

    #[inline]
    fn validate_idx(&self, idx: uint) -> int {
        if idx <= MAX {
            let idx = idx as int;

            if idx < self.init {
                return idx;
            }
        }

        panic!("invalid index {} -- greater than capacity {}", idx, self.cap);
    }

    fn token_to_idx(&self, token: Token) -> uint {
        token.as_uint() - self.off
    }

    fn idx_to_token(&self, idx: int) -> Token {
        Token(idx as uint + self.off)
    }
}

impl<T> Index<Token, T> for Slab<T> {
    fn index<'a>(&'a self, idx: &Token) -> &'a T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &e.val
    }
}

impl<T> IndexMut<Token, T> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: &Token) -> &'a mut T {
        let idx = self.token_to_idx(*idx);
        let idx = self.validate_idx(idx);

        let e = self.mut_entry(idx);

        if !e.in_use() {
            panic!("invalid index; idx={}", idx);
        }

        &mut e.val
    }
}

#[unsafe_destructor]
impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        // TODO: check whether or not this is needed with intrinsics::needs_drop
        let mut i = 0;

        while i < self.init {
            self.mut_entry(i).release();
            i += 1;
        }
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: int,
    val: T
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T, init: bool) -> int {
        assert!(init || self.nxt != IN_USE);

        let ret = self.nxt;

        unsafe { ptr::write(&mut self.val as *mut T, val); }
        self.nxt = IN_USE;

        // Could be uninitialized memory, but the caller (Slab) should guard
        // not use the return value in those cases.
        ret
    }

    fn remove(&mut self, nxt: int) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            Some(unsafe { ptr::read(&self.val as *const T) })
        } else {
            None
        }
    }

    fn release(&mut self) {
        if self.in_use() {
            let _ = Some(unsafe { ptr::read(&self.val as *const T) });
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.nxt == IN_USE
    }
}

#[cfg(test)]
mod tests {
    use super::Slab;
    use {Token};

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10u).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10u);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10u);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10u);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10u).ok().expect("Failed to insert");
        slab.insert(10u).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10u).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20u).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20u);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(slab[t1].as_slice(), "foobar");
    }

    #[test]
    #[should_fail]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();
        let t1 = slab.insert(456u).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();

        assert!(slab[t0] == 123u);
        assert!(slab.remove(t0) == Some(123u));

        let t0 = slab.insert(456u).unwrap();

        assert!(slab[t0] == 456u);

        let t1 = slab.insert(789u).unwrap();

        assert!(slab[t0] == 456u);
        assert!(slab[t1] == 789u);

        assert!(slab.remove(t0).unwrap() == 456u);
        assert!(slab.remove(t1).unwrap() == 789u);

        assert!(slab.count() == 0);
    }

    #[test]
    #[should_fail]
    fn test_accessing_out_of_bounds() {
        let slab = Slab::<uint>::new(16);
        slab[Token(0)];
    }
}
<|endoftext|>


<commit_before>use libc::c_void;

/// Celix status code.
pub type celix_status_t = isize;
/// Successfully executed function.
pub const CELIX_SUCCESS: celix_status_t = 0;
/// Failed to start the bundle.
pub const CELIX_START_ERROR: celix_status_t = 70000;
/// Pointer to a context.
pub type bundle_context_pt = *mut c_void;

#[macro_export]
macro_rules! manifest {
	($key:ident = $val:expr, $($cont:expr),+) => (
		pub static $key: &'static str = stringify!($val);
		manifest!($($cont),+)
	);
	($key:ident = $val:expr) => (
		pub static $key: &'static str = stringify!($val);
		//println!("{} = {}", stringify!($key), stringify!($val));
	)
}<commit_msg>Removed temporary shim<commit_after><|endoftext|>


<commit_before>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Common utilities.

mod text;
pub use self::text::{Text, TextSlice, TextIterator, IntoTextIterator, trim_newline};

mod nonnanfloat;
pub use self::nonnanfloat::NonNaNFloat;

mod interval;
pub use self::interval::{Interval, IntervalError};

/// Strand information.
#[derive(Debug, Clone, Copy)]
pub enum Strand {
    Forward,
    Reverse,
    Unknown,
}

impl PartialEq for Strand {
    /// Returns true if both are `Forward` or both are `Reverse`, otherwise returns false.
    fn eq(&self, other: &Strand) -> bool {
        match (self, other) {
            (&Strand::Forward, &Strand::Forward) => true,
            (&Strand::Reverse, &Strand::Reverse) => true,
            _ => false
        }
    }
}

impl Strand {

    /// Returns a `Strand` enum representing the given char.
    ///
    /// The mapping is as follows:
    ///     * '+', 'f', or 'F' becomes `Strand::Forward`
    ///     * '-', 'r', or 'R' becomes `Strand::Forward`
    ///     * '.', '?' becomes `Strand::Forward`
    ///     * Any other inputs will return an `Err(Error::InvalidStrandChar)`
    pub fn from_char(strand_char: &char) -> Result<Strand, Error> {
        match *strand_char {
            '+' | 'f' | 'F' => Ok(Strand::Forward),
            '-' | 'r' | 'R' => Ok(Strand::Reverse),
            '.' | '?'  => Ok(Strand::Unknown),
            invalid => Err(Error::InvalidStrandChar(invalid)),
        }
    }

    pub fn is_unknown(&self) -> bool {
        match self {
            &Strand::Unknown => true,
            _ => false,
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidStrandChar(invalid_char: char) {
            description("invalid character for strand conversion")
            display("character {:?} can not be converted to a Strand", invalid_char)
        }
    }
}

/// In place implementation of scan over a slice.
pub fn scan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], op: F) {
    let mut s = a[0];
    for v in a.iter_mut().skip(1) {
        s = op(s, *v);
        *v = s;
    }
}

// Inplace implementation of prescan over a slice.
pub fn prescan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], neutral: T, op: F) {
    let mut s = neutral;
    for v in a.iter_mut() {
        let t = *v;
        *v = s;
        s = op(s, t);
    }
}

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

    #[test]
    fn test_scan() {
        let mut a = vec![1, 0, 0, 1];
        scan(&mut a[..], |a, b| a + b);
        assert_eq!(a, vec![1, 1, 1, 2]);
    }

    #[test]
    fn test_prescan() {
        let mut a = vec![1, 0, 0, 1];
        prescan(&mut a[..], 0, |a, b| a + b);
        assert_eq!(a, vec![0, 1, 1, 1]);
    }

    #[test]
    fn test_strand() {
        assert_eq!(Strand::from_char(&'+').unwrap(), Strand::Forward);
        assert_eq!(Strand::from_char(&'-').unwrap(), Strand::Reverse);
        assert!(Strand::from_char(&'.').unwrap().is_unknown());
        assert!(Strand::from_char(&'o').is_err());
    }
}
<commit_msg>Fix from_char docs<commit_after>// Copyright 2014-2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Common utilities.

mod text;
pub use self::text::{Text, TextSlice, TextIterator, IntoTextIterator, trim_newline};

mod nonnanfloat;
pub use self::nonnanfloat::NonNaNFloat;

mod interval;
pub use self::interval::{Interval, IntervalError};

/// Strand information.
#[derive(Debug, Clone, Copy)]
pub enum Strand {
    Forward,
    Reverse,
    Unknown,
}

impl PartialEq for Strand {
    /// Returns true if both are `Forward` or both are `Reverse`, otherwise returns false.
    fn eq(&self, other: &Strand) -> bool {
        match (self, other) {
            (&Strand::Forward, &Strand::Forward) => true,
            (&Strand::Reverse, &Strand::Reverse) => true,
            _ => false
        }
    }
}

impl Strand {

    /// Returns a `Strand` enum representing the given char.
    ///
    /// The mapping is as follows:
    ///     * '+', 'f', or 'F' becomes `Strand::Forward`
    ///     * '-', 'r', or 'R' becomes `Strand::Reverse`
    ///     * '.', '?' becomes `Strand::Unknown`
    ///     * Any other inputs will return an `Err(Error::InvalidStrandChar)`
    pub fn from_char(strand_char: &char) -> Result<Strand, Error> {
        match *strand_char {
            '+' | 'f' | 'F' => Ok(Strand::Forward),
            '-' | 'r' | 'R' => Ok(Strand::Reverse),
            '.' | '?'  => Ok(Strand::Unknown),
            invalid => Err(Error::InvalidStrandChar(invalid)),
        }
    }

    pub fn is_unknown(&self) -> bool {
        match self {
            &Strand::Unknown => true,
            _ => false,
        }
    }
}

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        InvalidStrandChar(invalid_char: char) {
            description("invalid character for strand conversion")
            display("character {:?} can not be converted to a Strand", invalid_char)
        }
    }
}

/// In place implementation of scan over a slice.
pub fn scan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], op: F) {
    let mut s = a[0];
    for v in a.iter_mut().skip(1) {
        s = op(s, *v);
        *v = s;
    }
}

// Inplace implementation of prescan over a slice.
pub fn prescan<T: Copy, F: Fn(T, T) -> T>(a: &mut [T], neutral: T, op: F) {
    let mut s = neutral;
    for v in a.iter_mut() {
        let t = *v;
        *v = s;
        s = op(s, t);
    }
}

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

    #[test]
    fn test_scan() {
        let mut a = vec![1, 0, 0, 1];
        scan(&mut a[..], |a, b| a + b);
        assert_eq!(a, vec![1, 1, 1, 2]);
    }

    #[test]
    fn test_prescan() {
        let mut a = vec![1, 0, 0, 1];
        prescan(&mut a[..], 0, |a, b| a + b);
        assert_eq!(a, vec![0, 1, 1, 1]);
    }

    #[test]
    fn test_strand() {
        assert_eq!(Strand::from_char(&'+').unwrap(), Strand::Forward);
        assert_eq!(Strand::from_char(&'-').unwrap(), Strand::Reverse);
        assert!(Strand::from_char(&'.').unwrap().is_unknown());
        assert!(Strand::from_char(&'o').is_err());
    }
}
<|endoftext|>


<commit_before>// This file is part of the uutils coreutils package.
//
// (c) Joseph Crail <jbcrail@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

#[cfg(unix)]
use super::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind};
use std::io::Result as IOResult;
use std::path::{Component, Path, PathBuf};
#[cfg(unix)]
use std::borrow::Cow;

pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> {
    if path.components().all(|e| e != Component::ParentDir) {
        return path.into();
    }
    let root = Component::RootDir.as_os_str();
    let mut result = env::current_dir().unwrap_or(PathBuf::from(root));
    for comp in path.components() {
        match comp {
            Component::ParentDir => {
                result.pop();
            }
            Component::CurDir => (),
            Component::RootDir |
            Component::Normal(_) |
            Component::Prefix(_) => result.push(comp.as_os_str()),
        }
    }
    result.into()
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> IOResult<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::symlink_metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    }
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> IOResult<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec![];

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) |
            Component::RootDir => {
                result.push(part.as_os_str());
            }
            Component::CurDir => (),
            Component::ParentDir => {
                parts.pop();
            }
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if !parts.is_empty() {
        for part in parts[..parts.len() - 1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => {
                    match can_mode {
                        CanonicalizeMode::Missing => continue,
                        _ => return Err(e),
                    }
                }
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => {
                if can_mode == CanonicalizeMode::Existing {
                    return Err(e);
                }
            }
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<commit_msg>uucore: read symlinked directories correctly in resolve_relative_path()<commit_after>// This file is part of the uutils coreutils package.
//
// (c) Joseph Crail <jbcrail@gmail.com>
// (c) Jian Zeng <anonymousknight96 AT gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

#[cfg(unix)]
use super::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind};
use std::io::Result as IOResult;
use std::path::{Component, Path, PathBuf};
#[cfg(unix)]
use std::borrow::Cow;

pub fn resolve_relative_path<'a>(path: &'a Path) -> Cow<'a, Path> {
    if path.components().all(|e| e != Component::ParentDir) {
        return path.into();
    }
    let root = Component::RootDir.as_os_str();
    let mut result = env::current_dir().unwrap_or(PathBuf::from(root));
    for comp in path.components() {
        match comp {
            Component::ParentDir => {
                if let Ok(p) = result.read_link() {
                    result = p;
                }
                result.pop();
            }
            Component::CurDir => (),
            Component::RootDir |
            Component::Normal(_) |
            Component::Prefix(_) => result.push(comp.as_os_str()),
        }
    }
    result.into()
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> IOResult<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::symlink_metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    }
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> IOResult<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec![];

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) |
            Component::RootDir => {
                result.push(part.as_os_str());
            }
            Component::CurDir => (),
            Component::ParentDir => {
                parts.pop();
            }
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if !parts.is_empty() {
        for part in parts[..parts.len() - 1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => {
                    match can_mode {
                        CanonicalizeMode::Missing => continue,
                        _ => return Err(e),
                    }
                }
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => {
                if can_mode == CanonicalizeMode::Existing {
                    return Err(e);
                }
            }
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<|endoftext|>


<commit_before>use std::ops::{Add, Mul};

use cgmath::prelude::*;
use cgmath::vec3;
use image;

use math::*;

#[derive(Debug)]
pub struct Color {
    inner: Vector,
}

impl Color {
    pub fn new(inner: Vector) -> Color {
        Color { inner: inner }
    }

    pub fn rgb(r: f32, g: f32, b: f32) -> Color {
        Color::new(vec3(r, g, b))
    }

    pub fn from_bytes(r: u8, g: u8, b: u8) -> Color {
        Color::rgb((r as f32) / 255.0, (g as f32) / 255.0, (b as f32) / 255.0)
    }

    pub fn from_u32(color: u32) -> Color {
        let r = (color >> 24) as u8;
        let g = (color >> 16) as u8;
        let b = (color >> 8) as u8;

        Color::from_bytes(r, g, b)
    }

    pub fn into_pixel(self) -> image::Rgb<u8> {
        image::Rgb([convert_component(self.inner.x),
                    convert_component(self.inner.y),
                    convert_component(self.inner.z)])
    }
}

impl Add for Color {
    type Output = Color;

    fn add(self, rhs: Self) -> Self::Output {
        Color { inner: self.inner.add_element_wise(rhs.inner) }
    }
}

impl Mul for Color {
    type Output = Color;

    fn mul(self, rhs: Self) -> Self::Output {
        Color { inner: self.inner.mul_element_wise(rhs.inner) }
    }
}

impl Mul<f32> for Color {
    type Output = Color;

    fn mul(self, rhs: f32) -> Self::Output {
        Color { inner: self.inner * rhs }
    }
}

impl From<Vector> for Color {
    fn from(vector: Vector) -> Self {
        Color::new(vector)
    }
}

impl Into<Vector> for Color {
    fn into(self) -> Vector {
        self.inner
    }
}

fn convert_component(component: f32) -> u8 {
    map_range(clamp(component, 0.0, 1.0), 0.0..1.0, 0.0..255.0) as u8
}
<commit_msg>Use  where possible<commit_after>use std::ops::{Add, Mul};

use cgmath::prelude::*;
use cgmath::vec3;
use image;

use math::*;

#[derive(Debug)]
pub struct Color {
    inner: Vector,
}

impl Color {
    pub fn new(inner: Vector) -> Self {
        Color { inner: inner }
    }

    pub fn rgb(r: f32, g: f32, b: f32) -> Self {
        Color::new(vec3(r, g, b))
    }

    pub fn from_bytes(r: u8, g: u8, b: u8) -> Self {
        Color::rgb((r as f32) / 255.0, (g as f32) / 255.0, (b as f32) / 255.0)
    }

    pub fn from_u32(color: u32) -> Self {
        let r = (color >> 24) as u8;
        let g = (color >> 16) as u8;
        let b = (color >> 8) as u8;

        Color::from_bytes(r, g, b)
    }

    pub fn into_pixel(self) -> image::Rgb<u8> {
        image::Rgb([convert_component(self.inner.x),
                    convert_component(self.inner.y),
                    convert_component(self.inner.z)])
    }
}

impl Add for Color {
    type Output = Color;

    fn add(self, rhs: Self) -> Self::Output {
        Color { inner: self.inner.add_element_wise(rhs.inner) }
    }
}

impl Mul for Color {
    type Output = Color;

    fn mul(self, rhs: Self) -> Self::Output {
        Color { inner: self.inner.mul_element_wise(rhs.inner) }
    }
}

impl Mul<f32> for Color {
    type Output = Color;

    fn mul(self, rhs: f32) -> Self::Output {
        Color { inner: self.inner * rhs }
    }
}

impl From<Vector> for Color {
    fn from(vector: Vector) -> Self {
        Color::new(vector)
    }
}

impl Into<Vector> for Color {
    fn into(self) -> Vector {
        self.inner
    }
}

fn convert_component(component: f32) -> u8 {
    map_range(clamp(component, 0.0, 1.0), 0.0..1.0, 0.0..255.0) as u8
}
<|endoftext|>


<commit_before>use bson;
use client::wire_protocol::flags::OpQueryFlags;
use client::wire_protocol::operations::Message;
use std::collections::vec_deque::VecDeque;
use std::io::{Read, Write};

/// Maintains a connection to the server and lazily returns documents from a
/// query.
///
/// # Fields
///
/// `request_id` - Uniquely identifies the request being sent.
/// `namespace` - The full qualified name of the collection,
///                          beginning with the database name and a period.
/// `batch_size` - How many documents to fetch at a given time from the server.
/// `cursor_id` - Uniquely identifies the cursor being returned by the reply.
pub struct Cursor<'a, T> where T: Read + Write + 'a {
    request_id: i32,
    namespace: String,
    batch_size: i32,
    cursor_id: i64,
    buffer: VecDeque<bson::Document>,
    stream: &'a mut T,
}

impl <'a, T> Cursor<'a, T> where T: Read + Write + 'a {
    /// Gets the cursor id and BSON documents from a reply Message.
    ///
    /// # Arguments
    ///
    /// `message` - The reply message to get the documents from.
    ///
    /// # Return value.
    ///
    ///
    fn get_bson_and_cid_from_message(message: Message) -> Option<(VecDeque<bson::Document>, i64)> {
        match message {
            Message::OpReply { header: _, flags: _, cursor_id: cid,
                               starting_from: _, number_returned: _,
                               documents: docs } => {
                let mut v = VecDeque::new();

                for bson_doc in docs {
                    v.push_back(bson_doc);
                }

                Some((v, cid))
            },
            _ => None
        }
    }

    pub fn query_with_batch_size(stream: &'a mut T, batch_size: i32,
                                 request_id: i32, flags: OpQueryFlags,
                                 namespace: &str,
                                 number_to_skip: i32, number_to_return: i32,
                                 query: bson::Document,
                                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a, T>, String> {
        let result = Message::with_query(request_id, flags,
                                         namespace.to_owned(),
                                         number_to_skip, number_to_return,
                                         query, return_field_selector);

        let message = match result {
            Ok(m) => m,
            Err(s) => return Err(s)
        };

        match message.write(stream) {
            Ok(_) => (),
            Err(s) => return Err(s)
        };

        let reply  = match Message::read(stream) {
            Ok(m) => m,
            Err(s) => return Err(s)
        };

        match Cursor::<T>::get_bson_and_cid_from_message(reply) {
            Some((buf, cursor_id)) => Ok(Cursor {
                request_id: request_id,
                namespace: namespace.to_owned(),
                batch_size: batch_size,
                cursor_id: cursor_id,
                buffer: buf, stream: stream }),
            None => Err("Invalid resonse received".to_owned()),
        }
    }

    pub fn query(stream: &'a mut T, request_id: i32, flags: OpQueryFlags,
                 namespace: &str, number_to_skip: i32,
                 number_to_return: i32, query: bson::Document,
                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a, T>, String> {

        Cursor::query_with_batch_size(stream, 20, request_id, flags,
                                      namespace, number_to_skip,
                                      number_to_return, query,
                                      return_field_selector)
    }

    fn new_get_more_request(&mut self) -> Message {
        Message::with_get_more(self.request_id,
                               self.namespace.to_owned(),
                               self.batch_size, self.cursor_id)
    }

    fn next_from_stream(&mut self) -> Option<bson::Document> {
        let get_more = self.new_get_more_request();

        match get_more.write(&mut self.stream) {
            Ok(_) => (),
            Err(_) => return None
        };

        let reply = match Message::read(&mut self.stream) {
            Ok(m) => m,
            Err(_) => return None
        };

        match Cursor::<T>::get_bson_and_cid_from_message(reply) {
            Some((v, _)) => {
                self.buffer.extend(v);
                self.buffer.pop_front()
            },
            None => None
        }
    }

    pub fn next_n(&mut self, n: i32) -> Vec<bson::Document> {
        let mut vec = vec![];

        for _ in 0..n {
            let bson_option = self.next();

            match bson_option {
                Some(bson) => vec.push(bson),
                None => break
            };
        }

        vec
    }

    pub fn next_batch(&mut self) -> Vec<bson::Document> {
        let n = self.batch_size;

        self.next_n(n)
    }
}

impl <'a, T> Iterator for Cursor<'a, T> where T: Read + Write + 'a {
    type Item = bson::Document;

    fn next(&mut self) -> Option<bson::Document> {
        match self.buffer.pop_front() {
            Some(bson) => Some(bson),
            None => self.next_from_stream()
        }
    }
}
<commit_msg>fixed implementation of batch_size and limit<commit_after>use bson;
use client::wire_protocol::flags::OpQueryFlags;
use client::wire_protocol::operations::Message;
use std::collections::vec_deque::VecDeque;
use std::io::{Read, Write};

/// Maintains a connection to the server and lazily returns documents from a
/// query.
///
/// # Fields
///
/// `request_id` - Uniquely identifies the request being sent.
/// `namespace` - The full qualified name of the collection,
///                          beginning with the database name and a period.
/// `batch_size` - How many documents to fetch at a given time from the server.
/// `cursor_id` - Uniquely identifies the cursor being returned by the reply.
pub struct Cursor<'a, T> where T: Read + Write + 'a {
    request_id: i32,
    namespace: String,
    batch_size: i32,
    cursor_id: i64,
    limit: i32,
    count: i32,
    buffer: VecDeque<bson::Document>,
    stream: &'a mut T,
}

impl <'a, T> Cursor<'a, T> where T: Read + Write + 'a {
    /// Gets the cursor id and BSON documents from a reply Message.
    ///
    /// # Arguments
    ///
    /// `message` - The reply message to get the documents from.
    ///
    /// # Return value.
    ///
    ///
    fn get_bson_and_cid_from_message(message: Message) -> Option<(VecDeque<bson::Document>, i64)> {
        match message {
            Message::OpReply { header: _, flags: _, cursor_id: cid,
                               starting_from: _, number_returned: _,
                               documents: docs } => {
                let mut v = VecDeque::new();

                for bson_doc in docs {
                    v.push_back(bson_doc);
                }

                Some((v, cid))
            },
            _ => None
        }
    }

    pub fn query_with_batch_size(stream: &'a mut T, batch_size: i32,
                                 request_id: i32, flags: OpQueryFlags,
                                 namespace: &str,
                                 number_to_skip: i32, number_to_return: i32,
                                 query: bson::Document,
                                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a, T>, String> {
        let result = Message::with_query(request_id, flags,
                                         namespace.to_owned(),
                                         number_to_skip, batch_size,
                                         query, return_field_selector);

        let message = match result {
            Ok(m) => m,
            Err(s) => return Err(s)
        };

        match message.write(stream) {
            Ok(_) => (),
            Err(s) => return Err(s)
        };

        let reply  = match Message::read(stream) {
            Ok(m) => m,
            Err(s) => return Err(s)
        };

        match Cursor::<T>::get_bson_and_cid_from_message(reply) {
            Some((buf, cursor_id)) => Ok(Cursor {
                request_id: request_id,
                namespace: namespace.to_owned(),
                batch_size: batch_size,
                cursor_id: cursor_id,
                limit: number_to_return,
                count: 0,
                buffer: buf,
                stream: stream }),
            None => Err("Invalid resonse received".to_owned()),
        }
    }

    pub fn query(stream: &'a mut T, request_id: i32, flags: OpQueryFlags,
                 namespace: &str, number_to_skip: i32,
                 number_to_return: i32, query: bson::Document,
                 return_field_selector: Option<bson::Document>) -> Result<Cursor<'a, T>, String> {

        Cursor::query_with_batch_size(stream, 20, request_id, flags,
                                      namespace, number_to_skip,
                                      number_to_return, query,
                                      return_field_selector)
    }

    fn new_get_more_request(&mut self) -> Message {
        Message::with_get_more(self.request_id,
                               self.namespace.to_owned(),
                               self.batch_size, self.cursor_id)
    }

    fn next_from_stream(&mut self) -> Option<bson::Document> {
        let get_more = self.new_get_more_request();

        match get_more.write(&mut self.stream) {
            Ok(_) => (),
            Err(_) => return None
        };

        let reply = match Message::read(&mut self.stream) {
            Ok(m) => m,
            Err(_) => return None
        };

        match Cursor::<T>::get_bson_and_cid_from_message(reply) {
            Some((v, _)) => {
                self.buffer.extend(v);
                self.buffer.pop_front()
            },
            None => None
        }
    }

    pub fn next_n(&mut self, n: i32) -> Vec<bson::Document> {
        let mut vec = vec![];

        for _ in 0..n {
            let bson_option = self.next();

            match bson_option {
                Some(bson) => vec.push(bson),
                None => break
            };
        }

        vec
    }

    pub fn next_batch(&mut self) -> Vec<bson::Document> {
        let n = self.batch_size;

        self.next_n(n)
    }
}

impl <'a, T> Iterator for Cursor<'a, T> where T: Read + Write + 'a {
    type Item = bson::Document;

    fn next(&mut self) -> Option<bson::Document> {
        if self.limit != 0 && self.count >= self.limit {
            return None;
        }

        self.count += 1;

        match self.buffer.pop_front() {
            Some(bson) => Some(bson),
            None => self.next_from_stream()
        }
    }
}
<|endoftext|>


<commit_before>use rustc::hir;
use rustc::lint::*;
use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};

/// **What it does:** This lint checks for `+=` operations and similar
///
/// **Why is this bad?** Projects with many developers from languages without those operations
///                      may find them unreadable and not worth their weight
///
/// **Known problems:** None
///
/// **Example:**
/// ```
/// a += 1;
/// ```
declare_restriction_lint! {
    pub ASSIGN_OPS,
    "Any assignment operation"
}

/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns
///
/// **Why is this bad?** These can be written as the shorter `a op= b`
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
///
/// ```
/// let mut a = 5;
/// ...
/// a = a + b;
/// ```
declare_lint! {
    pub ASSIGN_OP_PATTERN,
    Warn,
    "assigning the result of an operation on a variable to that same variable"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN)
    }
}

impl LateLintPass for AssignOps {
    fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
        match expr.node {
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) {
                    span_lint_and_then(cx,
                                       ASSIGN_OPS,
                                       expr.span,
                                       "assign operation detected",
                                       |db| {
                                           match rhs.node {
                                               hir::ExprBinary(op2, _, _) if op2 != op => {
                                                   db.span_suggestion(expr.span,
                                                                       "replace it with",
                                                                       format!("{} = {} {} ({})", l, l, op.node.as_str(), r));
                                               },
                                               _ => {
                                                   db.span_suggestion(expr.span,
                                                                       "replace it with",
                                                                       format!("{} = {} {} {}", l, l, op.node.as_str(), r));
                                               }
                                           }
                                       });
                } else {
                    span_lint(cx,
                              ASSIGN_OPS,
                              expr.span,
                              "assign operation detected");
                }
            },
            hir::ExprAssign(ref assignee, ref e) => {
                if let hir::ExprBinary(op, ref l, ref r) = e.node {
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tcx.expr_ty(assignee);
                        if ty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        let rty = cx.tcx.expr_ty(rhs);
                        if rty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        macro_rules! ops {
                            ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => {
                                match $op {
                                    $(hir::$full_trait_name => {
                                        let [krate, module] = ::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        implements_trait($cx, $ty, trait_id, vec![$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(op.node, cx, ty, rty, Add:BiAdd,
                                                      Sub:BiSub,
                                                      Mul:BiMul,
                                                      Div:BiDiv,
                                                      Rem:BiRem,
                                                      And:BiAnd,
                                                      Or:BiOr,
                                                      BitAnd:BiBitAnd,
                                                      BitOr:BiBitOr,
                                                      BitXor:BiBitXor,
                                                      Shr:BiShr,
                                                      Shl:BiShl
                        ) {
                            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
                                span_lint_and_then(cx,
                                                   ASSIGN_OP_PATTERN,
                                                   expr.span,
                                                   "manual implementation of an assign operation",
                                                   |db| {
                                                       db.span_suggestion(expr.span,
                                                                           "replace it with",
                                                                           format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
                                                   });
                            } else {
                                span_lint(cx,
                                          ASSIGN_OP_PATTERN,
                                          expr.span,
                                          "manual implementation of an assign operation");
                            }
                        }
                    };
                    // a = a op b
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                        lint(assignee, r);
                    }
                    // a = b commutative_op a
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
                        match op.node {
                            hir::BiAdd | hir::BiMul |
                            hir::BiAnd | hir::BiOr |
                            hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => {
                                lint(assignee, l);
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }
}
<commit_msg>add known problems<commit_after>use rustc::hir;
use rustc::lint::*;
use utils::{span_lint_and_then, span_lint, snippet_opt, SpanlessEq, get_trait_def_id, implements_trait};

/// **What it does:** This lint checks for `+=` operations and similar
///
/// **Why is this bad?** Projects with many developers from languages without those operations
///                      may find them unreadable and not worth their weight
///
/// **Known problems:** Types implementing `OpAssign` don't necessarily implement `Op`
///
/// **Example:**
/// ```
/// a += 1;
/// ```
declare_restriction_lint! {
    pub ASSIGN_OPS,
    "Any assignment operation"
}

/// **What it does:** Check for `a = a op b` or `a = b commutative_op a` patterns
///
/// **Why is this bad?** These can be written as the shorter `a op= b`
///
/// **Known problems:** While forbidden by the spec, `OpAssign` traits may have implementations that differ from the regular `Op` impl
///
/// **Example:**
///
/// ```
/// let mut a = 5;
/// ...
/// a = a + b;
/// ```
declare_lint! {
    pub ASSIGN_OP_PATTERN,
    Warn,
    "assigning the result of an operation on a variable to that same variable"
}

#[derive(Copy, Clone, Default)]
pub struct AssignOps;

impl LintPass for AssignOps {
    fn get_lints(&self) -> LintArray {
        lint_array!(ASSIGN_OPS, ASSIGN_OP_PATTERN)
    }
}

impl LateLintPass for AssignOps {
    fn check_expr(&mut self, cx: &LateContext, expr: &hir::Expr) {
        match expr.node {
            hir::ExprAssignOp(op, ref lhs, ref rhs) => {
                if let (Some(l), Some(r)) = (snippet_opt(cx, lhs.span), snippet_opt(cx, rhs.span)) {
                    span_lint_and_then(cx,
                                       ASSIGN_OPS,
                                       expr.span,
                                       "assign operation detected",
                                       |db| {
                                           match rhs.node {
                                               hir::ExprBinary(op2, _, _) if op2 != op => {
                                                   db.span_suggestion(expr.span,
                                                                       "replace it with",
                                                                       format!("{} = {} {} ({})", l, l, op.node.as_str(), r));
                                               },
                                               _ => {
                                                   db.span_suggestion(expr.span,
                                                                       "replace it with",
                                                                       format!("{} = {} {} {}", l, l, op.node.as_str(), r));
                                               }
                                           }
                                       });
                } else {
                    span_lint(cx,
                              ASSIGN_OPS,
                              expr.span,
                              "assign operation detected");
                }
            },
            hir::ExprAssign(ref assignee, ref e) => {
                if let hir::ExprBinary(op, ref l, ref r) = e.node {
                    let lint = |assignee: &hir::Expr, rhs: &hir::Expr| {
                        let ty = cx.tcx.expr_ty(assignee);
                        if ty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        let rty = cx.tcx.expr_ty(rhs);
                        if rty.walk_shallow().next().is_some() {
                            return; // implements_trait does not work with generics
                        }
                        macro_rules! ops {
                            ($op:expr, $cx:expr, $ty:expr, $rty:expr, $($trait_name:ident:$full_trait_name:ident),+) => {
                                match $op {
                                    $(hir::$full_trait_name => {
                                        let [krate, module] = ::utils::paths::OPS_MODULE;
                                        let path = [krate, module, concat!(stringify!($trait_name), "Assign")];
                                        let trait_id = if let Some(trait_id) = get_trait_def_id($cx, &path) {
                                            trait_id
                                        } else {
                                            return; // useless if the trait doesn't exist
                                        };
                                        implements_trait($cx, $ty, trait_id, vec![$rty])
                                    },)*
                                    _ => false,
                                }
                            }
                        }
                        if ops!(op.node, cx, ty, rty, Add:BiAdd,
                                                      Sub:BiSub,
                                                      Mul:BiMul,
                                                      Div:BiDiv,
                                                      Rem:BiRem,
                                                      And:BiAnd,
                                                      Or:BiOr,
                                                      BitAnd:BiBitAnd,
                                                      BitOr:BiBitOr,
                                                      BitXor:BiBitXor,
                                                      Shr:BiShr,
                                                      Shl:BiShl
                        ) {
                            if let (Some(snip_a), Some(snip_r)) = (snippet_opt(cx, assignee.span), snippet_opt(cx, rhs.span)) {
                                span_lint_and_then(cx,
                                                   ASSIGN_OP_PATTERN,
                                                   expr.span,
                                                   "manual implementation of an assign operation",
                                                   |db| {
                                                       db.span_suggestion(expr.span,
                                                                           "replace it with",
                                                                           format!("{} {}= {}", snip_a, op.node.as_str(), snip_r));
                                                   });
                            } else {
                                span_lint(cx,
                                          ASSIGN_OP_PATTERN,
                                          expr.span,
                                          "manual implementation of an assign operation");
                            }
                        }
                    };
                    // a = a op b
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, l) {
                        lint(assignee, r);
                    }
                    // a = b commutative_op a
                    if SpanlessEq::new(cx).ignore_fn().eq_expr(assignee, r) {
                        match op.node {
                            hir::BiAdd | hir::BiMul |
                            hir::BiAnd | hir::BiOr |
                            hir::BiBitXor | hir::BiBitAnd | hir::BiBitOr => {
                                lint(assignee, l);
                            },
                            _ => {},
                        }
                    }
                }
            },
            _ => {},
        }
    }
}
<|endoftext|>


<commit_before>use url::form_urlencoded;
use command::{Command, Query};
use command::Command::Dump;

#[derive(Clone, Debug)]
pub struct CommandQuery {
    command: Command,
    arguments: Query,
    prefix: String,
}

impl Default for CommandQuery {
    fn default() -> CommandQuery {
        CommandQuery {
            command: Dump,
            arguments: vec![],
            prefix: "/d".to_string(),
        }
    }
}

impl CommandQuery {
    pub fn new(command: Command, query: Query) -> CommandQuery {
        let default: CommandQuery = Default::default();
        CommandQuery {
            command: command,
            arguments: query,
            prefix: default.prefix,
        }
    }

    /// Get command enum constant to construct url encoded query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Get vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn get_argument(&mut self) -> Query {
        self.arguments.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    #[doc(hidden)]
    // get HTTP URI prefix. default: /d
    // This function is mainly provided for internal usage.
    pub fn get_prefix(&mut self) -> String {
        self.prefix.clone()
    }

    #[doc(hidden)]
    // set HTTP URI prefix. This function is provided for advanced user.
    pub fn set_prefix(&mut self, prefix: String) {
        self.prefix = prefix
    }

    /// Create url encoded command query.
    ///
    /// `vec![("key","value")]` interprets to `"key=value"`.
    /// And two or more value pair are concatinate with `&`.
    pub fn make_query(&mut self) -> String {
        form_urlencoded::Serializer::new(String::new())
            .extend_pairs(self.arguments.to_owned())
            .finish()
    }

    ///
    /// Create Groonga HTTP server query URL.
    pub fn encode(&mut self) -> String {
        format!("{}/{}?{}",
                self.get_prefix(),
                self.get_command(),
                self.make_query())
    }
}

#[cfg(test)]
mod test {
    use super::CommandQuery;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
            .filter("output_column @ \"type_safe\"".to_string())
            .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/select?table=Test&filter=%27output_column+%40+%22type_safe%22%27";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("test".to_string(), load_data.to_string())
            .input_type(InputType::Json)
            .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/load?table=test&input_type=json";
        assert_eq!(url_encoded.to_string(), command.encode());
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/status?";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
            .tables(vec!["Books".to_string(), "Categories".to_string()])
            .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/dump?tables=Books%2CCategories";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
            .filter("author == unknown".to_string())
            .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/delete?table=Books&filter=%27author+%3D%3D+unknown%27";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
            .flags(vec![(TableFlagType::PatKey), (TableFlagType::KeyWithSIS)])
            .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/table_create?name=Test&flags=TABLE_PAT_KEY%7CKEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command.encode());
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
            .column_type(DataType::LongText)
            .build();
        let mut command = CommandQuery::new(command, query);
        let url_encoded = "/d/column_create?table=Test&name=element&type=LongText";
        assert_eq!(url_encoded.to_string(), command.encode());
    }
}
<commit_msg>command_query: Remove needless shadowing and mut<commit_after>use url::form_urlencoded;
use command::{Command, Query};
use command::Command::Dump;

#[derive(Clone, Debug)]
pub struct CommandQuery {
    command: Command,
    arguments: Query,
    prefix: String,
}

impl Default for CommandQuery {
    fn default() -> CommandQuery {
        CommandQuery {
            command: Dump,
            arguments: vec![],
            prefix: "/d".to_string(),
        }
    }
}

impl CommandQuery {
    pub fn new(command: Command, query: Query) -> CommandQuery {
        let default: CommandQuery = Default::default();
        CommandQuery {
            command: command,
            arguments: query,
            prefix: default.prefix,
        }
    }

    /// Get command enum constant to construct url encoded query.
    pub fn get_command(&mut self) -> Command {
        self.command.clone()
    }

    /// Get vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn get_argument(&mut self) -> Query {
        self.arguments.clone()
    }

    /// Set vectorize `("key", "value")` pairs to construct url encoded query.
    pub fn set_argument(&mut self, arguments: Query) {
        self.arguments = arguments
    }

    #[doc(hidden)]
    // get HTTP URI prefix. default: /d
    // This function is mainly provided for internal usage.
    pub fn get_prefix(&mut self) -> String {
        self.prefix.clone()
    }

    #[doc(hidden)]
    // set HTTP URI prefix. This function is provided for advanced user.
    pub fn set_prefix(&mut self, prefix: String) {
        self.prefix = prefix
    }

    /// Create url encoded command query.
    ///
    /// `vec![("key","value")]` interprets to `"key=value"`.
    /// And two or more value pair are concatinate with `&`.
    pub fn make_query(&mut self) -> String {
        form_urlencoded::Serializer::new(String::new())
            .extend_pairs(self.arguments.to_owned())
            .finish()
    }

    ///
    /// Create Groonga HTTP server query URL.
    pub fn encode(&mut self) -> String {
        format!("{}/{}?{}",
                self.get_prefix(),
                self.get_command(),
                self.make_query())
    }
}

#[cfg(test)]
mod test {
    use super::CommandQuery;
    use select::SelectCommand;
    use load::{LoadCommand, InputType};
    use status::StatusCommand;
    use dump::DumpCommand;
    use delete::DeleteCommand;
    use table_create::TableCreateCommand;
    use types::table_flag_type::TableFlagType;
    use column_create::ColumnCreateCommand;
    use types::data_type::DataType;

    #[test]
    fn test_select() {
        let (command, query) = SelectCommand::new("Test".to_string())
            .filter("output_column @ \"type_safe\"".to_string())
            .build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/select?table=Test&filter=%27output_column+%40+%22type_safe%22%27";
        assert_eq!(url_encoded.to_string(), command_query);
    }

    #[test]
    fn test_load() {
        let load_data: &'static str = r#"[
{"_key":"http://example.org/","title":"This is test record 1!"},
]"#;
        let (command, query, values) = LoadCommand::new("test".to_string(), load_data.to_string())
            .input_type(InputType::Json)
            .build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/load?table=test&input_type=json";
        assert_eq!(url_encoded.to_string(), command_query);
        assert_eq!(load_data.to_string(), values);
    }

    #[test]
    fn test_status() {
        let (command, query) = StatusCommand::new().build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/status?";
        assert_eq!(url_encoded.to_string(), command_query);
    }

    #[test]
    fn test_dump() {
        let (command, query) = DumpCommand::new()
            .tables(vec!["Books".to_string(), "Categories".to_string()])
            .build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/dump?tables=Books%2CCategories";
        assert_eq!(url_encoded.to_string(), command_query);
    }

    #[test]
    fn test_delete() {
        let (command, query) = DeleteCommand::new("Books".to_string())
            .filter("author == unknown".to_string())
            .build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/delete?table=Books&filter=%27author+%3D%3D+unknown%27";
        assert_eq!(url_encoded.to_string(), command_query);
    }

    #[test]
    fn test_table_create() {
        let (command, query) = TableCreateCommand::new("Test".to_string())
            .flags(vec![(TableFlagType::PatKey), (TableFlagType::KeyWithSIS)])
            .build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/table_create?name=Test&flags=TABLE_PAT_KEY%7CKEY_WITH_SIS";
        assert_eq!(url_encoded.to_string(), command_query);
    }

    #[test]
    fn test_column_create() {
        let (command, query) = ColumnCreateCommand::new("Test".to_string(), "element".to_string())
            .column_type(DataType::LongText)
            .build();
        let command_query = CommandQuery::new(command, query).encode();
        let url_encoded = "/d/column_create?table=Test&name=element&type=LongText";
        assert_eq!(url_encoded.to_string(), command_query);
    }
}
<|endoftext|>


<commit_before>extern crate bincode;
extern crate rustc_serialize;
extern crate rpsrtsrs;
use std::net::TcpListener;
use std::io::Write;
use std::ops::Deref;

use rpsrtsrs::colors;
use rpsrtsrs::state::{Game, Player};

use bincode::SizeLimit;
use bincode::rustc_serialize::encode;

fn main() {
    let game = Game{
        players: vec![
            Player{
                id: 0,
                units: vec![],
            }]
    };
    let encoded: Vec<u8> = encode(&game, SizeLimit::Infinite).unwrap();

    let socket_addr = "127.0.0.1:8080".to_string();
    let tcp_listener = TcpListener::bind(socket_addr.deref()).unwrap();
    println!("Start server: {:?}", tcp_listener);
    for stream in tcp_listener.incoming() {
        let mut stream = stream.unwrap();
        stream.write(&encoded).unwrap();
    }
}
<commit_msg>server: Use one thread per connection<commit_after>extern crate bincode;
extern crate rustc_serialize;
extern crate rpsrtsrs;
use std::net::TcpListener;
use std::io::Write;
use std::ops::Deref;
use std::sync::{Mutex,Arc};
use std::thread;

use rpsrtsrs::state::{Game, Player};

use bincode::SizeLimit;
use bincode::rustc_serialize::encode;

fn main() {
    let game = Arc::new(Mutex::new(Game{
        players: vec![],
    }));

    let socket_addr = "127.0.0.1:8080".to_string();
    let tcp_listener = TcpListener::bind(socket_addr.deref()).unwrap();
    println!("Start server: {:?}", tcp_listener);

    for stream in tcp_listener.incoming() {
        let game_clone = game.clone();
        thread::spawn(move || {
            let mut stream = stream.unwrap();
            let mut game_lock = game_clone.lock().unwrap();
            let id = game_lock.players.last().map_or(0, |player| player.id+1);

            // create new player for the newly connected client
            game_lock.players.push(Player::new(id));

            let encoded: Vec<u8> = encode(game_lock.deref(), SizeLimit::Infinite).unwrap();
            stream.write(&encoded).unwrap();
        });
    }
}
<|endoftext|>


<commit_before>use std::str;
use std::thread;
use std::sync::Mutex;
use std::cell::RefCell;
use std::time::{Duration,Instant};
use std::collections::BTreeMap;
use std::fmt::Arguments;
use std::net::SocketAddr;
use mio::net::UdpSocket;
use std::io::{self,Write,Error,ErrorKind};
use nom::HexDisplay;
use sozu_command::buffer::Buffer;
use sozu_command::messages::FilteredData;

thread_local! {
  pub static METRICS: RefCell<ProxyMetrics> = RefCell::new(ProxyMetrics::new(String::from("sozu")))
}

#[derive(Debug,Clone)]
pub enum MetricData {
  Gauge(usize),
  Count(i64),
  Time(Instant, Option<Instant>),
}

#[derive(Debug,Clone)]
pub struct StoredMetricData {
  last_sent: Instant,
  data:      MetricData,
}

#[derive(Debug)]
pub struct ProxyMetrics {
  pub buffer:      Buffer,
  pub prefix:      String,
  pub created:     Instant,
  pub data:        BTreeMap<String, StoredMetricData>,
  pub is_writable: bool,
  remote:          Option<(SocketAddr, UdpSocket)>,
}

impl ProxyMetrics {
  pub fn new(prefix: String) -> Self {
    ProxyMetrics {
      buffer:      Buffer::with_capacity(2048),
      prefix:      prefix,
      created:     Instant::now(),
      data:        BTreeMap::new(),
      remote:      None,
      is_writable: false,
    }
  }

  pub fn set_up_remote(&mut self, socket: UdpSocket, addr: SocketAddr) {
    self.remote = Some((addr, socket));
  }

  pub fn socket(&self) -> Option<&UdpSocket> {
    self.remote.as_ref().map(|remote| &remote.1)
  }

  pub fn write(&mut self, args: Arguments) {
    //FIXME: error handling
    self.buffer.write_fmt(args);
    self.send();
  }

  pub fn dump_data(&self) -> BTreeMap<String, FilteredData> {
    self.data.iter().filter(|&(_, ref value)| {
      if let MetricData::Time(_,None) = value.data {
        false
      } else {
        true
      }
    }).map(|(ref key, ref value)| {
      let val = match value.data {
        MetricData::Gauge(i) => FilteredData::Gauge(i),
        MetricData::Count(i) => FilteredData::Count(i),
        MetricData::Time(begin, Some(end)) => {
          let duration = end.duration_since(begin);
          let millis = duration.as_secs() * 1000 + (duration.subsec_nanos() / 1000000) as u64;
          FilteredData::Time(millis as usize)
        },
        _ => unreachable!()
      };
      (key.to_string(), val)
    }).collect()
  }

  pub fn count_add(&mut self, key: &str, count_value: i64) {
    if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData {
          last_sent: self.created,
          data: MetricData::Count(count_value)
        }
      );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Count(value) = stored_metric.data {
          stored_metric.data = MetricData::Count(value+count_value);
        } else {
          panic!("tried to put a count value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn set_gauge(&mut self, key: &str, gauge_value: usize) {
    if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData {
          last_sent: self.created,
          data: MetricData::Gauge(gauge_value)
        }
      );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Gauge(_) = stored_metric.data {
          stored_metric.data = MetricData::Gauge(gauge_value);
        } else {
          panic!("tried to put a gauge value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn set_time_begin(&mut self, key: &str) {
    let now = Instant::now();
    //info!("set time begin {} = {:#?}", key, now);
    if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData {
          last_sent: self.created,
          data: MetricData::Time(now, None)
        }
      );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Time(_,_) = stored_metric.data {
          stored_metric.data = MetricData::Time(now, None);
        } else {
          panic!("tried to put a time value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn set_time_end(&mut self, key: &str) {
    let now = Instant::now();
    //info!("set time end {} = {:#?}", key, now);
    if !self.data.contains_key(key) {
      panic!("tried to set the end time while the begin time was not set");
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Time(begin,_) = stored_metric.data {
          stored_metric.data = MetricData::Time(begin, Some(now));
        } else {
          panic!("tried to put a time value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn writable(&mut self) {
    self.is_writable = true;
  }

  pub fn fill_buffer(&mut self) {
    let now  = Instant::now();
    let secs = Duration::new(2, 0);
    for (ref key, ref mut stored_metric) in self.data.iter_mut().filter(|&(_, ref value)| now.duration_since(value.last_sent) > secs) {
      //info!("will write {} -> {:#?}", key, stored_metric);
      match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.buffer.write_fmt(format_args!("{}.{}:{}|g\n", self.prefix, key, value)).is_ok() {
            stored_metric.last_sent = now;
          } else {
            break;
          }
        },
        MetricData::Count(value) => {
          if self.buffer.write_fmt(format_args!("{}.{}:{}|g\n", self.prefix, key, value)).is_ok() {
            stored_metric.last_sent = now;
          } else {
            break;
          }
        },
        MetricData::Time(begin, Some(end)) => {
          let duration = end.duration_since(begin);
          let millis = duration.as_secs() * 1000 + (duration.subsec_nanos() / 1000000) as u64;
          if self.buffer.write_fmt(format_args!("{}.{}:{}|ms\n", self.prefix, key, millis)).is_ok() {
            //info!("wrote time to buffer:\n{}", str::from_utf8(self.buffer.data()).unwrap());
            stored_metric.last_sent = now;
          } else {
            break;
          }
        },
        _ => {}
      }
    }
  }

  pub fn send_data(&mut self) {
    let mut written = 0usize;
    loop {
      let buflen = self.buffer.available_data();
      self.fill_buffer();
      if self.buffer.available_data() == 0 {
        break;
      }

      if let Some((ref addr, ref socket)) = self.remote {
        if self.is_writable {
          match socket.send_to(self.buffer.data(), addr) {
            Ok(sz) => {
              self.buffer.consume(sz);
              written += sz;
            },
            Err(e) => match e.kind() {
              ErrorKind::WouldBlock => {
                self.is_writable = false;
                break;
              },
              e => {
                error!("metrics socket write error={:?}", e);
                break;
              },
            }
          }
        } else {
          break;
        }
      } else {
        break;
      }

      if buflen == self.buffer.available_data() {
        break;
      }
    }
  }

  pub fn send(&mut self) -> io::Result<usize> {
    //let res = if self.buffer.available_data() >= 512 {
    let res = if let Some((ref addr, ref socket)) = self.remote {
        match socket.send_to(self.buffer.data(), addr) {
          Ok(sz) => {
            self.buffer.consume(sz);
            Ok(sz)
          },
          Err(e) => {
            Err(e)
          }
        }
      } else {
        Err(Error::new(ErrorKind::NotConnected, "metrics socket not set up"))
      };
    //} else {
    //  Err(Error::new(ErrorKind::Other, "no data to send"))
    //};

    res
  }
}

#[macro_export]
macro_rules! metrics_set_up (
  ($host:expr, $port: expr) => {
    let metrics_socket = ::mio::net::UdpSocket::bind(&("0.0.0.0:0".parse().unwrap())).expect("could not parse address");
    info!("setting up metrics: local address = {:#?}", metrics_socket.local_addr());
    let metrics_host   = ($host, $port).to_socket_addrs().expect("could not parse address").next().expect("could not get first address");
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_up_remote(metrics_socket, metrics_host);
    });
  }
);

#[macro_export]
macro_rules! count (
  ($key:expr, $value: expr) => {
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).count_add($key, v);
    });
  }
);

#[macro_export]
macro_rules! incr (
  ($key:expr) => (count!($key, 1);)
);

#[macro_export]
macro_rules! decr (
  ($key:expr) => (count!($key, -1);)
);

#[macro_export]
macro_rules! gauge (
  ($key:expr, $value: expr) => {
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      info!("gauge {} -> {}", $key, v);
      //(*metrics.borrow_mut()).write(format_args!("{}.{}:{}|g\n", *$crate::logging::TAG, $key, v));
      (*metrics.borrow_mut()).set_gauge($key, v);
    });
  }
);

#[macro_export]
macro_rules! time_begin (
  ($key:expr) => {
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_time_begin($key);
    });
  }
);

#[macro_export]
macro_rules! time_end (
  ($key:expr) => {
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_time_end($key);
    });
  }
);

<commit_msg>Add new metrics macro to avoid some magic string by using incr, gauge, ...<commit_after>use std::str;
use std::thread;
use std::sync::Mutex;
use std::cell::RefCell;
use std::time::{Duration,Instant};
use std::collections::BTreeMap;
use std::fmt::Arguments;
use std::net::SocketAddr;
use mio::net::UdpSocket;
use std::io::{self,Write,Error,ErrorKind};
use nom::HexDisplay;
use sozu_command::buffer::Buffer;
use sozu_command::messages::FilteredData;

thread_local! {
  pub static METRICS: RefCell<ProxyMetrics> = RefCell::new(ProxyMetrics::new(String::from("sozu")))
}

#[derive(Debug,Clone)]
pub enum MetricData {
  Gauge(usize),
  Count(i64),
  Time(Instant, Option<Instant>),
}

#[derive(Debug,Clone)]
pub struct StoredMetricData {
  last_sent: Instant,
  data:      MetricData,
}

#[derive(Debug)]
pub struct ProxyMetrics {
  pub buffer:      Buffer,
  pub prefix:      String,
  pub created:     Instant,
  pub data:        BTreeMap<String, StoredMetricData>,
  pub is_writable: bool,
  remote:          Option<(SocketAddr, UdpSocket)>,
}

impl ProxyMetrics {
  pub fn new(prefix: String) -> Self {
    ProxyMetrics {
      buffer:      Buffer::with_capacity(2048),
      prefix:      prefix,
      created:     Instant::now(),
      data:        BTreeMap::new(),
      remote:      None,
      is_writable: false,
    }
  }

  pub fn set_up_remote(&mut self, socket: UdpSocket, addr: SocketAddr) {
    self.remote = Some((addr, socket));
  }

  pub fn socket(&self) -> Option<&UdpSocket> {
    self.remote.as_ref().map(|remote| &remote.1)
  }

  pub fn write(&mut self, args: Arguments) {
    //FIXME: error handling
    self.buffer.write_fmt(args);
    self.send();
  }

  pub fn dump_data(&self) -> BTreeMap<String, FilteredData> {
    self.data.iter().filter(|&(_, ref value)| {
      if let MetricData::Time(_,None) = value.data {
        false
      } else {
        true
      }
    }).map(|(ref key, ref value)| {
      let val = match value.data {
        MetricData::Gauge(i) => FilteredData::Gauge(i),
        MetricData::Count(i) => FilteredData::Count(i),
        MetricData::Time(begin, Some(end)) => {
          let duration = end.duration_since(begin);
          let millis = duration.as_secs() * 1000 + (duration.subsec_nanos() / 1000000) as u64;
          FilteredData::Time(millis as usize)
        },
        _ => unreachable!()
      };
      (key.to_string(), val)
    }).collect()
  }

  pub fn count_add(&mut self, key: &str, count_value: i64) {
    if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData {
          last_sent: self.created,
          data: MetricData::Count(count_value)
        }
      );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Count(value) = stored_metric.data {
          stored_metric.data = MetricData::Count(value+count_value);
        } else {
          panic!("tried to put a count value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn set_gauge(&mut self, key: &str, gauge_value: usize) {
    if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData {
          last_sent: self.created,
          data: MetricData::Gauge(gauge_value)
        }
      );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Gauge(_) = stored_metric.data {
          stored_metric.data = MetricData::Gauge(gauge_value);
        } else {
          panic!("tried to put a gauge value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn set_time_begin(&mut self, key: &str) {
    let now = Instant::now();
    //info!("set time begin {} = {:#?}", key, now);
    if !self.data.contains_key(key) {
      self.data.insert(
        String::from(key),
        StoredMetricData {
          last_sent: self.created,
          data: MetricData::Time(now, None)
        }
      );
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Time(_,_) = stored_metric.data {
          stored_metric.data = MetricData::Time(now, None);
        } else {
          panic!("tried to put a time value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn set_time_end(&mut self, key: &str) {
    let now = Instant::now();
    //info!("set time end {} = {:#?}", key, now);
    if !self.data.contains_key(key) {
      panic!("tried to set the end time while the begin time was not set");
    } else {
      self.data.get_mut(key).map(|stored_metric| {
        if let MetricData::Time(begin,_) = stored_metric.data {
          stored_metric.data = MetricData::Time(begin, Some(now));
        } else {
          panic!("tried to put a time value in an incompatible metric ({:?}) for key {}", stored_metric.data, key);
        }
      });
    }
  }

  pub fn writable(&mut self) {
    self.is_writable = true;
  }

  pub fn fill_buffer(&mut self) {
    let now  = Instant::now();
    let secs = Duration::new(2, 0);
    for (ref key, ref mut stored_metric) in self.data.iter_mut().filter(|&(_, ref value)| now.duration_since(value.last_sent) > secs) {
      //info!("will write {} -> {:#?}", key, stored_metric);
      match stored_metric.data {
        MetricData::Gauge(value) => {
          if self.buffer.write_fmt(format_args!("{}.{}:{}|g\n", self.prefix, key, value)).is_ok() {
            stored_metric.last_sent = now;
          } else {
            break;
          }
        },
        MetricData::Count(value) => {
          if self.buffer.write_fmt(format_args!("{}.{}:{}|g\n", self.prefix, key, value)).is_ok() {
            stored_metric.last_sent = now;
          } else {
            break;
          }
        },
        MetricData::Time(begin, Some(end)) => {
          let duration = end.duration_since(begin);
          let millis = duration.as_secs() * 1000 + (duration.subsec_nanos() / 1000000) as u64;
          if self.buffer.write_fmt(format_args!("{}.{}:{}|ms\n", self.prefix, key, millis)).is_ok() {
            //info!("wrote time to buffer:\n{}", str::from_utf8(self.buffer.data()).unwrap());
            stored_metric.last_sent = now;
          } else {
            break;
          }
        },
        _ => {}
      }
    }
  }

  pub fn send_data(&mut self) {
    let mut written = 0usize;
    loop {
      let buflen = self.buffer.available_data();
      self.fill_buffer();
      if self.buffer.available_data() == 0 {
        break;
      }

      if let Some((ref addr, ref socket)) = self.remote {
        if self.is_writable {
          match socket.send_to(self.buffer.data(), addr) {
            Ok(sz) => {
              self.buffer.consume(sz);
              written += sz;
            },
            Err(e) => match e.kind() {
              ErrorKind::WouldBlock => {
                self.is_writable = false;
                break;
              },
              e => {
                error!("metrics socket write error={:?}", e);
                break;
              },
            }
          }
        } else {
          break;
        }
      } else {
        break;
      }

      if buflen == self.buffer.available_data() {
        break;
      }
    }
  }

  pub fn send(&mut self) -> io::Result<usize> {
    //let res = if self.buffer.available_data() >= 512 {
    let res = if let Some((ref addr, ref socket)) = self.remote {
        match socket.send_to(self.buffer.data(), addr) {
          Ok(sz) => {
            self.buffer.consume(sz);
            Ok(sz)
          },
          Err(e) => {
            Err(e)
          }
        }
      } else {
        Err(Error::new(ErrorKind::NotConnected, "metrics socket not set up"))
      };
    //} else {
    //  Err(Error::new(ErrorKind::Other, "no data to send"))
    //};

    res
  }
}

#[macro_export]
macro_rules! metrics_set_up (
  ($host:expr, $port: expr) => {
    let metrics_socket = ::mio::net::UdpSocket::bind(&("0.0.0.0:0".parse().unwrap())).expect("could not parse address");
    info!("setting up metrics: local address = {:#?}", metrics_socket.local_addr());
    let metrics_host   = ($host, $port).to_socket_addrs().expect("could not parse address").next().expect("could not get first address");
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_up_remote(metrics_socket, metrics_host);
    });
  }
);

#[macro_export]
macro_rules! count (
  ($key:expr, $value: expr) => {
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).count_add($key, v);
    });
  }
);

#[macro_export]
macro_rules! incr (
  ($key:expr) => (count!($key, 1);)
);

#[macro_export]
macro_rules! decr (
  ($key:expr) => (count!($key, -1);)
);

#[macro_export]
macro_rules! gauge (
  ($key:expr, $value: expr) => {
    let v = $value;
    $crate::network::metrics::METRICS.with(|metrics| {
      info!("gauge {} -> {}", $key, v);
      //(*metrics.borrow_mut()).write(format_args!("{}.{}:{}|g\n", *$crate::logging::TAG, $key, v));
      (*metrics.borrow_mut()).set_gauge($key, v);
    });
  }
);

#[macro_export]
macro_rules! time_begin (
  ($key:expr) => {
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_time_begin($key);
    });
  }
);

#[macro_export]
macro_rules! time_end (
  ($key:expr) => {
    $crate::network::metrics::METRICS.with(|metrics| {
      (*metrics.borrow_mut()).set_time_end($key);
    });
  }
);

///Client-side request errors caused by:
///
/// * Client terminates before sending request
/// * Read error from client
/// * Client timeout
/// * Client terminated connection
#[macro_export]
macro_rules! incr_ereq (
  () => (incr!("ereq");)
);

#[macro_export]
macro_rules! incr_client_cmd (
  () => (incr!("client_cmd");)
);

#[macro_export]
macro_rules! incr_resp_client_cmd (
  () => (incr!("incr_resp_client_cmd");)
);
<|endoftext|>