<commit_before>use std::ffi::{CString, AsOsStr, OsStr, OsString};
use std::iter::IntoIterator;
use std::path::{Path, PathBuf};
use libc::{c_char, size_t};

use {raw, Error};

#[doc(hidden)]
trait IsNull {
    fn is_ptr_null(&self) -> bool;
}
impl<T> IsNull for *const T {
    fn is_ptr_null(&self) -> bool {
        self.is_null()
    }
}
impl<T> IsNull for *mut T {
    fn is_ptr_null(&self) -> bool {
        self.is_null()
    }
}

#[doc(hidden)]
pub trait Binding: Sized {
    type Raw;

    unsafe fn from_raw(raw: Self::Raw) -> Self;
    fn raw(&self) -> Self::Raw;

    unsafe fn from_raw_opt<T>(raw: T) -> Option<Self>
        where T: Copy + IsNull, Self: Binding<Raw=T>
    {
        if raw.is_ptr_null() {
            None
        } else {
            Some(Binding::from_raw(raw))
        }
    }
}

pub fn iter2cstrs<T, I>(iter: I) -> Result<(Vec<CString>, Vec<*const c_char>,
                                            raw::git_strarray), Error>
    where T: IntoCString, I: IntoIterator<Item=T>
{
    let cstrs: Vec<_> = try!(iter.into_iter().map(|i| i.into_c_string()).collect());
    let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::<Vec<_>>();
    let raw = raw::git_strarray {
        strings: ptrs.as_ptr() as *mut _,
        count: ptrs.len() as size_t,
    };
    Ok((cstrs, ptrs, raw))
}

#[cfg(unix)]
pub fn bytes2path(b: &[u8]) -> &Path {
    use std::os::unix::prelude::*;
    Path::new(OsStr::from_bytes(b))
}
#[cfg(windows)]
pub fn bytes2path(b: &[u8]) -> &Path {
    use std::str;
    Path::new(str::from_utf8(b).unwrap())
}

/// A class of types that can be converted to C strings.
///
/// These types are represented internally as byte slices and it is quite rare
/// for them to contain an interior 0 byte.
pub trait IntoCString {
    /// Consume this container, converting it into a CString
    fn into_c_string(self) -> Result<CString, Error>;
}

impl<'a, T: IntoCString + Clone> IntoCString for &'a T {
    fn into_c_string(self) -> Result<CString, Error> {
        self.clone().into_c_string()
    }
}

impl<'a> IntoCString for &'a str {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self)))
    }
}

impl IntoCString for String {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self.into_bytes())))
    }
}

impl IntoCString for CString {
    fn into_c_string(self) -> Result<CString, Error> { Ok(self) }
}

impl<'a> IntoCString for &'a Path {
    fn into_c_string(self) -> Result<CString, Error> {
        self.as_os_str().into_c_string()
    }
}

impl IntoCString for PathBuf {
    fn into_c_string(self) -> Result<CString, Error> {
        self.as_os_str().into_c_string()
    }
}

impl<'a> IntoCString for &'a OsStr {
    fn into_c_string(self) -> Result<CString, Error> {
        self.to_os_string().into_c_string()
    }
}

impl IntoCString for OsString {
    #[cfg(unix)]
    fn into_c_string(self) -> Result<CString, Error> {
        use std::os::unix::prelude::*;
        Ok(try!(CString::new(self.as_os_str().as_bytes())))
    }
    #[cfg(windows)]
    fn into_c_string(self) -> Result<CString, Error> {
        match self.to_str() {
            Some(s) => s.into_c_string(),
            None => Err(Error::from_str("only valid unicode paths are accepted \
                                         on windows")),
        }
    }
}

impl<'a> IntoCString for &'a [u8] {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self)))
    }
}

impl IntoCString for Vec<u8> {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self)))
    }
}
<commit_msg>Remove usage of AsOsStr<commit_after>use std::ffi::{CString, OsStr, OsString};
use std::iter::IntoIterator;
use std::path::{Path, PathBuf};
use libc::{c_char, size_t};

use {raw, Error};

#[doc(hidden)]
trait IsNull {
    fn is_ptr_null(&self) -> bool;
}
impl<T> IsNull for *const T {
    fn is_ptr_null(&self) -> bool {
        self.is_null()
    }
}
impl<T> IsNull for *mut T {
    fn is_ptr_null(&self) -> bool {
        self.is_null()
    }
}

#[doc(hidden)]
pub trait Binding: Sized {
    type Raw;

    unsafe fn from_raw(raw: Self::Raw) -> Self;
    fn raw(&self) -> Self::Raw;

    unsafe fn from_raw_opt<T>(raw: T) -> Option<Self>
        where T: Copy + IsNull, Self: Binding<Raw=T>
    {
        if raw.is_ptr_null() {
            None
        } else {
            Some(Binding::from_raw(raw))
        }
    }
}

pub fn iter2cstrs<T, I>(iter: I) -> Result<(Vec<CString>, Vec<*const c_char>,
                                            raw::git_strarray), Error>
    where T: IntoCString, I: IntoIterator<Item=T>
{
    let cstrs: Vec<_> = try!(iter.into_iter().map(|i| i.into_c_string()).collect());
    let ptrs = cstrs.iter().map(|i| i.as_ptr()).collect::<Vec<_>>();
    let raw = raw::git_strarray {
        strings: ptrs.as_ptr() as *mut _,
        count: ptrs.len() as size_t,
    };
    Ok((cstrs, ptrs, raw))
}

#[cfg(unix)]
pub fn bytes2path(b: &[u8]) -> &Path {
    use std::os::unix::prelude::*;
    Path::new(OsStr::from_bytes(b))
}
#[cfg(windows)]
pub fn bytes2path(b: &[u8]) -> &Path {
    use std::str;
    Path::new(str::from_utf8(b).unwrap())
}

/// A class of types that can be converted to C strings.
///
/// These types are represented internally as byte slices and it is quite rare
/// for them to contain an interior 0 byte.
pub trait IntoCString {
    /// Consume this container, converting it into a CString
    fn into_c_string(self) -> Result<CString, Error>;
}

impl<'a, T: IntoCString + Clone> IntoCString for &'a T {
    fn into_c_string(self) -> Result<CString, Error> {
        self.clone().into_c_string()
    }
}

impl<'a> IntoCString for &'a str {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self)))
    }
}

impl IntoCString for String {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self.into_bytes())))
    }
}

impl IntoCString for CString {
    fn into_c_string(self) -> Result<CString, Error> { Ok(self) }
}

impl<'a> IntoCString for &'a Path {
    fn into_c_string(self) -> Result<CString, Error> {
        let s: &OsStr = self.as_ref();
        s.into_c_string()
    }
}

impl IntoCString for PathBuf {
    fn into_c_string(self) -> Result<CString, Error> {
        let s: OsString = self.into();
        s.into_c_string()
    }
}

impl<'a> IntoCString for &'a OsStr {
    fn into_c_string(self) -> Result<CString, Error> {
        self.to_os_string().into_c_string()
    }
}

impl IntoCString for OsString {
    #[cfg(unix)]
    fn into_c_string(self) -> Result<CString, Error> {
        use std::os::unix::prelude::*;
        let s: &OsStr = self.as_ref();
        Ok(try!(CString::new(s.as_bytes())))
    }
    #[cfg(windows)]
    fn into_c_string(self) -> Result<CString, Error> {
        match self.to_str() {
            Some(s) => s.into_c_string(),
            None => Err(Error::from_str("only valid unicode paths are accepted \
                                         on windows")),
        }
    }
}

impl<'a> IntoCString for &'a [u8] {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self)))
    }
}

impl IntoCString for Vec<u8> {
    fn into_c_string(self) -> Result<CString, Error> {
        Ok(try!(CString::new(self)))
    }
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! make_getter_function_for_optional {
    ($fnname:ident, $name:expr, $mapper:ty) => {
        pub fn $fnname(&self) -> Option<$mapper> {
            self.0.get_only($name).cloned().map(From::from)
        }
    }
}

#[macro_export]
macro_rules! make_getter_function_for_values {
    ($fnname:ident, $name:expr, $mapper:ty) => {
        pub fn $fnname(&self) -> Vec<$mapper> {
            self.0
                .get_all($name)
                .iter()
                .map(Clone::clone)
                .map(From::from)
                .collect()
        }
    }
}

#[macro_export]
macro_rules! create_data_type {
    ( $name:ident ) => {
        #[derive(Eq, PartialEq, Debug)]
        pub struct $name(String, $crate::param::Parameters);

        impl $name {
            pub fn new(raw: String, params: $crate::param::Parameters) -> $name {
                $name(raw, params)
            }

            pub fn from_raw(raw: String) -> $name {
                $name(raw, BTreeMap::new())
            }

            pub fn raw(&self) -> &String {
                &self.0
            }

            pub fn into_raw(self) -> String {
                self.0
            }

            pub fn params(&self) -> &$crate::param::Parameters {
                &self.1
            }
        }

        impl From<Property> for $name {
            fn from(p: Property) -> $name {
                $name::new(p.raw_value, p.params)
            }
        }
    }
}

#[cfg(feature = "timeconversions")]
pub const DATE_TIME_FMT : &'static str = "%Y%m%dT%H%M%SZ";

#[cfg(feature = "timeconversions")]
pub const DATE_FMT      : &'static str = "%Y%m%d";

<commit_msg>De-publicize some macros<commit_after>macro_rules! make_getter_function_for_optional {
    ($fnname:ident, $name:expr, $mapper:ty) => {
        pub fn $fnname(&self) -> Option<$mapper> {
            self.0.get_only($name).cloned().map(From::from)
        }
    }
}

macro_rules! make_getter_function_for_values {
    ($fnname:ident, $name:expr, $mapper:ty) => {
        pub fn $fnname(&self) -> Vec<$mapper> {
            self.0
                .get_all($name)
                .iter()
                .map(Clone::clone)
                .map(From::from)
                .collect()
        }
    }
}

macro_rules! create_data_type {
    ( $name:ident ) => {
        #[derive(Eq, PartialEq, Debug)]
        pub struct $name(String, $crate::param::Parameters);

        impl $name {
            pub fn new(raw: String, params: $crate::param::Parameters) -> $name {
                $name(raw, params)
            }

            pub fn from_raw(raw: String) -> $name {
                $name(raw, BTreeMap::new())
            }

            pub fn raw(&self) -> &String {
                &self.0
            }

            pub fn into_raw(self) -> String {
                self.0
            }

            pub fn params(&self) -> &$crate::param::Parameters {
                &self.1
            }
        }

        impl From<Property> for $name {
            fn from(p: Property) -> $name {
                $name::new(p.raw_value, p.params)
            }
        }
    }
}

#[cfg(feature = "timeconversions")]
pub const DATE_TIME_FMT : &'static str = "%Y%m%dT%H%M%SZ";

#[cfg(feature = "timeconversions")]
pub const DATE_FMT      : &'static str = "%Y%m%d";

<|endoftext|>


<commit_before>use std::io::Read;
use std::sync::{Once, ONCE_INIT};

use failure::Error;
use serde_json::{Map, Value};

/// Maximum number of bytes that can be allocated when decoding
/// Avro-encoded values. This is a protection against ill-formed
/// data, whose length field might be interpreted as enourmous.
/// See max_allocation_bytes to change this limit.
pub static mut MAX_ALLOCATION_BYTES: usize = 512 * 1024 * 1024;
static MAX_ALLOCATION_BYTES_ONCE: Once = ONCE_INIT;

/// Describes errors happened trying to allocate too many bytes
#[derive(Fail, Debug)]
#[fail(display = "Allocation error: {}", _0)]
pub struct AllocationError(String);

impl AllocationError {
    pub fn new<S>(msg: S) -> AllocationError
    where
        S: Into<String>,
    {
        AllocationError(msg.into())
    }
}

/// Describes errors happened while decoding Avro data.
#[derive(Fail, Debug)]
#[fail(display = "Decoding error: {}", _0)]
pub struct DecodeError(String);

impl DecodeError {
    pub fn new<S>(msg: S) -> DecodeError
    where
        S: Into<String>,
    {
        DecodeError(msg.into())
    }
}

pub trait MapHelper {
    fn string(&self, key: &str) -> Option<String>;

    fn name(&self) -> Option<String> {
        self.string("name")
    }

    fn doc(&self) -> Option<String> {
        self.string("doc")
    }
}

impl MapHelper for Map<String, Value> {
    fn string(&self, key: &str) -> Option<String> {
        self.get(key)
            .and_then(|v| v.as_str())
            .map(|v| v.to_string())
    }
}

pub fn read_long<R: Read>(reader: &mut R) -> Result<i64, Error> {
    zag_i64(reader)
}

pub fn zig_i32(n: i32, buffer: &mut Vec<u8>) {
    encode_variable(i64::from((n << 1) ^ (n >> 31)), buffer)
}

pub fn zig_i64(n: i64, buffer: &mut Vec<u8>) {
    encode_variable((n << 1) ^ (n >> 63), buffer)
}

pub fn zag_i32<R: Read>(reader: &mut R) -> Result<i32, Error> {
    let i = zag_i64(reader)?;
    if i < i64::from(i32::min_value()) || i > i64::from(i32::max_value()) {
        Err(DecodeError::new("int out of range").into())
    } else {
        Ok(i as i32)
    }
}

pub fn zag_i64<R: Read>(reader: &mut R) -> Result<i64, Error> {
    let z = decode_variable(reader)?;
    Ok(if z & 0x1 == 0 {
        (z >> 1) as i64
    } else {
        !(z >> 1) as i64
    })
}

fn encode_variable(mut z: i64, buffer: &mut Vec<u8>) {
    loop {
        if z <= 0x7F {
            buffer.push((z & 0x7F) as u8);
            break
        } else {
            buffer.push((0x80 | (z & 0x7F)) as u8);
            z >>= 7;
        }
    }
}

fn decode_variable<R: Read>(reader: &mut R) -> Result<u64, Error> {
    let mut i = 0u64;
    let mut buf = [0u8; 1];

    let mut j = 0;
    loop {
        if j > 9 {
            // if j * 7 > 64
            return Err(DecodeError::new("Overflow when decoding integer value").into())
        }
        reader.read_exact(&mut buf[..])?;
        i |= (u64::from(buf[0] & 0x7F)) << (j * 7);
        if (buf[0] >> 7) == 0 {
            break
        } else {
            j += 1;
        }
    }

    Ok(i)
}

/// Set a new maximum number of bytes that can be allocated when decoding data.
/// Once called, the limit cannot be changed.
///
/// **NOTE** This function must be called before decoding **any** data. The
/// library leverages [`std::sync::Once`](https://doc.rust-lang.org/std/sync/struct.Once.html)
/// to set the limit either when calling this method, or when decoding for
/// the first time.
pub fn max_allocation_bytes(num_bytes: usize) -> usize {
    unsafe {
        MAX_ALLOCATION_BYTES_ONCE.call_once(|| {
            MAX_ALLOCATION_BYTES = num_bytes;
        });
        MAX_ALLOCATION_BYTES
    }
}

pub fn safe_len(len: usize) -> Result<usize, Error> {
    let max_bytes = max_allocation_bytes(512 * 1024 * 1024);

    if len <= max_bytes {
        Ok(len)
    } else {
        Err(AllocationError::new(format!(
            "Unable to allocate {} bytes (Maximum allowed: {})",
            len, max_bytes
        )).into())
    }
}

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

    #[test]
    fn test_zigzag() {
        let mut a = Vec::new();
        let mut b = Vec::new();
        zig_i32(42i32, &mut a);
        zig_i64(42i64, &mut b);
        assert_eq!(a, b);
    }

    #[test]
    fn test_zig_i64() {
        let mut s = Vec::new();
        zig_i64(2147483647i64, &mut s);
        assert_eq!(s, [254, 255, 255, 255, 15]);

        s.clear();
        zig_i64(2147483648i64, &mut s);
        assert_eq!(s, [128, 128, 128, 128, 16]);

        s.clear();
        zig_i64(-2147483648i64, &mut s);
        assert_eq!(s, [255, 255, 255, 255, 15]);

        s.clear();
        zig_i64(-2147483649i64, &mut s);
        assert_eq!(s, [129, 128, 128, 128, 16]);
    }

    #[test]
    fn test_overflow() {
        let causes_left_shift_overflow: &[u8] = &[0xe1, 0xe1, 0xe1, 0xe1, 0xe1];
        assert!(decode_variable(&mut &causes_left_shift_overflow[..]).is_err());
    }

    #[test]
    fn test_safe_len() {
        assert_eq!(42usize, safe_len(42usize).unwrap());
        assert!(safe_len(1024 * 1024 * 1024).is_err());
    }
}
<commit_msg>Convert i32 to i64 earlier during serialization<commit_after>use std::io::Read;
use std::sync::{Once, ONCE_INIT};

use failure::Error;
use serde_json::{Map, Value};

/// Maximum number of bytes that can be allocated when decoding
/// Avro-encoded values. This is a protection against ill-formed
/// data, whose length field might be interpreted as enourmous.
/// See max_allocation_bytes to change this limit.
pub static mut MAX_ALLOCATION_BYTES: usize = 512 * 1024 * 1024;
static MAX_ALLOCATION_BYTES_ONCE: Once = ONCE_INIT;

/// Describes errors happened trying to allocate too many bytes
#[derive(Fail, Debug)]
#[fail(display = "Allocation error: {}", _0)]
pub struct AllocationError(String);

impl AllocationError {
    pub fn new<S>(msg: S) -> AllocationError
    where
        S: Into<String>,
    {
        AllocationError(msg.into())
    }
}

/// Describes errors happened while decoding Avro data.
#[derive(Fail, Debug)]
#[fail(display = "Decoding error: {}", _0)]
pub struct DecodeError(String);

impl DecodeError {
    pub fn new<S>(msg: S) -> DecodeError
    where
        S: Into<String>,
    {
        DecodeError(msg.into())
    }
}

pub trait MapHelper {
    fn string(&self, key: &str) -> Option<String>;

    fn name(&self) -> Option<String> {
        self.string("name")
    }

    fn doc(&self) -> Option<String> {
        self.string("doc")
    }
}

impl MapHelper for Map<String, Value> {
    fn string(&self, key: &str) -> Option<String> {
        self.get(key)
            .and_then(|v| v.as_str())
            .map(|v| v.to_string())
    }
}

pub fn read_long<R: Read>(reader: &mut R) -> Result<i64, Error> {
    zag_i64(reader)
}

pub fn zig_i32(n: i32, buffer: &mut Vec<u8>) {
    zig_i64(n as i64, buffer)
}

pub fn zig_i64(n: i64, buffer: &mut Vec<u8>) {
    encode_variable((n << 1) ^ (n >> 63), buffer)
}

pub fn zag_i32<R: Read>(reader: &mut R) -> Result<i32, Error> {
    let i = zag_i64(reader)?;
    if i < i64::from(i32::min_value()) || i > i64::from(i32::max_value()) {
        Err(DecodeError::new("int out of range").into())
    } else {
        Ok(i as i32)
    }
}

pub fn zag_i64<R: Read>(reader: &mut R) -> Result<i64, Error> {
    let z = decode_variable(reader)?;
    Ok(if z & 0x1 == 0 {
        (z >> 1) as i64
    } else {
        !(z >> 1) as i64
    })
}

fn encode_variable(mut z: i64, buffer: &mut Vec<u8>) {
    loop {
        if z <= 0x7F {
            buffer.push((z & 0x7F) as u8);
            break
        } else {
            buffer.push((0x80 | (z & 0x7F)) as u8);
            z >>= 7;
        }
    }
}

fn decode_variable<R: Read>(reader: &mut R) -> Result<u64, Error> {
    let mut i = 0u64;
    let mut buf = [0u8; 1];

    let mut j = 0;
    loop {
        if j > 9 {
            // if j * 7 > 64
            return Err(DecodeError::new("Overflow when decoding integer value").into())
        }
        reader.read_exact(&mut buf[..])?;
        i |= (u64::from(buf[0] & 0x7F)) << (j * 7);
        if (buf[0] >> 7) == 0 {
            break
        } else {
            j += 1;
        }
    }

    Ok(i)
}

/// Set a new maximum number of bytes that can be allocated when decoding data.
/// Once called, the limit cannot be changed.
///
/// **NOTE** This function must be called before decoding **any** data. The
/// library leverages [`std::sync::Once`](https://doc.rust-lang.org/std/sync/struct.Once.html)
/// to set the limit either when calling this method, or when decoding for
/// the first time.
pub fn max_allocation_bytes(num_bytes: usize) -> usize {
    unsafe {
        MAX_ALLOCATION_BYTES_ONCE.call_once(|| {
            MAX_ALLOCATION_BYTES = num_bytes;
        });
        MAX_ALLOCATION_BYTES
    }
}

pub fn safe_len(len: usize) -> Result<usize, Error> {
    let max_bytes = max_allocation_bytes(512 * 1024 * 1024);

    if len <= max_bytes {
        Ok(len)
    } else {
        Err(AllocationError::new(format!(
            "Unable to allocate {} bytes (Maximum allowed: {})",
            len, max_bytes
        )).into())
    }
}

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

    #[test]
    fn test_zigzag() {
        let mut a = Vec::new();
        let mut b = Vec::new();
        zig_i32(42i32, &mut a);
        zig_i64(42i64, &mut b);
        assert_eq!(a, b);
    }

    #[test]
    fn test_zig_i64() {
        let mut s = Vec::new();
        zig_i64(2147483647i64, &mut s);
        assert_eq!(s, [254, 255, 255, 255, 15]);

        s.clear();
        zig_i64(2147483648i64, &mut s);
        assert_eq!(s, [128, 128, 128, 128, 16]);

        s.clear();
        zig_i64(-2147483648i64, &mut s);
        assert_eq!(s, [255, 255, 255, 255, 15]);

        s.clear();
        zig_i64(-2147483649i64, &mut s);
        assert_eq!(s, [129, 128, 128, 128, 16]);
    }

    #[test]
    fn test_zig_i32() {
        let mut s = Vec::new();
        zig_i32(1073741823i32, &mut s);
        assert_eq!(s, [254, 255, 255, 255, 7]);

        s.clear();
        zig_i32(-1073741824i32, &mut s);
        assert_eq!(s, [255, 255, 255, 255, 7]);

        s.clear();
        zig_i32(1073741824i32, &mut s);
        assert_eq!(s, [128, 128, 128, 128, 8]);

        s.clear();
        zig_i32(-1073741825i32, &mut s);
        assert_eq!(s, [129, 128, 128, 128, 8]);

        s.clear();
        zig_i32(2147483647i32, &mut s);
        assert_eq!(s, [254, 255, 255, 255, 15]);

        s.clear();
        zig_i32(-2147483648i32, &mut s);
        assert_eq!(s, [255, 255, 255, 255, 15]);
    }

    #[test]
    fn test_overflow() {
        let causes_left_shift_overflow: &[u8] = &[0xe1, 0xe1, 0xe1, 0xe1, 0xe1];
        assert!(decode_variable(&mut &causes_left_shift_overflow[..]).is_err());
    }

    #[test]
    fn test_safe_len() {
        assert_eq!(42usize, safe_len(42usize).unwrap());
        assert!(safe_len(1024 * 1024 * 1024).is_err());
    }
}
<|endoftext|>


<commit_before>extern crate time;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> f64 {
    let (prev_sample, prev_avg) = samples.iter().fold((0.0, 0.0), |acc, ref sample| match acc {
        (0.0, 0.0) => (sample.to_f64().unwrap(), sample.to_f64().unwrap()),
        (prev_sample, prev_avg) => (sample.to_f64().unwrap(), alpha * prev_sample + (1.0 - alpha) * prev_avg)
    });
    alpha * prev_sample + (1.0 - alpha) * prev_avg
}

mod test {
    #[test]
    fn test_ewma_empty_vector() {
        use super::ewma;

        let empty: Vec<u32> = vec!();
        let alpha = 1.0/3.0;
        assert_eq!(ewma(empty, alpha), 0.0);
    }

    #[test]
    fn test_ewma_one_element() {
        use super::ewma;

        let input = vec!(1u);
        let alpha = 1.0/3.0;
        assert_eq!(ewma(input, alpha), 1.0);
    }

    #[test]
    fn test_exponential_smoothed_moving_average() {
        use super::ewma;
        use std::iter::range_inclusive;

        let input = range_inclusive(1u, 10).collect();
        let alpha = 1.0/3.0;
        let expected = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0];
        assert_eq!(ewma(input, alpha), expected[expected.len() - 1]);
    }
}
<commit_msg>Document the EWMA function.<commit_after>extern crate time;

/// Return current time in microseconds since the UNIX epoch.
pub fn now_microseconds() -> u32 {
    let t = time::get_time();
    (t.sec * 1_000_000) as u32 + (t.nsec/1000) as u32
}

/// Calculate the exponential weighted moving average for a vector of numbers, with a smoothing
/// factor `alpha` between 0 and 1. A higher `alpha` discounts older observations faster.
pub fn ewma<T: ToPrimitive>(samples: Vec<T>, alpha: f64) -> f64 {
    let (prev_sample, prev_avg) = samples.iter().fold((0.0, 0.0), |acc, ref sample| match acc {
        (0.0, 0.0) => (sample.to_f64().unwrap(), sample.to_f64().unwrap()),
        (prev_sample, prev_avg) => (sample.to_f64().unwrap(), alpha * prev_sample + (1.0 - alpha) * prev_avg)
    });
    alpha * prev_sample + (1.0 - alpha) * prev_avg
}

mod test {
    #[test]
    fn test_ewma_empty_vector() {
        use super::ewma;

        let empty: Vec<u32> = vec!();
        let alpha = 1.0/3.0;
        assert_eq!(ewma(empty, alpha), 0.0);
    }

    #[test]
    fn test_ewma_one_element() {
        use super::ewma;

        let input = vec!(1u);
        let alpha = 1.0/3.0;
        assert_eq!(ewma(input, alpha), 1.0);
    }

    #[test]
    fn test_exponential_smoothed_moving_average() {
        use super::ewma;
        use std::iter::range_inclusive;

        let input = range_inclusive(1u, 10).collect();
        let alpha = 1.0/3.0;
        let expected = [1.0, 4.0/3.0, 17.0/9.0,
        70.0/27.0, 275.0/81.0, 1036.0/243.0, 3773.0/729.0, 13378.0/2187.0,
        46439.0/6561.0, 158488.0/19683.0];
        assert_eq!(ewma(input, alpha), expected[expected.len() - 1]);
    }
}
<|endoftext|>


<commit_before>//! Compile time optimized maps and sets.
//!
//! Keys can be string literals, byte string literals, byte literals, char
//! literals, or any of the fixed-size integral types.
#![doc(html_root_url="https://sfackler.github.io/doc")]
#![warn(missing_docs)]
#![feature(macro_rules, tuple_indexing, phase, globs)]
#![no_std]

#[phase(plugin, link)]
extern crate core;
extern crate collections;

pub use shared::PhfHash;
#[doc(inline)]
pub use map::Map;
#[doc(inline)]
pub use set::Set;
#[doc(inline)]
pub use ordered_map::OrderedMap;
#[doc(inline)]
pub use ordered_set::OrderedSet;

#[path="../../shared/mod.rs"]
mod shared;
pub mod map;
pub mod set;
pub mod ordered_map;
pub mod ordered_set;

mod std {
    pub use core::fmt;
}

<commit_msg>Add deprecated reexports<commit_after>//! Compile time optimized maps and sets.
//!
//! Keys can be string literals, byte string literals, byte literals, char
//! literals, or any of the fixed-size integral types.
#![doc(html_root_url="https://sfackler.github.io/doc")]
#![warn(missing_docs)]
#![feature(macro_rules, tuple_indexing, phase, globs)]
#![no_std]

#[phase(plugin, link)]
extern crate core;
extern crate collections;

pub use shared::PhfHash;
#[doc(inline)]
pub use map::Map;
#[doc(inline)]
pub use set::Set;
#[doc(inline)]
pub use ordered_map::OrderedMap;
#[doc(inline)]
pub use ordered_set::OrderedSet;

#[deprecated = "renamed to Map"]
pub use Map as PhfMap;
#[deprecated = "renamed to Set"]
pub use Set as PhfSet;
#[deprecated = "renamed to OrderedMap"]
pub use OrderedMap as PhfOrderedMap;
#[deprecated = "renamed to OrderedSet"]
pub use OrderedSet as PhfOrderedSet;

#[path="../../shared/mod.rs"]
mod shared;
pub mod map;
pub mod set;
pub mod ordered_map;
pub mod ordered_set;

mod std {
    pub use core::fmt;
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate rswm;
extern crate x11;

use std::os::raw::{c_uchar, c_uint};
use x11::{keysym, xlib};

use rswm::client::ClientW;
use rswm::config::*;
use rswm::core;
use rswm::loggers;
use rswm::layout::{Tile, FullScreen, Overview, Layout};
use rswm::util::spawn;

const KEYS: &'static [(c_uint, c_uint, &'static Fn(&mut core::WindowManager))] =
    &[(MOD_MASK, keysym::XK_r, &|_| spawn("dmenu_run", &[])),
      (MOD_MASK, keysym::XK_t, &|_| spawn("urxvt", &[])),
      (MOD_MASK, keysym::XK_Print, &|_| spawn("scrot", &["-e", "mv $f ~/"])),
      (MOD_MASK | xlib::Mod1Mask,
       keysym::XK_Print,
       &|_| spawn("scrot", &["-s", "-e", "mv $f ~/"])),
      (MOD_MASK, keysym::XK_f, &|_| spawn("pcmanfm", &[])),
      (MOD_MASK, keysym::XK_l, &|_| spawn("i3lock", &["-c", "000000", "-n"])),
      (0, keysym::XF86XK_MonBrightnessUp, &|_| spawn("xbrightness", &["+10000"])),
      (0, keysym::XF86XK_MonBrightnessDown, &|_| spawn("xbrightness", &["-10000"])),
      (0, keysym::XF86XK_AudioRaiseVolume, &|_| spawn("amixer", &["set", "Master", "5000+"])),
      (0, keysym::XF86XK_AudioLowerVolume, &|_| spawn("amixer", &["set", "Master", "5000-"])),
      (0, keysym::XF86XK_AudioMute, &|_| spawn("amixer", &["set", "Master", "toggle"])),
      (0, keysym::XF86XK_AudioMicMute, &|_| spawn("amixer", &["set", "Capture", "toggle"]))];

const START_PROGRAMS: &'static [&'static Fn()] =
    &[&|| spawn("xcompmgr", &[]),
      &|| spawn("fcitx", &[]),
      &|| spawn("tilda", &["--hidden"]),
      &|| spawn("/usr/lib/polkit-kde/polkit-kde-authentication-agent-1", &[])];

const TAG_LAYOUT: &'static [(c_uchar, &'static str)] = &[('9' as c_uchar, "fullscreen"),
                                                         (TAG_OVERVIEW as c_uchar, "overview")];

const RULES: &'static [(&'static Fn(&ClientW) -> bool, &'static Fn(&mut ClientW))] =
    &[(&|c| c.get_class() == "Gimp", &|c| c.set_floating(true)),
      (&|c| c.is_dialog(), &|c| c.set_floating(true)),
      (&|c| c.get_class() == "VirtualBox", &|c| c.set_floating(true)),
      (&|c| c.get_class() == "Tilda",
       &|c| {
           c.set_floating(true);
           c.set_sticky(true);
       })];

const TAG_KEYS: &'static (&'static [(c_uint, c_uint, &'static Fn(&mut core::WindowManager))],
          &'static [c_uchar]) = &define_tags!(MOD_MASK,
                                              xlib::ShiftMask,
                                              ['1', '2', '3', '4', '5', '6', '7', '8', '9']);

const TAG_DESCRIPTION: &'static [(c_uchar, &'static str)] = &[('1' as c_uchar, "网页"),
                                                              ('2' as c_uchar, "代码")];

fn main() {
    let config = Config::default()
        .border_width(2)
        .bar_height(19)
        .addtional_keys(KEYS)
        .start_programs(START_PROGRAMS)
        .tag_keys(TAG_KEYS)
        .tag_default('1' as c_uchar)
        .rules(RULES)
        .tag_description(TAG_DESCRIPTION)
        .tag_layout(vec![('9' as c_uchar, Box::new(FullScreen)),
                         (TAG_OVERVIEW as c_uchar, Box::new(Overview))]);
    let xmobar_logger = loggers::XMobarLogger::new(loggers::LoggerConfig::default(), &[]);
    let mut window_manager = core::WindowManager::new(config);
    window_manager.set_logger(Box::new(xmobar_logger));
    window_manager.run();
}
<commit_msg>add dmenu to switch between windows.<commit_after>#[macro_use]
extern crate rswm;
extern crate x11;

use std::io;
use std::io::{Read, Write};
use std::os::raw::{c_uchar, c_uint};
use std::process;
use x11::{keysym, xlib};

use rswm::client::ClientW;
use rswm::config::*;
use rswm::core;
use rswm::loggers;
use rswm::layout::{Tile, FullScreen, Overview, Layout};
use rswm::util::spawn;

const KEYS: &'static [(c_uint, c_uint, &'static Fn(&mut core::WindowManager))] =
    &[(MOD_MASK, keysym::XK_r, &|_| spawn("dmenu_run", &[])),
      (MOD_MASK, keysym::XK_t, &|_| spawn("urxvt", &[])),
      (MOD_MASK, keysym::XK_Print, &|_| spawn("scrot", &["-e", "mv $f ~/"])),
      (MOD_MASK | xlib::Mod1Mask,
       keysym::XK_Print,
       &|_| spawn("scrot", &["-s", "-e", "mv $f ~/"])),
      (MOD_MASK, keysym::XK_f, &|_| spawn("pcmanfm", &[])),
      (MOD_MASK, keysym::XK_l, &|_| spawn("i3lock", &["-c", "000000", "-n"])),
      (0, keysym::XF86XK_MonBrightnessUp, &|_| spawn("xbrightness", &["+10000"])),
      (0, keysym::XF86XK_MonBrightnessDown, &|_| spawn("xbrightness", &["-10000"])),
      (0, keysym::XF86XK_AudioRaiseVolume, &|_| spawn("amixer", &["set", "Master", "5000+"])),
      (0, keysym::XF86XK_AudioLowerVolume, &|_| spawn("amixer", &["set", "Master", "5000-"])),
      (0, keysym::XF86XK_AudioMute, &|_| spawn("amixer", &["set", "Master", "toggle"])),
      (0, keysym::XF86XK_AudioMicMute, &|_| spawn("amixer", &["set", "Capture", "toggle"])),
      (MOD_MASK,
       keysym::XK_w,
       &|w| {
        let clients = w.all_clients();
        let contents: Vec<String> =
            clients.iter().map(|c| format!("[{}] {}", c.get_class(), c.get_title())).collect();
        match dmenu_helper(contents.iter(),
                           &["-p", "window", "-i", "-l", "7", "-sb", "#000000", "-sf",
                             "#00ff00", "-nb", "#000000", "-nf", "#dddddd"]) {
            Ok(result) => {
                if let Some(position) = contents.iter().position(|s| *s == result.trim()) {
                    let c = clients[position].clone();
                    w.select_tag(c.tag());
                    w.set_focus(c);
                }
            }
            Err(_) => return,
        }
    })];

const START_PROGRAMS: &'static [&'static Fn()] =
    &[&|| spawn("xcompmgr", &[]),
      &|| spawn("fcitx", &[]),
      &|| spawn("tilda", &["--hidden"]),
      &|| spawn("/usr/lib/polkit-kde/polkit-kde-authentication-agent-1", &[])];

const TAG_LAYOUT: &'static [(c_uchar, &'static str)] = &[('9' as c_uchar, "fullscreen"),
                                                         (TAG_OVERVIEW as c_uchar, "overview")];

const RULES: &'static [(&'static Fn(&ClientW) -> bool, &'static Fn(&mut ClientW))] =
    &[(&|c| c.get_class() == "Gimp", &|c| c.set_floating(true)),
      (&|c| c.is_dialog(), &|c| c.set_floating(true)),
      (&|c| c.get_class() == "VirtualBox", &|c| c.set_floating(true)),
      (&|c| c.get_class() == "Tilda",
       &|c| {
           c.set_floating(true);
           c.set_sticky(true);
       })];

const TAG_KEYS: &'static (&'static [(c_uint, c_uint, &'static Fn(&mut core::WindowManager))],
          &'static [c_uchar]) = &define_tags!(MOD_MASK,
                                              xlib::ShiftMask,
                                              ['1', '2', '3', '4', '5', '6', '7', '8', '9']);

const TAG_DESCRIPTION: &'static [(c_uchar, &'static str)] = &[('1' as c_uchar, "网页"),
                                                              ('2' as c_uchar, "代码")];

fn main() {
    let config = Config::default()
        .border_width(2)
        .bar_height(19)
        .addtional_keys(KEYS)
        .start_programs(START_PROGRAMS)
        .tag_keys(TAG_KEYS)
        .tag_default('1' as c_uchar)
        .rules(RULES)
        .tag_description(TAG_DESCRIPTION)
        .tag_layout(vec![('9' as c_uchar, Box::new(FullScreen)),
                         (TAG_OVERVIEW as c_uchar, Box::new(Overview))]);
    let xmobar_logger = loggers::XMobarLogger::new(loggers::LoggerConfig::default(), &[]);
    let mut window_manager = core::WindowManager::new(config);
    window_manager.set_logger(Box::new(xmobar_logger));
    window_manager.run();
}

fn dmenu_helper<'a, I>(strings: I, args: &[&str]) -> Result<String, io::Error>
    where I: Iterator<Item = &'a String>
{
    let mut child = try!(process::Command::new("dmenu")
        .args(args)
        .stdin(process::Stdio::piped())
        .stdout(process::Stdio::piped())
        .spawn());
    for c in strings {
        try!(writeln!(child.stdin.as_mut().unwrap(), "{}", c));
    }
    try!(child.wait());
    let mut result = String::new();
    try!(child.stdout.unwrap().read_to_string(&mut result));
    Ok(result)
}<|endoftext|>


<commit_before>#![no_std]
#![allow(ctypes)]

#![feature(lang_items)]
#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

impl Copy for Color {
}

enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

enum Option<T> {
    None,
    Some(T)
}

struct IntRange {
    cur: int,
    max: int
}

impl IntRange {
    fn next(&mut self) -> Option<int> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: int, hi: int) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
	let mut r = range(0, 80 * 25);
	loop {
		match r.next() {
			Option::Some(x) => {
				unsafe {
					*((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
				}
			},
			Option::None =>{break}
		}
	}
}

#[no_mangle]
#[no_split_stack]
pub fn main() {
    clear_screen(Color::LightRed);
}
<commit_msg>Whitespace fixes.<commit_after>#![no_std]
#![allow(ctypes)]

#![feature(lang_items)]
#[lang="sized"]
trait Sized {}

#[lang="copy"]
trait Copy {}

impl Copy for Color {}

enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

enum Option<T> {
    None,
    Some(T)
}

struct IntRange {
    cur: int,
    max: int
}

impl IntRange {
    fn next(&mut self) -> Option<int> {
        if self.cur < self.max {
            self.cur += 1;
            Option::Some(self.cur - 1)
        } else {
            Option::None
        }
    }
}

fn range(lo: int, hi: int) -> IntRange {
    IntRange { cur: lo, max: hi }
}

fn clear_screen(background: Color) {
    let mut r = range(0, 80 * 25);
    loop {
        match r.next() {
            Option::Some(x) => {
                unsafe {
                    *((0xb8000 + x * 2) as *mut u16) = (background as u16) << 12;
                }
            },
            Option::None =>{break}
        }
    }
}

#[no_mangle]
#[no_split_stack]
pub fn main() {
    clear_screen(Color::LightRed);
}
<|endoftext|>


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

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{Matrix, Mat4, Mat3, ToMat4};
use cgmath::projection;
use cgmath::angle;
use cgmath::vector::{Vec3, Vec2};

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

fn print_mat4(name: &str, mat: Mat4<f32>) {
  println!("{}:", name);
  for i in range(0u, 4) {
    for j in range(0u, 4) {
      print!("{} ", *mat.cr(i, j));
    }
    println("");
  }
  println("");
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    // Attempt to compile the shader
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    // Get the link status
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

struct Win {
  vertex_shader: GLuint,
  fragment_shader: GLuint,
  program: GLuint,
  vertex_array_obj: GLuint,
  vertex_buffer_obj: GLuint,
  matrix_id: GLint, // TODO: _id
  window: glfw::Window
}

impl Win {
  fn new() -> Win {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    let mut win =  Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };

    win.window.make_context_current();
    win.window.set_cursor_pos_callback(~CursorPosContext);
    win.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    // Create GLSL shaders
    win.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    win.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    win.program = link_program(win.vertex_shader, win.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut win.vertex_array_obj);
      gl::BindVertexArray(win.vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut win.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, win.vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(win.program);
      gl::BindFragDataLocation(win.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        win.program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      // Get a handle for our "model_view_proj_matrix" uniform.
      // Only at initialisation time.
      win.matrix_id = gl::GetUniformLocation(
        win.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }

    win
  }

  fn cleanup(&self) {
    // Cleanup
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let fov = angle::deg(45.0f32);
    let ratio = 4.0 / 3.0;
    let display_range_min = 0.1;
    let display_range_max = 100.0;
    let projection_matrix = projection::perspective(
      fov, ratio, display_range_min, display_range_max
    );

    let mut mvp_matrix = projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);
    }

    unsafe {
      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform.
      // For each model you render, since the model_view_proj_matrix
      // will be different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();

    // Clear the screen to black
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);

    // Draw a triangle from the 3 vertices
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);

    self.window.swap_buffers();
  }

  fn is_running(&self) -> bool {
    return !self.window.should_close()
  }

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      // println!("Cursor position: ({}, {})", xpos, ypos);
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    match (action, key) {
      (glfw::Press, glfw::KeyEscape) => {
        window.set_should_close(true)
      }
      (glfw::Press, glfw::KeySpace) => {
        println!("space")
      }
      (glfw::Press, glfw::KeyUp) => unsafe { CAMERA_POS.y -= 1.0f32 },
      (glfw::Press, glfw::KeyDown) => unsafe { CAMERA_POS.y += 1.0f32 },
      (glfw::Press, glfw::KeyRight) => unsafe { CAMERA_POS.x -= 1.0f32 },
      (glfw::Press, glfw::KeyLeft) => unsafe { CAMERA_POS.x += 1.0f32 },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

// vim: set tabstop=2 shiftwidth=2 softtabstop=2 expandtab:
<commit_msg>Removed outdated TODO about matrix_id<commit_after>// See LICENSE file for copyright and license details.

// Marauder is grid-less turn-based strategy game.

extern mod glfw;
extern mod gl;
extern mod cgmath;

use gl::types::{
  GLenum,
  GLuint,
  GLint,
  GLchar,
  GLfloat,
  GLsizeiptr,
  GLboolean
};
use cgmath::matrix::{Matrix, Mat4, Mat3, ToMat4};
use cgmath::projection;
use cgmath::angle;
use cgmath::vector::{Vec3, Vec2};

#[link(name = "glfw")]
#[link(name = "m")]
extern {}

/// usage: let s = mvp_matrix; println(type_of(&s));
fn type_of<T>(_: &T) -> &'static str {
  unsafe {
    (*std::unstable::intrinsics::get_tydesc::<T>()).name
  }
}

fn print_mat4(name: &str, mat: Mat4<f32>) {
  println!("{}:", name);
  for i in range(0u, 4) {
    for j in range(0u, 4) {
      print!("{} ", *mat.cr(i, j));
    }
    println("");
  }
  println("");
}

static mut MOUSE_POS: Vec2<f32> = Vec2{x: 0.0f32, y: 0.0};
static mut CAMERA_POS: Vec3<f32> = Vec3{x: 0.0f32, y: 0.0, z: 0.0};

static WIN_SIZE: Vec2<uint> = Vec2{x: 640, y: 480};
static VERTICES_COUNT: i32 = 3 * 2;

static VERTEX_DATA: [GLfloat, ..VERTICES_COUNT * 3] = [
   0.0,  1.0, 0.0,
   2.0, -1.0, 0.0,
  -2.0, -1.0, 0.0,

  0.0,  1.0,  0.0,
  0.0, -1.0,  2.0,
  0.0, -1.0, -2.0
];

static VERTEX_SHADER_SRC: &'static str = "
  #version 130
  in vec3 position;
  uniform mat4 model_view_proj_matrix;
  void main() {
    vec4 v = vec4(position, 1);
    gl_Position = model_view_proj_matrix * v;
  }
";

static FRAGMENT_SHADER_SRC: &'static str = "
  #version 130
  out vec4 out_color;
  void main() {
    out_color = vec4(1.0, 1.0, 1.0, 1.0);
  }
";

fn compile_shader(src: &str, ty: GLenum) -> GLuint {
  let shader = gl::CreateShader(ty);
  unsafe {
    // Attempt to compile the shader
    gl::ShaderSource(shader, 1, &src.to_c_str().unwrap(), std::ptr::null());
    gl::CompileShader(shader);

    // Get the compile status
    let mut status = gl::FALSE as GLint;
    gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len = 0;
      gl::GetShaderiv(shader, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetShaderInfoLog(shader, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("compile_shader(): " + std::str::raw::from_utf8(buf));
    }
  }
  shader
}

fn link_program(vertex_shader: GLuint, fragment_shader: GLuint) -> GLuint {
  let program = gl::CreateProgram();
  gl::AttachShader(program, vertex_shader);
  gl::AttachShader(program, fragment_shader);
  gl::LinkProgram(program);
  unsafe {
    // Get the link status
    let mut status = gl::FALSE as GLint;
    gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);

    // Fail on error
    if status != (gl::TRUE as GLint) {
      let mut len: GLint = 0;
      gl::GetProgramiv(program, gl::INFO_LOG_LENGTH, &mut len);
      // subtract 1 to skip the trailing null character
      let mut buf = std::vec::from_elem(len as uint - 1, 0u8);
      gl::GetProgramInfoLog(program, len, std::ptr::mut_null(),
        std::vec::raw::to_mut_ptr(buf) as *mut GLchar
      );
      fail!("link_program(): " + std::str::raw::from_utf8(buf));
    }
  }
  program
}

fn tr(m: Mat4<f32>, v: Vec3<f32>) -> Mat4<f32> {
  let mut t = Mat4::<f32>::identity();
  *t.mut_cr(3, 0) = v.x;
  *t.mut_cr(3, 1) = v.y;
  *t.mut_cr(3, 2) = v.z;
  m.mul_m(&t)
}

fn rot_x(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_x(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

fn rot_y(m: Mat4<f32>, angle: f32) -> Mat4<f32> {
  let r = Mat3::from_angle_y(angle::rad(angle)).to_mat4();
  m.mul_m(&r)
}

struct Win {
  vertex_shader: GLuint,
  fragment_shader: GLuint,
  program: GLuint,
  vertex_array_obj: GLuint,
  vertex_buffer_obj: GLuint,
  matrix_id: GLint,
  window: glfw::Window
}

impl Win {
  fn new() -> Win {
    // TODO: Move to opengl_init method
    // glfw::window_hint::context_version(3, 2);

    let mut win =  Win{
      vertex_shader: 0,
      fragment_shader: 0,
      program: 0,
      vertex_array_obj: 0,
      vertex_buffer_obj: 0,
      matrix_id: 0,
      window: glfw::Window::create(
        WIN_SIZE.x,
        WIN_SIZE.y,
        "OpenGL",
        glfw::Windowed
      ).unwrap()
    };

    win.window.make_context_current();
    win.window.set_cursor_pos_callback(~CursorPosContext);
    win.window.set_key_callback(~KeyContext);

    // Load the OpenGL function pointers
    gl::load_with(glfw::get_proc_address);

    // Create GLSL shaders
    win.vertex_shader = compile_shader(
      VERTEX_SHADER_SRC, gl::VERTEX_SHADER);
    win.fragment_shader = compile_shader(
      FRAGMENT_SHADER_SRC, gl::FRAGMENT_SHADER);
    win.program = link_program(win.vertex_shader, win.fragment_shader);

    unsafe {
      // Create Vertex Array Object
      gl::GenVertexArrays(1, &mut win.vertex_array_obj);
      gl::BindVertexArray(win.vertex_array_obj);

      // Create a Vertex Buffer Object and copy the vertex data to it
      gl::GenBuffers(1, &mut win.vertex_buffer_obj);
      gl::BindBuffer(gl::ARRAY_BUFFER, win.vertex_buffer_obj);
      let float_size = std::mem::size_of::<GLfloat>();
      let vertices_ptr = (VERTEX_DATA.len() * float_size) as GLsizeiptr;
      gl::BufferData(
        gl::ARRAY_BUFFER,
        vertices_ptr,
        std::cast::transmute(&VERTEX_DATA[0]),
        gl::STATIC_DRAW
      );

      gl::UseProgram(win.program);
      gl::BindFragDataLocation(win.program, 0, "out_color".to_c_str().unwrap());

      // Specify the layout of the vertex data
      let pos_attr = gl::GetAttribLocation(
        win.program, "position".to_c_str().unwrap()) as GLuint;
      gl::EnableVertexAttribArray(pos_attr);
      let size = 3;
      let normalized = gl::FALSE as GLboolean;
      let stride = 0;
      gl::VertexAttribPointer(
        pos_attr,
        size,
        gl::FLOAT,
        normalized,
        stride,
        std::ptr::null()
      );

      // Get a handle for our "model_view_proj_matrix" uniform.
      // Only at initialisation time.
      win.matrix_id = gl::GetUniformLocation(
        win.program, "model_view_proj_matrix".to_c_str().unwrap()
      );
    }

    win
  }

  fn cleanup(&self) {
    // Cleanup
    gl::DeleteProgram(self.program);
    gl::DeleteShader(self.fragment_shader);
    gl::DeleteShader(self.vertex_shader);
    unsafe {
      gl::DeleteBuffers(1, &self.vertex_buffer_obj);
      gl::DeleteVertexArrays(1, &self.vertex_array_obj);
    }
  }

  fn update_matrices(&self) {
    let fov = angle::deg(45.0f32);
    let ratio = 4.0 / 3.0;
    let display_range_min = 0.1;
    let display_range_max = 100.0;
    let projection_matrix = projection::perspective(
      fov, ratio, display_range_min, display_range_max
    );

    let mut mvp_matrix = projection_matrix;
    unsafe {
      mvp_matrix = tr(mvp_matrix, Vec3{x: 0.0f32, y: 0.0, z: -10.0f32});
      mvp_matrix = rot_x(mvp_matrix, MOUSE_POS.y / 100.0);
      mvp_matrix = rot_y(mvp_matrix, MOUSE_POS.x / 100.0);
      mvp_matrix = tr(mvp_matrix, CAMERA_POS);
    }

    unsafe {
      // Send our transformation to the currently bound shader,
      // in the "model_view_proj_matrix" uniform.
      // For each model you render, since the model_view_proj_matrix
      // will be different (at least the M part).
      gl::UniformMatrix4fv(self.matrix_id, 1, gl::FALSE, mvp_matrix.cr(0, 0));
    }
  }

  fn draw(&self) {
    self.update_matrices();

    // Clear the screen to black
    gl::ClearColor(0.3, 0.3, 0.3, 1.0);
    gl::Clear(gl::COLOR_BUFFER_BIT);

    // Draw a triangle from the 3 vertices
    gl::DrawArrays(gl::TRIANGLES, 0, VERTICES_COUNT);

    self.window.swap_buffers();
  }

  fn is_running(&self) -> bool {
    return !self.window.should_close()
  }

  fn process_events(&self) {
    glfw::poll_events();
  }
}

struct CursorPosContext;
impl glfw::CursorPosCallback for CursorPosContext {
  fn call(&self, w: &glfw::Window, xpos: f64, ypos: f64) {
    if w.get_mouse_button(glfw::MouseButtonRight) == glfw::Press {
      // println!("Cursor position: ({}, {})", xpos, ypos);
      unsafe {
        MOUSE_POS.x = xpos as f32;
        MOUSE_POS.y = ypos as f32;
      }
    }
  }
}

struct ErrorContext;
impl glfw::ErrorCallback for ErrorContext {
  fn call(&self, _: glfw::Error, description: ~str) {
    println!("GLFW Error: {:s}", description);
  }
}

struct KeyContext;
impl glfw::KeyCallback for KeyContext {
  fn call(
    &self,
    window: &glfw::Window,
    key:    glfw::Key,
    _:      std::libc::c_int,
    action: glfw::Action,
    _:      glfw::Modifiers
  ) {
    match (action, key) {
      (glfw::Press, glfw::KeyEscape) => {
        window.set_should_close(true)
      }
      (glfw::Press, glfw::KeySpace) => {
        println!("space")
      }
      (glfw::Press, glfw::KeyUp) => unsafe { CAMERA_POS.y -= 1.0f32 },
      (glfw::Press, glfw::KeyDown) => unsafe { CAMERA_POS.y += 1.0f32 },
      (glfw::Press, glfw::KeyRight) => unsafe { CAMERA_POS.x -= 1.0f32 },
      (glfw::Press, glfw::KeyLeft) => unsafe { CAMERA_POS.x += 1.0f32 },
      _ => {}
    }
  }
}

fn main() {
  glfw::set_error_callback(~ErrorContext);
  do glfw::start {
    let win =  Win::new();
    while win.is_running() {
      win.process_events();
      win.draw();
    }
    win.cleanup();
  }
}

#[start]
fn start(argc: int, argv: **u8) -> int {
  std::rt::start_on_main_thread(argc, argv, main)
}

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


<commit_before>use std::fmt::Debug;
use std::marker::PhantomData;

use pmcfg::*;
use cfg::{LetterT, CFGComposition, CFGRule, CFG};

pub fn from_pmcfg<N: Clone + Debug + Ord + PartialEq,
     T: Clone + Debug + Ord + PartialEq,
     W: Clone + Debug + Ord + PartialEq
     >(pmcfg :PMCFG<N, T, W>) -> Result<CFG<N,T,W>, String> {
        let mut rules = Vec::new();

        for r in pmcfg.rules{
            if r.composition.composition.len()!=1{
                return Err(format!("Too many clauses"))
            }

            let mut new_composition = Vec::new();

            let r_0 = &r.composition.composition[0];

            for v in r_0{
                match v{
                    &VarT::T(ref x)=>{
                        new_composition.push(
                            LetterT::Value(x.clone())
                        );
                    },
                    &VarT::Var(i,0)=>{
                        let x = &r.tail[i as usize];
                        new_composition.push(
                            LetterT::Label(x.clone())
                        );
                    },
                    _=> return Err(format!("Could not compile rules")),
                }

            }
            rules.push(CFGRule{
                head: r.head.clone(),
                composition: CFGComposition{
                    composition: new_composition,
                },
                weight: r.weight.clone(),
            });
        }

        Ok(CFG {
            _dummy: PhantomData,
            initial: pmcfg.initial.clone(),
            rules: rules,
        })

}
<commit_msg>src/cfg/from_pmcfg.rs: made `from_pmcfg` the impl of `From<PMCFG<N, T, W>>`<commit_after>use std::fmt::Debug;
use std::marker::PhantomData;

use pmcfg::*;
use cfg::{LetterT, CFGComposition, CFGRule, CFG};

impl<N: Clone + Debug + Ord + PartialEq,
     T: Clone + Debug + Ord + PartialEq,
     W: Clone + Debug + Ord + PartialEq> From<PMCFG<N, T, W>> for CFG<N, T, W> {
    fn from(pmcfg: PMCFG<N, T, W>) -> CFG<N, T, W> {
        let mut rules = Vec::new();

        for r in pmcfg.rules{
            if r.composition.composition.len() != 1 {
                panic!("[ERROR] Too many clauses: {:?}", r)
            }

            let mut new_composition = Vec::new();

            let r_0 = &r.composition.composition[0];

            for v in r_0 {
                match v{
                    &VarT::T(ref x)=>{
                        new_composition.push(
                            LetterT::Value(x.clone())
                        );
                    },
                    &VarT::Var(i,0)=>{
                        let x = &r.tail[i as usize];
                        new_composition.push(
                            LetterT::Label(x.clone())
                        );
                    },
                    _=> panic!("[ERROR] Access to wrong component: {:?} in {:?}", v, r_0),
                }

            }
            rules.push(CFGRule{
                head: r.head.clone(),
                composition: CFGComposition{
                    composition: new_composition,
                },
                weight: r.weight.clone(),
            });
        }

        CFG { _dummy: PhantomData,
               initial: pmcfg.initial.clone(),
               rules: rules,
        }
    }
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::sync::Arc;

use regex::Regex;
use threadpool::ThreadPool;

use config::Config;
use git::Git;
use github;
use github::api::Session;
use git_clone_manager::GitCloneManager;
use messenger;
use slack::SlackAttachmentBuilder;
use worker;

pub fn merge_pull_request(session: &Session, clone_mgr: &GitCloneManager, owner: &str, repo: &str,
                          pull_request: &github::PullRequest, target_branch: &str)
                          -> Result<github::PullRequest, String> {
    Merger::new(session, clone_mgr).merge_pull_request(owner, repo, pull_request, target_branch)
}

struct Merger<'a> {
    session: &'a Session,
    clone_mgr: &'a GitCloneManager,
}

impl<'a> Merger<'a> {
    pub fn new(session: &'a Session, clone_mgr: &'a GitCloneManager) -> Merger<'a> {
        Merger {
            session: session,
            clone_mgr: clone_mgr,
        }
    }

    pub fn merge_pull_request(&self, owner: &str, repo: &str, pull_request: &github::PullRequest,
                              target_branch: &str)
                              -> Result<github::PullRequest, String> {
        if !pull_request.is_merged() {
            return Err(format!("Pull Request #{} is not yet merged.", pull_request.number));
        }

        let merge_commit_sha;
        if let Some(ref sha) = pull_request.merge_commit_sha {
            merge_commit_sha = sha;
        } else {
            return Err(format!("Pull Request #{} has no merge commit.", pull_request.number));
        }

        // strip everything before last slash
        let regex = Regex::new(r".*/").unwrap();
        let pr_branch_name = format!("{}-{}",
                                     regex.replace(&pull_request.head.ref_name, ""),
                                     regex.replace(&target_branch, ""));

        let held_clone_dir = try!(self.clone_mgr.clone(owner, repo));
        let clone_dir = held_clone_dir.dir();

        let git = Git::new(self.session.github_host(), self.session.github_token(), clone_dir);

        // make sure there isn't already such a branch
        let current_remotes = try!(git.run(&["ls-remote", "--heads"]));
        if current_remotes.contains(&format!("refs/heads/{}", pr_branch_name)) {
            return Err(format!("PR branch already exists on origin: '{}'", pr_branch_name));
        }

        let (title, body) = try!(self.cherry_pick(&git,
                                                  &merge_commit_sha,
                                                  &pr_branch_name,
                                                  pull_request.number,
                                                  &target_branch,
                                                  &pull_request.base.ref_name));

        try!(git.run(&["push", "origin", &format!("{}:{}", pr_branch_name, pr_branch_name)]));

        let new_pr = try!(self.session
            .create_pull_request(owner, repo, &title, &body, &pr_branch_name, &target_branch));

        let assignees: Vec<String> =
            pull_request.assignees.iter().map(|a| a.login().to_string()).collect();
        try!(self.session.assign_pull_request(owner, repo, new_pr.number, assignees));

        Ok(new_pr)
    }

    fn cherry_pick(&self, git: &Git, commit_hash: &str, pr_branch_name: &str,
                   pr_number: u32, target_branch: &str, orig_base_branch: &str)
                   -> Result<(String, String), String> {
        try!(git.checkout_branch(pr_branch_name, &format!("origin/{}", target_branch)));

        // cherry-pick!
        try!(git.run(&["cherry-pick", "-X", "ignore-all-space", commit_hash]));

        let desc = try!(git.get_commit_desc(commit_hash));

        // grab original title and strip out the PR number at the end
        let pr_regex = Regex::new(r"(\s*\(#\d+\))+$").unwrap();
        let orig_title = pr_regex.replace(&desc.0, "");
        // strip out 'release' from the prefix to keep titles shorter
        let release_branch_regex = Regex::new(r"^release/").unwrap();
        let title = format!("{}->{}: {}",
                            orig_base_branch,
                            release_branch_regex.replace(target_branch, ""),
                            orig_title);
        let mut body = desc.1;

        if body.len() != 0 {
            body += "\n\n";
        }
        body += format!("(cherry-picked from {}, PR #{})",
                        &commit_hash[0..7],
                        pr_number)
            .as_str();

        // change commit message
        try!(git.run_with_stdin(&["commit", "--amend", "-F", "-"], &format!("{}\n\n{}", title, body)));

        Ok((title, body))
    }
}

#[derive(Debug)]
pub struct PRMergeRequest {
    pub repo: github::Repo,
    pub pull_request: github::PullRequest,
    pub target_branch: String,
}

struct Runner {
    config: Arc<Config>,
    github_session: Arc<Session>,
    clone_mgr: Arc<GitCloneManager>,
    thread_pool: ThreadPool,
}

pub fn req(repo: &github::Repo, pull_request: &github::PullRequest, target_branch: &str) -> PRMergeRequest {
    PRMergeRequest {
        repo: repo.clone(),
        pull_request: pull_request.clone(),
        target_branch: target_branch.to_string(),
    }
}

pub fn new_worker(max_concurrency: usize, config: Arc<Config>, github_session: Arc<Session>, clone_mgr: Arc<GitCloneManager>)
               -> worker::Worker<PRMergeRequest> {
    worker::Worker::new(Runner {
        config: config,
        github_session: github_session,
        clone_mgr: clone_mgr.clone(),
        thread_pool: ThreadPool::new(max_concurrency),
    })
}

impl worker::Runner<PRMergeRequest> for Runner {
    fn handle(&self, req: PRMergeRequest) {
        let github_session = self.github_session.clone();
        let clone_mgr = self.clone_mgr.clone();
        let config = self.config.clone();

        // launch another thread to do the merge
        self.thread_pool.execute(move || {
            if let Err(e) = merge_pull_request(github_session.borrow(),
                                               &clone_mgr,
                                               &req.repo.owner.login(),
                                               &req.repo.name,
                                               &req.pull_request,
                                               &req.target_branch) {

                let attach = SlackAttachmentBuilder::new(&e)
                    .title(format!("Source PR: #{}: \"{}\"",
                                   req.pull_request.number,
                                   req.pull_request.title)
                        .as_str())
                    .title_link(req.pull_request.html_url.clone())
                    .color("danger")
                    .build();

                let messenger = messenger::from_config(config);
                messenger.send_to_owner("Error creating merge Pull Request",
                                        &vec![attach],
                                        &req.pull_request.user,
                                        &req.repo);
            }
        });
    }
}
<commit_msg>Use full commit hash in 'cherry-picked from'. (#81)<commit_after>use std::borrow::Borrow;
use std::sync::Arc;

use regex::Regex;
use threadpool::ThreadPool;

use config::Config;
use git::Git;
use github;
use github::api::Session;
use git_clone_manager::GitCloneManager;
use messenger;
use slack::SlackAttachmentBuilder;
use worker;

pub fn merge_pull_request(session: &Session, clone_mgr: &GitCloneManager, owner: &str, repo: &str,
                          pull_request: &github::PullRequest, target_branch: &str)
                          -> Result<github::PullRequest, String> {
    Merger::new(session, clone_mgr).merge_pull_request(owner, repo, pull_request, target_branch)
}

struct Merger<'a> {
    session: &'a Session,
    clone_mgr: &'a GitCloneManager,
}

impl<'a> Merger<'a> {
    pub fn new(session: &'a Session, clone_mgr: &'a GitCloneManager) -> Merger<'a> {
        Merger {
            session: session,
            clone_mgr: clone_mgr,
        }
    }

    pub fn merge_pull_request(&self, owner: &str, repo: &str, pull_request: &github::PullRequest,
                              target_branch: &str)
                              -> Result<github::PullRequest, String> {
        if !pull_request.is_merged() {
            return Err(format!("Pull Request #{} is not yet merged.", pull_request.number));
        }

        let merge_commit_sha;
        if let Some(ref sha) = pull_request.merge_commit_sha {
            merge_commit_sha = sha;
        } else {
            return Err(format!("Pull Request #{} has no merge commit.", pull_request.number));
        }

        // strip everything before last slash
        let regex = Regex::new(r".*/").unwrap();
        let pr_branch_name = format!("{}-{}",
                                     regex.replace(&pull_request.head.ref_name, ""),
                                     regex.replace(&target_branch, ""));

        let held_clone_dir = try!(self.clone_mgr.clone(owner, repo));
        let clone_dir = held_clone_dir.dir();

        let git = Git::new(self.session.github_host(), self.session.github_token(), clone_dir);

        // make sure there isn't already such a branch
        let current_remotes = try!(git.run(&["ls-remote", "--heads"]));
        if current_remotes.contains(&format!("refs/heads/{}", pr_branch_name)) {
            return Err(format!("PR branch already exists on origin: '{}'", pr_branch_name));
        }

        let (title, body) = try!(self.cherry_pick(&git,
                                                  &merge_commit_sha,
                                                  &pr_branch_name,
                                                  pull_request.number,
                                                  &target_branch,
                                                  &pull_request.base.ref_name));

        try!(git.run(&["push", "origin", &format!("{}:{}", pr_branch_name, pr_branch_name)]));

        let new_pr = try!(self.session
            .create_pull_request(owner, repo, &title, &body, &pr_branch_name, &target_branch));

        let assignees: Vec<String> =
            pull_request.assignees.iter().map(|a| a.login().to_string()).collect();
        try!(self.session.assign_pull_request(owner, repo, new_pr.number, assignees));

        Ok(new_pr)
    }

    fn cherry_pick(&self, git: &Git, commit_hash: &str, pr_branch_name: &str,
                   pr_number: u32, target_branch: &str, orig_base_branch: &str)
                   -> Result<(String, String), String> {
        try!(git.checkout_branch(pr_branch_name, &format!("origin/{}", target_branch)));

        // cherry-pick!
        try!(git.run(&["cherry-pick", "-X", "ignore-all-space", commit_hash]));

        let desc = try!(git.get_commit_desc(commit_hash));

        // grab original title and strip out the PR number at the end
        let pr_regex = Regex::new(r"(\s*\(#\d+\))+$").unwrap();
        let orig_title = pr_regex.replace(&desc.0, "");
        // strip out 'release' from the prefix to keep titles shorter
        let release_branch_regex = Regex::new(r"^release/").unwrap();
        let title = format!("{}->{}: {}",
                            orig_base_branch,
                            release_branch_regex.replace(target_branch, ""),
                            orig_title);
        let mut body = desc.1;

        if body.len() != 0 {
            body += "\n\n";
        }
        body += format!("(cherry-picked from {}, PR #{})", commit_hash, pr_number).as_str();

        // change commit message
        try!(git.run_with_stdin(&["commit", "--amend", "-F", "-"], &format!("{}\n\n{}", title, body)));

        Ok((title, body))
    }
}

#[derive(Debug)]
pub struct PRMergeRequest {
    pub repo: github::Repo,
    pub pull_request: github::PullRequest,
    pub target_branch: String,
}

struct Runner {
    config: Arc<Config>,
    github_session: Arc<Session>,
    clone_mgr: Arc<GitCloneManager>,
    thread_pool: ThreadPool,
}

pub fn req(repo: &github::Repo, pull_request: &github::PullRequest, target_branch: &str) -> PRMergeRequest {
    PRMergeRequest {
        repo: repo.clone(),
        pull_request: pull_request.clone(),
        target_branch: target_branch.to_string(),
    }
}

pub fn new_worker(max_concurrency: usize, config: Arc<Config>, github_session: Arc<Session>, clone_mgr: Arc<GitCloneManager>)
               -> worker::Worker<PRMergeRequest> {
    worker::Worker::new(Runner {
        config: config,
        github_session: github_session,
        clone_mgr: clone_mgr.clone(),
        thread_pool: ThreadPool::new(max_concurrency),
    })
}

impl worker::Runner<PRMergeRequest> for Runner {
    fn handle(&self, req: PRMergeRequest) {
        let github_session = self.github_session.clone();
        let clone_mgr = self.clone_mgr.clone();
        let config = self.config.clone();

        // launch another thread to do the merge
        self.thread_pool.execute(move || {
            if let Err(e) = merge_pull_request(github_session.borrow(),
                                               &clone_mgr,
                                               &req.repo.owner.login(),
                                               &req.repo.name,
                                               &req.pull_request,
                                               &req.target_branch) {

                let attach = SlackAttachmentBuilder::new(&e)
                    .title(format!("Source PR: #{}: \"{}\"",
                                   req.pull_request.number,
                                   req.pull_request.title)
                        .as_str())
                    .title_link(req.pull_request.html_url.clone())
                    .color("danger")
                    .build();

                let messenger = messenger::from_config(config);
                messenger.send_to_owner("Error creating merge Pull Request",
                                        &vec![attach],
                                        &req.pull_request.user,
                                        &req.repo);
            }
        });
    }
}
<|endoftext|>


<commit_before>use libc::c_int;
use rgtk::*;
use std::num::FromPrimitive;
use std::path::Path;
use std::process::Command;

fn save_project(state: &mut ::utils::State, tree: &mut gtk::TreeView, path_str: &String) {
    state.projects.insert(path_str.clone());
    state.selection = Some(path_str.clone());
    ::utils::write_prefs(state);
    ::ui::update_project_tree(state, tree);
}

pub fn new_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    if let Some(dialog) = gtk::FileChooserDialog::new(
        "New Project",
        None,
        gtk::FileChooserAction::Save
    ) {
        if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                let path = Path::new(path_str.as_slice());
                if let Some(name_os_str) = path.file_name() {
                    if let Some(name_str) = name_os_str.to_str() {
                        if let Some(parent_path) = path.parent() {
                            match Command::new("cargo").arg("new").arg(name_str).arg("--bin")
                                .current_dir(parent_path).status()
                            {
                                Ok(_) => save_project(state, tree, &path_str),
                                Err(e) => println!("Error creating {}: {}", name_str, e)
                            }
                        }
                    }
                }
            }
        }
        dialog.destroy();
    }
}

pub fn import_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    if let Some(dialog) = gtk::FileChooserDialog::new(
        "Import",
        None,
        gtk::FileChooserAction::SelectFolder
    ) {
        if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                save_project(state, tree, &path_str);
            }
        }
        dialog.destroy();
    }
}

pub fn rename_file(state: &mut ::utils::State, fd: c_int) {
    if let Some(_) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::FileChooserDialog::new(
            "Rename",
            None,
            gtk::FileChooserAction::Save
        ) {
            if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
                if let Some(path_str) = dialog.get_filename() {
                    state.selection = Some(path_str.clone());
                    ::utils::write_prefs(&state);
                    ::ffi::send_message(fd, format!(":Move {}", path_str).as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn remove_item(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: c_int) {
    if let Some(path_str) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::MessageDialog::new_with_markup(
            Some(state.window.clone()),
            gtk::DialogFlags::Modal,
            gtk::MessageType::Question,
            gtk::ButtonsType::OkCancel,
            if state.projects.contains(&path_str) {
                "Remove this project? It WILL NOT be deleted from the disk."
            } else {
                "Remove this file? It WILL be deleted from the disk."
            }
        ) {
            if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
                if state.projects.contains(&path_str) {
                    state.projects.remove(&path_str);
                    ::utils::remove_expansions_for_path(state, &path_str);
                    ::utils::write_prefs(state);
                    ::ui::update_project_tree(state, tree);
                } else {
                    ::ffi::send_message(fd, ":call delete(expand('%')) | bdelete!".as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn set_selection(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: c_int) {
    if !state.is_refreshing_tree {
        if let Some(path_str) = ::utils::get_selected_path(state) {
            state.selection = Some(path_str.clone());
            ::utils::write_prefs(state);
            ::ui::update_project_tree(state, tree);
            ::ffi::send_message(fd, format!("e {}", path_str).as_slice());
        }
    }
}

pub fn remove_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        ::utils::remove_expansions_for_path(state, &path_str);
        ::utils::write_prefs(state);
    }
}

pub fn add_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        state.expansions.insert(path_str);
        ::utils::write_prefs(state);
    }
}
<commit_msg>Remove unnecessary colons<commit_after>use libc::c_int;
use rgtk::*;
use std::num::FromPrimitive;
use std::path::Path;
use std::process::Command;

fn save_project(state: &mut ::utils::State, tree: &mut gtk::TreeView, path_str: &String) {
    state.projects.insert(path_str.clone());
    state.selection = Some(path_str.clone());
    ::utils::write_prefs(state);
    ::ui::update_project_tree(state, tree);
}

pub fn new_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    if let Some(dialog) = gtk::FileChooserDialog::new(
        "New Project",
        None,
        gtk::FileChooserAction::Save
    ) {
        if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                let path = Path::new(path_str.as_slice());
                if let Some(name_os_str) = path.file_name() {
                    if let Some(name_str) = name_os_str.to_str() {
                        if let Some(parent_path) = path.parent() {
                            match Command::new("cargo").arg("new").arg(name_str).arg("--bin")
                                .current_dir(parent_path).status()
                            {
                                Ok(_) => save_project(state, tree, &path_str),
                                Err(e) => println!("Error creating {}: {}", name_str, e)
                            }
                        }
                    }
                }
            }
        }
        dialog.destroy();
    }
}

pub fn import_project(state: &mut ::utils::State, tree: &mut gtk::TreeView) {
    if let Some(dialog) = gtk::FileChooserDialog::new(
        "Import",
        None,
        gtk::FileChooserAction::SelectFolder
    ) {
        if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
            if let Some(path_str) = dialog.get_filename() {
                save_project(state, tree, &path_str);
            }
        }
        dialog.destroy();
    }
}

pub fn rename_file(state: &mut ::utils::State, fd: c_int) {
    if let Some(_) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::FileChooserDialog::new(
            "Rename",
            None,
            gtk::FileChooserAction::Save
        ) {
            if let Some(gtk::ResponseType::Accept) = FromPrimitive::from_i32(dialog.run()) {
                if let Some(path_str) = dialog.get_filename() {
                    state.selection = Some(path_str.clone());
                    ::utils::write_prefs(&state);
                    ::ffi::send_message(fd, format!("Move {}", path_str).as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn remove_item(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: c_int) {
    if let Some(path_str) = ::utils::get_selected_path(state) {
        if let Some(dialog) = gtk::MessageDialog::new_with_markup(
            Some(state.window.clone()),
            gtk::DialogFlags::Modal,
            gtk::MessageType::Question,
            gtk::ButtonsType::OkCancel,
            if state.projects.contains(&path_str) {
                "Remove this project? It WILL NOT be deleted from the disk."
            } else {
                "Remove this file? It WILL be deleted from the disk."
            }
        ) {
            if let Some(gtk::ResponseType::Ok) = FromPrimitive::from_i32(dialog.run()) {
                if state.projects.contains(&path_str) {
                    state.projects.remove(&path_str);
                    ::utils::remove_expansions_for_path(state, &path_str);
                    ::utils::write_prefs(state);
                    ::ui::update_project_tree(state, tree);
                } else {
                    ::ffi::send_message(fd, "call delete(expand('%')) | bdelete!".as_slice());
                }
            }
            dialog.destroy();
        }
    }
}

pub fn set_selection(state: &mut ::utils::State, tree: &mut gtk::TreeView, fd: c_int) {
    if !state.is_refreshing_tree {
        if let Some(path_str) = ::utils::get_selected_path(state) {
            state.selection = Some(path_str.clone());
            ::utils::write_prefs(state);
            ::ui::update_project_tree(state, tree);
            ::ffi::send_message(fd, format!("e {}", path_str).as_slice());
        }
    }
}

pub fn remove_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        ::utils::remove_expansions_for_path(state, &path_str);
        ::utils::write_prefs(state);
    }
}

pub fn add_expansion(state: &mut ::utils::State, iter: &gtk::TreeIter) {
    if let Some(path_str) = state.tree_model.get_value(iter, 1).get_string() {
        state.expansions.insert(path_str);
        ::utils::write_prefs(state);
    }
}
<|endoftext|>


<commit_before>use libc;
use std::ptr;
use std::ffi::CString;
use raw;
use aux;

// implement the same function that luaL_newstate uses, so we can test lua_newstate directly
// FIXME (#10025): We can't define this as `unsafe extern "C"`
unsafe extern "C" fn alloc_helper(_ud: *mut libc::c_void, ptr: *mut libc::c_void,
                                  _osize: libc::size_t, nsize: libc::size_t) -> *mut libc::c_void {
    if nsize == 0 {
        libc::free(ptr as *mut libc::c_void);
        ptr::null_mut()
    } else {
        libc::realloc(ptr, nsize)
    }
}

// panic function should panic!() so Lua doesn't abort
unsafe extern "C" fn panic_helper(_L: *mut raw::lua_State) -> libc::c_int {
    panic!("lua error");
}

#[test]
fn test_lua_newstate() {
    unsafe {
        let L = raw::lua_newstate(alloc_helper, ptr::null_mut());
        raw::lua_atpanic(L, panic_helper);
        raw::lua_pushinteger(L, 42);
        raw::lua_close(L);
    }
}

#[test]
fn test_luaL_newstate() {
    unsafe {
        let L = aux::raw::luaL_newstate();
        raw::lua_atpanic(L, panic_helper);
        raw::lua_pushinteger(L, 42);
        raw::lua_close(L);
    }
}

#[test]
#[should_panic]
fn test_lua_error() {
    unsafe {
        let L = aux::raw::luaL_newstate();
        raw::lua_atpanic(L, panic_helper);
        raw::lua_pushinteger(L, 42);
        raw::lua_error(L);
    }
}

#[test]
fn test_dostring() {
    unsafe {
        let L = aux::raw::luaL_newstate();
        raw::lua_atpanic(L, panic_helper);
        let s = "function foo(x,y) return x+y end";
        let ret = aux::raw::luaL_dostring(L, CString::new(s).unwrap().as_ptr());
        assert_eq!(ret, 0);
        raw::lua_getglobal(L, CString::new(b"foo").unwrap().as_ptr());

        raw::lua_pushinteger(L, 5);
        raw::lua_pushinteger(L, 3);

        raw::lua_call(L, 2, 1);
        let val = raw::lua_tointeger(L, -1);
        assert_eq!(val, 8);
        raw::lua_close(L);
    }
}
<commit_msg>Bytestrings are now [u8; N] instead of &[u8]<commit_after>use libc;
use std::ptr;
use std::ffi::CString;
use raw;
use aux;

// implement the same function that luaL_newstate uses, so we can test lua_newstate directly
// FIXME (#10025): We can't define this as `unsafe extern "C"`
unsafe extern "C" fn alloc_helper(_ud: *mut libc::c_void, ptr: *mut libc::c_void,
                                  _osize: libc::size_t, nsize: libc::size_t) -> *mut libc::c_void {
    if nsize == 0 {
        libc::free(ptr as *mut libc::c_void);
        ptr::null_mut()
    } else {
        libc::realloc(ptr, nsize)
    }
}

// panic function should panic!() so Lua doesn't abort
unsafe extern "C" fn panic_helper(_L: *mut raw::lua_State) -> libc::c_int {
    panic!("lua error");
}

#[test]
fn test_lua_newstate() {
    unsafe {
        let L = raw::lua_newstate(alloc_helper, ptr::null_mut());
        raw::lua_atpanic(L, panic_helper);
        raw::lua_pushinteger(L, 42);
        raw::lua_close(L);
    }
}

#[test]
fn test_luaL_newstate() {
    unsafe {
        let L = aux::raw::luaL_newstate();
        raw::lua_atpanic(L, panic_helper);
        raw::lua_pushinteger(L, 42);
        raw::lua_close(L);
    }
}

#[test]
#[should_panic]
fn test_lua_error() {
    unsafe {
        let L = aux::raw::luaL_newstate();
        raw::lua_atpanic(L, panic_helper);
        raw::lua_pushinteger(L, 42);
        raw::lua_error(L);
    }
}

#[test]
fn test_dostring() {
    unsafe {
        let L = aux::raw::luaL_newstate();
        raw::lua_atpanic(L, panic_helper);
        let s = "function foo(x,y) return x+y end";
        let ret = aux::raw::luaL_dostring(L, CString::new(s).unwrap().as_ptr());
        assert_eq!(ret, 0);
        raw::lua_getglobal(L, CString::new("foo").unwrap().as_ptr());

        raw::lua_pushinteger(L, 5);
        raw::lua_pushinteger(L, 3);

        raw::lua_call(L, 2, 1);
        let val = raw::lua_tointeger(L, -1);
        assert_eq!(val, 8);
        raw::lua_close(L);
    }
}
<|endoftext|>